From 93275070779d55213169353b7b7104d39a3da247 Mon Sep 17 00:00:00 2001 From: Tannin Date: Fri, 21 Nov 2014 14:45:30 +0100 Subject: [PATCH 0001/1544] [game_skyrim] - started on a refactoring moving functionality out of the MainWindow class - started on support for game-plugins --- src/games/skyrim/src/gameSkyrim.pro | 28 ++++++ src/games/skyrim/src/gameskyrim.cpp | 114 +++++++++++++++++++++++ src/games/skyrim/src/gameskyrim.h | 50 ++++++++++ src/games/skyrim/src/gameskyrim.json | 1 + src/games/skyrim/src/gameskyrim_global.h | 12 +++ 5 files changed, 205 insertions(+) create mode 100644 src/games/skyrim/src/gameSkyrim.pro create mode 100644 src/games/skyrim/src/gameskyrim.cpp create mode 100644 src/games/skyrim/src/gameskyrim.h create mode 100644 src/games/skyrim/src/gameskyrim.json create mode 100644 src/games/skyrim/src/gameskyrim_global.h diff --git a/src/games/skyrim/src/gameSkyrim.pro b/src/games/skyrim/src/gameSkyrim.pro new file mode 100644 index 00000000..90289889 --- /dev/null +++ b/src/games/skyrim/src/gameSkyrim.pro @@ -0,0 +1,28 @@ +#------------------------------------------------- +# +# Project created by QtCreator 2014-11-15T15:36:33 +# +#------------------------------------------------- + +QT -= gui + +TARGET = gameSkyrim +TEMPLATE = lib + +CONFIG += plugins +CONFIG += dll + +DEFINES += GAMESKYRIM_LIBRARY + +SOURCES += gameskyrim.cpp + +HEADERS += gameskyrim.h + +include(../plugin_template.pri) + +INCLUDEPATH += "$${BOOSTPATH}" + +LIBS += -ladvapi32 + +OTHER_FILES += \ + gameskyrim.json diff --git a/src/games/skyrim/src/gameskyrim.cpp b/src/games/skyrim/src/gameskyrim.cpp new file mode 100644 index 00000000..03db4429 --- /dev/null +++ b/src/games/skyrim/src/gameskyrim.cpp @@ -0,0 +1,114 @@ +#include "gameskyrim.h" +#include +#include +#include +#include + + +using namespace MOBase; + + +GameSkyrim::GameSkyrim() +{ +} + +bool GameSkyrim::init(MOBase::IOrganizer *moInfo) +{ + m_GamePath = identifyPath(); + qDebug("found: %s", qPrintable(m_GamePath)); + return true; +} + +std::unique_ptr getRegValue(HKEY key, LPCWSTR subKey, LPCWSTR value, DWORD flags, LPDWORD type = nullptr) +{ + DWORD size = 0; + DWORD res = ::RegGetValueW(key, subKey, value, flags, type, nullptr, &size); + if (res == ERROR_FILE_NOT_FOUND) { + return std::unique_ptr(); + } else if ((res != ERROR_SUCCESS) && (res != ERROR_MORE_DATA)) { + throw MyException(QObject::tr("failed to query registry path (preflight): %1").arg(res, 0, 16)); + } + + std::unique_ptr result(new BYTE[size]); + res = ::RegGetValueW(key, subKey, value, flags, type, result.get(), &size); + + if (res != ERROR_SUCCESS) { + throw MyException(QObject::tr("failed to query registry path (read): %1").arg(res, 0, 16)); + } + + return result; +} + +QString findInRegistry(HKEY baseKey, LPCWSTR path, LPCWSTR value) +{ + std::unique_ptr buffer = getRegValue(baseKey, path, value, RRF_RT_REG_SZ | RRF_NOEXPAND); + + if (buffer.get() != nullptr) { + return QString::fromUtf16(reinterpret_cast(buffer.get())); + } else { + return QString(); + } +} + +QString GameSkyrim::identifyPath() +{ + return findInRegistry(HKEY_LOCAL_MACHINE, L"Software\\Bethesda Softworks\\Skyrim", L"Installed Path"); +} + +QString GameSkyrim::gameName() const +{ + return "Skyrim"; +} + +QDir GameSkyrim::gameDirectory() const +{ + return QDir(m_GamePath); +} + +QList GameSkyrim::executables() +{ + return QList() + << ExecutableInfo("SKSE", findInGameFolder("skse_loader.exe")) + << ExecutableInfo("SBW", findInGameFolder("SBW.exe")) + << ExecutableInfo("Skyrim", findInGameFolder("TESV.exe")) + << ExecutableInfo("Skyrim Launcher", findInGameFolder("SkyrimLauncher.exe")) + << ExecutableInfo("BOSS", findInGameFolder("BOSS/BOSS.exe")) + << ExecutableInfo("LOOT", findInRegistry(HKEY_LOCAL_MACHINE, L"Software\\LOOT", L"Installed Path")) + << ExecutableInfo("Creation Kit", findInGameFolder("CreationKit.exe")).withSteamAppId("202480") + ; +} + +QString GameSkyrim::name() const +{ + return "Skyrim Support Plugin"; +} + +QString GameSkyrim::author() const +{ + return "Tannin"; +} + +QString GameSkyrim::description() const +{ + return tr("Adds support for the game Sykrim"); +} + +MOBase::VersionInfo GameSkyrim::version() const +{ + return VersionInfo(1, 0, 0, VersionInfo::RELEASE_FINAL); +} + +bool GameSkyrim::isActive() const +{ + return true; +} + +QList GameSkyrim::settings() const +{ + return QList(); +} + +QFileInfo GameSkyrim::findInGameFolder(const QString &relativePath) +{ + return QFileInfo(m_GamePath + "/" + relativePath); +} diff --git a/src/games/skyrim/src/gameskyrim.h b/src/games/skyrim/src/gameskyrim.h new file mode 100644 index 00000000..216a37c2 --- /dev/null +++ b/src/games/skyrim/src/gameskyrim.h @@ -0,0 +1,50 @@ +#ifndef GAMESKYRIM_H +#define GAMESKYRIM_H + + +#include +#include + + +class GameSkyrim : public MOBase::IPluginGame +{ + Q_OBJECT + Q_INTERFACES(MOBase::IPlugin MOBase::IPluginGame) +#if QT_VERSION >= QT_VERSION_CHECK(5,0,0) + Q_PLUGIN_METADATA(IID "org.tannin.DiagnoseBasic" FILE "gameskyrim.json") +#endif + +public: + GameSkyrim(); + + // IPluginGame interface +public: + + virtual QString gameName() const; + + virtual QDir gameDirectory() const; + + virtual QList executables(); + + // IPlugin interface +public: + virtual bool init(MOBase::IOrganizer *moInfo); + virtual QString name() const; + virtual QString author() const; + virtual QString description() const; + virtual MOBase::VersionInfo version() const; + virtual bool isActive() const; + virtual QList settings() const; + +private: + + QFileInfo findInGameFolder(const QString &relativePath); + + QString identifyPath(); + +private: + + QString m_GamePath; +}; + +#endif // GAMESKYRIM_H diff --git a/src/games/skyrim/src/gameskyrim.json b/src/games/skyrim/src/gameskyrim.json new file mode 100644 index 00000000..69a88e3b --- /dev/null +++ b/src/games/skyrim/src/gameskyrim.json @@ -0,0 +1 @@ +{} diff --git a/src/games/skyrim/src/gameskyrim_global.h b/src/games/skyrim/src/gameskyrim_global.h new file mode 100644 index 00000000..aa84c500 --- /dev/null +++ b/src/games/skyrim/src/gameskyrim_global.h @@ -0,0 +1,12 @@ +#ifndef GAMESKYRIM_GLOBAL_H +#define GAMESKYRIM_GLOBAL_H + +#include + +#if defined(GAMESKYRIM_LIBRARY) +# define GAMESKYRIMSHARED_EXPORT Q_DECL_EXPORT +#else +# define GAMESKYRIMSHARED_EXPORT Q_DECL_IMPORT +#endif + +#endif // GAMESKYRIM_GLOBAL_H From 13caf8d3a4cad6a4c757dd36b52f7e407d50d3d5 Mon Sep 17 00:00:00 2001 From: Tannin Date: Tue, 6 Jan 2015 19:31:53 +0100 Subject: [PATCH 0002/1544] [game_skyrim] - bugfixes - moved more functionality to game-plugins - further decoupled management functionality from the UI - created another "tutorial" which is only a single page with relevant parts of the ui highlighted with info as tooltips --- src/games/skyrim/src/gameSkyrim.pro | 2 +- src/games/skyrim/src/gameskyrim.cpp | 119 +++++++++++++++++++++++++++- src/games/skyrim/src/gameskyrim.h | 18 ++++- 3 files changed, 133 insertions(+), 6 deletions(-) diff --git a/src/games/skyrim/src/gameSkyrim.pro b/src/games/skyrim/src/gameSkyrim.pro index 90289889..58971763 100644 --- a/src/games/skyrim/src/gameSkyrim.pro +++ b/src/games/skyrim/src/gameSkyrim.pro @@ -22,7 +22,7 @@ include(../plugin_template.pri) INCLUDEPATH += "$${BOOSTPATH}" -LIBS += -ladvapi32 +LIBS += -ladvapi32 -lole32 OTHER_FILES += \ gameskyrim.json diff --git a/src/games/skyrim/src/gameskyrim.cpp b/src/games/skyrim/src/gameskyrim.cpp index 03db4429..fa3a4e6d 100644 --- a/src/games/skyrim/src/gameskyrim.cpp +++ b/src/games/skyrim/src/gameskyrim.cpp @@ -1,8 +1,10 @@ #include "gameskyrim.h" +#include #include #include #include #include +#include using namespace MOBase; @@ -14,7 +16,8 @@ GameSkyrim::GameSkyrim() bool GameSkyrim::init(MOBase::IOrganizer *moInfo) { - m_GamePath = identifyPath(); + m_GamePath = identifyGamePath(); + m_MyGamesPath = myGamesPath(); qDebug("found: %s", qPrintable(m_GamePath)); return true; } @@ -50,11 +53,71 @@ QString findInRegistry(HKEY baseKey, LPCWSTR path, LPCWSTR value) } } -QString GameSkyrim::identifyPath() +QString GameSkyrim::identifyGamePath() { return findInRegistry(HKEY_LOCAL_MACHINE, L"Software\\Bethesda Softworks\\Skyrim", L"Installed Path"); } + +QString GameSkyrim::getKnownFolderPath(REFKNOWNFOLDERID folderId, bool useDefault) const +{ + PWSTR path = nullptr; + ON_BLOCK_EXIT([&] () { + if (path != nullptr) ::CoTaskMemFree(path); + }); + + if (::SHGetKnownFolderPath(folderId, useDefault ? KF_FLAG_DEFAULT_PATH : 0, NULL, &path) == S_OK) { + return QDir::fromNativeSeparators(QString::fromWCharArray(path)); + } else { + return QString(); + } +} + + +QString GameSkyrim::getSpecialPath(const QString &name) const +{ + QString base = findInRegistry(HKEY_CURRENT_USER, + L"Software\\Microsoft\\Windows\\CurrentVersion\\Explorer\\User Shell Folders", + name.toStdWString().c_str()); + + WCHAR temp[MAX_PATH]; + if (::ExpandEnvironmentStringsW(base.toStdWString().c_str(), temp, MAX_PATH) != 0) { + return QString::fromWCharArray(temp); + } else { + return base; + } +} + +QString GameSkyrim::myGamesPath() +{ + // a) this is the way it should work. get the configured My Documents directory + QString result = getKnownFolderPath(FOLDERID_Documents, false); + + // b) if there is no directory there, look in the default directory + if (result.isEmpty() + || !QFileInfo(result + "/My Games/Skyrim").exists()) { + result = getKnownFolderPath(FOLDERID_Documents, true); + } + // c) finally, look in the registry. This is discouraged + if (result.isEmpty() + || !QFileInfo(result + "/My Games/Skyrim").exists()) { + result = getSpecialPath("Personal"); + } + + return result + "/My Games/Skyrim"; +} + +QString GameSkyrim::localAppFolder() const +{ + QString result = getKnownFolderPath(FOLDERID_LocalAppData, false); + if (result.isEmpty()) { + // fallback: try the registry + result = getSpecialPath("Local AppData"); + } + + return result; +} + QString GameSkyrim::gameName() const { return "Skyrim"; @@ -112,3 +175,55 @@ QFileInfo GameSkyrim::findInGameFolder(const QString &relativePath) { return QFileInfo(m_GamePath + "/" + relativePath); } + +void GameSkyrim::copyToProfile(const QString &sourcePath, const QDir &destinationDirectory, + const QString &sourceFileName, const QString &destinationFileName) const +{ + QString filePath = destinationDirectory.absoluteFilePath(destinationFileName.isEmpty() ? sourceFileName + : destinationFileName); + if (!QFileInfo(filePath).exists()) { + if (!shellCopy(sourcePath + "/" + sourceFileName, filePath)) { + // if copy file fails, create the file empty + QFile(filePath).open(QIODevice::WriteOnly); + } + } +} + +void GameSkyrim::initializeProfile(const QDir &path, ProfileSettings settings) const +{ + if (settings.testFlag(IPluginGame::MODS)) { + copyToProfile(localAppFolder() + "/Skyrim", path, "plugins.txt"); + copyToProfile(localAppFolder() + "/Skyrim", path, "loadorder.txt"); + } + + if (settings.testFlag(IPluginGame::CONFIGURATION)) { + if (settings.testFlag(IPluginGame::PREFER_DEFAULTS) + || !QFileInfo(m_MyGamesPath + "/skyrim.ini").exists()) { + copyToProfile(m_GamePath, path, "skyrim_default.ini", "skyrim.ini"); + } else { + copyToProfile(m_MyGamesPath, path, "skyrim.ini"); + } + + copyToProfile(m_MyGamesPath, path, "skyrimprefs.ini"); + } +} + +QString GameSkyrim::savegameExtension() const +{ + return "ess"; +} + +QDir GameSkyrim::savesDirectory() const +{ + return m_MyGamesPath + "/Saves"; +} + +QDir GameSkyrim::documentsDirectory() const +{ + return m_MyGamesPath; +} + +QString GameSkyrim::steamAPPId() const +{ + return "72850"; +} diff --git a/src/games/skyrim/src/gameskyrim.h b/src/games/skyrim/src/gameskyrim.h index 216a37c2..7203aee7 100644 --- a/src/games/skyrim/src/gameskyrim.h +++ b/src/games/skyrim/src/gameskyrim.h @@ -4,6 +4,7 @@ #include #include +#include class GameSkyrim : public MOBase::IPluginGame @@ -21,10 +22,13 @@ public: public: virtual QString gameName() const; - virtual QDir gameDirectory() const; - + virtual QDir savesDirectory() const; + virtual QDir documentsDirectory() const; virtual QList executables(); + virtual void initializeProfile(const QDir &path, ProfileSettings settings) const; + virtual QString savegameExtension() const; + virtual QString steamAPPId() const; // IPlugin interface public: @@ -40,11 +44,19 @@ private: QFileInfo findInGameFolder(const QString &relativePath); - QString identifyPath(); + QString identifyGamePath(); + QString myGamesPath(); + QString getKnownFolderPath(REFKNOWNFOLDERID folderId, bool useDefault) const; + QString getSpecialPath(const QString &name) const; + QString localAppFolder() const; + void copyToProfile(const QString &sourcePath, const QDir &destinationDirectory, + const QString &sourceFileName, const QString &destinationFileName = QString()) const; private: QString m_GamePath; + QString m_MyGamesPath; + }; #endif // GAMESKYRIM_H From 45772191ea0f057fb26893286f347aced0bfffbd Mon Sep 17 00:00:00 2001 From: Tannin Date: Thu, 29 Jan 2015 19:26:42 +0100 Subject: [PATCH 0003/1544] [game_skyrim] extended the game-plugin interface --- src/games/skyrim/src/gameSkyrim.pro | 25 ++- src/games/skyrim/src/gameskyrim.cpp | 144 +++++------------- src/games/skyrim/src/gameskyrim.h | 43 +++--- src/games/skyrim/src/gameskyrim_global.h | 12 -- .../skyrim/src/skyrimbsainvalidation.cpp | 18 +++ src/games/skyrim/src/skyrimbsainvalidation.h | 23 +++ src/games/skyrim/src/skyrimdataarchives.cpp | 46 ++++++ src/games/skyrim/src/skyrimdataarchives.h | 24 +++ src/games/skyrim/src/skyrimscriptextender.cpp | 7 + src/games/skyrim/src/skyrimscriptextender.h | 14 ++ 10 files changed, 214 insertions(+), 142 deletions(-) delete mode 100644 src/games/skyrim/src/gameskyrim_global.h create mode 100644 src/games/skyrim/src/skyrimbsainvalidation.cpp create mode 100644 src/games/skyrim/src/skyrimbsainvalidation.h create mode 100644 src/games/skyrim/src/skyrimdataarchives.cpp create mode 100644 src/games/skyrim/src/skyrimdataarchives.h create mode 100644 src/games/skyrim/src/skyrimscriptextender.cpp create mode 100644 src/games/skyrim/src/skyrimscriptextender.h diff --git a/src/games/skyrim/src/gameSkyrim.pro b/src/games/skyrim/src/gameSkyrim.pro index 58971763..6198a022 100644 --- a/src/games/skyrim/src/gameSkyrim.pro +++ b/src/games/skyrim/src/gameSkyrim.pro @@ -4,7 +4,6 @@ # #------------------------------------------------- -QT -= gui TARGET = gameSkyrim TEMPLATE = lib @@ -14,15 +13,31 @@ CONFIG += dll DEFINES += GAMESKYRIM_LIBRARY -SOURCES += gameskyrim.cpp +SOURCES += gameskyrim.cpp \ + skyrimbsainvalidation.cpp \ + skyrimscriptextender.cpp \ + skyrimdataarchives.cpp -HEADERS += gameskyrim.h +HEADERS += gameskyrim.h \ + skyrimbsainvalidation.h \ + skyrimscriptextender.h \ + skyrimdataarchives.h + +CONFIG(debug, debug|release) { + LIBS += -L"$${OUT_PWD}/../gameGamebryo/debug" + PRE_TARGETDEPS += \ + $$OUT_PWD/../gameGamebryo/debug/gameGamebryo.lib +} else { + LIBS += -L"$${OUT_PWD}/../gameGamebryo/release" + PRE_TARGETDEPS += \ + $$OUT_PWD/../gameGamebryo/release/gameGamebryo.lib +} include(../plugin_template.pri) -INCLUDEPATH += "$${BOOSTPATH}" +INCLUDEPATH += "$${BOOSTPATH}" "$${PWD}/../gamefeatures" "$${PWD}/../gamegamebryo" -LIBS += -ladvapi32 -lole32 +LIBS += -ladvapi32 -lole32 -lgameGamebryo OTHER_FILES += \ gameskyrim.json diff --git a/src/games/skyrim/src/gameskyrim.cpp b/src/games/skyrim/src/gameskyrim.cpp index fa3a4e6d..81db3d2a 100644 --- a/src/games/skyrim/src/gameskyrim.cpp +++ b/src/games/skyrim/src/gameskyrim.cpp @@ -1,6 +1,7 @@ #include "gameskyrim.h" #include #include +#include #include #include #include @@ -14,97 +15,25 @@ GameSkyrim::GameSkyrim() { } -bool GameSkyrim::init(MOBase::IOrganizer *moInfo) +bool GameSkyrim::init(IOrganizer *moInfo) { - m_GamePath = identifyGamePath(); - m_MyGamesPath = myGamesPath(); - qDebug("found: %s", qPrintable(m_GamePath)); + if (!GameGamebryo::init(moInfo)) { + return false; + } + m_ScriptExtender = std::shared_ptr(new SkyrimScriptExtender()); + m_DataArchives = std::shared_ptr(new SkyrimDataArchives()); + m_BSAInvalidation = std::shared_ptr(new SkyrimBSAInvalidation(m_DataArchives, moInfo)); return true; } -std::unique_ptr getRegValue(HKEY key, LPCWSTR subKey, LPCWSTR value, DWORD flags, LPDWORD type = nullptr) -{ - DWORD size = 0; - DWORD res = ::RegGetValueW(key, subKey, value, flags, type, nullptr, &size); - if (res == ERROR_FILE_NOT_FOUND) { - return std::unique_ptr(); - } else if ((res != ERROR_SUCCESS) && (res != ERROR_MORE_DATA)) { - throw MyException(QObject::tr("failed to query registry path (preflight): %1").arg(res, 0, 16)); - } - - std::unique_ptr result(new BYTE[size]); - res = ::RegGetValueW(key, subKey, value, flags, type, result.get(), &size); - - if (res != ERROR_SUCCESS) { - throw MyException(QObject::tr("failed to query registry path (read): %1").arg(res, 0, 16)); - } - - return result; -} - -QString findInRegistry(HKEY baseKey, LPCWSTR path, LPCWSTR value) -{ - std::unique_ptr buffer = getRegValue(baseKey, path, value, RRF_RT_REG_SZ | RRF_NOEXPAND); - - if (buffer.get() != nullptr) { - return QString::fromUtf16(reinterpret_cast(buffer.get())); - } else { - return QString(); - } -} - -QString GameSkyrim::identifyGamePath() +QString GameSkyrim::identifyGamePath() const { return findInRegistry(HKEY_LOCAL_MACHINE, L"Software\\Bethesda Softworks\\Skyrim", L"Installed Path"); } - -QString GameSkyrim::getKnownFolderPath(REFKNOWNFOLDERID folderId, bool useDefault) const +QString GameSkyrim::gameName() const { - PWSTR path = nullptr; - ON_BLOCK_EXIT([&] () { - if (path != nullptr) ::CoTaskMemFree(path); - }); - - if (::SHGetKnownFolderPath(folderId, useDefault ? KF_FLAG_DEFAULT_PATH : 0, NULL, &path) == S_OK) { - return QDir::fromNativeSeparators(QString::fromWCharArray(path)); - } else { - return QString(); - } -} - - -QString GameSkyrim::getSpecialPath(const QString &name) const -{ - QString base = findInRegistry(HKEY_CURRENT_USER, - L"Software\\Microsoft\\Windows\\CurrentVersion\\Explorer\\User Shell Folders", - name.toStdWString().c_str()); - - WCHAR temp[MAX_PATH]; - if (::ExpandEnvironmentStringsW(base.toStdWString().c_str(), temp, MAX_PATH) != 0) { - return QString::fromWCharArray(temp); - } else { - return base; - } -} - -QString GameSkyrim::myGamesPath() -{ - // a) this is the way it should work. get the configured My Documents directory - QString result = getKnownFolderPath(FOLDERID_Documents, false); - - // b) if there is no directory there, look in the default directory - if (result.isEmpty() - || !QFileInfo(result + "/My Games/Skyrim").exists()) { - result = getKnownFolderPath(FOLDERID_Documents, true); - } - // c) finally, look in the registry. This is discouraged - if (result.isEmpty() - || !QFileInfo(result + "/My Games/Skyrim").exists()) { - result = getSpecialPath("Personal"); - } - - return result + "/My Games/Skyrim"; + return "Skyrim"; } QString GameSkyrim::localAppFolder() const @@ -118,15 +47,12 @@ QString GameSkyrim::localAppFolder() const return result; } -QString GameSkyrim::gameName() const +QString GameSkyrim::myGamesFolderName() const { return "Skyrim"; } -QDir GameSkyrim::gameDirectory() const -{ - return QDir(m_GamePath); -} + QList GameSkyrim::executables() { @@ -171,10 +97,7 @@ QList GameSkyrim::settings() const return QList(); } -QFileInfo GameSkyrim::findInGameFolder(const QString &relativePath) -{ - return QFileInfo(m_GamePath + "/" + relativePath); -} + void GameSkyrim::copyToProfile(const QString &sourcePath, const QDir &destinationDirectory, const QString &sourceFileName, const QString &destinationFileName) const @@ -198,13 +121,13 @@ void GameSkyrim::initializeProfile(const QDir &path, ProfileSettings settings) c if (settings.testFlag(IPluginGame::CONFIGURATION)) { if (settings.testFlag(IPluginGame::PREFER_DEFAULTS) - || !QFileInfo(m_MyGamesPath + "/skyrim.ini").exists()) { - copyToProfile(m_GamePath, path, "skyrim_default.ini", "skyrim.ini"); + || !QFileInfo(myGamesPath() + "/skyrim.ini").exists()) { + copyToProfile(gameDirectory().absolutePath(), path, "skyrim_default.ini", "skyrim.ini"); } else { - copyToProfile(m_MyGamesPath, path, "skyrim.ini"); + copyToProfile(myGamesPath(), path, "skyrim.ini"); } - copyToProfile(m_MyGamesPath, path, "skyrimprefs.ini"); + copyToProfile(myGamesPath(), path, "skyrimprefs.ini"); } } @@ -213,17 +136,28 @@ QString GameSkyrim::savegameExtension() const return "ess"; } -QDir GameSkyrim::savesDirectory() const -{ - return m_MyGamesPath + "/Saves"; -} - -QDir GameSkyrim::documentsDirectory() const -{ - return m_MyGamesPath; -} - QString GameSkyrim::steamAPPId() const { return "72850"; } + +QStringList GameSkyrim::getPrimaryPlugins() +{ + return { "skyrim.esm", "update.esm" }; +} + +QIcon GameSkyrim::gameIcon() const +{ + return MOBase::iconForExecutable(gameDirectory().absoluteFilePath("TESV.exe")); +} + +const std::map &GameSkyrim::featureList() const +{ + static std::map result { + { typeid(BSAInvalidation), m_BSAInvalidation.get() }, + { typeid(ScriptExtender), m_ScriptExtender.get() }, + { typeid(DataArchives), m_DataArchives.get() } + }; + + return result; +} diff --git a/src/games/skyrim/src/gameskyrim.h b/src/games/skyrim/src/gameskyrim.h index 7203aee7..743223e7 100644 --- a/src/games/skyrim/src/gameskyrim.h +++ b/src/games/skyrim/src/gameskyrim.h @@ -2,37 +2,38 @@ #define GAMESKYRIM_H -#include +#include "skyrimbsainvalidation.h" +#include "skyrimscriptextender.h" +#include "skyrimdataarchives.h" +#include #include -#include -class GameSkyrim : public MOBase::IPluginGame +class GameSkyrim : public GameGamebryo { Q_OBJECT - Q_INTERFACES(MOBase::IPlugin MOBase::IPluginGame) #if QT_VERSION >= QT_VERSION_CHECK(5,0,0) - Q_PLUGIN_METADATA(IID "org.tannin.DiagnoseBasic" FILE "gameskyrim.json") + Q_PLUGIN_METADATA(IID "org.tannin.GameSkyrim" FILE "gameskyrim.json") #endif public: + GameSkyrim(); - // IPluginGame interface -public: + virtual bool init(MOBase::IOrganizer *moInfo) override; + +public: // IPluginGame interface virtual QString gameName() const; - virtual QDir gameDirectory() const; - virtual QDir savesDirectory() const; - virtual QDir documentsDirectory() const; virtual QList executables(); virtual void initializeProfile(const QDir &path, ProfileSettings settings) const; virtual QString savegameExtension() const; virtual QString steamAPPId() const; + virtual QStringList getPrimaryPlugins(); + virtual QIcon gameIcon() const override; + +public: // IPlugin interface - // IPlugin interface -public: - virtual bool init(MOBase::IOrganizer *moInfo); virtual QString name() const; virtual QString author() const; virtual QString description() const; @@ -40,22 +41,24 @@ public: virtual bool isActive() const; virtual QList settings() const; +protected: + + virtual const std::map &featureList() const; + private: - QFileInfo findInGameFolder(const QString &relativePath); + virtual QString identifyGamePath() const override; + virtual QString myGamesFolderName() const override; - QString identifyGamePath(); - QString myGamesPath(); - QString getKnownFolderPath(REFKNOWNFOLDERID folderId, bool useDefault) const; - QString getSpecialPath(const QString &name) const; QString localAppFolder() const; void copyToProfile(const QString &sourcePath, const QDir &destinationDirectory, const QString &sourceFileName, const QString &destinationFileName = QString()) const; private: - QString m_GamePath; - QString m_MyGamesPath; + std::shared_ptr m_ScriptExtender { nullptr }; + std::shared_ptr m_DataArchives { nullptr }; + std::shared_ptr m_BSAInvalidation { nullptr }; }; diff --git a/src/games/skyrim/src/gameskyrim_global.h b/src/games/skyrim/src/gameskyrim_global.h deleted file mode 100644 index aa84c500..00000000 --- a/src/games/skyrim/src/gameskyrim_global.h +++ /dev/null @@ -1,12 +0,0 @@ -#ifndef GAMESKYRIM_GLOBAL_H -#define GAMESKYRIM_GLOBAL_H - -#include - -#if defined(GAMESKYRIM_LIBRARY) -# define GAMESKYRIMSHARED_EXPORT Q_DECL_EXPORT -#else -# define GAMESKYRIMSHARED_EXPORT Q_DECL_IMPORT -#endif - -#endif // GAMESKYRIM_GLOBAL_H diff --git a/src/games/skyrim/src/skyrimbsainvalidation.cpp b/src/games/skyrim/src/skyrimbsainvalidation.cpp new file mode 100644 index 00000000..a63261d5 --- /dev/null +++ b/src/games/skyrim/src/skyrimbsainvalidation.cpp @@ -0,0 +1,18 @@ +#include "skyrimbsainvalidation.h" +#include + + +SkyrimBSAInvalidation::SkyrimBSAInvalidation(const std::shared_ptr &dataArchives, MOBase::IOrganizer *moInfo) + : GamebryoBSAInvalidation(dataArchives, "skyrim.ini", moInfo) +{ +} + +QString SkyrimBSAInvalidation::invalidationBSAName() const +{ + return "Skyrim - Invalidation.bsa"; +} + +unsigned long SkyrimBSAInvalidation::bsaVersion() const +{ + return 0x68; +} diff --git a/src/games/skyrim/src/skyrimbsainvalidation.h b/src/games/skyrim/src/skyrimbsainvalidation.h new file mode 100644 index 00000000..02e3c664 --- /dev/null +++ b/src/games/skyrim/src/skyrimbsainvalidation.h @@ -0,0 +1,23 @@ +#ifndef SKYRIMBSAINVALIDATION_H +#define SKYRIMBSAINVALIDATION_H + + +#include +#include +#include "skyrimdataarchives.h" + + +class SkyrimBSAInvalidation : public GamebryoBSAInvalidation +{ +public: + + SkyrimBSAInvalidation(const std::shared_ptr &dataArchives, MOBase::IOrganizer *moInfo); + +private: + + virtual QString invalidationBSAName() const override; + virtual unsigned long bsaVersion() const override; + +}; + +#endif // SKYRIMBSAINVALIDATION_H diff --git a/src/games/skyrim/src/skyrimdataarchives.cpp b/src/games/skyrim/src/skyrimdataarchives.cpp new file mode 100644 index 00000000..f259978f --- /dev/null +++ b/src/games/skyrim/src/skyrimdataarchives.cpp @@ -0,0 +1,46 @@ +#include "skyrimdataarchives.h" +#include +#include + + +QStringList SkyrimDataArchives::vanillaArchives() const +{ + return { "Skyrim - Misc.bsa" + , "Skyrim - Shaders.bsa" + , "Skyrim - Textures.bsa" + , "HighResTexturePack01.bsa" + , "HighResTexturePack02.bsa" + , "HighResTexturePack03.bsa" + , "Skyrim - Interface.bsa" + , "Skyrim - Animations.bsa" + , "Skyrim - Meshes.bsa" + , "Skyrim - Sounds.bsa" + , "Skyrim - Voices.bsa" + , "Skyrim - VoicesExtra.bsa" }; +} + + +QStringList SkyrimDataArchives::archives(const MOBase::IProfile *profile) const +{ + QStringList result; + + QString iniFile = QDir(profile->absolutePath()).absoluteFilePath("skyrim.ini"); + result.append(getArchivesFromKey(iniFile, "SResourceArchiveList")); + result.append(getArchivesFromKey(iniFile, "SResourceArchiveList2")); + + return result; +} + +void SkyrimDataArchives::writeArchiveList(MOBase::IProfile *profile, QStringList before) +{ + QString list = before.join(','); + + QString iniFile = QDir(profile->absolutePath()).absoluteFilePath("skyrim.ini"); + if (list.length() > 255) { + int splitIdx = list.lastIndexOf(",", 256); + setArchivesToKey(iniFile, "SResourceArchiveList", list.mid(0, splitIdx)); + setArchivesToKey(iniFile, "SResourceArchiveList2", list.mid(splitIdx + 1)); + } else { + setArchivesToKey(iniFile, "SResourceArchiveList", list); + } +} diff --git a/src/games/skyrim/src/skyrimdataarchives.h b/src/games/skyrim/src/skyrimdataarchives.h new file mode 100644 index 00000000..277c2b0b --- /dev/null +++ b/src/games/skyrim/src/skyrimdataarchives.h @@ -0,0 +1,24 @@ +#ifndef SKYRIMDATAARCHIVES_H +#define SKYRIMDATAARCHIVES_H + + +#include +#include +#include +#include + +class SkyrimDataArchives : public GamebryoDataArchives +{ + +public: + + virtual QStringList vanillaArchives() const override; + virtual QStringList archives(const MOBase::IProfile *profile) const override; + +private: + + virtual void writeArchiveList(MOBase::IProfile *profile, QStringList before) override; + +}; + +#endif // SKYRIMDATAARCHIVES_H diff --git a/src/games/skyrim/src/skyrimscriptextender.cpp b/src/games/skyrim/src/skyrimscriptextender.cpp new file mode 100644 index 00000000..f3d5539a --- /dev/null +++ b/src/games/skyrim/src/skyrimscriptextender.cpp @@ -0,0 +1,7 @@ +#include "skyrimscriptextender.h" + + +QString SkyrimScriptExtender::name() const +{ + return "skse"; +} diff --git a/src/games/skyrim/src/skyrimscriptextender.h b/src/games/skyrim/src/skyrimscriptextender.h new file mode 100644 index 00000000..7f2df32d --- /dev/null +++ b/src/games/skyrim/src/skyrimscriptextender.h @@ -0,0 +1,14 @@ +#ifndef SKYRIMSCRIPTEXTENDER_H +#define SKYRIMSCRIPTEXTENDER_H + + +#include + + +class SkyrimScriptExtender : public ScriptExtender +{ +public: + virtual QString name() const override; +}; + +#endif // SKYRIMSCRIPTEXTENDER_H From 967230bc88141dbf97d05b77fe94b2ec0784bb9e Mon Sep 17 00:00:00 2001 From: Tannin Date: Thu, 29 Jan 2015 19:26:42 +0100 Subject: [PATCH 0004/1544] [game_falloutnv] extended the game-plugin interface --- .../src/falloutnvbsainvalidation.cpp | 18 ++ .../falloutnv/src/falloutnvbsainvalidation.h | 23 +++ .../falloutnv/src/falloutnvdataarchives.cpp | 33 ++++ .../falloutnv/src/falloutnvdataarchives.h | 24 +++ .../falloutnv/src/falloutnvscriptextender.cpp | 7 + .../falloutnv/src/falloutnvscriptextender.h | 14 ++ src/games/falloutnv/src/gameFalloutNV.pro | 43 +++++ src/games/falloutnv/src/gamefalloutnv.cpp | 163 ++++++++++++++++++ src/games/falloutnv/src/gamefalloutnv.h | 65 +++++++ src/games/falloutnv/src/gamefalloutnv.json | 1 + 10 files changed, 391 insertions(+) create mode 100644 src/games/falloutnv/src/falloutnvbsainvalidation.cpp create mode 100644 src/games/falloutnv/src/falloutnvbsainvalidation.h create mode 100644 src/games/falloutnv/src/falloutnvdataarchives.cpp create mode 100644 src/games/falloutnv/src/falloutnvdataarchives.h create mode 100644 src/games/falloutnv/src/falloutnvscriptextender.cpp create mode 100644 src/games/falloutnv/src/falloutnvscriptextender.h create mode 100644 src/games/falloutnv/src/gameFalloutNV.pro create mode 100644 src/games/falloutnv/src/gamefalloutnv.cpp create mode 100644 src/games/falloutnv/src/gamefalloutnv.h create mode 100644 src/games/falloutnv/src/gamefalloutnv.json diff --git a/src/games/falloutnv/src/falloutnvbsainvalidation.cpp b/src/games/falloutnv/src/falloutnvbsainvalidation.cpp new file mode 100644 index 00000000..45b86f7c --- /dev/null +++ b/src/games/falloutnv/src/falloutnvbsainvalidation.cpp @@ -0,0 +1,18 @@ +#include "falloutnvbsainvalidation.h" +#include + + +FalloutNVBSAInvalidation::FalloutNVBSAInvalidation(const std::shared_ptr &dataArchives, MOBase::IOrganizer *moInfo) + : GamebryoBSAInvalidation(dataArchives, "fallout.ini", moInfo) +{ +} + +QString FalloutNVBSAInvalidation::invalidationBSAName() const +{ + return "Fallout - Invalidation.bsa"; +} + +unsigned long FalloutNVBSAInvalidation::bsaVersion() const +{ + return 0x68; +} diff --git a/src/games/falloutnv/src/falloutnvbsainvalidation.h b/src/games/falloutnv/src/falloutnvbsainvalidation.h new file mode 100644 index 00000000..74c4efc7 --- /dev/null +++ b/src/games/falloutnv/src/falloutnvbsainvalidation.h @@ -0,0 +1,23 @@ +#ifndef FALLOUTNVBSAINVALIDATION_H +#define FALLOUTNVBSAINVALIDATION_H + + +#include +#include +#include "falloutnvdataarchives.h" + + +class FalloutNVBSAInvalidation : public GamebryoBSAInvalidation +{ +public: + + FalloutNVBSAInvalidation(const std::shared_ptr &dataArchives, MOBase::IOrganizer *moInfo); + +private: + + virtual QString invalidationBSAName() const override; + virtual unsigned long bsaVersion() const override; + +}; + +#endif // FALLOUTNVBSAINVALIDATION_H diff --git a/src/games/falloutnv/src/falloutnvdataarchives.cpp b/src/games/falloutnv/src/falloutnvdataarchives.cpp new file mode 100644 index 00000000..ad22822b --- /dev/null +++ b/src/games/falloutnv/src/falloutnvdataarchives.cpp @@ -0,0 +1,33 @@ +#include "falloutnvdataarchives.h" +#include +#include + + +QStringList FalloutNVDataArchives::vanillaArchives() const +{ + return { "Fallout - Textures.bsa" + , "Fallout - Textures2.bsa" + , "Fallout - Meshes.bsa" + , "Fallout - Voices1.bsa" + , "Fallout - Sound.bsa" + , "Fallout - Misc.bsa" }; +} + + +QStringList FalloutNVDataArchives::archives(const MOBase::IProfile *profile) const +{ + QStringList result; + + QString iniFile = QDir(profile->absolutePath()).absoluteFilePath("falloutnv.ini"); + result.append(getArchivesFromKey(iniFile, "SArchiveList")); + + return result; +} + +void FalloutNVDataArchives::writeArchiveList(MOBase::IProfile *profile, QStringList before) +{ + QString list = before.join(','); + + QString iniFile = QDir(profile->absolutePath()).absoluteFilePath("falloutnv.ini"); + setArchivesToKey(iniFile, "SArchiveList", list); +} diff --git a/src/games/falloutnv/src/falloutnvdataarchives.h b/src/games/falloutnv/src/falloutnvdataarchives.h new file mode 100644 index 00000000..67728b74 --- /dev/null +++ b/src/games/falloutnv/src/falloutnvdataarchives.h @@ -0,0 +1,24 @@ +#ifndef FALLOUTNVDATAARCHIVES_H +#define FALLOUTNVDATAARCHIVES_H + + +#include +#include +#include +#include + +class FalloutNVDataArchives : public GamebryoDataArchives +{ + +public: + + virtual QStringList vanillaArchives() const override; + virtual QStringList archives(const MOBase::IProfile *profile) const override; + +private: + + virtual void writeArchiveList(MOBase::IProfile *profile, QStringList before) override; + +}; + +#endif // FALLOUTNVDATAARCHIVES_H diff --git a/src/games/falloutnv/src/falloutnvscriptextender.cpp b/src/games/falloutnv/src/falloutnvscriptextender.cpp new file mode 100644 index 00000000..90d67e35 --- /dev/null +++ b/src/games/falloutnv/src/falloutnvscriptextender.cpp @@ -0,0 +1,7 @@ +#include "falloutnvscriptextender.h" + + +QString FalloutNVScriptExtender::name() const +{ + return "nvse"; +} diff --git a/src/games/falloutnv/src/falloutnvscriptextender.h b/src/games/falloutnv/src/falloutnvscriptextender.h new file mode 100644 index 00000000..951574b2 --- /dev/null +++ b/src/games/falloutnv/src/falloutnvscriptextender.h @@ -0,0 +1,14 @@ +#ifndef FALLOUTNVSCRIPTEXTENDER_H +#define FALLOUTNVSCRIPTEXTENDER_H + + +#include + + +class FalloutNVScriptExtender : public ScriptExtender +{ +public: + virtual QString name() const override; +}; + +#endif // FALLOUTNVSCRIPTEXTENDER_H diff --git a/src/games/falloutnv/src/gameFalloutNV.pro b/src/games/falloutnv/src/gameFalloutNV.pro new file mode 100644 index 00000000..992282ae --- /dev/null +++ b/src/games/falloutnv/src/gameFalloutNV.pro @@ -0,0 +1,43 @@ +#------------------------------------------------- +# +# Project created by QtCreator 2014-11-15T15:36:33 +# +#------------------------------------------------- + + +TARGET = gameFalloutNV +TEMPLATE = lib + +CONFIG += plugins +CONFIG += dll + +DEFINES += GAMEFALLOUTNV_LIBRARY + +SOURCES += gamefalloutnv.cpp \ + falloutnvbsainvalidation.cpp \ + falloutnvscriptextender.cpp \ + falloutnvdataarchives.cpp + +HEADERS += gamefalloutnv.h \ + falloutnvbsainvalidation.h \ + falloutnvscriptextender.h \ + falloutnvdataarchives.h + +CONFIG(debug, debug|release) { + LIBS += -L"$${OUT_PWD}/../gameGamebryo/debug" + PRE_TARGETDEPS += \ + $$OUT_PWD/../gameGamebryo/debug/gameGamebryo.lib +} else { + LIBS += -L"$${OUT_PWD}/../gameGamebryo/release" + PRE_TARGETDEPS += \ + $$OUT_PWD/../gameGamebryo/release/gameGamebryo.lib +} + +include(../plugin_template.pri) + +INCLUDEPATH += "$${BOOSTPATH}" "$${PWD}/../gamefeatures" "$${PWD}/../gamegamebryo" + +LIBS += -ladvapi32 -lole32 -lgameGamebryo + +OTHER_FILES += \ + gamefalloutnv.json diff --git a/src/games/falloutnv/src/gamefalloutnv.cpp b/src/games/falloutnv/src/gamefalloutnv.cpp new file mode 100644 index 00000000..a2710f59 --- /dev/null +++ b/src/games/falloutnv/src/gamefalloutnv.cpp @@ -0,0 +1,163 @@ +#include "gameFalloutNV.h" +#include +#include +#include +#include +#include +#include +#include + + +using namespace MOBase; + + +GameFalloutNV::GameFalloutNV() +{ +} + +bool GameFalloutNV::init(IOrganizer *moInfo) +{ + if (!GameGamebryo::init(moInfo)) { + return false; + } + m_ScriptExtender = std::shared_ptr(new FalloutNVScriptExtender()); + m_DataArchives = std::shared_ptr(new FalloutNVDataArchives()); + m_BSAInvalidation = std::shared_ptr(new FalloutNVBSAInvalidation(m_DataArchives, moInfo)); + return true; +} + +QString GameFalloutNV::identifyGamePath() const +{ + return findInRegistry(HKEY_LOCAL_MACHINE, L"Software\\Bethesda Softworks\\FalloutNV", L"Installed Path"); +} + +QString GameFalloutNV::gameName() const +{ + return "FalloutNV"; +} + +QString GameFalloutNV::localAppFolder() const +{ + QString result = getKnownFolderPath(FOLDERID_LocalAppData, false); + if (result.isEmpty()) { + // fallback: try the registry + result = getSpecialPath("Local AppData"); + } + + return result; +} + +QString GameFalloutNV::myGamesFolderName() const +{ + return "FalloutNV"; +} + + + +QList GameFalloutNV::executables() +{ + return QList() + << ExecutableInfo("NVSE", findInGameFolder("nvse_loader.exe")) + << ExecutableInfo("New Vegas", findInGameFolder("FalloutNV.exe")) + << ExecutableInfo("Fallout Mod Manager", findInGameFolder("fomm/fomm.exe")) + << ExecutableInfo("Construction Kit", findInGameFolder("geck.exe")) + << ExecutableInfo("Fallout Launcher", findInGameFolder("FalloutNVLauncher.exe")) + << ExecutableInfo("BOSS", findInGameFolder("BOSS/BOSS.exe")) + << ExecutableInfo("LOOT", findInRegistry(HKEY_LOCAL_MACHINE, L"Software\\LOOT", L"Installed Path")) + ; +} + +QString GameFalloutNV::name() const +{ + return "FalloutNV Support Plugin"; +} + +QString GameFalloutNV::author() const +{ + return "Tannin"; +} + +QString GameFalloutNV::description() const +{ + return tr("Adds support for the game Fallout New Vegas"); +} + +MOBase::VersionInfo GameFalloutNV::version() const +{ + return VersionInfo(1, 0, 0, VersionInfo::RELEASE_FINAL); +} + +bool GameFalloutNV::isActive() const +{ + return true; +} + +QList GameFalloutNV::settings() const +{ + return QList(); +} + + + +void GameFalloutNV::copyToProfile(const QString &sourcePath, const QDir &destinationDirectory, + const QString &sourceFileName, const QString &destinationFileName) const +{ + QString filePath = destinationDirectory.absoluteFilePath(destinationFileName.isEmpty() ? sourceFileName + : destinationFileName); + if (!QFileInfo(filePath).exists()) { + if (!shellCopy(sourcePath + "/" + sourceFileName, filePath)) { + // if copy file fails, create the file empty + QFile(filePath).open(QIODevice::WriteOnly); + } + } +} + +void GameFalloutNV::initializeProfile(const QDir &path, ProfileSettings settings) const +{ + if (settings.testFlag(IPluginGame::MODS)) { + copyToProfile(localAppFolder() + "/FalloutNV", path, "plugins.txt"); + copyToProfile(localAppFolder() + "/FalloutNV", path, "loadorder.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"); + } +} + +QString GameFalloutNV::savegameExtension() const +{ + return "fos"; +} + +QString GameFalloutNV::steamAPPId() const +{ + return "22380"; +} + +QStringList GameFalloutNV::getPrimaryPlugins() +{ + return { "falloutnv.esm" }; +} + +QIcon GameFalloutNV::gameIcon() const +{ + return MOBase::iconForExecutable(gameDirectory().absoluteFilePath("FalloutNV.exe")); +} + +const std::map &GameFalloutNV::featureList() const +{ + static std::map result { + { typeid(BSAInvalidation), m_BSAInvalidation.get() }, + { typeid(ScriptExtender), m_ScriptExtender.get() }, + { typeid(DataArchives), m_DataArchives.get() } + }; + + return result; +} diff --git a/src/games/falloutnv/src/gamefalloutnv.h b/src/games/falloutnv/src/gamefalloutnv.h new file mode 100644 index 00000000..35bd0458 --- /dev/null +++ b/src/games/falloutnv/src/gamefalloutnv.h @@ -0,0 +1,65 @@ +#ifndef GAMEFALLOUTNV_H +#define GAMEFALLOUTNV_H + + +#include "falloutnvbsainvalidation.h" +#include "falloutnvscriptextender.h" +#include "falloutnvdataarchives.h" +#include +#include + + +class GameFalloutNV : public GameGamebryo +{ + Q_OBJECT +#if QT_VERSION >= QT_VERSION_CHECK(5,0,0) + Q_PLUGIN_METADATA(IID "org.tannin.GameFalloutNV" FILE "gamefalloutnv.json") +#endif + +public: + + GameFalloutNV(); + + virtual bool init(MOBase::IOrganizer *moInfo) override; + +public: // IPluginGame interface + + virtual QString gameName() const; + virtual QList executables(); + virtual void initializeProfile(const QDir &path, ProfileSettings settings) const; + virtual QString savegameExtension() const; + virtual QString steamAPPId() const; + virtual QStringList getPrimaryPlugins(); + virtual QIcon gameIcon() const override; + +public: // IPlugin interface + + virtual QString name() const; + virtual QString author() const; + virtual QString description() const; + virtual MOBase::VersionInfo version() const; + virtual bool isActive() const; + virtual QList settings() const; + +protected: + + virtual const std::map &featureList() const; + +private: + + virtual QString identifyGamePath() const override; + virtual QString myGamesFolderName() const override; + + QString localAppFolder() const; + void copyToProfile(const QString &sourcePath, const QDir &destinationDirectory, + const QString &sourceFileName, const QString &destinationFileName = QString()) const; + +private: + + std::shared_ptr m_ScriptExtender { nullptr }; + std::shared_ptr m_DataArchives { nullptr }; + std::shared_ptr m_BSAInvalidation { nullptr }; + +}; + +#endif // GAMEFALLOUTNV_H diff --git a/src/games/falloutnv/src/gamefalloutnv.json b/src/games/falloutnv/src/gamefalloutnv.json new file mode 100644 index 00000000..69a88e3b --- /dev/null +++ b/src/games/falloutnv/src/gamefalloutnv.json @@ -0,0 +1 @@ +{} From 1b5cc4564e20faec599ed00026b30289e8ddf449 Mon Sep 17 00:00:00 2001 From: Tannin Date: Thu, 29 Jan 2015 19:26:42 +0100 Subject: [PATCH 0005/1544] extended the game-plugin interface --- src/dummybsa.cpp | 191 ++++++++++++++++++++++++++++++++ src/dummybsa.h | 64 +++++++++++ src/gameGamebryo.pro | 23 ++++ src/gamebryobsainvalidation.cpp | 79 +++++++++++++ src/gamebryobsainvalidation.h | 38 +++++++ src/gamebryodataarchives.cpp | 57 ++++++++++ src/gamebryodataarchives.h | 27 +++++ src/gamegamebryo.cpp | 124 +++++++++++++++++++++ src/gamegamebryo.h | 54 +++++++++ 9 files changed, 657 insertions(+) create mode 100644 src/dummybsa.cpp create mode 100644 src/dummybsa.h create mode 100644 src/gameGamebryo.pro create mode 100644 src/gamebryobsainvalidation.cpp create mode 100644 src/gamebryobsainvalidation.h create mode 100644 src/gamebryodataarchives.cpp create mode 100644 src/gamebryodataarchives.h create mode 100644 src/gamegamebryo.cpp create mode 100644 src/gamegamebryo.h diff --git a/src/dummybsa.cpp b/src/dummybsa.cpp new file mode 100644 index 00000000..efbf9dc8 --- /dev/null +++ b/src/dummybsa.cpp @@ -0,0 +1,191 @@ +/* +Copyright (C) 2012 Sebastian Herbord. All rights reserved. + +This file is part of Mod Organizer. + +Mod Organizer is free software: you can redistribute it and/or modify +it under the terms of the GNU General Public License as published by +the Free Software Foundation, either version 3 of the License, or +(at your option) any later version. + +Mod Organizer is distributed in the hope that it will be useful, +but WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +GNU General Public License for more details. + +You should have received a copy of the GNU General Public License +along with Mod Organizer. If not, see . +*/ + +#include "dummybsa.h" +#include +#define WIN32_LEAN_AND_MEAN +#include + + +static void writeUlong(unsigned char* buffer, int offset, unsigned long value) +{ + union { + unsigned long ulValue; + unsigned char cValue[4]; + }; + ulValue = value; + memcpy(buffer + offset, cValue, 4); +} + +static void writeUlonglong(unsigned char* buffer, int offset, unsigned long long value) +{ + union { + unsigned long long ullValue; + unsigned char cValue[8]; + }; + ullValue = value; + memcpy(buffer + offset, cValue, 8); +} + +static unsigned long genHashInt(const unsigned char *pos, const unsigned char *end) +{ + unsigned long hash = 0; + for (; pos < end; ++pos) { + hash *= 0x1003f; + hash += *pos; + } + return hash; +} + +static unsigned long long genHash(const char* fileName) +{ + char fileNameLower[MAX_PATH + 1]; + int i = 0; + for (; i < MAX_PATH && fileName[i] != '\0'; ++i) { + fileNameLower[i] = static_cast(tolower(fileName[i])); + if (fileNameLower[i] == '\\') { + fileNameLower[i] = '/'; + } + } + fileNameLower[i] = '\0'; + + unsigned char *fileNameLowerU = reinterpret_cast(fileNameLower); + + char* ext = strrchr(fileNameLower, '.'); + if (ext == nullptr) { + ext = fileNameLower + strlen(fileNameLower); + } + unsigned char *extU = reinterpret_cast(ext); + + int length = ext - fileNameLower; + + unsigned long long hash = 0ULL; + + if (length > 0) { + hash = *(extU - 1) | + ((length > 2 ? *(ext - 2) : 0) << 8) | + (length << 16) | + (fileNameLowerU[0] << 24); + } + + if (strlen(ext) > 0) { + if (strcmp(ext + 1, "kf") == 0) { + hash |= 0x80; + } else if (strcmp(ext + 1, "nif") == 0) { + hash |= 0x8000; + } else if (strcmp(ext + 1, "dds") == 0) { + hash |= 0x8080; + } else if (strcmp(ext + 1, "wav") == 0) { + hash |= 0x80000000; + } + + unsigned long long temp = static_cast(genHashInt( + fileNameLowerU + 1, extU - 2)); + temp += static_cast(genHashInt( + extU, extU + strlen(ext))); + + hash |= (temp & 0xFFFFFFFF) << 32; + } + return hash; +} + +DummyBSA::DummyBSA(unsigned long bsaVersion) + : m_Version(bsaVersion) + , m_FolderName("") + , m_FileName("dummy.dds") + , m_TotalFileNameLength(0) +{ +} + +void DummyBSA::writeHeader(QFile &file) +{ + unsigned char header[] = { + 'B', 'S', 'A', '\0', // magic string + 0xDE, 0xAD, 0xBE, 0xEF, // version - insert later + 0x24, 0x00, 0x00, 0x00, // offset to folder recors. header size is static + 0xDE, 0xAD, 0xBE, 0xEF, // archive flags - insert later + 0x01, 0x00, 0x00, 0x00, // folder count + 0x01, 0x00, 0x00, 0x00, // file count + 0xDE, 0xAD, 0xBE, 0xEF, // total folder names length - insert later + 0xDE, 0xAD, 0xBE, 0xEF, // total file names length - insert later + 0xDE, 0xAD, 0xBE, 0xEF // file flags - insert later + }; + + writeUlong(header, 4, m_Version); + writeUlong(header, 12, 0x01 | 0x02); // has directories and has files. + writeUlong(header, 24, m_FolderName.length() + 1); // empty folder name + writeUlong(header, 28, m_TotalFileNameLength); // single character file name + + writeUlong(header, 32, 2); // has dds + + file.write(reinterpret_cast(header), sizeof(header)); +} + +void DummyBSA::writeFolderRecord(QFile &file, const std::string &folderName) +{ + unsigned char folderRecord[] = { + 0xDE, 0xAD, 0xBE, 0xEF, 0xDE, 0xAD, 0xBE, 0xEF, // folder hash + 0x01, 0x00, 0x00, 0x00, // file count + 0xDE, 0xAD, 0xBE, 0xEF, // offset to folder name + }; + // we'd usually have to sort folders be the hash value generated here + writeUlonglong(folderRecord, 0, genHash(folderName.c_str())); + writeUlong( folderRecord, 12, 0x34 + m_TotalFileNameLength); // TODO: this should be calculated properly + + file.write(reinterpret_cast(folderRecord), sizeof(folderRecord)); +} + +void DummyBSA::writeFileRecord(QFile &file, const std::string &fileName) +{ + unsigned char fileRecord[] = { + 0xDE, 0xAD, 0xBE, 0xEF, 0xDE, 0xAD, 0xBE, 0xEF, // file name hash + 0xDE, 0xAD, 0xBE, 0xEF, // size + 0xDE, 0xAD, 0xBE, 0xEF, // offset to file data + }; + + // we'd usually have to sort files by the value generated here + writeUlonglong(fileRecord, 0, genHash(fileName.c_str())); + writeUlong( fileRecord, 8, 0); + writeUlong( fileRecord, 12, 0x44 + (fileName.length() + 1) + 4); // after this record we expect the filename and 4 bytes of file size + + file.write(reinterpret_cast(fileRecord), sizeof(fileRecord)); +} + +void DummyBSA::writeFileRecordBlocks(QFile &file, const std::string &folderName) +{ + file.write(folderName.c_str(), folderName.length() + 1); + + writeFileRecord(file, m_FileName); +} + +void DummyBSA::write(const QString &fileName) +{ + QFile file(fileName); + file.open(QIODevice::WriteOnly); + + m_TotalFileNameLength = m_FileName.length() + 1; + + writeHeader(file); + writeFolderRecord(file, m_FolderName); + writeFileRecordBlocks(file, m_FolderName); + file.write(m_FileName.c_str() , m_FileName.length() + 1); + char fileSize[] = { 0x00, 0x00, 0x00, 0x00 }; + file.write(fileSize, sizeof(fileSize)); + file.close(); +} diff --git a/src/dummybsa.h b/src/dummybsa.h new file mode 100644 index 00000000..35288439 --- /dev/null +++ b/src/dummybsa.h @@ -0,0 +1,64 @@ +/* +Copyright (C) 2012 Sebastian Herbord. All rights reserved. + +This file is part of Mod Organizer. + +Mod Organizer is free software: you can redistribute it and/or modify +it under the terms of the GNU General Public License as published by +the Free Software Foundation, either version 3 of the License, or +(at your option) any later version. + +Mod Organizer is distributed in the hope that it will be useful, +but WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +GNU General Public License for more details. + +You should have received a copy of the GNU General Public License +along with Mod Organizer. If not, see . +*/ + +#ifndef DUMMYBSA_H +#define DUMMYBSA_H + +#include +#include + +/** + * @brief Class for creating a dummy bsa used for archive invalidation + **/ +class DummyBSA +{ + +public: + + /** + * @brief constructor + * + **/ + DummyBSA(unsigned long bsaVersion); + + /** + * @brief write to the specified file + * + * @param fileName name of the file to write to + **/ + void write(const QString &fileName); + +private: + + void writeHeader(QFile &file); + void writeFolderRecord(QFile &file, const std::string &folderName); + void writeFileRecord(QFile &file, const std::string &fileName); + void writeFileRecordBlocks(QFile &file, const std::string &folderName); + +private: + + unsigned long m_Version; + std::string m_FolderName; + std::string m_FileName; + unsigned long m_TotalFileNameLength; + +}; + + +#endif // DUMMYBSA_H diff --git a/src/gameGamebryo.pro b/src/gameGamebryo.pro new file mode 100644 index 00000000..1873ffde --- /dev/null +++ b/src/gameGamebryo.pro @@ -0,0 +1,23 @@ +#------------------------------------------------- +# +# Project created by QtCreator 2015-01-26T19:47:42 +# +#------------------------------------------------- + +TARGET = gameGamebryo +TEMPLATE = lib +CONFIG += staticlib + +SOURCES += gamegamebryo.cpp \ + dummybsa.cpp \ + gamebryobsainvalidation.cpp \ + gamebryodataarchives.cpp + +HEADERS += gamegamebryo.h \ + dummybsa.h \ + gamebryobsainvalidation.h \ + gamebryodataarchives.h + +include(../plugin_template.pri) + +INCLUDEPATH += "$${BOOSTPATH}" "$${PWD}/../gamefeatures" diff --git a/src/gamebryobsainvalidation.cpp b/src/gamebryobsainvalidation.cpp new file mode 100644 index 00000000..515948e3 --- /dev/null +++ b/src/gamebryobsainvalidation.cpp @@ -0,0 +1,79 @@ +#include "gamebryobsainvalidation.h" +#include "dummybsa.h" +#include +#include +#include +#include +#include +#include + + +GamebryoBSAInvalidation::GamebryoBSAInvalidation(const std::shared_ptr &dataArchives + , const QString &iniFilename + , MOBase::IOrganizer *moInfo) + : m_DataArchives(dataArchives) + , m_IniFileName(iniFilename) + , m_Organizer(moInfo) +{ +} + +bool GamebryoBSAInvalidation::isInvalidationBSA(const QString &bsaName) +{ + static QStringList invalidation { invalidationBSAName() }; + + for (const QString &file : invalidation) { + if (file.compare(bsaName, Qt::CaseInsensitive) == 0) { + return true; + } + } + return false; +} + +void GamebryoBSAInvalidation::deactivate(MOBase::IProfile *profile) +{ + QStringList archivesBefore = m_DataArchives->archives(profile); + for (const QString &archive : archivesBefore) { + if (!isInvalidationBSA(archive)) { + m_DataArchives->removeArchive(profile, archive); + } + } + + QString iniFile = QDir(profile->absolutePath()).absoluteFilePath(m_IniFileName); + + if (!::WritePrivateProfileStringW(L"Archive", L"bInvalidateOlderFiles", L"0", iniFile.toStdWString().c_str()) || + !::WritePrivateProfileStringW(L"Archive", L"SInvalidationFile", L"ArchiveInvalidation.txt", iniFile.toStdWString().c_str())) { + throw MOBase::MyException(QObject::tr("failed to deactivate BSA invalidation in \"%1\" (errorcode %2)").arg(iniFile, ::GetLastError())); + } +} + +void GamebryoBSAInvalidation::activate(MOBase::IProfile *profile) +{ + // set the invalidation bsa up to be loaded + QStringList archives = m_DataArchives->archives(profile); + bool bsaInstalled = false; + for (const QString &archive : archives) { + if (isInvalidationBSA(archive)) { + bsaInstalled = true; + break; + } + } + if (!bsaInstalled) { + m_DataArchives->addArchive(profile, 0, invalidationBSAName()); + + // create the dummy bsa if necessary + QString bsaFile = m_Organizer->gameInfo().path() + "/" + invalidationBSAName(); + if (!QFile::exists(bsaFile)) { + DummyBSA bsa(bsaVersion()); + bsa.write(bsaFile); + } + } + + // set the remaining ini settings required + QString iniFile = QDir(profile->absolutePath()).absoluteFilePath(m_IniFileName); + + if (!::WritePrivateProfileStringW(L"Archive", L"bInvalidateOlderFiles", L"1", iniFile.toStdWString().c_str()) || + !::WritePrivateProfileStringW(L"Archive", L"SInvalidationFile", L"", iniFile.toStdWString().c_str())) { + throw MOBase::MyException(QObject::tr("failed to activate BSA invalidation in \"%1\" (errorcode %2)").arg(iniFile, ::GetLastError())); + } +} + diff --git a/src/gamebryobsainvalidation.h b/src/gamebryobsainvalidation.h new file mode 100644 index 00000000..9366a5ab --- /dev/null +++ b/src/gamebryobsainvalidation.h @@ -0,0 +1,38 @@ +#ifndef GAMEBRYOBSAINVALIDATION_H +#define GAMEBRYOBSAINVALIDATION_H + + +#include +#include +#include +#include + + +namespace MOBase { + class IOrganizer; +} + +class GamebryoBSAInvalidation : public BSAInvalidation +{ +public: + + GamebryoBSAInvalidation(const std::shared_ptr &dataArchives, const QString &iniFilename, MOBase::IOrganizer *moInfo); + + virtual bool isInvalidationBSA(const QString &bsaName) override; + virtual void deactivate(MOBase::IProfile *profile) override; + virtual void activate(MOBase::IProfile *profile) override; + +private: + + virtual QString invalidationBSAName() const = 0; + virtual unsigned long bsaVersion() const = 0; // 0x67 for oblivion, 0x68 for everything else + +private: + + std::shared_ptr m_DataArchives; + QString m_IniFileName; + MOBase::IOrganizer *m_Organizer; + +}; + +#endif // GAMEBRYOBSAINVALIDATION_H diff --git a/src/gamebryodataarchives.cpp b/src/gamebryodataarchives.cpp new file mode 100644 index 00000000..7a8862bf --- /dev/null +++ b/src/gamebryodataarchives.cpp @@ -0,0 +1,57 @@ +#include "gamebryodataarchives.h" +#include +#include +#include + + +QStringList GamebryoDataArchives::getArchivesFromKey(const QString &iniFile, const QString &key) const +{ + wchar_t buffer[256]; + QStringList result; + std::wstring iniFileW = QDir::toNativeSeparators(iniFile).toStdWString(); + + // epic ms fail: GetPrivateProfileString uses errno (for whatever reason) to signal a fail since the return value + // has a different meaning (number of bytes copied). HOWEVER, it will not set errno to 0 if NO error occured + errno = 0; + + if (::GetPrivateProfileStringW(L"Archive", key.toStdWString().c_str(), + L"", buffer, 256, iniFileW.c_str()) != 0) { + result.append(QString::fromStdWString(buffer).split(',')); + } + + for (int i = 0; i < result.count(); ++i) { + result[i] = result[i].trimmed(); + } + return result; +} + +void GamebryoDataArchives::setArchivesToKey(const QString &iniFile, const QString &key, const QString &value) +{ + if (!::WritePrivateProfileStringW(L"Archive", key.toStdWString().c_str(), value.toStdWString().c_str(), iniFile.toStdWString().c_str())) { + throw MOBase::MyException(QObject::tr("failed to set archive key (errorcode %1)").arg(errno)); + } +} + +void GamebryoDataArchives::addArchive(MOBase::IProfile *profile, int index, const QString &archiveName) +{ + QStringList current = archives(profile); + if (current.contains(archiveName, Qt::CaseInsensitive)) { + return; + } + + current.insert(index != INT_MAX ? index : current.size(), archiveName); + + writeArchiveList(profile, current); +} + +void GamebryoDataArchives::removeArchive(MOBase::IProfile *profile, const QString &archiveName) +{ + QStringList current = archives(profile); + if (!current.contains(archiveName, Qt::CaseInsensitive)) { + return; + } + + current.removeAll(archiveName); + + writeArchiveList(profile, current); +} diff --git a/src/gamebryodataarchives.h b/src/gamebryodataarchives.h new file mode 100644 index 00000000..f9436dda --- /dev/null +++ b/src/gamebryodataarchives.h @@ -0,0 +1,27 @@ +#ifndef GAMEBRYODATAARCHIVES_H +#define GAMEBRYODATAARCHIVES_H + + +#include + + +class GamebryoDataArchives : public DataArchives +{ + +public: + + virtual void addArchive(MOBase::IProfile *profile, int index, const QString &archiveName) override; + virtual void removeArchive(MOBase::IProfile *profile, const QString &archiveName) override; + +protected: + + QStringList getArchivesFromKey(const QString &iniFile, const QString &key) const; + void setArchivesToKey(const QString &iniFile, const QString &key, const QString &value); + +private: + + virtual void writeArchiveList(MOBase::IProfile *profile, QStringList before) = 0; + +}; + +#endif // GAMEBRYODATAARCHIVES_H diff --git a/src/gamegamebryo.cpp b/src/gamegamebryo.cpp new file mode 100644 index 00000000..7777d449 --- /dev/null +++ b/src/gamegamebryo.cpp @@ -0,0 +1,124 @@ +#include "gamegamebryo.h" +#include +#include + + +GameGamebryo::GameGamebryo() +{ +} + +bool GameGamebryo::init(MOBase::IOrganizer *moInfo) +{ + m_GamePath = identifyGamePath(); + m_MyGamesPath = determineMyGamesPath(myGamesFolderName()); + m_Organizer = moInfo; + return true; +} + +QDir GameGamebryo::gameDirectory() const +{ + return QDir(m_GamePath); +} + +QDir GameGamebryo::savesDirectory() const +{ + return QDir(m_MyGamesPath + "/Saves"); +} + +QDir GameGamebryo::documentsDirectory() const +{ + return m_MyGamesPath; +} + +bool GameGamebryo::isInstalled() const +{ + return !m_GamePath.isEmpty(); +} + +std::unique_ptr GameGamebryo::getRegValue(HKEY key, LPCWSTR subKey, LPCWSTR value, DWORD flags, LPDWORD type) const +{ + DWORD size = 0; + DWORD res = ::RegGetValueW(key, subKey, value, flags, type, nullptr, &size); + if (res == ERROR_FILE_NOT_FOUND) { + return std::unique_ptr(); + } else if ((res != ERROR_SUCCESS) && (res != ERROR_MORE_DATA)) { + throw MOBase::MyException(QObject::tr("failed to query registry path (preflight): %1").arg(res, 0, 16)); + } + + std::unique_ptr result(new BYTE[size]); + res = ::RegGetValueW(key, subKey, value, flags, type, result.get(), &size); + + if (res != ERROR_SUCCESS) { + throw MOBase::MyException(QObject::tr("failed to query registry path (read): %1").arg(res, 0, 16)); + } + + return result; +} + +QString GameGamebryo::findInRegistry(HKEY baseKey, LPCWSTR path, LPCWSTR value) const +{ + std::unique_ptr buffer = getRegValue(baseKey, path, value, RRF_RT_REG_SZ | RRF_NOEXPAND); + + if (buffer.get() != nullptr) { + return QString::fromUtf16(reinterpret_cast(buffer.get())); + } else { + return QString(); + } +} + +QFileInfo GameGamebryo::findInGameFolder(const QString &relativePath) +{ + return QFileInfo(m_GamePath + "/" + relativePath); +} + +QString GameGamebryo::getKnownFolderPath(REFKNOWNFOLDERID folderId, bool useDefault) const +{ + PWSTR path = nullptr; + ON_BLOCK_EXIT([&] () { + if (path != nullptr) ::CoTaskMemFree(path); + }); + + if (::SHGetKnownFolderPath(folderId, useDefault ? KF_FLAG_DEFAULT_PATH : 0, NULL, &path) == S_OK) { + return QDir::fromNativeSeparators(QString::fromWCharArray(path)); + } else { + return QString(); + } +} + +QString GameGamebryo::determineMyGamesPath(const QString &gameName) +{ + // a) this is the way it should work. get the configured My Documents directory + QString result = getKnownFolderPath(FOLDERID_Documents, false); + + // b) if there is no directory there, look in the default directory + if (result.isEmpty() + || !QFileInfo(result + "/My Games/" + gameName).exists()) { + result = getKnownFolderPath(FOLDERID_Documents, true); + } + // c) finally, look in the registry. This is discouraged + if (result.isEmpty() + || !QFileInfo(result + "/My Games/" + gameName).exists()) { + result = getSpecialPath("Personal"); + } + + return result + "/My Games/" + gameName; +} + +QString GameGamebryo::getSpecialPath(const QString &name) const +{ + QString base = findInRegistry(HKEY_CURRENT_USER, + L"Software\\Microsoft\\Windows\\CurrentVersion\\Explorer\\User Shell Folders", + name.toStdWString().c_str()); + + WCHAR temp[MAX_PATH]; + if (::ExpandEnvironmentStringsW(base.toStdWString().c_str(), temp, MAX_PATH) != 0) { + return QString::fromWCharArray(temp); + } else { + return base; + } +} + +QString GameGamebryo::myGamesPath() const +{ + return m_MyGamesPath; +} diff --git a/src/gamegamebryo.h b/src/gamegamebryo.h new file mode 100644 index 00000000..81a4fb16 --- /dev/null +++ b/src/gamegamebryo.h @@ -0,0 +1,54 @@ +#ifndef GAMEGAMEBRYO_H +#define GAMEGAMEBRYO_H + + +#include +#include +#include + + +class GameGamebryo : public MOBase::IPluginGame +{ + Q_OBJECT + Q_INTERFACES(MOBase::IPlugin MOBase::IPluginGame) + +public: + + GameGamebryo(); + + virtual bool init(MOBase::IOrganizer *moInfo) override; + +public: // IPluginGame interface + + virtual QDir gameDirectory() const; + virtual QDir savesDirectory() const; + virtual QDir documentsDirectory() const; + + virtual bool isInstalled() const override; + +protected: + + std::unique_ptr getRegValue(HKEY key, LPCWSTR subKey, LPCWSTR value, DWORD flags, LPDWORD type = nullptr) const; + QString findInRegistry(HKEY baseKey, LPCWSTR path, LPCWSTR value) const; + QFileInfo findInGameFolder(const QString &relativePath); + QString getKnownFolderPath(REFKNOWNFOLDERID folderId, bool useDefault) const; + QString getSpecialPath(const QString &name) const; + QString myGamesPath() const; + +private: + + QString determineMyGamesPath(const QString &gameName); + + virtual QString myGamesFolderName() const = 0; + virtual QString identifyGamePath() const = 0; + +private: + + QString m_GamePath; + QString m_MyGamesPath; + + MOBase::IOrganizer *m_Organizer; + +}; + +#endif // GAMEGAMEBRYO_H From 129477e67fa932b187b9450a20db8b8c389bde20 Mon Sep 17 00:00:00 2001 From: Tannin Date: Thu, 29 Jan 2015 19:26:42 +0100 Subject: [PATCH 0006/1544] [game_oblivion] extended the game-plugin interface --- src/games/oblivion/src/gameOblivion.pro | 43 ++++++ src/games/oblivion/src/gameoblivion.cpp | 163 +++++++++++++++++++++++ src/games/oblivion/src/gameoblivion.h | 65 +++++++++ src/games/oblivion/src/gameoblivion.json | 1 + 4 files changed, 272 insertions(+) create mode 100644 src/games/oblivion/src/gameOblivion.pro create mode 100644 src/games/oblivion/src/gameoblivion.cpp create mode 100644 src/games/oblivion/src/gameoblivion.h create mode 100644 src/games/oblivion/src/gameoblivion.json diff --git a/src/games/oblivion/src/gameOblivion.pro b/src/games/oblivion/src/gameOblivion.pro new file mode 100644 index 00000000..f089b124 --- /dev/null +++ b/src/games/oblivion/src/gameOblivion.pro @@ -0,0 +1,43 @@ +#------------------------------------------------- +# +# Project created by QtCreator 2014-11-15T15:36:33 +# +#------------------------------------------------- + + +TARGET = gameOblivion +TEMPLATE = lib + +CONFIG += plugins +CONFIG += dll + +DEFINES += GAMEOBLIVION_LIBRARY + +SOURCES += gameoblivion.cpp \ + oblivionbsainvalidation.cpp \ + oblivionscriptextender.cpp \ + obliviondataarchives.cpp + +HEADERS += gameoblivion.h \ + oblivionbsainvalidation.h \ + oblivionscriptextender.h \ + obliviondataarchives.h + +CONFIG(debug, debug|release) { + LIBS += -L"$${OUT_PWD}/../gameGamebryo/debug" + PRE_TARGETDEPS += \ + $$OUT_PWD/../gameGamebryo/debug/gameGamebryo.lib +} else { + LIBS += -L"$${OUT_PWD}/../gameGamebryo/release" + PRE_TARGETDEPS += \ + $$OUT_PWD/../gameGamebryo/release/gameGamebryo.lib +} + +include(../plugin_template.pri) + +INCLUDEPATH += "$${BOOSTPATH}" "$${PWD}/../gamefeatures" "$${PWD}/../gamegamebryo" + +LIBS += -ladvapi32 -lole32 -lgameGamebryo + +OTHER_FILES += \ + gameoblivion.json diff --git a/src/games/oblivion/src/gameoblivion.cpp b/src/games/oblivion/src/gameoblivion.cpp new file mode 100644 index 00000000..cc3d0d38 --- /dev/null +++ b/src/games/oblivion/src/gameoblivion.cpp @@ -0,0 +1,163 @@ +#include "gameoblivion.h" +#include +#include +#include +#include +#include +#include +#include + + +using namespace MOBase; + + +GameOblivion::GameOblivion() +{ +} + +bool GameOblivion::init(IOrganizer *moInfo) +{ + if (!GameGamebryo::init(moInfo)) { + return false; + } + m_ScriptExtender = std::shared_ptr(new OblivionScriptExtender()); + m_DataArchives = std::shared_ptr(new OblivionDataArchives()); + m_BSAInvalidation = std::shared_ptr(new OblivionBSAInvalidation(m_DataArchives, moInfo)); + return true; +} + +QString GameOblivion::identifyGamePath() const +{ + return findInRegistry(HKEY_LOCAL_MACHINE, L"Software\\Bethesda Softworks\\Oblivion", L"Installed Path"); +} + +QString GameOblivion::gameName() const +{ + return "Oblivion"; +} + +QString GameOblivion::localAppFolder() const +{ + QString result = getKnownFolderPath(FOLDERID_LocalAppData, false); + if (result.isEmpty()) { + // fallback: try the registry + result = getSpecialPath("Local AppData"); + } + + return result; +} + +QString GameOblivion::myGamesFolderName() const +{ + return "Oblivion"; +} + + + +QList GameOblivion::executables() +{ + return QList() + << ExecutableInfo("OBSE", findInGameFolder("obse_loader.exe")) + << ExecutableInfo("Oblivion", findInGameFolder("oblivion.exe")) + << ExecutableInfo("Oblivion Launcher", findInGameFolder("OblivionLauncher.exe")) + << ExecutableInfo("Oblivion Mod Manager", findInGameFolder("OblivionModManager.exe")) + << ExecutableInfo("BOSS", findInGameFolder("BOSS/BOSS.exe")) + << ExecutableInfo("LOOT", findInRegistry(HKEY_LOCAL_MACHINE, L"Software\\LOOT", L"Installed Path")) + << ExecutableInfo("Construction Set", findInGameFolder("TESConstructionSet.exe")) + ; +} + +QString GameOblivion::name() const +{ + return "Oblivion Support Plugin"; +} + +QString GameOblivion::author() const +{ + return "Tannin"; +} + +QString GameOblivion::description() const +{ + return tr("Adds support for the game Oblivion"); +} + +MOBase::VersionInfo GameOblivion::version() const +{ + return VersionInfo(1, 0, 0, VersionInfo::RELEASE_FINAL); +} + +bool GameOblivion::isActive() const +{ + return true; +} + +QList GameOblivion::settings() const +{ + return QList(); +} + + + +void GameOblivion::copyToProfile(const QString &sourcePath, const QDir &destinationDirectory, + const QString &sourceFileName, const QString &destinationFileName) const +{ + QString filePath = destinationDirectory.absoluteFilePath(destinationFileName.isEmpty() ? sourceFileName + : destinationFileName); + if (!QFileInfo(filePath).exists()) { + if (!shellCopy(sourcePath + "/" + sourceFileName, filePath)) { + // if copy file fails, create the file empty + QFile(filePath).open(QIODevice::WriteOnly); + } + } +} + +void GameOblivion::initializeProfile(const QDir &path, ProfileSettings settings) const +{ + if (settings.testFlag(IPluginGame::MODS)) { + copyToProfile(localAppFolder() + "/Oblivion", path, "plugins.txt"); + copyToProfile(localAppFolder() + "/Oblivion", path, "loadorder.txt"); + } + + if (settings.testFlag(IPluginGame::CONFIGURATION)) { + if (settings.testFlag(IPluginGame::PREFER_DEFAULTS) + || !QFileInfo(myGamesPath() + "/oblivion.ini").exists()) { + copyToProfile(gameDirectory().absolutePath(), path, "oblivion_default.ini", "oblivion.ini"); + } else { + copyToProfile(myGamesPath(), path, "oblivion.ini"); + } + + copyToProfile(myGamesPath(), path, "oblivionprefs.ini"); + } +} + +QString GameOblivion::savegameExtension() const +{ + return "ess"; +} + +QString GameOblivion::steamAPPId() const +{ + return "72850"; +} + +QStringList GameOblivion::getPrimaryPlugins() +{ + return { "oblivion.esm", "update.esm" }; +} + +QIcon GameOblivion::gameIcon() const +{ + return MOBase::iconForExecutable(gameDirectory().absoluteFilePath("Oblivion.exe")); +} + +const std::map &GameOblivion::featureList() const +{ + static std::map result { + { typeid(BSAInvalidation), m_BSAInvalidation.get() }, + { typeid(ScriptExtender), m_ScriptExtender.get() }, + { typeid(DataArchives), m_DataArchives.get() } + }; + + return result; +} diff --git a/src/games/oblivion/src/gameoblivion.h b/src/games/oblivion/src/gameoblivion.h new file mode 100644 index 00000000..66a67f6a --- /dev/null +++ b/src/games/oblivion/src/gameoblivion.h @@ -0,0 +1,65 @@ +#ifndef GAMEOBLIVION_H +#define GAMEOBLIVION_H + + +#include "oblivionbsainvalidation.h" +#include "oblivionscriptextender.h" +#include "obliviondataarchives.h" +#include +#include + + +class GameOblivion : public GameGamebryo +{ + Q_OBJECT +#if QT_VERSION >= QT_VERSION_CHECK(5,0,0) + Q_PLUGIN_METADATA(IID "org.tannin.GameOblivion" FILE "gameoblivion.json") +#endif + +public: + + GameOblivion(); + + virtual bool init(MOBase::IOrganizer *moInfo) override; + +public: // IPluginGame interface + + virtual QString gameName() const; + virtual QList executables(); + virtual void initializeProfile(const QDir &path, ProfileSettings settings) const; + virtual QString savegameExtension() const; + virtual QString steamAPPId() const; + virtual QStringList getPrimaryPlugins(); + virtual QIcon gameIcon() const override; + +public: // IPlugin interface + + virtual QString name() const; + virtual QString author() const; + virtual QString description() const; + virtual MOBase::VersionInfo version() const; + virtual bool isActive() const; + virtual QList settings() const; + +protected: + + virtual const std::map &featureList() const; + +private: + + virtual QString identifyGamePath() const override; + virtual QString myGamesFolderName() const override; + + QString localAppFolder() const; + void copyToProfile(const QString &sourcePath, const QDir &destinationDirectory, + const QString &sourceFileName, const QString &destinationFileName = QString()) const; + +private: + + std::shared_ptr m_ScriptExtender { nullptr }; + std::shared_ptr m_DataArchives { nullptr }; + std::shared_ptr m_BSAInvalidation { nullptr }; + +}; + +#endif // GAMEOBLIVION_H diff --git a/src/games/oblivion/src/gameoblivion.json b/src/games/oblivion/src/gameoblivion.json new file mode 100644 index 00000000..69a88e3b --- /dev/null +++ b/src/games/oblivion/src/gameoblivion.json @@ -0,0 +1 @@ +{} From 5ed5718588aae559880e824933afd7d9459364ea Mon Sep 17 00:00:00 2001 From: Tannin Date: Thu, 29 Jan 2015 19:26:42 +0100 Subject: [PATCH 0007/1544] [game_fallout3] extended the game-plugin interface --- .../fallout3/src/fallout3bsainvalidation.cpp | 18 ++ .../fallout3/src/fallout3bsainvalidation.h | 23 +++ .../fallout3/src/fallout3dataarchives.cpp | 33 ++++ src/games/fallout3/src/fallout3dataarchives.h | 24 +++ .../fallout3/src/fallout3scriptextender.cpp | 7 + .../fallout3/src/fallout3scriptextender.h | 14 ++ src/games/fallout3/src/gameFallout3.pro | 43 +++++ src/games/fallout3/src/gamefallout3.cpp | 161 ++++++++++++++++++ src/games/fallout3/src/gamefallout3.h | 65 +++++++ src/games/fallout3/src/gamefallout3.json | 1 + 10 files changed, 389 insertions(+) create mode 100644 src/games/fallout3/src/fallout3bsainvalidation.cpp create mode 100644 src/games/fallout3/src/fallout3bsainvalidation.h create mode 100644 src/games/fallout3/src/fallout3dataarchives.cpp create mode 100644 src/games/fallout3/src/fallout3dataarchives.h create mode 100644 src/games/fallout3/src/fallout3scriptextender.cpp create mode 100644 src/games/fallout3/src/fallout3scriptextender.h create mode 100644 src/games/fallout3/src/gameFallout3.pro create mode 100644 src/games/fallout3/src/gamefallout3.cpp create mode 100644 src/games/fallout3/src/gamefallout3.h create mode 100644 src/games/fallout3/src/gamefallout3.json diff --git a/src/games/fallout3/src/fallout3bsainvalidation.cpp b/src/games/fallout3/src/fallout3bsainvalidation.cpp new file mode 100644 index 00000000..3262787b --- /dev/null +++ b/src/games/fallout3/src/fallout3bsainvalidation.cpp @@ -0,0 +1,18 @@ +#include "fallout3bsainvalidation.h" +#include + + +Fallout3BSAInvalidation::Fallout3BSAInvalidation(const std::shared_ptr &dataArchives, MOBase::IOrganizer *moInfo) + : GamebryoBSAInvalidation(dataArchives, "fallout.ini", moInfo) +{ +} + +QString Fallout3BSAInvalidation::invalidationBSAName() const +{ + return "Fallout - Invalidation.bsa"; +} + +unsigned long Fallout3BSAInvalidation::bsaVersion() const +{ + return 0x68; +} diff --git a/src/games/fallout3/src/fallout3bsainvalidation.h b/src/games/fallout3/src/fallout3bsainvalidation.h new file mode 100644 index 00000000..7cb192d2 --- /dev/null +++ b/src/games/fallout3/src/fallout3bsainvalidation.h @@ -0,0 +1,23 @@ +#ifndef FALLOUT3BSAINVALIDATION_H +#define FALLOUT3BSAINVALIDATION_H + + +#include +#include +#include "fallout3dataarchives.h" + + +class Fallout3BSAInvalidation : public GamebryoBSAInvalidation +{ +public: + + Fallout3BSAInvalidation(const std::shared_ptr &dataArchives, MOBase::IOrganizer *moInfo); + +private: + + virtual QString invalidationBSAName() const override; + virtual unsigned long bsaVersion() const override; + +}; + +#endif // FALLOUT3BSAINVALIDATION_H diff --git a/src/games/fallout3/src/fallout3dataarchives.cpp b/src/games/fallout3/src/fallout3dataarchives.cpp new file mode 100644 index 00000000..3ee8a603 --- /dev/null +++ b/src/games/fallout3/src/fallout3dataarchives.cpp @@ -0,0 +1,33 @@ +#include "fallout3dataarchives.h" +#include +#include + + +QStringList Fallout3DataArchives::vanillaArchives() const +{ + return { "Fallout - Textures.bsa" + , "Fallout - Meshes.bsa" + , "Fallout - Voices.bsa" + , "Fallout - Sound.bsa" + , "Fallout - MenuVoices.bsa" + , "Fallout - Misc.bsa" }; +} + + +QStringList Fallout3DataArchives::archives(const MOBase::IProfile *profile) const +{ + QStringList result; + + QString iniFile = QDir(profile->absolutePath()).absoluteFilePath("fallout3.ini"); + result.append(getArchivesFromKey(iniFile, "SArchiveList")); + + return result; +} + +void Fallout3DataArchives::writeArchiveList(MOBase::IProfile *profile, QStringList before) +{ + QString list = before.join(','); + + QString iniFile = QDir(profile->absolutePath()).absoluteFilePath("fallout3.ini"); + setArchivesToKey(iniFile, "SArchiveList", list); +} diff --git a/src/games/fallout3/src/fallout3dataarchives.h b/src/games/fallout3/src/fallout3dataarchives.h new file mode 100644 index 00000000..df9fba46 --- /dev/null +++ b/src/games/fallout3/src/fallout3dataarchives.h @@ -0,0 +1,24 @@ +#ifndef FALLOUT3DATAARCHIVES_H +#define FALLOUT3DATAARCHIVES_H + + +#include +#include +#include +#include + +class Fallout3DataArchives : public GamebryoDataArchives +{ + +public: + + virtual QStringList vanillaArchives() const override; + virtual QStringList archives(const MOBase::IProfile *profile) const override; + +private: + + virtual void writeArchiveList(MOBase::IProfile *profile, QStringList before) override; + +}; + +#endif // FALLOUT3DATAARCHIVES_H diff --git a/src/games/fallout3/src/fallout3scriptextender.cpp b/src/games/fallout3/src/fallout3scriptextender.cpp new file mode 100644 index 00000000..d71c3cee --- /dev/null +++ b/src/games/fallout3/src/fallout3scriptextender.cpp @@ -0,0 +1,7 @@ +#include "fallout3scriptextender.h" + + +QString Fallout3ScriptExtender::name() const +{ + return "fose"; +} diff --git a/src/games/fallout3/src/fallout3scriptextender.h b/src/games/fallout3/src/fallout3scriptextender.h new file mode 100644 index 00000000..3c362f2f --- /dev/null +++ b/src/games/fallout3/src/fallout3scriptextender.h @@ -0,0 +1,14 @@ +#ifndef FALLOUT3SCRIPTEXTENDER_H +#define FALLOUT3SCRIPTEXTENDER_H + + +#include + + +class Fallout3ScriptExtender : public ScriptExtender +{ +public: + virtual QString name() const override; +}; + +#endif // FALLOUT3SCRIPTEXTENDER_H diff --git a/src/games/fallout3/src/gameFallout3.pro b/src/games/fallout3/src/gameFallout3.pro new file mode 100644 index 00000000..d958ca1b --- /dev/null +++ b/src/games/fallout3/src/gameFallout3.pro @@ -0,0 +1,43 @@ +#------------------------------------------------- +# +# Project created by QtCreator 2014-11-15T15:36:33 +# +#------------------------------------------------- + + +TARGET = gameFallout3 +TEMPLATE = lib + +CONFIG += plugins +CONFIG += dll + +DEFINES += GAMEFALLOUTNV_LIBRARY + +SOURCES += gamefallout3.cpp \ + fallout3bsainvalidation.cpp \ + fallout3scriptextender.cpp \ + fallout3dataarchives.cpp + +HEADERS += gamefallout3.h \ + fallout3bsainvalidation.h \ + fallout3scriptextender.h \ + fallout3dataarchives.h + +CONFIG(debug, debug|release) { + LIBS += -L"$${OUT_PWD}/../gameGamebryo/debug" + PRE_TARGETDEPS += \ + $$OUT_PWD/../gameGamebryo/debug/gameGamebryo.lib +} else { + LIBS += -L"$${OUT_PWD}/../gameGamebryo/release" + PRE_TARGETDEPS += \ + $$OUT_PWD/../gameGamebryo/release/gameGamebryo.lib +} + +include(../plugin_template.pri) + +INCLUDEPATH += "$${BOOSTPATH}" "$${PWD}/../gamefeatures" "$${PWD}/../gamegamebryo" + +LIBS += -ladvapi32 -lole32 -lgameGamebryo + +OTHER_FILES += \ + gamefallout3.json diff --git a/src/games/fallout3/src/gamefallout3.cpp b/src/games/fallout3/src/gamefallout3.cpp new file mode 100644 index 00000000..37931da4 --- /dev/null +++ b/src/games/fallout3/src/gamefallout3.cpp @@ -0,0 +1,161 @@ +#include "gameFallout3.h" +#include +#include +#include +#include +#include +#include +#include + + +using namespace MOBase; + + +GameFallout3::GameFallout3() +{ +} + +bool GameFallout3::init(IOrganizer *moInfo) +{ + if (!GameGamebryo::init(moInfo)) { + return false; + } + m_ScriptExtender = std::shared_ptr(new Fallout3ScriptExtender()); + m_DataArchives = std::shared_ptr(new Fallout3DataArchives()); + m_BSAInvalidation = std::shared_ptr(new Fallout3BSAInvalidation(m_DataArchives, moInfo)); + return true; +} + +QString GameFallout3::identifyGamePath() const +{ + return findInRegistry(HKEY_LOCAL_MACHINE, L"Software\\Bethesda Softworks\\Fallout3", L"Installed Path"); +} + +QString GameFallout3::gameName() const +{ + return "Fallout 3"; +} + +QString GameFallout3::localAppFolder() const +{ + QString result = getKnownFolderPath(FOLDERID_LocalAppData, false); + if (result.isEmpty()) { + // fallback: try the registry + result = getSpecialPath("Local AppData"); + } + + return result; +} + +QString GameFallout3::myGamesFolderName() const +{ + return "Fallout3"; +} + +QList GameFallout3::executables() +{ + return QList() + << ExecutableInfo("FOSE", findInGameFolder("fose_loader.exe")) + << ExecutableInfo("Fallout 3", findInGameFolder("Fallout3.exe")) + << ExecutableInfo("Fallout Mod Manager", findInGameFolder("fomm/fomm.exe")) + << ExecutableInfo("Construction Kit", findInGameFolder("geck.exe")) + << ExecutableInfo("Fallout Launcher", findInGameFolder("Fallout3Launcher.exe")) + << ExecutableInfo("BOSS", findInGameFolder("BOSS/BOSS.exe")) + << ExecutableInfo("LOOT", findInRegistry(HKEY_LOCAL_MACHINE, L"Software\\LOOT", L"Installed Path")) + ; +} + +QString GameFallout3::name() const +{ + return "Fallout3 Support Plugin"; +} + +QString GameFallout3::author() const +{ + return "Tannin"; +} + +QString GameFallout3::description() const +{ + return tr("Adds support for the game Fallout 3s"); +} + +MOBase::VersionInfo GameFallout3::version() const +{ + return VersionInfo(1, 0, 0, VersionInfo::RELEASE_FINAL); +} + +bool GameFallout3::isActive() const +{ + return true; +} + +QList GameFallout3::settings() const +{ + return QList(); +} + + + +void GameFallout3::copyToProfile(const QString &sourcePath, const QDir &destinationDirectory, + const QString &sourceFileName, const QString &destinationFileName) const +{ + QString filePath = destinationDirectory.absoluteFilePath(destinationFileName.isEmpty() ? sourceFileName + : destinationFileName); + if (!QFileInfo(filePath).exists()) { + if (!shellCopy(sourcePath + "/" + sourceFileName, filePath)) { + // if copy file fails, create the file empty + QFile(filePath).open(QIODevice::WriteOnly); + } + } +} + +void GameFallout3::initializeProfile(const QDir &path, ProfileSettings settings) const +{ + if (settings.testFlag(IPluginGame::MODS)) { + copyToProfile(localAppFolder() + "/Fallout3", path, "plugins.txt"); + copyToProfile(localAppFolder() + "/Fallout3", path, "loadorder.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"); + } +} + +QString GameFallout3::savegameExtension() const +{ + return "fos"; +} + +QString GameFallout3::steamAPPId() const +{ + return "22380"; +} + +QStringList GameFallout3::getPrimaryPlugins() +{ + return { "fallout3.esm" }; +} + +QIcon GameFallout3::gameIcon() const +{ + return MOBase::iconForExecutable(gameDirectory().absoluteFilePath("Fallout3.exe")); +} + +const std::map &GameFallout3::featureList() const +{ + static std::map result { + { typeid(BSAInvalidation), m_BSAInvalidation.get() }, + { typeid(ScriptExtender), m_ScriptExtender.get() }, + { typeid(DataArchives), m_DataArchives.get() } + }; + + return result; +} diff --git a/src/games/fallout3/src/gamefallout3.h b/src/games/fallout3/src/gamefallout3.h new file mode 100644 index 00000000..83512d01 --- /dev/null +++ b/src/games/fallout3/src/gamefallout3.h @@ -0,0 +1,65 @@ +#ifndef GAMEFALLOUT3_H +#define GAMEFALLOUT3_H + + +#include "fallout3bsainvalidation.h" +#include "fallout3scriptextender.h" +#include "fallout3dataarchives.h" +#include +#include + + +class GameFallout3 : public GameGamebryo +{ + Q_OBJECT +#if QT_VERSION >= QT_VERSION_CHECK(5,0,0) + Q_PLUGIN_METADATA(IID "org.tannin.GameFallout3" FILE "gamefallout3.json") +#endif + +public: + + GameFallout3(); + + virtual bool init(MOBase::IOrganizer *moInfo) override; + +public: // IPluginGame interface + + virtual QString gameName() const; + virtual QList executables(); + virtual void initializeProfile(const QDir &path, ProfileSettings settings) const; + virtual QString savegameExtension() const; + virtual QString steamAPPId() const; + virtual QStringList getPrimaryPlugins(); + virtual QIcon gameIcon() const override; + +public: // IPlugin interface + + virtual QString name() const; + virtual QString author() const; + virtual QString description() const; + virtual MOBase::VersionInfo version() const; + virtual bool isActive() const; + virtual QList settings() const; + +protected: + + virtual const std::map &featureList() const; + +private: + + virtual QString identifyGamePath() const override; + virtual QString myGamesFolderName() const override; + + QString localAppFolder() const; + void copyToProfile(const QString &sourcePath, const QDir &destinationDirectory, + const QString &sourceFileName, const QString &destinationFileName = QString()) const; + +private: + + std::shared_ptr m_ScriptExtender { nullptr }; + std::shared_ptr m_DataArchives { nullptr }; + std::shared_ptr m_BSAInvalidation { nullptr }; + +}; + +#endif // GAMEFALLOUT3_H diff --git a/src/games/fallout3/src/gamefallout3.json b/src/games/fallout3/src/gamefallout3.json new file mode 100644 index 00000000..69a88e3b --- /dev/null +++ b/src/games/fallout3/src/gamefallout3.json @@ -0,0 +1 @@ +{} From 5c3134420226b78cc9f53d725b4029d0b603841c Mon Sep 17 00:00:00 2001 From: Tannin Date: Wed, 25 Feb 2015 18:38:01 +0100 Subject: [PATCH 0008/1544] [game_skyrim] tons of code cleanup and minor fixes to harden the code (mostly suggestions from static code analysis) --- src/games/skyrim/src/gameSkyrim.pro | 1 - src/games/skyrim/src/gameskyrim.cpp | 2 +- 2 files changed, 1 insertion(+), 2 deletions(-) diff --git a/src/games/skyrim/src/gameSkyrim.pro b/src/games/skyrim/src/gameSkyrim.pro index 6198a022..74ca971b 100644 --- a/src/games/skyrim/src/gameSkyrim.pro +++ b/src/games/skyrim/src/gameSkyrim.pro @@ -10,7 +10,6 @@ TEMPLATE = lib CONFIG += plugins CONFIG += dll - DEFINES += GAMESKYRIM_LIBRARY SOURCES += gameskyrim.cpp \ diff --git a/src/games/skyrim/src/gameskyrim.cpp b/src/games/skyrim/src/gameskyrim.cpp index 81db3d2a..2633c77c 100644 --- a/src/games/skyrim/src/gameskyrim.cpp +++ b/src/games/skyrim/src/gameskyrim.cpp @@ -143,7 +143,7 @@ QString GameSkyrim::steamAPPId() const QStringList GameSkyrim::getPrimaryPlugins() { - return { "skyrim.esm", "update.esm" }; + return QStringList({ QString("skyrim.esm"), QString("update.esm") }); } QIcon GameSkyrim::gameIcon() const From 7da5bc2658beb9ddb9891e812c1b5a7abc7c4888 Mon Sep 17 00:00:00 2001 From: Tannin Date: Wed, 25 Feb 2015 18:38:01 +0100 Subject: [PATCH 0009/1544] [game_falloutnv] tons of code cleanup and minor fixes to harden the code (mostly suggestions from static code analysis) --- src/games/falloutnv/src/gamefalloutnv.cpp | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/src/games/falloutnv/src/gamefalloutnv.cpp b/src/games/falloutnv/src/gamefalloutnv.cpp index a2710f59..40c54ea6 100644 --- a/src/games/falloutnv/src/gamefalloutnv.cpp +++ b/src/games/falloutnv/src/gamefalloutnv.cpp @@ -33,7 +33,7 @@ QString GameFalloutNV::identifyGamePath() const QString GameFalloutNV::gameName() const { - return "FalloutNV"; + return "New Vegas"; } QString GameFalloutNV::localAppFolder() const @@ -52,8 +52,6 @@ QString GameFalloutNV::myGamesFolderName() const return "FalloutNV"; } - - QList GameFalloutNV::executables() { return QList() From 2580dd90a4958e40f01cea19d6a5323ccb705cc0 Mon Sep 17 00:00:00 2001 From: Tannin Date: Wed, 25 Feb 2015 18:38:01 +0100 Subject: [PATCH 0010/1544] tons of code cleanup and minor fixes to harden the code (mostly suggestions from static code analysis) --- src/gamegamebryo.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/gamegamebryo.cpp b/src/gamegamebryo.cpp index 7777d449..dca670fa 100644 --- a/src/gamegamebryo.cpp +++ b/src/gamegamebryo.cpp @@ -39,7 +39,7 @@ std::unique_ptr GameGamebryo::getRegValue(HKEY key, LPCWSTR subKey, LPCW { DWORD size = 0; DWORD res = ::RegGetValueW(key, subKey, value, flags, type, nullptr, &size); - if (res == ERROR_FILE_NOT_FOUND) { + if ((res == ERROR_FILE_NOT_FOUND) || (res == ERROR_UNSUPPORTED_TYPE)) { return std::unique_ptr(); } else if ((res != ERROR_SUCCESS) && (res != ERROR_MORE_DATA)) { throw MOBase::MyException(QObject::tr("failed to query registry path (preflight): %1").arg(res, 0, 16)); From ca6fe4f1f0adcd732e6476f004386ff177fb7e68 Mon Sep 17 00:00:00 2001 From: Tannin Date: Mon, 9 Mar 2015 12:22:06 +0100 Subject: [PATCH 0011/1544] [game_oblivion] added oblivion game-plugin --- .../oblivion/src/oblivionbsainvalidation.cpp | 18 ++++++++ .../oblivion/src/oblivionbsainvalidation.h | 23 +++++++++++ .../oblivion/src/obliviondataarchives.cpp | 41 +++++++++++++++++++ src/games/oblivion/src/obliviondataarchives.h | 24 +++++++++++ .../oblivion/src/oblivionscriptextender.cpp | 7 ++++ .../oblivion/src/oblivionscriptextender.h | 14 +++++++ 6 files changed, 127 insertions(+) create mode 100644 src/games/oblivion/src/oblivionbsainvalidation.cpp create mode 100644 src/games/oblivion/src/oblivionbsainvalidation.h create mode 100644 src/games/oblivion/src/obliviondataarchives.cpp create mode 100644 src/games/oblivion/src/obliviondataarchives.h create mode 100644 src/games/oblivion/src/oblivionscriptextender.cpp create mode 100644 src/games/oblivion/src/oblivionscriptextender.h diff --git a/src/games/oblivion/src/oblivionbsainvalidation.cpp b/src/games/oblivion/src/oblivionbsainvalidation.cpp new file mode 100644 index 00000000..cfa9f9ea --- /dev/null +++ b/src/games/oblivion/src/oblivionbsainvalidation.cpp @@ -0,0 +1,18 @@ +#include "oblivionbsainvalidation.h" +#include + + +OblivionBSAInvalidation::OblivionBSAInvalidation(const std::shared_ptr &dataArchives, MOBase::IOrganizer *moInfo) + : GamebryoBSAInvalidation(dataArchives, "oblivion.ini", moInfo) +{ +} + +QString OblivionBSAInvalidation::invalidationBSAName() const +{ + return "Oblivion - Invalidation.bsa"; +} + +unsigned long OblivionBSAInvalidation::bsaVersion() const +{ + return 0x67; +} diff --git a/src/games/oblivion/src/oblivionbsainvalidation.h b/src/games/oblivion/src/oblivionbsainvalidation.h new file mode 100644 index 00000000..2213df1b --- /dev/null +++ b/src/games/oblivion/src/oblivionbsainvalidation.h @@ -0,0 +1,23 @@ +#ifndef OBLIVIONBSAINVALIDATION_H +#define OBLIVIONBSAINVALIDATION_H + + +#include +#include +#include "obliviondataarchives.h" + + +class OblivionBSAInvalidation : public GamebryoBSAInvalidation +{ +public: + + OblivionBSAInvalidation(const std::shared_ptr &dataArchives, MOBase::IOrganizer *moInfo); + +private: + + virtual QString invalidationBSAName() const override; + virtual unsigned long bsaVersion() const override; + +}; + +#endif // OBLIVIONBSAINVALIDATION_H diff --git a/src/games/oblivion/src/obliviondataarchives.cpp b/src/games/oblivion/src/obliviondataarchives.cpp new file mode 100644 index 00000000..7a177429 --- /dev/null +++ b/src/games/oblivion/src/obliviondataarchives.cpp @@ -0,0 +1,41 @@ +#include "obliviondataarchives.h" +#include +#include + + +QStringList OblivionDataArchives::vanillaArchives() const +{ + return { "Oblivion - Misc.bsa" + , "Oblivion - Textures - Compressed.bsa" + , "Oblivion - Meshes.bsa" + , "Oblivion - Sounds.bsa" + , "Oblivion - Voices1.bsa" + , "Oblivion - Voices2.bsa" + }; +} + + +QStringList OblivionDataArchives::archives(const MOBase::IProfile *profile) const +{ + QStringList result; + + QString iniFile = QDir(profile->absolutePath()).absoluteFilePath("oblivion.ini"); + result.append(getArchivesFromKey(iniFile, "SResourceArchiveList")); + result.append(getArchivesFromKey(iniFile, "SResourceArchiveList2")); + + return result; +} + +void OblivionDataArchives::writeArchiveList(MOBase::IProfile *profile, QStringList before) +{ + QString list = before.join(','); + + QString iniFile = QDir(profile->absolutePath()).absoluteFilePath("oblivion.ini"); + if (list.length() > 255) { + int splitIdx = list.lastIndexOf(",", 256); + setArchivesToKey(iniFile, "SResourceArchiveList", list.mid(0, splitIdx)); + setArchivesToKey(iniFile, "SResourceArchiveList2", list.mid(splitIdx + 1)); + } else { + setArchivesToKey(iniFile, "SResourceArchiveList", list); + } +} diff --git a/src/games/oblivion/src/obliviondataarchives.h b/src/games/oblivion/src/obliviondataarchives.h new file mode 100644 index 00000000..82e8424f --- /dev/null +++ b/src/games/oblivion/src/obliviondataarchives.h @@ -0,0 +1,24 @@ +#ifndef OBLIVIONDATAARCHIVES_H +#define OBLIVIONDATAARCHIVES_H + + +#include +#include +#include +#include + +class OblivionDataArchives : public GamebryoDataArchives +{ + +public: + + virtual QStringList vanillaArchives() const override; + virtual QStringList archives(const MOBase::IProfile *profile) const override; + +private: + + virtual void writeArchiveList(MOBase::IProfile *profile, QStringList before) override; + +}; + +#endif // OBLIVIONDATAARCHIVES_H diff --git a/src/games/oblivion/src/oblivionscriptextender.cpp b/src/games/oblivion/src/oblivionscriptextender.cpp new file mode 100644 index 00000000..452ddc51 --- /dev/null +++ b/src/games/oblivion/src/oblivionscriptextender.cpp @@ -0,0 +1,7 @@ +#include "oblivionscriptextender.h" + + +QString OblivionScriptExtender::name() const +{ + return "obse"; +} diff --git a/src/games/oblivion/src/oblivionscriptextender.h b/src/games/oblivion/src/oblivionscriptextender.h new file mode 100644 index 00000000..f0cb5843 --- /dev/null +++ b/src/games/oblivion/src/oblivionscriptextender.h @@ -0,0 +1,14 @@ +#ifndef OBLIVIONSCRIPTEXTENDER_H +#define OBLIVIONSCRIPTEXTENDER_H + + +#include + + +class OblivionScriptExtender : public ScriptExtender +{ +public: + virtual QString name() const override; +}; + +#endif // OBLIVIONSCRIPTEXTENDER_H From 9a0696b1f22622c06423c7938c0ef1301ff4f3d4 Mon Sep 17 00:00:00 2001 From: Tom Tanner Date: Sun, 22 Mar 2015 10:49:15 +0000 Subject: [PATCH 0012/1544] [game_skyrim] Fix a meory leak with modules that error during loading More Sconscript stuff --- src/games/skyrim/src/gameSkyrim.pro | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/src/games/skyrim/src/gameSkyrim.pro b/src/games/skyrim/src/gameSkyrim.pro index 74ca971b..ea977820 100644 --- a/src/games/skyrim/src/gameSkyrim.pro +++ b/src/games/skyrim/src/gameSkyrim.pro @@ -39,4 +39,5 @@ INCLUDEPATH += "$${BOOSTPATH}" "$${PWD}/../gamefeatures" "$${PWD}/../gamegamebry LIBS += -ladvapi32 -lole32 -lgameGamebryo OTHER_FILES += \ - gameskyrim.json + gameskyrim.json\ + SConscript From 2e79bc2b38873d9caee1fa98e346734ab0e11860 Mon Sep 17 00:00:00 2001 From: Tom Tanner Date: Sun, 22 Mar 2015 10:49:15 +0000 Subject: [PATCH 0013/1544] Fix a meory leak with modules that error during loading More Sconscript stuff --- src/gameGamebryo.pro | 3 +++ 1 file changed, 3 insertions(+) diff --git a/src/gameGamebryo.pro b/src/gameGamebryo.pro index 1873ffde..2be6f8ab 100644 --- a/src/gameGamebryo.pro +++ b/src/gameGamebryo.pro @@ -21,3 +21,6 @@ HEADERS += gamegamebryo.h \ include(../plugin_template.pri) INCLUDEPATH += "$${BOOSTPATH}" "$${PWD}/../gamefeatures" + +OTHER_FILES +=\ + SConscript From 82a5573a5d53a7ae721cf003156bdf8d05241719 Mon Sep 17 00:00:00 2001 From: Tom Tanner Date: Sun, 22 Mar 2015 10:49:29 +0000 Subject: [PATCH 0014/1544] [game_skyrim] More new scons files --- src/games/skyrim/src/SConscript | 36 +++++++++++++++++++++++++++++++++ 1 file changed, 36 insertions(+) create mode 100644 src/games/skyrim/src/SConscript diff --git a/src/games/skyrim/src/SConscript b/src/games/skyrim/src/SConscript new file mode 100644 index 00000000..4c99411c --- /dev/null +++ b/src/games/skyrim/src/SConscript @@ -0,0 +1,36 @@ +import os + +Import('qt_env') + +env = qt_env.Clone() + +env.AppendUnique(CPPDEFINES = [ 'GAMESKYRIM_LIBRARY' ]) + +env.AppendUnique(CPPPATH = [ + os.path.join('..', 'gameGamebryo'), + os.path.join('..', 'gamefeatures'), + '${BOOSTPATH}' +]) + +env.AppendUnique(LIBPATH = '../gameGamebryo') + +env.AppendUnique(LIBS = [ + 'gameGamebryo', + 'advapi32', + 'ole32', + 'shell32' +]) + +lib = env.SharedLibrary('gameSkyrim', env.Glob('*.cpp')) +env.InstallModule(lib) + +res = env['QT_USED_MODULES'] +Return('res') + +""" + +LIBS += -ladvapi32 -lole32 -lgameGamebryo + +OTHER_FILES += \ + gameskyrim.json\ +""" From 6d42e1820ae44256aec314a08c9a01dc4b0006f3 Mon Sep 17 00:00:00 2001 From: Tom Tanner Date: Sun, 22 Mar 2015 10:49:29 +0000 Subject: [PATCH 0015/1544] More new scons files --- src/SConscript | 15 +++++++++++++++ 1 file changed, 15 insertions(+) create mode 100644 src/SConscript diff --git a/src/SConscript b/src/SConscript new file mode 100644 index 00000000..3b96d894 --- /dev/null +++ b/src/SConscript @@ -0,0 +1,15 @@ +import os + +Import('qt_env') + +env = qt_env.Clone() + +env.AppendUnique(CPPPATH = [ + os.path.join('..', 'gamefeatures'), + '${BOOSTPATH}' +]) + +env.StaticLibrary('gameGamebryo', env.Glob('*.cpp')) + +res = env['QT_USED_MODULES'] +Return('res') From 27063f7f567fe7a7fd68b158097e2a49ac6b7ec1 Mon Sep 17 00:00:00 2001 From: Tom Tanner Date: Wed, 25 Mar 2015 22:35:53 +0000 Subject: [PATCH 0016/1544] [game_skyrim] Add in all the necessary stuff for scons --- src/games/skyrim/src/SConscript | 25 +------------------------ 1 file changed, 1 insertion(+), 24 deletions(-) diff --git a/src/games/skyrim/src/SConscript b/src/games/skyrim/src/SConscript index 4c99411c..3382d84b 100644 --- a/src/games/skyrim/src/SConscript +++ b/src/games/skyrim/src/SConscript @@ -1,36 +1,13 @@ -import os - Import('qt_env') env = qt_env.Clone() env.AppendUnique(CPPDEFINES = [ 'GAMESKYRIM_LIBRARY' ]) -env.AppendUnique(CPPPATH = [ - os.path.join('..', 'gameGamebryo'), - os.path.join('..', 'gamefeatures'), - '${BOOSTPATH}' -]) - -env.AppendUnique(LIBPATH = '../gameGamebryo') - -env.AppendUnique(LIBS = [ - 'gameGamebryo', - 'advapi32', - 'ole32', - 'shell32' -]) +env.RequiresGamebryo() lib = env.SharedLibrary('gameSkyrim', env.Glob('*.cpp')) env.InstallModule(lib) res = env['QT_USED_MODULES'] Return('res') - -""" - -LIBS += -ladvapi32 -lole32 -lgameGamebryo - -OTHER_FILES += \ - gameskyrim.json\ -""" From f24afe4114242f54d5f476d09cfe6cb5b54ac9e2 Mon Sep 17 00:00:00 2001 From: Tom Tanner Date: Wed, 25 Mar 2015 22:35:53 +0000 Subject: [PATCH 0017/1544] [game_fallout3] Add in all the necessary stuff for scons --- src/games/fallout3/src/SConscript | 14 ++++++++++++++ src/games/fallout3/src/gameFallout3.pro | 3 ++- 2 files changed, 16 insertions(+), 1 deletion(-) create mode 100644 src/games/fallout3/src/SConscript diff --git a/src/games/fallout3/src/SConscript b/src/games/fallout3/src/SConscript new file mode 100644 index 00000000..721e3592 --- /dev/null +++ b/src/games/fallout3/src/SConscript @@ -0,0 +1,14 @@ +Import('qt_env') + +env = qt_env.Clone() + +# Shouldn't this be GAMEFALLOUT3_LIBRARY +env.AppendUnique(CPPDEFINES = [ 'GAMEFALLOUTNV_LIBRARY' ]) + +env.RequiresGamebryo() + +lib = env.SharedLibrary('gameFallout3', env.Glob('*.cpp')) +env.InstallModule(lib) + +res = env['QT_USED_MODULES'] +Return('res') diff --git a/src/games/fallout3/src/gameFallout3.pro b/src/games/fallout3/src/gameFallout3.pro index d958ca1b..ee65d092 100644 --- a/src/games/fallout3/src/gameFallout3.pro +++ b/src/games/fallout3/src/gameFallout3.pro @@ -40,4 +40,5 @@ INCLUDEPATH += "$${BOOSTPATH}" "$${PWD}/../gamefeatures" "$${PWD}/../gamegamebry LIBS += -ladvapi32 -lole32 -lgameGamebryo OTHER_FILES += \ - gamefallout3.json + gamefallout3.json\ + SConscript From 48b944b2d897f2a08a675c84104927da0c673e04 Mon Sep 17 00:00:00 2001 From: Tom Tanner Date: Wed, 25 Mar 2015 22:35:53 +0000 Subject: [PATCH 0018/1544] [game_oblivion] Add in all the necessary stuff for scons --- src/games/oblivion/src/SConscript | 13 +++++++++++++ src/games/oblivion/src/gameOblivion.pro | 3 ++- 2 files changed, 15 insertions(+), 1 deletion(-) create mode 100644 src/games/oblivion/src/SConscript diff --git a/src/games/oblivion/src/SConscript b/src/games/oblivion/src/SConscript new file mode 100644 index 00000000..d88941be --- /dev/null +++ b/src/games/oblivion/src/SConscript @@ -0,0 +1,13 @@ +Import('qt_env') + +env = qt_env.Clone() + +env.AppendUnique(CPPDEFINES = [ 'GAMEOBLIVION_LIBRARY' ]) + +env.RequiresGamebryo() + +lib = env.SharedLibrary('gameOblivion', env.Glob('*.cpp')) +env.InstallModule(lib) + +res = env['QT_USED_MODULES'] +Return('res') diff --git a/src/games/oblivion/src/gameOblivion.pro b/src/games/oblivion/src/gameOblivion.pro index f089b124..16b1836f 100644 --- a/src/games/oblivion/src/gameOblivion.pro +++ b/src/games/oblivion/src/gameOblivion.pro @@ -40,4 +40,5 @@ INCLUDEPATH += "$${BOOSTPATH}" "$${PWD}/../gamefeatures" "$${PWD}/../gamegamebry LIBS += -ladvapi32 -lole32 -lgameGamebryo OTHER_FILES += \ - gameoblivion.json + gameoblivion.json\ + SConscript From b705f5cb14ecb057c725bb7aa87144ce0dc3e22f Mon Sep 17 00:00:00 2001 From: Tom Tanner Date: Wed, 25 Mar 2015 22:35:53 +0000 Subject: [PATCH 0019/1544] [game_falloutnv] Add in all the necessary stuff for scons --- src/games/falloutnv/src/SConscript | 13 +++++++++++++ src/games/falloutnv/src/gameFalloutNV.pro | 3 ++- 2 files changed, 15 insertions(+), 1 deletion(-) create mode 100644 src/games/falloutnv/src/SConscript diff --git a/src/games/falloutnv/src/SConscript b/src/games/falloutnv/src/SConscript new file mode 100644 index 00000000..998dca40 --- /dev/null +++ b/src/games/falloutnv/src/SConscript @@ -0,0 +1,13 @@ +Import('qt_env') + +env = qt_env.Clone() + +env.AppendUnique(CPPDEFINES = [ 'GAMEFALLOUTNV_LIBRARY' ]) + +env.RequiresGamebryo() + +lib = env.SharedLibrary('gameFalloutNV', env.Glob('*.cpp')) +env.InstallModule(lib) + +res = env['QT_USED_MODULES'] +Return('res') diff --git a/src/games/falloutnv/src/gameFalloutNV.pro b/src/games/falloutnv/src/gameFalloutNV.pro index 992282ae..9790ca4f 100644 --- a/src/games/falloutnv/src/gameFalloutNV.pro +++ b/src/games/falloutnv/src/gameFalloutNV.pro @@ -40,4 +40,5 @@ INCLUDEPATH += "$${BOOSTPATH}" "$${PWD}/../gamefeatures" "$${PWD}/../gamegamebry LIBS += -ladvapi32 -lole32 -lgameGamebryo OTHER_FILES += \ - gamefalloutnv.json + gamefalloutnv.json\ + SConscript From a5ce3831c1081783de06c9d0a9ea737792a029bc Mon Sep 17 00:00:00 2001 From: Tannin Date: Tue, 31 Mar 2015 18:34:23 +0200 Subject: [PATCH 0020/1544] bsa invalidation will now try to make ini file writable before writing to them --- src/gamebryobsainvalidation.cpp | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/src/gamebryobsainvalidation.cpp b/src/gamebryobsainvalidation.cpp index 515948e3..7233933b 100644 --- a/src/gamebryobsainvalidation.cpp +++ b/src/gamebryobsainvalidation.cpp @@ -40,6 +40,8 @@ void GamebryoBSAInvalidation::deactivate(MOBase::IProfile *profile) QString iniFile = QDir(profile->absolutePath()).absoluteFilePath(m_IniFileName); + ::SetFileAttributesW(iniFile.toStdWString().c_str(), FILE_ATTRIBUTE_NORMAL); + if (!::WritePrivateProfileStringW(L"Archive", L"bInvalidateOlderFiles", L"0", iniFile.toStdWString().c_str()) || !::WritePrivateProfileStringW(L"Archive", L"SInvalidationFile", L"ArchiveInvalidation.txt", iniFile.toStdWString().c_str())) { throw MOBase::MyException(QObject::tr("failed to deactivate BSA invalidation in \"%1\" (errorcode %2)").arg(iniFile, ::GetLastError())); @@ -71,6 +73,8 @@ void GamebryoBSAInvalidation::activate(MOBase::IProfile *profile) // set the remaining ini settings required QString iniFile = QDir(profile->absolutePath()).absoluteFilePath(m_IniFileName); + ::SetFileAttributesW(iniFile.toStdWString().c_str(), FILE_ATTRIBUTE_NORMAL); + if (!::WritePrivateProfileStringW(L"Archive", L"bInvalidateOlderFiles", L"1", iniFile.toStdWString().c_str()) || !::WritePrivateProfileStringW(L"Archive", L"SInvalidationFile", L"", iniFile.toStdWString().c_str())) { throw MOBase::MyException(QObject::tr("failed to activate BSA invalidation in \"%1\" (errorcode %2)").arg(iniFile, ::GetLastError())); From acfec1792c22c1cb5e2c553ec1e5aa63fb73c47f Mon Sep 17 00:00:00 2001 From: Tannin Date: Sun, 12 Apr 2015 15:42:45 +0200 Subject: [PATCH 0021/1544] missing changes that belong into changeset 9e73493a3706 --- src/gamegamebryo.cpp | 6 ++++++ src/gamegamebryo.h | 1 + 2 files changed, 7 insertions(+) diff --git a/src/gamegamebryo.cpp b/src/gamegamebryo.cpp index dca670fa..f362fcdc 100644 --- a/src/gamegamebryo.cpp +++ b/src/gamegamebryo.cpp @@ -1,6 +1,7 @@ #include "gamegamebryo.h" #include #include +#include GameGamebryo::GameGamebryo() @@ -20,6 +21,11 @@ QDir GameGamebryo::gameDirectory() const return QDir(m_GamePath); } +void GameGamebryo::setGamePath(const QString &path) +{ + m_GamePath = path; +} + QDir GameGamebryo::savesDirectory() const { return QDir(m_MyGamesPath + "/Saves"); diff --git a/src/gamegamebryo.h b/src/gamegamebryo.h index 81a4fb16..1c1e936d 100644 --- a/src/gamegamebryo.h +++ b/src/gamegamebryo.h @@ -21,6 +21,7 @@ public: public: // IPluginGame interface virtual QDir gameDirectory() const; + virtual void setGamePath(const QString &path); virtual QDir savesDirectory() const; virtual QDir documentsDirectory() const; From 28f4d7f7ebc7e4511d6dd6a151854c7ff7f9d1b7 Mon Sep 17 00:00:00 2001 From: Tannin Date: Sun, 12 Apr 2015 15:54:14 +0200 Subject: [PATCH 0022/1544] [game_fallout3] refactorings --- src/games/fallout3/src/gamefallout3.cpp | 1 + 1 file changed, 1 insertion(+) diff --git a/src/games/fallout3/src/gamefallout3.cpp b/src/games/fallout3/src/gamefallout3.cpp index 37931da4..3241624d 100644 --- a/src/games/fallout3/src/gamefallout3.cpp +++ b/src/games/fallout3/src/gamefallout3.cpp @@ -6,6 +6,7 @@ #include #include #include +#include using namespace MOBase; From f988e54fd57526ec31504e7b6c112f545df8806c Mon Sep 17 00:00:00 2001 From: Tom Tanner Date: Wed, 29 Apr 2015 20:45:32 +0100 Subject: [PATCH 0023/1544] [game_skyrim] Fix for bug 1116 --- src/games/skyrim/src/gameskyrim.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/games/skyrim/src/gameskyrim.cpp b/src/games/skyrim/src/gameskyrim.cpp index 2633c77c..097e9bac 100644 --- a/src/games/skyrim/src/gameskyrim.cpp +++ b/src/games/skyrim/src/gameskyrim.cpp @@ -79,7 +79,7 @@ QString GameSkyrim::author() const QString GameSkyrim::description() const { - return tr("Adds support for the game Sykrim"); + return tr("Adds support for the game Skyrim"); } MOBase::VersionInfo GameSkyrim::version() const From 2b0107e1c0a2098ab708bad1a82e18f0b586dc9b Mon Sep 17 00:00:00 2001 From: Tom Tanner Date: Sat, 9 May 2015 18:06:27 +0100 Subject: [PATCH 0024/1544] Fixed detection of loot as the registry key doesn't include the executable (at least not on 0.6.1). Refactored to save having to change in 4 places in the future --- src/gamegamebryo.cpp | 5 +++++ src/gamegamebryo.h | 2 ++ 2 files changed, 7 insertions(+) diff --git a/src/gamegamebryo.cpp b/src/gamegamebryo.cpp index dca670fa..c2e685fb 100644 --- a/src/gamegamebryo.cpp +++ b/src/gamegamebryo.cpp @@ -122,3 +122,8 @@ QString GameGamebryo::myGamesPath() const { return m_MyGamesPath; } + +QString GameGamebryo::getLootPath() const +{ + return findInRegistry(HKEY_LOCAL_MACHINE, L"Software\\LOOT", L"Installed Path") + "/Loot.exe"; +} diff --git a/src/gamegamebryo.h b/src/gamegamebryo.h index 81a4fb16..cca41555 100644 --- a/src/gamegamebryo.h +++ b/src/gamegamebryo.h @@ -34,6 +34,8 @@ protected: QString getKnownFolderPath(REFKNOWNFOLDERID folderId, bool useDefault) const; QString getSpecialPath(const QString &name) const; QString myGamesPath() const; + //Arguably this shouldn't really be here but every gamebryo program seems to use it + QString GameGamebryo::getLootPath() const; private: From 849f5a3fbb91d3c6c5bed7177b8d6606b6cf0bad Mon Sep 17 00:00:00 2001 From: Tom Tanner Date: Sat, 9 May 2015 18:06:27 +0100 Subject: [PATCH 0025/1544] [game_fallout3] Fixed detection of loot as the registry key doesn't include the executable (at least not on 0.6.1). Refactored to save having to change in 4 places in the future --- src/games/fallout3/src/gamefallout3.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/games/fallout3/src/gamefallout3.cpp b/src/games/fallout3/src/gamefallout3.cpp index 37931da4..65348628 100644 --- a/src/games/fallout3/src/gamefallout3.cpp +++ b/src/games/fallout3/src/gamefallout3.cpp @@ -61,7 +61,7 @@ QList GameFallout3::executables() << ExecutableInfo("Construction Kit", findInGameFolder("geck.exe")) << ExecutableInfo("Fallout Launcher", findInGameFolder("Fallout3Launcher.exe")) << ExecutableInfo("BOSS", findInGameFolder("BOSS/BOSS.exe")) - << ExecutableInfo("LOOT", findInRegistry(HKEY_LOCAL_MACHINE, L"Software\\LOOT", L"Installed Path")) + << ExecutableInfo("LOOT", getLootPath()); ; } From 422e1540d7aabb0a4fda8ed3ca1bdf8553c0b9ad Mon Sep 17 00:00:00 2001 From: Tom Tanner Date: Sat, 9 May 2015 18:06:27 +0100 Subject: [PATCH 0026/1544] [game_oblivion] Fixed detection of loot as the registry key doesn't include the executable (at least not on 0.6.1). Refactored to save having to change in 4 places in the future --- src/games/oblivion/src/gameoblivion.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/games/oblivion/src/gameoblivion.cpp b/src/games/oblivion/src/gameoblivion.cpp index cc3d0d38..baba3e33 100644 --- a/src/games/oblivion/src/gameoblivion.cpp +++ b/src/games/oblivion/src/gameoblivion.cpp @@ -62,7 +62,7 @@ QList GameOblivion::executables() << ExecutableInfo("Oblivion Launcher", findInGameFolder("OblivionLauncher.exe")) << ExecutableInfo("Oblivion Mod Manager", findInGameFolder("OblivionModManager.exe")) << ExecutableInfo("BOSS", findInGameFolder("BOSS/BOSS.exe")) - << ExecutableInfo("LOOT", findInRegistry(HKEY_LOCAL_MACHINE, L"Software\\LOOT", L"Installed Path")) + << ExecutableInfo("LOOT", getLootPath()) << ExecutableInfo("Construction Set", findInGameFolder("TESConstructionSet.exe")) ; } From 5507d0af23b2005b86f37801456211718072f0d0 Mon Sep 17 00:00:00 2001 From: Tom Tanner Date: Sat, 9 May 2015 18:06:27 +0100 Subject: [PATCH 0027/1544] [game_falloutnv] Fixed detection of loot as the registry key doesn't include the executable (at least not on 0.6.1). Refactored to save having to change in 4 places in the future --- src/games/falloutnv/src/gamefalloutnv.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/games/falloutnv/src/gamefalloutnv.cpp b/src/games/falloutnv/src/gamefalloutnv.cpp index 40c54ea6..9aeecff5 100644 --- a/src/games/falloutnv/src/gamefalloutnv.cpp +++ b/src/games/falloutnv/src/gamefalloutnv.cpp @@ -61,7 +61,7 @@ QList GameFalloutNV::executables() << ExecutableInfo("Construction Kit", findInGameFolder("geck.exe")) << ExecutableInfo("Fallout Launcher", findInGameFolder("FalloutNVLauncher.exe")) << ExecutableInfo("BOSS", findInGameFolder("BOSS/BOSS.exe")) - << ExecutableInfo("LOOT", findInRegistry(HKEY_LOCAL_MACHINE, L"Software\\LOOT", L"Installed Path")) + << ExecutableInfo("LOOT", getLootPath()) ; } From 4ec3a9e9b345c329b3cad71e5e263861436b4c59 Mon Sep 17 00:00:00 2001 From: Tom Tanner Date: Sat, 9 May 2015 18:06:27 +0100 Subject: [PATCH 0028/1544] [game_skyrim] Fixed detection of loot as the registry key doesn't include the executable (at least not on 0.6.1). Refactored to save having to change in 4 places in the future --- src/games/skyrim/src/gameskyrim.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/games/skyrim/src/gameskyrim.cpp b/src/games/skyrim/src/gameskyrim.cpp index 097e9bac..7c273262 100644 --- a/src/games/skyrim/src/gameskyrim.cpp +++ b/src/games/skyrim/src/gameskyrim.cpp @@ -62,7 +62,7 @@ QList GameSkyrim::executables() << ExecutableInfo("Skyrim", findInGameFolder("TESV.exe")) << ExecutableInfo("Skyrim Launcher", findInGameFolder("SkyrimLauncher.exe")) << ExecutableInfo("BOSS", findInGameFolder("BOSS/BOSS.exe")) - << ExecutableInfo("LOOT", findInRegistry(HKEY_LOCAL_MACHINE, L"Software\\LOOT", L"Installed Path")) + << ExecutableInfo("LOOT", getLootPath()) << ExecutableInfo("Creation Kit", findInGameFolder("CreationKit.exe")).withSteamAppId("202480") ; } From 8f0def12b6e3e7288855e02619548e57a28c800a Mon Sep 17 00:00:00 2001 From: Tannin Date: Mon, 11 May 2015 18:05:57 +0200 Subject: [PATCH 0029/1544] bugfix: archive invalidation wasn't correctly enabled/disabled --- src/gamebryobsainvalidation.cpp | 10 ++++++++-- src/gamebryodataarchives.cpp | 1 - src/gamebryodataarchives.h | 2 +- 3 files changed, 9 insertions(+), 4 deletions(-) diff --git a/src/gamebryobsainvalidation.cpp b/src/gamebryobsainvalidation.cpp index 7233933b..3ce436b7 100644 --- a/src/gamebryobsainvalidation.cpp +++ b/src/gamebryobsainvalidation.cpp @@ -3,6 +3,7 @@ #include #include #include +#include #include #include #include @@ -33,11 +34,16 @@ void GamebryoBSAInvalidation::deactivate(MOBase::IProfile *profile) { QStringList archivesBefore = m_DataArchives->archives(profile); for (const QString &archive : archivesBefore) { - if (!isInvalidationBSA(archive)) { + if (isInvalidationBSA(archive)) { m_DataArchives->removeArchive(profile, archive); } } + QString bsaFile = m_Organizer->gameInfo().path() + "/data/" + invalidationBSAName(); + if (QFile::exists(bsaFile)) { + MOBase::shellDeleteQuiet(bsaFile); + } + QString iniFile = QDir(profile->absolutePath()).absoluteFilePath(m_IniFileName); ::SetFileAttributesW(iniFile.toStdWString().c_str(), FILE_ATTRIBUTE_NORMAL); @@ -63,7 +69,7 @@ void GamebryoBSAInvalidation::activate(MOBase::IProfile *profile) m_DataArchives->addArchive(profile, 0, invalidationBSAName()); // create the dummy bsa if necessary - QString bsaFile = m_Organizer->gameInfo().path() + "/" + invalidationBSAName(); + QString bsaFile = m_Organizer->gameInfo().path() + "/data/" + invalidationBSAName(); if (!QFile::exists(bsaFile)) { DummyBSA bsa(bsaVersion()); bsa.write(bsaFile); diff --git a/src/gamebryodataarchives.cpp b/src/gamebryodataarchives.cpp index 7a8862bf..912d7df7 100644 --- a/src/gamebryodataarchives.cpp +++ b/src/gamebryodataarchives.cpp @@ -50,7 +50,6 @@ void GamebryoDataArchives::removeArchive(MOBase::IProfile *profile, const QStrin if (!current.contains(archiveName, Qt::CaseInsensitive)) { return; } - current.removeAll(archiveName); writeArchiveList(profile, current); diff --git a/src/gamebryodataarchives.h b/src/gamebryodataarchives.h index f9436dda..a720afa0 100644 --- a/src/gamebryodataarchives.h +++ b/src/gamebryodataarchives.h @@ -20,7 +20,7 @@ protected: private: - virtual void writeArchiveList(MOBase::IProfile *profile, QStringList before) = 0; + virtual void writeArchiveList(MOBase::IProfile *profile, const QStringList &before) = 0; }; From ff807443b465bf050ef91ddf0acb87927296696f Mon Sep 17 00:00:00 2001 From: Tannin Date: Mon, 11 May 2015 18:05:57 +0200 Subject: [PATCH 0030/1544] [game_fallout3] bugfix: archive invalidation wasn't correctly enabled/disabled --- src/games/fallout3/src/fallout3dataarchives.cpp | 4 ++-- src/games/fallout3/src/fallout3dataarchives.h | 2 +- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/src/games/fallout3/src/fallout3dataarchives.cpp b/src/games/fallout3/src/fallout3dataarchives.cpp index 3ee8a603..bc3dd4a2 100644 --- a/src/games/fallout3/src/fallout3dataarchives.cpp +++ b/src/games/fallout3/src/fallout3dataarchives.cpp @@ -24,9 +24,9 @@ QStringList Fallout3DataArchives::archives(const MOBase::IProfile *profile) cons return result; } -void Fallout3DataArchives::writeArchiveList(MOBase::IProfile *profile, QStringList before) +void Fallout3DataArchives::writeArchiveList(MOBase::IProfile *profile, const QStringList &before) { - QString list = before.join(','); + QString list = before.join(", "); QString iniFile = QDir(profile->absolutePath()).absoluteFilePath("fallout3.ini"); setArchivesToKey(iniFile, "SArchiveList", list); diff --git a/src/games/fallout3/src/fallout3dataarchives.h b/src/games/fallout3/src/fallout3dataarchives.h index df9fba46..47e022b5 100644 --- a/src/games/fallout3/src/fallout3dataarchives.h +++ b/src/games/fallout3/src/fallout3dataarchives.h @@ -17,7 +17,7 @@ public: private: - virtual void writeArchiveList(MOBase::IProfile *profile, QStringList before) override; + virtual void writeArchiveList(MOBase::IProfile *profile, const QStringList &before) override; }; From 54774c6b87aa45e4236dee4ef0e335072e76d296 Mon Sep 17 00:00:00 2001 From: Tannin Date: Mon, 11 May 2015 18:05:57 +0200 Subject: [PATCH 0031/1544] [game_oblivion] bugfix: archive invalidation wasn't correctly enabled/disabled --- src/games/oblivion/src/obliviondataarchives.cpp | 6 +++--- src/games/oblivion/src/obliviondataarchives.h | 2 +- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/src/games/oblivion/src/obliviondataarchives.cpp b/src/games/oblivion/src/obliviondataarchives.cpp index 7a177429..db55642b 100644 --- a/src/games/oblivion/src/obliviondataarchives.cpp +++ b/src/games/oblivion/src/obliviondataarchives.cpp @@ -26,15 +26,15 @@ QStringList OblivionDataArchives::archives(const MOBase::IProfile *profile) cons return result; } -void OblivionDataArchives::writeArchiveList(MOBase::IProfile *profile, QStringList before) +void OblivionDataArchives::writeArchiveList(MOBase::IProfile *profile, const QStringList &before) { - QString list = before.join(','); + QString list = before.join(", "); QString iniFile = QDir(profile->absolutePath()).absoluteFilePath("oblivion.ini"); if (list.length() > 255) { int splitIdx = list.lastIndexOf(",", 256); setArchivesToKey(iniFile, "SResourceArchiveList", list.mid(0, splitIdx)); - setArchivesToKey(iniFile, "SResourceArchiveList2", list.mid(splitIdx + 1)); + setArchivesToKey(iniFile, "SResourceArchiveList2", list.mid(splitIdx + 2)); } else { setArchivesToKey(iniFile, "SResourceArchiveList", list); } diff --git a/src/games/oblivion/src/obliviondataarchives.h b/src/games/oblivion/src/obliviondataarchives.h index 82e8424f..c2703f8c 100644 --- a/src/games/oblivion/src/obliviondataarchives.h +++ b/src/games/oblivion/src/obliviondataarchives.h @@ -17,7 +17,7 @@ public: private: - virtual void writeArchiveList(MOBase::IProfile *profile, QStringList before) override; + virtual void writeArchiveList(MOBase::IProfile *profile, const QStringList &before) override; }; From f08920d16ab3d2c7dc38c52f6ae5f75df93ceef1 Mon Sep 17 00:00:00 2001 From: Tannin Date: Mon, 11 May 2015 18:05:57 +0200 Subject: [PATCH 0032/1544] [game_falloutnv] bugfix: archive invalidation wasn't correctly enabled/disabled --- src/games/falloutnv/src/falloutnvdataarchives.cpp | 4 ++-- src/games/falloutnv/src/falloutnvdataarchives.h | 2 +- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/src/games/falloutnv/src/falloutnvdataarchives.cpp b/src/games/falloutnv/src/falloutnvdataarchives.cpp index ad22822b..237a15f6 100644 --- a/src/games/falloutnv/src/falloutnvdataarchives.cpp +++ b/src/games/falloutnv/src/falloutnvdataarchives.cpp @@ -24,9 +24,9 @@ QStringList FalloutNVDataArchives::archives(const MOBase::IProfile *profile) con return result; } -void FalloutNVDataArchives::writeArchiveList(MOBase::IProfile *profile, QStringList before) +void FalloutNVDataArchives::writeArchiveList(MOBase::IProfile *profile, const QStringList &before) { - QString list = before.join(','); + QString list = before.join(", "); QString iniFile = QDir(profile->absolutePath()).absoluteFilePath("falloutnv.ini"); setArchivesToKey(iniFile, "SArchiveList", list); diff --git a/src/games/falloutnv/src/falloutnvdataarchives.h b/src/games/falloutnv/src/falloutnvdataarchives.h index 67728b74..931d3120 100644 --- a/src/games/falloutnv/src/falloutnvdataarchives.h +++ b/src/games/falloutnv/src/falloutnvdataarchives.h @@ -17,7 +17,7 @@ public: private: - virtual void writeArchiveList(MOBase::IProfile *profile, QStringList before) override; + virtual void writeArchiveList(MOBase::IProfile *profile, const QStringList &before) override; }; From 1f36e26b1e1a9408f1d9e66b8c93598ed45f943a Mon Sep 17 00:00:00 2001 From: Tannin Date: Mon, 11 May 2015 18:05:57 +0200 Subject: [PATCH 0033/1544] [game_skyrim] bugfix: archive invalidation wasn't correctly enabled/disabled --- src/games/skyrim/src/skyrimdataarchives.cpp | 6 +++--- src/games/skyrim/src/skyrimdataarchives.h | 2 +- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/src/games/skyrim/src/skyrimdataarchives.cpp b/src/games/skyrim/src/skyrimdataarchives.cpp index f259978f..e4c39c2e 100644 --- a/src/games/skyrim/src/skyrimdataarchives.cpp +++ b/src/games/skyrim/src/skyrimdataarchives.cpp @@ -31,15 +31,15 @@ QStringList SkyrimDataArchives::archives(const MOBase::IProfile *profile) const return result; } -void SkyrimDataArchives::writeArchiveList(MOBase::IProfile *profile, QStringList before) +void SkyrimDataArchives::writeArchiveList(MOBase::IProfile *profile, const QStringList &before) { - QString list = before.join(','); + QString list = before.join(", "); QString iniFile = QDir(profile->absolutePath()).absoluteFilePath("skyrim.ini"); if (list.length() > 255) { int splitIdx = list.lastIndexOf(",", 256); setArchivesToKey(iniFile, "SResourceArchiveList", list.mid(0, splitIdx)); - setArchivesToKey(iniFile, "SResourceArchiveList2", list.mid(splitIdx + 1)); + setArchivesToKey(iniFile, "SResourceArchiveList2", list.mid(splitIdx + 2)); } else { setArchivesToKey(iniFile, "SResourceArchiveList", list); } diff --git a/src/games/skyrim/src/skyrimdataarchives.h b/src/games/skyrim/src/skyrimdataarchives.h index 277c2b0b..8c532a4c 100644 --- a/src/games/skyrim/src/skyrimdataarchives.h +++ b/src/games/skyrim/src/skyrimdataarchives.h @@ -17,7 +17,7 @@ public: private: - virtual void writeArchiveList(MOBase::IProfile *profile, QStringList before) override; + virtual void writeArchiveList(MOBase::IProfile *profile, const QStringList &before) override; }; From c712ea3318700ba66c4fe19db6bba23cbfcedc12 Mon Sep 17 00:00:00 2001 From: Tannin Date: Tue, 7 Jul 2015 20:52:46 +0200 Subject: [PATCH 0034/1544] bugfix: invalidation bsa wasn't created when switching to a profile that needed it invalidation bsa is now always placed as the first bsa --- src/gamebryobsainvalidation.cpp | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/src/gamebryobsainvalidation.cpp b/src/gamebryobsainvalidation.cpp index 3ce436b7..dd7b1b02 100644 --- a/src/gamebryobsainvalidation.cpp +++ b/src/gamebryobsainvalidation.cpp @@ -67,13 +67,13 @@ void GamebryoBSAInvalidation::activate(MOBase::IProfile *profile) } if (!bsaInstalled) { m_DataArchives->addArchive(profile, 0, invalidationBSAName()); + } - // create the dummy bsa if necessary - QString bsaFile = m_Organizer->gameInfo().path() + "/data/" + invalidationBSAName(); - if (!QFile::exists(bsaFile)) { - DummyBSA bsa(bsaVersion()); - bsa.write(bsaFile); - } + // create the dummy bsa if necessary + QString bsaFile = m_Organizer->gameInfo().path() + "/data/" + invalidationBSAName(); + if (!QFile::exists(bsaFile)) { + DummyBSA bsa(bsaVersion()); + bsa.write(bsaFile); } // set the remaining ini settings required From 958cd38fca7b1067cf9e07bb9f9c4873b1f8c260 Mon Sep 17 00:00:00 2001 From: Tannin Date: Sun, 9 Aug 2015 13:04:01 +0200 Subject: [PATCH 0035/1544] added some (currently unused) functionality to dump the list of file mappings from real to virtual location --- src/gamegamebryo.cpp | 5 +++++ src/gamegamebryo.h | 1 + 2 files changed, 6 insertions(+) diff --git a/src/gamegamebryo.cpp b/src/gamegamebryo.cpp index d2faa660..122c5ec7 100644 --- a/src/gamegamebryo.cpp +++ b/src/gamegamebryo.cpp @@ -21,6 +21,11 @@ QDir GameGamebryo::gameDirectory() const return QDir(m_GamePath); } +QDir GameGamebryo::dataDirectory() const +{ + return gameDirectory().absoluteFilePath("data"); +} + void GameGamebryo::setGamePath(const QString &path) { m_GamePath = path; diff --git a/src/gamegamebryo.h b/src/gamegamebryo.h index 8c4277f2..9a19d6e5 100644 --- a/src/gamegamebryo.h +++ b/src/gamegamebryo.h @@ -21,6 +21,7 @@ public: public: // IPluginGame interface virtual QDir gameDirectory() const; + virtual QDir dataDirectory() const; virtual void setGamePath(const QString &path); virtual QDir savesDirectory() const; virtual QDir documentsDirectory() const; From 84c06f4668386695f52ac7c7634e26de5aead0fb Mon Sep 17 00:00:00 2001 From: Tannin Date: Mon, 17 Aug 2015 20:50:47 +0200 Subject: [PATCH 0036/1544] [game_fallout3] bugfix: wrong app ids used for oblivion and fallout 3 rewrote handling of different game variants: now resides in game plugin and works --- src/games/fallout3/src/gamefallout3.cpp | 14 +++++++++++--- src/games/fallout3/src/gamefallout3.h | 1 + 2 files changed, 12 insertions(+), 3 deletions(-) diff --git a/src/games/fallout3/src/gamefallout3.cpp b/src/games/fallout3/src/gamefallout3.cpp index b8612453..0e0584eb 100644 --- a/src/games/fallout3/src/gamefallout3.cpp +++ b/src/games/fallout3/src/gamefallout3.cpp @@ -96,8 +96,6 @@ QList GameFallout3::settings() const return QList(); } - - void GameFallout3::copyToProfile(const QString &sourcePath, const QDir &destinationDirectory, const QString &sourceFileName, const QString &destinationFileName) const { @@ -137,7 +135,11 @@ QString GameFallout3::savegameExtension() const QString GameFallout3::steamAPPId() const { - return "22380"; + if (selectedVariant() == "Game Of The Year") { + return "22370"; + } else { + return "22300"; + } } QStringList GameFallout3::getPrimaryPlugins() @@ -160,3 +162,9 @@ const std::map &GameFallout3::featureList() const return result; } + + +QStringList GameFallout3::gameVariants() const +{ + return { "Regular", "Game Of The Year" }; +} diff --git a/src/games/fallout3/src/gamefallout3.h b/src/games/fallout3/src/gamefallout3.h index 83512d01..8cd4ad23 100644 --- a/src/games/fallout3/src/gamefallout3.h +++ b/src/games/fallout3/src/gamefallout3.h @@ -31,6 +31,7 @@ public: // IPluginGame interface virtual QString steamAPPId() const; virtual QStringList getPrimaryPlugins(); virtual QIcon gameIcon() const override; + virtual QStringList gameVariants() const; public: // IPlugin interface From 9e200841ac8fbeac1cb3e18e4e64a994bc5347a1 Mon Sep 17 00:00:00 2001 From: Tannin Date: Mon, 17 Aug 2015 20:50:47 +0200 Subject: [PATCH 0037/1544] bugfix: wrong app ids used for oblivion and fallout 3 rewrote handling of different game variants: now resides in game plugin and works --- src/gamegamebryo.cpp | 16 ++++++++++++++++ src/gamegamebryo.h | 8 +++++++- 2 files changed, 23 insertions(+), 1 deletion(-) diff --git a/src/gamegamebryo.cpp b/src/gamegamebryo.cpp index 122c5ec7..18651f05 100644 --- a/src/gamegamebryo.cpp +++ b/src/gamegamebryo.cpp @@ -115,6 +115,11 @@ QString GameGamebryo::determineMyGamesPath(const QString &gameName) return result + "/My Games/" + gameName; } +QString GameGamebryo::selectedVariant() const +{ + return m_GameVariant; +} + QString GameGamebryo::getSpecialPath(const QString &name) const { QString base = findInRegistry(HKEY_CURRENT_USER, @@ -138,3 +143,14 @@ QString GameGamebryo::getLootPath() const { return findInRegistry(HKEY_LOCAL_MACHINE, L"Software\\LOOT", L"Installed Path") + "/Loot.exe"; } + + +QStringList GameGamebryo::gameVariants() const +{ + return QStringList(); +} + +void GameGamebryo::setGameVariant(const QString &variant) +{ + m_GameVariant = variant; +} diff --git a/src/gamegamebryo.h b/src/gamegamebryo.h index 9a19d6e5..e4d03e50 100644 --- a/src/gamegamebryo.h +++ b/src/gamegamebryo.h @@ -28,6 +28,9 @@ public: // IPluginGame interface virtual bool isInstalled() const override; + virtual QStringList gameVariants() const; + virtual void setGameVariant(const QString &variant); + protected: std::unique_ptr getRegValue(HKEY key, LPCWSTR subKey, LPCWSTR value, DWORD flags, LPDWORD type = nullptr) const; @@ -37,7 +40,8 @@ protected: QString getSpecialPath(const QString &name) const; QString myGamesPath() const; //Arguably this shouldn't really be here but every gamebryo program seems to use it - QString GameGamebryo::getLootPath() const; + QString getLootPath() const; + QString selectedVariant() const; private: @@ -51,6 +55,8 @@ private: QString m_GamePath; QString m_MyGamesPath; + QString m_GameVariant; + MOBase::IOrganizer *m_Organizer; }; From 11ce04c8a518bc360718d84ec2fb9868f00d5ab1 Mon Sep 17 00:00:00 2001 From: Tannin Date: Mon, 17 Aug 2015 20:50:47 +0200 Subject: [PATCH 0038/1544] [game_oblivion] bugfix: wrong app ids used for oblivion and fallout 3 rewrote handling of different game variants: now resides in game plugin and works --- src/games/oblivion/src/gameoblivion.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/games/oblivion/src/gameoblivion.cpp b/src/games/oblivion/src/gameoblivion.cpp index baba3e33..bfb25c63 100644 --- a/src/games/oblivion/src/gameoblivion.cpp +++ b/src/games/oblivion/src/gameoblivion.cpp @@ -138,7 +138,7 @@ QString GameOblivion::savegameExtension() const QString GameOblivion::steamAPPId() const { - return "72850"; + return "22330"; } QStringList GameOblivion::getPrimaryPlugins() From f993e710bb727e7ca86d1de60272d0a683da7aaa Mon Sep 17 00:00:00 2001 From: convert-repo Date: Mon, 7 Sep 2015 17:39:13 +0000 Subject: [PATCH 0039/1544] [game_fallout3] update tags From bec6ef1447647bee58e66a1f31a169ee19d4109f Mon Sep 17 00:00:00 2001 From: convert-repo Date: Mon, 7 Sep 2015 17:39:34 +0000 Subject: [PATCH 0040/1544] [game_falloutnv] update tags From 09137553603bec7c5642989947301d534e62d080 Mon Sep 17 00:00:00 2001 From: convert-repo Date: Mon, 7 Sep 2015 17:40:19 +0000 Subject: [PATCH 0041/1544] update tags From 0918aa619b5db2522dfff52b9c4c4dd24f1063be Mon Sep 17 00:00:00 2001 From: convert-repo Date: Mon, 7 Sep 2015 17:40:39 +0000 Subject: [PATCH 0042/1544] [game_oblivion] update tags From badd26e0d3766797f14143f865b2d6dd2b521c1f Mon Sep 17 00:00:00 2001 From: convert-repo Date: Mon, 7 Sep 2015 17:44:12 +0000 Subject: [PATCH 0043/1544] [game_skyrim] update tags From 17ecea64b95f663b7129dbf0d5d20a7cb57d01a8 Mon Sep 17 00:00:00 2001 From: Tannin Date: Thu, 24 Sep 2015 18:20:51 +0200 Subject: [PATCH 0044/1544] updated build system --- .gitignore | 2 ++ CMakeLists.txt | 14 ++++++++++++ src/CMakeLists.txt | 55 ++++++++++++++++++++++++++++++++++++++++++++++ 3 files changed, 71 insertions(+) create mode 100644 .gitignore create mode 100644 CMakeLists.txt create mode 100644 src/CMakeLists.txt diff --git a/.gitignore b/.gitignore new file mode 100644 index 00000000..2be5b91e --- /dev/null +++ b/.gitignore @@ -0,0 +1,2 @@ +std*.log +build diff --git a/CMakeLists.txt b/CMakeLists.txt new file mode 100644 index 00000000..0c6592ac --- /dev/null +++ b/CMakeLists.txt @@ -0,0 +1,14 @@ +CMAKE_MINIMUM_REQUIRED(VERSION 2.8) + +SET(DEPENDENCIES_DIR CACHE PATH "") + +# hint to find qt in dependencies path +FILE(GLOB_RECURSE QT5_FIND_MODULE ${DEPENDENCIES_DIR}/qt5.git/qtbase/bin/qmake.exe) +GET_FILENAME_COMPONENT(QT5_FIND_MODULE ${QT5_FIND_MODULE} DIRECTORY) +GET_FILENAME_COMPONENT(QT5_FIND_MODULE ${QT5_FIND_MODULE} DIRECTORY) +LIST(APPEND CMAKE_PREFIX_PATH ${QT5_FIND_MODULE}/lib/cmake) + +FILE(GLOB_RECURSE BOOST_ROOT ${DEPENDENCIES_DIR}/boost*/project-config.jam) +GET_FILENAME_COMPONENT(BOOST_ROOT ${BOOST_ROOT} DIRECTORY) + +ADD_SUBDIRECTORY(src) \ No newline at end of file diff --git a/src/CMakeLists.txt b/src/CMakeLists.txt new file mode 100644 index 00000000..b2db206a --- /dev/null +++ b/src/CMakeLists.txt @@ -0,0 +1,55 @@ +CMAKE_MINIMUM_REQUIRED (VERSION 2.8) + +SET(PROJ_NAME game_gamebryo) + +PROJECT(${PROJ_NAME}) + +CMAKE_POLICY(SET CMP0020 NEW) +CMAKE_POLICY(SET CMP0043 NEW) + +FILE(GLOB ${PROJ_NAME}_SRCS *.cpp) +FILE(GLOB ${PROJ_NAME}_HDRS *.h) +FILE(GLOB ${PROJ_NAME}_FORMS *.ui) + + +SET(CMAKE_INCLUDE_CURRENT_DIR ON) +SET(CMAKE_AUTOMOC ON) +SET(CMAKE_AUTOUIC ON) +FIND_PACKAGE(Qt5Widgets REQUIRED) +QT5_WRAP_UI(${PROJ_NAME}_UIHDRS ${${PROJ_NAME}_FORMS}) + +SET(Boost_USE_STATIC_LIBS ON) +SET(Boost_USE_MULTITHREADED ON) +SET(Boost_USE_STATIC_RUNTIME OFF) +FIND_PACKAGE(Boost) + +IF (Boost_FOUND) + INCLUDE_DIRECTORIES(${Boost_INCLUDE_DIRS}) +ENDIF (Boost_FOUND) + +SET(default_project_path "${CMAKE_SOURCE_DIR}/../..") +GET_FILENAME_COMPONENT(${default_project_path} ${default_project_path} REALPATH) + +SET(project_path "${default_project_path}" CACHE PATH "path to the other mo projects") + +INCLUDE_DIRECTORIES(${project_path}/uibase/src) +LINK_DIRECTORIES(${project_path}/uibase/src) + + +ADD_LIBRARY(${PROJ_NAME} SHARED ${${PROJ_NAME}_HDRS} ${${PROJ_NAME}_SRCS} ${${PROJ_NAME}_UIHDRS}) +TARGET_LINK_LIBRARIES(${PROJ_NAME} + Qt5::Widgets + ${Boost_LIBRARIES} + uibase) + +SET_TARGET_PROPERTIES(${PROJ_NAME} PROPERTIES COMPILE_FLAGS /GL) +SET_TARGET_PROPERTIES(${PROJ_NAME} PROPERTIES LINK_FLAGS_RELWITHDEBINFO "/LTCG /LARGEADDRESSAWARE /OPT:REF /OPT:ICF") + +QT5_USE_MODULES(${PROJ_NAME} Widgets) + +############### +## Installation + +INSTALL(TARGETS ${PROJ_NAME} + RUNTIME DESTINATION bin/plugins) +INSTALL(FILES ${CMAKE_CURRENT_BINARY_DIR}/${PROJ_NAME}.pdb DESTINATION pdb) From c9ea6c3db628694563d7f5be2ddee19cefe775b6 Mon Sep 17 00:00:00 2001 From: Tannin Date: Sat, 26 Sep 2015 12:01:28 +0200 Subject: [PATCH 0045/1544] updated build system --- src/CMakeLists.txt | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/src/CMakeLists.txt b/src/CMakeLists.txt index b2db206a..59b78236 100644 --- a/src/CMakeLists.txt +++ b/src/CMakeLists.txt @@ -32,11 +32,12 @@ GET_FILENAME_COMPONENT(${default_project_path} ${default_project_path} REALPATH) SET(project_path "${default_project_path}" CACHE PATH "path to the other mo projects") -INCLUDE_DIRECTORIES(${project_path}/uibase/src) -LINK_DIRECTORIES(${project_path}/uibase/src) +INCLUDE_DIRECTORIES(${project_path}/uibase/src + ${project_path}/plugin/game_features/src) +LINK_DIRECTORIES(${project_path}/uibase/build/src) -ADD_LIBRARY(${PROJ_NAME} SHARED ${${PROJ_NAME}_HDRS} ${${PROJ_NAME}_SRCS} ${${PROJ_NAME}_UIHDRS}) +ADD_LIBRARY(${PROJ_NAME} STATIC ${${PROJ_NAME}_HDRS} ${${PROJ_NAME}_SRCS} ${${PROJ_NAME}_UIHDRS}) TARGET_LINK_LIBRARIES(${PROJ_NAME} Qt5::Widgets ${Boost_LIBRARIES} @@ -51,5 +52,4 @@ QT5_USE_MODULES(${PROJ_NAME} Widgets) ## Installation INSTALL(TARGETS ${PROJ_NAME} - RUNTIME DESTINATION bin/plugins) -INSTALL(FILES ${CMAKE_CURRENT_BINARY_DIR}/${PROJ_NAME}.pdb DESTINATION pdb) + ARCHIVE DESTINATION libs) From b404d0cede9e71a5cff9a08e149788bd46161184 Mon Sep 17 00:00:00 2001 From: Tannin Date: Sat, 26 Sep 2015 12:03:12 +0200 Subject: [PATCH 0046/1544] [game_skyrim] updated build system --- src/games/skyrim/.gitignore | 1 + src/games/skyrim/CMakeLists.txt | 14 +++++++ src/games/skyrim/src/CMakeLists.txt | 60 +++++++++++++++++++++++++++++ 3 files changed, 75 insertions(+) create mode 100644 src/games/skyrim/.gitignore create mode 100644 src/games/skyrim/CMakeLists.txt create mode 100644 src/games/skyrim/src/CMakeLists.txt diff --git a/src/games/skyrim/.gitignore b/src/games/skyrim/.gitignore new file mode 100644 index 00000000..378eac25 --- /dev/null +++ b/src/games/skyrim/.gitignore @@ -0,0 +1 @@ +build diff --git a/src/games/skyrim/CMakeLists.txt b/src/games/skyrim/CMakeLists.txt new file mode 100644 index 00000000..0c6592ac --- /dev/null +++ b/src/games/skyrim/CMakeLists.txt @@ -0,0 +1,14 @@ +CMAKE_MINIMUM_REQUIRED(VERSION 2.8) + +SET(DEPENDENCIES_DIR CACHE PATH "") + +# hint to find qt in dependencies path +FILE(GLOB_RECURSE QT5_FIND_MODULE ${DEPENDENCIES_DIR}/qt5.git/qtbase/bin/qmake.exe) +GET_FILENAME_COMPONENT(QT5_FIND_MODULE ${QT5_FIND_MODULE} DIRECTORY) +GET_FILENAME_COMPONENT(QT5_FIND_MODULE ${QT5_FIND_MODULE} DIRECTORY) +LIST(APPEND CMAKE_PREFIX_PATH ${QT5_FIND_MODULE}/lib/cmake) + +FILE(GLOB_RECURSE BOOST_ROOT ${DEPENDENCIES_DIR}/boost*/project-config.jam) +GET_FILENAME_COMPONENT(BOOST_ROOT ${BOOST_ROOT} DIRECTORY) + +ADD_SUBDIRECTORY(src) \ No newline at end of file diff --git a/src/games/skyrim/src/CMakeLists.txt b/src/games/skyrim/src/CMakeLists.txt new file mode 100644 index 00000000..609d3915 --- /dev/null +++ b/src/games/skyrim/src/CMakeLists.txt @@ -0,0 +1,60 @@ +CMAKE_MINIMUM_REQUIRED (VERSION 2.8) + +SET(PROJ_NAME gameSkyrim) + +PROJECT(${PROJ_NAME}) + +CMAKE_POLICY(SET CMP0020 NEW) +CMAKE_POLICY(SET CMP0043 NEW) + +FILE(GLOB ${PROJ_NAME}_SRCS *.cpp) +FILE(GLOB ${PROJ_NAME}_HDRS *.h) +FILE(GLOB ${PROJ_NAME}_FORMS *.ui) + + +SET(CMAKE_INCLUDE_CURRENT_DIR ON) +SET(CMAKE_AUTOMOC ON) +SET(CMAKE_AUTOUIC ON) +FIND_PACKAGE(Qt5Widgets REQUIRED) +QT5_WRAP_UI(${PROJ_NAME}_UIHDRS ${${PROJ_NAME}_FORMS}) + +SET(Boost_USE_STATIC_LIBS ON) +SET(Boost_USE_MULTITHREADED ON) +SET(Boost_USE_STATIC_RUNTIME OFF) +FIND_PACKAGE(Boost) + +IF (Boost_FOUND) + INCLUDE_DIRECTORIES(${Boost_INCLUDE_DIRS}) +ENDIF () + +SET(default_project_path "${CMAKE_SOURCE_DIR}/../..") +GET_FILENAME_COMPONENT(${default_project_path} ${default_project_path} REALPATH) + +SET(project_path "${default_project_path}" CACHE PATH "path to the other mo projects") +SET(lib_path "${project_path}/../install/libs") + +INCLUDE_DIRECTORIES(${project_path}/uibase/src + ${project_path}/plugin/game_features/src + ${project_path}/plugin/game_gamebryo/src) +LINK_DIRECTORIES(${project_path}/uibase/build/src + ${lib_path}) + + +ADD_LIBRARY(${PROJ_NAME} SHARED ${${PROJ_NAME}_HDRS} ${${PROJ_NAME}_SRCS} ${${PROJ_NAME}_UIHDRS}) +TARGET_LINK_LIBRARIES(${PROJ_NAME} + Qt5::Widgets + ${Boost_LIBRARIES} + uibase + game_gamebryo) + +SET_TARGET_PROPERTIES(${PROJ_NAME} PROPERTIES COMPILE_FLAGS /GL) +SET_TARGET_PROPERTIES(${PROJ_NAME} PROPERTIES LINK_FLAGS_RELWITHDEBINFO "/LTCG /LARGEADDRESSAWARE /OPT:REF /OPT:ICF") + +QT5_USE_MODULES(${PROJ_NAME} Widgets) + +############### +## Installation + +INSTALL(TARGETS ${PROJ_NAME} + RUNTIME DESTINATION bin/plugins) +INSTALL(FILES ${CMAKE_CURRENT_BINARY_DIR}/${PROJ_NAME}.pdb DESTINATION pdb) From 55eef11bf2266c05d299197b03b24900adb322c2 Mon Sep 17 00:00:00 2001 From: Tannin Date: Sat, 26 Sep 2015 23:54:23 +0200 Subject: [PATCH 0047/1544] fixed build system --- CMakeLists.txt | 5 +---- 1 file changed, 1 insertion(+), 4 deletions(-) diff --git a/CMakeLists.txt b/CMakeLists.txt index 0c6592ac..e7d345e0 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -3,10 +3,7 @@ CMAKE_MINIMUM_REQUIRED(VERSION 2.8) SET(DEPENDENCIES_DIR CACHE PATH "") # hint to find qt in dependencies path -FILE(GLOB_RECURSE QT5_FIND_MODULE ${DEPENDENCIES_DIR}/qt5.git/qtbase/bin/qmake.exe) -GET_FILENAME_COMPONENT(QT5_FIND_MODULE ${QT5_FIND_MODULE} DIRECTORY) -GET_FILENAME_COMPONENT(QT5_FIND_MODULE ${QT5_FIND_MODULE} DIRECTORY) -LIST(APPEND CMAKE_PREFIX_PATH ${QT5_FIND_MODULE}/lib/cmake) +LIST(APPEND CMAKE_PREFIX_PATH ${DEPENDENCIES_DIR}/qt5/lib/cmake) FILE(GLOB_RECURSE BOOST_ROOT ${DEPENDENCIES_DIR}/boost*/project-config.jam) GET_FILENAME_COMPONENT(BOOST_ROOT ${BOOST_ROOT} DIRECTORY) From 945567dd48bf6d58cc9450d7ad4f3c6c4d44f09e Mon Sep 17 00:00:00 2001 From: Tannin Date: Sat, 26 Sep 2015 23:55:15 +0200 Subject: [PATCH 0048/1544] [game_skyrim] fixed build system --- src/games/skyrim/CMakeLists.txt | 5 +---- 1 file changed, 1 insertion(+), 4 deletions(-) diff --git a/src/games/skyrim/CMakeLists.txt b/src/games/skyrim/CMakeLists.txt index 0c6592ac..e7d345e0 100644 --- a/src/games/skyrim/CMakeLists.txt +++ b/src/games/skyrim/CMakeLists.txt @@ -3,10 +3,7 @@ CMAKE_MINIMUM_REQUIRED(VERSION 2.8) SET(DEPENDENCIES_DIR CACHE PATH "") # hint to find qt in dependencies path -FILE(GLOB_RECURSE QT5_FIND_MODULE ${DEPENDENCIES_DIR}/qt5.git/qtbase/bin/qmake.exe) -GET_FILENAME_COMPONENT(QT5_FIND_MODULE ${QT5_FIND_MODULE} DIRECTORY) -GET_FILENAME_COMPONENT(QT5_FIND_MODULE ${QT5_FIND_MODULE} DIRECTORY) -LIST(APPEND CMAKE_PREFIX_PATH ${QT5_FIND_MODULE}/lib/cmake) +LIST(APPEND CMAKE_PREFIX_PATH ${DEPENDENCIES_DIR}/qt5/lib/cmake) FILE(GLOB_RECURSE BOOST_ROOT ${DEPENDENCIES_DIR}/boost*/project-config.jam) GET_FILENAME_COMPONENT(BOOST_ROOT ${BOOST_ROOT} DIRECTORY) From f7bc3e1e4991c758f5577b86e171e4d4963605c0 Mon Sep 17 00:00:00 2001 From: Tannin Date: Fri, 9 Oct 2015 19:26:11 +0200 Subject: [PATCH 0049/1544] [game_fallout3] more work on build system --- src/games/fallout3/.gitignore | 4 ++ src/games/fallout3/CMakeLists.txt | 15 ++++++++ src/games/fallout3/src/CMakeLists.txt | 55 +++++++++++++++++++++++++++ 3 files changed, 74 insertions(+) create mode 100644 src/games/fallout3/.gitignore create mode 100644 src/games/fallout3/CMakeLists.txt create mode 100644 src/games/fallout3/src/CMakeLists.txt diff --git a/src/games/fallout3/.gitignore b/src/games/fallout3/.gitignore new file mode 100644 index 00000000..bcc50d34 --- /dev/null +++ b/src/games/fallout3/.gitignore @@ -0,0 +1,4 @@ +CMakeLists.txt.user +edit +build +std*.log diff --git a/src/games/fallout3/CMakeLists.txt b/src/games/fallout3/CMakeLists.txt new file mode 100644 index 00000000..4e429db1 --- /dev/null +++ b/src/games/fallout3/CMakeLists.txt @@ -0,0 +1,15 @@ +CMAKE_MINIMUM_REQUIRED(VERSION 2.8) + +SET(PROJ_NAME gameFallout3) + +PROJECT(${PROJ_NAME}) + +SET(DEPENDENCIES_DIR CACHE PATH "") + +# hint to find qt in dependencies path +LIST(APPEND CMAKE_PREFIX_PATH ${DEPENDENCIES_DIR}/qt5/lib/cmake) + +FILE(GLOB_RECURSE BOOST_ROOT ${DEPENDENCIES_DIR}/boost*/project-config.jam) +GET_FILENAME_COMPONENT(BOOST_ROOT ${BOOST_ROOT} DIRECTORY) + +ADD_SUBDIRECTORY(src) \ No newline at end of file diff --git a/src/games/fallout3/src/CMakeLists.txt b/src/games/fallout3/src/CMakeLists.txt new file mode 100644 index 00000000..2b48491d --- /dev/null +++ b/src/games/fallout3/src/CMakeLists.txt @@ -0,0 +1,55 @@ +CMAKE_MINIMUM_REQUIRED (VERSION 2.8) + +CMAKE_POLICY(SET CMP0020 NEW) + +FILE(GLOB ${PROJ_NAME}_SRCS *.cpp) +FILE(GLOB ${PROJ_NAME}_HDRS *.h) +FILE(GLOB ${PROJ_NAME}_FORMS *.ui) + + +SET(CMAKE_INCLUDE_CURRENT_DIR ON) +SET(CMAKE_AUTOMOC ON) +SET(CMAKE_AUTOUIC ON) +FIND_PACKAGE(Qt5Widgets REQUIRED) +QT5_WRAP_UI(${PROJ_NAME}_UIHDRS ${${PROJ_NAME}_FORMS}) + +SET(Boost_USE_STATIC_LIBS ON) +SET(Boost_USE_MULTITHREADED ON) +SET(Boost_USE_STATIC_RUNTIME OFF) +FIND_PACKAGE(Boost) + +IF (Boost_FOUND) + INCLUDE_DIRECTORIES(${Boost_INCLUDE_DIRS}) +ENDIF () + +SET(default_project_path "${CMAKE_SOURCE_DIR}/../..") +GET_FILENAME_COMPONENT(${default_project_path} ${default_project_path} REALPATH) + +SET(project_path "${default_project_path}" CACHE PATH "path to the other mo projects") +SET(lib_path "${project_path}/../install/libs") + +INCLUDE_DIRECTORIES(${project_path}/uibase/src + ${project_path}/plugin/game_features/src + ${project_path}/plugin/game_gamebryo/src) +LINK_DIRECTORIES(${project_path}/uibase/build/src + ${lib_path}) + + +ADD_LIBRARY(${PROJ_NAME} SHARED ${${PROJ_NAME}_HDRS} ${${PROJ_NAME}_SRCS} ${${PROJ_NAME}_UIHDRS}) +TARGET_LINK_LIBRARIES(${PROJ_NAME} + Qt5::Widgets + ${Boost_LIBRARIES} + uibase + game_gamebryo) + +SET_TARGET_PROPERTIES(${PROJ_NAME} PROPERTIES COMPILE_FLAGS /GL) +SET_TARGET_PROPERTIES(${PROJ_NAME} PROPERTIES LINK_FLAGS_RELWITHDEBINFO "/LTCG /LARGEADDRESSAWARE /OPT:REF /OPT:ICF") + +QT5_USE_MODULES(${PROJ_NAME} Widgets) + +############### +## Installation + +INSTALL(TARGETS ${PROJ_NAME} + RUNTIME DESTINATION bin/plugins) +INSTALL(FILES ${CMAKE_CURRENT_BINARY_DIR}/${PROJ_NAME}.pdb DESTINATION pdb) From ff93d2534520c887a0d77c96c0609476cca2e913 Mon Sep 17 00:00:00 2001 From: Tannin Date: Fri, 9 Oct 2015 19:27:22 +0200 Subject: [PATCH 0050/1544] [game_falloutnv] more work on build system --- src/games/falloutnv/.gitignore | 4 ++ src/games/falloutnv/CMakeLists.txt | 15 +++++++ src/games/falloutnv/src/CMakeLists.txt | 55 ++++++++++++++++++++++++++ 3 files changed, 74 insertions(+) create mode 100644 src/games/falloutnv/.gitignore create mode 100644 src/games/falloutnv/CMakeLists.txt create mode 100644 src/games/falloutnv/src/CMakeLists.txt diff --git a/src/games/falloutnv/.gitignore b/src/games/falloutnv/.gitignore new file mode 100644 index 00000000..5477e9c4 --- /dev/null +++ b/src/games/falloutnv/.gitignore @@ -0,0 +1,4 @@ +std*.log +build +CMakeLists.txt.user +edit diff --git a/src/games/falloutnv/CMakeLists.txt b/src/games/falloutnv/CMakeLists.txt new file mode 100644 index 00000000..cc6fe23e --- /dev/null +++ b/src/games/falloutnv/CMakeLists.txt @@ -0,0 +1,15 @@ +CMAKE_MINIMUM_REQUIRED(VERSION 2.8) + +SET(PROJ_NAME gameFalloutNV) + +PROJECT(${PROJ_NAME}) + +SET(DEPENDENCIES_DIR CACHE PATH "") + +# hint to find qt in dependencies path +LIST(APPEND CMAKE_PREFIX_PATH ${DEPENDENCIES_DIR}/qt5/lib/cmake) + +FILE(GLOB_RECURSE BOOST_ROOT ${DEPENDENCIES_DIR}/boost*/project-config.jam) +GET_FILENAME_COMPONENT(BOOST_ROOT ${BOOST_ROOT} DIRECTORY) + +ADD_SUBDIRECTORY(src) \ No newline at end of file diff --git a/src/games/falloutnv/src/CMakeLists.txt b/src/games/falloutnv/src/CMakeLists.txt new file mode 100644 index 00000000..2b48491d --- /dev/null +++ b/src/games/falloutnv/src/CMakeLists.txt @@ -0,0 +1,55 @@ +CMAKE_MINIMUM_REQUIRED (VERSION 2.8) + +CMAKE_POLICY(SET CMP0020 NEW) + +FILE(GLOB ${PROJ_NAME}_SRCS *.cpp) +FILE(GLOB ${PROJ_NAME}_HDRS *.h) +FILE(GLOB ${PROJ_NAME}_FORMS *.ui) + + +SET(CMAKE_INCLUDE_CURRENT_DIR ON) +SET(CMAKE_AUTOMOC ON) +SET(CMAKE_AUTOUIC ON) +FIND_PACKAGE(Qt5Widgets REQUIRED) +QT5_WRAP_UI(${PROJ_NAME}_UIHDRS ${${PROJ_NAME}_FORMS}) + +SET(Boost_USE_STATIC_LIBS ON) +SET(Boost_USE_MULTITHREADED ON) +SET(Boost_USE_STATIC_RUNTIME OFF) +FIND_PACKAGE(Boost) + +IF (Boost_FOUND) + INCLUDE_DIRECTORIES(${Boost_INCLUDE_DIRS}) +ENDIF () + +SET(default_project_path "${CMAKE_SOURCE_DIR}/../..") +GET_FILENAME_COMPONENT(${default_project_path} ${default_project_path} REALPATH) + +SET(project_path "${default_project_path}" CACHE PATH "path to the other mo projects") +SET(lib_path "${project_path}/../install/libs") + +INCLUDE_DIRECTORIES(${project_path}/uibase/src + ${project_path}/plugin/game_features/src + ${project_path}/plugin/game_gamebryo/src) +LINK_DIRECTORIES(${project_path}/uibase/build/src + ${lib_path}) + + +ADD_LIBRARY(${PROJ_NAME} SHARED ${${PROJ_NAME}_HDRS} ${${PROJ_NAME}_SRCS} ${${PROJ_NAME}_UIHDRS}) +TARGET_LINK_LIBRARIES(${PROJ_NAME} + Qt5::Widgets + ${Boost_LIBRARIES} + uibase + game_gamebryo) + +SET_TARGET_PROPERTIES(${PROJ_NAME} PROPERTIES COMPILE_FLAGS /GL) +SET_TARGET_PROPERTIES(${PROJ_NAME} PROPERTIES LINK_FLAGS_RELWITHDEBINFO "/LTCG /LARGEADDRESSAWARE /OPT:REF /OPT:ICF") + +QT5_USE_MODULES(${PROJ_NAME} Widgets) + +############### +## Installation + +INSTALL(TARGETS ${PROJ_NAME} + RUNTIME DESTINATION bin/plugins) +INSTALL(FILES ${CMAKE_CURRENT_BINARY_DIR}/${PROJ_NAME}.pdb DESTINATION pdb) From 94433351b75af81de265972973ff1ca5aa7d751b Mon Sep 17 00:00:00 2001 From: Tannin Date: Fri, 9 Oct 2015 19:28:35 +0200 Subject: [PATCH 0051/1544] more work on build system --- .gitignore | 2 ++ CMakeLists.txt | 3 +++ src/CMakeLists.txt | 5 ----- 3 files changed, 5 insertions(+), 5 deletions(-) diff --git a/.gitignore b/.gitignore index 2be5b91e..5477e9c4 100644 --- a/.gitignore +++ b/.gitignore @@ -1,2 +1,4 @@ std*.log build +CMakeLists.txt.user +edit diff --git a/CMakeLists.txt b/CMakeLists.txt index e7d345e0..e0a4f4c5 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -1,5 +1,8 @@ CMAKE_MINIMUM_REQUIRED(VERSION 2.8) +SET(PROJ_NAME game_gamebryo) +PROJECT(${PROJ_NAME}) + SET(DEPENDENCIES_DIR CACHE PATH "") # hint to find qt in dependencies path diff --git a/src/CMakeLists.txt b/src/CMakeLists.txt index 59b78236..4beb4f26 100644 --- a/src/CMakeLists.txt +++ b/src/CMakeLists.txt @@ -1,11 +1,6 @@ CMAKE_MINIMUM_REQUIRED (VERSION 2.8) -SET(PROJ_NAME game_gamebryo) - -PROJECT(${PROJ_NAME}) - CMAKE_POLICY(SET CMP0020 NEW) -CMAKE_POLICY(SET CMP0043 NEW) FILE(GLOB ${PROJ_NAME}_SRCS *.cpp) FILE(GLOB ${PROJ_NAME}_HDRS *.h) From 532b9933b398ac54f5d8aaa968d019ca87db2603 Mon Sep 17 00:00:00 2001 From: Tannin Date: Fri, 9 Oct 2015 19:32:44 +0200 Subject: [PATCH 0052/1544] [game_oblivion] more work on build system --- src/games/oblivion/.gitignore | 4 ++ src/games/oblivion/CMakeLists.txt | 15 ++++++++ src/games/oblivion/src/CMakeLists.txt | 55 +++++++++++++++++++++++++++ 3 files changed, 74 insertions(+) create mode 100644 src/games/oblivion/.gitignore create mode 100644 src/games/oblivion/CMakeLists.txt create mode 100644 src/games/oblivion/src/CMakeLists.txt diff --git a/src/games/oblivion/.gitignore b/src/games/oblivion/.gitignore new file mode 100644 index 00000000..c5a72415 --- /dev/null +++ b/src/games/oblivion/.gitignore @@ -0,0 +1,4 @@ +CMakeLists.txt.user +edit +std*.log +build diff --git a/src/games/oblivion/CMakeLists.txt b/src/games/oblivion/CMakeLists.txt new file mode 100644 index 00000000..6b0177ed --- /dev/null +++ b/src/games/oblivion/CMakeLists.txt @@ -0,0 +1,15 @@ +CMAKE_MINIMUM_REQUIRED(VERSION 2.8) + +SET(PROJ_NAME gameOblivion) + +PROJECT(${PROJ_NAME}) + +SET(DEPENDENCIES_DIR CACHE PATH "") + +# hint to find qt in dependencies path +LIST(APPEND CMAKE_PREFIX_PATH ${DEPENDENCIES_DIR}/qt5/lib/cmake) + +FILE(GLOB_RECURSE BOOST_ROOT ${DEPENDENCIES_DIR}/boost*/project-config.jam) +GET_FILENAME_COMPONENT(BOOST_ROOT ${BOOST_ROOT} DIRECTORY) + +ADD_SUBDIRECTORY(src) \ No newline at end of file diff --git a/src/games/oblivion/src/CMakeLists.txt b/src/games/oblivion/src/CMakeLists.txt new file mode 100644 index 00000000..2b48491d --- /dev/null +++ b/src/games/oblivion/src/CMakeLists.txt @@ -0,0 +1,55 @@ +CMAKE_MINIMUM_REQUIRED (VERSION 2.8) + +CMAKE_POLICY(SET CMP0020 NEW) + +FILE(GLOB ${PROJ_NAME}_SRCS *.cpp) +FILE(GLOB ${PROJ_NAME}_HDRS *.h) +FILE(GLOB ${PROJ_NAME}_FORMS *.ui) + + +SET(CMAKE_INCLUDE_CURRENT_DIR ON) +SET(CMAKE_AUTOMOC ON) +SET(CMAKE_AUTOUIC ON) +FIND_PACKAGE(Qt5Widgets REQUIRED) +QT5_WRAP_UI(${PROJ_NAME}_UIHDRS ${${PROJ_NAME}_FORMS}) + +SET(Boost_USE_STATIC_LIBS ON) +SET(Boost_USE_MULTITHREADED ON) +SET(Boost_USE_STATIC_RUNTIME OFF) +FIND_PACKAGE(Boost) + +IF (Boost_FOUND) + INCLUDE_DIRECTORIES(${Boost_INCLUDE_DIRS}) +ENDIF () + +SET(default_project_path "${CMAKE_SOURCE_DIR}/../..") +GET_FILENAME_COMPONENT(${default_project_path} ${default_project_path} REALPATH) + +SET(project_path "${default_project_path}" CACHE PATH "path to the other mo projects") +SET(lib_path "${project_path}/../install/libs") + +INCLUDE_DIRECTORIES(${project_path}/uibase/src + ${project_path}/plugin/game_features/src + ${project_path}/plugin/game_gamebryo/src) +LINK_DIRECTORIES(${project_path}/uibase/build/src + ${lib_path}) + + +ADD_LIBRARY(${PROJ_NAME} SHARED ${${PROJ_NAME}_HDRS} ${${PROJ_NAME}_SRCS} ${${PROJ_NAME}_UIHDRS}) +TARGET_LINK_LIBRARIES(${PROJ_NAME} + Qt5::Widgets + ${Boost_LIBRARIES} + uibase + game_gamebryo) + +SET_TARGET_PROPERTIES(${PROJ_NAME} PROPERTIES COMPILE_FLAGS /GL) +SET_TARGET_PROPERTIES(${PROJ_NAME} PROPERTIES LINK_FLAGS_RELWITHDEBINFO "/LTCG /LARGEADDRESSAWARE /OPT:REF /OPT:ICF") + +QT5_USE_MODULES(${PROJ_NAME} Widgets) + +############### +## Installation + +INSTALL(TARGETS ${PROJ_NAME} + RUNTIME DESTINATION bin/plugins) +INSTALL(FILES ${CMAKE_CURRENT_BINARY_DIR}/${PROJ_NAME}.pdb DESTINATION pdb) From 5c60f407439d32b48410a45a2c1082e310eee3a6 Mon Sep 17 00:00:00 2001 From: Tannin Date: Fri, 9 Oct 2015 19:34:04 +0200 Subject: [PATCH 0053/1544] [game_skyrim] more work on build system --- src/games/skyrim/.gitignore | 3 +++ src/games/skyrim/CMakeLists.txt | 4 ++++ src/games/skyrim/src/CMakeLists.txt | 5 ----- 3 files changed, 7 insertions(+), 5 deletions(-) diff --git a/src/games/skyrim/.gitignore b/src/games/skyrim/.gitignore index 378eac25..5ff13f91 100644 --- a/src/games/skyrim/.gitignore +++ b/src/games/skyrim/.gitignore @@ -1 +1,4 @@ build +CMakeLists.txt.user +edit +std*.log diff --git a/src/games/skyrim/CMakeLists.txt b/src/games/skyrim/CMakeLists.txt index e7d345e0..3bc9735b 100644 --- a/src/games/skyrim/CMakeLists.txt +++ b/src/games/skyrim/CMakeLists.txt @@ -1,5 +1,9 @@ CMAKE_MINIMUM_REQUIRED(VERSION 2.8) +SET(PROJ_NAME gameSkyrim) + +PROJECT(${PROJ_NAME}) + SET(DEPENDENCIES_DIR CACHE PATH "") # hint to find qt in dependencies path diff --git a/src/games/skyrim/src/CMakeLists.txt b/src/games/skyrim/src/CMakeLists.txt index 609d3915..2b48491d 100644 --- a/src/games/skyrim/src/CMakeLists.txt +++ b/src/games/skyrim/src/CMakeLists.txt @@ -1,11 +1,6 @@ CMAKE_MINIMUM_REQUIRED (VERSION 2.8) -SET(PROJ_NAME gameSkyrim) - -PROJECT(${PROJ_NAME}) - CMAKE_POLICY(SET CMP0020 NEW) -CMAKE_POLICY(SET CMP0043 NEW) FILE(GLOB ${PROJ_NAME}_SRCS *.cpp) FILE(GLOB ${PROJ_NAME}_HDRS *.h) From 5b22655c9da52406294886e8f7e21e5e9e30e02f Mon Sep 17 00:00:00 2001 From: Tannin Date: Mon, 16 Nov 2015 21:39:49 +0100 Subject: [PATCH 0054/1544] [game_fallout3] updated build scripts --- src/games/fallout3/src/CMakeLists.txt | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/src/games/fallout3/src/CMakeLists.txt b/src/games/fallout3/src/CMakeLists.txt index 2b48491d..15136936 100644 --- a/src/games/fallout3/src/CMakeLists.txt +++ b/src/games/fallout3/src/CMakeLists.txt @@ -22,15 +22,15 @@ IF (Boost_FOUND) INCLUDE_DIRECTORIES(${Boost_INCLUDE_DIRS}) ENDIF () -SET(default_project_path "${CMAKE_SOURCE_DIR}/../..") +SET(default_project_path "${CMAKE_SOURCE_DIR}/..") GET_FILENAME_COMPONENT(${default_project_path} ${default_project_path} REALPATH) SET(project_path "${default_project_path}" CACHE PATH "path to the other mo projects") -SET(lib_path "${project_path}/../install/libs") +SET(lib_path "${project_path}/../../install/libs") INCLUDE_DIRECTORIES(${project_path}/uibase/src - ${project_path}/plugin/game_features/src - ${project_path}/plugin/game_gamebryo/src) + ${project_path}/game_features/src + ${project_path}/game_gamebryo/src) LINK_DIRECTORIES(${project_path}/uibase/build/src ${lib_path}) From 3835772e1b8acbca62f0dacbca4fee1efc799d8b Mon Sep 17 00:00:00 2001 From: Tannin Date: Mon, 16 Nov 2015 21:39:50 +0100 Subject: [PATCH 0055/1544] updated build scripts --- src/CMakeLists.txt | 12 +++++++++--- 1 file changed, 9 insertions(+), 3 deletions(-) diff --git a/src/CMakeLists.txt b/src/CMakeLists.txt index 4beb4f26..e276aab0 100644 --- a/src/CMakeLists.txt +++ b/src/CMakeLists.txt @@ -22,14 +22,20 @@ IF (Boost_FOUND) INCLUDE_DIRECTORIES(${Boost_INCLUDE_DIRS}) ENDIF (Boost_FOUND) -SET(default_project_path "${CMAKE_SOURCE_DIR}/../..") +SET(default_project_path "${CMAKE_SOURCE_DIR}/..") GET_FILENAME_COMPONENT(${default_project_path} ${default_project_path} REALPATH) SET(project_path "${default_project_path}" CACHE PATH "path to the other mo projects") +SET(lib_path "${project_path}/../../install/libs") +SET(plugin_path "${project_path}") + +MESSAGE(STATUS ${lib_path}) +MESSAGE(STATUS ${plugin_path}) +MESSAGE(STATUS ${project_path}) INCLUDE_DIRECTORIES(${project_path}/uibase/src - ${project_path}/plugin/game_features/src) -LINK_DIRECTORIES(${project_path}/uibase/build/src) + ${project_path}/game_features/src) +LINK_DIRECTORIES(${lib_path}) ADD_LIBRARY(${PROJ_NAME} STATIC ${${PROJ_NAME}_HDRS} ${${PROJ_NAME}_SRCS} ${${PROJ_NAME}_UIHDRS}) From 093cfa2f17efa289c86e2100499a40ccdf6f7286 Mon Sep 17 00:00:00 2001 From: Tannin Date: Mon, 16 Nov 2015 21:39:50 +0100 Subject: [PATCH 0056/1544] [game_skyrim] updated build scripts --- src/games/skyrim/src/CMakeLists.txt | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/src/games/skyrim/src/CMakeLists.txt b/src/games/skyrim/src/CMakeLists.txt index 2b48491d..15136936 100644 --- a/src/games/skyrim/src/CMakeLists.txt +++ b/src/games/skyrim/src/CMakeLists.txt @@ -22,15 +22,15 @@ IF (Boost_FOUND) INCLUDE_DIRECTORIES(${Boost_INCLUDE_DIRS}) ENDIF () -SET(default_project_path "${CMAKE_SOURCE_DIR}/../..") +SET(default_project_path "${CMAKE_SOURCE_DIR}/..") GET_FILENAME_COMPONENT(${default_project_path} ${default_project_path} REALPATH) SET(project_path "${default_project_path}" CACHE PATH "path to the other mo projects") -SET(lib_path "${project_path}/../install/libs") +SET(lib_path "${project_path}/../../install/libs") INCLUDE_DIRECTORIES(${project_path}/uibase/src - ${project_path}/plugin/game_features/src - ${project_path}/plugin/game_gamebryo/src) + ${project_path}/game_features/src + ${project_path}/game_gamebryo/src) LINK_DIRECTORIES(${project_path}/uibase/build/src ${lib_path}) From 7e179551f1cb51976a0e1f54b91f9bf9a58475ea Mon Sep 17 00:00:00 2001 From: Tannin Date: Mon, 16 Nov 2015 21:39:50 +0100 Subject: [PATCH 0057/1544] [game_falloutnv] updated build scripts --- src/games/falloutnv/src/CMakeLists.txt | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/src/games/falloutnv/src/CMakeLists.txt b/src/games/falloutnv/src/CMakeLists.txt index 2b48491d..15136936 100644 --- a/src/games/falloutnv/src/CMakeLists.txt +++ b/src/games/falloutnv/src/CMakeLists.txt @@ -22,15 +22,15 @@ IF (Boost_FOUND) INCLUDE_DIRECTORIES(${Boost_INCLUDE_DIRS}) ENDIF () -SET(default_project_path "${CMAKE_SOURCE_DIR}/../..") +SET(default_project_path "${CMAKE_SOURCE_DIR}/..") GET_FILENAME_COMPONENT(${default_project_path} ${default_project_path} REALPATH) SET(project_path "${default_project_path}" CACHE PATH "path to the other mo projects") -SET(lib_path "${project_path}/../install/libs") +SET(lib_path "${project_path}/../../install/libs") INCLUDE_DIRECTORIES(${project_path}/uibase/src - ${project_path}/plugin/game_features/src - ${project_path}/plugin/game_gamebryo/src) + ${project_path}/game_features/src + ${project_path}/game_gamebryo/src) LINK_DIRECTORIES(${project_path}/uibase/build/src ${lib_path}) From 2f57c789d3ac7dd4ea626736f8a9c124fac8d229 Mon Sep 17 00:00:00 2001 From: Tannin Date: Mon, 16 Nov 2015 21:39:50 +0100 Subject: [PATCH 0058/1544] [game_oblivion] updated build scripts --- src/games/oblivion/src/CMakeLists.txt | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/src/games/oblivion/src/CMakeLists.txt b/src/games/oblivion/src/CMakeLists.txt index 2b48491d..15136936 100644 --- a/src/games/oblivion/src/CMakeLists.txt +++ b/src/games/oblivion/src/CMakeLists.txt @@ -22,15 +22,15 @@ IF (Boost_FOUND) INCLUDE_DIRECTORIES(${Boost_INCLUDE_DIRS}) ENDIF () -SET(default_project_path "${CMAKE_SOURCE_DIR}/../..") +SET(default_project_path "${CMAKE_SOURCE_DIR}/..") GET_FILENAME_COMPONENT(${default_project_path} ${default_project_path} REALPATH) SET(project_path "${default_project_path}" CACHE PATH "path to the other mo projects") -SET(lib_path "${project_path}/../install/libs") +SET(lib_path "${project_path}/../../install/libs") INCLUDE_DIRECTORIES(${project_path}/uibase/src - ${project_path}/plugin/game_features/src - ${project_path}/plugin/game_gamebryo/src) + ${project_path}/game_features/src + ${project_path}/game_gamebryo/src) LINK_DIRECTORIES(${project_path}/uibase/build/src ${lib_path}) From 57c05ad708c2effaf0d5d55326e5da3d1ad6de1a Mon Sep 17 00:00:00 2001 From: Tannin Date: Tue, 17 Nov 2015 20:59:34 +0100 Subject: [PATCH 0059/1544] [game_fallout4vr] initial commit --- src/games/fallout4vr/.gitignore | 4 + src/games/fallout4vr/CMakeLists.txt | 15 ++ src/games/fallout4vr/CMakeLists.txt.user | 207 ++++++++++++++++++ src/games/fallout4vr/src/CMakeLists.txt | 55 +++++ src/games/fallout4vr/src/SConscript | 14 ++ .../fallout4vr/src/fallout4dataarchives.cpp | 53 +++++ .../fallout4vr/src/fallout4dataarchives.h | 24 ++ .../fallout4vr/src/fallout4scriptextender.cpp | 7 + .../fallout4vr/src/fallout4scriptextender.h | 14 ++ src/games/fallout4vr/src/gamefallout4.cpp | 163 ++++++++++++++ src/games/fallout4vr/src/gamefallout4.h | 65 ++++++ src/games/fallout4vr/src/gamefallout4.json | 1 + 12 files changed, 622 insertions(+) create mode 100644 src/games/fallout4vr/.gitignore create mode 100644 src/games/fallout4vr/CMakeLists.txt create mode 100644 src/games/fallout4vr/CMakeLists.txt.user create mode 100644 src/games/fallout4vr/src/CMakeLists.txt create mode 100644 src/games/fallout4vr/src/SConscript create mode 100644 src/games/fallout4vr/src/fallout4dataarchives.cpp create mode 100644 src/games/fallout4vr/src/fallout4dataarchives.h create mode 100644 src/games/fallout4vr/src/fallout4scriptextender.cpp create mode 100644 src/games/fallout4vr/src/fallout4scriptextender.h create mode 100644 src/games/fallout4vr/src/gamefallout4.cpp create mode 100644 src/games/fallout4vr/src/gamefallout4.h create mode 100644 src/games/fallout4vr/src/gamefallout4.json diff --git a/src/games/fallout4vr/.gitignore b/src/games/fallout4vr/.gitignore new file mode 100644 index 00000000..bcc50d34 --- /dev/null +++ b/src/games/fallout4vr/.gitignore @@ -0,0 +1,4 @@ +CMakeLists.txt.user +edit +build +std*.log diff --git a/src/games/fallout4vr/CMakeLists.txt b/src/games/fallout4vr/CMakeLists.txt new file mode 100644 index 00000000..64470f51 --- /dev/null +++ b/src/games/fallout4vr/CMakeLists.txt @@ -0,0 +1,15 @@ +CMAKE_MINIMUM_REQUIRED(VERSION 2.8) + +SET(PROJ_NAME gameFallout4) + +PROJECT(${PROJ_NAME}) + +SET(DEPENDENCIES_DIR CACHE PATH "") + +# hint to find qt in dependencies path +LIST(APPEND CMAKE_PREFIX_PATH ${DEPENDENCIES_DIR}/qt5/lib/cmake) + +FILE(GLOB_RECURSE BOOST_ROOT ${DEPENDENCIES_DIR}/boost*/project-config.jam) +GET_FILENAME_COMPONENT(BOOST_ROOT ${BOOST_ROOT} DIRECTORY) + +ADD_SUBDIRECTORY(src) diff --git a/src/games/fallout4vr/CMakeLists.txt.user b/src/games/fallout4vr/CMakeLists.txt.user new file mode 100644 index 00000000..a177254f --- /dev/null +++ b/src/games/fallout4vr/CMakeLists.txt.user @@ -0,0 +1,207 @@ + + + + + + EnvironmentId + {be93058c-4cdc-4db3-a586-0930ff4430c6} + + + ProjectExplorer.Project.ActiveTarget + 0 + + + ProjectExplorer.Project.EditorSettings + + true + false + true + + Cpp + + CppGlobal + + + + QmlJS + + QmlJSGlobal + + + 2 + UTF-8 + false + 4 + false + 80 + true + true + 1 + true + false + 0 + true + 0 + 8 + true + 1 + true + true + true + false + + + + ProjectExplorer.Project.PluginSettings + + + + 1 + + + + + ProjectExplorer.Project.Target.0 + + Desktop + Desktop + {3d7af99e-d2b7-4536-ac05-c1dba2e378bf} + 0 + 0 + 0 + + false + d:\mo_build\build\modorganizer_super\game_fallout4\edit + + + + + false + + true + Make + + CMakeProjectManager.MakeStep + + + + + install + + false + + true + Make + + CMakeProjectManager.MakeStep + + 2 + Build + + ProjectExplorer.BuildSteps.Build + + + + clean + + true + + true + Make + + CMakeProjectManager.MakeStep + + 1 + Clean + + ProjectExplorer.BuildSteps.Clean + + 2 + false + + all + + CMakeProjectManager.CMakeBuildConfiguration + + 1 + + + 0 + Deploy + + ProjectExplorer.BuildSteps.Deploy + + 1 + Deploy locally + + ProjectExplorer.DefaultDeployConfiguration + + 1 + + + + false + false + false + false + true + 0.01 + 10 + true + 1 + 25 + + 1 + true + false + true + valgrind + + 0 + 1 + 2 + 3 + 4 + 5 + 6 + 7 + 8 + 9 + 10 + 11 + 12 + 13 + 14 + + 2 + + + + false + %{buildDir} + Custom Executable + + ProjectExplorer.CustomExecutableRunConfiguration + 3768 + false + true + false + false + true + + 1 + + + + ProjectExplorer.Project.TargetCount + 1 + + + ProjectExplorer.Project.Updater.FileVersion + 18 + + + Version + 18 + + diff --git a/src/games/fallout4vr/src/CMakeLists.txt b/src/games/fallout4vr/src/CMakeLists.txt new file mode 100644 index 00000000..15136936 --- /dev/null +++ b/src/games/fallout4vr/src/CMakeLists.txt @@ -0,0 +1,55 @@ +CMAKE_MINIMUM_REQUIRED (VERSION 2.8) + +CMAKE_POLICY(SET CMP0020 NEW) + +FILE(GLOB ${PROJ_NAME}_SRCS *.cpp) +FILE(GLOB ${PROJ_NAME}_HDRS *.h) +FILE(GLOB ${PROJ_NAME}_FORMS *.ui) + + +SET(CMAKE_INCLUDE_CURRENT_DIR ON) +SET(CMAKE_AUTOMOC ON) +SET(CMAKE_AUTOUIC ON) +FIND_PACKAGE(Qt5Widgets REQUIRED) +QT5_WRAP_UI(${PROJ_NAME}_UIHDRS ${${PROJ_NAME}_FORMS}) + +SET(Boost_USE_STATIC_LIBS ON) +SET(Boost_USE_MULTITHREADED ON) +SET(Boost_USE_STATIC_RUNTIME OFF) +FIND_PACKAGE(Boost) + +IF (Boost_FOUND) + INCLUDE_DIRECTORIES(${Boost_INCLUDE_DIRS}) +ENDIF () + +SET(default_project_path "${CMAKE_SOURCE_DIR}/..") +GET_FILENAME_COMPONENT(${default_project_path} ${default_project_path} REALPATH) + +SET(project_path "${default_project_path}" CACHE PATH "path to the other mo projects") +SET(lib_path "${project_path}/../../install/libs") + +INCLUDE_DIRECTORIES(${project_path}/uibase/src + ${project_path}/game_features/src + ${project_path}/game_gamebryo/src) +LINK_DIRECTORIES(${project_path}/uibase/build/src + ${lib_path}) + + +ADD_LIBRARY(${PROJ_NAME} SHARED ${${PROJ_NAME}_HDRS} ${${PROJ_NAME}_SRCS} ${${PROJ_NAME}_UIHDRS}) +TARGET_LINK_LIBRARIES(${PROJ_NAME} + Qt5::Widgets + ${Boost_LIBRARIES} + uibase + game_gamebryo) + +SET_TARGET_PROPERTIES(${PROJ_NAME} PROPERTIES COMPILE_FLAGS /GL) +SET_TARGET_PROPERTIES(${PROJ_NAME} PROPERTIES LINK_FLAGS_RELWITHDEBINFO "/LTCG /LARGEADDRESSAWARE /OPT:REF /OPT:ICF") + +QT5_USE_MODULES(${PROJ_NAME} Widgets) + +############### +## Installation + +INSTALL(TARGETS ${PROJ_NAME} + RUNTIME DESTINATION bin/plugins) +INSTALL(FILES ${CMAKE_CURRENT_BINARY_DIR}/${PROJ_NAME}.pdb DESTINATION pdb) diff --git a/src/games/fallout4vr/src/SConscript b/src/games/fallout4vr/src/SConscript new file mode 100644 index 00000000..c45b0341 --- /dev/null +++ b/src/games/fallout4vr/src/SConscript @@ -0,0 +1,14 @@ +Import('qt_env') + +env = qt_env.Clone() + +# Shouldn't this be GAMEFALLOUT3_LIBRARY +env.AppendUnique(CPPDEFINES = [ 'GAMEFALLOUTNV_LIBRARY' ]) + +env.RequiresGamebryo() + +lib = env.SharedLibrary('gameFallout4', env.Glob('*.cpp')) +env.InstallModule(lib) + +res = env['QT_USED_MODULES'] +Return('res') diff --git a/src/games/fallout4vr/src/fallout4dataarchives.cpp b/src/games/fallout4vr/src/fallout4dataarchives.cpp new file mode 100644 index 00000000..e2ed39e2 --- /dev/null +++ b/src/games/fallout4vr/src/fallout4dataarchives.cpp @@ -0,0 +1,53 @@ +#include "fallout4dataarchives.h" +#include +#include + + +QStringList Fallout4DataArchives::vanillaArchives() const +{ + return { "Fallout4 - Textures1.ba2" + , "Fallout4 - Textures2.ba2" + , "Fallout4 - Textures3.ba2" + , "Fallout4 - Textures4.ba2" + , "Fallout4 - Textures5.ba2" + , "Fallout4 - Textures6.ba2" + , "Fallout4 - Textures7.ba2" + , "Fallout4 - Textures8.ba2" + , "Fallout4 - Textures9.ba2" + , "Fallout4 - Meshes.ba2" + , "Fallout4 - MeshesExtra.ba2" + , "Fallout4 - Voices.ba2" + , "Fallout4 - Sounds.ba2" + , "Fallout4 - Interface.ba2" + , "Fallout4 - Animations.ba2" + , "Fallout4 - Materials.ba2" + , "Fallout4 - Shaders.ba2" + , "Fallout4 - Startup.ba2" + , "Fallout4 - Misc.ba2" }; +} + + +QStringList Fallout4DataArchives::archives(const MOBase::IProfile *profile) const +{ + QStringList result; + + QString iniFile = QDir(profile->absolutePath()).absoluteFilePath("fallout4.ini"); + result.append(getArchivesFromKey(iniFile, "SResourceArchiveList")); + result.append(getArchivesFromKey(iniFile, "SResourceArchiveList2")); + + return result; +} + +void Fallout4DataArchives::writeArchiveList(MOBase::IProfile *profile, const QStringList &before) +{ + QString list = before.join(", "); + + QString iniFile = QDir(profile->absolutePath()).absoluteFilePath("fallout4.ini"); + if (list.length() > 255) { + int splitIdx = list.lastIndexOf(",", 256); + setArchivesToKey(iniFile, "SResourceArchiveList", list.mid(0, splitIdx)); + setArchivesToKey(iniFile, "SResourceArchiveList2", list.mid(splitIdx + 2)); + } else { + setArchivesToKey(iniFile, "SResourceArchiveList", list); + } +} diff --git a/src/games/fallout4vr/src/fallout4dataarchives.h b/src/games/fallout4vr/src/fallout4dataarchives.h new file mode 100644 index 00000000..47c08c52 --- /dev/null +++ b/src/games/fallout4vr/src/fallout4dataarchives.h @@ -0,0 +1,24 @@ +#ifndef FALLOUT3DATAARCHIVES_H +#define FALLOUT3DATAARCHIVES_H + + +#include +#include +#include +#include + +class Fallout4DataArchives : public GamebryoDataArchives +{ + +public: + + 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 // FALLOUT3DATAARCHIVES_H diff --git a/src/games/fallout4vr/src/fallout4scriptextender.cpp b/src/games/fallout4vr/src/fallout4scriptextender.cpp new file mode 100644 index 00000000..ae2fcc96 --- /dev/null +++ b/src/games/fallout4vr/src/fallout4scriptextender.cpp @@ -0,0 +1,7 @@ +#include "fallout3scriptextender.h" + + +QString Fallout4ScriptExtender::name() const +{ + return "f4se"; +} diff --git a/src/games/fallout4vr/src/fallout4scriptextender.h b/src/games/fallout4vr/src/fallout4scriptextender.h new file mode 100644 index 00000000..d850bfd1 --- /dev/null +++ b/src/games/fallout4vr/src/fallout4scriptextender.h @@ -0,0 +1,14 @@ +#ifndef FALLOUT3SCRIPTEXTENDER_H +#define FALLOUT3SCRIPTEXTENDER_H + + +#include + + +class Fallout4ScriptExtender : public ScriptExtender +{ +public: + virtual QString name() const override; +}; + +#endif // FALLOUT3SCRIPTEXTENDER_H diff --git a/src/games/fallout4vr/src/gamefallout4.cpp b/src/games/fallout4vr/src/gamefallout4.cpp new file mode 100644 index 00000000..9b919c14 --- /dev/null +++ b/src/games/fallout4vr/src/gamefallout4.cpp @@ -0,0 +1,163 @@ +#include "gameFallout4.h" +#include +#include +#include +#include +#include +#include +#include +#include + + +using namespace MOBase; + + +GameFallout4::GameFallout4() +{ +} + +bool GameFallout4::init(IOrganizer *moInfo) +{ + if (!GameGamebryo::init(moInfo)) { + return false; + } + m_ScriptExtender = std::shared_ptr(new Fallout4ScriptExtender()); + m_DataArchives = std::shared_ptr(new Fallout4DataArchives()); + m_BSAInvalidation = std::shared_ptr(new Fallout4BSAInvalidation(m_DataArchives, moInfo)); + return true; +} + +QString GameFallout4::identifyGamePath() const +{ + return findInRegistry(HKEY_LOCAL_MACHINE, L"Software\\Bethesda Softworks\\Fallout4", L"Installed Path"); +} + +QString GameFallout4::gameName() const +{ + return "Fallout 4"; +} + +QString GameFallout4::localAppFolder() const +{ + QString result = getKnownFolderPath(FOLDERID_LocalAppData, false); + if (result.isEmpty()) { + // fallback: try the registry + result = getSpecialPath("Local AppData"); + } + + return result; +} + +QString GameFallout4::myGamesFolderName() const +{ + return "Fallout4"; +} + +QList GameFallout4::executables() +{ + return QList() + << ExecutableInfo("F4SE", findInGameFolder("f4se_loader.exe")) + << ExecutableInfo("Fallout 4", findInGameFolder("Fallout4.exe")) + << ExecutableInfo("Fallout Launcher", findInGameFolder("Fallout4Launcher.exe")) + << ExecutableInfo("LOOT", getLootPath()); + ; +} + +QString GameFallout4::name() const +{ + return "Fallout4 Support Plugin"; +} + +QString GameFallout4::author() const +{ + return "Tannin"; +} + +QString GameFallout4::description() const +{ + return tr("Adds support for the game Fallout 4"); +} + +MOBase::VersionInfo GameFallout4::version() const +{ + return VersionInfo(0, 1, 0, VersionInfo::RELEASE_BETA); +} + +bool GameFallout4::isActive() const +{ + return true; +} + +QList GameFallout4::settings() const +{ + return QList(); +} + +void GameFallout4::copyToProfile(const QString &sourcePath, const QDir &destinationDirectory, + const QString &sourceFileName, const QString &destinationFileName) const +{ + QString filePath = destinationDirectory.absoluteFilePath(destinationFileName.isEmpty() ? sourceFileName + : destinationFileName); + if (!QFileInfo(filePath).exists()) { + if (!shellCopy(sourcePath + "/" + sourceFileName, filePath)) { + // if copy file fails, create the file empty + QFile(filePath).open(QIODevice::WriteOnly); + } + } +} + +void GameFallout4::initializeProfile(const QDir &path, ProfileSettings settings) const +{ + if (settings.testFlag(IPluginGame::MODS)) { + copyToProfile(localAppFolder() + "/Fallout4", path, "plugins.txt"); + copyToProfile(localAppFolder() + "/Fallout4", path, "loadorder.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"); + } +} + +QString GameFallout4::savegameExtension() const +{ + return "fos"; +} + +QString GameFallout4::steamAPPId() const +{ + return "377160"; +} + +QStringList GameFallout4::getPrimaryPlugins() +{ + return { "fallout4.esm" }; +} + +QIcon GameFallout4::gameIcon() const +{ + return MOBase::iconForExecutable(gameDirectory().absoluteFilePath("Fallout4.exe")); +} + +const std::map &GameFallout4::featureList() const +{ + static std::map result { + { typeid(BSAInvalidation), m_BSAInvalidation.get() }, + { typeid(ScriptExtender), m_ScriptExtender.get() }, + { typeid(DataArchives), m_DataArchives.get() } + }; + + return result; +} + + +QStringList GameFallout4::gameVariants() const +{ + return { "Regular" }; +} diff --git a/src/games/fallout4vr/src/gamefallout4.h b/src/games/fallout4vr/src/gamefallout4.h new file mode 100644 index 00000000..d0bc90eb --- /dev/null +++ b/src/games/fallout4vr/src/gamefallout4.h @@ -0,0 +1,65 @@ +#ifndef GAMEFALLOUT4_H +#define GAMEFALLOUT4_H + + +#include "fallout4bsainvalidation.h" +#include "fallout4scriptextender.h" +#include "fallout4dataarchives.h" +#include +#include + + +class GameFallout4 : public GameGamebryo +{ + Q_OBJECT +#if QT_VERSION >= QT_VERSION_CHECK(5,0,0) + Q_PLUGIN_METADATA(IID "org.tannin.GameFallout4" FILE "gamefallout4.json") +#endif + +public: + + GameFallout4(); + + virtual bool init(MOBase::IOrganizer *moInfo) override; + +public: // IPluginGame interface + + virtual QString gameName() const; + virtual QList executables(); + virtual void initializeProfile(const QDir &path, ProfileSettings settings) const; + virtual QString savegameExtension() const; + virtual QString steamAPPId() const; + virtual QStringList getPrimaryPlugins(); + virtual QIcon gameIcon() const override; + virtual QStringList gameVariants() const; + +public: // IPlugin interface + + virtual QString name() const; + virtual QString author() const; + virtual QString description() const; + virtual MOBase::VersionInfo version() const; + virtual bool isActive() const; + virtual QList settings() const; + +protected: + + virtual const std::map &featureList() const; + +private: + + virtual QString identifyGamePath() const override; + virtual QString myGamesFolderName() const override; + + QString localAppFolder() const; + void copyToProfile(const QString &sourcePath, const QDir &destinationDirectory, + const QString &sourceFileName, const QString &destinationFileName = QString()) const; + +private: + + std::shared_ptr m_ScriptExtender { nullptr }; + std::shared_ptr m_DataArchives { nullptr }; + +}; + +#endif // GAMEFallout4_H diff --git a/src/games/fallout4vr/src/gamefallout4.json b/src/games/fallout4vr/src/gamefallout4.json new file mode 100644 index 00000000..0967ef42 --- /dev/null +++ b/src/games/fallout4vr/src/gamefallout4.json @@ -0,0 +1 @@ +{} From e5ad655643b628eaeac10543ff25358a75545c72 Mon Sep 17 00:00:00 2001 From: Tannin Date: Tue, 17 Nov 2015 20:59:34 +0100 Subject: [PATCH 0060/1544] [game_fallout76] initial commit --- src/games/fallout76/.gitignore | 4 + src/games/fallout76/CMakeLists.txt | 15 ++ src/games/fallout76/CMakeLists.txt.user | 207 ++++++++++++++++++ src/games/fallout76/src/CMakeLists.txt | 55 +++++ src/games/fallout76/src/SConscript | 14 ++ .../fallout76/src/fallout4dataarchives.cpp | 53 +++++ .../fallout76/src/fallout4dataarchives.h | 24 ++ .../fallout76/src/fallout4scriptextender.cpp | 7 + .../fallout76/src/fallout4scriptextender.h | 14 ++ src/games/fallout76/src/gamefallout4.cpp | 163 ++++++++++++++ src/games/fallout76/src/gamefallout4.h | 65 ++++++ src/games/fallout76/src/gamefallout4.json | 1 + 12 files changed, 622 insertions(+) create mode 100644 src/games/fallout76/.gitignore create mode 100644 src/games/fallout76/CMakeLists.txt create mode 100644 src/games/fallout76/CMakeLists.txt.user create mode 100644 src/games/fallout76/src/CMakeLists.txt create mode 100644 src/games/fallout76/src/SConscript create mode 100644 src/games/fallout76/src/fallout4dataarchives.cpp create mode 100644 src/games/fallout76/src/fallout4dataarchives.h create mode 100644 src/games/fallout76/src/fallout4scriptextender.cpp create mode 100644 src/games/fallout76/src/fallout4scriptextender.h create mode 100644 src/games/fallout76/src/gamefallout4.cpp create mode 100644 src/games/fallout76/src/gamefallout4.h create mode 100644 src/games/fallout76/src/gamefallout4.json diff --git a/src/games/fallout76/.gitignore b/src/games/fallout76/.gitignore new file mode 100644 index 00000000..bcc50d34 --- /dev/null +++ b/src/games/fallout76/.gitignore @@ -0,0 +1,4 @@ +CMakeLists.txt.user +edit +build +std*.log diff --git a/src/games/fallout76/CMakeLists.txt b/src/games/fallout76/CMakeLists.txt new file mode 100644 index 00000000..64470f51 --- /dev/null +++ b/src/games/fallout76/CMakeLists.txt @@ -0,0 +1,15 @@ +CMAKE_MINIMUM_REQUIRED(VERSION 2.8) + +SET(PROJ_NAME gameFallout4) + +PROJECT(${PROJ_NAME}) + +SET(DEPENDENCIES_DIR CACHE PATH "") + +# hint to find qt in dependencies path +LIST(APPEND CMAKE_PREFIX_PATH ${DEPENDENCIES_DIR}/qt5/lib/cmake) + +FILE(GLOB_RECURSE BOOST_ROOT ${DEPENDENCIES_DIR}/boost*/project-config.jam) +GET_FILENAME_COMPONENT(BOOST_ROOT ${BOOST_ROOT} DIRECTORY) + +ADD_SUBDIRECTORY(src) diff --git a/src/games/fallout76/CMakeLists.txt.user b/src/games/fallout76/CMakeLists.txt.user new file mode 100644 index 00000000..a177254f --- /dev/null +++ b/src/games/fallout76/CMakeLists.txt.user @@ -0,0 +1,207 @@ + + + + + + EnvironmentId + {be93058c-4cdc-4db3-a586-0930ff4430c6} + + + ProjectExplorer.Project.ActiveTarget + 0 + + + ProjectExplorer.Project.EditorSettings + + true + false + true + + Cpp + + CppGlobal + + + + QmlJS + + QmlJSGlobal + + + 2 + UTF-8 + false + 4 + false + 80 + true + true + 1 + true + false + 0 + true + 0 + 8 + true + 1 + true + true + true + false + + + + ProjectExplorer.Project.PluginSettings + + + + 1 + + + + + ProjectExplorer.Project.Target.0 + + Desktop + Desktop + {3d7af99e-d2b7-4536-ac05-c1dba2e378bf} + 0 + 0 + 0 + + false + d:\mo_build\build\modorganizer_super\game_fallout4\edit + + + + + false + + true + Make + + CMakeProjectManager.MakeStep + + + + + install + + false + + true + Make + + CMakeProjectManager.MakeStep + + 2 + Build + + ProjectExplorer.BuildSteps.Build + + + + clean + + true + + true + Make + + CMakeProjectManager.MakeStep + + 1 + Clean + + ProjectExplorer.BuildSteps.Clean + + 2 + false + + all + + CMakeProjectManager.CMakeBuildConfiguration + + 1 + + + 0 + Deploy + + ProjectExplorer.BuildSteps.Deploy + + 1 + Deploy locally + + ProjectExplorer.DefaultDeployConfiguration + + 1 + + + + false + false + false + false + true + 0.01 + 10 + true + 1 + 25 + + 1 + true + false + true + valgrind + + 0 + 1 + 2 + 3 + 4 + 5 + 6 + 7 + 8 + 9 + 10 + 11 + 12 + 13 + 14 + + 2 + + + + false + %{buildDir} + Custom Executable + + ProjectExplorer.CustomExecutableRunConfiguration + 3768 + false + true + false + false + true + + 1 + + + + ProjectExplorer.Project.TargetCount + 1 + + + ProjectExplorer.Project.Updater.FileVersion + 18 + + + Version + 18 + + diff --git a/src/games/fallout76/src/CMakeLists.txt b/src/games/fallout76/src/CMakeLists.txt new file mode 100644 index 00000000..15136936 --- /dev/null +++ b/src/games/fallout76/src/CMakeLists.txt @@ -0,0 +1,55 @@ +CMAKE_MINIMUM_REQUIRED (VERSION 2.8) + +CMAKE_POLICY(SET CMP0020 NEW) + +FILE(GLOB ${PROJ_NAME}_SRCS *.cpp) +FILE(GLOB ${PROJ_NAME}_HDRS *.h) +FILE(GLOB ${PROJ_NAME}_FORMS *.ui) + + +SET(CMAKE_INCLUDE_CURRENT_DIR ON) +SET(CMAKE_AUTOMOC ON) +SET(CMAKE_AUTOUIC ON) +FIND_PACKAGE(Qt5Widgets REQUIRED) +QT5_WRAP_UI(${PROJ_NAME}_UIHDRS ${${PROJ_NAME}_FORMS}) + +SET(Boost_USE_STATIC_LIBS ON) +SET(Boost_USE_MULTITHREADED ON) +SET(Boost_USE_STATIC_RUNTIME OFF) +FIND_PACKAGE(Boost) + +IF (Boost_FOUND) + INCLUDE_DIRECTORIES(${Boost_INCLUDE_DIRS}) +ENDIF () + +SET(default_project_path "${CMAKE_SOURCE_DIR}/..") +GET_FILENAME_COMPONENT(${default_project_path} ${default_project_path} REALPATH) + +SET(project_path "${default_project_path}" CACHE PATH "path to the other mo projects") +SET(lib_path "${project_path}/../../install/libs") + +INCLUDE_DIRECTORIES(${project_path}/uibase/src + ${project_path}/game_features/src + ${project_path}/game_gamebryo/src) +LINK_DIRECTORIES(${project_path}/uibase/build/src + ${lib_path}) + + +ADD_LIBRARY(${PROJ_NAME} SHARED ${${PROJ_NAME}_HDRS} ${${PROJ_NAME}_SRCS} ${${PROJ_NAME}_UIHDRS}) +TARGET_LINK_LIBRARIES(${PROJ_NAME} + Qt5::Widgets + ${Boost_LIBRARIES} + uibase + game_gamebryo) + +SET_TARGET_PROPERTIES(${PROJ_NAME} PROPERTIES COMPILE_FLAGS /GL) +SET_TARGET_PROPERTIES(${PROJ_NAME} PROPERTIES LINK_FLAGS_RELWITHDEBINFO "/LTCG /LARGEADDRESSAWARE /OPT:REF /OPT:ICF") + +QT5_USE_MODULES(${PROJ_NAME} Widgets) + +############### +## Installation + +INSTALL(TARGETS ${PROJ_NAME} + RUNTIME DESTINATION bin/plugins) +INSTALL(FILES ${CMAKE_CURRENT_BINARY_DIR}/${PROJ_NAME}.pdb DESTINATION pdb) diff --git a/src/games/fallout76/src/SConscript b/src/games/fallout76/src/SConscript new file mode 100644 index 00000000..c45b0341 --- /dev/null +++ b/src/games/fallout76/src/SConscript @@ -0,0 +1,14 @@ +Import('qt_env') + +env = qt_env.Clone() + +# Shouldn't this be GAMEFALLOUT3_LIBRARY +env.AppendUnique(CPPDEFINES = [ 'GAMEFALLOUTNV_LIBRARY' ]) + +env.RequiresGamebryo() + +lib = env.SharedLibrary('gameFallout4', env.Glob('*.cpp')) +env.InstallModule(lib) + +res = env['QT_USED_MODULES'] +Return('res') diff --git a/src/games/fallout76/src/fallout4dataarchives.cpp b/src/games/fallout76/src/fallout4dataarchives.cpp new file mode 100644 index 00000000..e2ed39e2 --- /dev/null +++ b/src/games/fallout76/src/fallout4dataarchives.cpp @@ -0,0 +1,53 @@ +#include "fallout4dataarchives.h" +#include +#include + + +QStringList Fallout4DataArchives::vanillaArchives() const +{ + return { "Fallout4 - Textures1.ba2" + , "Fallout4 - Textures2.ba2" + , "Fallout4 - Textures3.ba2" + , "Fallout4 - Textures4.ba2" + , "Fallout4 - Textures5.ba2" + , "Fallout4 - Textures6.ba2" + , "Fallout4 - Textures7.ba2" + , "Fallout4 - Textures8.ba2" + , "Fallout4 - Textures9.ba2" + , "Fallout4 - Meshes.ba2" + , "Fallout4 - MeshesExtra.ba2" + , "Fallout4 - Voices.ba2" + , "Fallout4 - Sounds.ba2" + , "Fallout4 - Interface.ba2" + , "Fallout4 - Animations.ba2" + , "Fallout4 - Materials.ba2" + , "Fallout4 - Shaders.ba2" + , "Fallout4 - Startup.ba2" + , "Fallout4 - Misc.ba2" }; +} + + +QStringList Fallout4DataArchives::archives(const MOBase::IProfile *profile) const +{ + QStringList result; + + QString iniFile = QDir(profile->absolutePath()).absoluteFilePath("fallout4.ini"); + result.append(getArchivesFromKey(iniFile, "SResourceArchiveList")); + result.append(getArchivesFromKey(iniFile, "SResourceArchiveList2")); + + return result; +} + +void Fallout4DataArchives::writeArchiveList(MOBase::IProfile *profile, const QStringList &before) +{ + QString list = before.join(", "); + + QString iniFile = QDir(profile->absolutePath()).absoluteFilePath("fallout4.ini"); + if (list.length() > 255) { + int splitIdx = list.lastIndexOf(",", 256); + setArchivesToKey(iniFile, "SResourceArchiveList", list.mid(0, splitIdx)); + setArchivesToKey(iniFile, "SResourceArchiveList2", list.mid(splitIdx + 2)); + } else { + setArchivesToKey(iniFile, "SResourceArchiveList", list); + } +} diff --git a/src/games/fallout76/src/fallout4dataarchives.h b/src/games/fallout76/src/fallout4dataarchives.h new file mode 100644 index 00000000..47c08c52 --- /dev/null +++ b/src/games/fallout76/src/fallout4dataarchives.h @@ -0,0 +1,24 @@ +#ifndef FALLOUT3DATAARCHIVES_H +#define FALLOUT3DATAARCHIVES_H + + +#include +#include +#include +#include + +class Fallout4DataArchives : public GamebryoDataArchives +{ + +public: + + 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 // FALLOUT3DATAARCHIVES_H diff --git a/src/games/fallout76/src/fallout4scriptextender.cpp b/src/games/fallout76/src/fallout4scriptextender.cpp new file mode 100644 index 00000000..ae2fcc96 --- /dev/null +++ b/src/games/fallout76/src/fallout4scriptextender.cpp @@ -0,0 +1,7 @@ +#include "fallout3scriptextender.h" + + +QString Fallout4ScriptExtender::name() const +{ + return "f4se"; +} diff --git a/src/games/fallout76/src/fallout4scriptextender.h b/src/games/fallout76/src/fallout4scriptextender.h new file mode 100644 index 00000000..d850bfd1 --- /dev/null +++ b/src/games/fallout76/src/fallout4scriptextender.h @@ -0,0 +1,14 @@ +#ifndef FALLOUT3SCRIPTEXTENDER_H +#define FALLOUT3SCRIPTEXTENDER_H + + +#include + + +class Fallout4ScriptExtender : public ScriptExtender +{ +public: + virtual QString name() const override; +}; + +#endif // FALLOUT3SCRIPTEXTENDER_H diff --git a/src/games/fallout76/src/gamefallout4.cpp b/src/games/fallout76/src/gamefallout4.cpp new file mode 100644 index 00000000..9b919c14 --- /dev/null +++ b/src/games/fallout76/src/gamefallout4.cpp @@ -0,0 +1,163 @@ +#include "gameFallout4.h" +#include +#include +#include +#include +#include +#include +#include +#include + + +using namespace MOBase; + + +GameFallout4::GameFallout4() +{ +} + +bool GameFallout4::init(IOrganizer *moInfo) +{ + if (!GameGamebryo::init(moInfo)) { + return false; + } + m_ScriptExtender = std::shared_ptr(new Fallout4ScriptExtender()); + m_DataArchives = std::shared_ptr(new Fallout4DataArchives()); + m_BSAInvalidation = std::shared_ptr(new Fallout4BSAInvalidation(m_DataArchives, moInfo)); + return true; +} + +QString GameFallout4::identifyGamePath() const +{ + return findInRegistry(HKEY_LOCAL_MACHINE, L"Software\\Bethesda Softworks\\Fallout4", L"Installed Path"); +} + +QString GameFallout4::gameName() const +{ + return "Fallout 4"; +} + +QString GameFallout4::localAppFolder() const +{ + QString result = getKnownFolderPath(FOLDERID_LocalAppData, false); + if (result.isEmpty()) { + // fallback: try the registry + result = getSpecialPath("Local AppData"); + } + + return result; +} + +QString GameFallout4::myGamesFolderName() const +{ + return "Fallout4"; +} + +QList GameFallout4::executables() +{ + return QList() + << ExecutableInfo("F4SE", findInGameFolder("f4se_loader.exe")) + << ExecutableInfo("Fallout 4", findInGameFolder("Fallout4.exe")) + << ExecutableInfo("Fallout Launcher", findInGameFolder("Fallout4Launcher.exe")) + << ExecutableInfo("LOOT", getLootPath()); + ; +} + +QString GameFallout4::name() const +{ + return "Fallout4 Support Plugin"; +} + +QString GameFallout4::author() const +{ + return "Tannin"; +} + +QString GameFallout4::description() const +{ + return tr("Adds support for the game Fallout 4"); +} + +MOBase::VersionInfo GameFallout4::version() const +{ + return VersionInfo(0, 1, 0, VersionInfo::RELEASE_BETA); +} + +bool GameFallout4::isActive() const +{ + return true; +} + +QList GameFallout4::settings() const +{ + return QList(); +} + +void GameFallout4::copyToProfile(const QString &sourcePath, const QDir &destinationDirectory, + const QString &sourceFileName, const QString &destinationFileName) const +{ + QString filePath = destinationDirectory.absoluteFilePath(destinationFileName.isEmpty() ? sourceFileName + : destinationFileName); + if (!QFileInfo(filePath).exists()) { + if (!shellCopy(sourcePath + "/" + sourceFileName, filePath)) { + // if copy file fails, create the file empty + QFile(filePath).open(QIODevice::WriteOnly); + } + } +} + +void GameFallout4::initializeProfile(const QDir &path, ProfileSettings settings) const +{ + if (settings.testFlag(IPluginGame::MODS)) { + copyToProfile(localAppFolder() + "/Fallout4", path, "plugins.txt"); + copyToProfile(localAppFolder() + "/Fallout4", path, "loadorder.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"); + } +} + +QString GameFallout4::savegameExtension() const +{ + return "fos"; +} + +QString GameFallout4::steamAPPId() const +{ + return "377160"; +} + +QStringList GameFallout4::getPrimaryPlugins() +{ + return { "fallout4.esm" }; +} + +QIcon GameFallout4::gameIcon() const +{ + return MOBase::iconForExecutable(gameDirectory().absoluteFilePath("Fallout4.exe")); +} + +const std::map &GameFallout4::featureList() const +{ + static std::map result { + { typeid(BSAInvalidation), m_BSAInvalidation.get() }, + { typeid(ScriptExtender), m_ScriptExtender.get() }, + { typeid(DataArchives), m_DataArchives.get() } + }; + + return result; +} + + +QStringList GameFallout4::gameVariants() const +{ + return { "Regular" }; +} diff --git a/src/games/fallout76/src/gamefallout4.h b/src/games/fallout76/src/gamefallout4.h new file mode 100644 index 00000000..d0bc90eb --- /dev/null +++ b/src/games/fallout76/src/gamefallout4.h @@ -0,0 +1,65 @@ +#ifndef GAMEFALLOUT4_H +#define GAMEFALLOUT4_H + + +#include "fallout4bsainvalidation.h" +#include "fallout4scriptextender.h" +#include "fallout4dataarchives.h" +#include +#include + + +class GameFallout4 : public GameGamebryo +{ + Q_OBJECT +#if QT_VERSION >= QT_VERSION_CHECK(5,0,0) + Q_PLUGIN_METADATA(IID "org.tannin.GameFallout4" FILE "gamefallout4.json") +#endif + +public: + + GameFallout4(); + + virtual bool init(MOBase::IOrganizer *moInfo) override; + +public: // IPluginGame interface + + virtual QString gameName() const; + virtual QList executables(); + virtual void initializeProfile(const QDir &path, ProfileSettings settings) const; + virtual QString savegameExtension() const; + virtual QString steamAPPId() const; + virtual QStringList getPrimaryPlugins(); + virtual QIcon gameIcon() const override; + virtual QStringList gameVariants() const; + +public: // IPlugin interface + + virtual QString name() const; + virtual QString author() const; + virtual QString description() const; + virtual MOBase::VersionInfo version() const; + virtual bool isActive() const; + virtual QList settings() const; + +protected: + + virtual const std::map &featureList() const; + +private: + + virtual QString identifyGamePath() const override; + virtual QString myGamesFolderName() const override; + + QString localAppFolder() const; + void copyToProfile(const QString &sourcePath, const QDir &destinationDirectory, + const QString &sourceFileName, const QString &destinationFileName = QString()) const; + +private: + + std::shared_ptr m_ScriptExtender { nullptr }; + std::shared_ptr m_DataArchives { nullptr }; + +}; + +#endif // GAMEFallout4_H diff --git a/src/games/fallout76/src/gamefallout4.json b/src/games/fallout76/src/gamefallout4.json new file mode 100644 index 00000000..0967ef42 --- /dev/null +++ b/src/games/fallout76/src/gamefallout4.json @@ -0,0 +1 @@ +{} From 4ec519658dbec5fd0846596fcb7e73153ff0fc74 Mon Sep 17 00:00:00 2001 From: Tannin Date: Tue, 17 Nov 2015 20:59:34 +0100 Subject: [PATCH 0061/1544] [game_fallout4] initial commit --- src/games/fallout4/.gitignore | 4 + src/games/fallout4/CMakeLists.txt | 15 ++ src/games/fallout4/CMakeLists.txt.user | 207 ++++++++++++++++++ src/games/fallout4/src/CMakeLists.txt | 55 +++++ src/games/fallout4/src/SConscript | 14 ++ .../fallout4/src/fallout4dataarchives.cpp | 53 +++++ src/games/fallout4/src/fallout4dataarchives.h | 24 ++ .../fallout4/src/fallout4scriptextender.cpp | 7 + .../fallout4/src/fallout4scriptextender.h | 14 ++ src/games/fallout4/src/gamefallout4.cpp | 163 ++++++++++++++ src/games/fallout4/src/gamefallout4.h | 65 ++++++ src/games/fallout4/src/gamefallout4.json | 1 + 12 files changed, 622 insertions(+) create mode 100644 src/games/fallout4/.gitignore create mode 100644 src/games/fallout4/CMakeLists.txt create mode 100644 src/games/fallout4/CMakeLists.txt.user create mode 100644 src/games/fallout4/src/CMakeLists.txt create mode 100644 src/games/fallout4/src/SConscript create mode 100644 src/games/fallout4/src/fallout4dataarchives.cpp create mode 100644 src/games/fallout4/src/fallout4dataarchives.h create mode 100644 src/games/fallout4/src/fallout4scriptextender.cpp create mode 100644 src/games/fallout4/src/fallout4scriptextender.h create mode 100644 src/games/fallout4/src/gamefallout4.cpp create mode 100644 src/games/fallout4/src/gamefallout4.h create mode 100644 src/games/fallout4/src/gamefallout4.json diff --git a/src/games/fallout4/.gitignore b/src/games/fallout4/.gitignore new file mode 100644 index 00000000..bcc50d34 --- /dev/null +++ b/src/games/fallout4/.gitignore @@ -0,0 +1,4 @@ +CMakeLists.txt.user +edit +build +std*.log diff --git a/src/games/fallout4/CMakeLists.txt b/src/games/fallout4/CMakeLists.txt new file mode 100644 index 00000000..64470f51 --- /dev/null +++ b/src/games/fallout4/CMakeLists.txt @@ -0,0 +1,15 @@ +CMAKE_MINIMUM_REQUIRED(VERSION 2.8) + +SET(PROJ_NAME gameFallout4) + +PROJECT(${PROJ_NAME}) + +SET(DEPENDENCIES_DIR CACHE PATH "") + +# hint to find qt in dependencies path +LIST(APPEND CMAKE_PREFIX_PATH ${DEPENDENCIES_DIR}/qt5/lib/cmake) + +FILE(GLOB_RECURSE BOOST_ROOT ${DEPENDENCIES_DIR}/boost*/project-config.jam) +GET_FILENAME_COMPONENT(BOOST_ROOT ${BOOST_ROOT} DIRECTORY) + +ADD_SUBDIRECTORY(src) diff --git a/src/games/fallout4/CMakeLists.txt.user b/src/games/fallout4/CMakeLists.txt.user new file mode 100644 index 00000000..a177254f --- /dev/null +++ b/src/games/fallout4/CMakeLists.txt.user @@ -0,0 +1,207 @@ + + + + + + EnvironmentId + {be93058c-4cdc-4db3-a586-0930ff4430c6} + + + ProjectExplorer.Project.ActiveTarget + 0 + + + ProjectExplorer.Project.EditorSettings + + true + false + true + + Cpp + + CppGlobal + + + + QmlJS + + QmlJSGlobal + + + 2 + UTF-8 + false + 4 + false + 80 + true + true + 1 + true + false + 0 + true + 0 + 8 + true + 1 + true + true + true + false + + + + ProjectExplorer.Project.PluginSettings + + + + 1 + + + + + ProjectExplorer.Project.Target.0 + + Desktop + Desktop + {3d7af99e-d2b7-4536-ac05-c1dba2e378bf} + 0 + 0 + 0 + + false + d:\mo_build\build\modorganizer_super\game_fallout4\edit + + + + + false + + true + Make + + CMakeProjectManager.MakeStep + + + + + install + + false + + true + Make + + CMakeProjectManager.MakeStep + + 2 + Build + + ProjectExplorer.BuildSteps.Build + + + + clean + + true + + true + Make + + CMakeProjectManager.MakeStep + + 1 + Clean + + ProjectExplorer.BuildSteps.Clean + + 2 + false + + all + + CMakeProjectManager.CMakeBuildConfiguration + + 1 + + + 0 + Deploy + + ProjectExplorer.BuildSteps.Deploy + + 1 + Deploy locally + + ProjectExplorer.DefaultDeployConfiguration + + 1 + + + + false + false + false + false + true + 0.01 + 10 + true + 1 + 25 + + 1 + true + false + true + valgrind + + 0 + 1 + 2 + 3 + 4 + 5 + 6 + 7 + 8 + 9 + 10 + 11 + 12 + 13 + 14 + + 2 + + + + false + %{buildDir} + Custom Executable + + ProjectExplorer.CustomExecutableRunConfiguration + 3768 + false + true + false + false + true + + 1 + + + + ProjectExplorer.Project.TargetCount + 1 + + + ProjectExplorer.Project.Updater.FileVersion + 18 + + + Version + 18 + + diff --git a/src/games/fallout4/src/CMakeLists.txt b/src/games/fallout4/src/CMakeLists.txt new file mode 100644 index 00000000..15136936 --- /dev/null +++ b/src/games/fallout4/src/CMakeLists.txt @@ -0,0 +1,55 @@ +CMAKE_MINIMUM_REQUIRED (VERSION 2.8) + +CMAKE_POLICY(SET CMP0020 NEW) + +FILE(GLOB ${PROJ_NAME}_SRCS *.cpp) +FILE(GLOB ${PROJ_NAME}_HDRS *.h) +FILE(GLOB ${PROJ_NAME}_FORMS *.ui) + + +SET(CMAKE_INCLUDE_CURRENT_DIR ON) +SET(CMAKE_AUTOMOC ON) +SET(CMAKE_AUTOUIC ON) +FIND_PACKAGE(Qt5Widgets REQUIRED) +QT5_WRAP_UI(${PROJ_NAME}_UIHDRS ${${PROJ_NAME}_FORMS}) + +SET(Boost_USE_STATIC_LIBS ON) +SET(Boost_USE_MULTITHREADED ON) +SET(Boost_USE_STATIC_RUNTIME OFF) +FIND_PACKAGE(Boost) + +IF (Boost_FOUND) + INCLUDE_DIRECTORIES(${Boost_INCLUDE_DIRS}) +ENDIF () + +SET(default_project_path "${CMAKE_SOURCE_DIR}/..") +GET_FILENAME_COMPONENT(${default_project_path} ${default_project_path} REALPATH) + +SET(project_path "${default_project_path}" CACHE PATH "path to the other mo projects") +SET(lib_path "${project_path}/../../install/libs") + +INCLUDE_DIRECTORIES(${project_path}/uibase/src + ${project_path}/game_features/src + ${project_path}/game_gamebryo/src) +LINK_DIRECTORIES(${project_path}/uibase/build/src + ${lib_path}) + + +ADD_LIBRARY(${PROJ_NAME} SHARED ${${PROJ_NAME}_HDRS} ${${PROJ_NAME}_SRCS} ${${PROJ_NAME}_UIHDRS}) +TARGET_LINK_LIBRARIES(${PROJ_NAME} + Qt5::Widgets + ${Boost_LIBRARIES} + uibase + game_gamebryo) + +SET_TARGET_PROPERTIES(${PROJ_NAME} PROPERTIES COMPILE_FLAGS /GL) +SET_TARGET_PROPERTIES(${PROJ_NAME} PROPERTIES LINK_FLAGS_RELWITHDEBINFO "/LTCG /LARGEADDRESSAWARE /OPT:REF /OPT:ICF") + +QT5_USE_MODULES(${PROJ_NAME} Widgets) + +############### +## Installation + +INSTALL(TARGETS ${PROJ_NAME} + RUNTIME DESTINATION bin/plugins) +INSTALL(FILES ${CMAKE_CURRENT_BINARY_DIR}/${PROJ_NAME}.pdb DESTINATION pdb) diff --git a/src/games/fallout4/src/SConscript b/src/games/fallout4/src/SConscript new file mode 100644 index 00000000..c45b0341 --- /dev/null +++ b/src/games/fallout4/src/SConscript @@ -0,0 +1,14 @@ +Import('qt_env') + +env = qt_env.Clone() + +# Shouldn't this be GAMEFALLOUT3_LIBRARY +env.AppendUnique(CPPDEFINES = [ 'GAMEFALLOUTNV_LIBRARY' ]) + +env.RequiresGamebryo() + +lib = env.SharedLibrary('gameFallout4', env.Glob('*.cpp')) +env.InstallModule(lib) + +res = env['QT_USED_MODULES'] +Return('res') diff --git a/src/games/fallout4/src/fallout4dataarchives.cpp b/src/games/fallout4/src/fallout4dataarchives.cpp new file mode 100644 index 00000000..e2ed39e2 --- /dev/null +++ b/src/games/fallout4/src/fallout4dataarchives.cpp @@ -0,0 +1,53 @@ +#include "fallout4dataarchives.h" +#include +#include + + +QStringList Fallout4DataArchives::vanillaArchives() const +{ + return { "Fallout4 - Textures1.ba2" + , "Fallout4 - Textures2.ba2" + , "Fallout4 - Textures3.ba2" + , "Fallout4 - Textures4.ba2" + , "Fallout4 - Textures5.ba2" + , "Fallout4 - Textures6.ba2" + , "Fallout4 - Textures7.ba2" + , "Fallout4 - Textures8.ba2" + , "Fallout4 - Textures9.ba2" + , "Fallout4 - Meshes.ba2" + , "Fallout4 - MeshesExtra.ba2" + , "Fallout4 - Voices.ba2" + , "Fallout4 - Sounds.ba2" + , "Fallout4 - Interface.ba2" + , "Fallout4 - Animations.ba2" + , "Fallout4 - Materials.ba2" + , "Fallout4 - Shaders.ba2" + , "Fallout4 - Startup.ba2" + , "Fallout4 - Misc.ba2" }; +} + + +QStringList Fallout4DataArchives::archives(const MOBase::IProfile *profile) const +{ + QStringList result; + + QString iniFile = QDir(profile->absolutePath()).absoluteFilePath("fallout4.ini"); + result.append(getArchivesFromKey(iniFile, "SResourceArchiveList")); + result.append(getArchivesFromKey(iniFile, "SResourceArchiveList2")); + + return result; +} + +void Fallout4DataArchives::writeArchiveList(MOBase::IProfile *profile, const QStringList &before) +{ + QString list = before.join(", "); + + QString iniFile = QDir(profile->absolutePath()).absoluteFilePath("fallout4.ini"); + if (list.length() > 255) { + int splitIdx = list.lastIndexOf(",", 256); + setArchivesToKey(iniFile, "SResourceArchiveList", list.mid(0, splitIdx)); + setArchivesToKey(iniFile, "SResourceArchiveList2", list.mid(splitIdx + 2)); + } else { + setArchivesToKey(iniFile, "SResourceArchiveList", list); + } +} diff --git a/src/games/fallout4/src/fallout4dataarchives.h b/src/games/fallout4/src/fallout4dataarchives.h new file mode 100644 index 00000000..47c08c52 --- /dev/null +++ b/src/games/fallout4/src/fallout4dataarchives.h @@ -0,0 +1,24 @@ +#ifndef FALLOUT3DATAARCHIVES_H +#define FALLOUT3DATAARCHIVES_H + + +#include +#include +#include +#include + +class Fallout4DataArchives : public GamebryoDataArchives +{ + +public: + + 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 // FALLOUT3DATAARCHIVES_H diff --git a/src/games/fallout4/src/fallout4scriptextender.cpp b/src/games/fallout4/src/fallout4scriptextender.cpp new file mode 100644 index 00000000..ae2fcc96 --- /dev/null +++ b/src/games/fallout4/src/fallout4scriptextender.cpp @@ -0,0 +1,7 @@ +#include "fallout3scriptextender.h" + + +QString Fallout4ScriptExtender::name() const +{ + return "f4se"; +} diff --git a/src/games/fallout4/src/fallout4scriptextender.h b/src/games/fallout4/src/fallout4scriptextender.h new file mode 100644 index 00000000..d850bfd1 --- /dev/null +++ b/src/games/fallout4/src/fallout4scriptextender.h @@ -0,0 +1,14 @@ +#ifndef FALLOUT3SCRIPTEXTENDER_H +#define FALLOUT3SCRIPTEXTENDER_H + + +#include + + +class Fallout4ScriptExtender : public ScriptExtender +{ +public: + virtual QString name() const override; +}; + +#endif // FALLOUT3SCRIPTEXTENDER_H diff --git a/src/games/fallout4/src/gamefallout4.cpp b/src/games/fallout4/src/gamefallout4.cpp new file mode 100644 index 00000000..9b919c14 --- /dev/null +++ b/src/games/fallout4/src/gamefallout4.cpp @@ -0,0 +1,163 @@ +#include "gameFallout4.h" +#include +#include +#include +#include +#include +#include +#include +#include + + +using namespace MOBase; + + +GameFallout4::GameFallout4() +{ +} + +bool GameFallout4::init(IOrganizer *moInfo) +{ + if (!GameGamebryo::init(moInfo)) { + return false; + } + m_ScriptExtender = std::shared_ptr(new Fallout4ScriptExtender()); + m_DataArchives = std::shared_ptr(new Fallout4DataArchives()); + m_BSAInvalidation = std::shared_ptr(new Fallout4BSAInvalidation(m_DataArchives, moInfo)); + return true; +} + +QString GameFallout4::identifyGamePath() const +{ + return findInRegistry(HKEY_LOCAL_MACHINE, L"Software\\Bethesda Softworks\\Fallout4", L"Installed Path"); +} + +QString GameFallout4::gameName() const +{ + return "Fallout 4"; +} + +QString GameFallout4::localAppFolder() const +{ + QString result = getKnownFolderPath(FOLDERID_LocalAppData, false); + if (result.isEmpty()) { + // fallback: try the registry + result = getSpecialPath("Local AppData"); + } + + return result; +} + +QString GameFallout4::myGamesFolderName() const +{ + return "Fallout4"; +} + +QList GameFallout4::executables() +{ + return QList() + << ExecutableInfo("F4SE", findInGameFolder("f4se_loader.exe")) + << ExecutableInfo("Fallout 4", findInGameFolder("Fallout4.exe")) + << ExecutableInfo("Fallout Launcher", findInGameFolder("Fallout4Launcher.exe")) + << ExecutableInfo("LOOT", getLootPath()); + ; +} + +QString GameFallout4::name() const +{ + return "Fallout4 Support Plugin"; +} + +QString GameFallout4::author() const +{ + return "Tannin"; +} + +QString GameFallout4::description() const +{ + return tr("Adds support for the game Fallout 4"); +} + +MOBase::VersionInfo GameFallout4::version() const +{ + return VersionInfo(0, 1, 0, VersionInfo::RELEASE_BETA); +} + +bool GameFallout4::isActive() const +{ + return true; +} + +QList GameFallout4::settings() const +{ + return QList(); +} + +void GameFallout4::copyToProfile(const QString &sourcePath, const QDir &destinationDirectory, + const QString &sourceFileName, const QString &destinationFileName) const +{ + QString filePath = destinationDirectory.absoluteFilePath(destinationFileName.isEmpty() ? sourceFileName + : destinationFileName); + if (!QFileInfo(filePath).exists()) { + if (!shellCopy(sourcePath + "/" + sourceFileName, filePath)) { + // if copy file fails, create the file empty + QFile(filePath).open(QIODevice::WriteOnly); + } + } +} + +void GameFallout4::initializeProfile(const QDir &path, ProfileSettings settings) const +{ + if (settings.testFlag(IPluginGame::MODS)) { + copyToProfile(localAppFolder() + "/Fallout4", path, "plugins.txt"); + copyToProfile(localAppFolder() + "/Fallout4", path, "loadorder.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"); + } +} + +QString GameFallout4::savegameExtension() const +{ + return "fos"; +} + +QString GameFallout4::steamAPPId() const +{ + return "377160"; +} + +QStringList GameFallout4::getPrimaryPlugins() +{ + return { "fallout4.esm" }; +} + +QIcon GameFallout4::gameIcon() const +{ + return MOBase::iconForExecutable(gameDirectory().absoluteFilePath("Fallout4.exe")); +} + +const std::map &GameFallout4::featureList() const +{ + static std::map result { + { typeid(BSAInvalidation), m_BSAInvalidation.get() }, + { typeid(ScriptExtender), m_ScriptExtender.get() }, + { typeid(DataArchives), m_DataArchives.get() } + }; + + return result; +} + + +QStringList GameFallout4::gameVariants() const +{ + return { "Regular" }; +} diff --git a/src/games/fallout4/src/gamefallout4.h b/src/games/fallout4/src/gamefallout4.h new file mode 100644 index 00000000..d0bc90eb --- /dev/null +++ b/src/games/fallout4/src/gamefallout4.h @@ -0,0 +1,65 @@ +#ifndef GAMEFALLOUT4_H +#define GAMEFALLOUT4_H + + +#include "fallout4bsainvalidation.h" +#include "fallout4scriptextender.h" +#include "fallout4dataarchives.h" +#include +#include + + +class GameFallout4 : public GameGamebryo +{ + Q_OBJECT +#if QT_VERSION >= QT_VERSION_CHECK(5,0,0) + Q_PLUGIN_METADATA(IID "org.tannin.GameFallout4" FILE "gamefallout4.json") +#endif + +public: + + GameFallout4(); + + virtual bool init(MOBase::IOrganizer *moInfo) override; + +public: // IPluginGame interface + + virtual QString gameName() const; + virtual QList executables(); + virtual void initializeProfile(const QDir &path, ProfileSettings settings) const; + virtual QString savegameExtension() const; + virtual QString steamAPPId() const; + virtual QStringList getPrimaryPlugins(); + virtual QIcon gameIcon() const override; + virtual QStringList gameVariants() const; + +public: // IPlugin interface + + virtual QString name() const; + virtual QString author() const; + virtual QString description() const; + virtual MOBase::VersionInfo version() const; + virtual bool isActive() const; + virtual QList settings() const; + +protected: + + virtual const std::map &featureList() const; + +private: + + virtual QString identifyGamePath() const override; + virtual QString myGamesFolderName() const override; + + QString localAppFolder() const; + void copyToProfile(const QString &sourcePath, const QDir &destinationDirectory, + const QString &sourceFileName, const QString &destinationFileName = QString()) const; + +private: + + std::shared_ptr m_ScriptExtender { nullptr }; + std::shared_ptr m_DataArchives { nullptr }; + +}; + +#endif // GAMEFallout4_H diff --git a/src/games/fallout4/src/gamefallout4.json b/src/games/fallout4/src/gamefallout4.json new file mode 100644 index 00000000..0967ef42 --- /dev/null +++ b/src/games/fallout4/src/gamefallout4.json @@ -0,0 +1 @@ +{} From c6dc1d4d3ec5eb0ff20591f1e0a3f053129cdf1b Mon Sep 17 00:00:00 2001 From: Tannin Date: Wed, 18 Nov 2015 19:26:14 +0100 Subject: [PATCH 0062/1544] [game_fallout4vr] fixes --- src/games/fallout4vr/CMakeLists.txt.user | 3 +-- src/games/fallout4vr/src/fallout4scriptextender.cpp | 2 +- src/games/fallout4vr/src/gamefallout4.cpp | 10 ++++------ src/games/fallout4vr/src/gamefallout4.h | 1 - 4 files changed, 6 insertions(+), 10 deletions(-) diff --git a/src/games/fallout4vr/CMakeLists.txt.user b/src/games/fallout4vr/CMakeLists.txt.user index a177254f..5d263ca5 100644 --- a/src/games/fallout4vr/CMakeLists.txt.user +++ b/src/games/fallout4vr/CMakeLists.txt.user @@ -1,6 +1,6 @@ - + EnvironmentId @@ -177,7 +177,6 @@ - false %{buildDir} Custom Executable diff --git a/src/games/fallout4vr/src/fallout4scriptextender.cpp b/src/games/fallout4vr/src/fallout4scriptextender.cpp index ae2fcc96..de4e0e70 100644 --- a/src/games/fallout4vr/src/fallout4scriptextender.cpp +++ b/src/games/fallout4vr/src/fallout4scriptextender.cpp @@ -1,4 +1,4 @@ -#include "fallout3scriptextender.h" +#include "fallout4scriptextender.h" QString Fallout4ScriptExtender::name() const diff --git a/src/games/fallout4vr/src/gamefallout4.cpp b/src/games/fallout4vr/src/gamefallout4.cpp index 9b919c14..18350703 100644 --- a/src/games/fallout4vr/src/gamefallout4.cpp +++ b/src/games/fallout4vr/src/gamefallout4.cpp @@ -23,7 +23,6 @@ bool GameFallout4::init(IOrganizer *moInfo) } m_ScriptExtender = std::shared_ptr(new Fallout4ScriptExtender()); m_DataArchives = std::shared_ptr(new Fallout4DataArchives()); - m_BSAInvalidation = std::shared_ptr(new Fallout4BSAInvalidation(m_DataArchives, moInfo)); return true; } @@ -115,13 +114,13 @@ void GameFallout4::initializeProfile(const QDir &path, ProfileSettings settings) 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"); + || !QFileInfo(myGamesPath() + "/fallout4.ini").exists()) { + copyToProfile(gameDirectory().absolutePath(), path, "fallout4_default.ini", "fallout4.ini"); } else { - copyToProfile(myGamesPath(), path, "fallout.ini"); + copyToProfile(myGamesPath(), path, "fallout4.ini"); } - copyToProfile(myGamesPath(), path, "falloutprefs.ini"); + copyToProfile(myGamesPath(), path, "fallout4prefs.ini"); } } @@ -148,7 +147,6 @@ QIcon GameFallout4::gameIcon() const const std::map &GameFallout4::featureList() const { static std::map result { - { typeid(BSAInvalidation), m_BSAInvalidation.get() }, { typeid(ScriptExtender), m_ScriptExtender.get() }, { typeid(DataArchives), m_DataArchives.get() } }; diff --git a/src/games/fallout4vr/src/gamefallout4.h b/src/games/fallout4vr/src/gamefallout4.h index d0bc90eb..371a64a4 100644 --- a/src/games/fallout4vr/src/gamefallout4.h +++ b/src/games/fallout4vr/src/gamefallout4.h @@ -2,7 +2,6 @@ #define GAMEFALLOUT4_H -#include "fallout4bsainvalidation.h" #include "fallout4scriptextender.h" #include "fallout4dataarchives.h" #include From 1965d3def362ceff3b103b00f590691fe9908725 Mon Sep 17 00:00:00 2001 From: Tannin Date: Wed, 18 Nov 2015 19:26:14 +0100 Subject: [PATCH 0063/1544] [game_fallout76] fixes --- src/games/fallout76/CMakeLists.txt.user | 3 +-- src/games/fallout76/src/fallout4scriptextender.cpp | 2 +- src/games/fallout76/src/gamefallout4.cpp | 10 ++++------ src/games/fallout76/src/gamefallout4.h | 1 - 4 files changed, 6 insertions(+), 10 deletions(-) diff --git a/src/games/fallout76/CMakeLists.txt.user b/src/games/fallout76/CMakeLists.txt.user index a177254f..5d263ca5 100644 --- a/src/games/fallout76/CMakeLists.txt.user +++ b/src/games/fallout76/CMakeLists.txt.user @@ -1,6 +1,6 @@ - + EnvironmentId @@ -177,7 +177,6 @@ - false %{buildDir} Custom Executable diff --git a/src/games/fallout76/src/fallout4scriptextender.cpp b/src/games/fallout76/src/fallout4scriptextender.cpp index ae2fcc96..de4e0e70 100644 --- a/src/games/fallout76/src/fallout4scriptextender.cpp +++ b/src/games/fallout76/src/fallout4scriptextender.cpp @@ -1,4 +1,4 @@ -#include "fallout3scriptextender.h" +#include "fallout4scriptextender.h" QString Fallout4ScriptExtender::name() const diff --git a/src/games/fallout76/src/gamefallout4.cpp b/src/games/fallout76/src/gamefallout4.cpp index 9b919c14..18350703 100644 --- a/src/games/fallout76/src/gamefallout4.cpp +++ b/src/games/fallout76/src/gamefallout4.cpp @@ -23,7 +23,6 @@ bool GameFallout4::init(IOrganizer *moInfo) } m_ScriptExtender = std::shared_ptr(new Fallout4ScriptExtender()); m_DataArchives = std::shared_ptr(new Fallout4DataArchives()); - m_BSAInvalidation = std::shared_ptr(new Fallout4BSAInvalidation(m_DataArchives, moInfo)); return true; } @@ -115,13 +114,13 @@ void GameFallout4::initializeProfile(const QDir &path, ProfileSettings settings) 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"); + || !QFileInfo(myGamesPath() + "/fallout4.ini").exists()) { + copyToProfile(gameDirectory().absolutePath(), path, "fallout4_default.ini", "fallout4.ini"); } else { - copyToProfile(myGamesPath(), path, "fallout.ini"); + copyToProfile(myGamesPath(), path, "fallout4.ini"); } - copyToProfile(myGamesPath(), path, "falloutprefs.ini"); + copyToProfile(myGamesPath(), path, "fallout4prefs.ini"); } } @@ -148,7 +147,6 @@ QIcon GameFallout4::gameIcon() const const std::map &GameFallout4::featureList() const { static std::map result { - { typeid(BSAInvalidation), m_BSAInvalidation.get() }, { typeid(ScriptExtender), m_ScriptExtender.get() }, { typeid(DataArchives), m_DataArchives.get() } }; diff --git a/src/games/fallout76/src/gamefallout4.h b/src/games/fallout76/src/gamefallout4.h index d0bc90eb..371a64a4 100644 --- a/src/games/fallout76/src/gamefallout4.h +++ b/src/games/fallout76/src/gamefallout4.h @@ -2,7 +2,6 @@ #define GAMEFALLOUT4_H -#include "fallout4bsainvalidation.h" #include "fallout4scriptextender.h" #include "fallout4dataarchives.h" #include From 3b6d837b9a6f809645030d3adb041015b0af999c Mon Sep 17 00:00:00 2001 From: Tannin Date: Wed, 18 Nov 2015 19:26:14 +0100 Subject: [PATCH 0064/1544] [game_fallout4] fixes --- src/games/fallout4/CMakeLists.txt.user | 3 +-- src/games/fallout4/src/fallout4scriptextender.cpp | 2 +- src/games/fallout4/src/gamefallout4.cpp | 10 ++++------ src/games/fallout4/src/gamefallout4.h | 1 - 4 files changed, 6 insertions(+), 10 deletions(-) diff --git a/src/games/fallout4/CMakeLists.txt.user b/src/games/fallout4/CMakeLists.txt.user index a177254f..5d263ca5 100644 --- a/src/games/fallout4/CMakeLists.txt.user +++ b/src/games/fallout4/CMakeLists.txt.user @@ -1,6 +1,6 @@ - + EnvironmentId @@ -177,7 +177,6 @@ - false %{buildDir} Custom Executable diff --git a/src/games/fallout4/src/fallout4scriptextender.cpp b/src/games/fallout4/src/fallout4scriptextender.cpp index ae2fcc96..de4e0e70 100644 --- a/src/games/fallout4/src/fallout4scriptextender.cpp +++ b/src/games/fallout4/src/fallout4scriptextender.cpp @@ -1,4 +1,4 @@ -#include "fallout3scriptextender.h" +#include "fallout4scriptextender.h" QString Fallout4ScriptExtender::name() const diff --git a/src/games/fallout4/src/gamefallout4.cpp b/src/games/fallout4/src/gamefallout4.cpp index 9b919c14..18350703 100644 --- a/src/games/fallout4/src/gamefallout4.cpp +++ b/src/games/fallout4/src/gamefallout4.cpp @@ -23,7 +23,6 @@ bool GameFallout4::init(IOrganizer *moInfo) } m_ScriptExtender = std::shared_ptr(new Fallout4ScriptExtender()); m_DataArchives = std::shared_ptr(new Fallout4DataArchives()); - m_BSAInvalidation = std::shared_ptr(new Fallout4BSAInvalidation(m_DataArchives, moInfo)); return true; } @@ -115,13 +114,13 @@ void GameFallout4::initializeProfile(const QDir &path, ProfileSettings settings) 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"); + || !QFileInfo(myGamesPath() + "/fallout4.ini").exists()) { + copyToProfile(gameDirectory().absolutePath(), path, "fallout4_default.ini", "fallout4.ini"); } else { - copyToProfile(myGamesPath(), path, "fallout.ini"); + copyToProfile(myGamesPath(), path, "fallout4.ini"); } - copyToProfile(myGamesPath(), path, "falloutprefs.ini"); + copyToProfile(myGamesPath(), path, "fallout4prefs.ini"); } } @@ -148,7 +147,6 @@ QIcon GameFallout4::gameIcon() const const std::map &GameFallout4::featureList() const { static std::map result { - { typeid(BSAInvalidation), m_BSAInvalidation.get() }, { typeid(ScriptExtender), m_ScriptExtender.get() }, { typeid(DataArchives), m_DataArchives.get() } }; diff --git a/src/games/fallout4/src/gamefallout4.h b/src/games/fallout4/src/gamefallout4.h index d0bc90eb..371a64a4 100644 --- a/src/games/fallout4/src/gamefallout4.h +++ b/src/games/fallout4/src/gamefallout4.h @@ -2,7 +2,6 @@ #define GAMEFALLOUT4_H -#include "fallout4bsainvalidation.h" #include "fallout4scriptextender.h" #include "fallout4dataarchives.h" #include From bfe20d959609877b53a31460d92ba59a2308c463 Mon Sep 17 00:00:00 2001 From: Thomas Tanner Date: Sat, 21 Nov 2015 12:35:03 +0000 Subject: [PATCH 0065/1544] [game_falloutnv] Move getBinaryName to plugins --- src/games/falloutnv/src/gamefalloutnv.cpp | 10 ++++++++-- src/games/falloutnv/src/gamefalloutnv.h | 1 + 2 files changed, 9 insertions(+), 2 deletions(-) diff --git a/src/games/falloutnv/src/gamefalloutnv.cpp b/src/games/falloutnv/src/gamefalloutnv.cpp index 9aeecff5..67fc4a88 100644 --- a/src/games/falloutnv/src/gamefalloutnv.cpp +++ b/src/games/falloutnv/src/gamefalloutnv.cpp @@ -56,7 +56,7 @@ QList GameFalloutNV::executables() { return QList() << ExecutableInfo("NVSE", findInGameFolder("nvse_loader.exe")) - << ExecutableInfo("New Vegas", findInGameFolder("FalloutNV.exe")) + << ExecutableInfo("New Vegas", findInGameFolder(getBinaryName())) << ExecutableInfo("Fallout Mod Manager", findInGameFolder("fomm/fomm.exe")) << ExecutableInfo("Construction Kit", findInGameFolder("geck.exe")) << ExecutableInfo("Fallout Launcher", findInGameFolder("FalloutNVLauncher.exe")) @@ -146,7 +146,7 @@ QStringList GameFalloutNV::getPrimaryPlugins() QIcon GameFalloutNV::gameIcon() const { - return MOBase::iconForExecutable(gameDirectory().absoluteFilePath("FalloutNV.exe")); + return MOBase::iconForExecutable(gameDirectory().absoluteFilePath(getBinaryName())); } const std::map &GameFalloutNV::featureList() const @@ -159,3 +159,9 @@ const std::map &GameFalloutNV::featureList() const return result; } + +QString GameFalloutNV::getBinaryName() const +{ + return "FalloutNV.exe"; +} + diff --git a/src/games/falloutnv/src/gamefalloutnv.h b/src/games/falloutnv/src/gamefalloutnv.h index 35bd0458..efed9e5b 100644 --- a/src/games/falloutnv/src/gamefalloutnv.h +++ b/src/games/falloutnv/src/gamefalloutnv.h @@ -31,6 +31,7 @@ public: // IPluginGame interface virtual QString steamAPPId() const; virtual QStringList getPrimaryPlugins(); virtual QIcon gameIcon() const override; + virtual QString getBinaryName() const override; public: // IPlugin interface From 10d9ae8cba3751fa500dd046290b375b588af419 Mon Sep 17 00:00:00 2001 From: Thomas Tanner Date: Sat, 21 Nov 2015 12:35:22 +0000 Subject: [PATCH 0066/1544] [game_fallout3] Move getBinaryName to plugins --- src/games/fallout3/src/gamefallout3.cpp | 9 +++++++-- src/games/fallout3/src/gamefallout3.h | 1 + 2 files changed, 8 insertions(+), 2 deletions(-) diff --git a/src/games/fallout3/src/gamefallout3.cpp b/src/games/fallout3/src/gamefallout3.cpp index 0e0584eb..a1c3db81 100644 --- a/src/games/fallout3/src/gamefallout3.cpp +++ b/src/games/fallout3/src/gamefallout3.cpp @@ -57,7 +57,7 @@ QList GameFallout3::executables() { return QList() << ExecutableInfo("FOSE", findInGameFolder("fose_loader.exe")) - << ExecutableInfo("Fallout 3", findInGameFolder("Fallout3.exe")) + << ExecutableInfo("Fallout 3", findInGameFolder(getBinaryName())) << ExecutableInfo("Fallout Mod Manager", findInGameFolder("fomm/fomm.exe")) << ExecutableInfo("Construction Kit", findInGameFolder("geck.exe")) << ExecutableInfo("Fallout Launcher", findInGameFolder("Fallout3Launcher.exe")) @@ -149,7 +149,7 @@ QStringList GameFallout3::getPrimaryPlugins() QIcon GameFallout3::gameIcon() const { - return MOBase::iconForExecutable(gameDirectory().absoluteFilePath("Fallout3.exe")); + return MOBase::iconForExecutable(gameDirectory().absoluteFilePath(getBinaryName())); } const std::map &GameFallout3::featureList() const @@ -168,3 +168,8 @@ QStringList GameFallout3::gameVariants() const { return { "Regular", "Game Of The Year" }; } + +QString GameFallout3::getBinaryName() const +{ + return "Fallout3.exe"; +} diff --git a/src/games/fallout3/src/gamefallout3.h b/src/games/fallout3/src/gamefallout3.h index 8cd4ad23..ffb4aef3 100644 --- a/src/games/fallout3/src/gamefallout3.h +++ b/src/games/fallout3/src/gamefallout3.h @@ -32,6 +32,7 @@ public: // IPluginGame interface virtual QStringList getPrimaryPlugins(); virtual QIcon gameIcon() const override; virtual QStringList gameVariants() const; + virtual QString getBinaryName() const override; public: // IPlugin interface From 2d9bbac4ebc9053b59cfd0e10c00f1f354b8a4fa Mon Sep 17 00:00:00 2001 From: Thomas Tanner Date: Sat, 21 Nov 2015 12:36:08 +0000 Subject: [PATCH 0067/1544] [game_oblivion] Move getBinaryName to plugins --- src/games/oblivion/src/gameoblivion.cpp | 11 ++++++++--- src/games/oblivion/src/gameoblivion.h | 1 + 2 files changed, 9 insertions(+), 3 deletions(-) diff --git a/src/games/oblivion/src/gameoblivion.cpp b/src/games/oblivion/src/gameoblivion.cpp index bfb25c63..80e32577 100644 --- a/src/games/oblivion/src/gameoblivion.cpp +++ b/src/games/oblivion/src/gameoblivion.cpp @@ -1,7 +1,6 @@ #include "gameoblivion.h" #include #include -#include #include #include #include @@ -58,7 +57,7 @@ QList GameOblivion::executables() { return QList() << ExecutableInfo("OBSE", findInGameFolder("obse_loader.exe")) - << ExecutableInfo("Oblivion", findInGameFolder("oblivion.exe")) + << ExecutableInfo("Oblivion", findInGameFolder(getBinaryName())) << ExecutableInfo("Oblivion Launcher", findInGameFolder("OblivionLauncher.exe")) << ExecutableInfo("Oblivion Mod Manager", findInGameFolder("OblivionModManager.exe")) << ExecutableInfo("BOSS", findInGameFolder("BOSS/BOSS.exe")) @@ -148,7 +147,7 @@ QStringList GameOblivion::getPrimaryPlugins() QIcon GameOblivion::gameIcon() const { - return MOBase::iconForExecutable(gameDirectory().absoluteFilePath("Oblivion.exe")); + return MOBase::iconForExecutable(gameDirectory().absoluteFilePath(getBinaryName())); } const std::map &GameOblivion::featureList() const @@ -161,3 +160,9 @@ const std::map &GameOblivion::featureList() const return result; } + +QString GameOblivion::getBinaryName() const +{ + return "Oblivion.exe"; +} + diff --git a/src/games/oblivion/src/gameoblivion.h b/src/games/oblivion/src/gameoblivion.h index 66a67f6a..f51afbf4 100644 --- a/src/games/oblivion/src/gameoblivion.h +++ b/src/games/oblivion/src/gameoblivion.h @@ -31,6 +31,7 @@ public: // IPluginGame interface virtual QString steamAPPId() const; virtual QStringList getPrimaryPlugins(); virtual QIcon gameIcon() const override; + virtual QString getBinaryName() const override; public: // IPlugin interface From 1d428f07f12507a762920b5e5d0a4849a97857a6 Mon Sep 17 00:00:00 2001 From: Thomas Tanner Date: Sat, 21 Nov 2015 12:36:32 +0000 Subject: [PATCH 0068/1544] [game_skyrim] Move getBinaryName to plugins --- src/games/skyrim/src/gameskyrim.cpp | 11 ++++++++--- src/games/skyrim/src/gameskyrim.h | 1 + 2 files changed, 9 insertions(+), 3 deletions(-) diff --git a/src/games/skyrim/src/gameskyrim.cpp b/src/games/skyrim/src/gameskyrim.cpp index 7c273262..a642d013 100644 --- a/src/games/skyrim/src/gameskyrim.cpp +++ b/src/games/skyrim/src/gameskyrim.cpp @@ -1,7 +1,6 @@ #include "gameskyrim.h" #include #include -#include #include #include #include @@ -59,7 +58,7 @@ QList GameSkyrim::executables() return QList() << ExecutableInfo("SKSE", findInGameFolder("skse_loader.exe")) << ExecutableInfo("SBW", findInGameFolder("SBW.exe")) - << ExecutableInfo("Skyrim", findInGameFolder("TESV.exe")) + << ExecutableInfo("Skyrim", findInGameFolder(getBinaryName())) << ExecutableInfo("Skyrim Launcher", findInGameFolder("SkyrimLauncher.exe")) << ExecutableInfo("BOSS", findInGameFolder("BOSS/BOSS.exe")) << ExecutableInfo("LOOT", getLootPath()) @@ -148,7 +147,7 @@ QStringList GameSkyrim::getPrimaryPlugins() QIcon GameSkyrim::gameIcon() const { - return MOBase::iconForExecutable(gameDirectory().absoluteFilePath("TESV.exe")); + return MOBase::iconForExecutable(gameDirectory().absoluteFilePath(getBinaryName())); } const std::map &GameSkyrim::featureList() const @@ -161,3 +160,9 @@ const std::map &GameSkyrim::featureList() const return result; } + + +QString GameSkyrim::getBinaryName() const +{ + return "TESV.exe"; +} diff --git a/src/games/skyrim/src/gameskyrim.h b/src/games/skyrim/src/gameskyrim.h index 743223e7..7180c911 100644 --- a/src/games/skyrim/src/gameskyrim.h +++ b/src/games/skyrim/src/gameskyrim.h @@ -31,6 +31,7 @@ public: // IPluginGame interface virtual QString steamAPPId() const; virtual QStringList getPrimaryPlugins(); virtual QIcon gameIcon() const override; + virtual QString getBinaryName() const override; public: // IPlugin interface From 1a984dc782fd1afeb1b0931ac87d428bc5ce723b Mon Sep 17 00:00:00 2001 From: Thomas Tanner Date: Sat, 21 Nov 2015 16:35:38 +0000 Subject: [PATCH 0069/1544] [game_fallout3] Replace GameInfo::path with iPluginGame::gameDirectory (or dataDirectory where applicable) Simplified plugin bsa invalidation setup as it already knows what game it is --- src/games/fallout3/src/fallout3bsainvalidation.cpp | 6 ++---- src/games/fallout3/src/fallout3bsainvalidation.h | 6 +++--- src/games/fallout3/src/gamefallout3.cpp | 2 +- 3 files changed, 6 insertions(+), 8 deletions(-) diff --git a/src/games/fallout3/src/fallout3bsainvalidation.cpp b/src/games/fallout3/src/fallout3bsainvalidation.cpp index 3262787b..f75f7da8 100644 --- a/src/games/fallout3/src/fallout3bsainvalidation.cpp +++ b/src/games/fallout3/src/fallout3bsainvalidation.cpp @@ -1,9 +1,7 @@ #include "fallout3bsainvalidation.h" -#include - -Fallout3BSAInvalidation::Fallout3BSAInvalidation(const std::shared_ptr &dataArchives, MOBase::IOrganizer *moInfo) - : GamebryoBSAInvalidation(dataArchives, "fallout.ini", moInfo) +Fallout3BSAInvalidation::Fallout3BSAInvalidation(const std::shared_ptr &dataArchives, MOBase::IPluginGame *game) + : GamebryoBSAInvalidation(dataArchives, "fallout.ini", game) { } diff --git a/src/games/fallout3/src/fallout3bsainvalidation.h b/src/games/fallout3/src/fallout3bsainvalidation.h index 7cb192d2..11d13107 100644 --- a/src/games/fallout3/src/fallout3bsainvalidation.h +++ b/src/games/fallout3/src/fallout3bsainvalidation.h @@ -2,16 +2,16 @@ #define FALLOUT3BSAINVALIDATION_H -#include -#include +#include "gamebryobsainvalidation.h" #include "fallout3dataarchives.h" +#include class Fallout3BSAInvalidation : public GamebryoBSAInvalidation { public: - Fallout3BSAInvalidation(const std::shared_ptr &dataArchives, MOBase::IOrganizer *moInfo); + Fallout3BSAInvalidation(const std::shared_ptr &dataArchives, MOBase::IPluginGame *game); private: diff --git a/src/games/fallout3/src/gamefallout3.cpp b/src/games/fallout3/src/gamefallout3.cpp index a1c3db81..1f65b34b 100644 --- a/src/games/fallout3/src/gamefallout3.cpp +++ b/src/games/fallout3/src/gamefallout3.cpp @@ -23,7 +23,7 @@ bool GameFallout3::init(IOrganizer *moInfo) } m_ScriptExtender = std::shared_ptr(new Fallout3ScriptExtender()); m_DataArchives = std::shared_ptr(new Fallout3DataArchives()); - m_BSAInvalidation = std::shared_ptr(new Fallout3BSAInvalidation(m_DataArchives, moInfo)); + m_BSAInvalidation = std::shared_ptr(new Fallout3BSAInvalidation(m_DataArchives, this)); return true; } From 825b89a4ddc58d04c85db06251ddf64fa116e0f7 Mon Sep 17 00:00:00 2001 From: Thomas Tanner Date: Sat, 21 Nov 2015 16:35:56 +0000 Subject: [PATCH 0070/1544] [game_falloutnv] Replace GameInfo::path with iPluginGame::gameDirectory (or dataDirectory where applicable) Simplified plugin bsa invalidation setup as it already knows what game it is --- src/games/falloutnv/src/falloutnvbsainvalidation.cpp | 6 ++---- src/games/falloutnv/src/falloutnvbsainvalidation.h | 6 +++--- src/games/falloutnv/src/gamefalloutnv.cpp | 2 +- 3 files changed, 6 insertions(+), 8 deletions(-) diff --git a/src/games/falloutnv/src/falloutnvbsainvalidation.cpp b/src/games/falloutnv/src/falloutnvbsainvalidation.cpp index 45b86f7c..22581654 100644 --- a/src/games/falloutnv/src/falloutnvbsainvalidation.cpp +++ b/src/games/falloutnv/src/falloutnvbsainvalidation.cpp @@ -1,9 +1,7 @@ #include "falloutnvbsainvalidation.h" -#include - -FalloutNVBSAInvalidation::FalloutNVBSAInvalidation(const std::shared_ptr &dataArchives, MOBase::IOrganizer *moInfo) - : GamebryoBSAInvalidation(dataArchives, "fallout.ini", moInfo) +FalloutNVBSAInvalidation::FalloutNVBSAInvalidation(const std::shared_ptr &dataArchives, MOBase::IPluginGame *game) + : GamebryoBSAInvalidation(dataArchives, "fallout.ini", game) { } diff --git a/src/games/falloutnv/src/falloutnvbsainvalidation.h b/src/games/falloutnv/src/falloutnvbsainvalidation.h index 74c4efc7..0cd77a36 100644 --- a/src/games/falloutnv/src/falloutnvbsainvalidation.h +++ b/src/games/falloutnv/src/falloutnvbsainvalidation.h @@ -2,16 +2,16 @@ #define FALLOUTNVBSAINVALIDATION_H -#include -#include +#include "gamebryobsainvalidation.h" #include "falloutnvdataarchives.h" +#include class FalloutNVBSAInvalidation : public GamebryoBSAInvalidation { public: - FalloutNVBSAInvalidation(const std::shared_ptr &dataArchives, MOBase::IOrganizer *moInfo); + FalloutNVBSAInvalidation(const std::shared_ptr &dataArchives, MOBase::IPluginGame *game); private: diff --git a/src/games/falloutnv/src/gamefalloutnv.cpp b/src/games/falloutnv/src/gamefalloutnv.cpp index 67fc4a88..9ce1dab1 100644 --- a/src/games/falloutnv/src/gamefalloutnv.cpp +++ b/src/games/falloutnv/src/gamefalloutnv.cpp @@ -22,7 +22,7 @@ bool GameFalloutNV::init(IOrganizer *moInfo) } m_ScriptExtender = std::shared_ptr(new FalloutNVScriptExtender()); m_DataArchives = std::shared_ptr(new FalloutNVDataArchives()); - m_BSAInvalidation = std::shared_ptr(new FalloutNVBSAInvalidation(m_DataArchives, moInfo)); + m_BSAInvalidation = std::shared_ptr(new FalloutNVBSAInvalidation(m_DataArchives, this)); return true; } From 07936253345095966d744f255c81cdc9fac0aaba Mon Sep 17 00:00:00 2001 From: Thomas Tanner Date: Sat, 21 Nov 2015 16:36:36 +0000 Subject: [PATCH 0071/1544] Replace GameInfo::path with iPluginGame::gameDirectory (or dataDirectory where applicable) Simplified plugin bsa invalidation setup as it already knows what game it is --- src/gamebryobsainvalidation.cpp | 11 +++++++---- src/gamebryobsainvalidation.h | 9 +++++---- 2 files changed, 12 insertions(+), 8 deletions(-) diff --git a/src/gamebryobsainvalidation.cpp b/src/gamebryobsainvalidation.cpp index dd7b1b02..36f1479e 100644 --- a/src/gamebryobsainvalidation.cpp +++ b/src/gamebryobsainvalidation.cpp @@ -1,9 +1,12 @@ #include "gamebryobsainvalidation.h" + #include "dummybsa.h" +#include "iplugingame.h" #include #include #include #include + #include #include #include @@ -11,10 +14,10 @@ GamebryoBSAInvalidation::GamebryoBSAInvalidation(const std::shared_ptr &dataArchives , const QString &iniFilename - , MOBase::IOrganizer *moInfo) + , MOBase::IPluginGame *game) : m_DataArchives(dataArchives) , m_IniFileName(iniFilename) - , m_Organizer(moInfo) + , m_Game(game) { } @@ -39,7 +42,7 @@ void GamebryoBSAInvalidation::deactivate(MOBase::IProfile *profile) } } - QString bsaFile = m_Organizer->gameInfo().path() + "/data/" + invalidationBSAName(); + QString bsaFile = m_Game->dataDirectory().absoluteFilePath(invalidationBSAName()); if (QFile::exists(bsaFile)) { MOBase::shellDeleteQuiet(bsaFile); } @@ -70,7 +73,7 @@ void GamebryoBSAInvalidation::activate(MOBase::IProfile *profile) } // create the dummy bsa if necessary - QString bsaFile = m_Organizer->gameInfo().path() + "/data/" + invalidationBSAName(); + QString bsaFile = m_Game->dataDirectory().absoluteFilePath(invalidationBSAName()); if (!QFile::exists(bsaFile)) { DummyBSA bsa(bsaVersion()); bsa.write(bsaFile); diff --git a/src/gamebryobsainvalidation.h b/src/gamebryobsainvalidation.h index 9366a5ab..d59e75f5 100644 --- a/src/gamebryobsainvalidation.h +++ b/src/gamebryobsainvalidation.h @@ -7,16 +7,17 @@ #include #include - namespace MOBase { - class IOrganizer; + class IPluginGame; } class GamebryoBSAInvalidation : public BSAInvalidation { public: - GamebryoBSAInvalidation(const std::shared_ptr &dataArchives, const QString &iniFilename, MOBase::IOrganizer *moInfo); + GamebryoBSAInvalidation(const std::shared_ptr &dataArchives, + const QString &iniFilename, + MOBase::IPluginGame *game); virtual bool isInvalidationBSA(const QString &bsaName) override; virtual void deactivate(MOBase::IProfile *profile) override; @@ -31,7 +32,7 @@ private: std::shared_ptr m_DataArchives; QString m_IniFileName; - MOBase::IOrganizer *m_Organizer; + MOBase::IPluginGame *m_Game; }; From ce2767e5a7bba7d8bee4cb4a4b5ef40c351f519d Mon Sep 17 00:00:00 2001 From: Thomas Tanner Date: Sat, 21 Nov 2015 16:36:57 +0000 Subject: [PATCH 0072/1544] [game_oblivion] Replace GameInfo::path with iPluginGame::gameDirectory (or dataDirectory where applicable) Simplified plugin bsa invalidation setup as it already knows what game it is --- src/games/oblivion/src/gameoblivion.cpp | 2 +- src/games/oblivion/src/oblivionbsainvalidation.cpp | 5 ++--- src/games/oblivion/src/oblivionbsainvalidation.h | 6 +++--- 3 files changed, 6 insertions(+), 7 deletions(-) diff --git a/src/games/oblivion/src/gameoblivion.cpp b/src/games/oblivion/src/gameoblivion.cpp index 80e32577..0d99c28e 100644 --- a/src/games/oblivion/src/gameoblivion.cpp +++ b/src/games/oblivion/src/gameoblivion.cpp @@ -21,7 +21,7 @@ bool GameOblivion::init(IOrganizer *moInfo) } m_ScriptExtender = std::shared_ptr(new OblivionScriptExtender()); m_DataArchives = std::shared_ptr(new OblivionDataArchives()); - m_BSAInvalidation = std::shared_ptr(new OblivionBSAInvalidation(m_DataArchives, moInfo)); + m_BSAInvalidation = std::shared_ptr(new OblivionBSAInvalidation(m_DataArchives, this)); return true; } diff --git a/src/games/oblivion/src/oblivionbsainvalidation.cpp b/src/games/oblivion/src/oblivionbsainvalidation.cpp index cfa9f9ea..c1c54933 100644 --- a/src/games/oblivion/src/oblivionbsainvalidation.cpp +++ b/src/games/oblivion/src/oblivionbsainvalidation.cpp @@ -1,9 +1,8 @@ #include "oblivionbsainvalidation.h" -#include -OblivionBSAInvalidation::OblivionBSAInvalidation(const std::shared_ptr &dataArchives, MOBase::IOrganizer *moInfo) - : GamebryoBSAInvalidation(dataArchives, "oblivion.ini", moInfo) +OblivionBSAInvalidation::OblivionBSAInvalidation(const std::shared_ptr &dataArchives, MOBase::IPluginGame *game) + : GamebryoBSAInvalidation(dataArchives, "oblivion.ini", game) { } diff --git a/src/games/oblivion/src/oblivionbsainvalidation.h b/src/games/oblivion/src/oblivionbsainvalidation.h index 2213df1b..bf018735 100644 --- a/src/games/oblivion/src/oblivionbsainvalidation.h +++ b/src/games/oblivion/src/oblivionbsainvalidation.h @@ -2,16 +2,16 @@ #define OBLIVIONBSAINVALIDATION_H -#include -#include +#include "gamebryobsainvalidation.h" #include "obliviondataarchives.h" +#include class OblivionBSAInvalidation : public GamebryoBSAInvalidation { public: - OblivionBSAInvalidation(const std::shared_ptr &dataArchives, MOBase::IOrganizer *moInfo); + OblivionBSAInvalidation(const std::shared_ptr &dataArchives, MOBase::IPluginGame *game); private: From 1125f740e6f944eb4812ba1790d81dacbcb12bd3 Mon Sep 17 00:00:00 2001 From: Thomas Tanner Date: Sat, 21 Nov 2015 16:38:18 +0000 Subject: [PATCH 0073/1544] [game_skyrim] Replace GameInfo::path with iPluginGame::gameDirectory (or dataDirectory where applicable) Simplified plugin bsa invalidation setup as it already knows what game it is --- src/games/skyrim/src/gameskyrim.cpp | 2 +- src/games/skyrim/src/skyrimbsainvalidation.cpp | 6 ++---- src/games/skyrim/src/skyrimbsainvalidation.h | 6 +++--- 3 files changed, 6 insertions(+), 8 deletions(-) diff --git a/src/games/skyrim/src/gameskyrim.cpp b/src/games/skyrim/src/gameskyrim.cpp index a642d013..cad08c30 100644 --- a/src/games/skyrim/src/gameskyrim.cpp +++ b/src/games/skyrim/src/gameskyrim.cpp @@ -21,7 +21,7 @@ bool GameSkyrim::init(IOrganizer *moInfo) } m_ScriptExtender = std::shared_ptr(new SkyrimScriptExtender()); m_DataArchives = std::shared_ptr(new SkyrimDataArchives()); - m_BSAInvalidation = std::shared_ptr(new SkyrimBSAInvalidation(m_DataArchives, moInfo)); + m_BSAInvalidation = std::shared_ptr(new SkyrimBSAInvalidation(m_DataArchives, this)); return true; } diff --git a/src/games/skyrim/src/skyrimbsainvalidation.cpp b/src/games/skyrim/src/skyrimbsainvalidation.cpp index a63261d5..a153b18c 100644 --- a/src/games/skyrim/src/skyrimbsainvalidation.cpp +++ b/src/games/skyrim/src/skyrimbsainvalidation.cpp @@ -1,9 +1,7 @@ #include "skyrimbsainvalidation.h" -#include - -SkyrimBSAInvalidation::SkyrimBSAInvalidation(const std::shared_ptr &dataArchives, MOBase::IOrganizer *moInfo) - : GamebryoBSAInvalidation(dataArchives, "skyrim.ini", moInfo) +SkyrimBSAInvalidation::SkyrimBSAInvalidation(const std::shared_ptr &dataArchives, MOBase::IPluginGame *game) + : GamebryoBSAInvalidation(dataArchives, "skyrim.ini", game) { } diff --git a/src/games/skyrim/src/skyrimbsainvalidation.h b/src/games/skyrim/src/skyrimbsainvalidation.h index 02e3c664..99557791 100644 --- a/src/games/skyrim/src/skyrimbsainvalidation.h +++ b/src/games/skyrim/src/skyrimbsainvalidation.h @@ -2,16 +2,16 @@ #define SKYRIMBSAINVALIDATION_H -#include -#include +#include "gamebryobsainvalidation.h" #include "skyrimdataarchives.h" +#include class SkyrimBSAInvalidation : public GamebryoBSAInvalidation { public: - SkyrimBSAInvalidation(const std::shared_ptr &dataArchives, MOBase::IOrganizer *moInfo); + SkyrimBSAInvalidation(const std::shared_ptr &dataArchives, MOBase::IPluginGame *game); private: From f46e54f7d7c24d5d33b9f0cc736fb381e3630026 Mon Sep 17 00:00:00 2001 From: Thomas Tanner Date: Sun, 22 Nov 2015 08:38:37 +0000 Subject: [PATCH 0074/1544] [game_fallout3] Removes igameinfo.h from everywhere apart from (sort of) the pythonrunner plugin. --- src/games/fallout3/src/gamefallout3.cpp | 14 +++++++++++++- src/games/fallout3/src/gamefallout3.h | 2 ++ 2 files changed, 15 insertions(+), 1 deletion(-) diff --git a/src/games/fallout3/src/gamefallout3.cpp b/src/games/fallout3/src/gamefallout3.cpp index 1f65b34b..fc131880 100644 --- a/src/games/fallout3/src/gamefallout3.cpp +++ b/src/games/fallout3/src/gamefallout3.cpp @@ -1,10 +1,12 @@ #include "gameFallout3.h" + #include #include -#include #include #include + #include + #include #include @@ -173,3 +175,13 @@ QString GameFallout3::getBinaryName() const { return "Fallout3.exe"; } + +QString GameFallout3::getNexusName() const +{ + return "Fallout3"; +} + +QStringList GameFallout3::getIniFiles() const +{ + return { "fallout.ini", "falloutprefs.ini" }; +} diff --git a/src/games/fallout3/src/gamefallout3.h b/src/games/fallout3/src/gamefallout3.h index ffb4aef3..ef343953 100644 --- a/src/games/fallout3/src/gamefallout3.h +++ b/src/games/fallout3/src/gamefallout3.h @@ -33,6 +33,8 @@ public: // IPluginGame interface virtual QIcon gameIcon() const override; virtual QStringList gameVariants() const; virtual QString getBinaryName() const override; + virtual QString getNexusName() const override; + virtual QStringList getIniFiles() const override; public: // IPlugin interface From f1d38d0af1289626b5b1891cc68cb19f746ddb8b Mon Sep 17 00:00:00 2001 From: Thomas Tanner Date: Sun, 22 Nov 2015 08:38:57 +0000 Subject: [PATCH 0075/1544] [game_falloutnv] Removes igameinfo.h from everywhere apart from (sort of) the pythonrunner plugin. --- src/games/falloutnv/src/gamefalloutnv.cpp | 13 ++++++++++++- src/games/falloutnv/src/gamefalloutnv.h | 2 ++ 2 files changed, 14 insertions(+), 1 deletion(-) diff --git a/src/games/falloutnv/src/gamefalloutnv.cpp b/src/games/falloutnv/src/gamefalloutnv.cpp index 9ce1dab1..e0db7c81 100644 --- a/src/games/falloutnv/src/gamefalloutnv.cpp +++ b/src/games/falloutnv/src/gamefalloutnv.cpp @@ -1,10 +1,12 @@ #include "gameFalloutNV.h" + #include #include -#include #include #include + #include + #include @@ -165,3 +167,12 @@ QString GameFalloutNV::getBinaryName() const return "FalloutNV.exe"; } +QString GameFalloutNV::getNexusName() const +{ + return "FalloutNV"; +} + +QStringList GameFalloutNV::getIniFiles() const +{ + return { "fallout.ini", "falloutprefs.ini" }; +} diff --git a/src/games/falloutnv/src/gamefalloutnv.h b/src/games/falloutnv/src/gamefalloutnv.h index efed9e5b..cab230dc 100644 --- a/src/games/falloutnv/src/gamefalloutnv.h +++ b/src/games/falloutnv/src/gamefalloutnv.h @@ -32,6 +32,8 @@ public: // IPluginGame interface virtual QStringList getPrimaryPlugins(); virtual QIcon gameIcon() const override; virtual QString getBinaryName() const override; + virtual QString getNexusName() const override; + virtual QStringList getIniFiles() const override; public: // IPlugin interface From 6e22345ec8a4458d875319823891e84ef3eded98 Mon Sep 17 00:00:00 2001 From: Thomas Tanner Date: Sun, 22 Nov 2015 08:39:18 +0000 Subject: [PATCH 0076/1544] Removes igameinfo.h from everywhere apart from (sort of) the pythonrunner plugin. --- src/gamebryobsainvalidation.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/gamebryobsainvalidation.cpp b/src/gamebryobsainvalidation.cpp index 36f1479e..5ed92c5c 100644 --- a/src/gamebryobsainvalidation.cpp +++ b/src/gamebryobsainvalidation.cpp @@ -4,11 +4,11 @@ #include "iplugingame.h" #include #include -#include #include #include #include + #include From 9a11bae3589692d6d1cb913d7c4ce9be7b25b953 Mon Sep 17 00:00:00 2001 From: Thomas Tanner Date: Sun, 22 Nov 2015 08:41:03 +0000 Subject: [PATCH 0077/1544] [game_oblivion] Removes igameinfo.h from everywhere apart from (sort of) the pythonrunner plugin. --- src/games/oblivion/src/gameoblivion.cpp | 9 +++++++++ src/games/oblivion/src/gameoblivion.h | 2 ++ 2 files changed, 11 insertions(+) diff --git a/src/games/oblivion/src/gameoblivion.cpp b/src/games/oblivion/src/gameoblivion.cpp index 0d99c28e..4e46389d 100644 --- a/src/games/oblivion/src/gameoblivion.cpp +++ b/src/games/oblivion/src/gameoblivion.cpp @@ -166,3 +166,12 @@ QString GameOblivion::getBinaryName() const return "Oblivion.exe"; } +QString GameOblivion::getNexusName() const +{ + return "Oblivion"; +} + +QStringList GameOblivion::getIniFiles() const +{ + return { "oblivion.ini", "oblivionprefs.ini" }; +} diff --git a/src/games/oblivion/src/gameoblivion.h b/src/games/oblivion/src/gameoblivion.h index f51afbf4..e63dab3e 100644 --- a/src/games/oblivion/src/gameoblivion.h +++ b/src/games/oblivion/src/gameoblivion.h @@ -32,6 +32,8 @@ public: // IPluginGame interface virtual QStringList getPrimaryPlugins(); virtual QIcon gameIcon() const override; virtual QString getBinaryName() const override; + virtual QString getNexusName() const override; + virtual QStringList getIniFiles() const override; public: // IPlugin interface From e736ed8f14e1bd008721ad05c2d5c219f04cb7df Mon Sep 17 00:00:00 2001 From: Thomas Tanner Date: Sun, 22 Nov 2015 08:41:18 +0000 Subject: [PATCH 0078/1544] [game_skyrim] Removes igameinfo.h from everywhere apart from (sort of) the pythonrunner plugin. --- src/games/skyrim/src/gameskyrim.cpp | 11 ++++++++++- src/games/skyrim/src/gameskyrim.h | 2 ++ 2 files changed, 12 insertions(+), 1 deletion(-) diff --git a/src/games/skyrim/src/gameskyrim.cpp b/src/games/skyrim/src/gameskyrim.cpp index cad08c30..89a5eb9c 100644 --- a/src/games/skyrim/src/gameskyrim.cpp +++ b/src/games/skyrim/src/gameskyrim.cpp @@ -161,8 +161,17 @@ const std::map &GameSkyrim::featureList() const return result; } - QString GameSkyrim::getBinaryName() const { return "TESV.exe"; } + +QString GameSkyrim::getNexusName() const +{ + return "Skyrim"; +} + +QStringList GameSkyrim::getIniFiles() const +{ + return { "skyrim.ini", "skyrimprefs.ini" }; +} diff --git a/src/games/skyrim/src/gameskyrim.h b/src/games/skyrim/src/gameskyrim.h index 7180c911..397added 100644 --- a/src/games/skyrim/src/gameskyrim.h +++ b/src/games/skyrim/src/gameskyrim.h @@ -32,6 +32,8 @@ public: // IPluginGame interface virtual QStringList getPrimaryPlugins(); virtual QIcon gameIcon() const override; virtual QString getBinaryName() const override; + virtual QString getNexusName() const override; + virtual QStringList getIniFiles() const override; public: // IPlugin interface From 26f78a5010a33a5cc0f26ccee97e2024a5512732 Mon Sep 17 00:00:00 2001 From: Tannin Date: Sun, 22 Nov 2015 15:14:01 +0100 Subject: [PATCH 0079/1544] gamebryo plugin now correctly reads game registration from wow64 node if necessary --- src/gamegamebryo.cpp | 15 ++++++++++++--- 1 file changed, 12 insertions(+), 3 deletions(-) diff --git a/src/gamegamebryo.cpp b/src/gamegamebryo.cpp index 18651f05..954bd92d 100644 --- a/src/gamegamebryo.cpp +++ b/src/gamegamebryo.cpp @@ -1,4 +1,5 @@ #include "gamegamebryo.h" +#include #include #include #include @@ -46,10 +47,18 @@ bool GameGamebryo::isInstalled() const return !m_GamePath.isEmpty(); } -std::unique_ptr GameGamebryo::getRegValue(HKEY key, LPCWSTR subKey, LPCWSTR value, DWORD flags, LPDWORD type) const +std::unique_ptr GameGamebryo::getRegValue(HKEY key, LPCWSTR path, + LPCWSTR value, DWORD flags, + LPDWORD type) const { DWORD size = 0; - DWORD res = ::RegGetValueW(key, subKey, value, flags, type, nullptr, &size); + HKEY subKey; + LONG res = ::RegOpenKeyExW(key, path, 0, + KEY_QUERY_VALUE | KEY_WOW64_32KEY, &subKey); + if (res != ERROR_SUCCESS) { + return std::unique_ptr(); + } + res = ::RegGetValueW(subKey, L"", value, flags, type, nullptr, &size); if ((res == ERROR_FILE_NOT_FOUND) || (res == ERROR_UNSUPPORTED_TYPE)) { return std::unique_ptr(); } else if ((res != ERROR_SUCCESS) && (res != ERROR_MORE_DATA)) { @@ -57,7 +66,7 @@ std::unique_ptr GameGamebryo::getRegValue(HKEY key, LPCWSTR subKey, LPCW } std::unique_ptr result(new BYTE[size]); - res = ::RegGetValueW(key, subKey, value, flags, type, result.get(), &size); + res = ::RegGetValueW(subKey, L"", value, flags, type, result.get(), &size); if (res != ERROR_SUCCESS) { throw MOBase::MyException(QObject::tr("failed to query registry path (read): %1").arg(res, 0, 16)); From 423bdc47ac5e0553f3bc5c4b8a8f16c490106deb Mon Sep 17 00:00:00 2001 From: Thomas Tanner Date: Sun, 22 Nov 2015 21:15:45 +0000 Subject: [PATCH 0080/1544] [game_fallout3] Final eradication of igameinfo and adding python wrappers for IPluginGame --- src/games/fallout3/src/gamefallout3.cpp | 6 +++--- src/games/fallout3/src/gamefallout3.h | 14 +++++++------- 2 files changed, 10 insertions(+), 10 deletions(-) diff --git a/src/games/fallout3/src/gamefallout3.cpp b/src/games/fallout3/src/gamefallout3.cpp index fc131880..9f82644e 100644 --- a/src/games/fallout3/src/gamefallout3.cpp +++ b/src/games/fallout3/src/gamefallout3.cpp @@ -55,7 +55,7 @@ QString GameFallout3::myGamesFolderName() const return "Fallout3"; } -QList GameFallout3::executables() +QList GameFallout3::executables() const { return QList() << ExecutableInfo("FOSE", findInGameFolder("fose_loader.exe")) @@ -144,7 +144,7 @@ QString GameFallout3::steamAPPId() const } } -QStringList GameFallout3::getPrimaryPlugins() +QStringList GameFallout3::getPrimaryPlugins() const { return { "fallout3.esm" }; } @@ -154,7 +154,7 @@ QIcon GameFallout3::gameIcon() const return MOBase::iconForExecutable(gameDirectory().absoluteFilePath(getBinaryName())); } -const std::map &GameFallout3::featureList() const +std::map GameFallout3::featureList() const { static std::map result { { typeid(BSAInvalidation), m_BSAInvalidation.get() }, diff --git a/src/games/fallout3/src/gamefallout3.h b/src/games/fallout3/src/gamefallout3.h index ef343953..1e904728 100644 --- a/src/games/fallout3/src/gamefallout3.h +++ b/src/games/fallout3/src/gamefallout3.h @@ -24,12 +24,12 @@ public: public: // IPluginGame interface - virtual QString gameName() const; - virtual QList executables(); - virtual void initializeProfile(const QDir &path, ProfileSettings settings) const; - virtual QString savegameExtension() const; - virtual QString steamAPPId() const; - virtual QStringList getPrimaryPlugins(); + virtual QString gameName() const override; + virtual QList executables() const override; + virtual void initializeProfile(const QDir &path, ProfileSettings settings) const override; + virtual QString savegameExtension() const override; + virtual QString steamAPPId() const override; + virtual QStringList getPrimaryPlugins() const override; virtual QIcon gameIcon() const override; virtual QStringList gameVariants() const; virtual QString getBinaryName() const override; @@ -47,7 +47,7 @@ public: // IPlugin interface protected: - virtual const std::map &featureList() const; + virtual std::map featureList() const override; private: From 1d1589968ec8f631bcb9e94c8023e18c796b4efd Mon Sep 17 00:00:00 2001 From: Thomas Tanner Date: Sun, 22 Nov 2015 21:16:10 +0000 Subject: [PATCH 0081/1544] [game_falloutnv] Final eradication of igameinfo and adding python wrappers for IPluginGame --- src/games/falloutnv/src/gamefalloutnv.cpp | 6 +++--- src/games/falloutnv/src/gamefalloutnv.h | 14 +++++++------- 2 files changed, 10 insertions(+), 10 deletions(-) diff --git a/src/games/falloutnv/src/gamefalloutnv.cpp b/src/games/falloutnv/src/gamefalloutnv.cpp index e0db7c81..f792570d 100644 --- a/src/games/falloutnv/src/gamefalloutnv.cpp +++ b/src/games/falloutnv/src/gamefalloutnv.cpp @@ -54,7 +54,7 @@ QString GameFalloutNV::myGamesFolderName() const return "FalloutNV"; } -QList GameFalloutNV::executables() +QList GameFalloutNV::executables() const { return QList() << ExecutableInfo("NVSE", findInGameFolder("nvse_loader.exe")) @@ -141,7 +141,7 @@ QString GameFalloutNV::steamAPPId() const return "22380"; } -QStringList GameFalloutNV::getPrimaryPlugins() +QStringList GameFalloutNV::getPrimaryPlugins() const { return { "falloutnv.esm" }; } @@ -151,7 +151,7 @@ QIcon GameFalloutNV::gameIcon() const return MOBase::iconForExecutable(gameDirectory().absoluteFilePath(getBinaryName())); } -const std::map &GameFalloutNV::featureList() const +std::map GameFalloutNV::featureList() const { static std::map result { { typeid(BSAInvalidation), m_BSAInvalidation.get() }, diff --git a/src/games/falloutnv/src/gamefalloutnv.h b/src/games/falloutnv/src/gamefalloutnv.h index cab230dc..271cadc0 100644 --- a/src/games/falloutnv/src/gamefalloutnv.h +++ b/src/games/falloutnv/src/gamefalloutnv.h @@ -24,12 +24,12 @@ public: public: // IPluginGame interface - virtual QString gameName() const; - virtual QList executables(); - virtual void initializeProfile(const QDir &path, ProfileSettings settings) const; - virtual QString savegameExtension() const; - virtual QString steamAPPId() const; - virtual QStringList getPrimaryPlugins(); + virtual QString gameName() const override; + virtual QList executables() const override; + virtual void initializeProfile(const QDir &path, ProfileSettings settings) const override; + virtual QString savegameExtension() const override; + virtual QString steamAPPId() const override; + virtual QStringList getPrimaryPlugins() const override; virtual QIcon gameIcon() const override; virtual QString getBinaryName() const override; virtual QString getNexusName() const override; @@ -46,7 +46,7 @@ public: // IPlugin interface protected: - virtual const std::map &featureList() const; + virtual std::map featureList() const override; private: From b3f069b1381566eafc7b410544ff91d0703d6828 Mon Sep 17 00:00:00 2001 From: Thomas Tanner Date: Sun, 22 Nov 2015 21:16:36 +0000 Subject: [PATCH 0082/1544] Final eradication of igameinfo and adding python wrappers for IPluginGame --- src/gamegamebryo.cpp | 2 +- src/gamegamebryo.h | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/src/gamegamebryo.cpp b/src/gamegamebryo.cpp index 18651f05..68c2fb8a 100644 --- a/src/gamegamebryo.cpp +++ b/src/gamegamebryo.cpp @@ -77,7 +77,7 @@ QString GameGamebryo::findInRegistry(HKEY baseKey, LPCWSTR path, LPCWSTR value) } } -QFileInfo GameGamebryo::findInGameFolder(const QString &relativePath) +QFileInfo GameGamebryo::findInGameFolder(const QString &relativePath) const { return QFileInfo(m_GamePath + "/" + relativePath); } diff --git a/src/gamegamebryo.h b/src/gamegamebryo.h index e4d03e50..d0cb2c86 100644 --- a/src/gamegamebryo.h +++ b/src/gamegamebryo.h @@ -35,7 +35,7 @@ protected: std::unique_ptr getRegValue(HKEY key, LPCWSTR subKey, LPCWSTR value, DWORD flags, LPDWORD type = nullptr) const; QString findInRegistry(HKEY baseKey, LPCWSTR path, LPCWSTR value) const; - QFileInfo findInGameFolder(const QString &relativePath); + QFileInfo findInGameFolder(const QString &relativePath) const; QString getKnownFolderPath(REFKNOWNFOLDERID folderId, bool useDefault) const; QString getSpecialPath(const QString &name) const; QString myGamesPath() const; From 6574206dd441de6d3c228fb8c73eb68cff11b827 Mon Sep 17 00:00:00 2001 From: Thomas Tanner Date: Sun, 22 Nov 2015 21:17:15 +0000 Subject: [PATCH 0083/1544] [game_oblivion] Final eradication of igameinfo and adding python wrappers for IPluginGame --- src/games/oblivion/src/gameoblivion.cpp | 6 +++--- src/games/oblivion/src/gameoblivion.h | 14 +++++++------- 2 files changed, 10 insertions(+), 10 deletions(-) diff --git a/src/games/oblivion/src/gameoblivion.cpp b/src/games/oblivion/src/gameoblivion.cpp index 4e46389d..74d0fdc5 100644 --- a/src/games/oblivion/src/gameoblivion.cpp +++ b/src/games/oblivion/src/gameoblivion.cpp @@ -53,7 +53,7 @@ QString GameOblivion::myGamesFolderName() const -QList GameOblivion::executables() +QList GameOblivion::executables() const { return QList() << ExecutableInfo("OBSE", findInGameFolder("obse_loader.exe")) @@ -140,7 +140,7 @@ QString GameOblivion::steamAPPId() const return "22330"; } -QStringList GameOblivion::getPrimaryPlugins() +QStringList GameOblivion::getPrimaryPlugins() const { return { "oblivion.esm", "update.esm" }; } @@ -150,7 +150,7 @@ QIcon GameOblivion::gameIcon() const return MOBase::iconForExecutable(gameDirectory().absoluteFilePath(getBinaryName())); } -const std::map &GameOblivion::featureList() const +std::map GameOblivion::featureList() const { static std::map result { { typeid(BSAInvalidation), m_BSAInvalidation.get() }, diff --git a/src/games/oblivion/src/gameoblivion.h b/src/games/oblivion/src/gameoblivion.h index e63dab3e..c1d0534e 100644 --- a/src/games/oblivion/src/gameoblivion.h +++ b/src/games/oblivion/src/gameoblivion.h @@ -24,12 +24,12 @@ public: public: // IPluginGame interface - virtual QString gameName() const; - virtual QList executables(); - virtual void initializeProfile(const QDir &path, ProfileSettings settings) const; - virtual QString savegameExtension() const; - virtual QString steamAPPId() const; - virtual QStringList getPrimaryPlugins(); + virtual QString gameName() const override; + virtual QList executables() const override; + virtual void initializeProfile(const QDir &path, ProfileSettings settings) const override; + virtual QString savegameExtension() const override; + virtual QString steamAPPId() const override; + virtual QStringList getPrimaryPlugins() const override; virtual QIcon gameIcon() const override; virtual QString getBinaryName() const override; virtual QString getNexusName() const override; @@ -46,7 +46,7 @@ public: // IPlugin interface protected: - virtual const std::map &featureList() const; + virtual std::map featureList() const override; private: From da219e6824de83bcbbc800932824b199fa8555bc Mon Sep 17 00:00:00 2001 From: Thomas Tanner Date: Sun, 22 Nov 2015 21:17:29 +0000 Subject: [PATCH 0084/1544] [game_skyrim] Final eradication of igameinfo and adding python wrappers for IPluginGame --- src/games/skyrim/src/gameskyrim.cpp | 8 ++++---- src/games/skyrim/src/gameskyrim.h | 14 +++++++------- 2 files changed, 11 insertions(+), 11 deletions(-) diff --git a/src/games/skyrim/src/gameskyrim.cpp b/src/games/skyrim/src/gameskyrim.cpp index 89a5eb9c..373a8b7b 100644 --- a/src/games/skyrim/src/gameskyrim.cpp +++ b/src/games/skyrim/src/gameskyrim.cpp @@ -53,7 +53,7 @@ QString GameSkyrim::myGamesFolderName() const -QList GameSkyrim::executables() +QList GameSkyrim::executables() const { return QList() << ExecutableInfo("SKSE", findInGameFolder("skse_loader.exe")) @@ -140,9 +140,9 @@ QString GameSkyrim::steamAPPId() const return "72850"; } -QStringList GameSkyrim::getPrimaryPlugins() +QStringList GameSkyrim::getPrimaryPlugins() const { - return QStringList({ QString("skyrim.esm"), QString("update.esm") }); + return { "skyrim.esm", "update.esm" }; } QIcon GameSkyrim::gameIcon() const @@ -150,7 +150,7 @@ QIcon GameSkyrim::gameIcon() const return MOBase::iconForExecutable(gameDirectory().absoluteFilePath(getBinaryName())); } -const std::map &GameSkyrim::featureList() const +std::map GameSkyrim::featureList() const { static std::map result { { typeid(BSAInvalidation), m_BSAInvalidation.get() }, diff --git a/src/games/skyrim/src/gameskyrim.h b/src/games/skyrim/src/gameskyrim.h index 397added..8a02d920 100644 --- a/src/games/skyrim/src/gameskyrim.h +++ b/src/games/skyrim/src/gameskyrim.h @@ -24,12 +24,12 @@ public: public: // IPluginGame interface - virtual QString gameName() const; - virtual QList executables(); - virtual void initializeProfile(const QDir &path, ProfileSettings settings) const; - virtual QString savegameExtension() const; - virtual QString steamAPPId() const; - virtual QStringList getPrimaryPlugins(); + virtual QString gameName() const override; + virtual QList executables() const override; + virtual void initializeProfile(const QDir &path, ProfileSettings settings) const override; + virtual QString savegameExtension() const override; + virtual QString steamAPPId() const override; + virtual QStringList getPrimaryPlugins() const override; virtual QIcon gameIcon() const override; virtual QString getBinaryName() const override; virtual QString getNexusName() const override; @@ -46,7 +46,7 @@ public: // IPlugin interface protected: - virtual const std::map &featureList() const; + virtual std::map featureList() const override; private: From 71397e6bde5b128fe848fdcbe71f7f588e1c2822 Mon Sep 17 00:00:00 2001 From: Thomas Tanner Date: Mon, 23 Nov 2015 18:34:26 +0000 Subject: [PATCH 0085/1544] [game_fallout3] Remove most instances of GameInfo::getname, and transfer getDLCPlugins to the plugingame interface --- src/games/fallout3/src/gamefallout3.cpp | 5 +++++ src/games/fallout3/src/gamefallout3.h | 1 + 2 files changed, 6 insertions(+) diff --git a/src/games/fallout3/src/gamefallout3.cpp b/src/games/fallout3/src/gamefallout3.cpp index 9f82644e..1203507e 100644 --- a/src/games/fallout3/src/gamefallout3.cpp +++ b/src/games/fallout3/src/gamefallout3.cpp @@ -185,3 +185,8 @@ QStringList GameFallout3::getIniFiles() const { return { "fallout.ini", "falloutprefs.ini" }; } + +QStringList GameFallout3::getDLCPlugins() const +{ + return { "ThePitt.esm", "Anchorage.esm", "BrokenSteel.esm", "PointLookout.esm", "Zeta.esm" }; +} diff --git a/src/games/fallout3/src/gamefallout3.h b/src/games/fallout3/src/gamefallout3.h index 1e904728..3604d5d0 100644 --- a/src/games/fallout3/src/gamefallout3.h +++ b/src/games/fallout3/src/gamefallout3.h @@ -35,6 +35,7 @@ public: // IPluginGame interface virtual QString getBinaryName() const override; virtual QString getNexusName() const override; virtual QStringList getIniFiles() const override; + virtual QStringList getDLCPlugins() const override; public: // IPlugin interface From 875cc216ec58153eb314623cbeff1cf892c58ea7 Mon Sep 17 00:00:00 2001 From: Thomas Tanner Date: Mon, 23 Nov 2015 18:34:40 +0000 Subject: [PATCH 0086/1544] [game_falloutnv] Remove most instances of GameInfo::getname, and transfer getDLCPlugins to the plugingame interface --- src/games/falloutnv/src/gamefalloutnv.cpp | 7 +++++++ src/games/falloutnv/src/gamefalloutnv.h | 1 + 2 files changed, 8 insertions(+) diff --git a/src/games/falloutnv/src/gamefalloutnv.cpp b/src/games/falloutnv/src/gamefalloutnv.cpp index f792570d..0549cf81 100644 --- a/src/games/falloutnv/src/gamefalloutnv.cpp +++ b/src/games/falloutnv/src/gamefalloutnv.cpp @@ -176,3 +176,10 @@ QStringList GameFalloutNV::getIniFiles() const { return { "fallout.ini", "falloutprefs.ini" }; } + +QStringList GameFalloutNV::getDLCPlugins() const +{ + return { "DeadMoney.esm", "HonestHearts.esm", "OldWorldBlues.esm", + "LonesomeRoad.esm", "GunRunnersArsenal.esm", "CaravanPack.esm", + "ClassicPack.esm", "MercenaryPack.esm", "TribalPack.esm" }; +} diff --git a/src/games/falloutnv/src/gamefalloutnv.h b/src/games/falloutnv/src/gamefalloutnv.h index 271cadc0..dc3a9888 100644 --- a/src/games/falloutnv/src/gamefalloutnv.h +++ b/src/games/falloutnv/src/gamefalloutnv.h @@ -34,6 +34,7 @@ public: // IPluginGame interface virtual QString getBinaryName() const override; virtual QString getNexusName() const override; virtual QStringList getIniFiles() const override; + virtual QStringList getDLCPlugins() const override; public: // IPlugin interface From 7a12c501f4153c17c304cc268dbc0d616a895701 Mon Sep 17 00:00:00 2001 From: Thomas Tanner Date: Mon, 23 Nov 2015 18:34:56 +0000 Subject: [PATCH 0087/1544] [game_oblivion] Remove most instances of GameInfo::getname, and transfer getDLCPlugins to the plugingame interface --- src/games/oblivion/src/gameoblivion.cpp | 7 +++++++ src/games/oblivion/src/gameoblivion.h | 1 + 2 files changed, 8 insertions(+) diff --git a/src/games/oblivion/src/gameoblivion.cpp b/src/games/oblivion/src/gameoblivion.cpp index 74d0fdc5..bf1001ef 100644 --- a/src/games/oblivion/src/gameoblivion.cpp +++ b/src/games/oblivion/src/gameoblivion.cpp @@ -175,3 +175,10 @@ QStringList GameOblivion::getIniFiles() const { return { "oblivion.ini", "oblivionprefs.ini" }; } + +QStringList GameOblivion::getDLCPlugins() const +{ + return { "DLCShiveringIsles.esp", "Knights.esp", "DLCFrostcrag.esp", + "DLCSpellTomes.esp", "DLCMehrunesRazor.esp", "DLCOrrery.esp", + "DLCThievesDen.esp", "DLCVileLair.esp", "DLCHorseArmor.esp" }; +} diff --git a/src/games/oblivion/src/gameoblivion.h b/src/games/oblivion/src/gameoblivion.h index c1d0534e..05a04b12 100644 --- a/src/games/oblivion/src/gameoblivion.h +++ b/src/games/oblivion/src/gameoblivion.h @@ -34,6 +34,7 @@ public: // IPluginGame interface virtual QString getBinaryName() const override; virtual QString getNexusName() const override; virtual QStringList getIniFiles() const override; + virtual QStringList getDLCPlugins() const override; public: // IPlugin interface From 79fb3c8c3470989959560d59b5d740a20a39fd41 Mon Sep 17 00:00:00 2001 From: Thomas Tanner Date: Mon, 23 Nov 2015 18:35:16 +0000 Subject: [PATCH 0088/1544] [game_skyrim] Remove most instances of GameInfo::getname, and transfer getDLCPlugins to the plugingame interface --- src/games/skyrim/src/gameskyrim.cpp | 6 ++++++ src/games/skyrim/src/gameskyrim.h | 1 + 2 files changed, 7 insertions(+) diff --git a/src/games/skyrim/src/gameskyrim.cpp b/src/games/skyrim/src/gameskyrim.cpp index 373a8b7b..59b329b3 100644 --- a/src/games/skyrim/src/gameskyrim.cpp +++ b/src/games/skyrim/src/gameskyrim.cpp @@ -175,3 +175,9 @@ QStringList GameSkyrim::getIniFiles() const { return { "skyrim.ini", "skyrimprefs.ini" }; } + +QStringList GameSkyrim::getDLCPlugins() const +{ + return { "Dawnguard.esm", "Dragonborn.esm", "HearthFires.esm", + "HighResTexturePack01.esp", "HighResTexturePack02.esp", "HighResTexturePack03.esp" }; +} diff --git a/src/games/skyrim/src/gameskyrim.h b/src/games/skyrim/src/gameskyrim.h index 8a02d920..c570c0cd 100644 --- a/src/games/skyrim/src/gameskyrim.h +++ b/src/games/skyrim/src/gameskyrim.h @@ -34,6 +34,7 @@ public: // IPluginGame interface virtual QString getBinaryName() const override; virtual QString getNexusName() const override; virtual QStringList getIniFiles() const override; + virtual QStringList getDLCPlugins() const override; public: // IPlugin interface From 8013fbdfac41eeafac9c9403861ceff0d54b4021 Mon Sep 17 00:00:00 2001 From: Thomas Tanner Date: Tue, 24 Nov 2015 14:20:08 +0000 Subject: [PATCH 0089/1544] [game_skyrim] Replace GameInfo::getLoadorderMechanism with IPluginGame::getLoadOrderMechanism --- src/games/skyrim/src/SConscript | 2 ++ src/games/skyrim/src/gameskyrim.cpp | 55 ++++++++++++++++++++++++++++- src/games/skyrim/src/gameskyrim.h | 1 + 3 files changed, 57 insertions(+), 1 deletion(-) diff --git a/src/games/skyrim/src/SConscript b/src/games/skyrim/src/SConscript index 3382d84b..75b5fa99 100644 --- a/src/games/skyrim/src/SConscript +++ b/src/games/skyrim/src/SConscript @@ -6,6 +6,8 @@ env.AppendUnique(CPPDEFINES = [ 'GAMESKYRIM_LIBRARY' ]) env.RequiresGamebryo() +env.AppendUnique(LIBS = [ 'Version' ]) + lib = env.SharedLibrary('gameSkyrim', env.Glob('*.cpp')) env.InstallModule(lib) diff --git a/src/games/skyrim/src/gameskyrim.cpp b/src/games/skyrim/src/gameskyrim.cpp index 59b329b3..7f07851f 100644 --- a/src/games/skyrim/src/gameskyrim.cpp +++ b/src/games/skyrim/src/gameskyrim.cpp @@ -1,11 +1,19 @@ #include "gameskyrim.h" + #include #include #include #include -#include + +#include #include +#include + +#include +#include +#include + using namespace MOBase; @@ -181,3 +189,48 @@ QStringList GameSkyrim::getDLCPlugins() const return { "Dawnguard.esm", "Dragonborn.esm", "HearthFires.esm", "HighResTexturePack01.esp", "HighResTexturePack02.esp", "HighResTexturePack03.esp" }; } + +namespace { +//Note: This is ripped off from shared/util. And in an upcoming move, the fomod +//installer requires something similar. I suspect I should abstract this out +//into gamebro and add a getVersion mechanism in gamebryo (or lower level) + +VS_FIXEDFILEINFO GetFileVersion(const std::wstring &fileName) +{ + DWORD handle = 0UL; + DWORD size = ::GetFileVersionInfoSizeW(fileName.c_str(), &handle); + if (size == 0) { + throw std::runtime_error("failed to determine file version info size"); + } + + std::vector buffer(size); + handle = 0UL; + if (!::GetFileVersionInfoW(fileName.c_str(), handle, size, buffer.data())) { + throw std::runtime_error("failed to determine file version info"); + } + + void *versionInfoPtr = nullptr; + UINT versionInfoLength = 0; + if (!::VerQueryValue(buffer.data(), L"\\", &versionInfoPtr, &versionInfoLength)) { + throw std::runtime_error("failed to determine file version"); + } + + return *static_cast(versionInfoPtr); +} + +} + +IPluginGame::LoadOrderMechanism GameSkyrim::getLoadOrderMechanism() const +{ + try { + std::wstring fileName = gameDirectory().absoluteFilePath(getBinaryName()).toStdWString().c_str(); + VS_FIXEDFILEINFO versionInfo = ::GetFileVersion(fileName); + if ((versionInfo.dwFileVersionMS > 0x10004) || // version >= 1.5.x? + ((versionInfo.dwFileVersionMS == 0x10004) && (versionInfo.dwFileVersionLS >= 0x1A0000))) { // version >= ?.4.26 + return LoadOrderMechanism::PluginsTxt; + } + } catch (const std::exception &e) { + qCritical() << "TESV.exe is invalid: " << e.what(); + } + return LoadOrderMechanism::FileTime; +} diff --git a/src/games/skyrim/src/gameskyrim.h b/src/games/skyrim/src/gameskyrim.h index c570c0cd..2c05b3d6 100644 --- a/src/games/skyrim/src/gameskyrim.h +++ b/src/games/skyrim/src/gameskyrim.h @@ -35,6 +35,7 @@ public: // IPluginGame interface virtual QString getNexusName() const override; virtual QStringList getIniFiles() const override; virtual QStringList getDLCPlugins() const override; + virtual LoadOrderMechanism getLoadOrderMechanism() const override; public: // IPlugin interface From 25f0b48fca2d7fd0890379f623b6f3da1f2fc4e9 Mon Sep 17 00:00:00 2001 From: Thomas Tanner Date: Tue, 24 Nov 2015 14:20:26 +0000 Subject: [PATCH 0090/1544] Replace GameInfo::getLoadorderMechanism with IPluginGame::getLoadOrderMechanism --- src/gamegamebryo.cpp | 5 +++++ src/gamegamebryo.h | 15 ++++++++------- 2 files changed, 13 insertions(+), 7 deletions(-) diff --git a/src/gamegamebryo.cpp b/src/gamegamebryo.cpp index 68c2fb8a..811637db 100644 --- a/src/gamegamebryo.cpp +++ b/src/gamegamebryo.cpp @@ -154,3 +154,8 @@ void GameGamebryo::setGameVariant(const QString &variant) { m_GameVariant = variant; } + +MOBase::IPluginGame::LoadOrderMechanism GameGamebryo::getLoadOrderMechanism() const +{ + return LoadOrderMechanism::FileTime; +} diff --git a/src/gamegamebryo.h b/src/gamegamebryo.h index d0cb2c86..6f0e56ae 100644 --- a/src/gamegamebryo.h +++ b/src/gamegamebryo.h @@ -20,16 +20,17 @@ public: public: // IPluginGame interface - virtual QDir gameDirectory() const; - virtual QDir dataDirectory() const; - virtual void setGamePath(const QString &path); - virtual QDir savesDirectory() const; - virtual QDir documentsDirectory() const; + virtual QDir gameDirectory() const override; + virtual QDir dataDirectory() const override; + virtual void setGamePath(const QString &path) override; + virtual QDir savesDirectory() const override; + virtual QDir documentsDirectory() const override; virtual bool isInstalled() const override; - virtual QStringList gameVariants() const; - virtual void setGameVariant(const QString &variant); + virtual QStringList gameVariants() const override; + virtual void setGameVariant(const QString &variant) override; + virtual LoadOrderMechanism getLoadOrderMechanism() const override; protected: From 9c22478a8a198f61decee65603d1de816d63609e Mon Sep 17 00:00:00 2001 From: Thomas Tanner Date: Tue, 24 Nov 2015 16:14:58 +0000 Subject: [PATCH 0091/1544] [game_fallout3] Replace GameInfo::getNexusModID with IPluginGame::getNexusModOrganizerID() Also implement IPluginGame::getNexusGameID() but not hooked it in yet. --- src/games/fallout3/src/gamefallout3.cpp | 10 ++++++++++ src/games/fallout3/src/gamefallout3.h | 2 ++ 2 files changed, 12 insertions(+) diff --git a/src/games/fallout3/src/gamefallout3.cpp b/src/games/fallout3/src/gamefallout3.cpp index 1203507e..09b36e2a 100644 --- a/src/games/fallout3/src/gamefallout3.cpp +++ b/src/games/fallout3/src/gamefallout3.cpp @@ -190,3 +190,13 @@ QStringList GameFallout3::getDLCPlugins() const { return { "ThePitt.esm", "Anchorage.esm", "BrokenSteel.esm", "PointLookout.esm", "Zeta.esm" }; } + +int GameFallout3::getNexusModOrganizerID() const +{ + return 16348; +} + +int GameFallout3::getNexusGameID() const +{ + return 120; +} diff --git a/src/games/fallout3/src/gamefallout3.h b/src/games/fallout3/src/gamefallout3.h index 3604d5d0..217fb84a 100644 --- a/src/games/fallout3/src/gamefallout3.h +++ b/src/games/fallout3/src/gamefallout3.h @@ -36,6 +36,8 @@ public: // IPluginGame interface virtual QString getNexusName() const override; virtual QStringList getIniFiles() const override; virtual QStringList getDLCPlugins() const override; + virtual int getNexusModOrganizerID() const override; + virtual int getNexusGameID() const override; public: // IPlugin interface From 17add708d17e12f25bfaefc720dcda6152a305a2 Mon Sep 17 00:00:00 2001 From: Thomas Tanner Date: Tue, 24 Nov 2015 16:15:14 +0000 Subject: [PATCH 0092/1544] [game_falloutnv] Replace GameInfo::getNexusModID with IPluginGame::getNexusModOrganizerID() Also implement IPluginGame::getNexusGameID() but not hooked it in yet. --- src/games/falloutnv/src/gamefalloutnv.cpp | 10 ++++++++++ src/games/falloutnv/src/gamefalloutnv.h | 2 ++ 2 files changed, 12 insertions(+) diff --git a/src/games/falloutnv/src/gamefalloutnv.cpp b/src/games/falloutnv/src/gamefalloutnv.cpp index 0549cf81..ec205f33 100644 --- a/src/games/falloutnv/src/gamefalloutnv.cpp +++ b/src/games/falloutnv/src/gamefalloutnv.cpp @@ -183,3 +183,13 @@ QStringList GameFalloutNV::getDLCPlugins() const "LonesomeRoad.esm", "GunRunnersArsenal.esm", "CaravanPack.esm", "ClassicPack.esm", "MercenaryPack.esm", "TribalPack.esm" }; } + +int GameFalloutNV::getNexusModOrganizerID() const +{ + return 42572; +} + +int GameFalloutNV::getNexusGameID() const +{ + return 130; +} diff --git a/src/games/falloutnv/src/gamefalloutnv.h b/src/games/falloutnv/src/gamefalloutnv.h index dc3a9888..e8a95bc0 100644 --- a/src/games/falloutnv/src/gamefalloutnv.h +++ b/src/games/falloutnv/src/gamefalloutnv.h @@ -35,6 +35,8 @@ public: // IPluginGame interface virtual QString getNexusName() const override; virtual QStringList getIniFiles() const override; virtual QStringList getDLCPlugins() const override; + virtual int getNexusModOrganizerID() const override; + virtual int getNexusGameID() const override; public: // IPlugin interface From 05d7e7b8c6533a7745381442528af4504c04a008 Mon Sep 17 00:00:00 2001 From: Thomas Tanner Date: Tue, 24 Nov 2015 16:15:28 +0000 Subject: [PATCH 0093/1544] [game_oblivion] Replace GameInfo::getNexusModID with IPluginGame::getNexusModOrganizerID() Also implement IPluginGame::getNexusGameID() but not hooked it in yet. --- src/games/oblivion/src/gameoblivion.cpp | 11 +++++++++++ src/games/oblivion/src/gameoblivion.h | 2 ++ 2 files changed, 13 insertions(+) diff --git a/src/games/oblivion/src/gameoblivion.cpp b/src/games/oblivion/src/gameoblivion.cpp index bf1001ef..72c47258 100644 --- a/src/games/oblivion/src/gameoblivion.cpp +++ b/src/games/oblivion/src/gameoblivion.cpp @@ -182,3 +182,14 @@ QStringList GameOblivion::getDLCPlugins() const "DLCSpellTomes.esp", "DLCMehrunesRazor.esp", "DLCOrrery.esp", "DLCThievesDen.esp", "DLCVileLair.esp", "DLCHorseArmor.esp" }; } + + +int GameOblivion::getNexusModOrganizerID() const +{ + return 38277; +} + +int GameOblivion::getNexusGameID() const +{ + return 101; +} diff --git a/src/games/oblivion/src/gameoblivion.h b/src/games/oblivion/src/gameoblivion.h index 05a04b12..b5191b67 100644 --- a/src/games/oblivion/src/gameoblivion.h +++ b/src/games/oblivion/src/gameoblivion.h @@ -35,6 +35,8 @@ public: // IPluginGame interface virtual QString getNexusName() const override; virtual QStringList getIniFiles() const override; virtual QStringList getDLCPlugins() const override; + virtual int getNexusModOrganizerID() const override; + virtual int getNexusGameID() const override; public: // IPlugin interface From 55686dff574b3713bf2538e05e8764a43651776f Mon Sep 17 00:00:00 2001 From: Thomas Tanner Date: Tue, 24 Nov 2015 16:15:40 +0000 Subject: [PATCH 0094/1544] [game_skyrim] Replace GameInfo::getNexusModID with IPluginGame::getNexusModOrganizerID() Also implement IPluginGame::getNexusGameID() but not hooked it in yet. --- src/games/skyrim/src/gameskyrim.cpp | 13 ++++++++++++- src/games/skyrim/src/gameskyrim.h | 2 ++ 2 files changed, 14 insertions(+), 1 deletion(-) diff --git a/src/games/skyrim/src/gameskyrim.cpp b/src/games/skyrim/src/gameskyrim.cpp index 7f07851f..b72e8149 100644 --- a/src/games/skyrim/src/gameskyrim.cpp +++ b/src/games/skyrim/src/gameskyrim.cpp @@ -193,7 +193,7 @@ QStringList GameSkyrim::getDLCPlugins() const namespace { //Note: This is ripped off from shared/util. And in an upcoming move, the fomod //installer requires something similar. I suspect I should abstract this out -//into gamebro and add a getVersion mechanism in gamebryo (or lower level) +//into gamebryo (or lower level) VS_FIXEDFILEINFO GetFileVersion(const std::wstring &fileName) { @@ -234,3 +234,14 @@ IPluginGame::LoadOrderMechanism GameSkyrim::getLoadOrderMechanism() const } return LoadOrderMechanism::FileTime; } + + +int GameSkyrim::getNexusModOrganizerID() const +{ + return 1334; +} + +int GameSkyrim::getNexusGameID() const +{ + return 110; +} diff --git a/src/games/skyrim/src/gameskyrim.h b/src/games/skyrim/src/gameskyrim.h index 2c05b3d6..279abada 100644 --- a/src/games/skyrim/src/gameskyrim.h +++ b/src/games/skyrim/src/gameskyrim.h @@ -36,6 +36,8 @@ public: // IPluginGame interface virtual QStringList getIniFiles() const override; virtual QStringList getDLCPlugins() const override; virtual LoadOrderMechanism getLoadOrderMechanism() const override; + virtual int getNexusModOrganizerID() const override; + virtual int getNexusGameID() const override; public: // IPlugin interface From 2d293bee20d4ee80f3a864f437ea7ade80d2282a Mon Sep 17 00:00:00 2001 From: Thomas Tanner Date: Thu, 26 Nov 2015 07:33:47 +0000 Subject: [PATCH 0095/1544] [game_fallout3] Yet more const correctness --- src/games/fallout3/src/fallout3bsainvalidation.cpp | 2 +- src/games/fallout3/src/fallout3bsainvalidation.h | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/src/games/fallout3/src/fallout3bsainvalidation.cpp b/src/games/fallout3/src/fallout3bsainvalidation.cpp index f75f7da8..9fde6f05 100644 --- a/src/games/fallout3/src/fallout3bsainvalidation.cpp +++ b/src/games/fallout3/src/fallout3bsainvalidation.cpp @@ -1,6 +1,6 @@ #include "fallout3bsainvalidation.h" -Fallout3BSAInvalidation::Fallout3BSAInvalidation(const std::shared_ptr &dataArchives, MOBase::IPluginGame *game) +Fallout3BSAInvalidation::Fallout3BSAInvalidation(const std::shared_ptr &dataArchives, MOBase::IPluginGame const *game) : GamebryoBSAInvalidation(dataArchives, "fallout.ini", game) { } diff --git a/src/games/fallout3/src/fallout3bsainvalidation.h b/src/games/fallout3/src/fallout3bsainvalidation.h index 11d13107..2ae7a212 100644 --- a/src/games/fallout3/src/fallout3bsainvalidation.h +++ b/src/games/fallout3/src/fallout3bsainvalidation.h @@ -11,7 +11,7 @@ class Fallout3BSAInvalidation : public GamebryoBSAInvalidation { public: - Fallout3BSAInvalidation(const std::shared_ptr &dataArchives, MOBase::IPluginGame *game); + Fallout3BSAInvalidation(const std::shared_ptr &dataArchives, MOBase::IPluginGame const *game); private: From c91937339b7d0f0b003cc2806131941575dab514 Mon Sep 17 00:00:00 2001 From: Thomas Tanner Date: Thu, 26 Nov 2015 07:34:18 +0000 Subject: [PATCH 0096/1544] [game_falloutnv] Yet more const correctness --- src/games/falloutnv/src/falloutnvbsainvalidation.cpp | 2 +- src/games/falloutnv/src/falloutnvbsainvalidation.h | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/src/games/falloutnv/src/falloutnvbsainvalidation.cpp b/src/games/falloutnv/src/falloutnvbsainvalidation.cpp index 22581654..a742c32c 100644 --- a/src/games/falloutnv/src/falloutnvbsainvalidation.cpp +++ b/src/games/falloutnv/src/falloutnvbsainvalidation.cpp @@ -1,6 +1,6 @@ #include "falloutnvbsainvalidation.h" -FalloutNVBSAInvalidation::FalloutNVBSAInvalidation(const std::shared_ptr &dataArchives, MOBase::IPluginGame *game) +FalloutNVBSAInvalidation::FalloutNVBSAInvalidation(const std::shared_ptr &dataArchives, MOBase::IPluginGame const *game) : GamebryoBSAInvalidation(dataArchives, "fallout.ini", game) { } diff --git a/src/games/falloutnv/src/falloutnvbsainvalidation.h b/src/games/falloutnv/src/falloutnvbsainvalidation.h index 0cd77a36..215141b0 100644 --- a/src/games/falloutnv/src/falloutnvbsainvalidation.h +++ b/src/games/falloutnv/src/falloutnvbsainvalidation.h @@ -11,7 +11,7 @@ class FalloutNVBSAInvalidation : public GamebryoBSAInvalidation { public: - FalloutNVBSAInvalidation(const std::shared_ptr &dataArchives, MOBase::IPluginGame *game); + FalloutNVBSAInvalidation(const std::shared_ptr &dataArchives, MOBase::IPluginGame const *game); private: From 3d23cb3fc52c1a366ab9b707112aa826d91492a2 Mon Sep 17 00:00:00 2001 From: Thomas Tanner Date: Thu, 26 Nov 2015 07:36:27 +0000 Subject: [PATCH 0097/1544] Oops. Forgot the necessary underlying code for the two URL methods. --- src/gamebryobsainvalidation.cpp | 2 +- src/gamebryobsainvalidation.h | 4 ++-- src/gamegamebryo.cpp | 10 ++++++++++ src/gamegamebryo.h | 2 ++ 4 files changed, 15 insertions(+), 3 deletions(-) diff --git a/src/gamebryobsainvalidation.cpp b/src/gamebryobsainvalidation.cpp index 5ed92c5c..af6e2d08 100644 --- a/src/gamebryobsainvalidation.cpp +++ b/src/gamebryobsainvalidation.cpp @@ -14,7 +14,7 @@ GamebryoBSAInvalidation::GamebryoBSAInvalidation(const std::shared_ptr &dataArchives , const QString &iniFilename - , MOBase::IPluginGame *game) + , MOBase::IPluginGame const *game) : m_DataArchives(dataArchives) , m_IniFileName(iniFilename) , m_Game(game) diff --git a/src/gamebryobsainvalidation.h b/src/gamebryobsainvalidation.h index d59e75f5..99a988d7 100644 --- a/src/gamebryobsainvalidation.h +++ b/src/gamebryobsainvalidation.h @@ -17,7 +17,7 @@ public: GamebryoBSAInvalidation(const std::shared_ptr &dataArchives, const QString &iniFilename, - MOBase::IPluginGame *game); + MOBase::IPluginGame const *game); virtual bool isInvalidationBSA(const QString &bsaName) override; virtual void deactivate(MOBase::IProfile *profile) override; @@ -32,7 +32,7 @@ private: std::shared_ptr m_DataArchives; QString m_IniFileName; - MOBase::IPluginGame *m_Game; + MOBase::IPluginGame const *m_Game; }; diff --git a/src/gamegamebryo.cpp b/src/gamegamebryo.cpp index 811637db..5a32796f 100644 --- a/src/gamegamebryo.cpp +++ b/src/gamegamebryo.cpp @@ -159,3 +159,13 @@ MOBase::IPluginGame::LoadOrderMechanism GameGamebryo::getLoadOrderMechanism() co { return LoadOrderMechanism::FileTime; } + +QString GameGamebryo::getNexusManagementURL() const +{ + return "http://nmm.nexusmods.com/" + getNexusName().toLower(); +} + +QString GameGamebryo::getNexusDisplayURL() const +{ + return "http://www.nexusmods.com/" + getNexusName().toLower(); +} diff --git a/src/gamegamebryo.h b/src/gamegamebryo.h index 6f0e56ae..8cf191d8 100644 --- a/src/gamegamebryo.h +++ b/src/gamegamebryo.h @@ -31,6 +31,8 @@ public: // IPluginGame interface virtual QStringList gameVariants() const override; virtual void setGameVariant(const QString &variant) override; virtual LoadOrderMechanism getLoadOrderMechanism() const override; + virtual QString getNexusManagementURL() const override; + virtual QString getNexusDisplayURL() const override; protected: From b50a864a0d861203049f502ab52e5f737baf5502 Mon Sep 17 00:00:00 2001 From: Thomas Tanner Date: Thu, 26 Nov 2015 07:36:48 +0000 Subject: [PATCH 0098/1544] [game_oblivion] Yet more const correctness --- src/games/oblivion/src/oblivionbsainvalidation.cpp | 2 +- src/games/oblivion/src/oblivionbsainvalidation.h | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/src/games/oblivion/src/oblivionbsainvalidation.cpp b/src/games/oblivion/src/oblivionbsainvalidation.cpp index c1c54933..71806d02 100644 --- a/src/games/oblivion/src/oblivionbsainvalidation.cpp +++ b/src/games/oblivion/src/oblivionbsainvalidation.cpp @@ -1,7 +1,7 @@ #include "oblivionbsainvalidation.h" -OblivionBSAInvalidation::OblivionBSAInvalidation(const std::shared_ptr &dataArchives, MOBase::IPluginGame *game) +OblivionBSAInvalidation::OblivionBSAInvalidation(const std::shared_ptr &dataArchives, MOBase::IPluginGame const *game) : GamebryoBSAInvalidation(dataArchives, "oblivion.ini", game) { } diff --git a/src/games/oblivion/src/oblivionbsainvalidation.h b/src/games/oblivion/src/oblivionbsainvalidation.h index bf018735..e4862f68 100644 --- a/src/games/oblivion/src/oblivionbsainvalidation.h +++ b/src/games/oblivion/src/oblivionbsainvalidation.h @@ -11,7 +11,7 @@ class OblivionBSAInvalidation : public GamebryoBSAInvalidation { public: - OblivionBSAInvalidation(const std::shared_ptr &dataArchives, MOBase::IPluginGame *game); + OblivionBSAInvalidation(const std::shared_ptr &dataArchives, MOBase::IPluginGame const *game); private: From 4041eee99c80dc281b343a9b277ea3f56a124317 Mon Sep 17 00:00:00 2001 From: Thomas Tanner Date: Thu, 26 Nov 2015 07:37:02 +0000 Subject: [PATCH 0099/1544] [game_skyrim] Yet more const correctness --- src/games/skyrim/src/skyrimbsainvalidation.cpp | 2 +- src/games/skyrim/src/skyrimbsainvalidation.h | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/src/games/skyrim/src/skyrimbsainvalidation.cpp b/src/games/skyrim/src/skyrimbsainvalidation.cpp index a153b18c..9d2be945 100644 --- a/src/games/skyrim/src/skyrimbsainvalidation.cpp +++ b/src/games/skyrim/src/skyrimbsainvalidation.cpp @@ -1,6 +1,6 @@ #include "skyrimbsainvalidation.h" -SkyrimBSAInvalidation::SkyrimBSAInvalidation(const std::shared_ptr &dataArchives, MOBase::IPluginGame *game) +SkyrimBSAInvalidation::SkyrimBSAInvalidation(const std::shared_ptr &dataArchives, MOBase::IPluginGame const *game) : GamebryoBSAInvalidation(dataArchives, "skyrim.ini", game) { } diff --git a/src/games/skyrim/src/skyrimbsainvalidation.h b/src/games/skyrim/src/skyrimbsainvalidation.h index 99557791..b03ffd8d 100644 --- a/src/games/skyrim/src/skyrimbsainvalidation.h +++ b/src/games/skyrim/src/skyrimbsainvalidation.h @@ -11,7 +11,7 @@ class SkyrimBSAInvalidation : public GamebryoBSAInvalidation { public: - SkyrimBSAInvalidation(const std::shared_ptr &dataArchives, MOBase::IPluginGame *game); + SkyrimBSAInvalidation(const std::shared_ptr &dataArchives, MOBase::IPluginGame const *game); private: From f2690d262b51475c02311e7302ef457bf449d926 Mon Sep 17 00:00:00 2001 From: Thomas Tanner Date: Thu, 26 Nov 2015 17:44:14 +0000 Subject: [PATCH 0100/1544] Remove the getNexusManagementURL as it is a property of how you talk to nexus, not the game --- src/gamegamebryo.cpp | 19 +++++++++++-------- src/gamegamebryo.h | 2 +- 2 files changed, 12 insertions(+), 9 deletions(-) diff --git a/src/gamegamebryo.cpp b/src/gamegamebryo.cpp index 5a32796f..ab2dfd80 100644 --- a/src/gamegamebryo.cpp +++ b/src/gamegamebryo.cpp @@ -1,8 +1,9 @@ #include "gamegamebryo.h" -#include -#include -#include +#include "utility.h" +#include "scopeguard.h" + +#include GameGamebryo::GameGamebryo() { @@ -160,12 +161,14 @@ MOBase::IPluginGame::LoadOrderMechanism GameGamebryo::getLoadOrderMechanism() co return LoadOrderMechanism::FileTime; } -QString GameGamebryo::getNexusManagementURL() const -{ - return "http://nmm.nexusmods.com/" + getNexusName().toLower(); -} - QString GameGamebryo::getNexusDisplayURL() const { return "http://www.nexusmods.com/" + getNexusName().toLower(); } + +bool GameGamebryo::isRelatedURL(QUrl const &url) const +{ + QString const name(url.toString()); + return name.startsWith(getNexusDisplayURL() + "/") || + name.startsWith("http://" + getNexusName().toLower() + ".nexusmods.com/mods/"); +} diff --git a/src/gamegamebryo.h b/src/gamegamebryo.h index 8cf191d8..212bcb31 100644 --- a/src/gamegamebryo.h +++ b/src/gamegamebryo.h @@ -31,8 +31,8 @@ public: // IPluginGame interface virtual QStringList gameVariants() const override; virtual void setGameVariant(const QString &variant) override; virtual LoadOrderMechanism getLoadOrderMechanism() const override; - virtual QString getNexusManagementURL() const override; virtual QString getNexusDisplayURL() const override; + virtual bool isRelatedURL(QUrl const &) const override; protected: From 151015247b01f6016d5c23ca1e6469d501c6192f Mon Sep 17 00:00:00 2001 From: Thomas Tanner Date: Thu, 26 Nov 2015 21:03:46 +0000 Subject: [PATCH 0101/1544] Replaced the IPluginGame getNexusDisplayURL with some APIs in NexusInterface It makes more sense to have them here as they have very little to do with the game, more to do with the origin of the mod. --- src/gamegamebryo.cpp | 12 ------------ src/gamegamebryo.h | 2 -- 2 files changed, 14 deletions(-) diff --git a/src/gamegamebryo.cpp b/src/gamegamebryo.cpp index ab2dfd80..4cce716f 100644 --- a/src/gamegamebryo.cpp +++ b/src/gamegamebryo.cpp @@ -160,15 +160,3 @@ MOBase::IPluginGame::LoadOrderMechanism GameGamebryo::getLoadOrderMechanism() co { return LoadOrderMechanism::FileTime; } - -QString GameGamebryo::getNexusDisplayURL() const -{ - return "http://www.nexusmods.com/" + getNexusName().toLower(); -} - -bool GameGamebryo::isRelatedURL(QUrl const &url) const -{ - QString const name(url.toString()); - return name.startsWith(getNexusDisplayURL() + "/") || - name.startsWith("http://" + getNexusName().toLower() + ".nexusmods.com/mods/"); -} diff --git a/src/gamegamebryo.h b/src/gamegamebryo.h index 212bcb31..6f0e56ae 100644 --- a/src/gamegamebryo.h +++ b/src/gamegamebryo.h @@ -31,8 +31,6 @@ public: // IPluginGame interface virtual QStringList gameVariants() const override; virtual void setGameVariant(const QString &variant) override; virtual LoadOrderMechanism getLoadOrderMechanism() const override; - virtual QString getNexusDisplayURL() const override; - virtual bool isRelatedURL(QUrl const &) const override; protected: From 49d5f899c7ee2be17472aea9f517f87494b29abe Mon Sep 17 00:00:00 2001 From: Thomas Tanner Date: Thu, 26 Nov 2015 21:14:16 +0000 Subject: [PATCH 0102/1544] [game_fallout3] Renamed getNexusName to getGameShortName as previously because it hopefully isn't too nexus related. --- src/games/fallout3/src/gamefallout3.cpp | 2 +- src/games/fallout3/src/gamefallout3.h | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/src/games/fallout3/src/gamefallout3.cpp b/src/games/fallout3/src/gamefallout3.cpp index 09b36e2a..0d0f49c3 100644 --- a/src/games/fallout3/src/gamefallout3.cpp +++ b/src/games/fallout3/src/gamefallout3.cpp @@ -176,7 +176,7 @@ QString GameFallout3::getBinaryName() const return "Fallout3.exe"; } -QString GameFallout3::getNexusName() const +QString GameFallout3::getGameShortName() const { return "Fallout3"; } diff --git a/src/games/fallout3/src/gamefallout3.h b/src/games/fallout3/src/gamefallout3.h index 217fb84a..03ec630e 100644 --- a/src/games/fallout3/src/gamefallout3.h +++ b/src/games/fallout3/src/gamefallout3.h @@ -33,7 +33,7 @@ public: // IPluginGame interface virtual QIcon gameIcon() const override; virtual QStringList gameVariants() const; virtual QString getBinaryName() const override; - virtual QString getNexusName() const override; + virtual QString getGameShortName() const override; virtual QStringList getIniFiles() const override; virtual QStringList getDLCPlugins() const override; virtual int getNexusModOrganizerID() const override; From 9b6c0f0610dbadfb58cf9273150b11eaa0486d8f Mon Sep 17 00:00:00 2001 From: Thomas Tanner Date: Thu, 26 Nov 2015 21:14:28 +0000 Subject: [PATCH 0103/1544] [game_falloutnv] Renamed getNexusName to getGameShortName as previously because it hopefully isn't too nexus related. --- src/games/falloutnv/src/gamefalloutnv.cpp | 2 +- src/games/falloutnv/src/gamefalloutnv.h | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/src/games/falloutnv/src/gamefalloutnv.cpp b/src/games/falloutnv/src/gamefalloutnv.cpp index ec205f33..8e9c1c91 100644 --- a/src/games/falloutnv/src/gamefalloutnv.cpp +++ b/src/games/falloutnv/src/gamefalloutnv.cpp @@ -167,7 +167,7 @@ QString GameFalloutNV::getBinaryName() const return "FalloutNV.exe"; } -QString GameFalloutNV::getNexusName() const +QString GameFalloutNV::getGameShortName() const { return "FalloutNV"; } diff --git a/src/games/falloutnv/src/gamefalloutnv.h b/src/games/falloutnv/src/gamefalloutnv.h index e8a95bc0..f6dbbe96 100644 --- a/src/games/falloutnv/src/gamefalloutnv.h +++ b/src/games/falloutnv/src/gamefalloutnv.h @@ -32,7 +32,7 @@ public: // IPluginGame interface virtual QStringList getPrimaryPlugins() const override; virtual QIcon gameIcon() const override; virtual QString getBinaryName() const override; - virtual QString getNexusName() const override; + virtual QString getGameShortName() const override; virtual QStringList getIniFiles() const override; virtual QStringList getDLCPlugins() const override; virtual int getNexusModOrganizerID() const override; From 857a7f3e177d6b8d32658f14b7d8b0d888ea35c6 Mon Sep 17 00:00:00 2001 From: Thomas Tanner Date: Thu, 26 Nov 2015 21:14:47 +0000 Subject: [PATCH 0104/1544] [game_oblivion] Renamed getNexusName to getGameShortName as previously because it hopefully isn't too nexus related. --- src/games/oblivion/src/gameoblivion.cpp | 2 +- src/games/oblivion/src/gameoblivion.h | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/src/games/oblivion/src/gameoblivion.cpp b/src/games/oblivion/src/gameoblivion.cpp index 72c47258..13879f83 100644 --- a/src/games/oblivion/src/gameoblivion.cpp +++ b/src/games/oblivion/src/gameoblivion.cpp @@ -166,7 +166,7 @@ QString GameOblivion::getBinaryName() const return "Oblivion.exe"; } -QString GameOblivion::getNexusName() const +QString GameOblivion::getGameShortName() const { return "Oblivion"; } diff --git a/src/games/oblivion/src/gameoblivion.h b/src/games/oblivion/src/gameoblivion.h index b5191b67..3da1e712 100644 --- a/src/games/oblivion/src/gameoblivion.h +++ b/src/games/oblivion/src/gameoblivion.h @@ -32,7 +32,7 @@ public: // IPluginGame interface virtual QStringList getPrimaryPlugins() const override; virtual QIcon gameIcon() const override; virtual QString getBinaryName() const override; - virtual QString getNexusName() const override; + virtual QString getGameShortName() const override; virtual QStringList getIniFiles() const override; virtual QStringList getDLCPlugins() const override; virtual int getNexusModOrganizerID() const override; From 125a07cdee53aa03ba9062aa610d731bfd0fb7e5 Mon Sep 17 00:00:00 2001 From: Thomas Tanner Date: Thu, 26 Nov 2015 21:15:05 +0000 Subject: [PATCH 0105/1544] [game_skyrim] Renamed getNexusName to getGameShortName as previously because it hopefully isn't too nexus related. --- src/games/skyrim/src/gameskyrim.cpp | 2 +- src/games/skyrim/src/gameskyrim.h | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/src/games/skyrim/src/gameskyrim.cpp b/src/games/skyrim/src/gameskyrim.cpp index b72e8149..e28bdf93 100644 --- a/src/games/skyrim/src/gameskyrim.cpp +++ b/src/games/skyrim/src/gameskyrim.cpp @@ -174,7 +174,7 @@ QString GameSkyrim::getBinaryName() const return "TESV.exe"; } -QString GameSkyrim::getNexusName() const +QString GameSkyrim::getGameShortName() const { return "Skyrim"; } diff --git a/src/games/skyrim/src/gameskyrim.h b/src/games/skyrim/src/gameskyrim.h index 279abada..b57cc4f8 100644 --- a/src/games/skyrim/src/gameskyrim.h +++ b/src/games/skyrim/src/gameskyrim.h @@ -32,7 +32,7 @@ public: // IPluginGame interface virtual QStringList getPrimaryPlugins() const override; virtual QIcon gameIcon() const override; virtual QString getBinaryName() const override; - virtual QString getNexusName() const override; + virtual QString getGameShortName() const override; virtual QStringList getIniFiles() const override; virtual QStringList getDLCPlugins() const override; virtual LoadOrderMechanism getLoadOrderMechanism() const override; From 2af4f85eb6a77f83972bab8201695f0bb66600a0 Mon Sep 17 00:00:00 2001 From: Tannin Date: Sat, 28 Nov 2015 10:55:25 +0100 Subject: [PATCH 0106/1544] gamebryo game plugins now correctly map the plugin-list(s) from the profile --- src/gamegamebryo.cpp | 15 +++++++++++++++ src/gamegamebryo.h | 10 ++++++++-- 2 files changed, 23 insertions(+), 2 deletions(-) diff --git a/src/gamegamebryo.cpp b/src/gamegamebryo.cpp index 954bd92d..5684ee27 100644 --- a/src/gamegamebryo.cpp +++ b/src/gamegamebryo.cpp @@ -159,7 +159,22 @@ QStringList GameGamebryo::gameVariants() const return QStringList(); } + void GameGamebryo::setGameVariant(const QString &variant) { m_GameVariant = variant; } + + +MappingType GameGamebryo::mappings() const +{ + MappingType result; + + for (const QString &profileFile : { "plugins.txt", "loadorder.txt" }) { + result.push_back({ m_Organizer->profilePath() + "/" + profileFile, + m_MyGamesPath + "/" + profileFile, + false }); + } + + return result; +} diff --git a/src/gamegamebryo.h b/src/gamegamebryo.h index e4d03e50..5c776e34 100644 --- a/src/gamegamebryo.h +++ b/src/gamegamebryo.h @@ -3,14 +3,16 @@ #include +#include #include #include -class GameGamebryo : public MOBase::IPluginGame +class GameGamebryo : public MOBase::IPluginGame, + public MOBase::IPluginFileMapper { Q_OBJECT - Q_INTERFACES(MOBase::IPlugin MOBase::IPluginGame) + Q_INTERFACES(MOBase::IPlugin MOBase::IPluginGame MOBase::IPluginFileMapper) public: @@ -31,6 +33,10 @@ public: // IPluginGame interface virtual QStringList gameVariants() const; virtual void setGameVariant(const QString &variant); +public: // IPluginFileMapper interface + + virtual MappingType mappings() const; + protected: std::unique_ptr getRegValue(HKEY key, LPCWSTR subKey, LPCWSTR value, DWORD flags, LPDWORD type = nullptr) const; From dd051e8e667505efb006ea5a021d0248942b10ed Mon Sep 17 00:00:00 2001 From: Thomas Tanner Date: Sat, 28 Nov 2015 14:43:43 +0000 Subject: [PATCH 0107/1544] [game_fallout3] Addition of script extender loader name and savegame attachment list to ScriptExtender interface --- src/games/fallout3/src/fallout3scriptextender.cpp | 12 ++++++++++++ src/games/fallout3/src/fallout3scriptextender.h | 5 +++++ src/games/fallout3/src/gamefallout3.cpp | 7 +------ src/games/fallout3/src/gamefallout3.h | 1 - 4 files changed, 18 insertions(+), 7 deletions(-) diff --git a/src/games/fallout3/src/fallout3scriptextender.cpp b/src/games/fallout3/src/fallout3scriptextender.cpp index d71c3cee..47226247 100644 --- a/src/games/fallout3/src/fallout3scriptextender.cpp +++ b/src/games/fallout3/src/fallout3scriptextender.cpp @@ -1,7 +1,19 @@ #include "fallout3scriptextender.h" +#include +#include QString Fallout3ScriptExtender::name() const { return "fose"; } + +QString Fallout3ScriptExtender::loaderName() const +{ + return name() + "_loader.exe"; +} + +QStringList Fallout3ScriptExtender::saveGameAttachmentExtensions() const +{ + return { }; +} diff --git a/src/games/fallout3/src/fallout3scriptextender.h b/src/games/fallout3/src/fallout3scriptextender.h index 3c362f2f..987124b9 100644 --- a/src/games/fallout3/src/fallout3scriptextender.h +++ b/src/games/fallout3/src/fallout3scriptextender.h @@ -9,6 +9,11 @@ class Fallout3ScriptExtender : public ScriptExtender { public: virtual QString name() const override; + + virtual QString loaderName() const override; + + virtual QStringList saveGameAttachmentExtensions() const override; + }; #endif // FALLOUT3SCRIPTEXTENDER_H diff --git a/src/games/fallout3/src/gamefallout3.cpp b/src/games/fallout3/src/gamefallout3.cpp index 0d0f49c3..c0de1e5d 100644 --- a/src/games/fallout3/src/gamefallout3.cpp +++ b/src/games/fallout3/src/gamefallout3.cpp @@ -62,7 +62,7 @@ QList GameFallout3::executables() const << ExecutableInfo("Fallout 3", findInGameFolder(getBinaryName())) << ExecutableInfo("Fallout Mod Manager", findInGameFolder("fomm/fomm.exe")) << ExecutableInfo("Construction Kit", findInGameFolder("geck.exe")) - << ExecutableInfo("Fallout Launcher", findInGameFolder("Fallout3Launcher.exe")) + << ExecutableInfo("Fallout Launcher", findInGameFolder(getLauncherName())) << ExecutableInfo("BOSS", findInGameFolder("BOSS/BOSS.exe")) << ExecutableInfo("LOOT", getLootPath()); ; @@ -171,11 +171,6 @@ QStringList GameFallout3::gameVariants() const return { "Regular", "Game Of The Year" }; } -QString GameFallout3::getBinaryName() const -{ - return "Fallout3.exe"; -} - QString GameFallout3::getGameShortName() const { return "Fallout3"; diff --git a/src/games/fallout3/src/gamefallout3.h b/src/games/fallout3/src/gamefallout3.h index 03ec630e..ffc5197c 100644 --- a/src/games/fallout3/src/gamefallout3.h +++ b/src/games/fallout3/src/gamefallout3.h @@ -32,7 +32,6 @@ public: // IPluginGame interface virtual QStringList getPrimaryPlugins() const override; virtual QIcon gameIcon() const override; virtual QStringList gameVariants() const; - virtual QString getBinaryName() const override; virtual QString getGameShortName() const override; virtual QStringList getIniFiles() const override; virtual QStringList getDLCPlugins() const override; From 25167a98ffa8333af30870a97709287ad8dc380b Mon Sep 17 00:00:00 2001 From: Thomas Tanner Date: Sat, 28 Nov 2015 14:44:02 +0000 Subject: [PATCH 0108/1544] [game_falloutnv] Addition of script extender loader name and savegame attachment list to ScriptExtender interface --- src/games/falloutnv/src/falloutnvscriptextender.cpp | 12 ++++++++++++ src/games/falloutnv/src/falloutnvscriptextender.h | 5 +++++ src/games/falloutnv/src/gamefalloutnv.cpp | 7 +------ src/games/falloutnv/src/gamefalloutnv.h | 1 - 4 files changed, 18 insertions(+), 7 deletions(-) diff --git a/src/games/falloutnv/src/falloutnvscriptextender.cpp b/src/games/falloutnv/src/falloutnvscriptextender.cpp index 90d67e35..7efdebc5 100644 --- a/src/games/falloutnv/src/falloutnvscriptextender.cpp +++ b/src/games/falloutnv/src/falloutnvscriptextender.cpp @@ -1,7 +1,19 @@ #include "falloutnvscriptextender.h" +#include +#include QString FalloutNVScriptExtender::name() const { return "nvse"; } + +QString FalloutNVScriptExtender::loaderName() const +{ + return name() + "_loader.exe"; +} + +QStringList FalloutNVScriptExtender::saveGameAttachmentExtensions() const +{ + return { }; +} diff --git a/src/games/falloutnv/src/falloutnvscriptextender.h b/src/games/falloutnv/src/falloutnvscriptextender.h index 951574b2..d859aa66 100644 --- a/src/games/falloutnv/src/falloutnvscriptextender.h +++ b/src/games/falloutnv/src/falloutnvscriptextender.h @@ -9,6 +9,11 @@ class FalloutNVScriptExtender : public ScriptExtender { public: virtual QString name() const override; + + virtual QString loaderName() const override; + + virtual QStringList saveGameAttachmentExtensions() const override; + }; #endif // FALLOUTNVSCRIPTEXTENDER_H diff --git a/src/games/falloutnv/src/gamefalloutnv.cpp b/src/games/falloutnv/src/gamefalloutnv.cpp index 8e9c1c91..26fc6127 100644 --- a/src/games/falloutnv/src/gamefalloutnv.cpp +++ b/src/games/falloutnv/src/gamefalloutnv.cpp @@ -61,7 +61,7 @@ QList GameFalloutNV::executables() const << ExecutableInfo("New Vegas", findInGameFolder(getBinaryName())) << ExecutableInfo("Fallout Mod Manager", findInGameFolder("fomm/fomm.exe")) << ExecutableInfo("Construction Kit", findInGameFolder("geck.exe")) - << ExecutableInfo("Fallout Launcher", findInGameFolder("FalloutNVLauncher.exe")) + << ExecutableInfo("Fallout Launcher", findInGameFolder(getLauncherName())) << ExecutableInfo("BOSS", findInGameFolder("BOSS/BOSS.exe")) << ExecutableInfo("LOOT", getLootPath()) ; @@ -162,11 +162,6 @@ std::map GameFalloutNV::featureList() const return result; } -QString GameFalloutNV::getBinaryName() const -{ - return "FalloutNV.exe"; -} - QString GameFalloutNV::getGameShortName() const { return "FalloutNV"; diff --git a/src/games/falloutnv/src/gamefalloutnv.h b/src/games/falloutnv/src/gamefalloutnv.h index f6dbbe96..9bbe548f 100644 --- a/src/games/falloutnv/src/gamefalloutnv.h +++ b/src/games/falloutnv/src/gamefalloutnv.h @@ -31,7 +31,6 @@ public: // IPluginGame interface virtual QString steamAPPId() const override; virtual QStringList getPrimaryPlugins() const override; virtual QIcon gameIcon() const override; - virtual QString getBinaryName() const override; virtual QString getGameShortName() const override; virtual QStringList getIniFiles() const override; virtual QStringList getDLCPlugins() const override; From 22d56f71993bb3dbf318b42a734736b5c132e6f9 Mon Sep 17 00:00:00 2001 From: Thomas Tanner Date: Sat, 28 Nov 2015 14:46:11 +0000 Subject: [PATCH 0109/1544] Added some code to support startup without gameinfo Moved a few things around in an OCD way --- src/gamegamebryo.cpp | 60 ++++++++++++++++++++++++++++---------------- src/gamegamebryo.h | 20 ++++++++++++--- 2 files changed, 54 insertions(+), 26 deletions(-) diff --git a/src/gamegamebryo.cpp b/src/gamegamebryo.cpp index cfed4109..d2c03616 100644 --- a/src/gamegamebryo.cpp +++ b/src/gamegamebryo.cpp @@ -19,6 +19,11 @@ bool GameGamebryo::init(MOBase::IOrganizer *moInfo) return true; } +bool GameGamebryo::isInstalled() const +{ + return !m_GamePath.isEmpty(); +} + QDir GameGamebryo::gameDirectory() const { return QDir(m_GamePath); @@ -34,19 +39,45 @@ void GameGamebryo::setGamePath(const QString &path) m_GamePath = path; } -QDir GameGamebryo::savesDirectory() const -{ - return QDir(m_MyGamesPath + "/Saves"); -} - QDir GameGamebryo::documentsDirectory() const { return m_MyGamesPath; } -bool GameGamebryo::isInstalled() const +QDir GameGamebryo::savesDirectory() const { - return !m_GamePath.isEmpty(); + return QDir(m_MyGamesPath + "/Saves"); +} + +QStringList GameGamebryo::gameVariants() const +{ + return QStringList(); +} + +void GameGamebryo::setGameVariant(const QString &variant) +{ + m_GameVariant = variant; +} + +QString GameGamebryo::getBinaryName() const +{ + return getGameShortName() + ".exe"; +} + +MOBase::IPluginGame::LoadOrderMechanism GameGamebryo::getLoadOrderMechanism() const +{ + return LoadOrderMechanism::FileTime; +} + +bool GameGamebryo::looksValid(QDir const &path) const +{ + //Check for .exe and Launcher.exe for now. + return path.exists(getBinaryName()) && path.exists(getLauncherName()); +} + +QString GameGamebryo::getLauncherName() const +{ + return getGameShortName() + "Launcher.exe"; } std::unique_ptr GameGamebryo::getRegValue(HKEY key, LPCWSTR path, @@ -155,18 +186,3 @@ QString GameGamebryo::getLootPath() const return findInRegistry(HKEY_LOCAL_MACHINE, L"Software\\LOOT", L"Installed Path") + "/Loot.exe"; } - -QStringList GameGamebryo::gameVariants() const -{ - return QStringList(); -} - -void GameGamebryo::setGameVariant(const QString &variant) -{ - m_GameVariant = variant; -} - -MOBase::IPluginGame::LoadOrderMechanism GameGamebryo::getLoadOrderMechanism() const -{ - return LoadOrderMechanism::FileTime; -} diff --git a/src/gamegamebryo.h b/src/gamegamebryo.h index 6f0e56ae..5e7c5832 100644 --- a/src/gamegamebryo.h +++ b/src/gamegamebryo.h @@ -20,17 +20,28 @@ public: public: // IPluginGame interface + //initializeProfile + //savegameExtension + virtual bool isInstalled() const override; + //gameIcon virtual QDir gameDirectory() const override; virtual QDir dataDirectory() const override; virtual void setGamePath(const QString &path) override; - virtual QDir savesDirectory() const override; virtual QDir documentsDirectory() const override; - - virtual bool isInstalled() const override; - + virtual QDir savesDirectory() const override; + //executables + //steamAPPId + //getPrimaryPlugins virtual QStringList gameVariants() const override; virtual void setGameVariant(const QString &variant) override; + virtual QString getBinaryName() const override; + //getGameShortName + //getIniFiles + //getDLCPlugins virtual LoadOrderMechanism getLoadOrderMechanism() const override; + //getNexusModOrganizerID + //getNexusGameID + virtual bool looksValid(QDir const &) const override; protected: @@ -43,6 +54,7 @@ protected: //Arguably this shouldn't really be here but every gamebryo program seems to use it QString getLootPath() const; QString selectedVariant() const; + virtual QString getLauncherName() const; private: From 9a23255c25171a9d6c71fe4f81d83edd9b2f1d1a Mon Sep 17 00:00:00 2001 From: Thomas Tanner Date: Sat, 28 Nov 2015 14:47:20 +0000 Subject: [PATCH 0110/1544] [game_oblivion] Addition of functionality to ScriptExtender feature Abstracted around some common functionality --- src/games/oblivion/src/gameoblivion.cpp | 7 +------ src/games/oblivion/src/gameoblivion.h | 1 - src/games/oblivion/src/oblivionscriptextender.cpp | 12 ++++++++++++ src/games/oblivion/src/oblivionscriptextender.h | 5 +++++ 4 files changed, 18 insertions(+), 7 deletions(-) diff --git a/src/games/oblivion/src/gameoblivion.cpp b/src/games/oblivion/src/gameoblivion.cpp index 13879f83..34371e26 100644 --- a/src/games/oblivion/src/gameoblivion.cpp +++ b/src/games/oblivion/src/gameoblivion.cpp @@ -58,7 +58,7 @@ QList GameOblivion::executables() const return QList() << ExecutableInfo("OBSE", findInGameFolder("obse_loader.exe")) << ExecutableInfo("Oblivion", findInGameFolder(getBinaryName())) - << ExecutableInfo("Oblivion Launcher", findInGameFolder("OblivionLauncher.exe")) + << ExecutableInfo("Oblivion Launcher", findInGameFolder(getLauncherName())) << ExecutableInfo("Oblivion Mod Manager", findInGameFolder("OblivionModManager.exe")) << ExecutableInfo("BOSS", findInGameFolder("BOSS/BOSS.exe")) << ExecutableInfo("LOOT", getLootPath()) @@ -161,11 +161,6 @@ std::map GameOblivion::featureList() const return result; } -QString GameOblivion::getBinaryName() const -{ - return "Oblivion.exe"; -} - QString GameOblivion::getGameShortName() const { return "Oblivion"; diff --git a/src/games/oblivion/src/gameoblivion.h b/src/games/oblivion/src/gameoblivion.h index 3da1e712..257ef3d4 100644 --- a/src/games/oblivion/src/gameoblivion.h +++ b/src/games/oblivion/src/gameoblivion.h @@ -31,7 +31,6 @@ public: // IPluginGame interface virtual QString steamAPPId() const override; virtual QStringList getPrimaryPlugins() const override; virtual QIcon gameIcon() const override; - virtual QString getBinaryName() const override; virtual QString getGameShortName() const override; virtual QStringList getIniFiles() const override; virtual QStringList getDLCPlugins() const override; diff --git a/src/games/oblivion/src/oblivionscriptextender.cpp b/src/games/oblivion/src/oblivionscriptextender.cpp index 452ddc51..dd43835a 100644 --- a/src/games/oblivion/src/oblivionscriptextender.cpp +++ b/src/games/oblivion/src/oblivionscriptextender.cpp @@ -1,7 +1,19 @@ #include "oblivionscriptextender.h" +#include +#include QString OblivionScriptExtender::name() const { return "obse"; } + +QString OblivionScriptExtender::loaderName() const +{ + return name() + "_loader.exe"; +} + +QStringList OblivionScriptExtender::saveGameAttachmentExtensions() const +{ + return { name() }; +} diff --git a/src/games/oblivion/src/oblivionscriptextender.h b/src/games/oblivion/src/oblivionscriptextender.h index f0cb5843..1088271f 100644 --- a/src/games/oblivion/src/oblivionscriptextender.h +++ b/src/games/oblivion/src/oblivionscriptextender.h @@ -9,6 +9,11 @@ class OblivionScriptExtender : public ScriptExtender { public: virtual QString name() const override; + + virtual QString loaderName() const override; + + virtual QStringList saveGameAttachmentExtensions() const override; + }; #endif // OBLIVIONSCRIPTEXTENDER_H From 2c820f5d76123aaa9dae32c5efbcce712248d1ae Mon Sep 17 00:00:00 2001 From: Thomas Tanner Date: Sat, 28 Nov 2015 14:47:42 +0000 Subject: [PATCH 0111/1544] [game_skyrim] Addition of functionality to ScriptExtender feature Abstracted around some common functionality --- src/games/skyrim/src/gameskyrim.cpp | 2 +- src/games/skyrim/src/skyrimscriptextender.cpp | 12 ++++++++++++ src/games/skyrim/src/skyrimscriptextender.h | 5 +++++ 3 files changed, 18 insertions(+), 1 deletion(-) diff --git a/src/games/skyrim/src/gameskyrim.cpp b/src/games/skyrim/src/gameskyrim.cpp index e28bdf93..1c6ca5ca 100644 --- a/src/games/skyrim/src/gameskyrim.cpp +++ b/src/games/skyrim/src/gameskyrim.cpp @@ -67,7 +67,7 @@ QList GameSkyrim::executables() const << ExecutableInfo("SKSE", findInGameFolder("skse_loader.exe")) << ExecutableInfo("SBW", findInGameFolder("SBW.exe")) << ExecutableInfo("Skyrim", findInGameFolder(getBinaryName())) - << ExecutableInfo("Skyrim Launcher", findInGameFolder("SkyrimLauncher.exe")) + << ExecutableInfo("Skyrim Launcher", findInGameFolder(getLauncherName())) << ExecutableInfo("BOSS", findInGameFolder("BOSS/BOSS.exe")) << ExecutableInfo("LOOT", getLootPath()) << ExecutableInfo("Creation Kit", findInGameFolder("CreationKit.exe")).withSteamAppId("202480") diff --git a/src/games/skyrim/src/skyrimscriptextender.cpp b/src/games/skyrim/src/skyrimscriptextender.cpp index f3d5539a..924c0400 100644 --- a/src/games/skyrim/src/skyrimscriptextender.cpp +++ b/src/games/skyrim/src/skyrimscriptextender.cpp @@ -1,7 +1,19 @@ #include "skyrimscriptextender.h" +#include +#include QString SkyrimScriptExtender::name() const { return "skse"; } + +QString SkyrimScriptExtender::loaderName() const +{ + return name() + "_loader.exe"; +} + +QStringList SkyrimScriptExtender::saveGameAttachmentExtensions() const +{ + return { name() }; +} diff --git a/src/games/skyrim/src/skyrimscriptextender.h b/src/games/skyrim/src/skyrimscriptextender.h index 7f2df32d..53ae440d 100644 --- a/src/games/skyrim/src/skyrimscriptextender.h +++ b/src/games/skyrim/src/skyrimscriptextender.h @@ -9,6 +9,11 @@ class SkyrimScriptExtender : public ScriptExtender { public: virtual QString name() const override; + + virtual QString loaderName() const override; + + virtual QStringList saveGameAttachmentExtensions() const override; + }; #endif // SKYRIMSCRIPTEXTENDER_H From e5dfeccf8f8f7bcc26ae0e54387dfb5b33cc265a Mon Sep 17 00:00:00 2001 From: Thomas Tanner Date: Sat, 28 Nov 2015 15:43:17 +0000 Subject: [PATCH 0112/1544] [game_fallout4vr] Do the work for issue 356 for this as well. Pushed the .pro file because I'm using QT as my ide right now --- src/games/fallout4vr/src/SConscript | 2 +- .../fallout4vr/src/fallout4scriptextender.cpp | 12 +++++ .../fallout4vr/src/fallout4scriptextender.h | 5 +++ src/games/fallout4vr/src/gameFallout4.pro | 44 ++++++++++++++++++ src/games/fallout4vr/src/gamefallout4.cpp | 45 +++++++++++++++---- src/games/fallout4vr/src/gamefallout4.h | 35 +++++++++------ 6 files changed, 120 insertions(+), 23 deletions(-) create mode 100644 src/games/fallout4vr/src/gameFallout4.pro diff --git a/src/games/fallout4vr/src/SConscript b/src/games/fallout4vr/src/SConscript index c45b0341..ebd2e920 100644 --- a/src/games/fallout4vr/src/SConscript +++ b/src/games/fallout4vr/src/SConscript @@ -3,7 +3,7 @@ Import('qt_env') env = qt_env.Clone() # Shouldn't this be GAMEFALLOUT3_LIBRARY -env.AppendUnique(CPPDEFINES = [ 'GAMEFALLOUTNV_LIBRARY' ]) +env.AppendUnique(CPPDEFINES = [ 'GAMEFALLOUT4_LIBRARY' ]) env.RequiresGamebryo() diff --git a/src/games/fallout4vr/src/fallout4scriptextender.cpp b/src/games/fallout4vr/src/fallout4scriptextender.cpp index de4e0e70..d3e0c3c5 100644 --- a/src/games/fallout4vr/src/fallout4scriptextender.cpp +++ b/src/games/fallout4vr/src/fallout4scriptextender.cpp @@ -1,7 +1,19 @@ #include "fallout4scriptextender.h" +#include +#include QString Fallout4ScriptExtender::name() const { return "f4se"; } + +QString Fallout4ScriptExtender::loaderName() const +{ + return name() + "_loader.exe"; +} + +QStringList Fallout4ScriptExtender::saveGameAttachmentExtensions() const +{ + return { }; +} diff --git a/src/games/fallout4vr/src/fallout4scriptextender.h b/src/games/fallout4vr/src/fallout4scriptextender.h index d850bfd1..7427d7bf 100644 --- a/src/games/fallout4vr/src/fallout4scriptextender.h +++ b/src/games/fallout4vr/src/fallout4scriptextender.h @@ -9,6 +9,11 @@ class Fallout4ScriptExtender : public ScriptExtender { public: virtual QString name() const override; + + virtual QString loaderName() const override; + + virtual QStringList saveGameAttachmentExtensions() const override; + }; #endif // FALLOUT3SCRIPTEXTENDER_H diff --git a/src/games/fallout4vr/src/gameFallout4.pro b/src/games/fallout4vr/src/gameFallout4.pro new file mode 100644 index 00000000..2d5697e3 --- /dev/null +++ b/src/games/fallout4vr/src/gameFallout4.pro @@ -0,0 +1,44 @@ +#------------------------------------------------- +# +# Project created by QtCreator 2014-11-15T15:36:33 +# +#------------------------------------------------- + + +TARGET = gameFallout3 +TEMPLATE = lib + +CONFIG += plugins +CONFIG += dll + +DEFINES += GAMEFALLOUT4_LIBRARY + +SOURCES += gamefallout4.cpp \ + fallout4bsainvalidation.cpp \ + fallout4scriptextender.cpp \ + fallout4dataarchives.cpp + +HEADERS += gamefallout4.h \ + fallout4bsainvalidation.h \ + fallout4scriptextender.h \ + fallout4dataarchives.h + +CONFIG(debug, debug|release) { + LIBS += -L"$${OUT_PWD}/../gameGamebryo/debug" + PRE_TARGETDEPS += \ + $$OUT_PWD/../gameGamebryo/debug/gameGamebryo.lib +} else { + LIBS += -L"$${OUT_PWD}/../gameGamebryo/release" + PRE_TARGETDEPS += \ + $$OUT_PWD/../gameGamebryo/release/gameGamebryo.lib +} + +include(../plugin_template.pri) + +INCLUDEPATH += "$${BOOSTPATH}" "$${PWD}/../gamefeatures" "$${PWD}/../gamegamebryo" + +LIBS += -ladvapi32 -lole32 -lgameGamebryo + +OTHER_FILES += \ + gamefallout4.json\ + SConscript diff --git a/src/games/fallout4vr/src/gamefallout4.cpp b/src/games/fallout4vr/src/gamefallout4.cpp index 18350703..d7057a6a 100644 --- a/src/games/fallout4vr/src/gamefallout4.cpp +++ b/src/games/fallout4vr/src/gamefallout4.cpp @@ -1,13 +1,15 @@ #include "gameFallout4.h" + #include #include -#include +#include "iplugingame.h" #include #include -#include + #include #include +#include using namespace MOBase; @@ -52,13 +54,13 @@ QString GameFallout4::myGamesFolderName() const return "Fallout4"; } -QList GameFallout4::executables() +QList GameFallout4::executables() const { return QList() << ExecutableInfo("F4SE", findInGameFolder("f4se_loader.exe")) - << ExecutableInfo("Fallout 4", findInGameFolder("Fallout4.exe")) - << ExecutableInfo("Fallout Launcher", findInGameFolder("Fallout4Launcher.exe")) - << ExecutableInfo("LOOT", getLootPath()); + << ExecutableInfo("Fallout 4", findInGameFolder(getBinaryName())) + << ExecutableInfo("Fallout Launcher", findInGameFolder(getLauncherName())) + << ExecutableInfo("LOOT", getLootPath()) ; } @@ -134,7 +136,7 @@ QString GameFallout4::steamAPPId() const return "377160"; } -QStringList GameFallout4::getPrimaryPlugins() +QStringList GameFallout4::getPrimaryPlugins() const { return { "fallout4.esm" }; } @@ -144,7 +146,7 @@ QIcon GameFallout4::gameIcon() const return MOBase::iconForExecutable(gameDirectory().absoluteFilePath("Fallout4.exe")); } -const std::map &GameFallout4::featureList() const +std::map GameFallout4::featureList() const { static std::map result { { typeid(ScriptExtender), m_ScriptExtender.get() }, @@ -159,3 +161,30 @@ QStringList GameFallout4::gameVariants() const { return { "Regular" }; } + +QString GameFallout4::getGameShortName() const +{ + return "Fallout4"; +} + +QStringList GameFallout4::getIniFiles() const +{ + return { "fallout4.ini", "fallout4prefs.ini" }; +} +QStringList GameFallout4::getDLCPlugins() const +{ + return {}; +} + +//what load order mechanism? +// virtual LoadOrderMechanism getLoadOrderMechanism() const = 0; + +int GameFallout4::getNexusModOrganizerID() const +{ + return 0; //... +} + +int GameFallout4::getNexusGameID() const +{ + return 1151; +} diff --git a/src/games/fallout4vr/src/gamefallout4.h b/src/games/fallout4vr/src/gamefallout4.h index 371a64a4..aaebd865 100644 --- a/src/games/fallout4vr/src/gamefallout4.h +++ b/src/games/fallout4vr/src/gamefallout4.h @@ -23,27 +23,34 @@ public: public: // IPluginGame interface - virtual QString gameName() const; - virtual QList executables(); - virtual void initializeProfile(const QDir &path, ProfileSettings settings) const; - virtual QString savegameExtension() const; - virtual QString steamAPPId() const; - virtual QStringList getPrimaryPlugins(); + virtual QString gameName() const override; + virtual QList executables() const override; + virtual void initializeProfile(const QDir &path, ProfileSettings settings) const override; + virtual QString savegameExtension() const override; + virtual QString steamAPPId() const override; + virtual QStringList getPrimaryPlugins() const override; virtual QIcon gameIcon() const override; - virtual QStringList gameVariants() const; + virtual QStringList gameVariants() const override; + virtual QString getGameShortName() const override; + virtual QStringList getIniFiles() const override; + virtual QStringList getDLCPlugins() const override; +//what load order mechanism? +// virtual LoadOrderMechanism getLoadOrderMechanism() const = 0; + virtual int getNexusModOrganizerID() const override; + virtual int getNexusGameID() const override; public: // IPlugin interface - virtual QString name() const; - virtual QString author() const; - virtual QString description() const; - virtual MOBase::VersionInfo version() const; - virtual bool isActive() const; - virtual QList settings() const; + virtual QString name() const override; + virtual QString author() const override; + virtual QString description() const override; + virtual MOBase::VersionInfo version() const override; + virtual bool isActive() const override; + virtual QList settings() const override; protected: - virtual const std::map &featureList() const; + virtual std::map featureList() const override; private: From 3efc32ed5c6d51f55e003650e14e6731419f6cbb Mon Sep 17 00:00:00 2001 From: Thomas Tanner Date: Sat, 28 Nov 2015 15:43:17 +0000 Subject: [PATCH 0113/1544] [game_fallout76] Do the work for issue 356 for this as well. Pushed the .pro file because I'm using QT as my ide right now --- src/games/fallout76/src/SConscript | 2 +- .../fallout76/src/fallout4scriptextender.cpp | 12 +++++ .../fallout76/src/fallout4scriptextender.h | 5 +++ src/games/fallout76/src/gameFallout4.pro | 44 ++++++++++++++++++ src/games/fallout76/src/gamefallout4.cpp | 45 +++++++++++++++---- src/games/fallout76/src/gamefallout4.h | 35 +++++++++------ 6 files changed, 120 insertions(+), 23 deletions(-) create mode 100644 src/games/fallout76/src/gameFallout4.pro diff --git a/src/games/fallout76/src/SConscript b/src/games/fallout76/src/SConscript index c45b0341..ebd2e920 100644 --- a/src/games/fallout76/src/SConscript +++ b/src/games/fallout76/src/SConscript @@ -3,7 +3,7 @@ Import('qt_env') env = qt_env.Clone() # Shouldn't this be GAMEFALLOUT3_LIBRARY -env.AppendUnique(CPPDEFINES = [ 'GAMEFALLOUTNV_LIBRARY' ]) +env.AppendUnique(CPPDEFINES = [ 'GAMEFALLOUT4_LIBRARY' ]) env.RequiresGamebryo() diff --git a/src/games/fallout76/src/fallout4scriptextender.cpp b/src/games/fallout76/src/fallout4scriptextender.cpp index de4e0e70..d3e0c3c5 100644 --- a/src/games/fallout76/src/fallout4scriptextender.cpp +++ b/src/games/fallout76/src/fallout4scriptextender.cpp @@ -1,7 +1,19 @@ #include "fallout4scriptextender.h" +#include +#include QString Fallout4ScriptExtender::name() const { return "f4se"; } + +QString Fallout4ScriptExtender::loaderName() const +{ + return name() + "_loader.exe"; +} + +QStringList Fallout4ScriptExtender::saveGameAttachmentExtensions() const +{ + return { }; +} diff --git a/src/games/fallout76/src/fallout4scriptextender.h b/src/games/fallout76/src/fallout4scriptextender.h index d850bfd1..7427d7bf 100644 --- a/src/games/fallout76/src/fallout4scriptextender.h +++ b/src/games/fallout76/src/fallout4scriptextender.h @@ -9,6 +9,11 @@ class Fallout4ScriptExtender : public ScriptExtender { public: virtual QString name() const override; + + virtual QString loaderName() const override; + + virtual QStringList saveGameAttachmentExtensions() const override; + }; #endif // FALLOUT3SCRIPTEXTENDER_H diff --git a/src/games/fallout76/src/gameFallout4.pro b/src/games/fallout76/src/gameFallout4.pro new file mode 100644 index 00000000..2d5697e3 --- /dev/null +++ b/src/games/fallout76/src/gameFallout4.pro @@ -0,0 +1,44 @@ +#------------------------------------------------- +# +# Project created by QtCreator 2014-11-15T15:36:33 +# +#------------------------------------------------- + + +TARGET = gameFallout3 +TEMPLATE = lib + +CONFIG += plugins +CONFIG += dll + +DEFINES += GAMEFALLOUT4_LIBRARY + +SOURCES += gamefallout4.cpp \ + fallout4bsainvalidation.cpp \ + fallout4scriptextender.cpp \ + fallout4dataarchives.cpp + +HEADERS += gamefallout4.h \ + fallout4bsainvalidation.h \ + fallout4scriptextender.h \ + fallout4dataarchives.h + +CONFIG(debug, debug|release) { + LIBS += -L"$${OUT_PWD}/../gameGamebryo/debug" + PRE_TARGETDEPS += \ + $$OUT_PWD/../gameGamebryo/debug/gameGamebryo.lib +} else { + LIBS += -L"$${OUT_PWD}/../gameGamebryo/release" + PRE_TARGETDEPS += \ + $$OUT_PWD/../gameGamebryo/release/gameGamebryo.lib +} + +include(../plugin_template.pri) + +INCLUDEPATH += "$${BOOSTPATH}" "$${PWD}/../gamefeatures" "$${PWD}/../gamegamebryo" + +LIBS += -ladvapi32 -lole32 -lgameGamebryo + +OTHER_FILES += \ + gamefallout4.json\ + SConscript diff --git a/src/games/fallout76/src/gamefallout4.cpp b/src/games/fallout76/src/gamefallout4.cpp index 18350703..d7057a6a 100644 --- a/src/games/fallout76/src/gamefallout4.cpp +++ b/src/games/fallout76/src/gamefallout4.cpp @@ -1,13 +1,15 @@ #include "gameFallout4.h" + #include #include -#include +#include "iplugingame.h" #include #include -#include + #include #include +#include using namespace MOBase; @@ -52,13 +54,13 @@ QString GameFallout4::myGamesFolderName() const return "Fallout4"; } -QList GameFallout4::executables() +QList GameFallout4::executables() const { return QList() << ExecutableInfo("F4SE", findInGameFolder("f4se_loader.exe")) - << ExecutableInfo("Fallout 4", findInGameFolder("Fallout4.exe")) - << ExecutableInfo("Fallout Launcher", findInGameFolder("Fallout4Launcher.exe")) - << ExecutableInfo("LOOT", getLootPath()); + << ExecutableInfo("Fallout 4", findInGameFolder(getBinaryName())) + << ExecutableInfo("Fallout Launcher", findInGameFolder(getLauncherName())) + << ExecutableInfo("LOOT", getLootPath()) ; } @@ -134,7 +136,7 @@ QString GameFallout4::steamAPPId() const return "377160"; } -QStringList GameFallout4::getPrimaryPlugins() +QStringList GameFallout4::getPrimaryPlugins() const { return { "fallout4.esm" }; } @@ -144,7 +146,7 @@ QIcon GameFallout4::gameIcon() const return MOBase::iconForExecutable(gameDirectory().absoluteFilePath("Fallout4.exe")); } -const std::map &GameFallout4::featureList() const +std::map GameFallout4::featureList() const { static std::map result { { typeid(ScriptExtender), m_ScriptExtender.get() }, @@ -159,3 +161,30 @@ QStringList GameFallout4::gameVariants() const { return { "Regular" }; } + +QString GameFallout4::getGameShortName() const +{ + return "Fallout4"; +} + +QStringList GameFallout4::getIniFiles() const +{ + return { "fallout4.ini", "fallout4prefs.ini" }; +} +QStringList GameFallout4::getDLCPlugins() const +{ + return {}; +} + +//what load order mechanism? +// virtual LoadOrderMechanism getLoadOrderMechanism() const = 0; + +int GameFallout4::getNexusModOrganizerID() const +{ + return 0; //... +} + +int GameFallout4::getNexusGameID() const +{ + return 1151; +} diff --git a/src/games/fallout76/src/gamefallout4.h b/src/games/fallout76/src/gamefallout4.h index 371a64a4..aaebd865 100644 --- a/src/games/fallout76/src/gamefallout4.h +++ b/src/games/fallout76/src/gamefallout4.h @@ -23,27 +23,34 @@ public: public: // IPluginGame interface - virtual QString gameName() const; - virtual QList executables(); - virtual void initializeProfile(const QDir &path, ProfileSettings settings) const; - virtual QString savegameExtension() const; - virtual QString steamAPPId() const; - virtual QStringList getPrimaryPlugins(); + virtual QString gameName() const override; + virtual QList executables() const override; + virtual void initializeProfile(const QDir &path, ProfileSettings settings) const override; + virtual QString savegameExtension() const override; + virtual QString steamAPPId() const override; + virtual QStringList getPrimaryPlugins() const override; virtual QIcon gameIcon() const override; - virtual QStringList gameVariants() const; + virtual QStringList gameVariants() const override; + virtual QString getGameShortName() const override; + virtual QStringList getIniFiles() const override; + virtual QStringList getDLCPlugins() const override; +//what load order mechanism? +// virtual LoadOrderMechanism getLoadOrderMechanism() const = 0; + virtual int getNexusModOrganizerID() const override; + virtual int getNexusGameID() const override; public: // IPlugin interface - virtual QString name() const; - virtual QString author() const; - virtual QString description() const; - virtual MOBase::VersionInfo version() const; - virtual bool isActive() const; - virtual QList settings() const; + virtual QString name() const override; + virtual QString author() const override; + virtual QString description() const override; + virtual MOBase::VersionInfo version() const override; + virtual bool isActive() const override; + virtual QList settings() const override; protected: - virtual const std::map &featureList() const; + virtual std::map featureList() const override; private: From a780cc395c83c9943950f1a68ac5f1d003b75b03 Mon Sep 17 00:00:00 2001 From: Thomas Tanner Date: Sat, 28 Nov 2015 15:43:17 +0000 Subject: [PATCH 0114/1544] [game_fallout4] Do the work for issue 356 for this as well. Pushed the .pro file because I'm using QT as my ide right now --- src/games/fallout4/src/SConscript | 2 +- .../fallout4/src/fallout4scriptextender.cpp | 12 +++++ .../fallout4/src/fallout4scriptextender.h | 5 +++ src/games/fallout4/src/gameFallout4.pro | 44 ++++++++++++++++++ src/games/fallout4/src/gamefallout4.cpp | 45 +++++++++++++++---- src/games/fallout4/src/gamefallout4.h | 35 +++++++++------ 6 files changed, 120 insertions(+), 23 deletions(-) create mode 100644 src/games/fallout4/src/gameFallout4.pro diff --git a/src/games/fallout4/src/SConscript b/src/games/fallout4/src/SConscript index c45b0341..ebd2e920 100644 --- a/src/games/fallout4/src/SConscript +++ b/src/games/fallout4/src/SConscript @@ -3,7 +3,7 @@ Import('qt_env') env = qt_env.Clone() # Shouldn't this be GAMEFALLOUT3_LIBRARY -env.AppendUnique(CPPDEFINES = [ 'GAMEFALLOUTNV_LIBRARY' ]) +env.AppendUnique(CPPDEFINES = [ 'GAMEFALLOUT4_LIBRARY' ]) env.RequiresGamebryo() diff --git a/src/games/fallout4/src/fallout4scriptextender.cpp b/src/games/fallout4/src/fallout4scriptextender.cpp index de4e0e70..d3e0c3c5 100644 --- a/src/games/fallout4/src/fallout4scriptextender.cpp +++ b/src/games/fallout4/src/fallout4scriptextender.cpp @@ -1,7 +1,19 @@ #include "fallout4scriptextender.h" +#include +#include QString Fallout4ScriptExtender::name() const { return "f4se"; } + +QString Fallout4ScriptExtender::loaderName() const +{ + return name() + "_loader.exe"; +} + +QStringList Fallout4ScriptExtender::saveGameAttachmentExtensions() const +{ + return { }; +} diff --git a/src/games/fallout4/src/fallout4scriptextender.h b/src/games/fallout4/src/fallout4scriptextender.h index d850bfd1..7427d7bf 100644 --- a/src/games/fallout4/src/fallout4scriptextender.h +++ b/src/games/fallout4/src/fallout4scriptextender.h @@ -9,6 +9,11 @@ class Fallout4ScriptExtender : public ScriptExtender { public: virtual QString name() const override; + + virtual QString loaderName() const override; + + virtual QStringList saveGameAttachmentExtensions() const override; + }; #endif // FALLOUT3SCRIPTEXTENDER_H diff --git a/src/games/fallout4/src/gameFallout4.pro b/src/games/fallout4/src/gameFallout4.pro new file mode 100644 index 00000000..2d5697e3 --- /dev/null +++ b/src/games/fallout4/src/gameFallout4.pro @@ -0,0 +1,44 @@ +#------------------------------------------------- +# +# Project created by QtCreator 2014-11-15T15:36:33 +# +#------------------------------------------------- + + +TARGET = gameFallout3 +TEMPLATE = lib + +CONFIG += plugins +CONFIG += dll + +DEFINES += GAMEFALLOUT4_LIBRARY + +SOURCES += gamefallout4.cpp \ + fallout4bsainvalidation.cpp \ + fallout4scriptextender.cpp \ + fallout4dataarchives.cpp + +HEADERS += gamefallout4.h \ + fallout4bsainvalidation.h \ + fallout4scriptextender.h \ + fallout4dataarchives.h + +CONFIG(debug, debug|release) { + LIBS += -L"$${OUT_PWD}/../gameGamebryo/debug" + PRE_TARGETDEPS += \ + $$OUT_PWD/../gameGamebryo/debug/gameGamebryo.lib +} else { + LIBS += -L"$${OUT_PWD}/../gameGamebryo/release" + PRE_TARGETDEPS += \ + $$OUT_PWD/../gameGamebryo/release/gameGamebryo.lib +} + +include(../plugin_template.pri) + +INCLUDEPATH += "$${BOOSTPATH}" "$${PWD}/../gamefeatures" "$${PWD}/../gamegamebryo" + +LIBS += -ladvapi32 -lole32 -lgameGamebryo + +OTHER_FILES += \ + gamefallout4.json\ + SConscript diff --git a/src/games/fallout4/src/gamefallout4.cpp b/src/games/fallout4/src/gamefallout4.cpp index 18350703..d7057a6a 100644 --- a/src/games/fallout4/src/gamefallout4.cpp +++ b/src/games/fallout4/src/gamefallout4.cpp @@ -1,13 +1,15 @@ #include "gameFallout4.h" + #include #include -#include +#include "iplugingame.h" #include #include -#include + #include #include +#include using namespace MOBase; @@ -52,13 +54,13 @@ QString GameFallout4::myGamesFolderName() const return "Fallout4"; } -QList GameFallout4::executables() +QList GameFallout4::executables() const { return QList() << ExecutableInfo("F4SE", findInGameFolder("f4se_loader.exe")) - << ExecutableInfo("Fallout 4", findInGameFolder("Fallout4.exe")) - << ExecutableInfo("Fallout Launcher", findInGameFolder("Fallout4Launcher.exe")) - << ExecutableInfo("LOOT", getLootPath()); + << ExecutableInfo("Fallout 4", findInGameFolder(getBinaryName())) + << ExecutableInfo("Fallout Launcher", findInGameFolder(getLauncherName())) + << ExecutableInfo("LOOT", getLootPath()) ; } @@ -134,7 +136,7 @@ QString GameFallout4::steamAPPId() const return "377160"; } -QStringList GameFallout4::getPrimaryPlugins() +QStringList GameFallout4::getPrimaryPlugins() const { return { "fallout4.esm" }; } @@ -144,7 +146,7 @@ QIcon GameFallout4::gameIcon() const return MOBase::iconForExecutable(gameDirectory().absoluteFilePath("Fallout4.exe")); } -const std::map &GameFallout4::featureList() const +std::map GameFallout4::featureList() const { static std::map result { { typeid(ScriptExtender), m_ScriptExtender.get() }, @@ -159,3 +161,30 @@ QStringList GameFallout4::gameVariants() const { return { "Regular" }; } + +QString GameFallout4::getGameShortName() const +{ + return "Fallout4"; +} + +QStringList GameFallout4::getIniFiles() const +{ + return { "fallout4.ini", "fallout4prefs.ini" }; +} +QStringList GameFallout4::getDLCPlugins() const +{ + return {}; +} + +//what load order mechanism? +// virtual LoadOrderMechanism getLoadOrderMechanism() const = 0; + +int GameFallout4::getNexusModOrganizerID() const +{ + return 0; //... +} + +int GameFallout4::getNexusGameID() const +{ + return 1151; +} diff --git a/src/games/fallout4/src/gamefallout4.h b/src/games/fallout4/src/gamefallout4.h index 371a64a4..aaebd865 100644 --- a/src/games/fallout4/src/gamefallout4.h +++ b/src/games/fallout4/src/gamefallout4.h @@ -23,27 +23,34 @@ public: public: // IPluginGame interface - virtual QString gameName() const; - virtual QList executables(); - virtual void initializeProfile(const QDir &path, ProfileSettings settings) const; - virtual QString savegameExtension() const; - virtual QString steamAPPId() const; - virtual QStringList getPrimaryPlugins(); + virtual QString gameName() const override; + virtual QList executables() const override; + virtual void initializeProfile(const QDir &path, ProfileSettings settings) const override; + virtual QString savegameExtension() const override; + virtual QString steamAPPId() const override; + virtual QStringList getPrimaryPlugins() const override; virtual QIcon gameIcon() const override; - virtual QStringList gameVariants() const; + virtual QStringList gameVariants() const override; + virtual QString getGameShortName() const override; + virtual QStringList getIniFiles() const override; + virtual QStringList getDLCPlugins() const override; +//what load order mechanism? +// virtual LoadOrderMechanism getLoadOrderMechanism() const = 0; + virtual int getNexusModOrganizerID() const override; + virtual int getNexusGameID() const override; public: // IPlugin interface - virtual QString name() const; - virtual QString author() const; - virtual QString description() const; - virtual MOBase::VersionInfo version() const; - virtual bool isActive() const; - virtual QList settings() const; + virtual QString name() const override; + virtual QString author() const override; + virtual QString description() const override; + virtual MOBase::VersionInfo version() const override; + virtual bool isActive() const override; + virtual QList settings() const override; protected: - virtual const std::map &featureList() const; + virtual std::map featureList() const override; private: From bd6a875e25249357dc7ba9a5c41b246784f2eab6 Mon Sep 17 00:00:00 2001 From: Thomas Tanner Date: Sat, 28 Nov 2015 23:06:08 +0000 Subject: [PATCH 0115/1544] [game_fallout3] Abstract away the xxse_loader manipulation and make use of the 'ScriptExtender' feature instead --- src/games/fallout3/src/fallout3scriptextender.cpp | 10 +++++----- src/games/fallout3/src/fallout3scriptextender.h | 9 ++++----- src/games/fallout3/src/gamefallout3.cpp | 9 ++------- src/games/fallout3/src/gamefallout3.h | 1 - 4 files changed, 11 insertions(+), 18 deletions(-) diff --git a/src/games/fallout3/src/fallout3scriptextender.cpp b/src/games/fallout3/src/fallout3scriptextender.cpp index 47226247..085bddd9 100644 --- a/src/games/fallout3/src/fallout3scriptextender.cpp +++ b/src/games/fallout3/src/fallout3scriptextender.cpp @@ -3,16 +3,16 @@ #include #include +Fallout3ScriptExtender::Fallout3ScriptExtender(GameGamebryo const *game) : + GamebryoScriptExtender(game) +{ +} + QString Fallout3ScriptExtender::name() const { return "fose"; } -QString Fallout3ScriptExtender::loaderName() const -{ - return name() + "_loader.exe"; -} - QStringList Fallout3ScriptExtender::saveGameAttachmentExtensions() const { return { }; diff --git a/src/games/fallout3/src/fallout3scriptextender.h b/src/games/fallout3/src/fallout3scriptextender.h index 987124b9..d4c0141b 100644 --- a/src/games/fallout3/src/fallout3scriptextender.h +++ b/src/games/fallout3/src/fallout3scriptextender.h @@ -2,15 +2,14 @@ #define FALLOUT3SCRIPTEXTENDER_H -#include +#include "gamebryoscriptextender.h" - -class Fallout3ScriptExtender : public ScriptExtender +class Fallout3ScriptExtender : public GamebryoScriptExtender { public: - virtual QString name() const override; + Fallout3ScriptExtender(GameGamebryo const *game); - virtual QString loaderName() const override; + virtual QString name() const override; virtual QStringList saveGameAttachmentExtensions() const override; diff --git a/src/games/fallout3/src/gamefallout3.cpp b/src/games/fallout3/src/gamefallout3.cpp index c0de1e5d..43ec35ac 100644 --- a/src/games/fallout3/src/gamefallout3.cpp +++ b/src/games/fallout3/src/gamefallout3.cpp @@ -23,7 +23,7 @@ bool GameFallout3::init(IOrganizer *moInfo) if (!GameGamebryo::init(moInfo)) { return false; } - m_ScriptExtender = std::shared_ptr(new Fallout3ScriptExtender()); + m_ScriptExtender = std::shared_ptr(new Fallout3ScriptExtender(this)); m_DataArchives = std::shared_ptr(new Fallout3DataArchives()); m_BSAInvalidation = std::shared_ptr(new Fallout3BSAInvalidation(m_DataArchives, this)); return true; @@ -58,7 +58,7 @@ QString GameFallout3::myGamesFolderName() const QList GameFallout3::executables() const { return QList() - << ExecutableInfo("FOSE", findInGameFolder("fose_loader.exe")) + << ExecutableInfo("FOSE", findInGameFolder(m_ScriptExtender->loaderName())) << ExecutableInfo("Fallout 3", findInGameFolder(getBinaryName())) << ExecutableInfo("Fallout Mod Manager", findInGameFolder("fomm/fomm.exe")) << ExecutableInfo("Construction Kit", findInGameFolder("geck.exe")) @@ -149,11 +149,6 @@ QStringList GameFallout3::getPrimaryPlugins() const return { "fallout3.esm" }; } -QIcon GameFallout3::gameIcon() const -{ - return MOBase::iconForExecutable(gameDirectory().absoluteFilePath(getBinaryName())); -} - std::map GameFallout3::featureList() const { static std::map result { diff --git a/src/games/fallout3/src/gamefallout3.h b/src/games/fallout3/src/gamefallout3.h index ffc5197c..365cc1a4 100644 --- a/src/games/fallout3/src/gamefallout3.h +++ b/src/games/fallout3/src/gamefallout3.h @@ -30,7 +30,6 @@ public: // IPluginGame interface virtual QString savegameExtension() const override; virtual QString steamAPPId() const override; virtual QStringList getPrimaryPlugins() const override; - virtual QIcon gameIcon() const override; virtual QStringList gameVariants() const; virtual QString getGameShortName() const override; virtual QStringList getIniFiles() const override; From ca3e809140700f9e410e86c9dbd6da4d975c9293 Mon Sep 17 00:00:00 2001 From: Thomas Tanner Date: Sat, 28 Nov 2015 23:06:22 +0000 Subject: [PATCH 0116/1544] [game_falloutnv] Abstract away the xxse_loader manipulation and make use of the 'ScriptExtender' feature instead --- src/games/falloutnv/src/falloutnvscriptextender.cpp | 10 +++++----- src/games/falloutnv/src/falloutnvscriptextender.h | 10 ++++------ src/games/falloutnv/src/gamefalloutnv.cpp | 9 ++------- src/games/falloutnv/src/gamefalloutnv.h | 1 - 4 files changed, 11 insertions(+), 19 deletions(-) diff --git a/src/games/falloutnv/src/falloutnvscriptextender.cpp b/src/games/falloutnv/src/falloutnvscriptextender.cpp index 7efdebc5..d57a19b1 100644 --- a/src/games/falloutnv/src/falloutnvscriptextender.cpp +++ b/src/games/falloutnv/src/falloutnvscriptextender.cpp @@ -3,16 +3,16 @@ #include #include +FalloutNVScriptExtender::FalloutNVScriptExtender(GameGamebryo const *game) : + GamebryoScriptExtender(game) +{ +} + QString FalloutNVScriptExtender::name() const { return "nvse"; } -QString FalloutNVScriptExtender::loaderName() const -{ - return name() + "_loader.exe"; -} - QStringList FalloutNVScriptExtender::saveGameAttachmentExtensions() const { return { }; diff --git a/src/games/falloutnv/src/falloutnvscriptextender.h b/src/games/falloutnv/src/falloutnvscriptextender.h index d859aa66..1361c710 100644 --- a/src/games/falloutnv/src/falloutnvscriptextender.h +++ b/src/games/falloutnv/src/falloutnvscriptextender.h @@ -1,16 +1,14 @@ #ifndef FALLOUTNVSCRIPTEXTENDER_H #define FALLOUTNVSCRIPTEXTENDER_H +#include "gamebryoscriptextender.h" -#include - - -class FalloutNVScriptExtender : public ScriptExtender +class FalloutNVScriptExtender : public GamebryoScriptExtender { public: - virtual QString name() const override; + FalloutNVScriptExtender(const GameGamebryo *game); - virtual QString loaderName() const override; + virtual QString name() const override; virtual QStringList saveGameAttachmentExtensions() const override; diff --git a/src/games/falloutnv/src/gamefalloutnv.cpp b/src/games/falloutnv/src/gamefalloutnv.cpp index 26fc6127..31c8bf24 100644 --- a/src/games/falloutnv/src/gamefalloutnv.cpp +++ b/src/games/falloutnv/src/gamefalloutnv.cpp @@ -22,7 +22,7 @@ bool GameFalloutNV::init(IOrganizer *moInfo) if (!GameGamebryo::init(moInfo)) { return false; } - m_ScriptExtender = std::shared_ptr(new FalloutNVScriptExtender()); + m_ScriptExtender = std::shared_ptr(new FalloutNVScriptExtender(this)); m_DataArchives = std::shared_ptr(new FalloutNVDataArchives()); m_BSAInvalidation = std::shared_ptr(new FalloutNVBSAInvalidation(m_DataArchives, this)); return true; @@ -57,7 +57,7 @@ QString GameFalloutNV::myGamesFolderName() const QList GameFalloutNV::executables() const { return QList() - << ExecutableInfo("NVSE", findInGameFolder("nvse_loader.exe")) + << ExecutableInfo("NVSE", findInGameFolder(m_ScriptExtender->loaderName())) << ExecutableInfo("New Vegas", findInGameFolder(getBinaryName())) << ExecutableInfo("Fallout Mod Manager", findInGameFolder("fomm/fomm.exe")) << ExecutableInfo("Construction Kit", findInGameFolder("geck.exe")) @@ -146,11 +146,6 @@ QStringList GameFalloutNV::getPrimaryPlugins() const return { "falloutnv.esm" }; } -QIcon GameFalloutNV::gameIcon() const -{ - return MOBase::iconForExecutable(gameDirectory().absoluteFilePath(getBinaryName())); -} - std::map GameFalloutNV::featureList() const { static std::map result { diff --git a/src/games/falloutnv/src/gamefalloutnv.h b/src/games/falloutnv/src/gamefalloutnv.h index 9bbe548f..eff99862 100644 --- a/src/games/falloutnv/src/gamefalloutnv.h +++ b/src/games/falloutnv/src/gamefalloutnv.h @@ -30,7 +30,6 @@ public: // IPluginGame interface virtual QString savegameExtension() const override; virtual QString steamAPPId() const override; virtual QStringList getPrimaryPlugins() const override; - virtual QIcon gameIcon() const override; virtual QString getGameShortName() const override; virtual QStringList getIniFiles() const override; virtual QStringList getDLCPlugins() const override; From 1df67304e8ecc6f88ef7c6b862da7162bcb76fa5 Mon Sep 17 00:00:00 2001 From: Thomas Tanner Date: Sat, 28 Nov 2015 23:07:20 +0000 Subject: [PATCH 0117/1544] Abstract away the xxse_loader manipulation and make use of the 'ScriptExtender' feature instead Some of this is dealt with generically by gamebryoscriptextender now --- src/gameGamebryo.pro | 6 ++++-- src/gamebryoscriptextender.cpp | 32 ++++++++++++++++++++++++++++++++ src/gamebryoscriptextender.h | 29 +++++++++++++++++++++++++++++ src/gamegamebryo.cpp | 5 +++++ src/gamegamebryo.h | 2 +- 5 files changed, 71 insertions(+), 3 deletions(-) create mode 100644 src/gamebryoscriptextender.cpp create mode 100644 src/gamebryoscriptextender.h diff --git a/src/gameGamebryo.pro b/src/gameGamebryo.pro index 2be6f8ab..ef2cfe60 100644 --- a/src/gameGamebryo.pro +++ b/src/gameGamebryo.pro @@ -11,12 +11,14 @@ CONFIG += staticlib SOURCES += gamegamebryo.cpp \ dummybsa.cpp \ gamebryobsainvalidation.cpp \ - gamebryodataarchives.cpp + gamebryodataarchives.cpp \ + gamebryoscriptextender.cpp HEADERS += gamegamebryo.h \ dummybsa.h \ gamebryobsainvalidation.h \ - gamebryodataarchives.h + gamebryodataarchives.h \ + gamebryoscriptextender.h include(../plugin_template.pri) diff --git a/src/gamebryoscriptextender.cpp b/src/gamebryoscriptextender.cpp new file mode 100644 index 00000000..8db9d996 --- /dev/null +++ b/src/gamebryoscriptextender.cpp @@ -0,0 +1,32 @@ +#include "gamebryoscriptextender.h" + +#include "gamegamebryo.h" + +GamebryoScriptExtender::GamebryoScriptExtender(const GameGamebryo *game) : + m_Game(game) +{ +} + +GamebryoScriptExtender::~GamebryoScriptExtender() +{ +} + +QString GamebryoScriptExtender::loaderName() const +{ + return name() + "_loader.exe"; +} + +QString GamebryoScriptExtender::loaderPath() const +{ + return m_Game->gameDirectory().absoluteFilePath(loaderName()); +} + +bool GamebryoScriptExtender::isInstalled() const +{ + //A note: It is possibly also OK if xxse_steam_loader.dll exists, but it's + //not clear why that would exist and the exe not if you'd installed it per + //instructions, and it'd mess up NCC installs a treat. + return m_Game->gameDirectory().exists(loaderName()); + +} + diff --git a/src/gamebryoscriptextender.h b/src/gamebryoscriptextender.h new file mode 100644 index 00000000..1e235b99 --- /dev/null +++ b/src/gamebryoscriptextender.h @@ -0,0 +1,29 @@ +#ifndef GAMEBRYOSCRIPTEXTENDER_H +#define GAMEBRYOSCRIPTEXTENDER_H + +#include "scriptextender.h" + +class GameGamebryo; + +class GamebryoScriptExtender : public ScriptExtender +{ +public: + GamebryoScriptExtender(GameGamebryo const *game); + + virtual ~GamebryoScriptExtender(); + + //virtual QString name() const override; + + virtual QString loaderName() const override; + + virtual QString loaderPath() const override; + + //virtual QStringList saveGameAttachmentExtensions() const override; + + virtual bool isInstalled() const override; + +protected: + GameGamebryo const * const m_Game; +}; + +#endif // GAMEBRYOSCRIPTEXTENDER_H diff --git a/src/gamegamebryo.cpp b/src/gamegamebryo.cpp index d2c03616..02c82e9d 100644 --- a/src/gamegamebryo.cpp +++ b/src/gamegamebryo.cpp @@ -24,6 +24,11 @@ bool GameGamebryo::isInstalled() const return !m_GamePath.isEmpty(); } +QIcon GameGamebryo::gameIcon() const +{ + return MOBase::iconForExecutable(gameDirectory().absoluteFilePath(getBinaryName())); +} + QDir GameGamebryo::gameDirectory() const { return QDir(m_GamePath); diff --git a/src/gamegamebryo.h b/src/gamegamebryo.h index 5e7c5832..f4ef1186 100644 --- a/src/gamegamebryo.h +++ b/src/gamegamebryo.h @@ -23,7 +23,7 @@ public: // IPluginGame interface //initializeProfile //savegameExtension virtual bool isInstalled() const override; - //gameIcon + virtual QIcon gameIcon() const override; virtual QDir gameDirectory() const override; virtual QDir dataDirectory() const override; virtual void setGamePath(const QString &path) override; From 48d3fac01e921f8d966fffc97069e447614d67e9 Mon Sep 17 00:00:00 2001 From: Thomas Tanner Date: Sat, 28 Nov 2015 23:09:49 +0000 Subject: [PATCH 0118/1544] [game_oblivion] Abstract away the xxse_loader manipulation and make use of the 'ScriptExtender' feature instead --- src/games/oblivion/src/gameoblivion.cpp | 9 ++------- src/games/oblivion/src/gameoblivion.h | 1 - src/games/oblivion/src/oblivionscriptextender.cpp | 10 +++++----- src/games/oblivion/src/oblivionscriptextender.h | 10 ++++------ 4 files changed, 11 insertions(+), 19 deletions(-) diff --git a/src/games/oblivion/src/gameoblivion.cpp b/src/games/oblivion/src/gameoblivion.cpp index 34371e26..1d6a07e5 100644 --- a/src/games/oblivion/src/gameoblivion.cpp +++ b/src/games/oblivion/src/gameoblivion.cpp @@ -19,7 +19,7 @@ bool GameOblivion::init(IOrganizer *moInfo) if (!GameGamebryo::init(moInfo)) { return false; } - m_ScriptExtender = std::shared_ptr(new OblivionScriptExtender()); + m_ScriptExtender = std::shared_ptr(new OblivionScriptExtender(this)); m_DataArchives = std::shared_ptr(new OblivionDataArchives()); m_BSAInvalidation = std::shared_ptr(new OblivionBSAInvalidation(m_DataArchives, this)); return true; @@ -56,7 +56,7 @@ QString GameOblivion::myGamesFolderName() const QList GameOblivion::executables() const { return QList() - << ExecutableInfo("OBSE", findInGameFolder("obse_loader.exe")) + << ExecutableInfo("OBSE", findInGameFolder(m_ScriptExtender->loaderName())) << ExecutableInfo("Oblivion", findInGameFolder(getBinaryName())) << ExecutableInfo("Oblivion Launcher", findInGameFolder(getLauncherName())) << ExecutableInfo("Oblivion Mod Manager", findInGameFolder("OblivionModManager.exe")) @@ -145,11 +145,6 @@ QStringList GameOblivion::getPrimaryPlugins() const return { "oblivion.esm", "update.esm" }; } -QIcon GameOblivion::gameIcon() const -{ - return MOBase::iconForExecutable(gameDirectory().absoluteFilePath(getBinaryName())); -} - std::map GameOblivion::featureList() const { static std::map result { diff --git a/src/games/oblivion/src/gameoblivion.h b/src/games/oblivion/src/gameoblivion.h index 257ef3d4..1e86eb3e 100644 --- a/src/games/oblivion/src/gameoblivion.h +++ b/src/games/oblivion/src/gameoblivion.h @@ -30,7 +30,6 @@ public: // IPluginGame interface virtual QString savegameExtension() const override; virtual QString steamAPPId() const override; virtual QStringList getPrimaryPlugins() const override; - virtual QIcon gameIcon() const override; virtual QString getGameShortName() const override; virtual QStringList getIniFiles() const override; virtual QStringList getDLCPlugins() const override; diff --git a/src/games/oblivion/src/oblivionscriptextender.cpp b/src/games/oblivion/src/oblivionscriptextender.cpp index dd43835a..159b87b3 100644 --- a/src/games/oblivion/src/oblivionscriptextender.cpp +++ b/src/games/oblivion/src/oblivionscriptextender.cpp @@ -3,16 +3,16 @@ #include #include +OblivionScriptExtender::OblivionScriptExtender(GameGamebryo const *game) : + GamebryoScriptExtender(game) +{ +} + QString OblivionScriptExtender::name() const { return "obse"; } -QString OblivionScriptExtender::loaderName() const -{ - return name() + "_loader.exe"; -} - QStringList OblivionScriptExtender::saveGameAttachmentExtensions() const { return { name() }; diff --git a/src/games/oblivion/src/oblivionscriptextender.h b/src/games/oblivion/src/oblivionscriptextender.h index 1088271f..a748431d 100644 --- a/src/games/oblivion/src/oblivionscriptextender.h +++ b/src/games/oblivion/src/oblivionscriptextender.h @@ -1,16 +1,14 @@ #ifndef OBLIVIONSCRIPTEXTENDER_H #define OBLIVIONSCRIPTEXTENDER_H +#include "gamebryoscriptextender.h" -#include - - -class OblivionScriptExtender : public ScriptExtender +class OblivionScriptExtender : public GamebryoScriptExtender { public: - virtual QString name() const override; + OblivionScriptExtender(const GameGamebryo *game); - virtual QString loaderName() const override; + virtual QString name() const override; virtual QStringList saveGameAttachmentExtensions() const override; From 42f73e34d19002223d6cd6376d54b0d601c4e3e5 Mon Sep 17 00:00:00 2001 From: Thomas Tanner Date: Sat, 28 Nov 2015 23:10:02 +0000 Subject: [PATCH 0119/1544] [game_skyrim] Abstract away the xxse_loader manipulation and make use of the 'ScriptExtender' feature instead --- src/games/skyrim/src/gameskyrim.cpp | 9 ++------- src/games/skyrim/src/gameskyrim.h | 1 - src/games/skyrim/src/skyrimscriptextender.cpp | 10 +++++----- src/games/skyrim/src/skyrimscriptextender.h | 10 ++++------ 4 files changed, 11 insertions(+), 19 deletions(-) diff --git a/src/games/skyrim/src/gameskyrim.cpp b/src/games/skyrim/src/gameskyrim.cpp index 1c6ca5ca..6cb042d6 100644 --- a/src/games/skyrim/src/gameskyrim.cpp +++ b/src/games/skyrim/src/gameskyrim.cpp @@ -27,7 +27,7 @@ bool GameSkyrim::init(IOrganizer *moInfo) if (!GameGamebryo::init(moInfo)) { return false; } - m_ScriptExtender = std::shared_ptr(new SkyrimScriptExtender()); + m_ScriptExtender = std::shared_ptr(new SkyrimScriptExtender(this)); m_DataArchives = std::shared_ptr(new SkyrimDataArchives()); m_BSAInvalidation = std::shared_ptr(new SkyrimBSAInvalidation(m_DataArchives, this)); return true; @@ -64,7 +64,7 @@ QString GameSkyrim::myGamesFolderName() const QList GameSkyrim::executables() const { return QList() - << ExecutableInfo("SKSE", findInGameFolder("skse_loader.exe")) + << ExecutableInfo("SKSE", findInGameFolder(m_ScriptExtender->loaderName())) << ExecutableInfo("SBW", findInGameFolder("SBW.exe")) << ExecutableInfo("Skyrim", findInGameFolder(getBinaryName())) << ExecutableInfo("Skyrim Launcher", findInGameFolder(getLauncherName())) @@ -153,11 +153,6 @@ QStringList GameSkyrim::getPrimaryPlugins() const return { "skyrim.esm", "update.esm" }; } -QIcon GameSkyrim::gameIcon() const -{ - return MOBase::iconForExecutable(gameDirectory().absoluteFilePath(getBinaryName())); -} - std::map GameSkyrim::featureList() const { static std::map result { diff --git a/src/games/skyrim/src/gameskyrim.h b/src/games/skyrim/src/gameskyrim.h index b57cc4f8..13f59666 100644 --- a/src/games/skyrim/src/gameskyrim.h +++ b/src/games/skyrim/src/gameskyrim.h @@ -30,7 +30,6 @@ public: // IPluginGame interface virtual QString savegameExtension() const override; virtual QString steamAPPId() const override; virtual QStringList getPrimaryPlugins() const override; - virtual QIcon gameIcon() const override; virtual QString getBinaryName() const override; virtual QString getGameShortName() const override; virtual QStringList getIniFiles() const override; diff --git a/src/games/skyrim/src/skyrimscriptextender.cpp b/src/games/skyrim/src/skyrimscriptextender.cpp index 924c0400..f9a9317b 100644 --- a/src/games/skyrim/src/skyrimscriptextender.cpp +++ b/src/games/skyrim/src/skyrimscriptextender.cpp @@ -3,16 +3,16 @@ #include #include +SkyrimScriptExtender::SkyrimScriptExtender(GameGamebryo const *game) : + GamebryoScriptExtender(game) +{ +} + QString SkyrimScriptExtender::name() const { return "skse"; } -QString SkyrimScriptExtender::loaderName() const -{ - return name() + "_loader.exe"; -} - QStringList SkyrimScriptExtender::saveGameAttachmentExtensions() const { return { name() }; diff --git a/src/games/skyrim/src/skyrimscriptextender.h b/src/games/skyrim/src/skyrimscriptextender.h index 53ae440d..1aa37493 100644 --- a/src/games/skyrim/src/skyrimscriptextender.h +++ b/src/games/skyrim/src/skyrimscriptextender.h @@ -1,16 +1,14 @@ #ifndef SKYRIMSCRIPTEXTENDER_H #define SKYRIMSCRIPTEXTENDER_H +#include "gamebryoscriptextender.h" -#include - - -class SkyrimScriptExtender : public ScriptExtender +class SkyrimScriptExtender : public GamebryoScriptExtender { public: - virtual QString name() const override; + SkyrimScriptExtender(const GameGamebryo *game); - virtual QString loaderName() const override; + virtual QString name() const override; virtual QStringList saveGameAttachmentExtensions() const override; From 7b839e9117dacd99a2c85bb0dd5fc563d7685ec3 Mon Sep 17 00:00:00 2001 From: Thomas Tanner Date: Sat, 28 Nov 2015 23:10:17 +0000 Subject: [PATCH 0120/1544] [game_fallout4vr] Abstract away the xxse_loader manipulation and make use of the 'ScriptExtender' feature instead --- src/games/fallout4vr/src/fallout4scriptextender.cpp | 10 +++++----- src/games/fallout4vr/src/fallout4scriptextender.h | 10 ++++------ src/games/fallout4vr/src/gamefallout4.cpp | 10 +++------- src/games/fallout4vr/src/gamefallout4.h | 1 - 4 files changed, 12 insertions(+), 19 deletions(-) diff --git a/src/games/fallout4vr/src/fallout4scriptextender.cpp b/src/games/fallout4vr/src/fallout4scriptextender.cpp index d3e0c3c5..7eb54a90 100644 --- a/src/games/fallout4vr/src/fallout4scriptextender.cpp +++ b/src/games/fallout4vr/src/fallout4scriptextender.cpp @@ -3,16 +3,16 @@ #include #include +Fallout4ScriptExtender::Fallout4ScriptExtender(GameGamebryo const *game) : + GamebryoScriptExtender(game) +{ +} + QString Fallout4ScriptExtender::name() const { return "f4se"; } -QString Fallout4ScriptExtender::loaderName() const -{ - return name() + "_loader.exe"; -} - QStringList Fallout4ScriptExtender::saveGameAttachmentExtensions() const { return { }; diff --git a/src/games/fallout4vr/src/fallout4scriptextender.h b/src/games/fallout4vr/src/fallout4scriptextender.h index 7427d7bf..add3697c 100644 --- a/src/games/fallout4vr/src/fallout4scriptextender.h +++ b/src/games/fallout4vr/src/fallout4scriptextender.h @@ -1,16 +1,14 @@ #ifndef FALLOUT3SCRIPTEXTENDER_H #define FALLOUT3SCRIPTEXTENDER_H +#include "gamebryoscriptextender.h" -#include - - -class Fallout4ScriptExtender : public ScriptExtender +class Fallout4ScriptExtender : public GamebryoScriptExtender { public: - virtual QString name() const override; + Fallout4ScriptExtender(GameGamebryo const *game); - virtual QString loaderName() const override; + virtual QString name() const override; virtual QStringList saveGameAttachmentExtensions() const override; diff --git a/src/games/fallout4vr/src/gamefallout4.cpp b/src/games/fallout4vr/src/gamefallout4.cpp index d7057a6a..d5c6829f 100644 --- a/src/games/fallout4vr/src/gamefallout4.cpp +++ b/src/games/fallout4vr/src/gamefallout4.cpp @@ -23,7 +23,7 @@ bool GameFallout4::init(IOrganizer *moInfo) if (!GameGamebryo::init(moInfo)) { return false; } - m_ScriptExtender = std::shared_ptr(new Fallout4ScriptExtender()); + m_ScriptExtender = std::shared_ptr(new Fallout4ScriptExtender(this)); m_DataArchives = std::shared_ptr(new Fallout4DataArchives()); return true; } @@ -57,7 +57,7 @@ QString GameFallout4::myGamesFolderName() const QList GameFallout4::executables() const { return QList() - << ExecutableInfo("F4SE", findInGameFolder("f4se_loader.exe")) + << ExecutableInfo("F4SE", findInGameFolder(m_ScriptExtender->loaderName())) << ExecutableInfo("Fallout 4", findInGameFolder(getBinaryName())) << ExecutableInfo("Fallout Launcher", findInGameFolder(getLauncherName())) << ExecutableInfo("LOOT", getLootPath()) @@ -141,11 +141,6 @@ QStringList GameFallout4::getPrimaryPlugins() const return { "fallout4.esm" }; } -QIcon GameFallout4::gameIcon() const -{ - return MOBase::iconForExecutable(gameDirectory().absoluteFilePath("Fallout4.exe")); -} - std::map GameFallout4::featureList() const { static std::map result { @@ -171,6 +166,7 @@ QStringList GameFallout4::getIniFiles() const { return { "fallout4.ini", "fallout4prefs.ini" }; } + QStringList GameFallout4::getDLCPlugins() const { return {}; diff --git a/src/games/fallout4vr/src/gamefallout4.h b/src/games/fallout4vr/src/gamefallout4.h index aaebd865..74e9f101 100644 --- a/src/games/fallout4vr/src/gamefallout4.h +++ b/src/games/fallout4vr/src/gamefallout4.h @@ -29,7 +29,6 @@ public: // IPluginGame interface virtual QString savegameExtension() const override; virtual QString steamAPPId() const override; virtual QStringList getPrimaryPlugins() const override; - virtual QIcon gameIcon() const override; virtual QStringList gameVariants() const override; virtual QString getGameShortName() const override; virtual QStringList getIniFiles() const override; From 6b94f54e2905242dba051287dbefa31248aa3746 Mon Sep 17 00:00:00 2001 From: Thomas Tanner Date: Sat, 28 Nov 2015 23:10:17 +0000 Subject: [PATCH 0121/1544] [game_fallout76] Abstract away the xxse_loader manipulation and make use of the 'ScriptExtender' feature instead --- src/games/fallout76/src/fallout4scriptextender.cpp | 10 +++++----- src/games/fallout76/src/fallout4scriptextender.h | 10 ++++------ src/games/fallout76/src/gamefallout4.cpp | 10 +++------- src/games/fallout76/src/gamefallout4.h | 1 - 4 files changed, 12 insertions(+), 19 deletions(-) diff --git a/src/games/fallout76/src/fallout4scriptextender.cpp b/src/games/fallout76/src/fallout4scriptextender.cpp index d3e0c3c5..7eb54a90 100644 --- a/src/games/fallout76/src/fallout4scriptextender.cpp +++ b/src/games/fallout76/src/fallout4scriptextender.cpp @@ -3,16 +3,16 @@ #include #include +Fallout4ScriptExtender::Fallout4ScriptExtender(GameGamebryo const *game) : + GamebryoScriptExtender(game) +{ +} + QString Fallout4ScriptExtender::name() const { return "f4se"; } -QString Fallout4ScriptExtender::loaderName() const -{ - return name() + "_loader.exe"; -} - QStringList Fallout4ScriptExtender::saveGameAttachmentExtensions() const { return { }; diff --git a/src/games/fallout76/src/fallout4scriptextender.h b/src/games/fallout76/src/fallout4scriptextender.h index 7427d7bf..add3697c 100644 --- a/src/games/fallout76/src/fallout4scriptextender.h +++ b/src/games/fallout76/src/fallout4scriptextender.h @@ -1,16 +1,14 @@ #ifndef FALLOUT3SCRIPTEXTENDER_H #define FALLOUT3SCRIPTEXTENDER_H +#include "gamebryoscriptextender.h" -#include - - -class Fallout4ScriptExtender : public ScriptExtender +class Fallout4ScriptExtender : public GamebryoScriptExtender { public: - virtual QString name() const override; + Fallout4ScriptExtender(GameGamebryo const *game); - virtual QString loaderName() const override; + virtual QString name() const override; virtual QStringList saveGameAttachmentExtensions() const override; diff --git a/src/games/fallout76/src/gamefallout4.cpp b/src/games/fallout76/src/gamefallout4.cpp index d7057a6a..d5c6829f 100644 --- a/src/games/fallout76/src/gamefallout4.cpp +++ b/src/games/fallout76/src/gamefallout4.cpp @@ -23,7 +23,7 @@ bool GameFallout4::init(IOrganizer *moInfo) if (!GameGamebryo::init(moInfo)) { return false; } - m_ScriptExtender = std::shared_ptr(new Fallout4ScriptExtender()); + m_ScriptExtender = std::shared_ptr(new Fallout4ScriptExtender(this)); m_DataArchives = std::shared_ptr(new Fallout4DataArchives()); return true; } @@ -57,7 +57,7 @@ QString GameFallout4::myGamesFolderName() const QList GameFallout4::executables() const { return QList() - << ExecutableInfo("F4SE", findInGameFolder("f4se_loader.exe")) + << ExecutableInfo("F4SE", findInGameFolder(m_ScriptExtender->loaderName())) << ExecutableInfo("Fallout 4", findInGameFolder(getBinaryName())) << ExecutableInfo("Fallout Launcher", findInGameFolder(getLauncherName())) << ExecutableInfo("LOOT", getLootPath()) @@ -141,11 +141,6 @@ QStringList GameFallout4::getPrimaryPlugins() const return { "fallout4.esm" }; } -QIcon GameFallout4::gameIcon() const -{ - return MOBase::iconForExecutable(gameDirectory().absoluteFilePath("Fallout4.exe")); -} - std::map GameFallout4::featureList() const { static std::map result { @@ -171,6 +166,7 @@ QStringList GameFallout4::getIniFiles() const { return { "fallout4.ini", "fallout4prefs.ini" }; } + QStringList GameFallout4::getDLCPlugins() const { return {}; diff --git a/src/games/fallout76/src/gamefallout4.h b/src/games/fallout76/src/gamefallout4.h index aaebd865..74e9f101 100644 --- a/src/games/fallout76/src/gamefallout4.h +++ b/src/games/fallout76/src/gamefallout4.h @@ -29,7 +29,6 @@ public: // IPluginGame interface virtual QString savegameExtension() const override; virtual QString steamAPPId() const override; virtual QStringList getPrimaryPlugins() const override; - virtual QIcon gameIcon() const override; virtual QStringList gameVariants() const override; virtual QString getGameShortName() const override; virtual QStringList getIniFiles() const override; From 10979184450e18ab542057895299c10c38452aef Mon Sep 17 00:00:00 2001 From: Thomas Tanner Date: Sat, 28 Nov 2015 23:10:17 +0000 Subject: [PATCH 0122/1544] [game_fallout4] Abstract away the xxse_loader manipulation and make use of the 'ScriptExtender' feature instead --- src/games/fallout4/src/fallout4scriptextender.cpp | 10 +++++----- src/games/fallout4/src/fallout4scriptextender.h | 10 ++++------ src/games/fallout4/src/gamefallout4.cpp | 10 +++------- src/games/fallout4/src/gamefallout4.h | 1 - 4 files changed, 12 insertions(+), 19 deletions(-) diff --git a/src/games/fallout4/src/fallout4scriptextender.cpp b/src/games/fallout4/src/fallout4scriptextender.cpp index d3e0c3c5..7eb54a90 100644 --- a/src/games/fallout4/src/fallout4scriptextender.cpp +++ b/src/games/fallout4/src/fallout4scriptextender.cpp @@ -3,16 +3,16 @@ #include #include +Fallout4ScriptExtender::Fallout4ScriptExtender(GameGamebryo const *game) : + GamebryoScriptExtender(game) +{ +} + QString Fallout4ScriptExtender::name() const { return "f4se"; } -QString Fallout4ScriptExtender::loaderName() const -{ - return name() + "_loader.exe"; -} - QStringList Fallout4ScriptExtender::saveGameAttachmentExtensions() const { return { }; diff --git a/src/games/fallout4/src/fallout4scriptextender.h b/src/games/fallout4/src/fallout4scriptextender.h index 7427d7bf..add3697c 100644 --- a/src/games/fallout4/src/fallout4scriptextender.h +++ b/src/games/fallout4/src/fallout4scriptextender.h @@ -1,16 +1,14 @@ #ifndef FALLOUT3SCRIPTEXTENDER_H #define FALLOUT3SCRIPTEXTENDER_H +#include "gamebryoscriptextender.h" -#include - - -class Fallout4ScriptExtender : public ScriptExtender +class Fallout4ScriptExtender : public GamebryoScriptExtender { public: - virtual QString name() const override; + Fallout4ScriptExtender(GameGamebryo const *game); - virtual QString loaderName() const override; + virtual QString name() const override; virtual QStringList saveGameAttachmentExtensions() const override; diff --git a/src/games/fallout4/src/gamefallout4.cpp b/src/games/fallout4/src/gamefallout4.cpp index d7057a6a..d5c6829f 100644 --- a/src/games/fallout4/src/gamefallout4.cpp +++ b/src/games/fallout4/src/gamefallout4.cpp @@ -23,7 +23,7 @@ bool GameFallout4::init(IOrganizer *moInfo) if (!GameGamebryo::init(moInfo)) { return false; } - m_ScriptExtender = std::shared_ptr(new Fallout4ScriptExtender()); + m_ScriptExtender = std::shared_ptr(new Fallout4ScriptExtender(this)); m_DataArchives = std::shared_ptr(new Fallout4DataArchives()); return true; } @@ -57,7 +57,7 @@ QString GameFallout4::myGamesFolderName() const QList GameFallout4::executables() const { return QList() - << ExecutableInfo("F4SE", findInGameFolder("f4se_loader.exe")) + << ExecutableInfo("F4SE", findInGameFolder(m_ScriptExtender->loaderName())) << ExecutableInfo("Fallout 4", findInGameFolder(getBinaryName())) << ExecutableInfo("Fallout Launcher", findInGameFolder(getLauncherName())) << ExecutableInfo("LOOT", getLootPath()) @@ -141,11 +141,6 @@ QStringList GameFallout4::getPrimaryPlugins() const return { "fallout4.esm" }; } -QIcon GameFallout4::gameIcon() const -{ - return MOBase::iconForExecutable(gameDirectory().absoluteFilePath("Fallout4.exe")); -} - std::map GameFallout4::featureList() const { static std::map result { @@ -171,6 +166,7 @@ QStringList GameFallout4::getIniFiles() const { return { "fallout4.ini", "fallout4prefs.ini" }; } + QStringList GameFallout4::getDLCPlugins() const { return {}; diff --git a/src/games/fallout4/src/gamefallout4.h b/src/games/fallout4/src/gamefallout4.h index aaebd865..74e9f101 100644 --- a/src/games/fallout4/src/gamefallout4.h +++ b/src/games/fallout4/src/gamefallout4.h @@ -29,7 +29,6 @@ public: // IPluginGame interface virtual QString savegameExtension() const override; virtual QString steamAPPId() const override; virtual QStringList getPrimaryPlugins() const override; - virtual QIcon gameIcon() const override; virtual QStringList gameVariants() const override; virtual QString getGameShortName() const override; virtual QStringList getIniFiles() const override; From fb4423bc075ee15eda06089ff292e1cf06cc9ccb Mon Sep 17 00:00:00 2001 From: Thomas Tanner Date: Sun, 29 Nov 2015 12:41:14 +0000 Subject: [PATCH 0123/1544] Tdying things up before going to a massive refactor of save game code --- src/gameGamebryo.pro | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/src/gameGamebryo.pro b/src/gameGamebryo.pro index ef2cfe60..62b71e48 100644 --- a/src/gameGamebryo.pro +++ b/src/gameGamebryo.pro @@ -25,4 +25,5 @@ include(../plugin_template.pri) INCLUDEPATH += "$${BOOSTPATH}" "$${PWD}/../gamefeatures" OTHER_FILES +=\ - SConscript + SConscript \ + CMakeLists.txt From 6e3edc28648872673f7dadd0aec3fadb8629fda6 Mon Sep 17 00:00:00 2001 From: Thomas Tanner Date: Sat, 5 Dec 2015 06:49:46 +0000 Subject: [PATCH 0124/1544] [game_fallout3] Most of work for savegame --- .../fallout3/src/fallout3dataarchives.cpp | 3 + src/games/fallout3/src/fallout3dataarchives.h | 5 +- src/games/fallout3/src/fallout3savegame.cpp | 60 +++++++++++++++++++ src/games/fallout3/src/fallout3savegame.h | 12 ++++ .../fallout3/src/fallout3savegameinfo.cpp | 9 +++ src/games/fallout3/src/fallout3savegameinfo.h | 12 ++++ src/games/fallout3/src/gameFallout3.pro | 12 +++- src/games/fallout3/src/gamefallout3.cpp | 17 ++---- src/games/fallout3/src/gamefallout3.h | 18 +----- 9 files changed, 113 insertions(+), 35 deletions(-) create mode 100644 src/games/fallout3/src/fallout3savegame.cpp create mode 100644 src/games/fallout3/src/fallout3savegame.h create mode 100644 src/games/fallout3/src/fallout3savegameinfo.cpp create mode 100644 src/games/fallout3/src/fallout3savegameinfo.h diff --git a/src/games/fallout3/src/fallout3dataarchives.cpp b/src/games/fallout3/src/fallout3dataarchives.cpp index bc3dd4a2..b2d42bc0 100644 --- a/src/games/fallout3/src/fallout3dataarchives.cpp +++ b/src/games/fallout3/src/fallout3dataarchives.cpp @@ -1,5 +1,8 @@ #include "fallout3dataarchives.h" + +#include "iprofile.h" #include + #include diff --git a/src/games/fallout3/src/fallout3dataarchives.h b/src/games/fallout3/src/fallout3dataarchives.h index 47e022b5..7b2a5345 100644 --- a/src/games/fallout3/src/fallout3dataarchives.h +++ b/src/games/fallout3/src/fallout3dataarchives.h @@ -2,10 +2,7 @@ #define FALLOUT3DATAARCHIVES_H -#include -#include -#include -#include +#include "gamebryodataarchives.h" class Fallout3DataArchives : public GamebryoDataArchives { diff --git a/src/games/fallout3/src/fallout3savegame.cpp b/src/games/fallout3/src/fallout3savegame.cpp new file mode 100644 index 00000000..7fe24e57 --- /dev/null +++ b/src/games/fallout3/src/fallout3savegame.cpp @@ -0,0 +1,60 @@ +#include "fallout3savegame.h" + +Fallout3SaveGame::Fallout3SaveGame(QString const &fileName) : + GamebryoSaveGame(fileName) +{ + FileWrapper file(this, "FO3SAVEGAME"); + + file.skip(); + + char ignore = 0x00; + while (ignore != 0x7c) { + file.read(ignore); // unknown + } + bool newVegas = false; + if (newVegas) { + ignore = 0x00; + // in new vegas there is another block of uninteresting (?) information + file.skip(); // 0x7c + while (ignore != 0x7c) { + file.read(ignore); // unknown + } + } + + file.setHasFieldMarkers(true); + + unsigned long width; + file.read(width); + + unsigned long height; + file.read(height); + + file.read(m_SaveNumber); + + file.read(m_PCName); + + QString whatthis; + file.read(whatthis); + + long level; + file.read(level); + m_PCLevel = level; + + file.read(m_PCLocation); + + QString playtime; + file.read(playtime); + + //Abstract this + QScopedArrayPointer buffer(new unsigned char[width * height * 3]); + file.read(buffer.data(), width * height * 3); + // why do I have to copy here? without the copy, the buffer seems to get deleted after the + // temporary vanishes, but Qts implicit sharing should handle that? + m_Screenshot = QImage(buffer.data(), width, height, QImage::Format_RGB888).scaledToWidth(256); + + file.skip(5); // unknown + + //Abstract this + file.readPlugins(); +} + diff --git a/src/games/fallout3/src/fallout3savegame.h b/src/games/fallout3/src/fallout3savegame.h new file mode 100644 index 00000000..7f953efa --- /dev/null +++ b/src/games/fallout3/src/fallout3savegame.h @@ -0,0 +1,12 @@ +#ifndef FALLOUT3SAVEGAME_H +#define FALLOUT3SAVEGAME_H + +#include "gamebryosavegame.h" + +class Fallout3SaveGame : public GamebryoSaveGame +{ +public: + Fallout3SaveGame(QString const &fileName); +}; + +#endif // FALLOUT3SAVEGAME_H diff --git a/src/games/fallout3/src/fallout3savegameinfo.cpp b/src/games/fallout3/src/fallout3savegameinfo.cpp new file mode 100644 index 00000000..c9823272 --- /dev/null +++ b/src/games/fallout3/src/fallout3savegameinfo.cpp @@ -0,0 +1,9 @@ +#include "fallout3savegameinfo.h" + +#include "fallout3savegame.h" + +MOBase::ISaveGame const *Fallout3SaveGameInfo::getSaveGameInfo(const QString &file) const +{ + return new Fallout3SaveGame(file); +} + diff --git a/src/games/fallout3/src/fallout3savegameinfo.h b/src/games/fallout3/src/fallout3savegameinfo.h new file mode 100644 index 00000000..3f2e96c4 --- /dev/null +++ b/src/games/fallout3/src/fallout3savegameinfo.h @@ -0,0 +1,12 @@ +#ifndef FALLOUT3SAVEGAMEINFO_H +#define FALLOUT3SAVEGAMEINFO_H + +#include "savegameinfo.h" + +class Fallout3SaveGameInfo : public SaveGameInfo +{ +public: + virtual MOBase::ISaveGame const *getSaveGameInfo(QString const &file) const override; +}; + +#endif // FALLOUT3SAVEGAMEINFO_H diff --git a/src/games/fallout3/src/gameFallout3.pro b/src/games/fallout3/src/gameFallout3.pro index ee65d092..3510d026 100644 --- a/src/games/fallout3/src/gameFallout3.pro +++ b/src/games/fallout3/src/gameFallout3.pro @@ -16,12 +16,16 @@ DEFINES += GAMEFALLOUTNV_LIBRARY SOURCES += gamefallout3.cpp \ fallout3bsainvalidation.cpp \ fallout3scriptextender.cpp \ - fallout3dataarchives.cpp + fallout3dataarchives.cpp \ + fallout3savegame.cpp \ + fallout3savegameinfo.cpp HEADERS += gamefallout3.h \ fallout3bsainvalidation.h \ fallout3scriptextender.h \ - fallout3dataarchives.h + fallout3dataarchives.h \ + fallout3savegame.h \ + fallout3savegameinfo.h CONFIG(debug, debug|release) { LIBS += -L"$${OUT_PWD}/../gameGamebryo/debug" @@ -41,4 +45,6 @@ LIBS += -ladvapi32 -lole32 -lgameGamebryo OTHER_FILES += \ gamefallout3.json\ - SConscript + SConscript \ + CMakeLists.txt + diff --git a/src/games/fallout3/src/gamefallout3.cpp b/src/games/fallout3/src/gamefallout3.cpp index 43ec35ac..8bc5a522 100644 --- a/src/games/fallout3/src/gamefallout3.cpp +++ b/src/games/fallout3/src/gamefallout3.cpp @@ -1,5 +1,10 @@ #include "gameFallout3.h" +#include "fallout3bsainvalidation.h" +#include "fallout3scriptextender.h" +#include "fallout3dataarchives.h" +#include "fallout3savegameinfo.h" + #include #include #include @@ -26,6 +31,7 @@ bool GameFallout3::init(IOrganizer *moInfo) m_ScriptExtender = std::shared_ptr(new Fallout3ScriptExtender(this)); m_DataArchives = std::shared_ptr(new Fallout3DataArchives()); m_BSAInvalidation = std::shared_ptr(new Fallout3BSAInvalidation(m_DataArchives, this)); + m_SaveGameInfo = std::shared_ptr(new Fallout3SaveGameInfo()); return true; } @@ -149,17 +155,6 @@ QStringList GameFallout3::getPrimaryPlugins() const return { "fallout3.esm" }; } -std::map GameFallout3::featureList() const -{ - static std::map result { - { typeid(BSAInvalidation), m_BSAInvalidation.get() }, - { typeid(ScriptExtender), m_ScriptExtender.get() }, - { typeid(DataArchives), m_DataArchives.get() } - }; - - return result; -} - QStringList GameFallout3::gameVariants() const { diff --git a/src/games/fallout3/src/gamefallout3.h b/src/games/fallout3/src/gamefallout3.h index 365cc1a4..70373e37 100644 --- a/src/games/fallout3/src/gamefallout3.h +++ b/src/games/fallout3/src/gamefallout3.h @@ -1,13 +1,7 @@ #ifndef GAMEFALLOUT3_H #define GAMEFALLOUT3_H - -#include "fallout3bsainvalidation.h" -#include "fallout3scriptextender.h" -#include "fallout3dataarchives.h" -#include -#include - +#include "gamegamebryo.h" class GameFallout3 : public GameGamebryo { @@ -46,10 +40,6 @@ public: // IPlugin interface virtual bool isActive() const; virtual QList settings() const; -protected: - - virtual std::map featureList() const override; - private: virtual QString identifyGamePath() const override; @@ -59,12 +49,6 @@ private: void copyToProfile(const QString &sourcePath, const QDir &destinationDirectory, const QString &sourceFileName, const QString &destinationFileName = QString()) const; -private: - - std::shared_ptr m_ScriptExtender { nullptr }; - std::shared_ptr m_DataArchives { nullptr }; - std::shared_ptr m_BSAInvalidation { nullptr }; - }; #endif // GAMEFALLOUT3_H From 6c6ca2f5307a05772586de60e4285ed11ae8dd5d Mon Sep 17 00:00:00 2001 From: Thomas Tanner Date: Sat, 5 Dec 2015 06:50:01 +0000 Subject: [PATCH 0125/1544] [game_falloutnv] Most of work for savegame --- src/games/falloutnv/src/falloutnvsavegame.cpp | 57 +++++++++++++++++++ src/games/falloutnv/src/falloutnvsavegame.h | 12 ++++ .../falloutnv/src/falloutnvsavegameinfo.cpp | 8 +++ .../falloutnv/src/falloutnvsavegameinfo.h | 12 ++++ src/games/falloutnv/src/gameFalloutNV.pro | 12 +++- src/games/falloutnv/src/gamefalloutnv.cpp | 16 ++---- src/games/falloutnv/src/gamefalloutnv.h | 18 +----- 7 files changed, 104 insertions(+), 31 deletions(-) create mode 100644 src/games/falloutnv/src/falloutnvsavegame.cpp create mode 100644 src/games/falloutnv/src/falloutnvsavegame.h create mode 100644 src/games/falloutnv/src/falloutnvsavegameinfo.cpp create mode 100644 src/games/falloutnv/src/falloutnvsavegameinfo.h diff --git a/src/games/falloutnv/src/falloutnvsavegame.cpp b/src/games/falloutnv/src/falloutnvsavegame.cpp new file mode 100644 index 00000000..9a27c275 --- /dev/null +++ b/src/games/falloutnv/src/falloutnvsavegame.cpp @@ -0,0 +1,57 @@ +#include "falloutnvsavegame.h" + +FalloutNVSaveGame::FalloutNVSaveGame(QString const &fileName) : + GamebryoSaveGame(fileName) +{ + FileWrapper file(this, "FO3SAVEGAME"); + + file.skip(); + + char ignore = 0x00; + while (ignore != 0x7c) { + file.read(ignore); // unknown + } + ignore = 0x00; + // in new vegas there is another block of uninteresting (?) information + file.skip(); // 0x7c + while (ignore != 0x7c) { + file.read(ignore); // unknown + } + + file.setHasFieldMarkers(true); + + unsigned long width; + file.read(width); + + unsigned long height; + file.read(height); + + file.read(m_SaveNumber); + + file.read(m_PCName); + + QString whatthis; + file.read(whatthis); + + long level; + file.read(level); + m_PCLevel = level; + + file.read(m_PCLocation); + + QString playtime; + file.read(playtime); + + //Abstract this + QScopedArrayPointer buffer(new unsigned char[width * height * 3]); + file.read(buffer.data(), width * height * 3); + // why do I have to copy here? without the copy, the buffer seems to get deleted after the + // temporary vanishes, but Qts implicit sharing should handle that? + m_Screenshot = QImage(buffer.data(), width, height, QImage::Format_RGB888).scaledToWidth(256); + + file.skip(5); // unknown + + //Abstract this + file.readPlugins(); +} + diff --git a/src/games/falloutnv/src/falloutnvsavegame.h b/src/games/falloutnv/src/falloutnvsavegame.h new file mode 100644 index 00000000..15c6b4ec --- /dev/null +++ b/src/games/falloutnv/src/falloutnvsavegame.h @@ -0,0 +1,12 @@ +#ifndef FALLOUTNVSAVEGAME_H +#define FALLOUTNVSAVEGAME_H + +#include "gamebryosavegame.h" + +class FalloutNVSaveGame : public GamebryoSaveGame +{ +public: + FalloutNVSaveGame(QString const &fileName); +}; + +#endif // FALLOUTNVSAVEGAME_H diff --git a/src/games/falloutnv/src/falloutnvsavegameinfo.cpp b/src/games/falloutnv/src/falloutnvsavegameinfo.cpp new file mode 100644 index 00000000..1e675323 --- /dev/null +++ b/src/games/falloutnv/src/falloutnvsavegameinfo.cpp @@ -0,0 +1,8 @@ +#include "falloutnvsavegameinfo.h" + +#include "falloutnvsavegame.h" + +MOBase::ISaveGame const *FalloutNVSaveGameInfo::getSaveGameInfo(const QString &file) const +{ + return new FalloutNVSaveGame(file); +} diff --git a/src/games/falloutnv/src/falloutnvsavegameinfo.h b/src/games/falloutnv/src/falloutnvsavegameinfo.h new file mode 100644 index 00000000..cf6591ea --- /dev/null +++ b/src/games/falloutnv/src/falloutnvsavegameinfo.h @@ -0,0 +1,12 @@ +#ifndef FALLOUTNVSAVEGAMEINFO_H +#define FALLOUTNVSAVEGAMEINFO_H + +#include "savegameinfo.h" + +class FalloutNVSaveGameInfo : public SaveGameInfo +{ +public: + virtual MOBase::ISaveGame const *getSaveGameInfo(QString const &file) const override; +}; + +#endif // FALLOUTNVSAVEGAMEINFO_H diff --git a/src/games/falloutnv/src/gameFalloutNV.pro b/src/games/falloutnv/src/gameFalloutNV.pro index 9790ca4f..d15f0b1a 100644 --- a/src/games/falloutnv/src/gameFalloutNV.pro +++ b/src/games/falloutnv/src/gameFalloutNV.pro @@ -16,12 +16,16 @@ DEFINES += GAMEFALLOUTNV_LIBRARY SOURCES += gamefalloutnv.cpp \ falloutnvbsainvalidation.cpp \ falloutnvscriptextender.cpp \ - falloutnvdataarchives.cpp + falloutnvdataarchives.cpp \ + falloutnvsavegame.cpp \ + falloutnvsavegameinfo.cpp HEADERS += gamefalloutnv.h \ falloutnvbsainvalidation.h \ falloutnvscriptextender.h \ - falloutnvdataarchives.h + falloutnvdataarchives.h \ + falloutnvsavegame.h \ + falloutnvsavegameinfo.h CONFIG(debug, debug|release) { LIBS += -L"$${OUT_PWD}/../gameGamebryo/debug" @@ -41,4 +45,6 @@ LIBS += -ladvapi32 -lole32 -lgameGamebryo OTHER_FILES += \ gamefalloutnv.json\ - SConscript + SConscript \ + CMakeLists.txt + diff --git a/src/games/falloutnv/src/gamefalloutnv.cpp b/src/games/falloutnv/src/gamefalloutnv.cpp index 31c8bf24..f812f055 100644 --- a/src/games/falloutnv/src/gamefalloutnv.cpp +++ b/src/games/falloutnv/src/gamefalloutnv.cpp @@ -1,5 +1,9 @@ #include "gameFalloutNV.h" +#include "falloutnvbsainvalidation.h" +#include "falloutnvdataarchives.h" +#include "falloutnvsavegameinfo.h" +#include "falloutnvscriptextender.h" #include #include #include @@ -25,6 +29,7 @@ bool GameFalloutNV::init(IOrganizer *moInfo) m_ScriptExtender = std::shared_ptr(new FalloutNVScriptExtender(this)); m_DataArchives = std::shared_ptr(new FalloutNVDataArchives()); m_BSAInvalidation = std::shared_ptr(new FalloutNVBSAInvalidation(m_DataArchives, this)); + m_SaveGameInfo = std::shared_ptr(new FalloutNVSaveGameInfo()); return true; } @@ -146,17 +151,6 @@ QStringList GameFalloutNV::getPrimaryPlugins() const return { "falloutnv.esm" }; } -std::map GameFalloutNV::featureList() const -{ - static std::map result { - { typeid(BSAInvalidation), m_BSAInvalidation.get() }, - { typeid(ScriptExtender), m_ScriptExtender.get() }, - { typeid(DataArchives), m_DataArchives.get() } - }; - - return result; -} - QString GameFalloutNV::getGameShortName() const { return "FalloutNV"; diff --git a/src/games/falloutnv/src/gamefalloutnv.h b/src/games/falloutnv/src/gamefalloutnv.h index eff99862..c3f4737d 100644 --- a/src/games/falloutnv/src/gamefalloutnv.h +++ b/src/games/falloutnv/src/gamefalloutnv.h @@ -1,13 +1,7 @@ #ifndef GAMEFALLOUTNV_H #define GAMEFALLOUTNV_H - -#include "falloutnvbsainvalidation.h" -#include "falloutnvscriptextender.h" -#include "falloutnvdataarchives.h" -#include -#include - +#include "gamegamebryo.h" class GameFalloutNV : public GameGamebryo { @@ -45,10 +39,6 @@ public: // IPlugin interface virtual bool isActive() const; virtual QList settings() const; -protected: - - virtual std::map featureList() const override; - private: virtual QString identifyGamePath() const override; @@ -58,12 +48,6 @@ private: void copyToProfile(const QString &sourcePath, const QDir &destinationDirectory, const QString &sourceFileName, const QString &destinationFileName = QString()) const; -private: - - std::shared_ptr m_ScriptExtender { nullptr }; - std::shared_ptr m_DataArchives { nullptr }; - std::shared_ptr m_BSAInvalidation { nullptr }; - }; #endif // GAMEFALLOUTNV_H From aa6b1d5a5cb1477881ff7a9aa09315f32793cd16 Mon Sep 17 00:00:00 2001 From: Thomas Tanner Date: Sat, 5 Dec 2015 06:50:20 +0000 Subject: [PATCH 0126/1544] Most of work for savegame --- src/SConscript | 2 + src/gameGamebryo.pro | 6 +- src/gamebryobsainvalidation.cpp | 1 + src/gamebryodataarchives.h | 3 +- src/gamebryosavegame.cpp | 115 ++++++++++++++++++++++++++++++++ src/gamebryosavegame.h | 114 +++++++++++++++++++++++++++++++ src/gamegamebryo.cpp | 12 ++++ src/gamegamebryo.h | 22 +++++- 8 files changed, 270 insertions(+), 5 deletions(-) create mode 100644 src/gamebryosavegame.cpp create mode 100644 src/gamebryosavegame.h diff --git a/src/SConscript b/src/SConscript index 3b96d894..94801639 100644 --- a/src/SConscript +++ b/src/SConscript @@ -1,5 +1,7 @@ import os +print 'calling gamebro sconscript' + Import('qt_env') env = qt_env.Clone() diff --git a/src/gameGamebryo.pro b/src/gameGamebryo.pro index 62b71e48..24e3c9dd 100644 --- a/src/gameGamebryo.pro +++ b/src/gameGamebryo.pro @@ -12,13 +12,15 @@ SOURCES += gamegamebryo.cpp \ dummybsa.cpp \ gamebryobsainvalidation.cpp \ gamebryodataarchives.cpp \ - gamebryoscriptextender.cpp + gamebryoscriptextender.cpp \ + gamebryosavegame.cpp HEADERS += gamegamebryo.h \ dummybsa.h \ gamebryobsainvalidation.h \ gamebryodataarchives.h \ - gamebryoscriptextender.h + gamebryoscriptextender.h \ + gamebryosavegame.h include(../plugin_template.pri) diff --git a/src/gamebryobsainvalidation.cpp b/src/gamebryobsainvalidation.cpp index af6e2d08..dfc9484f 100644 --- a/src/gamebryobsainvalidation.cpp +++ b/src/gamebryobsainvalidation.cpp @@ -2,6 +2,7 @@ #include "dummybsa.h" #include "iplugingame.h" +#include "iprofile.h" #include #include #include diff --git a/src/gamebryodataarchives.h b/src/gamebryodataarchives.h index a720afa0..66390880 100644 --- a/src/gamebryodataarchives.h +++ b/src/gamebryodataarchives.h @@ -2,8 +2,7 @@ #define GAMEBRYODATAARCHIVES_H -#include - +#include "dataarchives.h" class GamebryoDataArchives : public DataArchives { diff --git a/src/gamebryosavegame.cpp b/src/gamebryosavegame.cpp new file mode 100644 index 00000000..e8c515de --- /dev/null +++ b/src/gamebryosavegame.cpp @@ -0,0 +1,115 @@ +#include "gamebryosavegame.h" + +#include +#include + +#include +#include + +GamebryoSaveGame::GamebryoSaveGame(QString const &file) : + m_FileName(file), + m_CreationTime(QFileInfo(file).lastModified()) +{ +} + +GamebryoSaveGame::~GamebryoSaveGame() +{ +} + +QString GamebryoSaveGame::getFilename() const +{ + return m_FileName; +} + +QDateTime GamebryoSaveGame::getCreationTime() const +{ + return m_CreationTime; +} + +void GamebryoSaveGame::readHeader(QFile &file, const QString &expected) +{ + file.setFileName(m_FileName); + if (!file.open(QIODevice::ReadOnly)) { + throw std::runtime_error(QObject::tr("failed to open %1").arg(m_FileName).toUtf8().constData()); + } + + std::vector fileID(expected.length() + 1); + file.read(fileID.data(), expected.length()); + fileID[expected.length()] = '\0'; + + QString id(fileID.data()); + if (expected != id) { + throw std::runtime_error( + QObject::tr("wrong file format - expected %1 got %2").arg(expected).arg(id).toUtf8().constData()); + } +} + +GamebryoSaveGame::FileWrapper::FileWrapper(GamebryoSaveGame *game, + QString const &expected) : + m_Game(game), + m_File(game->m_FileName), + m_HasFieldMarkers(false) +{ + if (!m_File.open(QIODevice::ReadOnly)) { + throw std::runtime_error(QObject::tr("failed to open %1").arg(game->m_FileName).toUtf8().constData()); + } + + std::vector fileID(expected.length() + 1); + m_File.read(fileID.data(), expected.length()); + fileID[expected.length()] = '\0'; + + QString id(fileID.data()); + if (expected != id) { + throw std::runtime_error( + QObject::tr("wrong file format - expected %1 got %2").arg(expected).arg(id).toUtf8().constData()); + } +} + +void GamebryoSaveGame::FileWrapper::setHasFieldMarkers(bool state) +{ + m_HasFieldMarkers = state; +} + +void GamebryoSaveGame::FileWrapper::setStringLength(size_t len) +{ + m_Length = len; +} + +template <> __declspec(dllexport) void GamebryoSaveGame::FileWrapper::read(QString &value) +{ + unsigned short length; + if (m_Length == 1) { + unsigned char len; + read(len); + length = len; + } else { + read(length); + } + std::vector buffer(length); + + read(buffer.data(), length); + if (m_HasFieldMarkers) { + skip(); + } + + value = QString::fromLatin1(buffer.data(), length); +} + +void GamebryoSaveGame::FileWrapper::read(void *buff, std::size_t length) +{ + int read = m_File.read(static_cast(buff), length); + if (read != length) { + throw std::runtime_error("unexpected end of file"); + } +} + +void GamebryoSaveGame::FileWrapper::readPlugins() +{ + unsigned char count; + read(count); + for (std::size_t i = 0; i < count; ++i) { + QString name; + read(name); + m_Game->m_Plugins.push_back(name); + } +} diff --git a/src/gamebryosavegame.h b/src/gamebryosavegame.h new file mode 100644 index 00000000..7068da53 --- /dev/null +++ b/src/gamebryosavegame.h @@ -0,0 +1,114 @@ +#ifndef GAMEBRYOSAVEGAME_H +#define GAMEBRYOSAVEGAME_H + +#include "isavegame.h" + +#include +#include +#include +#include + +//class QFile; +#include + +class GamebryoSaveGame : public MOBase::ISaveGame +{ +public: + GamebryoSaveGame(QString const &file); + + virtual ~GamebryoSaveGame(); + + virtual QString getFilename() const override; + + virtual QDateTime getCreationTime() const override; + + //Simple getters + QString getPCName() const { return m_PCName; } + unsigned short getPCLevel() const { return m_PCLevel; } + QString getPCLocation() const { return m_PCLocation; } + unsigned long getSaveNumber() const { return m_SaveNumber; } + QStringList const &getPlugins() const { return m_Plugins; } + QImage const &getScreenshot() const { return m_Screenshot; } + +protected: + + friend class FileWrapper; + + class FileWrapper + { + public: + /** Construct the save file information. + * @params expected - expect bytes at start of file + **/ + FileWrapper(GamebryoSaveGame *game, QString const &expected); + + /** Set this for save games that have a marker at the end of each + * field. Specifically fallout + **/ + void setHasFieldMarkers(bool); + + /** The length of the string length. + * Normally a string has a 2 byte length. Oblivion has a single byte. + **/ + void setStringLength(std::size_t len); + + template void skip(int count = 1) + { + if (!m_File.seek(m_File.pos() + count * sizeof(T))) { + throw std::runtime_error("unexpected end of file"); + } + } + + template void read(T &value) + { + int read = m_File.read(reinterpret_cast(&value), sizeof(T)); + if (read != sizeof(T)) { + throw std::runtime_error("unexpected end of file"); + } + if (m_HasFieldMarkers) { + skip(); + } + } + + template <> void read(QString &value); + + void read(void *buff, std::size_t length); + + void readPlugins(); + + private: + GamebryoSaveGame *m_Game; + QFile m_File; + bool m_HasFieldMarkers; + std::size_t m_Length; + }; + + + template void FileRead(QFile &file, T &value) + { + int read = file.read(reinterpret_cast(&value), sizeof(T)); + if (read != sizeof(T)) { + throw std::runtime_error("unexpected end of file"); + } + } + + template void FileSkip(QFile &file, int count = 1) + { + if (!file.seek(file.pos() + count * sizeof(T))) { + throw std::runtime_error("unexpected end of file"); + } + } + + void readHeader(QFile &file, QString const &expected); + + QString m_FileName; + QString m_PCName; + unsigned short m_PCLevel; + QString m_PCLocation; + unsigned long m_SaveNumber; + QDateTime m_CreationTime; + QStringList m_Plugins; + QImage m_Screenshot; +}; + +#endif // GAMEBRYOSAVEGAME_H diff --git a/src/gamegamebryo.cpp b/src/gamegamebryo.cpp index 02c82e9d..d471b75e 100644 --- a/src/gamegamebryo.cpp +++ b/src/gamegamebryo.cpp @@ -191,3 +191,15 @@ QString GameGamebryo::getLootPath() const return findInRegistry(HKEY_LOCAL_MACHINE, L"Software\\LOOT", L"Installed Path") + "/Loot.exe"; } +std::map GameGamebryo::featureList() const +{ + static std::map result { + { typeid(BSAInvalidation), m_BSAInvalidation.get() }, + { typeid(ScriptExtender), m_ScriptExtender.get() }, + { typeid(DataArchives), m_DataArchives.get() }, + { typeid(SaveGameInfo), m_SaveGameInfo.get() } + }; + + return result; +} + diff --git a/src/gamegamebryo.h b/src/gamegamebryo.h index f4ef1186..4b1f6c8f 100644 --- a/src/gamegamebryo.h +++ b/src/gamegamebryo.h @@ -1,9 +1,17 @@ #ifndef GAMEGAMEBRYO_H #define GAMEGAMEBRYO_H +#include "iplugingame.h" + +class ScriptExtender; +class DataArchives; +class SaveGameInfo; +class BSAInvalidation; + +#include -#include #include + #include @@ -56,6 +64,18 @@ protected: QString selectedVariant() const; virtual QString getLauncherName() const; +protected: + + std::map featureList() const; + + //These should be implemented by anything that uses gamebro (I think) + //(and if they don't, it'll be a null pointer and won't look implemented, + //so that's fine too). + std::shared_ptr m_ScriptExtender { nullptr }; + std::shared_ptr m_DataArchives { nullptr }; + std::shared_ptr m_BSAInvalidation { nullptr }; + std::shared_ptr m_SaveGameInfo { nullptr }; + private: QString determineMyGamesPath(const QString &gameName); From f660289bba8c85bf7e9fd4d093c86bd1a249c221 Mon Sep 17 00:00:00 2001 From: Thomas Tanner Date: Sat, 5 Dec 2015 06:50:32 +0000 Subject: [PATCH 0127/1544] [game_oblivion] Most of work for savegame --- src/games/oblivion/src/gameOblivion.pro | 12 +++-- src/games/oblivion/src/gameoblivion.cpp | 18 +++---- src/games/oblivion/src/gameoblivion.h | 18 +------ src/games/oblivion/src/oblivionsavegame.cpp | 50 +++++++++++++++++++ src/games/oblivion/src/oblivionsavegame.h | 12 +++++ .../oblivion/src/oblivionsavegameinfo.cpp | 9 ++++ src/games/oblivion/src/oblivionsavegameinfo.h | 12 +++++ .../oblivion/src/oblivionscriptextender.cpp | 4 ++ .../oblivion/src/oblivionscriptextender.h | 1 + 9 files changed, 105 insertions(+), 31 deletions(-) create mode 100644 src/games/oblivion/src/oblivionsavegame.cpp create mode 100644 src/games/oblivion/src/oblivionsavegame.h create mode 100644 src/games/oblivion/src/oblivionsavegameinfo.cpp create mode 100644 src/games/oblivion/src/oblivionsavegameinfo.h diff --git a/src/games/oblivion/src/gameOblivion.pro b/src/games/oblivion/src/gameOblivion.pro index 16b1836f..51b1766e 100644 --- a/src/games/oblivion/src/gameOblivion.pro +++ b/src/games/oblivion/src/gameOblivion.pro @@ -16,12 +16,16 @@ DEFINES += GAMEOBLIVION_LIBRARY SOURCES += gameoblivion.cpp \ oblivionbsainvalidation.cpp \ oblivionscriptextender.cpp \ - obliviondataarchives.cpp + obliviondataarchives.cpp \ + oblivionsavegame.cpp \ + oblivionsavegameinfo.cpp HEADERS += gameoblivion.h \ oblivionbsainvalidation.h \ oblivionscriptextender.h \ - obliviondataarchives.h + obliviondataarchives.h \ + oblivionsavegame.h \ + oblivionsavegameinfo.h CONFIG(debug, debug|release) { LIBS += -L"$${OUT_PWD}/../gameGamebryo/debug" @@ -41,4 +45,6 @@ LIBS += -ladvapi32 -lole32 -lgameGamebryo OTHER_FILES += \ gameoblivion.json\ - SConscript + SConscript \ + CMakeLists.txt + diff --git a/src/games/oblivion/src/gameoblivion.cpp b/src/games/oblivion/src/gameoblivion.cpp index 1d6a07e5..ccfeb324 100644 --- a/src/games/oblivion/src/gameoblivion.cpp +++ b/src/games/oblivion/src/gameoblivion.cpp @@ -1,4 +1,10 @@ #include "gameoblivion.h" + +#include "oblivionbsainvalidation.h" +#include "obliviondataarchives.h" +#include "oblivionsavegameinfo.h" +#include "oblivionscriptextender.h" + #include #include #include @@ -22,6 +28,7 @@ bool GameOblivion::init(IOrganizer *moInfo) m_ScriptExtender = std::shared_ptr(new OblivionScriptExtender(this)); m_DataArchives = std::shared_ptr(new OblivionDataArchives()); m_BSAInvalidation = std::shared_ptr(new OblivionBSAInvalidation(m_DataArchives, this)); + m_SaveGameInfo = std::shared_ptr(new OblivionSaveGameInfo()); return true; } @@ -145,17 +152,6 @@ QStringList GameOblivion::getPrimaryPlugins() const return { "oblivion.esm", "update.esm" }; } -std::map GameOblivion::featureList() const -{ - static std::map result { - { typeid(BSAInvalidation), m_BSAInvalidation.get() }, - { typeid(ScriptExtender), m_ScriptExtender.get() }, - { typeid(DataArchives), m_DataArchives.get() } - }; - - return result; -} - QString GameOblivion::getGameShortName() const { return "Oblivion"; diff --git a/src/games/oblivion/src/gameoblivion.h b/src/games/oblivion/src/gameoblivion.h index 1e86eb3e..7d853de3 100644 --- a/src/games/oblivion/src/gameoblivion.h +++ b/src/games/oblivion/src/gameoblivion.h @@ -1,13 +1,7 @@ #ifndef GAMEOBLIVION_H #define GAMEOBLIVION_H - -#include "oblivionbsainvalidation.h" -#include "oblivionscriptextender.h" -#include "obliviondataarchives.h" -#include -#include - +#include "gamegamebryo.h" class GameOblivion : public GameGamebryo { @@ -45,10 +39,6 @@ public: // IPlugin interface virtual bool isActive() const; virtual QList settings() const; -protected: - - virtual std::map featureList() const override; - private: virtual QString identifyGamePath() const override; @@ -58,12 +48,6 @@ private: void copyToProfile(const QString &sourcePath, const QDir &destinationDirectory, const QString &sourceFileName, const QString &destinationFileName = QString()) const; -private: - - std::shared_ptr m_ScriptExtender { nullptr }; - std::shared_ptr m_DataArchives { nullptr }; - std::shared_ptr m_BSAInvalidation { nullptr }; - }; #endif // GAMEOBLIVION_H diff --git a/src/games/oblivion/src/oblivionsavegame.cpp b/src/games/oblivion/src/oblivionsavegame.cpp new file mode 100644 index 00000000..4bb4e7d1 --- /dev/null +++ b/src/games/oblivion/src/oblivionsavegame.cpp @@ -0,0 +1,50 @@ +#include "oblivionsavegame.h" + +#include + +OblivionSaveGame::OblivionSaveGame(const QString &game) : + GamebryoSaveGame(game) +{ + FileWrapper file(this, "TES4SAVEGAME"); + file.setStringLength(1); + + file.skip(); + + //Hmm. We could probably just skip all of these + unsigned char version_minor; + file.read(version_minor); + file.skip(); + unsigned long headerVersion; + file.read(headerVersion); + unsigned long saveHeaderSize; + file.read(saveHeaderSize); + + file.read(m_SaveNumber); + + file.read(m_PCName); + file.read(m_PCLevel); + file.read(m_PCLocation); + + file.skip(); //game days + file.skip(); //game ticks + + SYSTEMTIME ctime; + file.read(ctime); + //FIXME update creation time with this + + unsigned long size; + file.read(size); + + unsigned long width; + file.read(width); + unsigned long height; + file.read(height); + + QScopedArrayPointer buffer(new unsigned char[width * height * 3]); + file.read(buffer.data(), width * height * 3); + // why do I have to copy here? without the copy, the buffer seems to get deleted after the + // temporary vanishes, but Qts implicit sharing should handle that? + m_Screenshot = QImage(buffer.data(), width, height, QImage::Format_RGB888).copy(); + + file.readPlugins(); +} diff --git a/src/games/oblivion/src/oblivionsavegame.h b/src/games/oblivion/src/oblivionsavegame.h new file mode 100644 index 00000000..f6e05ea8 --- /dev/null +++ b/src/games/oblivion/src/oblivionsavegame.h @@ -0,0 +1,12 @@ +#ifndef OBLIVIONSAVEGAME_H +#define OBLIVIONSAVEGAME_H + +#include "gamebryosavegame.h" + +class OblivionSaveGame : public GamebryoSaveGame +{ +public: + OblivionSaveGame(QString const &); +}; + +#endif // OBLIVIONSAVEGAME_H diff --git a/src/games/oblivion/src/oblivionsavegameinfo.cpp b/src/games/oblivion/src/oblivionsavegameinfo.cpp new file mode 100644 index 00000000..1b6dad0c --- /dev/null +++ b/src/games/oblivion/src/oblivionsavegameinfo.cpp @@ -0,0 +1,9 @@ +#include "oblivionsavegameinfo.h" + +#include "oblivionsavegame.h" + +MOBase::ISaveGame const *OblivionSaveGameInfo::getSaveGameInfo(const QString &file) const +{ + return new OblivionSaveGame(file); +} + diff --git a/src/games/oblivion/src/oblivionsavegameinfo.h b/src/games/oblivion/src/oblivionsavegameinfo.h new file mode 100644 index 00000000..38462c4a --- /dev/null +++ b/src/games/oblivion/src/oblivionsavegameinfo.h @@ -0,0 +1,12 @@ +#ifndef OBLIVIONSAVEGAMEINFO_H +#define OBLIVIONSAVEGAMEINFO_H + +#include "savegameinfo.h" + +class OblivionSaveGameInfo : public SaveGameInfo +{ +public: + virtual MOBase::ISaveGame const *getSaveGameInfo(QString const &file) const override; +}; + +#endif // OBLIVIONSAVEGAMEINFO_H diff --git a/src/games/oblivion/src/oblivionscriptextender.cpp b/src/games/oblivion/src/oblivionscriptextender.cpp index 159b87b3..7db7d466 100644 --- a/src/games/oblivion/src/oblivionscriptextender.cpp +++ b/src/games/oblivion/src/oblivionscriptextender.cpp @@ -8,6 +8,10 @@ OblivionScriptExtender::OblivionScriptExtender(GameGamebryo const *game) : { } +OblivionScriptExtender::~OblivionScriptExtender() +{ +} + QString OblivionScriptExtender::name() const { return "obse"; diff --git a/src/games/oblivion/src/oblivionscriptextender.h b/src/games/oblivion/src/oblivionscriptextender.h index a748431d..6efb45de 100644 --- a/src/games/oblivion/src/oblivionscriptextender.h +++ b/src/games/oblivion/src/oblivionscriptextender.h @@ -7,6 +7,7 @@ class OblivionScriptExtender : public GamebryoScriptExtender { public: OblivionScriptExtender(const GameGamebryo *game); + ~OblivionScriptExtender(); virtual QString name() const override; From 08e9014ef7d18bece3c89f0e1af3aecf0d860dd7 Mon Sep 17 00:00:00 2001 From: Thomas Tanner Date: Sat, 5 Dec 2015 06:50:46 +0000 Subject: [PATCH 0128/1544] [game_skyrim] Most of work for savegame --- src/games/skyrim/src/gameSkyrim.pro | 12 ++++-- src/games/skyrim/src/gameskyrim.cpp | 17 +++----- src/games/skyrim/src/gameskyrim.h | 18 +-------- src/games/skyrim/src/skyrimsavegame.cpp | 44 +++++++++++++++++++++ src/games/skyrim/src/skyrimsavegame.h | 12 ++++++ src/games/skyrim/src/skyrimsavegameinfo.cpp | 9 +++++ src/games/skyrim/src/skyrimsavegameinfo.h | 12 ++++++ 7 files changed, 93 insertions(+), 31 deletions(-) create mode 100644 src/games/skyrim/src/skyrimsavegame.cpp create mode 100644 src/games/skyrim/src/skyrimsavegame.h create mode 100644 src/games/skyrim/src/skyrimsavegameinfo.cpp create mode 100644 src/games/skyrim/src/skyrimsavegameinfo.h diff --git a/src/games/skyrim/src/gameSkyrim.pro b/src/games/skyrim/src/gameSkyrim.pro index ea977820..6fd27a4c 100644 --- a/src/games/skyrim/src/gameSkyrim.pro +++ b/src/games/skyrim/src/gameSkyrim.pro @@ -15,12 +15,16 @@ DEFINES += GAMESKYRIM_LIBRARY SOURCES += gameskyrim.cpp \ skyrimbsainvalidation.cpp \ skyrimscriptextender.cpp \ - skyrimdataarchives.cpp + skyrimdataarchives.cpp \ + skyrimsavegame.cpp \ + skyrimsavegameinfo.cpp HEADERS += gameskyrim.h \ skyrimbsainvalidation.h \ skyrimscriptextender.h \ - skyrimdataarchives.h + skyrimdataarchives.h \ + skyrimsavegame.h \ + skyrimsavegameinfo.h CONFIG(debug, debug|release) { LIBS += -L"$${OUT_PWD}/../gameGamebryo/debug" @@ -40,4 +44,6 @@ LIBS += -ladvapi32 -lole32 -lgameGamebryo OTHER_FILES += \ gameskyrim.json\ - SConscript + SConscript \ + CMakeLists.txt + diff --git a/src/games/skyrim/src/gameskyrim.cpp b/src/games/skyrim/src/gameskyrim.cpp index 6cb042d6..f1606d39 100644 --- a/src/games/skyrim/src/gameskyrim.cpp +++ b/src/games/skyrim/src/gameskyrim.cpp @@ -1,5 +1,10 @@ #include "gameskyrim.h" +#include "skyrimbsainvalidation.h" +#include "skyrimscriptextender.h" +#include "skyrimdataarchives.h" +#include "skyrimsavegameinfo.h" + #include #include #include @@ -30,6 +35,7 @@ bool GameSkyrim::init(IOrganizer *moInfo) m_ScriptExtender = std::shared_ptr(new SkyrimScriptExtender(this)); m_DataArchives = std::shared_ptr(new SkyrimDataArchives()); m_BSAInvalidation = std::shared_ptr(new SkyrimBSAInvalidation(m_DataArchives, this)); + m_SaveGameInfo = std::shared_ptr(new SkyrimSaveGameInfo()); return true; } @@ -153,17 +159,6 @@ QStringList GameSkyrim::getPrimaryPlugins() const return { "skyrim.esm", "update.esm" }; } -std::map GameSkyrim::featureList() const -{ - static std::map result { - { typeid(BSAInvalidation), m_BSAInvalidation.get() }, - { typeid(ScriptExtender), m_ScriptExtender.get() }, - { typeid(DataArchives), m_DataArchives.get() } - }; - - return result; -} - QString GameSkyrim::getBinaryName() const { return "TESV.exe"; diff --git a/src/games/skyrim/src/gameskyrim.h b/src/games/skyrim/src/gameskyrim.h index 13f59666..9d8fc066 100644 --- a/src/games/skyrim/src/gameskyrim.h +++ b/src/games/skyrim/src/gameskyrim.h @@ -1,13 +1,7 @@ #ifndef GAMESKYRIM_H #define GAMESKYRIM_H - -#include "skyrimbsainvalidation.h" -#include "skyrimscriptextender.h" -#include "skyrimdataarchives.h" -#include -#include - +#include "gamegamebryo.h" class GameSkyrim : public GameGamebryo { @@ -47,10 +41,6 @@ public: // IPlugin interface virtual bool isActive() const; virtual QList settings() const; -protected: - - virtual std::map featureList() const override; - private: virtual QString identifyGamePath() const override; @@ -60,12 +50,6 @@ private: void copyToProfile(const QString &sourcePath, const QDir &destinationDirectory, const QString &sourceFileName, const QString &destinationFileName = QString()) const; -private: - - std::shared_ptr m_ScriptExtender { nullptr }; - std::shared_ptr m_DataArchives { nullptr }; - std::shared_ptr m_BSAInvalidation { nullptr }; - }; #endif // GAMESKYRIM_H diff --git a/src/games/skyrim/src/skyrimsavegame.cpp b/src/games/skyrim/src/skyrimsavegame.cpp new file mode 100644 index 00000000..eb14da62 --- /dev/null +++ b/src/games/skyrim/src/skyrimsavegame.cpp @@ -0,0 +1,44 @@ +#include "skyrimsavegame.h" + +SkyrimSaveGame::SkyrimSaveGame(QString const &fileName) : + GamebryoSaveGame(fileName) +{ + FileWrapper file(this, "TESV_SAVEGAME"); + file.skip(); // header size + file.skip(); // header version, -> 8 + file.read(m_SaveNumber); + + file.read(m_PCName); + + unsigned long temp; + file.read(temp); + m_PCLevel = static_cast(temp); + + file.read(m_PCLocation); + + QString playTime; + file.read(playTime); + + QString race; + file.read(race); // race name (i.e. BretonRace) + + file.skip(); // ??? + file.skip(2); // ??? + //FIXME If this is a system time read it and use it as the creation time + file.skip(8); // filetime + + unsigned long width, height; + file.read(width); // 320 + file.read(height); // 192 + + QScopedArrayPointer buffer(new unsigned char[width * height * 3]); + file.read(buffer.data(), width * height * 3); + // why do I have to copy here? without the copy, the buffer seems to get deleted after the + // temporary vanishes, but Qts implicit sharing should handle that? + m_Screenshot = QImage(buffer.data(), width, height, QImage::Format_RGB888).copy(); + + file.skip(); // form version + file.skip(); // plugin info size + + file.readPlugins(); +} diff --git a/src/games/skyrim/src/skyrimsavegame.h b/src/games/skyrim/src/skyrimsavegame.h new file mode 100644 index 00000000..db93c3f6 --- /dev/null +++ b/src/games/skyrim/src/skyrimsavegame.h @@ -0,0 +1,12 @@ +#ifndef SKYRIMSAVEGAME_H +#define SKYRIMSAVEGAME_H + +#include "gamebryosavegame.h" + +class SkyrimSaveGame : public GamebryoSaveGame +{ +public: + SkyrimSaveGame(QString const &fileName); +}; + +#endif // SKYRIMSAVEGAME_H diff --git a/src/games/skyrim/src/skyrimsavegameinfo.cpp b/src/games/skyrim/src/skyrimsavegameinfo.cpp new file mode 100644 index 00000000..51265fd8 --- /dev/null +++ b/src/games/skyrim/src/skyrimsavegameinfo.cpp @@ -0,0 +1,9 @@ +#include "skyrimsavegameinfo.h" + +#include "skyrimsavegame.h" + +MOBase::ISaveGame const *SkyrimSaveGameInfo::getSaveGameInfo(const QString &file) const +{ + return new SkyrimSaveGame(file); +} + diff --git a/src/games/skyrim/src/skyrimsavegameinfo.h b/src/games/skyrim/src/skyrimsavegameinfo.h new file mode 100644 index 00000000..bb7054cf --- /dev/null +++ b/src/games/skyrim/src/skyrimsavegameinfo.h @@ -0,0 +1,12 @@ +#ifndef SKYRIMSAVEGAMEINFO_H +#define SKYRIMSAVEGAMEINFO_H + +#include "savegameinfo.h" + +class SkyrimSaveGameInfo : public SaveGameInfo +{ +public: + virtual MOBase::ISaveGame const *getSaveGameInfo(QString const &file) const override; +}; + +#endif // SKYRIMSAVEGAMEINFO_H From fbd57e48747c19bf291405586a0a166179864810 Mon Sep 17 00:00:00 2001 From: Thomas Tanner Date: Sat, 5 Dec 2015 06:50:56 +0000 Subject: [PATCH 0129/1544] [game_fallout4vr] Most of work for savegame --- src/games/fallout4vr/src/fallout4dataarchives.cpp | 3 +++ src/games/fallout4vr/src/fallout4dataarchives.h | 12 ++++++------ src/games/fallout4vr/src/fallout4scriptextender.h | 6 +++--- src/games/fallout4vr/src/gameFallout4.pro | 4 +++- src/games/fallout4vr/src/gamefallout4.cpp | 13 ++----------- src/games/fallout4vr/src/gamefallout4.h | 15 +-------------- 6 files changed, 18 insertions(+), 35 deletions(-) diff --git a/src/games/fallout4vr/src/fallout4dataarchives.cpp b/src/games/fallout4vr/src/fallout4dataarchives.cpp index e2ed39e2..e5908ac4 100644 --- a/src/games/fallout4vr/src/fallout4dataarchives.cpp +++ b/src/games/fallout4vr/src/fallout4dataarchives.cpp @@ -1,5 +1,8 @@ #include "fallout4dataarchives.h" + +#include "iprofile.h" #include + #include diff --git a/src/games/fallout4vr/src/fallout4dataarchives.h b/src/games/fallout4vr/src/fallout4dataarchives.h index 47c08c52..a23eb10f 100644 --- a/src/games/fallout4vr/src/fallout4dataarchives.h +++ b/src/games/fallout4vr/src/fallout4dataarchives.h @@ -1,10 +1,10 @@ -#ifndef FALLOUT3DATAARCHIVES_H -#define FALLOUT3DATAARCHIVES_H +#ifndef FALLOUT4DATAARCHIVES_H +#define FALLOUT4DATAARCHIVES_H +#include "gamebryodataarchives.h" + +namespace MOBase { class IProfile; } -#include -#include -#include #include class Fallout4DataArchives : public GamebryoDataArchives @@ -21,4 +21,4 @@ private: }; -#endif // FALLOUT3DATAARCHIVES_H +#endif // FALLOUT4DATAARCHIVES_H diff --git a/src/games/fallout4vr/src/fallout4scriptextender.h b/src/games/fallout4vr/src/fallout4scriptextender.h index add3697c..99a26cc1 100644 --- a/src/games/fallout4vr/src/fallout4scriptextender.h +++ b/src/games/fallout4vr/src/fallout4scriptextender.h @@ -1,5 +1,5 @@ -#ifndef FALLOUT3SCRIPTEXTENDER_H -#define FALLOUT3SCRIPTEXTENDER_H +#ifndef FALLOUT4SCRIPTEXTENDER_H +#define FALLOUT4SCRIPTEXTENDER_H #include "gamebryoscriptextender.h" @@ -14,4 +14,4 @@ public: }; -#endif // FALLOUT3SCRIPTEXTENDER_H +#endif // FALLOUT4SCRIPTEXTENDER_H diff --git a/src/games/fallout4vr/src/gameFallout4.pro b/src/games/fallout4vr/src/gameFallout4.pro index 2d5697e3..e34a6a67 100644 --- a/src/games/fallout4vr/src/gameFallout4.pro +++ b/src/games/fallout4vr/src/gameFallout4.pro @@ -41,4 +41,6 @@ LIBS += -ladvapi32 -lole32 -lgameGamebryo OTHER_FILES += \ gamefallout4.json\ - SConscript + SConscript \ + CMakeLists.txt + diff --git a/src/games/fallout4vr/src/gamefallout4.cpp b/src/games/fallout4vr/src/gamefallout4.cpp index d5c6829f..c01e01cc 100644 --- a/src/games/fallout4vr/src/gamefallout4.cpp +++ b/src/games/fallout4vr/src/gamefallout4.cpp @@ -1,5 +1,7 @@ #include "gameFallout4.h" +#include "fallout4dataarchives.h" +#include "fallout4scriptextender.h" #include #include #include "iplugingame.h" @@ -141,17 +143,6 @@ QStringList GameFallout4::getPrimaryPlugins() const return { "fallout4.esm" }; } -std::map GameFallout4::featureList() const -{ - static std::map result { - { typeid(ScriptExtender), m_ScriptExtender.get() }, - { typeid(DataArchives), m_DataArchives.get() } - }; - - return result; -} - - QStringList GameFallout4::gameVariants() const { return { "Regular" }; diff --git a/src/games/fallout4vr/src/gamefallout4.h b/src/games/fallout4vr/src/gamefallout4.h index 74e9f101..21b9c8be 100644 --- a/src/games/fallout4vr/src/gamefallout4.h +++ b/src/games/fallout4vr/src/gamefallout4.h @@ -2,11 +2,7 @@ #define GAMEFALLOUT4_H -#include "fallout4scriptextender.h" -#include "fallout4dataarchives.h" -#include -#include - +#include "gamegamebryo.h" class GameFallout4 : public GameGamebryo { @@ -47,10 +43,6 @@ public: // IPlugin interface virtual bool isActive() const override; virtual QList settings() const override; -protected: - - virtual std::map featureList() const override; - private: virtual QString identifyGamePath() const override; @@ -60,11 +52,6 @@ private: void copyToProfile(const QString &sourcePath, const QDir &destinationDirectory, const QString &sourceFileName, const QString &destinationFileName = QString()) const; -private: - - std::shared_ptr m_ScriptExtender { nullptr }; - std::shared_ptr m_DataArchives { nullptr }; - }; #endif // GAMEFallout4_H From 3c11afc5f4aa69433178868da3094f8d192676b6 Mon Sep 17 00:00:00 2001 From: Thomas Tanner Date: Sat, 5 Dec 2015 06:50:56 +0000 Subject: [PATCH 0130/1544] [game_fallout76] Most of work for savegame --- src/games/fallout76/src/fallout4dataarchives.cpp | 3 +++ src/games/fallout76/src/fallout4dataarchives.h | 12 ++++++------ src/games/fallout76/src/fallout4scriptextender.h | 6 +++--- src/games/fallout76/src/gameFallout4.pro | 4 +++- src/games/fallout76/src/gamefallout4.cpp | 13 ++----------- src/games/fallout76/src/gamefallout4.h | 15 +-------------- 6 files changed, 18 insertions(+), 35 deletions(-) diff --git a/src/games/fallout76/src/fallout4dataarchives.cpp b/src/games/fallout76/src/fallout4dataarchives.cpp index e2ed39e2..e5908ac4 100644 --- a/src/games/fallout76/src/fallout4dataarchives.cpp +++ b/src/games/fallout76/src/fallout4dataarchives.cpp @@ -1,5 +1,8 @@ #include "fallout4dataarchives.h" + +#include "iprofile.h" #include + #include diff --git a/src/games/fallout76/src/fallout4dataarchives.h b/src/games/fallout76/src/fallout4dataarchives.h index 47c08c52..a23eb10f 100644 --- a/src/games/fallout76/src/fallout4dataarchives.h +++ b/src/games/fallout76/src/fallout4dataarchives.h @@ -1,10 +1,10 @@ -#ifndef FALLOUT3DATAARCHIVES_H -#define FALLOUT3DATAARCHIVES_H +#ifndef FALLOUT4DATAARCHIVES_H +#define FALLOUT4DATAARCHIVES_H +#include "gamebryodataarchives.h" + +namespace MOBase { class IProfile; } -#include -#include -#include #include class Fallout4DataArchives : public GamebryoDataArchives @@ -21,4 +21,4 @@ private: }; -#endif // FALLOUT3DATAARCHIVES_H +#endif // FALLOUT4DATAARCHIVES_H diff --git a/src/games/fallout76/src/fallout4scriptextender.h b/src/games/fallout76/src/fallout4scriptextender.h index add3697c..99a26cc1 100644 --- a/src/games/fallout76/src/fallout4scriptextender.h +++ b/src/games/fallout76/src/fallout4scriptextender.h @@ -1,5 +1,5 @@ -#ifndef FALLOUT3SCRIPTEXTENDER_H -#define FALLOUT3SCRIPTEXTENDER_H +#ifndef FALLOUT4SCRIPTEXTENDER_H +#define FALLOUT4SCRIPTEXTENDER_H #include "gamebryoscriptextender.h" @@ -14,4 +14,4 @@ public: }; -#endif // FALLOUT3SCRIPTEXTENDER_H +#endif // FALLOUT4SCRIPTEXTENDER_H diff --git a/src/games/fallout76/src/gameFallout4.pro b/src/games/fallout76/src/gameFallout4.pro index 2d5697e3..e34a6a67 100644 --- a/src/games/fallout76/src/gameFallout4.pro +++ b/src/games/fallout76/src/gameFallout4.pro @@ -41,4 +41,6 @@ LIBS += -ladvapi32 -lole32 -lgameGamebryo OTHER_FILES += \ gamefallout4.json\ - SConscript + SConscript \ + CMakeLists.txt + diff --git a/src/games/fallout76/src/gamefallout4.cpp b/src/games/fallout76/src/gamefallout4.cpp index d5c6829f..c01e01cc 100644 --- a/src/games/fallout76/src/gamefallout4.cpp +++ b/src/games/fallout76/src/gamefallout4.cpp @@ -1,5 +1,7 @@ #include "gameFallout4.h" +#include "fallout4dataarchives.h" +#include "fallout4scriptextender.h" #include #include #include "iplugingame.h" @@ -141,17 +143,6 @@ QStringList GameFallout4::getPrimaryPlugins() const return { "fallout4.esm" }; } -std::map GameFallout4::featureList() const -{ - static std::map result { - { typeid(ScriptExtender), m_ScriptExtender.get() }, - { typeid(DataArchives), m_DataArchives.get() } - }; - - return result; -} - - QStringList GameFallout4::gameVariants() const { return { "Regular" }; diff --git a/src/games/fallout76/src/gamefallout4.h b/src/games/fallout76/src/gamefallout4.h index 74e9f101..21b9c8be 100644 --- a/src/games/fallout76/src/gamefallout4.h +++ b/src/games/fallout76/src/gamefallout4.h @@ -2,11 +2,7 @@ #define GAMEFALLOUT4_H -#include "fallout4scriptextender.h" -#include "fallout4dataarchives.h" -#include -#include - +#include "gamegamebryo.h" class GameFallout4 : public GameGamebryo { @@ -47,10 +43,6 @@ public: // IPlugin interface virtual bool isActive() const override; virtual QList settings() const override; -protected: - - virtual std::map featureList() const override; - private: virtual QString identifyGamePath() const override; @@ -60,11 +52,6 @@ private: void copyToProfile(const QString &sourcePath, const QDir &destinationDirectory, const QString &sourceFileName, const QString &destinationFileName = QString()) const; -private: - - std::shared_ptr m_ScriptExtender { nullptr }; - std::shared_ptr m_DataArchives { nullptr }; - }; #endif // GAMEFallout4_H From 689022050b9a5869e551509eaec5c68e3c4fd145 Mon Sep 17 00:00:00 2001 From: Thomas Tanner Date: Sat, 5 Dec 2015 06:50:56 +0000 Subject: [PATCH 0131/1544] [game_fallout4] Most of work for savegame --- src/games/fallout4/src/fallout4dataarchives.cpp | 3 +++ src/games/fallout4/src/fallout4dataarchives.h | 12 ++++++------ src/games/fallout4/src/fallout4scriptextender.h | 6 +++--- src/games/fallout4/src/gameFallout4.pro | 4 +++- src/games/fallout4/src/gamefallout4.cpp | 13 ++----------- src/games/fallout4/src/gamefallout4.h | 15 +-------------- 6 files changed, 18 insertions(+), 35 deletions(-) diff --git a/src/games/fallout4/src/fallout4dataarchives.cpp b/src/games/fallout4/src/fallout4dataarchives.cpp index e2ed39e2..e5908ac4 100644 --- a/src/games/fallout4/src/fallout4dataarchives.cpp +++ b/src/games/fallout4/src/fallout4dataarchives.cpp @@ -1,5 +1,8 @@ #include "fallout4dataarchives.h" + +#include "iprofile.h" #include + #include diff --git a/src/games/fallout4/src/fallout4dataarchives.h b/src/games/fallout4/src/fallout4dataarchives.h index 47c08c52..a23eb10f 100644 --- a/src/games/fallout4/src/fallout4dataarchives.h +++ b/src/games/fallout4/src/fallout4dataarchives.h @@ -1,10 +1,10 @@ -#ifndef FALLOUT3DATAARCHIVES_H -#define FALLOUT3DATAARCHIVES_H +#ifndef FALLOUT4DATAARCHIVES_H +#define FALLOUT4DATAARCHIVES_H +#include "gamebryodataarchives.h" + +namespace MOBase { class IProfile; } -#include -#include -#include #include class Fallout4DataArchives : public GamebryoDataArchives @@ -21,4 +21,4 @@ private: }; -#endif // FALLOUT3DATAARCHIVES_H +#endif // FALLOUT4DATAARCHIVES_H diff --git a/src/games/fallout4/src/fallout4scriptextender.h b/src/games/fallout4/src/fallout4scriptextender.h index add3697c..99a26cc1 100644 --- a/src/games/fallout4/src/fallout4scriptextender.h +++ b/src/games/fallout4/src/fallout4scriptextender.h @@ -1,5 +1,5 @@ -#ifndef FALLOUT3SCRIPTEXTENDER_H -#define FALLOUT3SCRIPTEXTENDER_H +#ifndef FALLOUT4SCRIPTEXTENDER_H +#define FALLOUT4SCRIPTEXTENDER_H #include "gamebryoscriptextender.h" @@ -14,4 +14,4 @@ public: }; -#endif // FALLOUT3SCRIPTEXTENDER_H +#endif // FALLOUT4SCRIPTEXTENDER_H diff --git a/src/games/fallout4/src/gameFallout4.pro b/src/games/fallout4/src/gameFallout4.pro index 2d5697e3..e34a6a67 100644 --- a/src/games/fallout4/src/gameFallout4.pro +++ b/src/games/fallout4/src/gameFallout4.pro @@ -41,4 +41,6 @@ LIBS += -ladvapi32 -lole32 -lgameGamebryo OTHER_FILES += \ gamefallout4.json\ - SConscript + SConscript \ + CMakeLists.txt + diff --git a/src/games/fallout4/src/gamefallout4.cpp b/src/games/fallout4/src/gamefallout4.cpp index d5c6829f..c01e01cc 100644 --- a/src/games/fallout4/src/gamefallout4.cpp +++ b/src/games/fallout4/src/gamefallout4.cpp @@ -1,5 +1,7 @@ #include "gameFallout4.h" +#include "fallout4dataarchives.h" +#include "fallout4scriptextender.h" #include #include #include "iplugingame.h" @@ -141,17 +143,6 @@ QStringList GameFallout4::getPrimaryPlugins() const return { "fallout4.esm" }; } -std::map GameFallout4::featureList() const -{ - static std::map result { - { typeid(ScriptExtender), m_ScriptExtender.get() }, - { typeid(DataArchives), m_DataArchives.get() } - }; - - return result; -} - - QStringList GameFallout4::gameVariants() const { return { "Regular" }; diff --git a/src/games/fallout4/src/gamefallout4.h b/src/games/fallout4/src/gamefallout4.h index 74e9f101..21b9c8be 100644 --- a/src/games/fallout4/src/gamefallout4.h +++ b/src/games/fallout4/src/gamefallout4.h @@ -2,11 +2,7 @@ #define GAMEFALLOUT4_H -#include "fallout4scriptextender.h" -#include "fallout4dataarchives.h" -#include -#include - +#include "gamegamebryo.h" class GameFallout4 : public GameGamebryo { @@ -47,10 +43,6 @@ public: // IPlugin interface virtual bool isActive() const override; virtual QList settings() const override; -protected: - - virtual std::map featureList() const override; - private: virtual QString identifyGamePath() const override; @@ -60,11 +52,6 @@ private: void copyToProfile(const QString &sourcePath, const QDir &destinationDirectory, const QString &sourceFileName, const QString &destinationFileName = QString()) const; -private: - - std::shared_ptr m_ScriptExtender { nullptr }; - std::shared_ptr m_DataArchives { nullptr }; - }; #endif // GAMEFallout4_H From 44f8c0aa8f5541f34c639c07531222e77f8dc267 Mon Sep 17 00:00:00 2001 From: Thomas Tanner Date: Sat, 5 Dec 2015 19:13:29 +0000 Subject: [PATCH 0132/1544] [game_fallout3] Gets rid of last vestiges of GameInfo apart from startup and hookdll Working on sorting out savegame stuff --- src/games/fallout3/src/fallout3savegame.cpp | 7 +------ 1 file changed, 1 insertion(+), 6 deletions(-) diff --git a/src/games/fallout3/src/fallout3savegame.cpp b/src/games/fallout3/src/fallout3savegame.cpp index 7fe24e57..d28c155a 100644 --- a/src/games/fallout3/src/fallout3savegame.cpp +++ b/src/games/fallout3/src/fallout3savegame.cpp @@ -45,12 +45,7 @@ Fallout3SaveGame::Fallout3SaveGame(QString const &fileName) : QString playtime; file.read(playtime); - //Abstract this - QScopedArrayPointer buffer(new unsigned char[width * height * 3]); - file.read(buffer.data(), width * height * 3); - // why do I have to copy here? without the copy, the buffer seems to get deleted after the - // temporary vanishes, but Qts implicit sharing should handle that? - m_Screenshot = QImage(buffer.data(), width, height, QImage::Format_RGB888).scaledToWidth(256); + file.readImage(width, height, 256); file.skip(5); // unknown From fb2efd3102f3eb0fb299a5dca96efe51c89b18b6 Mon Sep 17 00:00:00 2001 From: Thomas Tanner Date: Sat, 5 Dec 2015 19:13:46 +0000 Subject: [PATCH 0133/1544] [game_falloutnv] Gets rid of last vestiges of GameInfo apart from startup and hookdll Working on sorting out savegame stuff --- src/games/falloutnv/src/falloutnvsavegame.cpp | 7 +------ 1 file changed, 1 insertion(+), 6 deletions(-) diff --git a/src/games/falloutnv/src/falloutnvsavegame.cpp b/src/games/falloutnv/src/falloutnvsavegame.cpp index 9a27c275..f5ca121c 100644 --- a/src/games/falloutnv/src/falloutnvsavegame.cpp +++ b/src/games/falloutnv/src/falloutnvsavegame.cpp @@ -42,12 +42,7 @@ FalloutNVSaveGame::FalloutNVSaveGame(QString const &fileName) : QString playtime; file.read(playtime); - //Abstract this - QScopedArrayPointer buffer(new unsigned char[width * height * 3]); - file.read(buffer.data(), width * height * 3); - // why do I have to copy here? without the copy, the buffer seems to get deleted after the - // temporary vanishes, but Qts implicit sharing should handle that? - m_Screenshot = QImage(buffer.data(), width, height, QImage::Format_RGB888).scaledToWidth(256); + file.readImage(width, height, 256); file.skip(5); // unknown From 60d12d1a309c3a4c945fa576cfef6572d47b9578 Mon Sep 17 00:00:00 2001 From: Thomas Tanner Date: Sat, 5 Dec 2015 19:14:39 +0000 Subject: [PATCH 0134/1544] Gets rid of last vestiges of GameInfo apart from startup and hookdll Working on sorting out savegame stuff --- src/SConscript | 2 -- src/gamebryosavegame.cpp | 51 +++++++++++++++++++++++++++++----------- src/gamebryosavegame.h | 35 ++++++++++++++------------- 3 files changed, 54 insertions(+), 34 deletions(-) diff --git a/src/SConscript b/src/SConscript index 94801639..3b96d894 100644 --- a/src/SConscript +++ b/src/SConscript @@ -1,7 +1,5 @@ import os -print 'calling gamebro sconscript' - Import('qt_env') env = qt_env.Clone() diff --git a/src/gamebryosavegame.cpp b/src/gamebryosavegame.cpp index e8c515de..05b3a4de 100644 --- a/src/gamebryosavegame.cpp +++ b/src/gamebryosavegame.cpp @@ -3,6 +3,8 @@ #include #include +#include "Windows.h" + #include #include @@ -26,29 +28,27 @@ QDateTime GamebryoSaveGame::getCreationTime() const return m_CreationTime; } -void GamebryoSaveGame::readHeader(QFile &file, const QString &expected) +QString GamebryoSaveGame::getIdentifier() const { - file.setFileName(m_FileName); - if (!file.open(QIODevice::ReadOnly)) { - throw std::runtime_error(QObject::tr("failed to open %1").arg(m_FileName).toUtf8().constData()); - } + return m_PCName; +} - std::vector fileID(expected.length() + 1); - file.read(fileID.data(), expected.length()); - fileID[expected.length()] = '\0'; +void GamebryoSaveGame::setCreationTime(_SYSTEMTIME const &ctime) +{ + QDate date; + date.setDate(ctime.wYear, ctime.wMonth, ctime.wDay); + QTime time; + time.setHMS(ctime.wHour, ctime.wMinute, ctime.wSecond, ctime.wMilliseconds); - QString id(fileID.data()); - if (expected != id) { - throw std::runtime_error( - QObject::tr("wrong file format - expected %1 got %2").arg(expected).arg(id).toUtf8().constData()); - } + m_CreationTime = QDateTime(date, time, Qt::UTC); } GamebryoSaveGame::FileWrapper::FileWrapper(GamebryoSaveGame *game, QString const &expected) : m_Game(game), m_File(game->m_FileName), - m_HasFieldMarkers(false) + m_HasFieldMarkers(false), + m_Length(2) { if (!m_File.open(QIODevice::ReadOnly)) { throw std::runtime_error(QObject::tr("failed to open %1").arg(game->m_FileName).toUtf8().constData()); @@ -103,6 +103,29 @@ void GamebryoSaveGame::FileWrapper::read(void *buff, std::size_t length) } } +void GamebryoSaveGame::FileWrapper::readImage(int scale) +{ + unsigned long width; + read(width); + unsigned long height; + read(height); + readImage(width, height, scale); +} + +void GamebryoSaveGame::FileWrapper::readImage(unsigned long width, unsigned long height, int scale) +{ + QScopedArrayPointer buffer(new unsigned char[width * height * 3]); + read(buffer.data(), width * height * 3); + QImage image(buffer.data(), width, height, QImage::Format_RGB888); + if (scale) { + m_Game->m_Screenshot = image.scaledToWidth(scale); + } else { + // why do I have to copy here? without the copy, the buffer seems to get deleted after the + // temporary vanishes, but Qts implicit sharing should handle that? + m_Game->m_Screenshot = image.copy(); + } +} + void GamebryoSaveGame::FileWrapper::readPlugins() { unsigned char count; diff --git a/src/gamebryosavegame.h b/src/gamebryosavegame.h index 7068da53..c1a64e5e 100644 --- a/src/gamebryosavegame.h +++ b/src/gamebryosavegame.h @@ -8,9 +8,10 @@ #include #include -//class QFile; #include +struct _SYSTEMTIME; + class GamebryoSaveGame : public MOBase::ISaveGame { public: @@ -22,6 +23,8 @@ public: virtual QDateTime getCreationTime() const override; + virtual QString getIdentifier() const override; + //Simple getters QString getPCName() const { return m_PCName; } unsigned short getPCLevel() const { return m_PCLevel; } @@ -74,8 +77,20 @@ protected: void read(void *buff, std::size_t length); + /* Reads RGB image from save + * Assumes picture dimentions come immediately before the save + */ + void readImage(int scale = 0); + + /* Reads RGB image from save */ + void readImage(unsigned long width, unsigned long height, int scale = 0); + + /* Read the plugin list */ void readPlugins(); + /* Set the creation time from a system date */ + void setCreationTime(::_SYSTEMTIME const &); + private: GamebryoSaveGame *m_Game; QFile m_File; @@ -83,23 +98,7 @@ protected: std::size_t m_Length; }; - - template void FileRead(QFile &file, T &value) - { - int read = file.read(reinterpret_cast(&value), sizeof(T)); - if (read != sizeof(T)) { - throw std::runtime_error("unexpected end of file"); - } - } - - template void FileSkip(QFile &file, int count = 1) - { - if (!file.seek(file.pos() + count * sizeof(T))) { - throw std::runtime_error("unexpected end of file"); - } - } - - void readHeader(QFile &file, QString const &expected); + void setCreationTime(_SYSTEMTIME const &time); QString m_FileName; QString m_PCName; From 2f42a7ccdee8f2820bc113b2d1c81f05cc9f1787 Mon Sep 17 00:00:00 2001 From: Thomas Tanner Date: Sat, 5 Dec 2015 19:14:54 +0000 Subject: [PATCH 0135/1544] [game_oblivion] Gets rid of last vestiges of GameInfo apart from startup and hookdll Working on sorting out savegame stuff --- src/games/oblivion/src/oblivionsavegame.cpp | 15 ++++----------- 1 file changed, 4 insertions(+), 11 deletions(-) diff --git a/src/games/oblivion/src/oblivionsavegame.cpp b/src/games/oblivion/src/oblivionsavegame.cpp index 4bb4e7d1..4ff3f793 100644 --- a/src/games/oblivion/src/oblivionsavegame.cpp +++ b/src/games/oblivion/src/oblivionsavegame.cpp @@ -28,23 +28,16 @@ OblivionSaveGame::OblivionSaveGame(const QString &game) : file.skip(); //game days file.skip(); //game ticks + //there is a save time stored here. So use it rather than the file time, which + //could have been copied. SYSTEMTIME ctime; file.read(ctime); - //FIXME update creation time with this + setCreationTime(ctime); unsigned long size; file.read(size); - unsigned long width; - file.read(width); - unsigned long height; - file.read(height); - - QScopedArrayPointer buffer(new unsigned char[width * height * 3]); - file.read(buffer.data(), width * height * 3); - // why do I have to copy here? without the copy, the buffer seems to get deleted after the - // temporary vanishes, but Qts implicit sharing should handle that? - m_Screenshot = QImage(buffer.data(), width, height, QImage::Format_RGB888).copy(); + file.readImage(); file.readPlugins(); } From 3dadf8a84a750c13d706d976b86112178ff8ed87 Mon Sep 17 00:00:00 2001 From: Thomas Tanner Date: Sat, 5 Dec 2015 19:15:17 +0000 Subject: [PATCH 0136/1544] [game_skyrim] Gets rid of last vestiges of GameInfo apart from startup and hookdll Working on sorting out savegame stuff --- src/games/skyrim/src/skyrimsavegame.cpp | 32 +++++++++++++------------ 1 file changed, 17 insertions(+), 15 deletions(-) diff --git a/src/games/skyrim/src/skyrimsavegame.cpp b/src/games/skyrim/src/skyrimsavegame.cpp index eb14da62..b121b0bd 100644 --- a/src/games/skyrim/src/skyrimsavegame.cpp +++ b/src/games/skyrim/src/skyrimsavegame.cpp @@ -1,11 +1,13 @@ #include "skyrimsavegame.h" +#include + SkyrimSaveGame::SkyrimSaveGame(QString const &fileName) : GamebryoSaveGame(fileName) { FileWrapper file(this, "TESV_SAVEGAME"); file.skip(); // header size - file.skip(); // header version, -> 8 + file.skip(); // header version file.read(m_SaveNumber); file.read(m_PCName); @@ -16,26 +18,26 @@ SkyrimSaveGame::SkyrimSaveGame(QString const &fileName) : file.read(m_PCLocation); - QString playTime; - file.read(playTime); + QString timeOfDay; + file.read(timeOfDay); QString race; file.read(race); // race name (i.e. BretonRace) - file.skip(); // ??? - file.skip(2); // ??? - //FIXME If this is a system time read it and use it as the creation time - file.skip(8); // filetime + file.skip(); // Player gender (0 = male) + file.skip(2); // experience gathered, experience required - unsigned long width, height; - file.read(width); // 320 - file.read(height); // 192 + FILETIME ftime; + file.read(ftime); + //A file time is a 64-bit value that represents the number of 100-nanosecond + //intervals that have elapsed since 12:00 A.M. January 1, 1601 Coordinated Universal Time (UTC). + //So we need to convert that to something useful + SYSTEMTIME ctime; + ::FileTimeToSystemTime(&ftime, &ctime); - QScopedArrayPointer buffer(new unsigned char[width * height * 3]); - file.read(buffer.data(), width * height * 3); - // why do I have to copy here? without the copy, the buffer seems to get deleted after the - // temporary vanishes, but Qts implicit sharing should handle that? - m_Screenshot = QImage(buffer.data(), width, height, QImage::Format_RGB888).copy(); + setCreationTime(ctime); + + file.readImage(); file.skip(); // form version file.skip(); // plugin info size From fbab75e179a32a7c060f7697d69d163600ec9423 Mon Sep 17 00:00:00 2001 From: Thomas Tanner Date: Sat, 5 Dec 2015 22:39:38 +0000 Subject: [PATCH 0137/1544] [game_oblivion] Fix up null terminator in oblivion save game strings --- src/games/oblivion/src/oblivionsavegame.cpp | 24 ++++++++++----------- 1 file changed, 12 insertions(+), 12 deletions(-) diff --git a/src/games/oblivion/src/oblivionsavegame.cpp b/src/games/oblivion/src/oblivionsavegame.cpp index 4ff3f793..d60535e6 100644 --- a/src/games/oblivion/src/oblivionsavegame.cpp +++ b/src/games/oblivion/src/oblivionsavegame.cpp @@ -6,18 +6,15 @@ OblivionSaveGame::OblivionSaveGame(const QString &game) : GamebryoSaveGame(game) { FileWrapper file(this, "TES4SAVEGAME"); - file.setStringLength(1); + file.setBZString(true); - file.skip(); + file.skip(); //Major version + file.skip(); //Minor version - //Hmm. We could probably just skip all of these - unsigned char version_minor; - file.read(version_minor); - file.skip(); - unsigned long headerVersion; - file.read(headerVersion); - unsigned long saveHeaderSize; - file.read(saveHeaderSize); + file.skip(); // exe last modified (!) + + file.skip(); //Header version + file.skip(); //Header size file.read(m_SaveNumber); @@ -30,12 +27,15 @@ OblivionSaveGame::OblivionSaveGame(const QString &game) : //there is a save time stored here. So use it rather than the file time, which //could have been copied. + //Note: This says it uses getlocaltime api to obtain it which is u/s - if so + //we should ignore this. SYSTEMTIME ctime; file.read(ctime); setCreationTime(ctime); - unsigned long size; - file.read(size); + //Note that screenshot size, width, height and data are apparently the same + //structure + file.skip(); //Screenshot size. file.readImage(); From cfdd909e7f98d75fbe42aa0eb4171541d83a0988 Mon Sep 17 00:00:00 2001 From: Thomas Tanner Date: Sat, 5 Dec 2015 22:39:50 +0000 Subject: [PATCH 0138/1544] Fix up null terminator in oblivion save game strings --- src/gamebryosavegame.cpp | 13 +++++++++---- src/gamebryosavegame.h | 7 +++---- 2 files changed, 12 insertions(+), 8 deletions(-) diff --git a/src/gamebryosavegame.cpp b/src/gamebryosavegame.cpp index 05b3a4de..e77b8038 100644 --- a/src/gamebryosavegame.cpp +++ b/src/gamebryosavegame.cpp @@ -48,7 +48,7 @@ GamebryoSaveGame::FileWrapper::FileWrapper(GamebryoSaveGame *game, m_Game(game), m_File(game->m_FileName), m_HasFieldMarkers(false), - m_Length(2) + m_BZString(false) { if (!m_File.open(QIODevice::ReadOnly)) { throw std::runtime_error(QObject::tr("failed to open %1").arg(game->m_FileName).toUtf8().constData()); @@ -70,15 +70,15 @@ void GamebryoSaveGame::FileWrapper::setHasFieldMarkers(bool state) m_HasFieldMarkers = state; } -void GamebryoSaveGame::FileWrapper::setStringLength(size_t len) +void GamebryoSaveGame::FileWrapper::setBZString(bool state) { - m_Length = len; + m_BZString = state; } template <> __declspec(dllexport) void GamebryoSaveGame::FileWrapper::read(QString &value) { unsigned short length; - if (m_Length == 1) { + if (m_BZString) { unsigned char len; read(len); length = len; @@ -88,6 +88,11 @@ template <> __declspec(dllexport) void GamebryoSaveGame::FileWrapper::read(QStri std::vector buffer(length); read(buffer.data(), length); + + if (m_BZString) { + length -= 1; + } + if (m_HasFieldMarkers) { skip(); } diff --git a/src/gamebryosavegame.h b/src/gamebryosavegame.h index c1a64e5e..f46dd375 100644 --- a/src/gamebryosavegame.h +++ b/src/gamebryosavegame.h @@ -50,10 +50,9 @@ protected: **/ void setHasFieldMarkers(bool); - /** The length of the string length. - * Normally a string has a 2 byte length. Oblivion has a single byte. + /** Set bz string mode (1 byte length, null terminated) **/ - void setStringLength(std::size_t len); + void setBZString(bool); template void skip(int count = 1) { @@ -95,7 +94,7 @@ protected: GamebryoSaveGame *m_Game; QFile m_File; bool m_HasFieldMarkers; - std::size_t m_Length; + bool m_BZString; }; void setCreationTime(_SYSTEMTIME const &time); From 23c7d3c9861dcba874658bd2d13a59406be6005e Mon Sep 17 00:00:00 2001 From: Thomas Tanner Date: Sun, 6 Dec 2015 11:40:18 +0000 Subject: [PATCH 0139/1544] [game_fallout3] Clean up fallout save game processing a bit --- src/games/fallout3/src/fallout3savegame.cpp | 21 +++++---------------- 1 file changed, 5 insertions(+), 16 deletions(-) diff --git a/src/games/fallout3/src/fallout3savegame.cpp b/src/games/fallout3/src/fallout3savegame.cpp index d28c155a..d9fc9a4c 100644 --- a/src/games/fallout3/src/fallout3savegame.cpp +++ b/src/games/fallout3/src/fallout3savegame.cpp @@ -5,24 +5,13 @@ Fallout3SaveGame::Fallout3SaveGame(QString const &fileName) : { FileWrapper file(this, "FO3SAVEGAME"); - file.skip(); - - char ignore = 0x00; - while (ignore != 0x7c) { - file.read(ignore); // unknown - } - bool newVegas = false; - if (newVegas) { - ignore = 0x00; - // in new vegas there is another block of uninteresting (?) information - file.skip(); // 0x7c - while (ignore != 0x7c) { - file.read(ignore); // unknown - } - } + file.skip(); //Save header size file.setHasFieldMarkers(true); + file.skip(); //File version ? + file.skip(); //delimiter + unsigned long width; file.read(width); @@ -47,7 +36,7 @@ Fallout3SaveGame::Fallout3SaveGame(QString const &fileName) : file.readImage(width, height, 256); - file.skip(5); // unknown + file.skip(5); // unknown (1 byte), plugin size (4 bytes) //Abstract this file.readPlugins(); From 88aa5f5ae4601beee0b22bc16cb042c0ea2b4118 Mon Sep 17 00:00:00 2001 From: Thomas Tanner Date: Sun, 6 Dec 2015 11:40:31 +0000 Subject: [PATCH 0140/1544] [game_falloutnv] Clean up fallout save game processing a bit --- src/games/falloutnv/src/falloutnvsavegame.cpp | 19 +++++++++---------- 1 file changed, 9 insertions(+), 10 deletions(-) diff --git a/src/games/falloutnv/src/falloutnvsavegame.cpp b/src/games/falloutnv/src/falloutnvsavegame.cpp index f5ca121c..b8cae635 100644 --- a/src/games/falloutnv/src/falloutnvsavegame.cpp +++ b/src/games/falloutnv/src/falloutnvsavegame.cpp @@ -5,16 +5,15 @@ FalloutNVSaveGame::FalloutNVSaveGame(QString const &fileName) : { FileWrapper file(this, "FO3SAVEGAME"); - file.skip(); + file.skip(); //Save header size - char ignore = 0x00; - while (ignore != 0x7c) { - file.read(ignore); // unknown - } - ignore = 0x00; - // in new vegas there is another block of uninteresting (?) information - file.skip(); // 0x7c - while (ignore != 0x7c) { + file.skip(); //File version? + file.skip(); //Delimiter + + //A huge wodge of text with no length but a delimiter. Given the null bytes + //in it I presume it's a fixed length (64 bytes + delim) but I have no + //definite spec + for (unsigned char ignore = 0; ignore != 0x7c; ) { file.read(ignore); // unknown } @@ -44,7 +43,7 @@ FalloutNVSaveGame::FalloutNVSaveGame(QString const &fileName) : file.readImage(width, height, 256); - file.skip(5); // unknown + file.skip(5); // unknown byte, size of plugin data //Abstract this file.readPlugins(); From b7911e3ffe674eb38aa4a7c75594c7f6ede74bc4 Mon Sep 17 00:00:00 2001 From: Thomas Tanner Date: Sun, 6 Dec 2015 11:40:44 +0000 Subject: [PATCH 0141/1544] Clean up fallout save game processing a bit --- src/gamebryosavegame.cpp | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) diff --git a/src/gamebryosavegame.cpp b/src/gamebryosavegame.cpp index e77b8038..2c9640de 100644 --- a/src/gamebryosavegame.cpp +++ b/src/gamebryosavegame.cpp @@ -123,10 +123,13 @@ void GamebryoSaveGame::FileWrapper::readImage(unsigned long width, unsigned long read(buffer.data(), width * height * 3); QImage image(buffer.data(), width, height, QImage::Format_RGB888); if (scale) { + // NB Note that scaling rather messes up oblivion so we can't use this as + // the default m_Game->m_Screenshot = image.scaledToWidth(scale); } else { - // why do I have to copy here? without the copy, the buffer seems to get deleted after the - // temporary vanishes, but Qts implicit sharing should handle that? + // why do I have to copy here? without the copy, the buffer seems to get + // deleted after the temporary vanishes, but shouldn't Qts implicit sharing + // handle that? m_Game->m_Screenshot = image.copy(); } } From fe1c23e09e992ced6eb45c6a145fbfd0652abbec Mon Sep 17 00:00:00 2001 From: Thomas Tanner Date: Sun, 6 Dec 2015 17:29:54 +0000 Subject: [PATCH 0142/1544] Update fixes for issue/344 to go via iPluginGame interface --- src/gamebryoscriptextender.cpp | 5 +++ src/gamebryoscriptextender.h | 2 ++ src/gamegamebryo.cpp | 63 ++++++++++++++++++++++++++++++++++ src/gamegamebryo.h | 3 ++ 4 files changed, 73 insertions(+) diff --git a/src/gamebryoscriptextender.cpp b/src/gamebryoscriptextender.cpp index 8db9d996..b73bb543 100644 --- a/src/gamebryoscriptextender.cpp +++ b/src/gamebryoscriptextender.cpp @@ -30,3 +30,8 @@ bool GamebryoScriptExtender::isInstalled() const } +QString GamebryoScriptExtender::getExtenderVersion() const +{ + return m_Game->getVersion(loaderName()); +} + diff --git a/src/gamebryoscriptextender.h b/src/gamebryoscriptextender.h index 1e235b99..6f08f0e4 100644 --- a/src/gamebryoscriptextender.h +++ b/src/gamebryoscriptextender.h @@ -22,6 +22,8 @@ public: virtual bool isInstalled() const override; + virtual QString getExtenderVersion() const override; + protected: GameGamebryo const * const m_Game; }; diff --git a/src/gamegamebryo.cpp b/src/gamegamebryo.cpp index d471b75e..0976d07b 100644 --- a/src/gamegamebryo.cpp +++ b/src/gamegamebryo.cpp @@ -80,11 +80,46 @@ bool GameGamebryo::looksValid(QDir const &path) const return path.exists(getBinaryName()) && path.exists(getLauncherName()); } +QString GameGamebryo::getGameVersion() const +{ + return getVersion(getBinaryName()); +} + QString GameGamebryo::getLauncherName() const { return getGameShortName() + "Launcher.exe"; } +QString GameGamebryo::getVersion(const QString &program) const +{ + //This *really* needs to be factored out + std::wstring app_name = L"\\\\?\\" + + QDir::toNativeSeparators(this->gameDirectory().absoluteFilePath(program)).toStdWString(); + DWORD handle; + DWORD info_len = ::GetFileVersionInfoSizeW(app_name.c_str(), &handle); + if (info_len == 0) { + qDebug("GetFileVersionInfoSizeW Error %d", ::GetLastError()); + return ""; + } + + std::vector buff(info_len); + if( ! ::GetFileVersionInfoW(app_name.c_str(), handle, info_len, buff.data())) { + qDebug("GetFileVersionInfoW Error %d", ::GetLastError()); + return ""; + } + + VS_FIXEDFILEINFO *pFileInfo; + UINT buf_len; + if ( ! ::VerQueryValueW(buff.data(), L"\\", reinterpret_cast(&pFileInfo), &buf_len)) { + qDebug("VerQueryValueW Error %d", ::GetLastError()); + return ""; + } + return QString("%1.%2.%3.%4").arg(HIWORD(pFileInfo->dwFileVersionMS)) + .arg(LOWORD(pFileInfo->dwFileVersionMS)) + .arg(HIWORD(pFileInfo->dwFileVersionLS)) + .arg(LOWORD(pFileInfo->dwFileVersionLS)); +} + std::unique_ptr GameGamebryo::getRegValue(HKEY key, LPCWSTR path, LPCWSTR value, DWORD flags, LPDWORD type) const @@ -203,3 +238,31 @@ std::map GameGamebryo::featureList() const return result; } +/* +QString GetAppVersion(std::wstring const &app_name) +{ + DWORD handle; + DWORD info_len = ::GetFileVersionInfoSizeW(app_name.c_str(), &handle); + if (info_len == 0) { + qDebug("GetFileVersionInfoSizeW Error %d", ::GetLastError()); + return ""; + } + + std::vector buff(info_len); + if( ! ::GetFileVersionInfoW(app_name.c_str(), handle, info_len, buff.data())) { + qDebug("GetFileVersionInfoW Error %d", ::GetLastError()); + return ""; + } + + VS_FIXEDFILEINFO *pFileInfo; + UINT buf_len; + if ( ! ::VerQueryValueW(buff.data(), L"\\", reinterpret_cast(&pFileInfo), &buf_len)) { + qDebug("VerQueryValueW Error %d", ::GetLastError()); + return ""; + } + return QString("%1.%2.%3.%4").arg(HIWORD(pFileInfo->dwFileVersionMS)) + .arg(LOWORD(pFileInfo->dwFileVersionMS)) + .arg(HIWORD(pFileInfo->dwFileVersionLS)) + .arg(LOWORD(pFileInfo->dwFileVersionLS)); +} +*/ diff --git a/src/gamegamebryo.h b/src/gamegamebryo.h index 4b1f6c8f..f533d7cd 100644 --- a/src/gamegamebryo.h +++ b/src/gamegamebryo.h @@ -50,6 +50,7 @@ public: // IPluginGame interface //getNexusModOrganizerID //getNexusGameID virtual bool looksValid(QDir const &) const override; + virtual QString getGameVersion() const override; protected: @@ -63,6 +64,8 @@ protected: QString getLootPath() const; QString selectedVariant() const; virtual QString getLauncherName() const; + friend class GamebryoScriptExtender; + QString getVersion(QString const &program) const; protected: From b66f5933b7f91a477c335be62d7e68fea832d583 Mon Sep 17 00:00:00 2001 From: Tannin Date: Sun, 6 Dec 2015 20:21:55 +0100 Subject: [PATCH 0143/1544] [game_fallout4vr] cleanup --- src/games/fallout4vr/CMakeLists.txt.user | 206 ---------------------- src/games/fallout4vr/src/CMakeLists.txt | 2 +- src/games/fallout4vr/src/gamefallout4.cpp | 19 +- src/games/fallout4vr/src/gamefallout4.h | 7 +- 4 files changed, 8 insertions(+), 226 deletions(-) delete mode 100644 src/games/fallout4vr/CMakeLists.txt.user diff --git a/src/games/fallout4vr/CMakeLists.txt.user b/src/games/fallout4vr/CMakeLists.txt.user deleted file mode 100644 index 5d263ca5..00000000 --- a/src/games/fallout4vr/CMakeLists.txt.user +++ /dev/null @@ -1,206 +0,0 @@ - - - - - - EnvironmentId - {be93058c-4cdc-4db3-a586-0930ff4430c6} - - - ProjectExplorer.Project.ActiveTarget - 0 - - - ProjectExplorer.Project.EditorSettings - - true - false - true - - Cpp - - CppGlobal - - - - QmlJS - - QmlJSGlobal - - - 2 - UTF-8 - false - 4 - false - 80 - true - true - 1 - true - false - 0 - true - 0 - 8 - true - 1 - true - true - true - false - - - - ProjectExplorer.Project.PluginSettings - - - - 1 - - - - - ProjectExplorer.Project.Target.0 - - Desktop - Desktop - {3d7af99e-d2b7-4536-ac05-c1dba2e378bf} - 0 - 0 - 0 - - false - d:\mo_build\build\modorganizer_super\game_fallout4\edit - - - - - false - - true - Make - - CMakeProjectManager.MakeStep - - - - - install - - false - - true - Make - - CMakeProjectManager.MakeStep - - 2 - Build - - ProjectExplorer.BuildSteps.Build - - - - clean - - true - - true - Make - - CMakeProjectManager.MakeStep - - 1 - Clean - - ProjectExplorer.BuildSteps.Clean - - 2 - false - - all - - CMakeProjectManager.CMakeBuildConfiguration - - 1 - - - 0 - Deploy - - ProjectExplorer.BuildSteps.Deploy - - 1 - Deploy locally - - ProjectExplorer.DefaultDeployConfiguration - - 1 - - - - false - false - false - false - true - 0.01 - 10 - true - 1 - 25 - - 1 - true - false - true - valgrind - - 0 - 1 - 2 - 3 - 4 - 5 - 6 - 7 - 8 - 9 - 10 - 11 - 12 - 13 - 14 - - 2 - - - - %{buildDir} - Custom Executable - - ProjectExplorer.CustomExecutableRunConfiguration - 3768 - false - true - false - false - true - - 1 - - - - ProjectExplorer.Project.TargetCount - 1 - - - ProjectExplorer.Project.Updater.FileVersion - 18 - - - Version - 18 - - diff --git a/src/games/fallout4vr/src/CMakeLists.txt b/src/games/fallout4vr/src/CMakeLists.txt index 15136936..08e9431d 100644 --- a/src/games/fallout4vr/src/CMakeLists.txt +++ b/src/games/fallout4vr/src/CMakeLists.txt @@ -40,7 +40,7 @@ TARGET_LINK_LIBRARIES(${PROJ_NAME} Qt5::Widgets ${Boost_LIBRARIES} uibase - game_gamebryo) + gameGamebryo) SET_TARGET_PROPERTIES(${PROJ_NAME} PROPERTIES COMPILE_FLAGS /GL) SET_TARGET_PROPERTIES(${PROJ_NAME} PROPERTIES LINK_FLAGS_RELWITHDEBINFO "/LTCG /LARGEADDRESSAWARE /OPT:REF /OPT:ICF") diff --git a/src/games/fallout4vr/src/gamefallout4.cpp b/src/games/fallout4vr/src/gamefallout4.cpp index 18350703..f31af09c 100644 --- a/src/games/fallout4vr/src/gamefallout4.cpp +++ b/src/games/fallout4vr/src/gamefallout4.cpp @@ -3,9 +3,11 @@ #include #include #include +#include #include #include #include +#include #include @@ -22,7 +24,7 @@ bool GameFallout4::init(IOrganizer *moInfo) return false; } m_ScriptExtender = std::shared_ptr(new Fallout4ScriptExtender()); - m_DataArchives = std::shared_ptr(new Fallout4DataArchives()); + m_LocalSavegames.reset(new GamebryoLocalSavegames(myGamesPath(), "Fallout4.ini")); return true; } @@ -36,17 +38,6 @@ QString GameFallout4::gameName() const return "Fallout 4"; } -QString GameFallout4::localAppFolder() const -{ - QString result = getKnownFolderPath(FOLDERID_LocalAppData, false); - if (result.isEmpty()) { - // fallback: try the registry - result = getSpecialPath("Local AppData"); - } - - return result; -} - QString GameFallout4::myGamesFolderName() const { return "Fallout4"; @@ -84,7 +75,7 @@ MOBase::VersionInfo GameFallout4::version() const bool GameFallout4::isActive() const { - return true; + return qApp->property("managed_game").value() == this; } QList GameFallout4::settings() const @@ -148,7 +139,7 @@ const std::map &GameFallout4::featureList() const { static std::map result { { typeid(ScriptExtender), m_ScriptExtender.get() }, - { typeid(DataArchives), m_DataArchives.get() } + { typeid(LocalSavegames), m_LocalSavegames.get() } }; return result; diff --git a/src/games/fallout4vr/src/gamefallout4.h b/src/games/fallout4vr/src/gamefallout4.h index 371a64a4..ea61496b 100644 --- a/src/games/fallout4vr/src/gamefallout4.h +++ b/src/games/fallout4vr/src/gamefallout4.h @@ -3,7 +3,7 @@ #include "fallout4scriptextender.h" -#include "fallout4dataarchives.h" +#include "gamebryolocalsavegames.h" #include #include @@ -11,9 +11,7 @@ class GameFallout4 : public GameGamebryo { Q_OBJECT -#if QT_VERSION >= QT_VERSION_CHECK(5,0,0) Q_PLUGIN_METADATA(IID "org.tannin.GameFallout4" FILE "gamefallout4.json") -#endif public: @@ -50,14 +48,13 @@ private: virtual QString identifyGamePath() const override; virtual QString myGamesFolderName() const override; - QString localAppFolder() const; void copyToProfile(const QString &sourcePath, const QDir &destinationDirectory, const QString &sourceFileName, const QString &destinationFileName = QString()) const; private: std::shared_ptr m_ScriptExtender { nullptr }; - std::shared_ptr m_DataArchives { nullptr }; + std::shared_ptr m_LocalSavegames { nullptr }; }; From c7b9f289357a66ff9cabc56dc0cbbae969f122fc Mon Sep 17 00:00:00 2001 From: Tannin Date: Sun, 6 Dec 2015 20:21:55 +0100 Subject: [PATCH 0144/1544] [game_fallout76] cleanup --- src/games/fallout76/CMakeLists.txt.user | 206 ----------------------- src/games/fallout76/src/CMakeLists.txt | 2 +- src/games/fallout76/src/gamefallout4.cpp | 19 +-- src/games/fallout76/src/gamefallout4.h | 7 +- 4 files changed, 8 insertions(+), 226 deletions(-) delete mode 100644 src/games/fallout76/CMakeLists.txt.user diff --git a/src/games/fallout76/CMakeLists.txt.user b/src/games/fallout76/CMakeLists.txt.user deleted file mode 100644 index 5d263ca5..00000000 --- a/src/games/fallout76/CMakeLists.txt.user +++ /dev/null @@ -1,206 +0,0 @@ - - - - - - EnvironmentId - {be93058c-4cdc-4db3-a586-0930ff4430c6} - - - ProjectExplorer.Project.ActiveTarget - 0 - - - ProjectExplorer.Project.EditorSettings - - true - false - true - - Cpp - - CppGlobal - - - - QmlJS - - QmlJSGlobal - - - 2 - UTF-8 - false - 4 - false - 80 - true - true - 1 - true - false - 0 - true - 0 - 8 - true - 1 - true - true - true - false - - - - ProjectExplorer.Project.PluginSettings - - - - 1 - - - - - ProjectExplorer.Project.Target.0 - - Desktop - Desktop - {3d7af99e-d2b7-4536-ac05-c1dba2e378bf} - 0 - 0 - 0 - - false - d:\mo_build\build\modorganizer_super\game_fallout4\edit - - - - - false - - true - Make - - CMakeProjectManager.MakeStep - - - - - install - - false - - true - Make - - CMakeProjectManager.MakeStep - - 2 - Build - - ProjectExplorer.BuildSteps.Build - - - - clean - - true - - true - Make - - CMakeProjectManager.MakeStep - - 1 - Clean - - ProjectExplorer.BuildSteps.Clean - - 2 - false - - all - - CMakeProjectManager.CMakeBuildConfiguration - - 1 - - - 0 - Deploy - - ProjectExplorer.BuildSteps.Deploy - - 1 - Deploy locally - - ProjectExplorer.DefaultDeployConfiguration - - 1 - - - - false - false - false - false - true - 0.01 - 10 - true - 1 - 25 - - 1 - true - false - true - valgrind - - 0 - 1 - 2 - 3 - 4 - 5 - 6 - 7 - 8 - 9 - 10 - 11 - 12 - 13 - 14 - - 2 - - - - %{buildDir} - Custom Executable - - ProjectExplorer.CustomExecutableRunConfiguration - 3768 - false - true - false - false - true - - 1 - - - - ProjectExplorer.Project.TargetCount - 1 - - - ProjectExplorer.Project.Updater.FileVersion - 18 - - - Version - 18 - - diff --git a/src/games/fallout76/src/CMakeLists.txt b/src/games/fallout76/src/CMakeLists.txt index 15136936..08e9431d 100644 --- a/src/games/fallout76/src/CMakeLists.txt +++ b/src/games/fallout76/src/CMakeLists.txt @@ -40,7 +40,7 @@ TARGET_LINK_LIBRARIES(${PROJ_NAME} Qt5::Widgets ${Boost_LIBRARIES} uibase - game_gamebryo) + gameGamebryo) SET_TARGET_PROPERTIES(${PROJ_NAME} PROPERTIES COMPILE_FLAGS /GL) SET_TARGET_PROPERTIES(${PROJ_NAME} PROPERTIES LINK_FLAGS_RELWITHDEBINFO "/LTCG /LARGEADDRESSAWARE /OPT:REF /OPT:ICF") diff --git a/src/games/fallout76/src/gamefallout4.cpp b/src/games/fallout76/src/gamefallout4.cpp index 18350703..f31af09c 100644 --- a/src/games/fallout76/src/gamefallout4.cpp +++ b/src/games/fallout76/src/gamefallout4.cpp @@ -3,9 +3,11 @@ #include #include #include +#include #include #include #include +#include #include @@ -22,7 +24,7 @@ bool GameFallout4::init(IOrganizer *moInfo) return false; } m_ScriptExtender = std::shared_ptr(new Fallout4ScriptExtender()); - m_DataArchives = std::shared_ptr(new Fallout4DataArchives()); + m_LocalSavegames.reset(new GamebryoLocalSavegames(myGamesPath(), "Fallout4.ini")); return true; } @@ -36,17 +38,6 @@ QString GameFallout4::gameName() const return "Fallout 4"; } -QString GameFallout4::localAppFolder() const -{ - QString result = getKnownFolderPath(FOLDERID_LocalAppData, false); - if (result.isEmpty()) { - // fallback: try the registry - result = getSpecialPath("Local AppData"); - } - - return result; -} - QString GameFallout4::myGamesFolderName() const { return "Fallout4"; @@ -84,7 +75,7 @@ MOBase::VersionInfo GameFallout4::version() const bool GameFallout4::isActive() const { - return true; + return qApp->property("managed_game").value() == this; } QList GameFallout4::settings() const @@ -148,7 +139,7 @@ const std::map &GameFallout4::featureList() const { static std::map result { { typeid(ScriptExtender), m_ScriptExtender.get() }, - { typeid(DataArchives), m_DataArchives.get() } + { typeid(LocalSavegames), m_LocalSavegames.get() } }; return result; diff --git a/src/games/fallout76/src/gamefallout4.h b/src/games/fallout76/src/gamefallout4.h index 371a64a4..ea61496b 100644 --- a/src/games/fallout76/src/gamefallout4.h +++ b/src/games/fallout76/src/gamefallout4.h @@ -3,7 +3,7 @@ #include "fallout4scriptextender.h" -#include "fallout4dataarchives.h" +#include "gamebryolocalsavegames.h" #include #include @@ -11,9 +11,7 @@ class GameFallout4 : public GameGamebryo { Q_OBJECT -#if QT_VERSION >= QT_VERSION_CHECK(5,0,0) Q_PLUGIN_METADATA(IID "org.tannin.GameFallout4" FILE "gamefallout4.json") -#endif public: @@ -50,14 +48,13 @@ private: virtual QString identifyGamePath() const override; virtual QString myGamesFolderName() const override; - QString localAppFolder() const; void copyToProfile(const QString &sourcePath, const QDir &destinationDirectory, const QString &sourceFileName, const QString &destinationFileName = QString()) const; private: std::shared_ptr m_ScriptExtender { nullptr }; - std::shared_ptr m_DataArchives { nullptr }; + std::shared_ptr m_LocalSavegames { nullptr }; }; From 00e54dfefebc15eaf04a4318452723c00f2e98b8 Mon Sep 17 00:00:00 2001 From: Tannin Date: Sun, 6 Dec 2015 20:21:55 +0100 Subject: [PATCH 0145/1544] [game_fallout4] cleanup --- src/games/fallout4/CMakeLists.txt.user | 206 ------------------------ src/games/fallout4/src/CMakeLists.txt | 2 +- src/games/fallout4/src/gamefallout4.cpp | 19 +-- src/games/fallout4/src/gamefallout4.h | 7 +- 4 files changed, 8 insertions(+), 226 deletions(-) delete mode 100644 src/games/fallout4/CMakeLists.txt.user diff --git a/src/games/fallout4/CMakeLists.txt.user b/src/games/fallout4/CMakeLists.txt.user deleted file mode 100644 index 5d263ca5..00000000 --- a/src/games/fallout4/CMakeLists.txt.user +++ /dev/null @@ -1,206 +0,0 @@ - - - - - - EnvironmentId - {be93058c-4cdc-4db3-a586-0930ff4430c6} - - - ProjectExplorer.Project.ActiveTarget - 0 - - - ProjectExplorer.Project.EditorSettings - - true - false - true - - Cpp - - CppGlobal - - - - QmlJS - - QmlJSGlobal - - - 2 - UTF-8 - false - 4 - false - 80 - true - true - 1 - true - false - 0 - true - 0 - 8 - true - 1 - true - true - true - false - - - - ProjectExplorer.Project.PluginSettings - - - - 1 - - - - - ProjectExplorer.Project.Target.0 - - Desktop - Desktop - {3d7af99e-d2b7-4536-ac05-c1dba2e378bf} - 0 - 0 - 0 - - false - d:\mo_build\build\modorganizer_super\game_fallout4\edit - - - - - false - - true - Make - - CMakeProjectManager.MakeStep - - - - - install - - false - - true - Make - - CMakeProjectManager.MakeStep - - 2 - Build - - ProjectExplorer.BuildSteps.Build - - - - clean - - true - - true - Make - - CMakeProjectManager.MakeStep - - 1 - Clean - - ProjectExplorer.BuildSteps.Clean - - 2 - false - - all - - CMakeProjectManager.CMakeBuildConfiguration - - 1 - - - 0 - Deploy - - ProjectExplorer.BuildSteps.Deploy - - 1 - Deploy locally - - ProjectExplorer.DefaultDeployConfiguration - - 1 - - - - false - false - false - false - true - 0.01 - 10 - true - 1 - 25 - - 1 - true - false - true - valgrind - - 0 - 1 - 2 - 3 - 4 - 5 - 6 - 7 - 8 - 9 - 10 - 11 - 12 - 13 - 14 - - 2 - - - - %{buildDir} - Custom Executable - - ProjectExplorer.CustomExecutableRunConfiguration - 3768 - false - true - false - false - true - - 1 - - - - ProjectExplorer.Project.TargetCount - 1 - - - ProjectExplorer.Project.Updater.FileVersion - 18 - - - Version - 18 - - diff --git a/src/games/fallout4/src/CMakeLists.txt b/src/games/fallout4/src/CMakeLists.txt index 15136936..08e9431d 100644 --- a/src/games/fallout4/src/CMakeLists.txt +++ b/src/games/fallout4/src/CMakeLists.txt @@ -40,7 +40,7 @@ TARGET_LINK_LIBRARIES(${PROJ_NAME} Qt5::Widgets ${Boost_LIBRARIES} uibase - game_gamebryo) + gameGamebryo) SET_TARGET_PROPERTIES(${PROJ_NAME} PROPERTIES COMPILE_FLAGS /GL) SET_TARGET_PROPERTIES(${PROJ_NAME} PROPERTIES LINK_FLAGS_RELWITHDEBINFO "/LTCG /LARGEADDRESSAWARE /OPT:REF /OPT:ICF") diff --git a/src/games/fallout4/src/gamefallout4.cpp b/src/games/fallout4/src/gamefallout4.cpp index 18350703..f31af09c 100644 --- a/src/games/fallout4/src/gamefallout4.cpp +++ b/src/games/fallout4/src/gamefallout4.cpp @@ -3,9 +3,11 @@ #include #include #include +#include #include #include #include +#include #include @@ -22,7 +24,7 @@ bool GameFallout4::init(IOrganizer *moInfo) return false; } m_ScriptExtender = std::shared_ptr(new Fallout4ScriptExtender()); - m_DataArchives = std::shared_ptr(new Fallout4DataArchives()); + m_LocalSavegames.reset(new GamebryoLocalSavegames(myGamesPath(), "Fallout4.ini")); return true; } @@ -36,17 +38,6 @@ QString GameFallout4::gameName() const return "Fallout 4"; } -QString GameFallout4::localAppFolder() const -{ - QString result = getKnownFolderPath(FOLDERID_LocalAppData, false); - if (result.isEmpty()) { - // fallback: try the registry - result = getSpecialPath("Local AppData"); - } - - return result; -} - QString GameFallout4::myGamesFolderName() const { return "Fallout4"; @@ -84,7 +75,7 @@ MOBase::VersionInfo GameFallout4::version() const bool GameFallout4::isActive() const { - return true; + return qApp->property("managed_game").value() == this; } QList GameFallout4::settings() const @@ -148,7 +139,7 @@ const std::map &GameFallout4::featureList() const { static std::map result { { typeid(ScriptExtender), m_ScriptExtender.get() }, - { typeid(DataArchives), m_DataArchives.get() } + { typeid(LocalSavegames), m_LocalSavegames.get() } }; return result; diff --git a/src/games/fallout4/src/gamefallout4.h b/src/games/fallout4/src/gamefallout4.h index 371a64a4..ea61496b 100644 --- a/src/games/fallout4/src/gamefallout4.h +++ b/src/games/fallout4/src/gamefallout4.h @@ -3,7 +3,7 @@ #include "fallout4scriptextender.h" -#include "fallout4dataarchives.h" +#include "gamebryolocalsavegames.h" #include #include @@ -11,9 +11,7 @@ class GameFallout4 : public GameGamebryo { Q_OBJECT -#if QT_VERSION >= QT_VERSION_CHECK(5,0,0) Q_PLUGIN_METADATA(IID "org.tannin.GameFallout4" FILE "gamefallout4.json") -#endif public: @@ -50,14 +48,13 @@ private: virtual QString identifyGamePath() const override; virtual QString myGamesFolderName() const override; - QString localAppFolder() const; void copyToProfile(const QString &sourcePath, const QDir &destinationDirectory, const QString &sourceFileName, const QString &destinationFileName = QString()) const; private: std::shared_ptr m_ScriptExtender { nullptr }; - std::shared_ptr m_DataArchives { nullptr }; + std::shared_ptr m_LocalSavegames { nullptr }; }; From 4f0a07e63f31c5f1be92f31676b11852dc86990a Mon Sep 17 00:00:00 2001 From: Tannin Date: Sun, 6 Dec 2015 20:51:54 +0100 Subject: [PATCH 0146/1544] [game_skyrim] cleanup --- src/games/skyrim/src/CMakeLists.txt | 2 +- src/games/skyrim/src/gameskyrim.cpp | 14 ++------------ src/games/skyrim/src/gameskyrim.h | 1 - 3 files changed, 3 insertions(+), 14 deletions(-) diff --git a/src/games/skyrim/src/CMakeLists.txt b/src/games/skyrim/src/CMakeLists.txt index 15136936..08e9431d 100644 --- a/src/games/skyrim/src/CMakeLists.txt +++ b/src/games/skyrim/src/CMakeLists.txt @@ -40,7 +40,7 @@ TARGET_LINK_LIBRARIES(${PROJ_NAME} Qt5::Widgets ${Boost_LIBRARIES} uibase - game_gamebryo) + gameGamebryo) SET_TARGET_PROPERTIES(${PROJ_NAME} PROPERTIES COMPILE_FLAGS /GL) SET_TARGET_PROPERTIES(${PROJ_NAME} PROPERTIES LINK_FLAGS_RELWITHDEBINFO "/LTCG /LARGEADDRESSAWARE /OPT:REF /OPT:ICF") diff --git a/src/games/skyrim/src/gameskyrim.cpp b/src/games/skyrim/src/gameskyrim.cpp index 7c273262..66c963c9 100644 --- a/src/games/skyrim/src/gameskyrim.cpp +++ b/src/games/skyrim/src/gameskyrim.cpp @@ -6,6 +6,7 @@ #include #include #include +#include using namespace MOBase; @@ -36,17 +37,6 @@ QString GameSkyrim::gameName() const return "Skyrim"; } -QString GameSkyrim::localAppFolder() const -{ - QString result = getKnownFolderPath(FOLDERID_LocalAppData, false); - if (result.isEmpty()) { - // fallback: try the registry - result = getSpecialPath("Local AppData"); - } - - return result; -} - QString GameSkyrim::myGamesFolderName() const { return "Skyrim"; @@ -89,7 +79,7 @@ MOBase::VersionInfo GameSkyrim::version() const bool GameSkyrim::isActive() const { - return true; + return qApp->property("managed_game").value() == this; } QList GameSkyrim::settings() const diff --git a/src/games/skyrim/src/gameskyrim.h b/src/games/skyrim/src/gameskyrim.h index 743223e7..c57d63ca 100644 --- a/src/games/skyrim/src/gameskyrim.h +++ b/src/games/skyrim/src/gameskyrim.h @@ -50,7 +50,6 @@ private: virtual QString identifyGamePath() const override; virtual QString myGamesFolderName() const override; - QString localAppFolder() const; void copyToProfile(const QString &sourcePath, const QDir &destinationDirectory, const QString &sourceFileName, const QString &destinationFileName = QString()) const; From 03c1a7ea56f17a9ac3aceb1ad099aec92d3c432a Mon Sep 17 00:00:00 2001 From: Tannin Date: Sun, 6 Dec 2015 20:52:47 +0100 Subject: [PATCH 0147/1544] [game_falloutnv] cleanup --- src/games/falloutnv/src/CMakeLists.txt | 2 +- src/games/falloutnv/src/gamefalloutnv.cpp | 14 ++------------ src/games/falloutnv/src/gamefalloutnv.h | 1 - 3 files changed, 3 insertions(+), 14 deletions(-) diff --git a/src/games/falloutnv/src/CMakeLists.txt b/src/games/falloutnv/src/CMakeLists.txt index 15136936..08e9431d 100644 --- a/src/games/falloutnv/src/CMakeLists.txt +++ b/src/games/falloutnv/src/CMakeLists.txt @@ -40,7 +40,7 @@ TARGET_LINK_LIBRARIES(${PROJ_NAME} Qt5::Widgets ${Boost_LIBRARIES} uibase - game_gamebryo) + gameGamebryo) SET_TARGET_PROPERTIES(${PROJ_NAME} PROPERTIES COMPILE_FLAGS /GL) SET_TARGET_PROPERTIES(${PROJ_NAME} PROPERTIES LINK_FLAGS_RELWITHDEBINFO "/LTCG /LARGEADDRESSAWARE /OPT:REF /OPT:ICF") diff --git a/src/games/falloutnv/src/gamefalloutnv.cpp b/src/games/falloutnv/src/gamefalloutnv.cpp index 9aeecff5..372dccc0 100644 --- a/src/games/falloutnv/src/gamefalloutnv.cpp +++ b/src/games/falloutnv/src/gamefalloutnv.cpp @@ -6,6 +6,7 @@ #include #include #include +#include using namespace MOBase; @@ -36,17 +37,6 @@ QString GameFalloutNV::gameName() const return "New Vegas"; } -QString GameFalloutNV::localAppFolder() const -{ - QString result = getKnownFolderPath(FOLDERID_LocalAppData, false); - if (result.isEmpty()) { - // fallback: try the registry - result = getSpecialPath("Local AppData"); - } - - return result; -} - QString GameFalloutNV::myGamesFolderName() const { return "FalloutNV"; @@ -87,7 +77,7 @@ MOBase::VersionInfo GameFalloutNV::version() const bool GameFalloutNV::isActive() const { - return true; + return qApp->property("managed_game").value() == this; } QList GameFalloutNV::settings() const diff --git a/src/games/falloutnv/src/gamefalloutnv.h b/src/games/falloutnv/src/gamefalloutnv.h index 35bd0458..f7957b25 100644 --- a/src/games/falloutnv/src/gamefalloutnv.h +++ b/src/games/falloutnv/src/gamefalloutnv.h @@ -50,7 +50,6 @@ private: virtual QString identifyGamePath() const override; virtual QString myGamesFolderName() const override; - QString localAppFolder() const; void copyToProfile(const QString &sourcePath, const QDir &destinationDirectory, const QString &sourceFileName, const QString &destinationFileName = QString()) const; From d510e76c68eb88b4af5a59f87aee765bc854911d Mon Sep 17 00:00:00 2001 From: Tannin Date: Sun, 6 Dec 2015 20:53:29 +0100 Subject: [PATCH 0148/1544] [game_oblivion] cleanup --- src/games/oblivion/src/CMakeLists.txt | 2 +- src/games/oblivion/src/gameoblivion.cpp | 14 ++------------ src/games/oblivion/src/gameoblivion.h | 1 - 3 files changed, 3 insertions(+), 14 deletions(-) diff --git a/src/games/oblivion/src/CMakeLists.txt b/src/games/oblivion/src/CMakeLists.txt index 15136936..08e9431d 100644 --- a/src/games/oblivion/src/CMakeLists.txt +++ b/src/games/oblivion/src/CMakeLists.txt @@ -40,7 +40,7 @@ TARGET_LINK_LIBRARIES(${PROJ_NAME} Qt5::Widgets ${Boost_LIBRARIES} uibase - game_gamebryo) + gameGamebryo) SET_TARGET_PROPERTIES(${PROJ_NAME} PROPERTIES COMPILE_FLAGS /GL) SET_TARGET_PROPERTIES(${PROJ_NAME} PROPERTIES LINK_FLAGS_RELWITHDEBINFO "/LTCG /LARGEADDRESSAWARE /OPT:REF /OPT:ICF") diff --git a/src/games/oblivion/src/gameoblivion.cpp b/src/games/oblivion/src/gameoblivion.cpp index bfb25c63..57aa610e 100644 --- a/src/games/oblivion/src/gameoblivion.cpp +++ b/src/games/oblivion/src/gameoblivion.cpp @@ -6,6 +6,7 @@ #include #include #include +#include using namespace MOBase; @@ -36,17 +37,6 @@ QString GameOblivion::gameName() const return "Oblivion"; } -QString GameOblivion::localAppFolder() const -{ - QString result = getKnownFolderPath(FOLDERID_LocalAppData, false); - if (result.isEmpty()) { - // fallback: try the registry - result = getSpecialPath("Local AppData"); - } - - return result; -} - QString GameOblivion::myGamesFolderName() const { return "Oblivion"; @@ -89,7 +79,7 @@ MOBase::VersionInfo GameOblivion::version() const bool GameOblivion::isActive() const { - return true; + return qApp->property("managed_game").value() == this; } QList GameOblivion::settings() const diff --git a/src/games/oblivion/src/gameoblivion.h b/src/games/oblivion/src/gameoblivion.h index 66a67f6a..a4c2746d 100644 --- a/src/games/oblivion/src/gameoblivion.h +++ b/src/games/oblivion/src/gameoblivion.h @@ -50,7 +50,6 @@ private: virtual QString identifyGamePath() const override; virtual QString myGamesFolderName() const override; - QString localAppFolder() const; void copyToProfile(const QString &sourcePath, const QDir &destinationDirectory, const QString &sourceFileName, const QString &destinationFileName = QString()) const; From 40ac07d89aee2077dcd1d8ed7f6dbce5bc9599ed Mon Sep 17 00:00:00 2001 From: Tannin Date: Sun, 6 Dec 2015 21:00:06 +0100 Subject: [PATCH 0149/1544] [game_fallout3] cleanup --- src/games/fallout3/src/CMakeLists.txt | 2 +- src/games/fallout3/src/gamefallout3.cpp | 14 ++------------ src/games/fallout3/src/gamefallout3.h | 1 - 3 files changed, 3 insertions(+), 14 deletions(-) diff --git a/src/games/fallout3/src/CMakeLists.txt b/src/games/fallout3/src/CMakeLists.txt index 15136936..08e9431d 100644 --- a/src/games/fallout3/src/CMakeLists.txt +++ b/src/games/fallout3/src/CMakeLists.txt @@ -40,7 +40,7 @@ TARGET_LINK_LIBRARIES(${PROJ_NAME} Qt5::Widgets ${Boost_LIBRARIES} uibase - game_gamebryo) + gameGamebryo) SET_TARGET_PROPERTIES(${PROJ_NAME} PROPERTIES COMPILE_FLAGS /GL) SET_TARGET_PROPERTIES(${PROJ_NAME} PROPERTIES LINK_FLAGS_RELWITHDEBINFO "/LTCG /LARGEADDRESSAWARE /OPT:REF /OPT:ICF") diff --git a/src/games/fallout3/src/gamefallout3.cpp b/src/games/fallout3/src/gamefallout3.cpp index 0e0584eb..b5657317 100644 --- a/src/games/fallout3/src/gamefallout3.cpp +++ b/src/games/fallout3/src/gamefallout3.cpp @@ -7,6 +7,7 @@ #include #include #include +#include using namespace MOBase; @@ -37,17 +38,6 @@ QString GameFallout3::gameName() const return "Fallout 3"; } -QString GameFallout3::localAppFolder() const -{ - QString result = getKnownFolderPath(FOLDERID_LocalAppData, false); - if (result.isEmpty()) { - // fallback: try the registry - result = getSpecialPath("Local AppData"); - } - - return result; -} - QString GameFallout3::myGamesFolderName() const { return "Fallout3"; @@ -88,7 +78,7 @@ MOBase::VersionInfo GameFallout3::version() const bool GameFallout3::isActive() const { - return true; + return qApp->property("managed_game").value() == this; } QList GameFallout3::settings() const diff --git a/src/games/fallout3/src/gamefallout3.h b/src/games/fallout3/src/gamefallout3.h index 8cd4ad23..8142995e 100644 --- a/src/games/fallout3/src/gamefallout3.h +++ b/src/games/fallout3/src/gamefallout3.h @@ -51,7 +51,6 @@ private: virtual QString identifyGamePath() const override; virtual QString myGamesFolderName() const override; - QString localAppFolder() const; void copyToProfile(const QString &sourcePath, const QDir &destinationDirectory, const QString &sourceFileName, const QString &destinationFileName = QString()) const; From ec99a1d32688f6a5f9e6d66183b117f1185ad0fb Mon Sep 17 00:00:00 2001 From: Tannin Date: Mon, 7 Dec 2015 19:20:05 +0100 Subject: [PATCH 0150/1544] some cleanup --- CMakeLists.txt | 4 +-- src/CMakeLists.txt | 5 +-- src/dummybsa.cpp | 6 ++-- src/gamebryobsainvalidation.cpp | 1 - src/gamebryolocalsavegames.cpp | 58 +++++++++++++++++++++++++++++++++ src/gamebryolocalsavegames.h | 44 +++++++++++++++++++++++++ src/gamegamebryo.cpp | 13 +++++++- src/gamegamebryo.h | 1 + 8 files changed, 121 insertions(+), 11 deletions(-) create mode 100644 src/gamebryolocalsavegames.cpp create mode 100644 src/gamebryolocalsavegames.h diff --git a/CMakeLists.txt b/CMakeLists.txt index e0a4f4c5..3ef35bb0 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -1,6 +1,6 @@ CMAKE_MINIMUM_REQUIRED(VERSION 2.8) -SET(PROJ_NAME game_gamebryo) +SET(PROJ_NAME gameGamebryo) PROJECT(${PROJ_NAME}) SET(DEPENDENCIES_DIR CACHE PATH "") @@ -11,4 +11,4 @@ LIST(APPEND CMAKE_PREFIX_PATH ${DEPENDENCIES_DIR}/qt5/lib/cmake) FILE(GLOB_RECURSE BOOST_ROOT ${DEPENDENCIES_DIR}/boost*/project-config.jam) GET_FILENAME_COMPONENT(BOOST_ROOT ${BOOST_ROOT} DIRECTORY) -ADD_SUBDIRECTORY(src) \ No newline at end of file +ADD_SUBDIRECTORY(src) diff --git a/src/CMakeLists.txt b/src/CMakeLists.txt index e276aab0..dfbeaaeb 100644 --- a/src/CMakeLists.txt +++ b/src/CMakeLists.txt @@ -29,12 +29,9 @@ SET(project_path "${default_project_path}" CACHE PATH "path to the other mo proj SET(lib_path "${project_path}/../../install/libs") SET(plugin_path "${project_path}") -MESSAGE(STATUS ${lib_path}) -MESSAGE(STATUS ${plugin_path}) -MESSAGE(STATUS ${project_path}) INCLUDE_DIRECTORIES(${project_path}/uibase/src - ${project_path}/game_features/src) + ${project_path}/game_features/src) LINK_DIRECTORIES(${lib_path}) diff --git a/src/dummybsa.cpp b/src/dummybsa.cpp index efbf9dc8..d5c5096e 100644 --- a/src/dummybsa.cpp +++ b/src/dummybsa.cpp @@ -129,7 +129,7 @@ void DummyBSA::writeHeader(QFile &file) writeUlong(header, 4, m_Version); writeUlong(header, 12, 0x01 | 0x02); // has directories and has files. - writeUlong(header, 24, m_FolderName.length() + 1); // empty folder name + writeUlong(header, 24, static_cast(m_FolderName.length()) + 1); // empty folder name writeUlong(header, 28, m_TotalFileNameLength); // single character file name writeUlong(header, 32, 2); // has dds @@ -162,7 +162,7 @@ void DummyBSA::writeFileRecord(QFile &file, const std::string &fileName) // we'd usually have to sort files by the value generated here writeUlonglong(fileRecord, 0, genHash(fileName.c_str())); writeUlong( fileRecord, 8, 0); - writeUlong( fileRecord, 12, 0x44 + (fileName.length() + 1) + 4); // after this record we expect the filename and 4 bytes of file size + writeUlong( fileRecord, 12, 0x44 + static_cast(fileName.length() + 1) + 4); // after this record we expect the filename and 4 bytes of file size file.write(reinterpret_cast(fileRecord), sizeof(fileRecord)); } @@ -179,7 +179,7 @@ void DummyBSA::write(const QString &fileName) QFile file(fileName); file.open(QIODevice::WriteOnly); - m_TotalFileNameLength = m_FileName.length() + 1; + m_TotalFileNameLength = static_cast(m_FileName.length() + 1); writeHeader(file); writeFolderRecord(file, m_FolderName); diff --git a/src/gamebryobsainvalidation.cpp b/src/gamebryobsainvalidation.cpp index dd7b1b02..c9200872 100644 --- a/src/gamebryobsainvalidation.cpp +++ b/src/gamebryobsainvalidation.cpp @@ -2,7 +2,6 @@ #include "dummybsa.h" #include #include -#include #include #include #include diff --git a/src/gamebryolocalsavegames.cpp b/src/gamebryolocalsavegames.cpp new file mode 100644 index 00000000..6d9bb5f1 --- /dev/null +++ b/src/gamebryolocalsavegames.cpp @@ -0,0 +1,58 @@ +/* +Copyright (C) 2015 Sebastian Herbord. All rights reserved. + +This library is free software; you can redistribute it and/or +modify it under the terms of the GNU Lesser General Public +License as published by the Free Software Foundation; either +version 3 of the License, or (at your option) any later version. + +This library is distributed in the hope that it will be useful, +but WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +Lesser General Public License for more details. + +You should have received a copy of the GNU Lesser General Public +License along with this library; if not, write to the Free Software +Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA +*/ + + +#include +#include +#include + + +static const QString LocalSavesDummy = "__MO_Saves"; + + +GamebryoLocalSavegames::GamebryoLocalSavegames(const QDir &myGamesDir, + const QString &iniFileName) + : m_LocalSavesDir(myGamesDir.absoluteFilePath(LocalSavesDummy)) + , m_IniFileName(iniFileName) +{} + + +void GamebryoLocalSavegames::prepareProfile(MOBase::IProfile *profile) +{ + bool enable = profile->localSavesEnabled(); + qDebug("enable local saves: %d", enable); + QString iniFilePath = profile->absolutePath() + "/" + m_IniFileName; + WritePrivateProfileStringW(L"General", L"bUseMyGamesDirectory", + enable ? L"0" : L"1", + iniFilePath.toStdWString().c_str()); + + WritePrivateProfileStringW(L"General", L"SLocalSavePath", + enable ? (LocalSavesDummy + "\\").toStdWString().c_str() + : NULL, + iniFilePath.toStdWString().c_str()); +} + + +MappingType GamebryoLocalSavegames::mappings(const QDir &profileSaveDir) +{ + return {{ + profileSaveDir.absolutePath(), + m_LocalSavesDir.absolutePath(), + true + }}; +} diff --git a/src/gamebryolocalsavegames.h b/src/gamebryolocalsavegames.h new file mode 100644 index 00000000..7630e773 --- /dev/null +++ b/src/gamebryolocalsavegames.h @@ -0,0 +1,44 @@ +/* +Copyright (C) 2015 Sebastian Herbord. All rights reserved. + +This library is free software; you can redistribute it and/or +modify it under the terms of the GNU Lesser General Public +License as published by the Free Software Foundation; either +version 3 of the License, or (at your option) any later version. + +This library is distributed in the hope that it will be useful, +but WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +Lesser General Public License for more details. + +You should have received a copy of the GNU Lesser General Public +License along with this library; if not, write to the Free Software +Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA +*/ + + +#ifndef GAMEBRYOLOCALSAVEGAMES_H +#define GAMEBRYOLOCALSAVEGAMES_H + + +#include + + +class GamebryoLocalSavegames : public LocalSavegames +{ + +public: + GamebryoLocalSavegames(const QDir &myGamesDir, const QString &iniFileName); + + virtual void prepareProfile(MOBase::IProfile *profile) override; + virtual MappingType mappings(const QDir &profileSaveDir) override; + +private: + + QDir m_LocalSavesDir; + QString m_IniFileName; + +}; + + +#endif // GAMEBRYOLOCALSAVEGAMES_H diff --git a/src/gamegamebryo.cpp b/src/gamegamebryo.cpp index 5684ee27..e5f906b9 100644 --- a/src/gamegamebryo.cpp +++ b/src/gamegamebryo.cpp @@ -105,6 +105,17 @@ QString GameGamebryo::getKnownFolderPath(REFKNOWNFOLDERID folderId, bool useDefa } } +QString GameGamebryo::localAppFolder() const +{ + QString result = getKnownFolderPath(FOLDERID_LocalAppData, false); + if (result.isEmpty()) { + // fallback: try the registry + result = getSpecialPath("Local AppData"); + } + + return result; +} + QString GameGamebryo::determineMyGamesPath(const QString &gameName) { // a) this is the way it should work. get the configured My Documents directory @@ -172,7 +183,7 @@ MappingType GameGamebryo::mappings() const for (const QString &profileFile : { "plugins.txt", "loadorder.txt" }) { result.push_back({ m_Organizer->profilePath() + "/" + profileFile, - m_MyGamesPath + "/" + profileFile, + localAppFolder() + "/" + gameName().replace(" ", "") + "/" + profileFile, false }); } diff --git a/src/gamegamebryo.h b/src/gamegamebryo.h index 5c776e34..2296cca5 100644 --- a/src/gamegamebryo.h +++ b/src/gamegamebryo.h @@ -44,6 +44,7 @@ protected: QFileInfo findInGameFolder(const QString &relativePath); QString getKnownFolderPath(REFKNOWNFOLDERID folderId, bool useDefault) const; QString getSpecialPath(const QString &name) const; + QString localAppFolder() const; QString myGamesPath() const; //Arguably this shouldn't really be here but every gamebryo program seems to use it QString getLootPath() const; From bee7de335607a48ee5ba0730ffc544395620d7a6 Mon Sep 17 00:00:00 2001 From: Thomas Tanner Date: Sat, 12 Dec 2015 22:29:05 +0000 Subject: [PATCH 0151/1544] Fix some M/S specific coding --- src/gamebryosavegame.cpp | 2 +- src/gamebryosavegame.h | 2 +- src/gamegamebryo.cpp | 6 +++++- 3 files changed, 7 insertions(+), 3 deletions(-) diff --git a/src/gamebryosavegame.cpp b/src/gamebryosavegame.cpp index e77b8038..832fc249 100644 --- a/src/gamebryosavegame.cpp +++ b/src/gamebryosavegame.cpp @@ -75,7 +75,7 @@ void GamebryoSaveGame::FileWrapper::setBZString(bool state) m_BZString = state; } -template <> __declspec(dllexport) void GamebryoSaveGame::FileWrapper::read(QString &value) +void GamebryoSaveGame::FileWrapper::read(QString &value) { unsigned short length; if (m_BZString) { diff --git a/src/gamebryosavegame.h b/src/gamebryosavegame.h index f46dd375..c787cafb 100644 --- a/src/gamebryosavegame.h +++ b/src/gamebryosavegame.h @@ -72,7 +72,7 @@ protected: } } - template <> void read(QString &value); + void read(QString &value); void read(void *buff, std::size_t length); diff --git a/src/gamegamebryo.cpp b/src/gamegamebryo.cpp index 0976d07b..ac99a4c3 100644 --- a/src/gamegamebryo.cpp +++ b/src/gamegamebryo.cpp @@ -1,7 +1,11 @@ #include "gamegamebryo.h" -#include "utility.h" +#include "bsainvalidation.h" +#include "dataarchives.h" +#include "savegameinfo.h" +#include "scriptextender.h" #include "scopeguard.h" +#include "utility.h" #include From 30c6bcb79461c45a9ef2b1525e207a88b2e1291d Mon Sep 17 00:00:00 2001 From: Thomas Tanner Date: Sun, 13 Dec 2015 15:56:07 +0000 Subject: [PATCH 0152/1544] Restore template but in more standard conformant fashion --- src/gamebryosavegame.cpp | 2 +- src/gamebryosavegame.h | 8 +++++--- 2 files changed, 6 insertions(+), 4 deletions(-) diff --git a/src/gamebryosavegame.cpp b/src/gamebryosavegame.cpp index 832fc249..90e474bf 100644 --- a/src/gamebryosavegame.cpp +++ b/src/gamebryosavegame.cpp @@ -75,7 +75,7 @@ void GamebryoSaveGame::FileWrapper::setBZString(bool state) m_BZString = state; } -void GamebryoSaveGame::FileWrapper::read(QString &value) +template <> void GamebryoSaveGame::FileWrapper::read(QString &value) { unsigned short length; if (m_BZString) { diff --git a/src/gamebryosavegame.h b/src/gamebryosavegame.h index c787cafb..65b6fb11 100644 --- a/src/gamebryosavegame.h +++ b/src/gamebryosavegame.h @@ -4,11 +4,13 @@ #include "isavegame.h" #include +#include #include #include #include -#include +#include +#include struct _SYSTEMTIME; @@ -72,8 +74,6 @@ protected: } } - void read(QString &value); - void read(void *buff, std::size_t length); /* Reads RGB image from save @@ -109,4 +109,6 @@ protected: QImage m_Screenshot; }; +template <> void GamebryoSaveGame::FileWrapper::read(QString &); + #endif // GAMEBRYOSAVEGAME_H From 50f66a3efda25bb0590a6bb74e28493e5f9239ac Mon Sep 17 00:00:00 2001 From: Thomas Tanner Date: Tue, 15 Dec 2015 15:52:53 +0000 Subject: [PATCH 0153/1544] [game_falloutnv] For TanninOne/modorganizer#418 --- src/games/falloutnv/src/falloutnvsavegame.cpp | 7 +++---- src/games/falloutnv/src/falloutnvsavegame.h | 4 +++- .../falloutnv/src/falloutnvsavegameinfo.cpp | 9 ++++++-- .../falloutnv/src/falloutnvsavegameinfo.h | 8 ++++++- src/games/falloutnv/src/gamefalloutnv.cpp | 21 ++++++++++++------- 5 files changed, 33 insertions(+), 16 deletions(-) diff --git a/src/games/falloutnv/src/falloutnvsavegame.cpp b/src/games/falloutnv/src/falloutnvsavegame.cpp index b8cae635..a9d4b2ff 100644 --- a/src/games/falloutnv/src/falloutnvsavegame.cpp +++ b/src/games/falloutnv/src/falloutnvsavegame.cpp @@ -1,7 +1,7 @@ #include "falloutnvsavegame.h" -FalloutNVSaveGame::FalloutNVSaveGame(QString const &fileName) : - GamebryoSaveGame(fileName) +FalloutNVSaveGame::FalloutNVSaveGame(QString const &fileName, MOBase::IPluginGame const *game) : + GamebryoSaveGame(fileName, game) { FileWrapper file(this, "FO3SAVEGAME"); @@ -11,7 +11,7 @@ FalloutNVSaveGame::FalloutNVSaveGame(QString const &fileName) : file.skip(); //Delimiter //A huge wodge of text with no length but a delimiter. Given the null bytes - //in it I presume it's a fixed length (64 bytes + delim) but I have no + //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 @@ -48,4 +48,3 @@ FalloutNVSaveGame::FalloutNVSaveGame(QString const &fileName) : //Abstract this file.readPlugins(); } - diff --git a/src/games/falloutnv/src/falloutnvsavegame.h b/src/games/falloutnv/src/falloutnvsavegame.h index 15c6b4ec..b045469a 100644 --- a/src/games/falloutnv/src/falloutnvsavegame.h +++ b/src/games/falloutnv/src/falloutnvsavegame.h @@ -3,10 +3,12 @@ #include "gamebryosavegame.h" +namespace MOBase { class IPluginGame; } + class FalloutNVSaveGame : public GamebryoSaveGame { public: - FalloutNVSaveGame(QString const &fileName); + FalloutNVSaveGame(QString const &fileName, MOBase::IPluginGame const *game); }; #endif // FALLOUTNVSAVEGAME_H diff --git a/src/games/falloutnv/src/falloutnvsavegameinfo.cpp b/src/games/falloutnv/src/falloutnvsavegameinfo.cpp index 1e675323..b79cf33a 100644 --- a/src/games/falloutnv/src/falloutnvsavegameinfo.cpp +++ b/src/games/falloutnv/src/falloutnvsavegameinfo.cpp @@ -2,7 +2,12 @@ #include "falloutnvsavegame.h" -MOBase::ISaveGame const *FalloutNVSaveGameInfo::getSaveGameInfo(const QString &file) const +FalloutNVSaveGameInfo::FalloutNVSaveGameInfo(MOBase::IPluginGame const *game) : + m_Game(game) { - return new FalloutNVSaveGame(file); +} + +MOBase::ISaveGame const *FalloutNVSaveGameInfo::getSaveGameInfo(QString const &file) const +{ + return new FalloutNVSaveGame(file, m_Game); } diff --git a/src/games/falloutnv/src/falloutnvsavegameinfo.h b/src/games/falloutnv/src/falloutnvsavegameinfo.h index cf6591ea..cfe90d8f 100644 --- a/src/games/falloutnv/src/falloutnvsavegameinfo.h +++ b/src/games/falloutnv/src/falloutnvsavegameinfo.h @@ -3,10 +3,16 @@ #include "savegameinfo.h" +namespace MOBase { class IPluginGame; } + class FalloutNVSaveGameInfo : public SaveGameInfo { public: + FalloutNVSaveGameInfo(MOBase::IPluginGame const *game); virtual MOBase::ISaveGame const *getSaveGameInfo(QString const &file) const override; -}; +private: + MOBase::IPluginGame const* m_Game; + +}; #endif // FALLOUTNVSAVEGAMEINFO_H diff --git a/src/games/falloutnv/src/gamefalloutnv.cpp b/src/games/falloutnv/src/gamefalloutnv.cpp index f812f055..8e777b3c 100644 --- a/src/games/falloutnv/src/gamefalloutnv.cpp +++ b/src/games/falloutnv/src/gamefalloutnv.cpp @@ -4,16 +4,21 @@ #include "falloutnvdataarchives.h" #include "falloutnvsavegameinfo.h" #include "falloutnvscriptextender.h" -#include -#include -#include -#include + +#include "executableinfo.h" +#include "pluginsetting.h" +#include "utility.h" +#include "versioninfo.h" + +#include +#include +#include +#include +#include +#include #include -#include - - using namespace MOBase; @@ -29,7 +34,7 @@ bool GameFalloutNV::init(IOrganizer *moInfo) m_ScriptExtender = std::shared_ptr(new FalloutNVScriptExtender(this)); m_DataArchives = std::shared_ptr(new FalloutNVDataArchives()); m_BSAInvalidation = std::shared_ptr(new FalloutNVBSAInvalidation(m_DataArchives, this)); - m_SaveGameInfo = std::shared_ptr(new FalloutNVSaveGameInfo()); + m_SaveGameInfo = std::shared_ptr(new FalloutNVSaveGameInfo(this)); return true; } From 4311c556a50a6274b97e1710df135b1b19de8049 Mon Sep 17 00:00:00 2001 From: Thomas Tanner Date: Tue, 15 Dec 2015 15:54:00 +0000 Subject: [PATCH 0154/1544] [game_fallout3] For TanninOne/modorganizer#418 Make ISaveGame class responsible for handling extensions --- src/games/fallout3/src/fallout3savegame.cpp | 4 ++-- src/games/fallout3/src/fallout3savegame.h | 4 +++- .../fallout3/src/fallout3savegameinfo.cpp | 9 ++++++-- src/games/fallout3/src/fallout3savegameinfo.h | 5 +++++ src/games/fallout3/src/gamefallout3.cpp | 22 +++++++++++-------- 5 files changed, 30 insertions(+), 14 deletions(-) diff --git a/src/games/fallout3/src/fallout3savegame.cpp b/src/games/fallout3/src/fallout3savegame.cpp index d9fc9a4c..663e3cf3 100644 --- a/src/games/fallout3/src/fallout3savegame.cpp +++ b/src/games/fallout3/src/fallout3savegame.cpp @@ -1,7 +1,7 @@ #include "fallout3savegame.h" -Fallout3SaveGame::Fallout3SaveGame(QString const &fileName) : - GamebryoSaveGame(fileName) +Fallout3SaveGame::Fallout3SaveGame(QString const &fileName, MOBase::IPluginGame const *game) : + GamebryoSaveGame(fileName, game) { FileWrapper file(this, "FO3SAVEGAME"); diff --git a/src/games/fallout3/src/fallout3savegame.h b/src/games/fallout3/src/fallout3savegame.h index 7f953efa..a84cfda5 100644 --- a/src/games/fallout3/src/fallout3savegame.h +++ b/src/games/fallout3/src/fallout3savegame.h @@ -3,10 +3,12 @@ #include "gamebryosavegame.h" +namespace MOBase { class IPluginGame; } + class Fallout3SaveGame : public GamebryoSaveGame { public: - Fallout3SaveGame(QString const &fileName); + Fallout3SaveGame(QString const &fileName, MOBase::IPluginGame const *game); }; #endif // FALLOUT3SAVEGAME_H diff --git a/src/games/fallout3/src/fallout3savegameinfo.cpp b/src/games/fallout3/src/fallout3savegameinfo.cpp index c9823272..25142d04 100644 --- a/src/games/fallout3/src/fallout3savegameinfo.cpp +++ b/src/games/fallout3/src/fallout3savegameinfo.cpp @@ -2,8 +2,13 @@ #include "fallout3savegame.h" -MOBase::ISaveGame const *Fallout3SaveGameInfo::getSaveGameInfo(const QString &file) const +Fallout3SaveGameInfo::Fallout3SaveGameInfo(MOBase::IPluginGame const *game) : + m_Game(game) { - return new Fallout3SaveGame(file); +} + +MOBase::ISaveGame const *Fallout3SaveGameInfo::getSaveGameInfo(const QString &file) const +{ + return new Fallout3SaveGame(file, m_Game); } diff --git a/src/games/fallout3/src/fallout3savegameinfo.h b/src/games/fallout3/src/fallout3savegameinfo.h index 3f2e96c4..3d099ac2 100644 --- a/src/games/fallout3/src/fallout3savegameinfo.h +++ b/src/games/fallout3/src/fallout3savegameinfo.h @@ -3,10 +3,15 @@ #include "savegameinfo.h" +namespace MOBase { class IPluginGame; } + class Fallout3SaveGameInfo : public SaveGameInfo { public: + Fallout3SaveGameInfo(MOBase::IPluginGame const *game); virtual MOBase::ISaveGame const *getSaveGameInfo(QString const &file) const override; +private: + MOBase::IPluginGame const* m_Game; }; #endif // FALLOUT3SAVEGAMEINFO_H diff --git a/src/games/fallout3/src/gamefallout3.cpp b/src/games/fallout3/src/gamefallout3.cpp index 8bc5a522..795a539f 100644 --- a/src/games/fallout3/src/gamefallout3.cpp +++ b/src/games/fallout3/src/gamefallout3.cpp @@ -5,17 +5,21 @@ #include "fallout3dataarchives.h" #include "fallout3savegameinfo.h" -#include -#include -#include -#include +#include "executableinfo.h" +#include "pluginsetting.h" +#include "versioninfo.h" +#include "utility.h" + +#include +#include +#include +#include +#include +#include +#include #include -#include -#include - - using namespace MOBase; @@ -31,7 +35,7 @@ bool GameFallout3::init(IOrganizer *moInfo) m_ScriptExtender = std::shared_ptr(new Fallout3ScriptExtender(this)); m_DataArchives = std::shared_ptr(new Fallout3DataArchives()); m_BSAInvalidation = std::shared_ptr(new Fallout3BSAInvalidation(m_DataArchives, this)); - m_SaveGameInfo = std::shared_ptr(new Fallout3SaveGameInfo()); + m_SaveGameInfo = std::shared_ptr(new Fallout3SaveGameInfo(this)); return true; } From 2269919b6f86683aa5bdf88d0389886f231f5540 Mon Sep 17 00:00:00 2001 From: Thomas Tanner Date: Tue, 15 Dec 2015 15:54:53 +0000 Subject: [PATCH 0155/1544] For TanninOne/modorganizer#418 Make ISaveGame class responsible for handling extensions --- src/gamebryosavegame.cpp | 30 +++++++++++++++++++++++++++--- src/gamebryosavegame.h | 7 ++++++- 2 files changed, 33 insertions(+), 4 deletions(-) diff --git a/src/gamebryosavegame.cpp b/src/gamebryosavegame.cpp index 90e474bf..bb6de525 100644 --- a/src/gamebryosavegame.cpp +++ b/src/gamebryosavegame.cpp @@ -1,16 +1,23 @@ #include "gamebryosavegame.h" +#include "iplugingame.h" +#include "scriptextender.h" + +#include #include #include +#include +#include -#include "Windows.h" +#include #include #include -GamebryoSaveGame::GamebryoSaveGame(QString const &file) : +GamebryoSaveGame::GamebryoSaveGame(QString const &file, MOBase::IPluginGame const *game) : m_FileName(file), - m_CreationTime(QFileInfo(file).lastModified()) + m_CreationTime(QFileInfo(file).lastModified()), + m_Game(game) { } @@ -33,6 +40,23 @@ QString GamebryoSaveGame::getIdentifier() const return m_PCName; } +QStringList GamebryoSaveGame::allFiles() const +{ + //This returns all valid files associated with this game + QStringList res = { m_FileName }; + ScriptExtender const *e = m_Game->feature(); + if (e != nullptr) { + QFileInfo file(m_FileName); + for (QString const &ext : e->saveGameAttachmentExtensions()) { + QFileInfo name(file.absoluteDir().absoluteFilePath(file.completeBaseName() + "." + ext)); + if (name.exists()) { + res.push_back(name.absoluteFilePath()); + } + } + } + return res; +} + void GamebryoSaveGame::setCreationTime(_SYSTEMTIME const &ctime) { QDate date; diff --git a/src/gamebryosavegame.h b/src/gamebryosavegame.h index 65b6fb11..4503659f 100644 --- a/src/gamebryosavegame.h +++ b/src/gamebryosavegame.h @@ -14,10 +14,12 @@ struct _SYSTEMTIME; +namespace MOBase { class IPluginGame; } + class GamebryoSaveGame : public MOBase::ISaveGame { public: - GamebryoSaveGame(QString const &file); + GamebryoSaveGame(QString const &file, MOBase::IPluginGame const *game); virtual ~GamebryoSaveGame(); @@ -27,6 +29,8 @@ public: virtual QString getIdentifier() const override; + virtual QStringList allFiles() const override; + //Simple getters QString getPCName() const { return m_PCName; } unsigned short getPCLevel() const { return m_PCLevel; } @@ -107,6 +111,7 @@ protected: QDateTime m_CreationTime; QStringList m_Plugins; QImage m_Screenshot; + MOBase::IPluginGame const *m_Game; }; template <> void GamebryoSaveGame::FileWrapper::read(QString &); From b9b0ba9e9e9032b9da1bf3195a9013ebd445d3b3 Mon Sep 17 00:00:00 2001 From: Thomas Tanner Date: Tue, 15 Dec 2015 15:55:24 +0000 Subject: [PATCH 0156/1544] [game_oblivion] For TanninOne/modorganizer#418 Make ISaveGame class responsible for handling extensions --- src/games/oblivion/src/gameoblivion.cpp | 16 +++++++++------- src/games/oblivion/src/oblivionsavegame.cpp | 4 ++-- src/games/oblivion/src/oblivionsavegame.h | 2 +- src/games/oblivion/src/oblivionsavegameinfo.cpp | 9 +++++++-- src/games/oblivion/src/oblivionsavegameinfo.h | 10 ++++++++-- 5 files changed, 27 insertions(+), 14 deletions(-) diff --git a/src/games/oblivion/src/gameoblivion.cpp b/src/games/oblivion/src/gameoblivion.cpp index ccfeb324..ab48ac31 100644 --- a/src/games/oblivion/src/gameoblivion.cpp +++ b/src/games/oblivion/src/gameoblivion.cpp @@ -5,13 +5,15 @@ #include "oblivionsavegameinfo.h" #include "oblivionscriptextender.h" -#include -#include -#include -#include -#include -#include +#include "pluginsetting.h" +#include "executableinfo.h" +#include "utility.h" +#include +#include +#include + +#include using namespace MOBase; @@ -28,7 +30,7 @@ bool GameOblivion::init(IOrganizer *moInfo) m_ScriptExtender = std::shared_ptr(new OblivionScriptExtender(this)); m_DataArchives = std::shared_ptr(new OblivionDataArchives()); m_BSAInvalidation = std::shared_ptr(new OblivionBSAInvalidation(m_DataArchives, this)); - m_SaveGameInfo = std::shared_ptr(new OblivionSaveGameInfo()); + m_SaveGameInfo = std::shared_ptr(new OblivionSaveGameInfo(this)); return true; } diff --git a/src/games/oblivion/src/oblivionsavegame.cpp b/src/games/oblivion/src/oblivionsavegame.cpp index d60535e6..a639895b 100644 --- a/src/games/oblivion/src/oblivionsavegame.cpp +++ b/src/games/oblivion/src/oblivionsavegame.cpp @@ -2,8 +2,8 @@ #include -OblivionSaveGame::OblivionSaveGame(const QString &game) : - GamebryoSaveGame(game) +OblivionSaveGame::OblivionSaveGame(QString const &fileName, MOBase::IPluginGame const *game) : + GamebryoSaveGame(fileName, game) { FileWrapper file(this, "TES4SAVEGAME"); file.setBZString(true); diff --git a/src/games/oblivion/src/oblivionsavegame.h b/src/games/oblivion/src/oblivionsavegame.h index f6e05ea8..2df34f9b 100644 --- a/src/games/oblivion/src/oblivionsavegame.h +++ b/src/games/oblivion/src/oblivionsavegame.h @@ -6,7 +6,7 @@ class OblivionSaveGame : public GamebryoSaveGame { public: - OblivionSaveGame(QString const &); + OblivionSaveGame(QString const &fileName, MOBase::IPluginGame const *game); }; #endif // OBLIVIONSAVEGAME_H diff --git a/src/games/oblivion/src/oblivionsavegameinfo.cpp b/src/games/oblivion/src/oblivionsavegameinfo.cpp index 1b6dad0c..eaa93835 100644 --- a/src/games/oblivion/src/oblivionsavegameinfo.cpp +++ b/src/games/oblivion/src/oblivionsavegameinfo.cpp @@ -2,8 +2,13 @@ #include "oblivionsavegame.h" -MOBase::ISaveGame const *OblivionSaveGameInfo::getSaveGameInfo(const QString &file) const +OblivionSaveGameInfo::OblivionSaveGameInfo(MOBase::IPluginGame const *game) : + m_Game(game) { - return new OblivionSaveGame(file); +} + +MOBase::ISaveGame const *OblivionSaveGameInfo::getSaveGameInfo(QString const &file) const +{ + return new OblivionSaveGame(file, m_Game); } diff --git a/src/games/oblivion/src/oblivionsavegameinfo.h b/src/games/oblivion/src/oblivionsavegameinfo.h index 38462c4a..87f7f091 100644 --- a/src/games/oblivion/src/oblivionsavegameinfo.h +++ b/src/games/oblivion/src/oblivionsavegameinfo.h @@ -3,10 +3,16 @@ #include "savegameinfo.h" +namespace MOBase { class IPluginGame; } + class OblivionSaveGameInfo : public SaveGameInfo { public: - virtual MOBase::ISaveGame const *getSaveGameInfo(QString const &file) const override; -}; + OblivionSaveGameInfo(MOBase::IPluginGame const *game); + virtual MOBase::ISaveGame const *getSaveGameInfo(QString const &file) const override; + +private: + MOBase::IPluginGame const* m_Game; +}; #endif // OBLIVIONSAVEGAMEINFO_H From 5e8d9463c290256f17b15c094ee20609655f3158 Mon Sep 17 00:00:00 2001 From: Thomas Tanner Date: Tue, 15 Dec 2015 15:56:21 +0000 Subject: [PATCH 0157/1544] [game_skyrim] For TanninOne/modorganizer#418 Make ISaveGame class responsible for handling extensions --- src/games/skyrim/src/gameskyrim.cpp | 16 ++++++++++------ src/games/skyrim/src/skyrimsavegame.cpp | 4 ++-- src/games/skyrim/src/skyrimsavegame.h | 4 +++- src/games/skyrim/src/skyrimsavegameinfo.cpp | 10 ++++++++-- src/games/skyrim/src/skyrimsavegameinfo.h | 6 ++++++ 5 files changed, 29 insertions(+), 11 deletions(-) diff --git a/src/games/skyrim/src/gameskyrim.cpp b/src/games/skyrim/src/gameskyrim.cpp index f1606d39..3054e237 100644 --- a/src/games/skyrim/src/gameskyrim.cpp +++ b/src/games/skyrim/src/gameskyrim.cpp @@ -5,18 +5,22 @@ #include "skyrimdataarchives.h" #include "skyrimsavegameinfo.h" -#include -#include -#include -#include +#include "executableinfo.h" +#include "pluginsetting.h" +#include "utility.h" #include -#include +#include +#include + +#include #include #include #include +#include +#include #include @@ -35,7 +39,7 @@ bool GameSkyrim::init(IOrganizer *moInfo) m_ScriptExtender = std::shared_ptr(new SkyrimScriptExtender(this)); m_DataArchives = std::shared_ptr(new SkyrimDataArchives()); m_BSAInvalidation = std::shared_ptr(new SkyrimBSAInvalidation(m_DataArchives, this)); - m_SaveGameInfo = std::shared_ptr(new SkyrimSaveGameInfo()); + m_SaveGameInfo = std::shared_ptr(new SkyrimSaveGameInfo(this)); return true; } diff --git a/src/games/skyrim/src/skyrimsavegame.cpp b/src/games/skyrim/src/skyrimsavegame.cpp index b121b0bd..fa3f8e6d 100644 --- a/src/games/skyrim/src/skyrimsavegame.cpp +++ b/src/games/skyrim/src/skyrimsavegame.cpp @@ -2,8 +2,8 @@ #include -SkyrimSaveGame::SkyrimSaveGame(QString const &fileName) : - GamebryoSaveGame(fileName) +SkyrimSaveGame::SkyrimSaveGame(QString const &fileName, MOBase::IPluginGame const *game) : + GamebryoSaveGame(fileName, game) { FileWrapper file(this, "TESV_SAVEGAME"); file.skip(); // header size diff --git a/src/games/skyrim/src/skyrimsavegame.h b/src/games/skyrim/src/skyrimsavegame.h index db93c3f6..77740ba9 100644 --- a/src/games/skyrim/src/skyrimsavegame.h +++ b/src/games/skyrim/src/skyrimsavegame.h @@ -3,10 +3,12 @@ #include "gamebryosavegame.h" +namespace MOBase { class IPluginGame; } + class SkyrimSaveGame : public GamebryoSaveGame { public: - SkyrimSaveGame(QString const &fileName); + SkyrimSaveGame(QString const &fileName, MOBase::IPluginGame const *game); }; #endif // SKYRIMSAVEGAME_H diff --git a/src/games/skyrim/src/skyrimsavegameinfo.cpp b/src/games/skyrim/src/skyrimsavegameinfo.cpp index 51265fd8..3801e29e 100644 --- a/src/games/skyrim/src/skyrimsavegameinfo.cpp +++ b/src/games/skyrim/src/skyrimsavegameinfo.cpp @@ -2,8 +2,14 @@ #include "skyrimsavegame.h" -MOBase::ISaveGame const *SkyrimSaveGameInfo::getSaveGameInfo(const QString &file) const +SkyrimSaveGameInfo::SkyrimSaveGameInfo(MOBase::IPluginGame const *game) : + m_Game(game) { - return new SkyrimSaveGame(file); +} + + +MOBase::ISaveGame const *SkyrimSaveGameInfo::getSaveGameInfo(const QString &file) const +{ + return new SkyrimSaveGame(file, m_Game); } diff --git a/src/games/skyrim/src/skyrimsavegameinfo.h b/src/games/skyrim/src/skyrimsavegameinfo.h index bb7054cf..252dd978 100644 --- a/src/games/skyrim/src/skyrimsavegameinfo.h +++ b/src/games/skyrim/src/skyrimsavegameinfo.h @@ -3,10 +3,16 @@ #include "savegameinfo.h" +namespace MOBase { class IPluginGame; } + class SkyrimSaveGameInfo : public SaveGameInfo { public: + SkyrimSaveGameInfo(MOBase::IPluginGame const *game); virtual MOBase::ISaveGame const *getSaveGameInfo(QString const &file) const override; +private: + MOBase::IPluginGame const *m_Game; + }; #endif // SKYRIMSAVEGAMEINFO_H From 1c300629106c4f392321af69e7a57841332d2fcd Mon Sep 17 00:00:00 2001 From: Tannin Date: Fri, 18 Dec 2015 19:55:28 +0100 Subject: [PATCH 0158/1544] added support for alpha channel on gamebryo savegames --- src/gamebryolocalsavegames.cpp | 1 + src/gamebryosavegame.cpp | 18 ++++++++++-------- src/gamebryosavegame.h | 4 ++-- 3 files changed, 13 insertions(+), 10 deletions(-) diff --git a/src/gamebryolocalsavegames.cpp b/src/gamebryolocalsavegames.cpp index 6d9bb5f1..3406f332 100644 --- a/src/gamebryolocalsavegames.cpp +++ b/src/gamebryolocalsavegames.cpp @@ -53,6 +53,7 @@ MappingType GamebryoLocalSavegames::mappings(const QDir &profileSaveDir) return {{ profileSaveDir.absolutePath(), m_LocalSavesDir.absolutePath(), + true, true }}; } diff --git a/src/gamebryosavegame.cpp b/src/gamebryosavegame.cpp index e77b8038..a4bd34e2 100644 --- a/src/gamebryosavegame.cpp +++ b/src/gamebryosavegame.cpp @@ -75,7 +75,7 @@ void GamebryoSaveGame::FileWrapper::setBZString(bool state) m_BZString = state; } -template <> __declspec(dllexport) void GamebryoSaveGame::FileWrapper::read(QString &value) +template <> void GamebryoSaveGame::FileWrapper::read(QString &value) { unsigned short length; if (m_BZString) { @@ -108,21 +108,23 @@ void GamebryoSaveGame::FileWrapper::read(void *buff, std::size_t length) } } -void GamebryoSaveGame::FileWrapper::readImage(int scale) +void GamebryoSaveGame::FileWrapper::readImage(int scale, bool alpha) { unsigned long width; read(width); unsigned long height; read(height); - readImage(width, height, scale); + readImage(width, height, scale, alpha); } -void GamebryoSaveGame::FileWrapper::readImage(unsigned long width, unsigned long height, int scale) +void GamebryoSaveGame::FileWrapper::readImage(unsigned long width, unsigned long height, int scale, bool alpha) { - QScopedArrayPointer buffer(new unsigned char[width * height * 3]); - read(buffer.data(), width * height * 3); - QImage image(buffer.data(), width, height, QImage::Format_RGB888); - if (scale) { + int bpp = alpha ? 4 : 3; + QScopedArrayPointer buffer(new unsigned char[width * height * bpp]); + read(buffer.data(), width * height * bpp); + QImage image(buffer.data(), width, height, alpha ? QImage::Format_RGBA8888 + : QImage::Format_RGB888); + if (scale != 0) { m_Game->m_Screenshot = image.scaledToWidth(scale); } else { // why do I have to copy here? without the copy, the buffer seems to get deleted after the diff --git a/src/gamebryosavegame.h b/src/gamebryosavegame.h index f46dd375..cfef41a0 100644 --- a/src/gamebryosavegame.h +++ b/src/gamebryosavegame.h @@ -79,10 +79,10 @@ protected: /* Reads RGB image from save * Assumes picture dimentions come immediately before the save */ - void readImage(int scale = 0); + void readImage(int scale = 0, bool alpha = false); /* Reads RGB image from save */ - void readImage(unsigned long width, unsigned long height, int scale = 0); + void readImage(unsigned long width, unsigned long height, int scale = 0, bool alpha = false); /* Read the plugin list */ void readPlugins(); From f9466620c7b5472d0912d573bbbb9a227e925100 Mon Sep 17 00:00:00 2001 From: Tannin Date: Fri, 18 Dec 2015 20:34:36 +0100 Subject: [PATCH 0159/1544] [game_fallout4vr] added savegame interface --- src/games/fallout4vr/src/fallout4savegame.cpp | 44 +++++++++++++++++++ src/games/fallout4vr/src/fallout4savegame.h | 12 +++++ .../fallout4vr/src/fallout4savegameinfo.cpp | 9 ++++ .../fallout4vr/src/fallout4savegameinfo.h | 12 +++++ src/games/fallout4vr/src/gamefallout4.cpp | 2 + 5 files changed, 79 insertions(+) create mode 100644 src/games/fallout4vr/src/fallout4savegame.cpp create mode 100644 src/games/fallout4vr/src/fallout4savegame.h create mode 100644 src/games/fallout4vr/src/fallout4savegameinfo.cpp create mode 100644 src/games/fallout4vr/src/fallout4savegameinfo.h diff --git a/src/games/fallout4vr/src/fallout4savegame.cpp b/src/games/fallout4vr/src/fallout4savegame.cpp new file mode 100644 index 00000000..33b807ef --- /dev/null +++ b/src/games/fallout4vr/src/fallout4savegame.cpp @@ -0,0 +1,44 @@ +#include "fallout4savegame.h" + +#include + +Fallout4SaveGame::Fallout4SaveGame(QString const &fileName) : + GamebryoSaveGame(fileName) +{ + FileWrapper file(this, "FO4_SAVEGAME"); + file.skip(); // header size + file.skip(); // header version + file.read(m_SaveNumber); + + file.read(m_PCName); + + unsigned long temp; + file.read(temp); + m_PCLevel = static_cast(temp); + file.read(m_PCLocation); + + QString ignore; + file.read(ignore); // playtime as ascii hh.mm.ss + file.read(ignore); // race name (i.e. BretonRace) + + file.skip(); // Player gender (0 = male) + file.skip(2); // experience gathered, experience required + + FILETIME ftime; + file.read(ftime); + //A file time is a 64-bit value that represents the number of 100-nanosecond + //intervals that have elapsed since 12:00 A.M. January 1, 1601 Coordinated Universal Time (UTC). + //So we need to convert that to something useful + SYSTEMTIME ctime; + ::FileTimeToSystemTime(&ftime, &ctime); + + setCreationTime(ctime); + + file.readImage(384, true); + + file.skip(); // form version + file.read(ignore); // game version + file.skip(); // plugin info size + + file.readPlugins(); +} diff --git a/src/games/fallout4vr/src/fallout4savegame.h b/src/games/fallout4vr/src/fallout4savegame.h new file mode 100644 index 00000000..6c89b5bb --- /dev/null +++ b/src/games/fallout4vr/src/fallout4savegame.h @@ -0,0 +1,12 @@ +#ifndef FALLOUT4SAVEGAME_H +#define FALLOUT4SAVEGAME_H + +#include "gamebryosavegame.h" + +class Fallout4SaveGame : public GamebryoSaveGame +{ +public: + Fallout4SaveGame(QString const &fileName); +}; + +#endif // FALLOUT4SAVEGAME_H diff --git a/src/games/fallout4vr/src/fallout4savegameinfo.cpp b/src/games/fallout4vr/src/fallout4savegameinfo.cpp new file mode 100644 index 00000000..b2c60144 --- /dev/null +++ b/src/games/fallout4vr/src/fallout4savegameinfo.cpp @@ -0,0 +1,9 @@ +#include "fallout4savegameinfo.h" + +#include "fallout4savegame.h" + +const MOBase::ISaveGame *Fallout4SaveGameInfo::getSaveGameInfo(const QString &file) const +{ + return new Fallout4SaveGame(file); +} + diff --git a/src/games/fallout4vr/src/fallout4savegameinfo.h b/src/games/fallout4vr/src/fallout4savegameinfo.h new file mode 100644 index 00000000..68d8626e --- /dev/null +++ b/src/games/fallout4vr/src/fallout4savegameinfo.h @@ -0,0 +1,12 @@ +#ifndef SKYRIMSAVEGAMEINFO_H +#define SKYRIMSAVEGAMEINFO_H + +#include "savegameinfo.h" + +class Fallout4SaveGameInfo : public SaveGameInfo +{ +public: + virtual MOBase::ISaveGame const *getSaveGameInfo(QString const &file) const override; +}; + +#endif // SKYRIMSAVEGAMEINFO_H diff --git a/src/games/fallout4vr/src/gamefallout4.cpp b/src/games/fallout4vr/src/gamefallout4.cpp index 00984a94..8482df89 100644 --- a/src/games/fallout4vr/src/gamefallout4.cpp +++ b/src/games/fallout4vr/src/gamefallout4.cpp @@ -2,6 +2,7 @@ #include "fallout4dataarchives.h" #include "fallout4scriptextender.h" +#include "fallout4savegameinfo.h" #include #include #include "iplugingame.h" @@ -30,6 +31,7 @@ bool GameFallout4::init(IOrganizer *moInfo) m_ScriptExtender = std::shared_ptr(new Fallout4ScriptExtender(this)); m_DataArchives = std::shared_ptr(new Fallout4DataArchives()); m_LocalSavegames.reset(new GamebryoLocalSavegames(myGamesPath(), "Fallout4.ini")); + m_SaveGameInfo = std::shared_ptr(new Fallout4SaveGameInfo()); return true; } From da2c914ae203d71c6235e1c0f72b724a04347ba6 Mon Sep 17 00:00:00 2001 From: Tannin Date: Fri, 18 Dec 2015 20:34:36 +0100 Subject: [PATCH 0160/1544] [game_fallout76] added savegame interface --- src/games/fallout76/src/fallout4savegame.cpp | 44 +++++++++++++++++++ src/games/fallout76/src/fallout4savegame.h | 12 +++++ .../fallout76/src/fallout4savegameinfo.cpp | 9 ++++ .../fallout76/src/fallout4savegameinfo.h | 12 +++++ src/games/fallout76/src/gamefallout4.cpp | 2 + 5 files changed, 79 insertions(+) create mode 100644 src/games/fallout76/src/fallout4savegame.cpp create mode 100644 src/games/fallout76/src/fallout4savegame.h create mode 100644 src/games/fallout76/src/fallout4savegameinfo.cpp create mode 100644 src/games/fallout76/src/fallout4savegameinfo.h diff --git a/src/games/fallout76/src/fallout4savegame.cpp b/src/games/fallout76/src/fallout4savegame.cpp new file mode 100644 index 00000000..33b807ef --- /dev/null +++ b/src/games/fallout76/src/fallout4savegame.cpp @@ -0,0 +1,44 @@ +#include "fallout4savegame.h" + +#include + +Fallout4SaveGame::Fallout4SaveGame(QString const &fileName) : + GamebryoSaveGame(fileName) +{ + FileWrapper file(this, "FO4_SAVEGAME"); + file.skip(); // header size + file.skip(); // header version + file.read(m_SaveNumber); + + file.read(m_PCName); + + unsigned long temp; + file.read(temp); + m_PCLevel = static_cast(temp); + file.read(m_PCLocation); + + QString ignore; + file.read(ignore); // playtime as ascii hh.mm.ss + file.read(ignore); // race name (i.e. BretonRace) + + file.skip(); // Player gender (0 = male) + file.skip(2); // experience gathered, experience required + + FILETIME ftime; + file.read(ftime); + //A file time is a 64-bit value that represents the number of 100-nanosecond + //intervals that have elapsed since 12:00 A.M. January 1, 1601 Coordinated Universal Time (UTC). + //So we need to convert that to something useful + SYSTEMTIME ctime; + ::FileTimeToSystemTime(&ftime, &ctime); + + setCreationTime(ctime); + + file.readImage(384, true); + + file.skip(); // form version + file.read(ignore); // game version + file.skip(); // plugin info size + + file.readPlugins(); +} diff --git a/src/games/fallout76/src/fallout4savegame.h b/src/games/fallout76/src/fallout4savegame.h new file mode 100644 index 00000000..6c89b5bb --- /dev/null +++ b/src/games/fallout76/src/fallout4savegame.h @@ -0,0 +1,12 @@ +#ifndef FALLOUT4SAVEGAME_H +#define FALLOUT4SAVEGAME_H + +#include "gamebryosavegame.h" + +class Fallout4SaveGame : public GamebryoSaveGame +{ +public: + Fallout4SaveGame(QString const &fileName); +}; + +#endif // FALLOUT4SAVEGAME_H diff --git a/src/games/fallout76/src/fallout4savegameinfo.cpp b/src/games/fallout76/src/fallout4savegameinfo.cpp new file mode 100644 index 00000000..b2c60144 --- /dev/null +++ b/src/games/fallout76/src/fallout4savegameinfo.cpp @@ -0,0 +1,9 @@ +#include "fallout4savegameinfo.h" + +#include "fallout4savegame.h" + +const MOBase::ISaveGame *Fallout4SaveGameInfo::getSaveGameInfo(const QString &file) const +{ + return new Fallout4SaveGame(file); +} + diff --git a/src/games/fallout76/src/fallout4savegameinfo.h b/src/games/fallout76/src/fallout4savegameinfo.h new file mode 100644 index 00000000..68d8626e --- /dev/null +++ b/src/games/fallout76/src/fallout4savegameinfo.h @@ -0,0 +1,12 @@ +#ifndef SKYRIMSAVEGAMEINFO_H +#define SKYRIMSAVEGAMEINFO_H + +#include "savegameinfo.h" + +class Fallout4SaveGameInfo : public SaveGameInfo +{ +public: + virtual MOBase::ISaveGame const *getSaveGameInfo(QString const &file) const override; +}; + +#endif // SKYRIMSAVEGAMEINFO_H diff --git a/src/games/fallout76/src/gamefallout4.cpp b/src/games/fallout76/src/gamefallout4.cpp index 00984a94..8482df89 100644 --- a/src/games/fallout76/src/gamefallout4.cpp +++ b/src/games/fallout76/src/gamefallout4.cpp @@ -2,6 +2,7 @@ #include "fallout4dataarchives.h" #include "fallout4scriptextender.h" +#include "fallout4savegameinfo.h" #include #include #include "iplugingame.h" @@ -30,6 +31,7 @@ bool GameFallout4::init(IOrganizer *moInfo) m_ScriptExtender = std::shared_ptr(new Fallout4ScriptExtender(this)); m_DataArchives = std::shared_ptr(new Fallout4DataArchives()); m_LocalSavegames.reset(new GamebryoLocalSavegames(myGamesPath(), "Fallout4.ini")); + m_SaveGameInfo = std::shared_ptr(new Fallout4SaveGameInfo()); return true; } From 0bb6c013864020ce0ec381a42792f6aa905fb604 Mon Sep 17 00:00:00 2001 From: Tannin Date: Fri, 18 Dec 2015 20:34:36 +0100 Subject: [PATCH 0161/1544] [game_fallout4] added savegame interface --- src/games/fallout4/src/fallout4savegame.cpp | 44 +++++++++++++++++++ src/games/fallout4/src/fallout4savegame.h | 12 +++++ .../fallout4/src/fallout4savegameinfo.cpp | 9 ++++ src/games/fallout4/src/fallout4savegameinfo.h | 12 +++++ src/games/fallout4/src/gamefallout4.cpp | 2 + 5 files changed, 79 insertions(+) create mode 100644 src/games/fallout4/src/fallout4savegame.cpp create mode 100644 src/games/fallout4/src/fallout4savegame.h create mode 100644 src/games/fallout4/src/fallout4savegameinfo.cpp create mode 100644 src/games/fallout4/src/fallout4savegameinfo.h diff --git a/src/games/fallout4/src/fallout4savegame.cpp b/src/games/fallout4/src/fallout4savegame.cpp new file mode 100644 index 00000000..33b807ef --- /dev/null +++ b/src/games/fallout4/src/fallout4savegame.cpp @@ -0,0 +1,44 @@ +#include "fallout4savegame.h" + +#include + +Fallout4SaveGame::Fallout4SaveGame(QString const &fileName) : + GamebryoSaveGame(fileName) +{ + FileWrapper file(this, "FO4_SAVEGAME"); + file.skip(); // header size + file.skip(); // header version + file.read(m_SaveNumber); + + file.read(m_PCName); + + unsigned long temp; + file.read(temp); + m_PCLevel = static_cast(temp); + file.read(m_PCLocation); + + QString ignore; + file.read(ignore); // playtime as ascii hh.mm.ss + file.read(ignore); // race name (i.e. BretonRace) + + file.skip(); // Player gender (0 = male) + file.skip(2); // experience gathered, experience required + + FILETIME ftime; + file.read(ftime); + //A file time is a 64-bit value that represents the number of 100-nanosecond + //intervals that have elapsed since 12:00 A.M. January 1, 1601 Coordinated Universal Time (UTC). + //So we need to convert that to something useful + SYSTEMTIME ctime; + ::FileTimeToSystemTime(&ftime, &ctime); + + setCreationTime(ctime); + + file.readImage(384, true); + + file.skip(); // form version + file.read(ignore); // game version + file.skip(); // plugin info size + + file.readPlugins(); +} diff --git a/src/games/fallout4/src/fallout4savegame.h b/src/games/fallout4/src/fallout4savegame.h new file mode 100644 index 00000000..6c89b5bb --- /dev/null +++ b/src/games/fallout4/src/fallout4savegame.h @@ -0,0 +1,12 @@ +#ifndef FALLOUT4SAVEGAME_H +#define FALLOUT4SAVEGAME_H + +#include "gamebryosavegame.h" + +class Fallout4SaveGame : public GamebryoSaveGame +{ +public: + Fallout4SaveGame(QString const &fileName); +}; + +#endif // FALLOUT4SAVEGAME_H diff --git a/src/games/fallout4/src/fallout4savegameinfo.cpp b/src/games/fallout4/src/fallout4savegameinfo.cpp new file mode 100644 index 00000000..b2c60144 --- /dev/null +++ b/src/games/fallout4/src/fallout4savegameinfo.cpp @@ -0,0 +1,9 @@ +#include "fallout4savegameinfo.h" + +#include "fallout4savegame.h" + +const MOBase::ISaveGame *Fallout4SaveGameInfo::getSaveGameInfo(const QString &file) const +{ + return new Fallout4SaveGame(file); +} + diff --git a/src/games/fallout4/src/fallout4savegameinfo.h b/src/games/fallout4/src/fallout4savegameinfo.h new file mode 100644 index 00000000..68d8626e --- /dev/null +++ b/src/games/fallout4/src/fallout4savegameinfo.h @@ -0,0 +1,12 @@ +#ifndef SKYRIMSAVEGAMEINFO_H +#define SKYRIMSAVEGAMEINFO_H + +#include "savegameinfo.h" + +class Fallout4SaveGameInfo : public SaveGameInfo +{ +public: + virtual MOBase::ISaveGame const *getSaveGameInfo(QString const &file) const override; +}; + +#endif // SKYRIMSAVEGAMEINFO_H diff --git a/src/games/fallout4/src/gamefallout4.cpp b/src/games/fallout4/src/gamefallout4.cpp index 00984a94..8482df89 100644 --- a/src/games/fallout4/src/gamefallout4.cpp +++ b/src/games/fallout4/src/gamefallout4.cpp @@ -2,6 +2,7 @@ #include "fallout4dataarchives.h" #include "fallout4scriptextender.h" +#include "fallout4savegameinfo.h" #include #include #include "iplugingame.h" @@ -30,6 +31,7 @@ bool GameFallout4::init(IOrganizer *moInfo) m_ScriptExtender = std::shared_ptr(new Fallout4ScriptExtender(this)); m_DataArchives = std::shared_ptr(new Fallout4DataArchives()); m_LocalSavegames.reset(new GamebryoLocalSavegames(myGamesPath(), "Fallout4.ini")); + m_SaveGameInfo = std::shared_ptr(new Fallout4SaveGameInfo()); return true; } From 31358ea4687453e5006778eb9f9e675e1fa90d38 Mon Sep 17 00:00:00 2001 From: Thomas Tanner Date: Sat, 19 Dec 2015 20:45:57 +0000 Subject: [PATCH 0162/1544] [game_fallout3] Changes to support getting list of mods / esps to activate from game plugin --- src/games/fallout3/src/fallout3savegameinfo.cpp | 9 +++++++-- src/games/fallout3/src/fallout3savegameinfo.h | 12 ++++++------ 2 files changed, 13 insertions(+), 8 deletions(-) diff --git a/src/games/fallout3/src/fallout3savegameinfo.cpp b/src/games/fallout3/src/fallout3savegameinfo.cpp index 25142d04..a1401052 100644 --- a/src/games/fallout3/src/fallout3savegameinfo.cpp +++ b/src/games/fallout3/src/fallout3savegameinfo.cpp @@ -1,9 +1,14 @@ #include "fallout3savegameinfo.h" #include "fallout3savegame.h" +#include "gamegamebryo.h" -Fallout3SaveGameInfo::Fallout3SaveGameInfo(MOBase::IPluginGame const *game) : - m_Game(game) +Fallout3SaveGameInfo::Fallout3SaveGameInfo(GameGamebryo const *game) : + GamebryoSaveGameInfo(game) +{ +} + +Fallout3SaveGameInfo::~Fallout3SaveGameInfo() { } diff --git a/src/games/fallout3/src/fallout3savegameinfo.h b/src/games/fallout3/src/fallout3savegameinfo.h index 3d099ac2..d42d4746 100644 --- a/src/games/fallout3/src/fallout3savegameinfo.h +++ b/src/games/fallout3/src/fallout3savegameinfo.h @@ -1,17 +1,17 @@ #ifndef FALLOUT3SAVEGAMEINFO_H #define FALLOUT3SAVEGAMEINFO_H -#include "savegameinfo.h" +#include "gamebryosavegameinfo.h" -namespace MOBase { class IPluginGame; } +class GameGamebryo; -class Fallout3SaveGameInfo : public SaveGameInfo +class Fallout3SaveGameInfo : public GamebryoSaveGameInfo { public: - Fallout3SaveGameInfo(MOBase::IPluginGame const *game); + Fallout3SaveGameInfo(GameGamebryo const *game); + ~Fallout3SaveGameInfo(); + virtual MOBase::ISaveGame const *getSaveGameInfo(QString const &file) const override; -private: - MOBase::IPluginGame const* m_Game; }; #endif // FALLOUT3SAVEGAMEINFO_H From 8a987d01e0b27bfb4d180a9601ec469903732ec5 Mon Sep 17 00:00:00 2001 From: Thomas Tanner Date: Sat, 19 Dec 2015 20:46:14 +0000 Subject: [PATCH 0163/1544] [game_falloutnv] Changes to support getting list of mods / esps to activate from game plugin --- src/games/falloutnv/src/falloutnvsavegameinfo.cpp | 9 +++++++-- src/games/falloutnv/src/falloutnvsavegameinfo.h | 13 ++++++------- 2 files changed, 13 insertions(+), 9 deletions(-) diff --git a/src/games/falloutnv/src/falloutnvsavegameinfo.cpp b/src/games/falloutnv/src/falloutnvsavegameinfo.cpp index b79cf33a..830d5030 100644 --- a/src/games/falloutnv/src/falloutnvsavegameinfo.cpp +++ b/src/games/falloutnv/src/falloutnvsavegameinfo.cpp @@ -1,9 +1,14 @@ #include "falloutnvsavegameinfo.h" #include "falloutnvsavegame.h" +#include "gamegamebryo.h" -FalloutNVSaveGameInfo::FalloutNVSaveGameInfo(MOBase::IPluginGame const *game) : - m_Game(game) +FalloutNVSaveGameInfo::FalloutNVSaveGameInfo(GameGamebryo const *game) : + GamebryoSaveGameInfo(game) +{ +} + +FalloutNVSaveGameInfo::~FalloutNVSaveGameInfo() { } diff --git a/src/games/falloutnv/src/falloutnvsavegameinfo.h b/src/games/falloutnv/src/falloutnvsavegameinfo.h index cfe90d8f..6819e3e9 100644 --- a/src/games/falloutnv/src/falloutnvsavegameinfo.h +++ b/src/games/falloutnv/src/falloutnvsavegameinfo.h @@ -1,18 +1,17 @@ #ifndef FALLOUTNVSAVEGAMEINFO_H #define FALLOUTNVSAVEGAMEINFO_H -#include "savegameinfo.h" +#include "gamebryosavegameinfo.h" -namespace MOBase { class IPluginGame; } +class GameGamebryo; -class FalloutNVSaveGameInfo : public SaveGameInfo +class FalloutNVSaveGameInfo : public GamebryoSaveGameInfo { public: - FalloutNVSaveGameInfo(MOBase::IPluginGame const *game); - virtual MOBase::ISaveGame const *getSaveGameInfo(QString const &file) const override; + FalloutNVSaveGameInfo(GameGamebryo const *game); + ~FalloutNVSaveGameInfo(); -private: - MOBase::IPluginGame const* m_Game; + virtual MOBase::ISaveGame const *getSaveGameInfo(QString const &file) const override; }; #endif // FALLOUTNVSAVEGAMEINFO_H From 6da06503316985d92f55c978168d376b3f0bcdb0 Mon Sep 17 00:00:00 2001 From: Thomas Tanner Date: Sat, 19 Dec 2015 20:48:02 +0000 Subject: [PATCH 0164/1544] Changes to support getting list of mods / esps to activate from game plugin --- src/SConscript | 12 +++++- src/gameGamebryo.pro | 8 +++- src/gamebryosavegameinfo.cpp | 76 ++++++++++++++++++++++++++++++++++++ src/gamebryosavegameinfo.h | 20 ++++++++++ src/gamegamebryo.h | 5 ++- 5 files changed, 117 insertions(+), 4 deletions(-) create mode 100644 src/gamebryosavegameinfo.cpp create mode 100644 src/gamebryosavegameinfo.h diff --git a/src/SConscript b/src/SConscript index 3b96d894..2f8dc224 100644 --- a/src/SConscript +++ b/src/SConscript @@ -4,12 +4,22 @@ Import('qt_env') env = qt_env.Clone() +env.EnableQtModules('Widgets') + env.AppendUnique(CPPPATH = [ os.path.join('..', 'gamefeatures'), '${BOOSTPATH}' ]) -env.StaticLibrary('gameGamebryo', env.Glob('*.cpp')) +#env.AppendUnique(LIBS = [ +# 'advapi32', +# 'ole32', +# 'shell32', +# 'version' +#]) + +lib = env.StaticLibrary('gameGamebryo', env.Glob('*.cpp')) +#env.InstallModule(lib) res = env['QT_USED_MODULES'] Return('res') diff --git a/src/gameGamebryo.pro b/src/gameGamebryo.pro index 24e3c9dd..820128dd 100644 --- a/src/gameGamebryo.pro +++ b/src/gameGamebryo.pro @@ -8,19 +8,23 @@ TARGET = gameGamebryo TEMPLATE = lib CONFIG += staticlib +QT += widgets + SOURCES += gamegamebryo.cpp \ dummybsa.cpp \ gamebryobsainvalidation.cpp \ gamebryodataarchives.cpp \ gamebryoscriptextender.cpp \ - gamebryosavegame.cpp + gamebryosavegame.cpp \ + gamebryosavegameinfo.cpp HEADERS += gamegamebryo.h \ dummybsa.h \ gamebryobsainvalidation.h \ gamebryodataarchives.h \ gamebryoscriptextender.h \ - gamebryosavegame.h + gamebryosavegame.h \ + gamebryosavegameinfo.h include(../plugin_template.pri) diff --git a/src/gamebryosavegameinfo.cpp b/src/gamebryosavegameinfo.cpp new file mode 100644 index 00000000..edb1b708 --- /dev/null +++ b/src/gamebryosavegameinfo.cpp @@ -0,0 +1,76 @@ +#include "gamebryosavegameinfo.h" + +#include "gamebryosavegame.h" +#include "gamegamebryo.h" +#include "imodinterface.h" +#include "iplugingame.h" +#include "ipluginlist.h" + +#include + +GamebryoSaveGameInfo::GamebryoSaveGameInfo(GameGamebryo const *game) : + m_Game(game) +{ +} + +GamebryoSaveGameInfo::~GamebryoSaveGameInfo() +{ +} + +GamebryoSaveGameInfo::MissingAssets GamebryoSaveGameInfo::getMissingAssets(QString const &file) const +{ + GamebryoSaveGame const *save = dynamic_cast(getSaveGameInfo(file)); + MOBase::IOrganizer *organizerCore = m_Game->m_Organizer; + + // collect the list of missing plugins + MissingAssets missingAssets; + + for (QString const &pluginName : save->getPlugins()) { + if (organizerCore->pluginList()->state(pluginName) != MOBase::IPluginList::STATE_ACTIVE) { + missingAssets[pluginName] = ProvidingModules(); + } + } + + // figure out, for each esp/esm, which mod, if any, contains it + QStringList espFilter( { "*.esp", "*.esm" } ); + + // search in data. + //FIXME DO not search in data. + { + QDir dataDir(organizerCore->managedGame()->dataDirectory()); + QStringList esps = dataDir.entryList(espFilter); + for (const QString &esp : esps) { + MissingAssets::iterator iter = missingAssets.find(esp); + if (iter != missingAssets.end()) { + iter->push_back(""); + } + } + } + + //Search normal mods. A note: This will also find mods in data. + //FIXME Foreign mods should use the right name. + for (QString const &mod : organizerCore->modsSortedByProfilePriority()) { + MOBase::IModInterface *modInfo = organizerCore->getMod(mod); + QStringList esps = QDir(modInfo->absolutePath()).entryList(espFilter); + for (QString const &esp : esps) { + MissingAssets::iterator iter = missingAssets.find(esp); + if (iter != missingAssets.end()) { + iter->push_back(modInfo->name()); + } + } + } + + // search in overwrite + { + QDir overwriteDir(organizerCore->overwritePath()); + QStringList esps = overwriteDir.entryList(espFilter); + for (const QString &esp : esps) { + MissingAssets::iterator iter = missingAssets.find(esp); + if (iter != missingAssets.end()) { + iter->push_back(""); + } + } + } + + return missingAssets; +} diff --git a/src/gamebryosavegameinfo.h b/src/gamebryosavegameinfo.h new file mode 100644 index 00000000..401be6be --- /dev/null +++ b/src/gamebryosavegameinfo.h @@ -0,0 +1,20 @@ +#ifndef GAMEBRYOSAVEGAMEINFO_H +#define GAMEBRYOSAVEGAMEINFO_H + +#include "savegameinfo.h" + +class GameGamebryo; + +class GamebryoSaveGameInfo : public SaveGameInfo +{ +public: + GamebryoSaveGameInfo(GameGamebryo const *game); + ~GamebryoSaveGameInfo(); + + virtual MissingAssets getMissingAssets(QString const &file) const override; + +protected: + GameGamebryo const *m_Game; +}; + +#endif // GAMEBRYOSAVEGAMEINFO_H diff --git a/src/gamegamebryo.h b/src/gamegamebryo.h index f533d7cd..4d46fca9 100644 --- a/src/gamegamebryo.h +++ b/src/gamegamebryo.h @@ -20,6 +20,9 @@ class GameGamebryo : public MOBase::IPluginGame Q_OBJECT Q_INTERFACES(MOBase::IPlugin MOBase::IPluginGame) + friend class GamebryoScriptExtender; + friend class GamebryoSaveGameInfo; + public: GameGamebryo(); @@ -28,6 +31,7 @@ public: public: // IPluginGame interface + //getName //initializeProfile //savegameExtension virtual bool isInstalled() const override; @@ -64,7 +68,6 @@ protected: QString getLootPath() const; QString selectedVariant() const; virtual QString getLauncherName() const; - friend class GamebryoScriptExtender; QString getVersion(QString const &program) const; protected: From 23cf23b79134767fdda8ba088a3fb2094f504094 Mon Sep 17 00:00:00 2001 From: Thomas Tanner Date: Sat, 19 Dec 2015 20:48:16 +0000 Subject: [PATCH 0165/1544] [game_oblivion] Changes to support getting list of mods / esps to activate from game plugin --- src/games/oblivion/src/oblivionsavegameinfo.cpp | 9 +++++++-- src/games/oblivion/src/oblivionsavegameinfo.h | 11 +++++------ 2 files changed, 12 insertions(+), 8 deletions(-) diff --git a/src/games/oblivion/src/oblivionsavegameinfo.cpp b/src/games/oblivion/src/oblivionsavegameinfo.cpp index eaa93835..2fe16526 100644 --- a/src/games/oblivion/src/oblivionsavegameinfo.cpp +++ b/src/games/oblivion/src/oblivionsavegameinfo.cpp @@ -1,9 +1,14 @@ #include "oblivionsavegameinfo.h" #include "oblivionsavegame.h" +#include "gamegamebryo.h" -OblivionSaveGameInfo::OblivionSaveGameInfo(MOBase::IPluginGame const *game) : - m_Game(game) +OblivionSaveGameInfo::OblivionSaveGameInfo(GameGamebryo const *game) : + GamebryoSaveGameInfo(game) +{ +} + +OblivionSaveGameInfo::~OblivionSaveGameInfo() { } diff --git a/src/games/oblivion/src/oblivionsavegameinfo.h b/src/games/oblivion/src/oblivionsavegameinfo.h index 87f7f091..0639c756 100644 --- a/src/games/oblivion/src/oblivionsavegameinfo.h +++ b/src/games/oblivion/src/oblivionsavegameinfo.h @@ -1,18 +1,17 @@ #ifndef OBLIVIONSAVEGAMEINFO_H #define OBLIVIONSAVEGAMEINFO_H -#include "savegameinfo.h" +#include "gamebryosavegameinfo.h" -namespace MOBase { class IPluginGame; } +class GameGamebryo; -class OblivionSaveGameInfo : public SaveGameInfo +class OblivionSaveGameInfo : public GamebryoSaveGameInfo { public: - OblivionSaveGameInfo(MOBase::IPluginGame const *game); + OblivionSaveGameInfo(GameGamebryo const *game); + ~OblivionSaveGameInfo(); virtual MOBase::ISaveGame const *getSaveGameInfo(QString const &file) const override; -private: - MOBase::IPluginGame const* m_Game; }; #endif // OBLIVIONSAVEGAMEINFO_H From fd213591397b84b8cef3256d1845da919f48650c Mon Sep 17 00:00:00 2001 From: Thomas Tanner Date: Sat, 19 Dec 2015 20:48:49 +0000 Subject: [PATCH 0166/1544] [game_skyrim] Changes to support getting list of mods / esps to activate from game plugin --- src/games/skyrim/src/skyrimsavegameinfo.cpp | 9 +++++++-- src/games/skyrim/src/skyrimsavegameinfo.h | 13 ++++++------- 2 files changed, 13 insertions(+), 9 deletions(-) diff --git a/src/games/skyrim/src/skyrimsavegameinfo.cpp b/src/games/skyrim/src/skyrimsavegameinfo.cpp index 3801e29e..bd35aa0d 100644 --- a/src/games/skyrim/src/skyrimsavegameinfo.cpp +++ b/src/games/skyrim/src/skyrimsavegameinfo.cpp @@ -1,9 +1,14 @@ #include "skyrimsavegameinfo.h" #include "skyrimsavegame.h" +#include "gamegamebryo.h" -SkyrimSaveGameInfo::SkyrimSaveGameInfo(MOBase::IPluginGame const *game) : - m_Game(game) +SkyrimSaveGameInfo::SkyrimSaveGameInfo(GameGamebryo const *game) : + GamebryoSaveGameInfo(game) +{ +} + +SkyrimSaveGameInfo::~SkyrimSaveGameInfo() { } diff --git a/src/games/skyrim/src/skyrimsavegameinfo.h b/src/games/skyrim/src/skyrimsavegameinfo.h index 252dd978..fab45e5e 100644 --- a/src/games/skyrim/src/skyrimsavegameinfo.h +++ b/src/games/skyrim/src/skyrimsavegameinfo.h @@ -1,18 +1,17 @@ #ifndef SKYRIMSAVEGAMEINFO_H #define SKYRIMSAVEGAMEINFO_H -#include "savegameinfo.h" +#include "gamebryosavegameinfo.h" -namespace MOBase { class IPluginGame; } +class GameGamebryo; -class SkyrimSaveGameInfo : public SaveGameInfo +class SkyrimSaveGameInfo : public GamebryoSaveGameInfo { public: - SkyrimSaveGameInfo(MOBase::IPluginGame const *game); - virtual MOBase::ISaveGame const *getSaveGameInfo(QString const &file) const override; -private: - MOBase::IPluginGame const *m_Game; + SkyrimSaveGameInfo(GameGamebryo const *game); + ~SkyrimSaveGameInfo(); + virtual MOBase::ISaveGame const *getSaveGameInfo(QString const &file) const override; }; #endif // SKYRIMSAVEGAMEINFO_H From b22e4494991f676583bac37bd2b6d67d3c28a91f Mon Sep 17 00:00:00 2001 From: Thomas Tanner Date: Sun, 20 Dec 2015 21:07:46 +0000 Subject: [PATCH 0167/1544] Managed to remove SaveGame and SaveGameGamebryo classes from organizer --- src/gamebryosavegameinfo.cpp | 1 + 1 file changed, 1 insertion(+) diff --git a/src/gamebryosavegameinfo.cpp b/src/gamebryosavegameinfo.cpp index edb1b708..d8e12098 100644 --- a/src/gamebryosavegameinfo.cpp +++ b/src/gamebryosavegameinfo.cpp @@ -1,3 +1,4 @@ + #include "gamebryosavegameinfo.h" #include "gamebryosavegame.h" From 27541ca7be6381dde28447f4813d7f2799f95f7d Mon Sep 17 00:00:00 2001 From: Thomas Tanner Date: Sun, 20 Dec 2015 21:22:56 +0000 Subject: [PATCH 0168/1544] Rename the save game identifier method to make it clearer what it's for. --- src/gamebryosavegame.cpp | 2 +- src/gamebryosavegame.h | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/src/gamebryosavegame.cpp b/src/gamebryosavegame.cpp index bb6de525..6aa8370a 100644 --- a/src/gamebryosavegame.cpp +++ b/src/gamebryosavegame.cpp @@ -35,7 +35,7 @@ QDateTime GamebryoSaveGame::getCreationTime() const return m_CreationTime; } -QString GamebryoSaveGame::getIdentifier() const +QString GamebryoSaveGame::getSaveGroupIdentifier() const { return m_PCName; } diff --git a/src/gamebryosavegame.h b/src/gamebryosavegame.h index 4503659f..d5ec955e 100644 --- a/src/gamebryosavegame.h +++ b/src/gamebryosavegame.h @@ -27,7 +27,7 @@ public: virtual QDateTime getCreationTime() const override; - virtual QString getIdentifier() const override; + virtual QString getSaveGroupIdentifier() const override; virtual QStringList allFiles() const override; From 78b6cff861b08378bd023744d73c83d56496e021 Mon Sep 17 00:00:00 2001 From: Thomas Tanner Date: Fri, 25 Dec 2015 21:48:41 +0000 Subject: [PATCH 0169/1544] [game_fallout3] Transferring the savegame widget into gamebryo + some cleanup --- src/games/fallout3/src/fallout3savegame.cpp | 1 - 1 file changed, 1 deletion(-) diff --git a/src/games/fallout3/src/fallout3savegame.cpp b/src/games/fallout3/src/fallout3savegame.cpp index 663e3cf3..89bf0d5c 100644 --- a/src/games/fallout3/src/fallout3savegame.cpp +++ b/src/games/fallout3/src/fallout3savegame.cpp @@ -38,7 +38,6 @@ Fallout3SaveGame::Fallout3SaveGame(QString const &fileName, MOBase::IPluginGame file.skip(5); // unknown (1 byte), plugin size (4 bytes) - //Abstract this file.readPlugins(); } From 21c2e4b5dfa02f8c7c40ac42676bee377105d6ea Mon Sep 17 00:00:00 2001 From: Thomas Tanner Date: Fri, 25 Dec 2015 21:50:56 +0000 Subject: [PATCH 0170/1544] Transferring the savegame widget into gamebryo + some cleanup --- src/SConscript | 7 +- src/gameGamebryo.pro | 9 +- src/gamebryosavegameinfo.cpp | 8 +- src/gamebryosavegameinfo.h | 3 + src/gamebryosavegameinfowidget.cpp | 112 ++++++++++++++++ src/gamebryosavegameinfowidget.h | 28 ++++ src/gamebryosavegameinfowidget.ui | 209 +++++++++++++++++++++++++++++ src/gamegamebryo.cpp | 6 +- src/gamegamebryo.h | 1 + 9 files changed, 377 insertions(+), 6 deletions(-) create mode 100644 src/gamebryosavegameinfowidget.cpp create mode 100644 src/gamebryosavegameinfowidget.h create mode 100644 src/gamebryosavegameinfowidget.ui diff --git a/src/SConscript b/src/SConscript index 2f8dc224..c5db0034 100644 --- a/src/SConscript +++ b/src/SConscript @@ -6,10 +6,13 @@ env = qt_env.Clone() env.EnableQtModules('Widgets') -env.AppendUnique(CPPPATH = [ +env['CPPPATH'] += [ + '.', # Why is this necessary? os.path.join('..', 'gamefeatures'), '${BOOSTPATH}' -]) +] + +env.Uic(env.Glob('*.ui')) #env.AppendUnique(LIBS = [ # 'advapi32', diff --git a/src/gameGamebryo.pro b/src/gameGamebryo.pro index 820128dd..34513eb9 100644 --- a/src/gameGamebryo.pro +++ b/src/gameGamebryo.pro @@ -16,7 +16,8 @@ SOURCES += gamegamebryo.cpp \ gamebryodataarchives.cpp \ gamebryoscriptextender.cpp \ gamebryosavegame.cpp \ - gamebryosavegameinfo.cpp + gamebryosavegameinfo.cpp \ + gamebryosavegameinfowidget.cpp HEADERS += gamegamebryo.h \ dummybsa.h \ @@ -24,7 +25,8 @@ HEADERS += gamegamebryo.h \ gamebryodataarchives.h \ gamebryoscriptextender.h \ gamebryosavegame.h \ - gamebryosavegameinfo.h + gamebryosavegameinfo.h \ + gamebryosavegameinfowidget.h include(../plugin_template.pri) @@ -33,3 +35,6 @@ INCLUDEPATH += "$${BOOSTPATH}" "$${PWD}/../gamefeatures" OTHER_FILES +=\ SConscript \ CMakeLists.txt + +FORMS += \ + gamebryosavegameinfowidget.ui diff --git a/src/gamebryosavegameinfo.cpp b/src/gamebryosavegameinfo.cpp index d8e12098..651cce19 100644 --- a/src/gamebryosavegameinfo.cpp +++ b/src/gamebryosavegameinfo.cpp @@ -1,8 +1,9 @@ - #include "gamebryosavegameinfo.h" #include "gamebryosavegame.h" +#include "gamebryosavegameinfowidget.h" #include "gamegamebryo.h" +#include "imoinfo.h" #include "imodinterface.h" #include "iplugingame.h" #include "ipluginlist.h" @@ -75,3 +76,8 @@ GamebryoSaveGameInfo::MissingAssets GamebryoSaveGameInfo::getMissingAssets(QStri return missingAssets; } + +MOBase::ISaveGameInfoWidget *GamebryoSaveGameInfo::getSaveGameWidget(QWidget *parent) const +{ + return new GamebryoSaveGameInfoWidget(this, parent); +} diff --git a/src/gamebryosavegameinfo.h b/src/gamebryosavegameinfo.h index 401be6be..89c88e58 100644 --- a/src/gamebryosavegameinfo.h +++ b/src/gamebryosavegameinfo.h @@ -13,7 +13,10 @@ public: virtual MissingAssets getMissingAssets(QString const &file) const override; + virtual MOBase::ISaveGameInfoWidget *getSaveGameWidget(QWidget *) const override; + protected: + friend class GamebryoSaveGameInfoWidget; GameGamebryo const *m_Game; }; diff --git a/src/gamebryosavegameinfowidget.cpp b/src/gamebryosavegameinfowidget.cpp new file mode 100644 index 00000000..b7e326b8 --- /dev/null +++ b/src/gamebryosavegameinfowidget.cpp @@ -0,0 +1,112 @@ +#include "gamebryosavegameinfowidget.h" +#include "ui_gamebryosavegameinfowidget.h" + +#include "gamegamebryo.h" +#include "gamebryosavegame.h" +#include "gamebryosavegameinfo.h" +#include "imoinfo.h" +#include "ipluginlist.h" + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include + +#include + +GamebryoSaveGameInfoWidget::GamebryoSaveGameInfoWidget(GamebryoSaveGameInfo const *info, + QWidget *parent) + : MOBase::ISaveGameInfoWidget(parent) + , ui(new Ui::GamebryoSaveGameInfoWidget) + , m_Info(info) +{ + ui->setupUi(this); + this->setWindowFlags(Qt::ToolTip | Qt::BypassGraphicsProxyWidget); + setWindowOpacity(style()->styleHint(QStyle::SH_ToolTipLabel_Opacity, 0, this) / qreal(255.0)); + ui->gameFrame->setStyleSheet("background-color: transparent;"); + + QVBoxLayout *gameLayout = new QVBoxLayout(); + gameLayout->setMargin(0); + gameLayout->setSpacing(2); + ui->gameFrame->setLayout(gameLayout); +} + +GamebryoSaveGameInfoWidget::~GamebryoSaveGameInfoWidget() +{ + delete ui; +} + +void GamebryoSaveGameInfoWidget::setSave(QString const &file) +{ + std::unique_ptr save( + std::move(dynamic_cast(m_Info->getSaveGameInfo(file)))); + ui->saveNumLabel->setText(QString("%1").arg(save->getSaveNumber())); + ui->characterLabel->setText(save->getPCName()); + ui->locationLabel->setText(save->getPCLocation()); + ui->levelLabel->setText(QString("%1").arg(save->getPCLevel())); + //This somewhat contorted code is because on my system at least, the + //old way of doing this appears to give short date and long time. + QDateTime t = save->getCreationTime(); + ui->dateLabel->setText(t.date().toString(Qt::DefaultLocaleShortDate) + " " + + t.time().toString(Qt::DefaultLocaleLongDate)); + ui->screenshotLabel->setPixmap(QPixmap::fromImage(save->getScreenshot())); + if (ui->gameFrame->layout() != nullptr) { + QLayoutItem *item = nullptr; + while ((item = ui->gameFrame->layout()->takeAt(0)) != nullptr) { + delete item->widget(); + delete item; + } + ui->gameFrame->layout()->setSizeConstraint(QLayout::SetFixedSize); + } + + QLayout *layout = ui->gameFrame->layout(); + QLabel *header = new QLabel(tr("Missing ESPs")); + QFont headerFont = header->font(); + QFont contentFont = headerFont; + headerFont.setItalic(true); + contentFont.setBold(true); + contentFont.setPointSize(7); + header->setFont(headerFont); + layout->addWidget(header); + int count = 0; + MOBase::IPluginList *pluginList = m_Info->m_Game->m_Organizer->pluginList(); + for (QString const &pluginName : save->getPlugins()) { + if (pluginList->state(pluginName) == MOBase::IPluginList::STATE_ACTIVE) { + continue; + } + + ++count; + + if (count > 10) { + break; + } + + QLabel *pluginLabel = new QLabel(pluginName); + pluginLabel->setIndent(10); + pluginLabel->setFont(contentFont); + layout->addWidget(pluginLabel); + } + if (count > 10) { + QLabel *dotDotLabel = new QLabel("..."); + dotDotLabel->setIndent(10); + dotDotLabel->setFont(contentFont); + layout->addWidget(dotDotLabel); + } + if (count == 0) { + QLabel *dotDotLabel = new QLabel(tr("None")); + dotDotLabel->setIndent(10); + dotDotLabel->setFont(contentFont); + layout->addWidget(dotDotLabel); + } +} diff --git a/src/gamebryosavegameinfowidget.h b/src/gamebryosavegameinfowidget.h new file mode 100644 index 00000000..056b9464 --- /dev/null +++ b/src/gamebryosavegameinfowidget.h @@ -0,0 +1,28 @@ +#ifndef GAMEBRYOSAVEGAMEINFOWIDGET_H +#define GAMEBRYOSAVEGAMEINFOWIDGET_H + +#include "isavegameinfowidget.h" + +#include + +class GamebryoSaveGameInfo; + +namespace Ui { class GamebryoSaveGameInfoWidget; } + +class GamebryoSaveGameInfoWidget : public MOBase::ISaveGameInfoWidget +{ + Q_OBJECT + +public: + GamebryoSaveGameInfoWidget(GamebryoSaveGameInfo const *info, + QWidget *parent); + ~GamebryoSaveGameInfoWidget(); + + virtual void setSave(QString const &) override; + +private: + Ui::GamebryoSaveGameInfoWidget *ui; + GamebryoSaveGameInfo const *m_Info; +}; + +#endif // GAMEBRYOSAVEGAMEINFOWIDGET_H diff --git a/src/gamebryosavegameinfowidget.ui b/src/gamebryosavegameinfowidget.ui new file mode 100644 index 00000000..ea45d108 --- /dev/null +++ b/src/gamebryosavegameinfowidget.ui @@ -0,0 +1,209 @@ + + + GamebryoSaveGameInfoWidget + + + + 0 + 0 + 400 + 300 + + + + + 0 + 0 + + + + + + + + + + + + + QFormLayout::AllNonFixedFieldsGrow + + + + + + true + + + + Save # + + + + + + + + true + + + + Character + + + + + + + + true + + + + Level + + + + + + + + true + + + + Location + + + + + + + + true + + + + Date + + + + + + + + 75 + true + + + + + + + + + + + + 75 + true + + + + + + + + + + + + 75 + true + + + + + + + + + + + + 75 + true + + + + + + + + + + + + 75 + true + + + + + + + + + + + + + + 0 + 0 + + + + + 0 + 0 + + + + QFrame::StyledPanel + + + QFrame::Raised + + + + + + + + 0 + 0 + + + + + 16777215 + 16777215 + + + + false + + + + + + Qt::AlignCenter + + + + + + + + diff --git a/src/gamegamebryo.cpp b/src/gamegamebryo.cpp index ac99a4c3..1f4d211b 100644 --- a/src/gamegamebryo.cpp +++ b/src/gamegamebryo.cpp @@ -7,10 +7,14 @@ #include "scopeguard.h" #include "utility.h" -#include +#include + +#include #include +#include + GameGamebryo::GameGamebryo() { } diff --git a/src/gamegamebryo.h b/src/gamegamebryo.h index 4d46fca9..c17becc8 100644 --- a/src/gamegamebryo.h +++ b/src/gamegamebryo.h @@ -22,6 +22,7 @@ class GameGamebryo : public MOBase::IPluginGame friend class GamebryoScriptExtender; friend class GamebryoSaveGameInfo; + friend class GamebryoSaveGameInfoWidget; public: From dd8820c5eabc24537ac2ac7c15e581a2da563099 Mon Sep 17 00:00:00 2001 From: Thomas Tanner Date: Fri, 25 Dec 2015 21:55:54 +0000 Subject: [PATCH 0171/1544] [game_falloutnv] Transferring the savegame widget into gamebryo + some cleanup --- src/games/falloutnv/src/gamefalloutnv.cpp | 3 +++ 1 file changed, 3 insertions(+) diff --git a/src/games/falloutnv/src/gamefalloutnv.cpp b/src/games/falloutnv/src/gamefalloutnv.cpp index 8e777b3c..cc836219 100644 --- a/src/games/falloutnv/src/gamefalloutnv.cpp +++ b/src/games/falloutnv/src/gamefalloutnv.cpp @@ -14,9 +14,12 @@ #include #include #include +#include #include #include +#include + #include using namespace MOBase; From 60365c1bcdf07053599471661d787fd5c5e23372 Mon Sep 17 00:00:00 2001 From: Thomas Tanner Date: Fri, 25 Dec 2015 21:56:17 +0000 Subject: [PATCH 0172/1544] [game_oblivion] Transferring the savegame widget into gamebryo + some cleanup --- src/games/oblivion/src/gameoblivion.h | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/src/games/oblivion/src/gameoblivion.h b/src/games/oblivion/src/gameoblivion.h index 7d853de3..07eb0701 100644 --- a/src/games/oblivion/src/gameoblivion.h +++ b/src/games/oblivion/src/gameoblivion.h @@ -3,6 +3,13 @@ #include "gamegamebryo.h" +#include +#include + +#include + +class QDir; + class GameOblivion : public GameGamebryo { Q_OBJECT From 0d2d0db8bfa45b9289cf63ad9c15d13e405adc40 Mon Sep 17 00:00:00 2001 From: Thomas Tanner Date: Fri, 25 Dec 2015 21:56:33 +0000 Subject: [PATCH 0173/1544] [game_skyrim] Transferring the savegame widget into gamebryo + some cleanup --- src/games/skyrim/src/skyrimsavegameinfo.cpp | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/src/games/skyrim/src/skyrimsavegameinfo.cpp b/src/games/skyrim/src/skyrimsavegameinfo.cpp index bd35aa0d..558b83b9 100644 --- a/src/games/skyrim/src/skyrimsavegameinfo.cpp +++ b/src/games/skyrim/src/skyrimsavegameinfo.cpp @@ -13,8 +13,7 @@ SkyrimSaveGameInfo::~SkyrimSaveGameInfo() } -MOBase::ISaveGame const *SkyrimSaveGameInfo::getSaveGameInfo(const QString &file) const +MOBase::ISaveGame const *SkyrimSaveGameInfo::getSaveGameInfo(QString const &file) const { return new SkyrimSaveGame(file, m_Game); } - From 1cf46fd01c606774a6cb2278522829bc9fce7b8c Mon Sep 17 00:00:00 2001 From: Thomas Tanner Date: Sat, 26 Dec 2015 08:24:18 +0000 Subject: [PATCH 0174/1544] tidyup --- src/gamebryosavegameinfowidget.h | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/src/gamebryosavegameinfowidget.h b/src/gamebryosavegameinfowidget.h index 056b9464..387d4865 100644 --- a/src/gamebryosavegameinfowidget.h +++ b/src/gamebryosavegameinfowidget.h @@ -14,8 +14,7 @@ class GamebryoSaveGameInfoWidget : public MOBase::ISaveGameInfoWidget Q_OBJECT public: - GamebryoSaveGameInfoWidget(GamebryoSaveGameInfo const *info, - QWidget *parent); + GamebryoSaveGameInfoWidget(GamebryoSaveGameInfo const *info, QWidget *parent); ~GamebryoSaveGameInfoWidget(); virtual void setSave(QString const &) override; From b4860895a593d6e76d8556d3f333df0448f313dc Mon Sep 17 00:00:00 2001 From: Thomas Tanner Date: Sat, 26 Dec 2015 10:19:13 +0000 Subject: [PATCH 0175/1544] Fix up the issue with mod selection for unmanaged mods. --- src/gamebryosavegameinfo.cpp | 43 +++++++++++++++++++++--------------- 1 file changed, 25 insertions(+), 18 deletions(-) diff --git a/src/gamebryosavegameinfo.cpp b/src/gamebryosavegameinfo.cpp index 651cce19..518de909 100644 --- a/src/gamebryosavegameinfo.cpp +++ b/src/gamebryosavegameinfo.cpp @@ -9,6 +9,8 @@ #include "ipluginlist.h" #include +#include +#include GamebryoSaveGameInfo::GamebryoSaveGameInfo(GameGamebryo const *game) : m_Game(game) @@ -28,36 +30,39 @@ GamebryoSaveGameInfo::MissingAssets GamebryoSaveGameInfo::getMissingAssets(QStri MissingAssets missingAssets; for (QString const &pluginName : save->getPlugins()) { - if (organizerCore->pluginList()->state(pluginName) != MOBase::IPluginList::STATE_ACTIVE) { - missingAssets[pluginName] = ProvidingModules(); + switch (organizerCore->pluginList()->state(pluginName)) { + case MOBase::IPluginList::STATE_INACTIVE: + missingAssets[pluginName] = ProvidingModules { organizerCore->pluginList()->origin(pluginName) }; + break; + case MOBase::IPluginList::STATE_MISSING: + missingAssets[pluginName] = ProvidingModules(); + break; } } - // figure out, for each esp/esm, which mod, if any, contains it + //Find out any other mods that might contain the esp/esm QStringList espFilter( { "*.esp", "*.esm" } ); - // search in data. - //FIXME DO not search in data. - { - QDir dataDir(organizerCore->managedGame()->dataDirectory()); - QStringList esps = dataDir.entryList(espFilter); - for (const QString &esp : esps) { - MissingAssets::iterator iter = missingAssets.find(esp); - if (iter != missingAssets.end()) { - iter->push_back(""); - } - } - } + QString dataDir(organizerCore->managedGame()->dataDirectory().absolutePath()); //Search normal mods. A note: This will also find mods in data. - //FIXME Foreign mods should use the right name. for (QString const &mod : organizerCore->modsSortedByProfilePriority()) { MOBase::IModInterface *modInfo = organizerCore->getMod(mod); QStringList esps = QDir(modInfo->absolutePath()).entryList(espFilter); for (QString const &esp : esps) { MissingAssets::iterator iter = missingAssets.find(esp); + if (modInfo->absolutePath() == dataDir) { + //We have to prune esps that reside in the data directory, otherwise + //you get all the unmanaged mods listed as potential candidates for + //enabling + if (modInfo->name() != organizerCore->pluginList()->origin(esp)) { + continue; + } + } if (iter != missingAssets.end()) { - iter->push_back(modInfo->name()); + if (!iter->contains(modInfo->name())) { + iter->push_back(modInfo->name()); + } } } } @@ -69,7 +74,9 @@ GamebryoSaveGameInfo::MissingAssets GamebryoSaveGameInfo::getMissingAssets(QStri for (const QString &esp : esps) { MissingAssets::iterator iter = missingAssets.find(esp); if (iter != missingAssets.end()) { - iter->push_back(""); + if (!iter->contains("")) { + iter->push_back(""); + } } } } From a17a537157f04a55d1230d61bff76fa73559e8b0 Mon Sep 17 00:00:00 2001 From: Thomas Tanner Date: Sat, 26 Dec 2015 14:25:46 +0000 Subject: [PATCH 0176/1544] [game_skyrim] Abstract out localAppfolder() --- src/games/skyrim/src/gameskyrim.cpp | 11 ----------- src/games/skyrim/src/gameskyrim.h | 1 - 2 files changed, 12 deletions(-) diff --git a/src/games/skyrim/src/gameskyrim.cpp b/src/games/skyrim/src/gameskyrim.cpp index 3054e237..c712e7ea 100644 --- a/src/games/skyrim/src/gameskyrim.cpp +++ b/src/games/skyrim/src/gameskyrim.cpp @@ -53,17 +53,6 @@ QString GameSkyrim::gameName() const return "Skyrim"; } -QString GameSkyrim::localAppFolder() const -{ - QString result = getKnownFolderPath(FOLDERID_LocalAppData, false); - if (result.isEmpty()) { - // fallback: try the registry - result = getSpecialPath("Local AppData"); - } - - return result; -} - QString GameSkyrim::myGamesFolderName() const { return "Skyrim"; diff --git a/src/games/skyrim/src/gameskyrim.h b/src/games/skyrim/src/gameskyrim.h index 9d8fc066..ed8bef6f 100644 --- a/src/games/skyrim/src/gameskyrim.h +++ b/src/games/skyrim/src/gameskyrim.h @@ -46,7 +46,6 @@ private: virtual QString identifyGamePath() const override; virtual QString myGamesFolderName() const override; - QString localAppFolder() const; void copyToProfile(const QString &sourcePath, const QDir &destinationDirectory, const QString &sourceFileName, const QString &destinationFileName = QString()) const; From 67e042fe58dec5638f5bc08d2ad6d3225f2560e1 Mon Sep 17 00:00:00 2001 From: Thomas Tanner Date: Sat, 26 Dec 2015 14:26:16 +0000 Subject: [PATCH 0177/1544] [game_fallout4vr] Make it compile. WARNING: Some headers are missing. --- src/games/fallout4vr/src/fallout4savegame.cpp | 4 ++-- src/games/fallout4vr/src/fallout4savegame.h | 4 +++- src/games/fallout4vr/src/fallout4savegameinfo.cpp | 12 +++++++++++- src/games/fallout4vr/src/fallout4savegameinfo.h | 9 +++++++-- src/games/fallout4vr/src/gameFallout4.pro | 8 ++++++-- src/games/fallout4vr/src/gamefallout4.cpp | 7 ++++--- 6 files changed, 33 insertions(+), 11 deletions(-) diff --git a/src/games/fallout4vr/src/fallout4savegame.cpp b/src/games/fallout4vr/src/fallout4savegame.cpp index 33b807ef..063eb5c7 100644 --- a/src/games/fallout4vr/src/fallout4savegame.cpp +++ b/src/games/fallout4vr/src/fallout4savegame.cpp @@ -2,8 +2,8 @@ #include -Fallout4SaveGame::Fallout4SaveGame(QString const &fileName) : - GamebryoSaveGame(fileName) +Fallout4SaveGame::Fallout4SaveGame(QString const &fileName, MOBase::IPluginGame const *game) : + GamebryoSaveGame(fileName, game) { FileWrapper file(this, "FO4_SAVEGAME"); file.skip(); // header size diff --git a/src/games/fallout4vr/src/fallout4savegame.h b/src/games/fallout4vr/src/fallout4savegame.h index 6c89b5bb..d5d47e82 100644 --- a/src/games/fallout4vr/src/fallout4savegame.h +++ b/src/games/fallout4vr/src/fallout4savegame.h @@ -3,10 +3,12 @@ #include "gamebryosavegame.h" +namespace MOBase { class IPluginGame; } + class Fallout4SaveGame : public GamebryoSaveGame { public: - Fallout4SaveGame(QString const &fileName); + Fallout4SaveGame(QString const &fileName, MOBase::IPluginGame const *game); }; #endif // FALLOUT4SAVEGAME_H diff --git a/src/games/fallout4vr/src/fallout4savegameinfo.cpp b/src/games/fallout4vr/src/fallout4savegameinfo.cpp index b2c60144..22856d86 100644 --- a/src/games/fallout4vr/src/fallout4savegameinfo.cpp +++ b/src/games/fallout4vr/src/fallout4savegameinfo.cpp @@ -1,9 +1,19 @@ #include "fallout4savegameinfo.h" #include "fallout4savegame.h" +#include "gamegamebryo.h" + +Fallout4SaveGameInfo::Fallout4SaveGameInfo(GameGamebryo const *game) : + GamebryoSaveGameInfo(game) +{ +} + +Fallout4SaveGameInfo::~Fallout4SaveGameInfo() +{ +} const MOBase::ISaveGame *Fallout4SaveGameInfo::getSaveGameInfo(const QString &file) const { - return new Fallout4SaveGame(file); + return new Fallout4SaveGame(file, m_Game); } diff --git a/src/games/fallout4vr/src/fallout4savegameinfo.h b/src/games/fallout4vr/src/fallout4savegameinfo.h index 68d8626e..c36ec6f4 100644 --- a/src/games/fallout4vr/src/fallout4savegameinfo.h +++ b/src/games/fallout4vr/src/fallout4savegameinfo.h @@ -1,11 +1,16 @@ #ifndef SKYRIMSAVEGAMEINFO_H #define SKYRIMSAVEGAMEINFO_H -#include "savegameinfo.h" +#include "gamebryosavegameinfo.h" -class Fallout4SaveGameInfo : public SaveGameInfo +class GameGamebryo; + +class Fallout4SaveGameInfo : public GamebryoSaveGameInfo { public: + Fallout4SaveGameInfo(GameGamebryo const *game); + ~Fallout4SaveGameInfo(); + virtual MOBase::ISaveGame const *getSaveGameInfo(QString const &file) const override; }; diff --git a/src/games/fallout4vr/src/gameFallout4.pro b/src/games/fallout4vr/src/gameFallout4.pro index e34a6a67..f78bc45f 100644 --- a/src/games/fallout4vr/src/gameFallout4.pro +++ b/src/games/fallout4vr/src/gameFallout4.pro @@ -16,12 +16,16 @@ DEFINES += GAMEFALLOUT4_LIBRARY SOURCES += gamefallout4.cpp \ fallout4bsainvalidation.cpp \ fallout4scriptextender.cpp \ - fallout4dataarchives.cpp + fallout4dataarchives.cpp \ + fallout4savegame.cpp \ + fallout4savegameinfo.cpp HEADERS += gamefallout4.h \ fallout4bsainvalidation.h \ fallout4scriptextender.h \ - fallout4dataarchives.h + fallout4dataarchives.h \ + fallout4savegame.h \ + fallout4savegameinfo.h CONFIG(debug, debug|release) { LIBS += -L"$${OUT_PWD}/../gameGamebryo/debug" diff --git a/src/games/fallout4vr/src/gamefallout4.cpp b/src/games/fallout4vr/src/gamefallout4.cpp index 8482df89..62068b2b 100644 --- a/src/games/fallout4vr/src/gamefallout4.cpp +++ b/src/games/fallout4vr/src/gamefallout4.cpp @@ -7,7 +7,7 @@ #include #include "iplugingame.h" #include -#include +//#include #include #include @@ -30,8 +30,8 @@ bool GameFallout4::init(IOrganizer *moInfo) } m_ScriptExtender = std::shared_ptr(new Fallout4ScriptExtender(this)); m_DataArchives = std::shared_ptr(new Fallout4DataArchives()); - m_LocalSavegames.reset(new GamebryoLocalSavegames(myGamesPath(), "Fallout4.ini")); - m_SaveGameInfo = std::shared_ptr(new Fallout4SaveGameInfo()); +// m_LocalSavegames.reset(new GamebryoLocalSavegames(myGamesPath(), "Fallout4.ini")); + m_SaveGameInfo = std::shared_ptr(new Fallout4SaveGameInfo(this)); return true; } @@ -45,6 +45,7 @@ QString GameFallout4::gameName() const return "Fallout 4"; } + QString GameFallout4::myGamesFolderName() const { return "Fallout4"; From a0d4d27da7a8787f14ebe70b668cafd7c37676fe Mon Sep 17 00:00:00 2001 From: Thomas Tanner Date: Sat, 26 Dec 2015 14:26:16 +0000 Subject: [PATCH 0178/1544] [game_fallout76] Make it compile. WARNING: Some headers are missing. --- src/games/fallout76/src/fallout4savegame.cpp | 4 ++-- src/games/fallout76/src/fallout4savegame.h | 4 +++- src/games/fallout76/src/fallout4savegameinfo.cpp | 12 +++++++++++- src/games/fallout76/src/fallout4savegameinfo.h | 9 +++++++-- src/games/fallout76/src/gameFallout4.pro | 8 ++++++-- src/games/fallout76/src/gamefallout4.cpp | 7 ++++--- 6 files changed, 33 insertions(+), 11 deletions(-) diff --git a/src/games/fallout76/src/fallout4savegame.cpp b/src/games/fallout76/src/fallout4savegame.cpp index 33b807ef..063eb5c7 100644 --- a/src/games/fallout76/src/fallout4savegame.cpp +++ b/src/games/fallout76/src/fallout4savegame.cpp @@ -2,8 +2,8 @@ #include -Fallout4SaveGame::Fallout4SaveGame(QString const &fileName) : - GamebryoSaveGame(fileName) +Fallout4SaveGame::Fallout4SaveGame(QString const &fileName, MOBase::IPluginGame const *game) : + GamebryoSaveGame(fileName, game) { FileWrapper file(this, "FO4_SAVEGAME"); file.skip(); // header size diff --git a/src/games/fallout76/src/fallout4savegame.h b/src/games/fallout76/src/fallout4savegame.h index 6c89b5bb..d5d47e82 100644 --- a/src/games/fallout76/src/fallout4savegame.h +++ b/src/games/fallout76/src/fallout4savegame.h @@ -3,10 +3,12 @@ #include "gamebryosavegame.h" +namespace MOBase { class IPluginGame; } + class Fallout4SaveGame : public GamebryoSaveGame { public: - Fallout4SaveGame(QString const &fileName); + Fallout4SaveGame(QString const &fileName, MOBase::IPluginGame const *game); }; #endif // FALLOUT4SAVEGAME_H diff --git a/src/games/fallout76/src/fallout4savegameinfo.cpp b/src/games/fallout76/src/fallout4savegameinfo.cpp index b2c60144..22856d86 100644 --- a/src/games/fallout76/src/fallout4savegameinfo.cpp +++ b/src/games/fallout76/src/fallout4savegameinfo.cpp @@ -1,9 +1,19 @@ #include "fallout4savegameinfo.h" #include "fallout4savegame.h" +#include "gamegamebryo.h" + +Fallout4SaveGameInfo::Fallout4SaveGameInfo(GameGamebryo const *game) : + GamebryoSaveGameInfo(game) +{ +} + +Fallout4SaveGameInfo::~Fallout4SaveGameInfo() +{ +} const MOBase::ISaveGame *Fallout4SaveGameInfo::getSaveGameInfo(const QString &file) const { - return new Fallout4SaveGame(file); + return new Fallout4SaveGame(file, m_Game); } diff --git a/src/games/fallout76/src/fallout4savegameinfo.h b/src/games/fallout76/src/fallout4savegameinfo.h index 68d8626e..c36ec6f4 100644 --- a/src/games/fallout76/src/fallout4savegameinfo.h +++ b/src/games/fallout76/src/fallout4savegameinfo.h @@ -1,11 +1,16 @@ #ifndef SKYRIMSAVEGAMEINFO_H #define SKYRIMSAVEGAMEINFO_H -#include "savegameinfo.h" +#include "gamebryosavegameinfo.h" -class Fallout4SaveGameInfo : public SaveGameInfo +class GameGamebryo; + +class Fallout4SaveGameInfo : public GamebryoSaveGameInfo { public: + Fallout4SaveGameInfo(GameGamebryo const *game); + ~Fallout4SaveGameInfo(); + virtual MOBase::ISaveGame const *getSaveGameInfo(QString const &file) const override; }; diff --git a/src/games/fallout76/src/gameFallout4.pro b/src/games/fallout76/src/gameFallout4.pro index e34a6a67..f78bc45f 100644 --- a/src/games/fallout76/src/gameFallout4.pro +++ b/src/games/fallout76/src/gameFallout4.pro @@ -16,12 +16,16 @@ DEFINES += GAMEFALLOUT4_LIBRARY SOURCES += gamefallout4.cpp \ fallout4bsainvalidation.cpp \ fallout4scriptextender.cpp \ - fallout4dataarchives.cpp + fallout4dataarchives.cpp \ + fallout4savegame.cpp \ + fallout4savegameinfo.cpp HEADERS += gamefallout4.h \ fallout4bsainvalidation.h \ fallout4scriptextender.h \ - fallout4dataarchives.h + fallout4dataarchives.h \ + fallout4savegame.h \ + fallout4savegameinfo.h CONFIG(debug, debug|release) { LIBS += -L"$${OUT_PWD}/../gameGamebryo/debug" diff --git a/src/games/fallout76/src/gamefallout4.cpp b/src/games/fallout76/src/gamefallout4.cpp index 8482df89..62068b2b 100644 --- a/src/games/fallout76/src/gamefallout4.cpp +++ b/src/games/fallout76/src/gamefallout4.cpp @@ -7,7 +7,7 @@ #include #include "iplugingame.h" #include -#include +//#include #include #include @@ -30,8 +30,8 @@ bool GameFallout4::init(IOrganizer *moInfo) } m_ScriptExtender = std::shared_ptr(new Fallout4ScriptExtender(this)); m_DataArchives = std::shared_ptr(new Fallout4DataArchives()); - m_LocalSavegames.reset(new GamebryoLocalSavegames(myGamesPath(), "Fallout4.ini")); - m_SaveGameInfo = std::shared_ptr(new Fallout4SaveGameInfo()); +// m_LocalSavegames.reset(new GamebryoLocalSavegames(myGamesPath(), "Fallout4.ini")); + m_SaveGameInfo = std::shared_ptr(new Fallout4SaveGameInfo(this)); return true; } @@ -45,6 +45,7 @@ QString GameFallout4::gameName() const return "Fallout 4"; } + QString GameFallout4::myGamesFolderName() const { return "Fallout4"; From 5368a8f193ec1606ffefb5fc1c61af7a0ebeb206 Mon Sep 17 00:00:00 2001 From: Thomas Tanner Date: Sat, 26 Dec 2015 14:26:16 +0000 Subject: [PATCH 0179/1544] [game_fallout4] Make it compile. WARNING: Some headers are missing. --- src/games/fallout4/src/fallout4savegame.cpp | 4 ++-- src/games/fallout4/src/fallout4savegame.h | 4 +++- src/games/fallout4/src/fallout4savegameinfo.cpp | 12 +++++++++++- src/games/fallout4/src/fallout4savegameinfo.h | 9 +++++++-- src/games/fallout4/src/gameFallout4.pro | 8 ++++++-- src/games/fallout4/src/gamefallout4.cpp | 7 ++++--- 6 files changed, 33 insertions(+), 11 deletions(-) diff --git a/src/games/fallout4/src/fallout4savegame.cpp b/src/games/fallout4/src/fallout4savegame.cpp index 33b807ef..063eb5c7 100644 --- a/src/games/fallout4/src/fallout4savegame.cpp +++ b/src/games/fallout4/src/fallout4savegame.cpp @@ -2,8 +2,8 @@ #include -Fallout4SaveGame::Fallout4SaveGame(QString const &fileName) : - GamebryoSaveGame(fileName) +Fallout4SaveGame::Fallout4SaveGame(QString const &fileName, MOBase::IPluginGame const *game) : + GamebryoSaveGame(fileName, game) { FileWrapper file(this, "FO4_SAVEGAME"); file.skip(); // header size diff --git a/src/games/fallout4/src/fallout4savegame.h b/src/games/fallout4/src/fallout4savegame.h index 6c89b5bb..d5d47e82 100644 --- a/src/games/fallout4/src/fallout4savegame.h +++ b/src/games/fallout4/src/fallout4savegame.h @@ -3,10 +3,12 @@ #include "gamebryosavegame.h" +namespace MOBase { class IPluginGame; } + class Fallout4SaveGame : public GamebryoSaveGame { public: - Fallout4SaveGame(QString const &fileName); + Fallout4SaveGame(QString const &fileName, MOBase::IPluginGame const *game); }; #endif // FALLOUT4SAVEGAME_H diff --git a/src/games/fallout4/src/fallout4savegameinfo.cpp b/src/games/fallout4/src/fallout4savegameinfo.cpp index b2c60144..22856d86 100644 --- a/src/games/fallout4/src/fallout4savegameinfo.cpp +++ b/src/games/fallout4/src/fallout4savegameinfo.cpp @@ -1,9 +1,19 @@ #include "fallout4savegameinfo.h" #include "fallout4savegame.h" +#include "gamegamebryo.h" + +Fallout4SaveGameInfo::Fallout4SaveGameInfo(GameGamebryo const *game) : + GamebryoSaveGameInfo(game) +{ +} + +Fallout4SaveGameInfo::~Fallout4SaveGameInfo() +{ +} const MOBase::ISaveGame *Fallout4SaveGameInfo::getSaveGameInfo(const QString &file) const { - return new Fallout4SaveGame(file); + return new Fallout4SaveGame(file, m_Game); } diff --git a/src/games/fallout4/src/fallout4savegameinfo.h b/src/games/fallout4/src/fallout4savegameinfo.h index 68d8626e..c36ec6f4 100644 --- a/src/games/fallout4/src/fallout4savegameinfo.h +++ b/src/games/fallout4/src/fallout4savegameinfo.h @@ -1,11 +1,16 @@ #ifndef SKYRIMSAVEGAMEINFO_H #define SKYRIMSAVEGAMEINFO_H -#include "savegameinfo.h" +#include "gamebryosavegameinfo.h" -class Fallout4SaveGameInfo : public SaveGameInfo +class GameGamebryo; + +class Fallout4SaveGameInfo : public GamebryoSaveGameInfo { public: + Fallout4SaveGameInfo(GameGamebryo const *game); + ~Fallout4SaveGameInfo(); + virtual MOBase::ISaveGame const *getSaveGameInfo(QString const &file) const override; }; diff --git a/src/games/fallout4/src/gameFallout4.pro b/src/games/fallout4/src/gameFallout4.pro index e34a6a67..f78bc45f 100644 --- a/src/games/fallout4/src/gameFallout4.pro +++ b/src/games/fallout4/src/gameFallout4.pro @@ -16,12 +16,16 @@ DEFINES += GAMEFALLOUT4_LIBRARY SOURCES += gamefallout4.cpp \ fallout4bsainvalidation.cpp \ fallout4scriptextender.cpp \ - fallout4dataarchives.cpp + fallout4dataarchives.cpp \ + fallout4savegame.cpp \ + fallout4savegameinfo.cpp HEADERS += gamefallout4.h \ fallout4bsainvalidation.h \ fallout4scriptextender.h \ - fallout4dataarchives.h + fallout4dataarchives.h \ + fallout4savegame.h \ + fallout4savegameinfo.h CONFIG(debug, debug|release) { LIBS += -L"$${OUT_PWD}/../gameGamebryo/debug" diff --git a/src/games/fallout4/src/gamefallout4.cpp b/src/games/fallout4/src/gamefallout4.cpp index 8482df89..62068b2b 100644 --- a/src/games/fallout4/src/gamefallout4.cpp +++ b/src/games/fallout4/src/gamefallout4.cpp @@ -7,7 +7,7 @@ #include #include "iplugingame.h" #include -#include +//#include #include #include @@ -30,8 +30,8 @@ bool GameFallout4::init(IOrganizer *moInfo) } m_ScriptExtender = std::shared_ptr(new Fallout4ScriptExtender(this)); m_DataArchives = std::shared_ptr(new Fallout4DataArchives()); - m_LocalSavegames.reset(new GamebryoLocalSavegames(myGamesPath(), "Fallout4.ini")); - m_SaveGameInfo = std::shared_ptr(new Fallout4SaveGameInfo()); +// m_LocalSavegames.reset(new GamebryoLocalSavegames(myGamesPath(), "Fallout4.ini")); + m_SaveGameInfo = std::shared_ptr(new Fallout4SaveGameInfo(this)); return true; } @@ -45,6 +45,7 @@ QString GameFallout4::gameName() const return "Fallout 4"; } + QString GameFallout4::myGamesFolderName() const { return "Fallout4"; From db6fff522d0e17a7413df8cd303dbc52fa5e360c Mon Sep 17 00:00:00 2001 From: Thomas Tanner Date: Sat, 26 Dec 2015 14:26:29 +0000 Subject: [PATCH 0180/1544] [game_falloutnv] Abstract out localAppfolder() --- src/games/falloutnv/src/gamefalloutnv.cpp | 11 ----------- src/games/falloutnv/src/gamefalloutnv.h | 1 - 2 files changed, 12 deletions(-) diff --git a/src/games/falloutnv/src/gamefalloutnv.cpp b/src/games/falloutnv/src/gamefalloutnv.cpp index cc836219..b6b19a7d 100644 --- a/src/games/falloutnv/src/gamefalloutnv.cpp +++ b/src/games/falloutnv/src/gamefalloutnv.cpp @@ -51,17 +51,6 @@ QString GameFalloutNV::gameName() const return "New Vegas"; } -QString GameFalloutNV::localAppFolder() const -{ - QString result = getKnownFolderPath(FOLDERID_LocalAppData, false); - if (result.isEmpty()) { - // fallback: try the registry - result = getSpecialPath("Local AppData"); - } - - return result; -} - QString GameFalloutNV::myGamesFolderName() const { return "FalloutNV"; diff --git a/src/games/falloutnv/src/gamefalloutnv.h b/src/games/falloutnv/src/gamefalloutnv.h index c3f4737d..5335a0b5 100644 --- a/src/games/falloutnv/src/gamefalloutnv.h +++ b/src/games/falloutnv/src/gamefalloutnv.h @@ -44,7 +44,6 @@ private: virtual QString identifyGamePath() const override; virtual QString myGamesFolderName() const override; - QString localAppFolder() const; void copyToProfile(const QString &sourcePath, const QDir &destinationDirectory, const QString &sourceFileName, const QString &destinationFileName = QString()) const; From ff966dc0952ecda08be7ea978859f3b2389bd597 Mon Sep 17 00:00:00 2001 From: Thomas Tanner Date: Sat, 26 Dec 2015 14:27:26 +0000 Subject: [PATCH 0181/1544] [game_oblivion] Abstract out localAppfolder() --- src/games/oblivion/src/gameoblivion.cpp | 11 ----------- src/games/oblivion/src/gameoblivion.h | 1 - 2 files changed, 12 deletions(-) diff --git a/src/games/oblivion/src/gameoblivion.cpp b/src/games/oblivion/src/gameoblivion.cpp index ab48ac31..0e640958 100644 --- a/src/games/oblivion/src/gameoblivion.cpp +++ b/src/games/oblivion/src/gameoblivion.cpp @@ -44,17 +44,6 @@ QString GameOblivion::gameName() const return "Oblivion"; } -QString GameOblivion::localAppFolder() const -{ - QString result = getKnownFolderPath(FOLDERID_LocalAppData, false); - if (result.isEmpty()) { - // fallback: try the registry - result = getSpecialPath("Local AppData"); - } - - return result; -} - QString GameOblivion::myGamesFolderName() const { return "Oblivion"; diff --git a/src/games/oblivion/src/gameoblivion.h b/src/games/oblivion/src/gameoblivion.h index 07eb0701..384a9e94 100644 --- a/src/games/oblivion/src/gameoblivion.h +++ b/src/games/oblivion/src/gameoblivion.h @@ -51,7 +51,6 @@ private: virtual QString identifyGamePath() const override; virtual QString myGamesFolderName() const override; - QString localAppFolder() const; void copyToProfile(const QString &sourcePath, const QDir &destinationDirectory, const QString &sourceFileName, const QString &destinationFileName = QString()) const; From 59139a0ed0862ad6974ae552c06e284b9f7aaaa2 Mon Sep 17 00:00:00 2001 From: Thomas Tanner Date: Sat, 26 Dec 2015 14:28:38 +0000 Subject: [PATCH 0182/1544] [game_fallout3] Abstract out localAppfolder() --- src/games/fallout3/src/gamefallout3.cpp | 11 ----------- src/games/fallout3/src/gamefallout3.h | 1 - 2 files changed, 12 deletions(-) diff --git a/src/games/fallout3/src/gamefallout3.cpp b/src/games/fallout3/src/gamefallout3.cpp index 795a539f..67be73bd 100644 --- a/src/games/fallout3/src/gamefallout3.cpp +++ b/src/games/fallout3/src/gamefallout3.cpp @@ -49,17 +49,6 @@ QString GameFallout3::gameName() const return "Fallout 3"; } -QString GameFallout3::localAppFolder() const -{ - QString result = getKnownFolderPath(FOLDERID_LocalAppData, false); - if (result.isEmpty()) { - // fallback: try the registry - result = getSpecialPath("Local AppData"); - } - - return result; -} - QString GameFallout3::myGamesFolderName() const { return "Fallout3"; diff --git a/src/games/fallout3/src/gamefallout3.h b/src/games/fallout3/src/gamefallout3.h index 70373e37..2e4fc464 100644 --- a/src/games/fallout3/src/gamefallout3.h +++ b/src/games/fallout3/src/gamefallout3.h @@ -45,7 +45,6 @@ private: virtual QString identifyGamePath() const override; virtual QString myGamesFolderName() const override; - QString localAppFolder() const; void copyToProfile(const QString &sourcePath, const QDir &destinationDirectory, const QString &sourceFileName, const QString &destinationFileName = QString()) const; From aa370c8911a8bee167c7752a635950d987160f82 Mon Sep 17 00:00:00 2001 From: Thomas Tanner Date: Sat, 26 Dec 2015 14:27:11 +0000 Subject: [PATCH 0183/1544] Abstract out localAppfolder() --- src/gamegamebryo.cpp | 10 ++++++++++ src/gamegamebryo.h | 1 + 2 files changed, 11 insertions(+) diff --git a/src/gamegamebryo.cpp b/src/gamegamebryo.cpp index 1f4d211b..5ff7aa3e 100644 --- a/src/gamegamebryo.cpp +++ b/src/gamegamebryo.cpp @@ -246,6 +246,16 @@ std::map GameGamebryo::featureList() const return result; } +QString GameGamebryo::localAppFolder() const +{ + QString result = getKnownFolderPath(FOLDERID_LocalAppData, false); + if (result.isEmpty()) { + // fallback: try the registry + result = getSpecialPath("Local AppData"); + } + return result; +} + /* QString GetAppVersion(std::wstring const &app_name) { diff --git a/src/gamegamebryo.h b/src/gamegamebryo.h index c17becc8..bb8e7972 100644 --- a/src/gamegamebryo.h +++ b/src/gamegamebryo.h @@ -70,6 +70,7 @@ protected: QString selectedVariant() const; virtual QString getLauncherName() const; QString getVersion(QString const &program) const; + QString localAppFolder() const; protected: From 6c0c79d0030b5d13abce7ec3332fa116ea763218 Mon Sep 17 00:00:00 2001 From: Thomas Tanner Date: Sat, 26 Dec 2015 20:31:52 +0000 Subject: [PATCH 0184/1544] [game_fallout3] Factored out copyToProfile and identifyFamePath, retired myGamesFolderName in favour of getGameShortName --- .../fallout3/src/fallout3scriptextender.h | 2 ++ src/games/fallout3/src/gamefallout3.cpp | 35 ++----------------- src/games/fallout3/src/gamefallout3.h | 11 ++---- 3 files changed, 7 insertions(+), 41 deletions(-) diff --git a/src/games/fallout3/src/fallout3scriptextender.h b/src/games/fallout3/src/fallout3scriptextender.h index d4c0141b..fe648395 100644 --- a/src/games/fallout3/src/fallout3scriptextender.h +++ b/src/games/fallout3/src/fallout3scriptextender.h @@ -4,6 +4,8 @@ #include "gamebryoscriptextender.h" +class GameGamebryo; + class Fallout3ScriptExtender : public GamebryoScriptExtender { public: diff --git a/src/games/fallout3/src/gamefallout3.cpp b/src/games/fallout3/src/gamefallout3.cpp index 2a151598..11b41419 100644 --- a/src/games/fallout3/src/gamefallout3.cpp +++ b/src/games/fallout3/src/gamefallout3.cpp @@ -1,34 +1,26 @@ -#include "gameFallout3.h" +#include "gamefallout3.h" #include "fallout3bsainvalidation.h" #include "fallout3scriptextender.h" #include "fallout3dataarchives.h" #include "fallout3savegameinfo.h" -#include "gamegamebryo.h" #include "executableinfo.h" #include "pluginsetting.h" #include "versioninfo.h" -#include "utility.h" #include #include -#include #include -#include #include #include #include #include -#include - #include - using namespace MOBase; - GameFallout3::GameFallout3() { } @@ -45,21 +37,11 @@ bool GameFallout3::init(IOrganizer *moInfo) return true; } -QString GameFallout3::identifyGamePath() const -{ - return findInRegistry(HKEY_LOCAL_MACHINE, L"Software\\Bethesda Softworks\\Fallout3", L"Installed Path"); -} - QString GameFallout3::gameName() const { return "Fallout 3"; } -QString GameFallout3::myGamesFolderName() const -{ - return "Fallout3"; -} - QList GameFallout3::executables() const { return QList() @@ -69,7 +51,7 @@ QList GameFallout3::executables() const << ExecutableInfo("Construction Kit", findInGameFolder("geck.exe")) << ExecutableInfo("Fallout Launcher", findInGameFolder(getLauncherName())) << ExecutableInfo("BOSS", findInGameFolder("BOSS/BOSS.exe")) - << ExecutableInfo("LOOT", getLootPath()); + << ExecutableInfo("LOOT", getLootPath()) ; } @@ -103,19 +85,6 @@ QList GameFallout3::settings() const return QList(); } -void GameFallout3::copyToProfile(const QString &sourcePath, const QDir &destinationDirectory, - const QString &sourceFileName, const QString &destinationFileName) const -{ - QString filePath = destinationDirectory.absoluteFilePath(destinationFileName.isEmpty() ? sourceFileName - : destinationFileName); - if (!QFileInfo(filePath).exists()) { - if (!shellCopy(sourcePath + "/" + sourceFileName, filePath)) { - // if copy file fails, create the file empty - QFile(filePath).open(QIODevice::WriteOnly); - } - } -} - void GameFallout3::initializeProfile(const QDir &path, ProfileSettings settings) const { if (settings.testFlag(IPluginGame::MODS)) { diff --git a/src/games/fallout3/src/gamefallout3.h b/src/games/fallout3/src/gamefallout3.h index 2e4fc464..43838558 100644 --- a/src/games/fallout3/src/gamefallout3.h +++ b/src/games/fallout3/src/gamefallout3.h @@ -3,6 +3,9 @@ #include "gamegamebryo.h" +#include +#include + class GameFallout3 : public GameGamebryo { Q_OBJECT @@ -40,14 +43,6 @@ public: // IPlugin interface virtual bool isActive() const; virtual QList settings() const; -private: - - virtual QString identifyGamePath() const override; - virtual QString myGamesFolderName() const override; - - void copyToProfile(const QString &sourcePath, const QDir &destinationDirectory, - const QString &sourceFileName, const QString &destinationFileName = QString()) const; - }; #endif // GAMEFALLOUT3_H From 7d1cb4498ab706b095d0bf076c1ae6caa63dc883 Mon Sep 17 00:00:00 2001 From: Thomas Tanner Date: Sat, 26 Dec 2015 20:32:11 +0000 Subject: [PATCH 0185/1544] [game_falloutnv] Factored out copyToProfile and identifyFamePath, retired myGamesFolderName in favour of getGameShortName --- .../falloutnv/src/falloutnvscriptextender.h | 2 ++ src/games/falloutnv/src/gamefalloutnv.cpp | 32 +------------------ src/games/falloutnv/src/gamefalloutnv.h | 11 ++----- 3 files changed, 6 insertions(+), 39 deletions(-) diff --git a/src/games/falloutnv/src/falloutnvscriptextender.h b/src/games/falloutnv/src/falloutnvscriptextender.h index 1361c710..eba6e287 100644 --- a/src/games/falloutnv/src/falloutnvscriptextender.h +++ b/src/games/falloutnv/src/falloutnvscriptextender.h @@ -3,6 +3,8 @@ #include "gamebryoscriptextender.h" +class GameGamebryo; + class FalloutNVScriptExtender : public GamebryoScriptExtender { public: diff --git a/src/games/falloutnv/src/gamefalloutnv.cpp b/src/games/falloutnv/src/gamefalloutnv.cpp index 7744689a..1b48faee 100644 --- a/src/games/falloutnv/src/gamefalloutnv.cpp +++ b/src/games/falloutnv/src/gamefalloutnv.cpp @@ -1,4 +1,4 @@ -#include "gameFalloutNV.h" +#include "gamefalloutnv.h" #include "falloutnvbsainvalidation.h" #include "falloutnvdataarchives.h" @@ -7,25 +7,20 @@ #include "executableinfo.h" #include "pluginsetting.h" -#include "utility.h" #include "versioninfo.h" #include #include -#include #include #include #include #include #include -#include - #include using namespace MOBase; - GameFalloutNV::GameFalloutNV() { } @@ -42,21 +37,11 @@ bool GameFalloutNV::init(IOrganizer *moInfo) return true; } -QString GameFalloutNV::identifyGamePath() const -{ - return findInRegistry(HKEY_LOCAL_MACHINE, L"Software\\Bethesda Softworks\\FalloutNV", L"Installed Path"); -} - QString GameFalloutNV::gameName() const { return "New Vegas"; } -QString GameFalloutNV::myGamesFolderName() const -{ - return "FalloutNV"; -} - QList GameFalloutNV::executables() const { return QList() @@ -100,21 +85,6 @@ QList GameFalloutNV::settings() const return QList(); } - - -void GameFalloutNV::copyToProfile(const QString &sourcePath, const QDir &destinationDirectory, - const QString &sourceFileName, const QString &destinationFileName) const -{ - QString filePath = destinationDirectory.absoluteFilePath(destinationFileName.isEmpty() ? sourceFileName - : destinationFileName); - if (!QFileInfo(filePath).exists()) { - if (!shellCopy(sourcePath + "/" + sourceFileName, filePath)) { - // if copy file fails, create the file empty - QFile(filePath).open(QIODevice::WriteOnly); - } - } -} - void GameFalloutNV::initializeProfile(const QDir &path, ProfileSettings settings) const { if (settings.testFlag(IPluginGame::MODS)) { diff --git a/src/games/falloutnv/src/gamefalloutnv.h b/src/games/falloutnv/src/gamefalloutnv.h index 5335a0b5..09cc3aa7 100644 --- a/src/games/falloutnv/src/gamefalloutnv.h +++ b/src/games/falloutnv/src/gamefalloutnv.h @@ -3,6 +3,9 @@ #include "gamegamebryo.h" +#include +#include + class GameFalloutNV : public GameGamebryo { Q_OBJECT @@ -39,14 +42,6 @@ public: // IPlugin interface virtual bool isActive() const; virtual QList settings() const; -private: - - virtual QString identifyGamePath() const override; - virtual QString myGamesFolderName() const override; - - void copyToProfile(const QString &sourcePath, const QDir &destinationDirectory, - const QString &sourceFileName, const QString &destinationFileName = QString()) const; - }; #endif // GAMEFALLOUTNV_H From 0df5defd727a8d870cbd9f1c0ea4084623f52c83 Mon Sep 17 00:00:00 2001 From: Thomas Tanner Date: Sat, 26 Dec 2015 20:32:41 +0000 Subject: [PATCH 0186/1544] Factored out copyToProfile and identifyFamePath, retired myGamesFolderName in favour of getGameShortName --- src/gamebryoscriptextender.cpp | 3 +++ src/gamebryoscriptextender.h | 4 --- src/gamegamebryo.cpp | 48 ++++++++++++++++------------------ src/gamegamebryo.h | 17 ++++++++++-- 4 files changed, 41 insertions(+), 31 deletions(-) diff --git a/src/gamebryoscriptextender.cpp b/src/gamebryoscriptextender.cpp index b73bb543..a1bc4ed6 100644 --- a/src/gamebryoscriptextender.cpp +++ b/src/gamebryoscriptextender.cpp @@ -2,6 +2,9 @@ #include "gamegamebryo.h" +#include +#include + GamebryoScriptExtender::GamebryoScriptExtender(const GameGamebryo *game) : m_Game(game) { diff --git a/src/gamebryoscriptextender.h b/src/gamebryoscriptextender.h index 6f08f0e4..6386e952 100644 --- a/src/gamebryoscriptextender.h +++ b/src/gamebryoscriptextender.h @@ -12,14 +12,10 @@ public: virtual ~GamebryoScriptExtender(); - //virtual QString name() const override; - virtual QString loaderName() const override; virtual QString loaderPath() const override; - //virtual QStringList saveGameAttachmentExtensions() const override; - virtual bool isInstalled() const override; virtual QString getExtenderVersion() const override; diff --git a/src/gamegamebryo.cpp b/src/gamegamebryo.cpp index 5ff7aa3e..96ca18cd 100644 --- a/src/gamegamebryo.cpp +++ b/src/gamegamebryo.cpp @@ -7,12 +7,17 @@ #include "scopeguard.h" #include "utility.h" +#include #include +#include #include +#include #include +#include +#include #include GameGamebryo::GameGamebryo() @@ -22,7 +27,7 @@ GameGamebryo::GameGamebryo() bool GameGamebryo::init(MOBase::IOrganizer *moInfo) { m_GamePath = identifyGamePath(); - m_MyGamesPath = determineMyGamesPath(myGamesFolderName()); + m_MyGamesPath = determineMyGamesPath(getGameShortName()); m_Organizer = moInfo; return true; } @@ -205,6 +210,12 @@ QString GameGamebryo::determineMyGamesPath(const QString &gameName) return result + "/My Games/" + gameName; } +QString GameGamebryo::identifyGamePath() const +{ + QString path = "Software\\Bethesda Softworks\\" + getGameShortName(); + return findInRegistry(HKEY_LOCAL_MACHINE, path.toStdWString().c_str(), L"Installed Path"); +} + QString GameGamebryo::selectedVariant() const { return m_GameVariant; @@ -256,31 +267,18 @@ QString GameGamebryo::localAppFolder() const return result; } -/* -QString GetAppVersion(std::wstring const &app_name) +void GameGamebryo::copyToProfile(const QString &sourcePath, const QDir &destinationDirectory, const QString &sourceFileName) { - DWORD handle; - DWORD info_len = ::GetFileVersionInfoSizeW(app_name.c_str(), &handle); - if (info_len == 0) { - qDebug("GetFileVersionInfoSizeW Error %d", ::GetLastError()); - return ""; - } - - std::vector buff(info_len); - if( ! ::GetFileVersionInfoW(app_name.c_str(), handle, info_len, buff.data())) { - qDebug("GetFileVersionInfoW Error %d", ::GetLastError()); - return ""; - } + copyToProfile(sourcePath, destinationDirectory, sourceFileName, sourceFileName); +} - VS_FIXEDFILEINFO *pFileInfo; - UINT buf_len; - if ( ! ::VerQueryValueW(buff.data(), L"\\", reinterpret_cast(&pFileInfo), &buf_len)) { - qDebug("VerQueryValueW Error %d", ::GetLastError()); - return ""; +void GameGamebryo::copyToProfile(const QString &sourcePath, const QDir &destinationDirectory, const QString &sourceFileName, const QString &destinationFileName) +{ + QString filePath = destinationDirectory.absoluteFilePath(destinationFileName); + if (!QFileInfo(filePath).exists()) { + if (!MOBase::shellCopy(sourcePath + "/" + sourceFileName, filePath)) { + // if copy file fails, create the file empty + QFile(filePath).open(QIODevice::WriteOnly); + } } - return QString("%1.%2.%3.%4").arg(HIWORD(pFileInfo->dwFileVersionMS)) - .arg(LOWORD(pFileInfo->dwFileVersionMS)) - .arg(HIWORD(pFileInfo->dwFileVersionLS)) - .arg(LOWORD(pFileInfo->dwFileVersionLS)); } -*/ diff --git a/src/gamegamebryo.h b/src/gamegamebryo.h index bb8e7972..5957f562 100644 --- a/src/gamegamebryo.h +++ b/src/gamegamebryo.h @@ -8,7 +8,10 @@ class DataArchives; class SaveGameInfo; class BSAInvalidation; +#include #include +class QDir; +class QFileInfo; #include @@ -72,6 +75,17 @@ protected: QString getVersion(QString const &program) const; QString localAppFolder() const; + //This function is not terribly well name as it copies exactly where it's told + //to, irrespective of whether it's in the profile... + static void copyToProfile(const QString &sourcePath, + const QDir &destinationDirectory, + const QString &sourceFileName); + + static void copyToProfile(const QString &sourcePath, + const QDir &destinationDirectory, + const QString &sourceFileName, + const QString &destinationFileName); + protected: std::map featureList() const; @@ -88,8 +102,7 @@ private: QString determineMyGamesPath(const QString &gameName); - virtual QString myGamesFolderName() const = 0; - virtual QString identifyGamePath() const = 0; + QString identifyGamePath() const; private: From ecdf47bb4686920af00a8f66719e376ad92c7873 Mon Sep 17 00:00:00 2001 From: Thomas Tanner Date: Sat, 26 Dec 2015 20:33:01 +0000 Subject: [PATCH 0187/1544] [game_oblivion] Factored out copyToProfile and identifyFamePath, retired myGamesFolderName in favour of getGameShortName --- src/games/oblivion/src/gameoblivion.cpp | 32 ------------------- src/games/oblivion/src/gameoblivion.h | 12 ------- .../oblivion/src/oblivionscriptextender.h | 2 ++ 3 files changed, 2 insertions(+), 44 deletions(-) diff --git a/src/games/oblivion/src/gameoblivion.cpp b/src/games/oblivion/src/gameoblivion.cpp index 8edc2c13..ce27b320 100644 --- a/src/games/oblivion/src/gameoblivion.cpp +++ b/src/games/oblivion/src/gameoblivion.cpp @@ -7,20 +7,15 @@ #include "pluginsetting.h" #include "executableinfo.h" -#include "utility.h" #include #include -#include #include -#include - #include using namespace MOBase; - GameOblivion::GameOblivion() { } @@ -37,23 +32,11 @@ bool GameOblivion::init(IOrganizer *moInfo) return true; } -QString GameOblivion::identifyGamePath() const -{ - return findInRegistry(HKEY_LOCAL_MACHINE, L"Software\\Bethesda Softworks\\Oblivion", L"Installed Path"); -} - QString GameOblivion::gameName() const { return "Oblivion"; } -QString GameOblivion::myGamesFolderName() const -{ - return "Oblivion"; -} - - - QList GameOblivion::executables() const { return QList() @@ -97,21 +80,6 @@ QList GameOblivion::settings() const return QList(); } - - -void GameOblivion::copyToProfile(const QString &sourcePath, const QDir &destinationDirectory, - const QString &sourceFileName, const QString &destinationFileName) const -{ - QString filePath = destinationDirectory.absoluteFilePath(destinationFileName.isEmpty() ? sourceFileName - : destinationFileName); - if (!QFileInfo(filePath).exists()) { - if (!shellCopy(sourcePath + "/" + sourceFileName, filePath)) { - // if copy file fails, create the file empty - QFile(filePath).open(QIODevice::WriteOnly); - } - } -} - void GameOblivion::initializeProfile(const QDir &path, ProfileSettings settings) const { if (settings.testFlag(IPluginGame::MODS)) { diff --git a/src/games/oblivion/src/gameoblivion.h b/src/games/oblivion/src/gameoblivion.h index 384a9e94..0103d167 100644 --- a/src/games/oblivion/src/gameoblivion.h +++ b/src/games/oblivion/src/gameoblivion.h @@ -4,12 +4,8 @@ #include "gamegamebryo.h" #include -#include - #include -class QDir; - class GameOblivion : public GameGamebryo { Q_OBJECT @@ -46,14 +42,6 @@ public: // IPlugin interface virtual bool isActive() const; virtual QList settings() const; -private: - - virtual QString identifyGamePath() const override; - virtual QString myGamesFolderName() const override; - - void copyToProfile(const QString &sourcePath, const QDir &destinationDirectory, - const QString &sourceFileName, const QString &destinationFileName = QString()) const; - }; #endif // GAMEOBLIVION_H diff --git a/src/games/oblivion/src/oblivionscriptextender.h b/src/games/oblivion/src/oblivionscriptextender.h index 6efb45de..d1010e56 100644 --- a/src/games/oblivion/src/oblivionscriptextender.h +++ b/src/games/oblivion/src/oblivionscriptextender.h @@ -3,6 +3,8 @@ #include "gamebryoscriptextender.h" +class GameGamebryo; + class OblivionScriptExtender : public GamebryoScriptExtender { public: From b20e2d7e2ade64de0f9a39d079408087b8539e1b Mon Sep 17 00:00:00 2001 From: Thomas Tanner Date: Sat, 26 Dec 2015 20:33:17 +0000 Subject: [PATCH 0188/1544] [game_skyrim] Factored out copyToProfile and identifyFamePath, retired myGamesFolderName in favour of getGameShortName --- src/games/skyrim/src/gameskyrim.cpp | 32 +-------------------- src/games/skyrim/src/gameskyrim.h | 12 ++------ src/games/skyrim/src/skyrimscriptextender.h | 2 ++ 3 files changed, 6 insertions(+), 40 deletions(-) diff --git a/src/games/skyrim/src/gameskyrim.cpp b/src/games/skyrim/src/gameskyrim.cpp index c2bf5f7a..57b92671 100644 --- a/src/games/skyrim/src/gameskyrim.cpp +++ b/src/games/skyrim/src/gameskyrim.cpp @@ -7,16 +7,15 @@ #include "executableinfo.h" #include "pluginsetting.h" -#include "utility.h" #include #include -#include #include #include #include +#include #include #include @@ -24,10 +23,8 @@ #include #include - using namespace MOBase; - GameSkyrim::GameSkyrim() { } @@ -44,23 +41,11 @@ bool GameSkyrim::init(IOrganizer *moInfo) return true; } -QString GameSkyrim::identifyGamePath() const -{ - return findInRegistry(HKEY_LOCAL_MACHINE, L"Software\\Bethesda Softworks\\Skyrim", L"Installed Path"); -} - QString GameSkyrim::gameName() const { return "Skyrim"; } -QString GameSkyrim::myGamesFolderName() const -{ - return "Skyrim"; -} - - - QList GameSkyrim::executables() const { return QList() @@ -104,21 +89,6 @@ QList GameSkyrim::settings() const return QList(); } - - -void GameSkyrim::copyToProfile(const QString &sourcePath, const QDir &destinationDirectory, - const QString &sourceFileName, const QString &destinationFileName) const -{ - QString filePath = destinationDirectory.absoluteFilePath(destinationFileName.isEmpty() ? sourceFileName - : destinationFileName); - if (!QFileInfo(filePath).exists()) { - if (!shellCopy(sourcePath + "/" + sourceFileName, filePath)) { - // if copy file fails, create the file empty - QFile(filePath).open(QIODevice::WriteOnly); - } - } -} - void GameSkyrim::initializeProfile(const QDir &path, ProfileSettings settings) const { if (settings.testFlag(IPluginGame::MODS)) { diff --git a/src/games/skyrim/src/gameskyrim.h b/src/games/skyrim/src/gameskyrim.h index ed8bef6f..8f295a79 100644 --- a/src/games/skyrim/src/gameskyrim.h +++ b/src/games/skyrim/src/gameskyrim.h @@ -3,6 +3,9 @@ #include "gamegamebryo.h" +#include +#include + class GameSkyrim : public GameGamebryo { Q_OBJECT @@ -40,15 +43,6 @@ public: // IPlugin interface virtual MOBase::VersionInfo version() const; virtual bool isActive() const; virtual QList settings() const; - -private: - - virtual QString identifyGamePath() const override; - virtual QString myGamesFolderName() const override; - - void copyToProfile(const QString &sourcePath, const QDir &destinationDirectory, - const QString &sourceFileName, const QString &destinationFileName = QString()) const; - }; #endif // GAMESKYRIM_H diff --git a/src/games/skyrim/src/skyrimscriptextender.h b/src/games/skyrim/src/skyrimscriptextender.h index 1aa37493..7f1e14b4 100644 --- a/src/games/skyrim/src/skyrimscriptextender.h +++ b/src/games/skyrim/src/skyrimscriptextender.h @@ -3,6 +3,8 @@ #include "gamebryoscriptextender.h" +class GameGamebryo; + class SkyrimScriptExtender : public GamebryoScriptExtender { public: From 0140a4480964adf4e97f39fe5f4f95a3c96f532f Mon Sep 17 00:00:00 2001 From: Thomas Tanner Date: Sat, 26 Dec 2015 20:33:35 +0000 Subject: [PATCH 0189/1544] [game_fallout4vr] Factored out copyToProfile and identifyFamePath, retired myGamesFolderName in favour of getGameShortName --- .../fallout4vr/src/fallout4scriptextender.h | 2 + src/games/fallout4vr/src/gamefallout4.cpp | 41 +++++-------------- src/games/fallout4vr/src/gamefallout4.h | 10 +---- 3 files changed, 14 insertions(+), 39 deletions(-) diff --git a/src/games/fallout4vr/src/fallout4scriptextender.h b/src/games/fallout4vr/src/fallout4scriptextender.h index 99a26cc1..6f9b17e6 100644 --- a/src/games/fallout4vr/src/fallout4scriptextender.h +++ b/src/games/fallout4vr/src/fallout4scriptextender.h @@ -3,6 +3,8 @@ #include "gamebryoscriptextender.h" +class GameGamebryo; + class Fallout4ScriptExtender : public GamebryoScriptExtender { public: diff --git a/src/games/fallout4vr/src/gamefallout4.cpp b/src/games/fallout4vr/src/gamefallout4.cpp index 62068b2b..8f96ca8e 100644 --- a/src/games/fallout4vr/src/gamefallout4.cpp +++ b/src/games/fallout4vr/src/gamefallout4.cpp @@ -3,22 +3,25 @@ #include "fallout4dataarchives.h" #include "fallout4scriptextender.h" #include "fallout4savegameinfo.h" -#include + #include #include "iplugingame.h" #include -//#include -#include +//**#include +#include "versioninfo.h" -#include #include -#include +#include +#include +#include +#include +#include +#include #include using namespace MOBase; - GameFallout4::GameFallout4() { } @@ -30,27 +33,16 @@ bool GameFallout4::init(IOrganizer *moInfo) } m_ScriptExtender = std::shared_ptr(new Fallout4ScriptExtender(this)); m_DataArchives = std::shared_ptr(new Fallout4DataArchives()); -// m_LocalSavegames.reset(new GamebryoLocalSavegames(myGamesPath(), "Fallout4.ini")); +//** m_LocalSavegames.reset(new GamebryoLocalSavegames(myGamesPath(), "Fallout4.ini")); m_SaveGameInfo = std::shared_ptr(new Fallout4SaveGameInfo(this)); return true; } -QString GameFallout4::identifyGamePath() const -{ - return findInRegistry(HKEY_LOCAL_MACHINE, L"Software\\Bethesda Softworks\\Fallout4", L"Installed Path"); -} - QString GameFallout4::gameName() const { return "Fallout 4"; } - -QString GameFallout4::myGamesFolderName() const -{ - return "Fallout4"; -} - QList GameFallout4::executables() const { return QList() @@ -91,19 +83,6 @@ QList GameFallout4::settings() const return QList(); } -void GameFallout4::copyToProfile(const QString &sourcePath, const QDir &destinationDirectory, - const QString &sourceFileName, const QString &destinationFileName) const -{ - QString filePath = destinationDirectory.absoluteFilePath(destinationFileName.isEmpty() ? sourceFileName - : destinationFileName); - if (!QFileInfo(filePath).exists()) { - if (!shellCopy(sourcePath + "/" + sourceFileName, filePath)) { - // if copy file fails, create the file empty - QFile(filePath).open(QIODevice::WriteOnly); - } - } -} - void GameFallout4::initializeProfile(const QDir &path, ProfileSettings settings) const { if (settings.testFlag(IPluginGame::MODS)) { diff --git a/src/games/fallout4vr/src/gamefallout4.h b/src/games/fallout4vr/src/gamefallout4.h index 612a37df..e4ce2cf4 100644 --- a/src/games/fallout4vr/src/gamefallout4.h +++ b/src/games/fallout4vr/src/gamefallout4.h @@ -4,6 +4,8 @@ #include "gamegamebryo.h" +#include +#include class GameFallout4 : public GameGamebryo { @@ -42,14 +44,6 @@ public: // IPlugin interface virtual bool isActive() const override; virtual QList settings() const override; -private: - - virtual QString identifyGamePath() const override; - virtual QString myGamesFolderName() const override; - - void copyToProfile(const QString &sourcePath, const QDir &destinationDirectory, - const QString &sourceFileName, const QString &destinationFileName = QString()) const; - }; #endif // GAMEFallout4_H From ade5e53a1ff44b56c474db0ef16a6f8d88061852 Mon Sep 17 00:00:00 2001 From: Thomas Tanner Date: Sat, 26 Dec 2015 20:33:35 +0000 Subject: [PATCH 0190/1544] [game_fallout76] Factored out copyToProfile and identifyFamePath, retired myGamesFolderName in favour of getGameShortName --- .../fallout76/src/fallout4scriptextender.h | 2 + src/games/fallout76/src/gamefallout4.cpp | 41 +++++-------------- src/games/fallout76/src/gamefallout4.h | 10 +---- 3 files changed, 14 insertions(+), 39 deletions(-) diff --git a/src/games/fallout76/src/fallout4scriptextender.h b/src/games/fallout76/src/fallout4scriptextender.h index 99a26cc1..6f9b17e6 100644 --- a/src/games/fallout76/src/fallout4scriptextender.h +++ b/src/games/fallout76/src/fallout4scriptextender.h @@ -3,6 +3,8 @@ #include "gamebryoscriptextender.h" +class GameGamebryo; + class Fallout4ScriptExtender : public GamebryoScriptExtender { public: diff --git a/src/games/fallout76/src/gamefallout4.cpp b/src/games/fallout76/src/gamefallout4.cpp index 62068b2b..8f96ca8e 100644 --- a/src/games/fallout76/src/gamefallout4.cpp +++ b/src/games/fallout76/src/gamefallout4.cpp @@ -3,22 +3,25 @@ #include "fallout4dataarchives.h" #include "fallout4scriptextender.h" #include "fallout4savegameinfo.h" -#include + #include #include "iplugingame.h" #include -//#include -#include +//**#include +#include "versioninfo.h" -#include #include -#include +#include +#include +#include +#include +#include +#include #include using namespace MOBase; - GameFallout4::GameFallout4() { } @@ -30,27 +33,16 @@ bool GameFallout4::init(IOrganizer *moInfo) } m_ScriptExtender = std::shared_ptr(new Fallout4ScriptExtender(this)); m_DataArchives = std::shared_ptr(new Fallout4DataArchives()); -// m_LocalSavegames.reset(new GamebryoLocalSavegames(myGamesPath(), "Fallout4.ini")); +//** m_LocalSavegames.reset(new GamebryoLocalSavegames(myGamesPath(), "Fallout4.ini")); m_SaveGameInfo = std::shared_ptr(new Fallout4SaveGameInfo(this)); return true; } -QString GameFallout4::identifyGamePath() const -{ - return findInRegistry(HKEY_LOCAL_MACHINE, L"Software\\Bethesda Softworks\\Fallout4", L"Installed Path"); -} - QString GameFallout4::gameName() const { return "Fallout 4"; } - -QString GameFallout4::myGamesFolderName() const -{ - return "Fallout4"; -} - QList GameFallout4::executables() const { return QList() @@ -91,19 +83,6 @@ QList GameFallout4::settings() const return QList(); } -void GameFallout4::copyToProfile(const QString &sourcePath, const QDir &destinationDirectory, - const QString &sourceFileName, const QString &destinationFileName) const -{ - QString filePath = destinationDirectory.absoluteFilePath(destinationFileName.isEmpty() ? sourceFileName - : destinationFileName); - if (!QFileInfo(filePath).exists()) { - if (!shellCopy(sourcePath + "/" + sourceFileName, filePath)) { - // if copy file fails, create the file empty - QFile(filePath).open(QIODevice::WriteOnly); - } - } -} - void GameFallout4::initializeProfile(const QDir &path, ProfileSettings settings) const { if (settings.testFlag(IPluginGame::MODS)) { diff --git a/src/games/fallout76/src/gamefallout4.h b/src/games/fallout76/src/gamefallout4.h index 612a37df..e4ce2cf4 100644 --- a/src/games/fallout76/src/gamefallout4.h +++ b/src/games/fallout76/src/gamefallout4.h @@ -4,6 +4,8 @@ #include "gamegamebryo.h" +#include +#include class GameFallout4 : public GameGamebryo { @@ -42,14 +44,6 @@ public: // IPlugin interface virtual bool isActive() const override; virtual QList settings() const override; -private: - - virtual QString identifyGamePath() const override; - virtual QString myGamesFolderName() const override; - - void copyToProfile(const QString &sourcePath, const QDir &destinationDirectory, - const QString &sourceFileName, const QString &destinationFileName = QString()) const; - }; #endif // GAMEFallout4_H From ae6a792861370092620fd938f54084d319b04062 Mon Sep 17 00:00:00 2001 From: Thomas Tanner Date: Sat, 26 Dec 2015 20:33:35 +0000 Subject: [PATCH 0191/1544] [game_fallout4] Factored out copyToProfile and identifyFamePath, retired myGamesFolderName in favour of getGameShortName --- .../fallout4/src/fallout4scriptextender.h | 2 + src/games/fallout4/src/gamefallout4.cpp | 41 +++++-------------- src/games/fallout4/src/gamefallout4.h | 10 +---- 3 files changed, 14 insertions(+), 39 deletions(-) diff --git a/src/games/fallout4/src/fallout4scriptextender.h b/src/games/fallout4/src/fallout4scriptextender.h index 99a26cc1..6f9b17e6 100644 --- a/src/games/fallout4/src/fallout4scriptextender.h +++ b/src/games/fallout4/src/fallout4scriptextender.h @@ -3,6 +3,8 @@ #include "gamebryoscriptextender.h" +class GameGamebryo; + class Fallout4ScriptExtender : public GamebryoScriptExtender { public: diff --git a/src/games/fallout4/src/gamefallout4.cpp b/src/games/fallout4/src/gamefallout4.cpp index 62068b2b..8f96ca8e 100644 --- a/src/games/fallout4/src/gamefallout4.cpp +++ b/src/games/fallout4/src/gamefallout4.cpp @@ -3,22 +3,25 @@ #include "fallout4dataarchives.h" #include "fallout4scriptextender.h" #include "fallout4savegameinfo.h" -#include + #include #include "iplugingame.h" #include -//#include -#include +//**#include +#include "versioninfo.h" -#include #include -#include +#include +#include +#include +#include +#include +#include #include using namespace MOBase; - GameFallout4::GameFallout4() { } @@ -30,27 +33,16 @@ bool GameFallout4::init(IOrganizer *moInfo) } m_ScriptExtender = std::shared_ptr(new Fallout4ScriptExtender(this)); m_DataArchives = std::shared_ptr(new Fallout4DataArchives()); -// m_LocalSavegames.reset(new GamebryoLocalSavegames(myGamesPath(), "Fallout4.ini")); +//** m_LocalSavegames.reset(new GamebryoLocalSavegames(myGamesPath(), "Fallout4.ini")); m_SaveGameInfo = std::shared_ptr(new Fallout4SaveGameInfo(this)); return true; } -QString GameFallout4::identifyGamePath() const -{ - return findInRegistry(HKEY_LOCAL_MACHINE, L"Software\\Bethesda Softworks\\Fallout4", L"Installed Path"); -} - QString GameFallout4::gameName() const { return "Fallout 4"; } - -QString GameFallout4::myGamesFolderName() const -{ - return "Fallout4"; -} - QList GameFallout4::executables() const { return QList() @@ -91,19 +83,6 @@ QList GameFallout4::settings() const return QList(); } -void GameFallout4::copyToProfile(const QString &sourcePath, const QDir &destinationDirectory, - const QString &sourceFileName, const QString &destinationFileName) const -{ - QString filePath = destinationDirectory.absoluteFilePath(destinationFileName.isEmpty() ? sourceFileName - : destinationFileName); - if (!QFileInfo(filePath).exists()) { - if (!shellCopy(sourcePath + "/" + sourceFileName, filePath)) { - // if copy file fails, create the file empty - QFile(filePath).open(QIODevice::WriteOnly); - } - } -} - void GameFallout4::initializeProfile(const QDir &path, ProfileSettings settings) const { if (settings.testFlag(IPluginGame::MODS)) { diff --git a/src/games/fallout4/src/gamefallout4.h b/src/games/fallout4/src/gamefallout4.h index 612a37df..e4ce2cf4 100644 --- a/src/games/fallout4/src/gamefallout4.h +++ b/src/games/fallout4/src/gamefallout4.h @@ -4,6 +4,8 @@ #include "gamegamebryo.h" +#include +#include class GameFallout4 : public GameGamebryo { @@ -42,14 +44,6 @@ public: // IPlugin interface virtual bool isActive() const override; virtual QList settings() const override; -private: - - virtual QString identifyGamePath() const override; - virtual QString myGamesFolderName() const override; - - void copyToProfile(const QString &sourcePath, const QDir &destinationDirectory, - const QString &sourceFileName, const QString &destinationFileName = QString()) const; - }; #endif // GAMEFallout4_H From 64a584e84389d7781ede70d311926504bebbb155 Mon Sep 17 00:00:00 2001 From: Thomas Tanner Date: Sat, 26 Dec 2015 22:56:28 +0000 Subject: [PATCH 0192/1544] refactored a bit, make use of static and put some code into anonymous namespace --- src/gamegamebryo.cpp | 190 +++++++++++++++++++++++-------------------- src/gamegamebryo.h | 25 ++---- 2 files changed, 109 insertions(+), 106 deletions(-) diff --git a/src/gamegamebryo.cpp b/src/gamegamebryo.cpp index 96ca18cd..c0c3d8cf 100644 --- a/src/gamegamebryo.cpp +++ b/src/gamegamebryo.cpp @@ -10,16 +10,106 @@ #include #include #include +#include #include #include +#include +#include #include #include +#include #include #include +namespace { + +std::unique_ptr getRegValue(HKEY key, LPCWSTR path, LPCWSTR value, + DWORD flags, LPDWORD type = nullptr) +{ + DWORD size = 0; + HKEY subKey; + LONG res = ::RegOpenKeyExW(key, path, 0, + KEY_QUERY_VALUE | KEY_WOW64_32KEY, &subKey); + if (res != ERROR_SUCCESS) { + return std::unique_ptr(); + } + res = ::RegGetValueW(subKey, L"", value, flags, type, nullptr, &size); + if (res == ERROR_FILE_NOT_FOUND || res == ERROR_UNSUPPORTED_TYPE) { + return std::unique_ptr(); + } + if (res != ERROR_SUCCESS && res != ERROR_MORE_DATA) { + throw MOBase::MyException(QObject::tr("failed to query registry path (preflight): %1").arg(res, 0, 16)); + } + + std::unique_ptr result(new BYTE[size]); + res = ::RegGetValueW(subKey, L"", value, flags, type, result.get(), &size); + + if (res != ERROR_SUCCESS) { + throw MOBase::MyException(QObject::tr("failed to query registry path (read): %1").arg(res, 0, 16)); + } + + return result; +} + +QString findInRegistry(HKEY baseKey, LPCWSTR path, LPCWSTR value) +{ + std::unique_ptr buffer = getRegValue(baseKey, path, value, RRF_RT_REG_SZ | RRF_NOEXPAND); + + return QString::fromUtf16(reinterpret_cast(buffer.get())); +} + +QString getKnownFolderPath(REFKNOWNFOLDERID folderId, bool useDefault) +{ + PWSTR path = nullptr; + ON_BLOCK_EXIT([&] () { + if (path != nullptr) ::CoTaskMemFree(path); + }); + + if (::SHGetKnownFolderPath(folderId, useDefault ? KF_FLAG_DEFAULT_PATH : 0, NULL, &path) == S_OK) { + return QDir::fromNativeSeparators(QString::fromWCharArray(path)); + } else { + return QString(); + } +} + +QString getSpecialPath(const QString &name) +{ + QString base = findInRegistry(HKEY_CURRENT_USER, + L"Software\\Microsoft\\Windows\\CurrentVersion\\Explorer\\User Shell Folders", + name.toStdWString().c_str()); + + WCHAR temp[MAX_PATH]; + if (::ExpandEnvironmentStringsW(base.toStdWString().c_str(), temp, MAX_PATH) != 0) { + return QString::fromWCharArray(temp); + } else { + return base; + } +} + +QString determineMyGamesPath(const QString &gameName) +{ + // a) this is the way it should work. get the configured My Documents directory + QString result = getKnownFolderPath(FOLDERID_Documents, false); + + // b) if there is no directory there, look in the default directory + if (result.isEmpty() + || !QFileInfo(result + "/My Games/" + gameName).exists()) { + result = getKnownFolderPath(FOLDERID_Documents, true); + } + // c) finally, look in the registry. This is discouraged + if (result.isEmpty() + || !QFileInfo(result + "/My Games/" + gameName).exists()) { + result = getSpecialPath("Personal"); + } + + return result + "/My Games/" + gameName; +} + +} + GameGamebryo::GameGamebryo() { } @@ -103,7 +193,7 @@ QString GameGamebryo::getLauncherName() const return getGameShortName() + "Launcher.exe"; } -QString GameGamebryo::getVersion(const QString &program) const +QString GameGamebryo::getVersion(QString const &program) const { //This *really* needs to be factored out std::wstring app_name = L"\\\\?\\" + @@ -133,82 +223,11 @@ QString GameGamebryo::getVersion(const QString &program) const .arg(LOWORD(pFileInfo->dwFileVersionLS)); } -std::unique_ptr GameGamebryo::getRegValue(HKEY key, LPCWSTR path, - LPCWSTR value, DWORD flags, - LPDWORD type) const -{ - DWORD size = 0; - HKEY subKey; - LONG res = ::RegOpenKeyExW(key, path, 0, - KEY_QUERY_VALUE | KEY_WOW64_32KEY, &subKey); - if (res != ERROR_SUCCESS) { - return std::unique_ptr(); - } - res = ::RegGetValueW(subKey, L"", value, flags, type, nullptr, &size); - if ((res == ERROR_FILE_NOT_FOUND) || (res == ERROR_UNSUPPORTED_TYPE)) { - return std::unique_ptr(); - } else if ((res != ERROR_SUCCESS) && (res != ERROR_MORE_DATA)) { - throw MOBase::MyException(QObject::tr("failed to query registry path (preflight): %1").arg(res, 0, 16)); - } - - std::unique_ptr result(new BYTE[size]); - res = ::RegGetValueW(subKey, L"", value, flags, type, result.get(), &size); - - if (res != ERROR_SUCCESS) { - throw MOBase::MyException(QObject::tr("failed to query registry path (read): %1").arg(res, 0, 16)); - } - - return result; -} - -QString GameGamebryo::findInRegistry(HKEY baseKey, LPCWSTR path, LPCWSTR value) const -{ - std::unique_ptr buffer = getRegValue(baseKey, path, value, RRF_RT_REG_SZ | RRF_NOEXPAND); - - if (buffer.get() != nullptr) { - return QString::fromUtf16(reinterpret_cast(buffer.get())); - } else { - return QString(); - } -} - QFileInfo GameGamebryo::findInGameFolder(const QString &relativePath) const { return QFileInfo(m_GamePath + "/" + relativePath); } -QString GameGamebryo::getKnownFolderPath(REFKNOWNFOLDERID folderId, bool useDefault) const -{ - PWSTR path = nullptr; - ON_BLOCK_EXIT([&] () { - if (path != nullptr) ::CoTaskMemFree(path); - }); - - if (::SHGetKnownFolderPath(folderId, useDefault ? KF_FLAG_DEFAULT_PATH : 0, NULL, &path) == S_OK) { - return QDir::fromNativeSeparators(QString::fromWCharArray(path)); - } else { - return QString(); - } -} - -QString GameGamebryo::determineMyGamesPath(const QString &gameName) -{ - // a) this is the way it should work. get the configured My Documents directory - QString result = getKnownFolderPath(FOLDERID_Documents, false); - - // b) if there is no directory there, look in the default directory - if (result.isEmpty() - || !QFileInfo(result + "/My Games/" + gameName).exists()) { - result = getKnownFolderPath(FOLDERID_Documents, true); - } - // c) finally, look in the registry. This is discouraged - if (result.isEmpty() - || !QFileInfo(result + "/My Games/" + gameName).exists()) { - result = getSpecialPath("Personal"); - } - - return result + "/My Games/" + gameName; -} QString GameGamebryo::identifyGamePath() const { @@ -221,26 +240,12 @@ QString GameGamebryo::selectedVariant() const return m_GameVariant; } -QString GameGamebryo::getSpecialPath(const QString &name) const -{ - QString base = findInRegistry(HKEY_CURRENT_USER, - L"Software\\Microsoft\\Windows\\CurrentVersion\\Explorer\\User Shell Folders", - name.toStdWString().c_str()); - - WCHAR temp[MAX_PATH]; - if (::ExpandEnvironmentStringsW(base.toStdWString().c_str(), temp, MAX_PATH) != 0) { - return QString::fromWCharArray(temp); - } else { - return base; - } -} - QString GameGamebryo::myGamesPath() const { return m_MyGamesPath; } -QString GameGamebryo::getLootPath() const +/*static*/ QString GameGamebryo::getLootPath() { return findInRegistry(HKEY_LOCAL_MACHINE, L"Software\\LOOT", L"Installed Path") + "/Loot.exe"; } @@ -257,7 +262,7 @@ std::map GameGamebryo::featureList() const return result; } -QString GameGamebryo::localAppFolder() const +/*static*/QString GameGamebryo::localAppFolder() { QString result = getKnownFolderPath(FOLDERID_LocalAppData, false); if (result.isEmpty()) { @@ -267,12 +272,17 @@ QString GameGamebryo::localAppFolder() const return result; } -void GameGamebryo::copyToProfile(const QString &sourcePath, const QDir &destinationDirectory, const QString &sourceFileName) +/*static*/void GameGamebryo::copyToProfile(QString const &sourcePath, + QDir const &destinationDirectory, + QString const &sourceFileName) { copyToProfile(sourcePath, destinationDirectory, sourceFileName, sourceFileName); } -void GameGamebryo::copyToProfile(const QString &sourcePath, const QDir &destinationDirectory, const QString &sourceFileName, const QString &destinationFileName) +/*static*/void GameGamebryo::copyToProfile(QString const &sourcePath, + QDir const &destinationDirectory, + QString const &sourceFileName, + QString const &destinationFileName) { QString filePath = destinationDirectory.absoluteFilePath(destinationFileName); if (!QFileInfo(filePath).exists()) { diff --git a/src/gamegamebryo.h b/src/gamegamebryo.h index 5957f562..fed7ed21 100644 --- a/src/gamegamebryo.h +++ b/src/gamegamebryo.h @@ -15,9 +15,6 @@ class QFileInfo; #include -#include - - class GameGamebryo : public MOBase::IPluginGame { Q_OBJECT @@ -62,18 +59,16 @@ public: // IPluginGame interface protected: - std::unique_ptr getRegValue(HKEY key, LPCWSTR subKey, LPCWSTR value, DWORD flags, LPDWORD type = nullptr) const; - QString findInRegistry(HKEY baseKey, LPCWSTR path, LPCWSTR value) const; - QFileInfo findInGameFolder(const QString &relativePath) const; - QString getKnownFolderPath(REFKNOWNFOLDERID folderId, bool useDefault) const; - QString getSpecialPath(const QString &name) const; - QString myGamesPath() const; - //Arguably this shouldn't really be here but every gamebryo program seems to use it - QString getLootPath() const; - QString selectedVariant() const; virtual QString getLauncherName() const; + + QFileInfo findInGameFolder(const QString &relativePath) const; + QString myGamesPath() const; + QString selectedVariant() const; QString getVersion(QString const &program) const; - QString localAppFolder() const; + + static QString localAppFolder(); + //Arguably this shouldn't really be here but every gamebryo program seems to use it + static QString getLootPath(); //This function is not terribly well name as it copies exactly where it's told //to, irrespective of whether it's in the profile... @@ -90,7 +85,7 @@ protected: std::map featureList() const; - //These should be implemented by anything that uses gamebro (I think) + //These should be implemented by anything that uses gamebryo (I think) //(and if they don't, it'll be a null pointer and won't look implemented, //so that's fine too). std::shared_ptr m_ScriptExtender { nullptr }; @@ -100,8 +95,6 @@ protected: private: - QString determineMyGamesPath(const QString &gameName); - QString identifyGamePath() const; private: From f5ed4fea492717935249203f4febb94029f03d85 Mon Sep 17 00:00:00 2001 From: Thomas Tanner Date: Sun, 27 Dec 2015 13:54:44 +0000 Subject: [PATCH 0193/1544] Include file tidyup --- src/gamegamebryo.cpp | 1 + 1 file changed, 1 insertion(+) diff --git a/src/gamegamebryo.cpp b/src/gamegamebryo.cpp index c0c3d8cf..c1579a9d 100644 --- a/src/gamegamebryo.cpp +++ b/src/gamegamebryo.cpp @@ -15,6 +15,7 @@ #include #include +#include #include #include #include From 50cba7d6e80d5c3ce4e9a3d5b4ef2df32470bb39 Mon Sep 17 00:00:00 2001 From: TanninOne Date: Mon, 28 Dec 2015 13:33:06 +0100 Subject: [PATCH 0194/1544] added local savegame feature to featurelist --- src/gamegamebryo.cpp | 9 ++++----- src/gamegamebryo.h | 2 ++ 2 files changed, 6 insertions(+), 5 deletions(-) diff --git a/src/gamegamebryo.cpp b/src/gamegamebryo.cpp index 2502418f..51138b2f 100644 --- a/src/gamegamebryo.cpp +++ b/src/gamegamebryo.cpp @@ -239,17 +239,16 @@ QString GameGamebryo::getLootPath() const std::map GameGamebryo::featureList() const { - static std::map result { + return { { typeid(BSAInvalidation), m_BSAInvalidation.get() }, { typeid(ScriptExtender), m_ScriptExtender.get() }, { typeid(DataArchives), m_DataArchives.get() }, - { typeid(SaveGameInfo), m_SaveGameInfo.get() } + { typeid(SaveGameInfo), m_SaveGameInfo.get() }, + { typeid(LocalSavegames), m_LocalSavegames.get() } }; - - return result; } - + /* QString GetAppVersion(std::wstring const &app_name) { diff --git a/src/gamegamebryo.h b/src/gamegamebryo.h index 29131c22..b52a8a7a 100644 --- a/src/gamegamebryo.h +++ b/src/gamegamebryo.h @@ -7,6 +7,7 @@ class ScriptExtender; class DataArchives; class SaveGameInfo; class BSAInvalidation; +class LocalSavegames; #include #include @@ -83,6 +84,7 @@ protected: std::shared_ptr m_ScriptExtender { nullptr }; std::shared_ptr m_DataArchives { nullptr }; std::shared_ptr m_BSAInvalidation { nullptr }; + std::shared_ptr m_LocalSavegames { nullptr }; std::shared_ptr m_SaveGameInfo { nullptr }; private: From 21ae45953e4f297a915625eb194fbbad8068737c Mon Sep 17 00:00:00 2001 From: Tannin Date: Mon, 28 Dec 2015 14:21:50 +0100 Subject: [PATCH 0195/1544] normalized function naming --- src/CMakeLists.txt | 5 +++-- src/gamegamebryo.cpp | 16 ++++++++-------- src/gamegamebryo.h | 6 +++--- 3 files changed, 14 insertions(+), 13 deletions(-) diff --git a/src/CMakeLists.txt b/src/CMakeLists.txt index dfbeaaeb..de40470f 100644 --- a/src/CMakeLists.txt +++ b/src/CMakeLists.txt @@ -39,10 +39,11 @@ ADD_LIBRARY(${PROJ_NAME} STATIC ${${PROJ_NAME}_HDRS} ${${PROJ_NAME}_SRCS} ${${PR TARGET_LINK_LIBRARIES(${PROJ_NAME} Qt5::Widgets ${Boost_LIBRARIES} - uibase) + uibase + Version) SET_TARGET_PROPERTIES(${PROJ_NAME} PROPERTIES COMPILE_FLAGS /GL) -SET_TARGET_PROPERTIES(${PROJ_NAME} PROPERTIES LINK_FLAGS_RELWITHDEBINFO "/LTCG /LARGEADDRESSAWARE /OPT:REF /OPT:ICF") +SET_TARGET_PROPERTIES(${PROJ_NAME} PROPERTIES LINK_FLAGS_RELWITHDEBINFO "/LARGEADDRESSAWARE ${OPTIMIZE_LINK_FLAGS}") QT5_USE_MODULES(${PROJ_NAME} Widgets) diff --git a/src/gamegamebryo.cpp b/src/gamegamebryo.cpp index 2502418f..b73b5edc 100644 --- a/src/gamegamebryo.cpp +++ b/src/gamegamebryo.cpp @@ -26,7 +26,7 @@ bool GameGamebryo::isInstalled() const QIcon GameGamebryo::gameIcon() const { - return MOBase::iconForExecutable(gameDirectory().absoluteFilePath(getBinaryName())); + return MOBase::iconForExecutable(gameDirectory().absoluteFilePath(binaryName())); } QDir GameGamebryo::gameDirectory() const @@ -64,12 +64,12 @@ void GameGamebryo::setGameVariant(const QString &variant) m_GameVariant = variant; } -QString GameGamebryo::getBinaryName() const +QString GameGamebryo::binaryName() const { - return getGameShortName() + ".exe"; + return gameShortName() + ".exe"; } -MOBase::IPluginGame::LoadOrderMechanism GameGamebryo::getLoadOrderMechanism() const +MOBase::IPluginGame::LoadOrderMechanism GameGamebryo::loadOrderMechanism() const { return LoadOrderMechanism::FileTime; } @@ -77,17 +77,17 @@ MOBase::IPluginGame::LoadOrderMechanism GameGamebryo::getLoadOrderMechanism() co bool GameGamebryo::looksValid(QDir const &path) const { //Check for .exe and Launcher.exe for now. - return path.exists(getBinaryName()) && path.exists(getLauncherName()); + return path.exists(binaryName()) && path.exists(getLauncherName()); } -QString GameGamebryo::getGameVersion() const +QString GameGamebryo::gameVersion() const { - return getVersion(getBinaryName()); + return getVersion(binaryName()); } QString GameGamebryo::getLauncherName() const { - return getGameShortName() + "Launcher.exe"; + return gameShortName() + "Launcher.exe"; } QString GameGamebryo::getVersion(const QString &program) const diff --git a/src/gamegamebryo.h b/src/gamegamebryo.h index 29131c22..c1edd61c 100644 --- a/src/gamegamebryo.h +++ b/src/gamegamebryo.h @@ -43,15 +43,15 @@ public: // IPluginGame interface //getPrimaryPlugins virtual QStringList gameVariants() const override; virtual void setGameVariant(const QString &variant) override; - virtual QString getBinaryName() const override; + virtual QString binaryName() const override; //getGameShortName //getIniFiles //getDLCPlugins - virtual LoadOrderMechanism getLoadOrderMechanism() const override; + virtual LoadOrderMechanism loadOrderMechanism() const override; //getNexusModOrganizerID //getNexusGameID virtual bool looksValid(QDir const &) const override; - virtual QString getGameVersion() const override; + virtual QString gameVersion() const override; public: // IPluginFileMapper interface From 207c27e67c21a52cda763b08cb49a3c009acb7a5 Mon Sep 17 00:00:00 2001 From: Tannin Date: Mon, 28 Dec 2015 14:51:33 +0100 Subject: [PATCH 0196/1544] [game_fallout4vr] removed get-prefix from getters --- src/games/fallout4vr/src/CMakeLists.txt | 3 ++- src/games/fallout4vr/src/gamefallout4.cpp | 14 +++++++------- src/games/fallout4vr/src/gamefallout4.h | 12 ++++++------ 3 files changed, 15 insertions(+), 14 deletions(-) diff --git a/src/games/fallout4vr/src/CMakeLists.txt b/src/games/fallout4vr/src/CMakeLists.txt index 08e9431d..a0c7f656 100644 --- a/src/games/fallout4vr/src/CMakeLists.txt +++ b/src/games/fallout4vr/src/CMakeLists.txt @@ -40,10 +40,11 @@ TARGET_LINK_LIBRARIES(${PROJ_NAME} Qt5::Widgets ${Boost_LIBRARIES} uibase + Version gameGamebryo) SET_TARGET_PROPERTIES(${PROJ_NAME} PROPERTIES COMPILE_FLAGS /GL) -SET_TARGET_PROPERTIES(${PROJ_NAME} PROPERTIES LINK_FLAGS_RELWITHDEBINFO "/LTCG /LARGEADDRESSAWARE /OPT:REF /OPT:ICF") +SET_TARGET_PROPERTIES(${PROJ_NAME} PROPERTIES LINK_FLAGS_RELWITHDEBINFO "/LARGEADDRESSAWARE ${OPTIMIZE_LINK_FLAGS}") QT5_USE_MODULES(${PROJ_NAME} Widgets) diff --git a/src/games/fallout4vr/src/gamefallout4.cpp b/src/games/fallout4vr/src/gamefallout4.cpp index 8482df89..35160c0c 100644 --- a/src/games/fallout4vr/src/gamefallout4.cpp +++ b/src/games/fallout4vr/src/gamefallout4.cpp @@ -54,7 +54,7 @@ QList GameFallout4::executables() const { return QList() << ExecutableInfo("F4SE", findInGameFolder(m_ScriptExtender->loaderName())) - << ExecutableInfo("Fallout 4", findInGameFolder(getBinaryName())) + << ExecutableInfo("Fallout 4", findInGameFolder(binaryName())) << ExecutableInfo("Fallout Launcher", findInGameFolder(getLauncherName())) << ExecutableInfo("LOOT", getLootPath()) ; @@ -132,7 +132,7 @@ QString GameFallout4::steamAPPId() const return "377160"; } -QStringList GameFallout4::getPrimaryPlugins() const +QStringList GameFallout4::primaryPlugins() const { return { "fallout4.esm" }; } @@ -142,17 +142,17 @@ QStringList GameFallout4::gameVariants() const return { "Regular" }; } -QString GameFallout4::getGameShortName() const +QString GameFallout4::gameShortName() const { return "Fallout4"; } -QStringList GameFallout4::getIniFiles() const +QStringList GameFallout4::iniFiles() const { return { "fallout4.ini", "fallout4prefs.ini" }; } -QStringList GameFallout4::getDLCPlugins() const +QStringList GameFallout4::DLCPlugins() const { return {}; } @@ -160,12 +160,12 @@ QStringList GameFallout4::getDLCPlugins() const //what load order mechanism? // virtual LoadOrderMechanism getLoadOrderMechanism() const = 0; -int GameFallout4::getNexusModOrganizerID() const +int GameFallout4::nexusModOrganizerID() const { return 0; //... } -int GameFallout4::getNexusGameID() const +int GameFallout4::nexusGameID() const { return 1151; } diff --git a/src/games/fallout4vr/src/gamefallout4.h b/src/games/fallout4vr/src/gamefallout4.h index 612a37df..c1884e55 100644 --- a/src/games/fallout4vr/src/gamefallout4.h +++ b/src/games/fallout4vr/src/gamefallout4.h @@ -23,15 +23,15 @@ public: // IPluginGame interface virtual void initializeProfile(const QDir &path, ProfileSettings settings) const override; virtual QString savegameExtension() const override; virtual QString steamAPPId() const override; - virtual QStringList getPrimaryPlugins() const override; + virtual QStringList primaryPlugins() const override; virtual QStringList gameVariants() const override; - virtual QString getGameShortName() const override; - virtual QStringList getIniFiles() const override; - virtual QStringList getDLCPlugins() const override; + virtual QString gameShortName() const override; + virtual QStringList iniFiles() const override; + virtual QStringList DLCPlugins() const override; //what load order mechanism? // virtual LoadOrderMechanism getLoadOrderMechanism() const = 0; - virtual int getNexusModOrganizerID() const override; - virtual int getNexusGameID() const override; + virtual int nexusModOrganizerID() const override; + virtual int nexusGameID() const override; public: // IPlugin interface From 69779ffdb8034a027938ee1c43523f99c0298af3 Mon Sep 17 00:00:00 2001 From: Tannin Date: Mon, 28 Dec 2015 14:51:33 +0100 Subject: [PATCH 0197/1544] [game_fallout76] removed get-prefix from getters --- src/games/fallout76/src/CMakeLists.txt | 3 ++- src/games/fallout76/src/gamefallout4.cpp | 14 +++++++------- src/games/fallout76/src/gamefallout4.h | 12 ++++++------ 3 files changed, 15 insertions(+), 14 deletions(-) diff --git a/src/games/fallout76/src/CMakeLists.txt b/src/games/fallout76/src/CMakeLists.txt index 08e9431d..a0c7f656 100644 --- a/src/games/fallout76/src/CMakeLists.txt +++ b/src/games/fallout76/src/CMakeLists.txt @@ -40,10 +40,11 @@ TARGET_LINK_LIBRARIES(${PROJ_NAME} Qt5::Widgets ${Boost_LIBRARIES} uibase + Version gameGamebryo) SET_TARGET_PROPERTIES(${PROJ_NAME} PROPERTIES COMPILE_FLAGS /GL) -SET_TARGET_PROPERTIES(${PROJ_NAME} PROPERTIES LINK_FLAGS_RELWITHDEBINFO "/LTCG /LARGEADDRESSAWARE /OPT:REF /OPT:ICF") +SET_TARGET_PROPERTIES(${PROJ_NAME} PROPERTIES LINK_FLAGS_RELWITHDEBINFO "/LARGEADDRESSAWARE ${OPTIMIZE_LINK_FLAGS}") QT5_USE_MODULES(${PROJ_NAME} Widgets) diff --git a/src/games/fallout76/src/gamefallout4.cpp b/src/games/fallout76/src/gamefallout4.cpp index 8482df89..35160c0c 100644 --- a/src/games/fallout76/src/gamefallout4.cpp +++ b/src/games/fallout76/src/gamefallout4.cpp @@ -54,7 +54,7 @@ QList GameFallout4::executables() const { return QList() << ExecutableInfo("F4SE", findInGameFolder(m_ScriptExtender->loaderName())) - << ExecutableInfo("Fallout 4", findInGameFolder(getBinaryName())) + << ExecutableInfo("Fallout 4", findInGameFolder(binaryName())) << ExecutableInfo("Fallout Launcher", findInGameFolder(getLauncherName())) << ExecutableInfo("LOOT", getLootPath()) ; @@ -132,7 +132,7 @@ QString GameFallout4::steamAPPId() const return "377160"; } -QStringList GameFallout4::getPrimaryPlugins() const +QStringList GameFallout4::primaryPlugins() const { return { "fallout4.esm" }; } @@ -142,17 +142,17 @@ QStringList GameFallout4::gameVariants() const return { "Regular" }; } -QString GameFallout4::getGameShortName() const +QString GameFallout4::gameShortName() const { return "Fallout4"; } -QStringList GameFallout4::getIniFiles() const +QStringList GameFallout4::iniFiles() const { return { "fallout4.ini", "fallout4prefs.ini" }; } -QStringList GameFallout4::getDLCPlugins() const +QStringList GameFallout4::DLCPlugins() const { return {}; } @@ -160,12 +160,12 @@ QStringList GameFallout4::getDLCPlugins() const //what load order mechanism? // virtual LoadOrderMechanism getLoadOrderMechanism() const = 0; -int GameFallout4::getNexusModOrganizerID() const +int GameFallout4::nexusModOrganizerID() const { return 0; //... } -int GameFallout4::getNexusGameID() const +int GameFallout4::nexusGameID() const { return 1151; } diff --git a/src/games/fallout76/src/gamefallout4.h b/src/games/fallout76/src/gamefallout4.h index 612a37df..c1884e55 100644 --- a/src/games/fallout76/src/gamefallout4.h +++ b/src/games/fallout76/src/gamefallout4.h @@ -23,15 +23,15 @@ public: // IPluginGame interface virtual void initializeProfile(const QDir &path, ProfileSettings settings) const override; virtual QString savegameExtension() const override; virtual QString steamAPPId() const override; - virtual QStringList getPrimaryPlugins() const override; + virtual QStringList primaryPlugins() const override; virtual QStringList gameVariants() const override; - virtual QString getGameShortName() const override; - virtual QStringList getIniFiles() const override; - virtual QStringList getDLCPlugins() const override; + virtual QString gameShortName() const override; + virtual QStringList iniFiles() const override; + virtual QStringList DLCPlugins() const override; //what load order mechanism? // virtual LoadOrderMechanism getLoadOrderMechanism() const = 0; - virtual int getNexusModOrganizerID() const override; - virtual int getNexusGameID() const override; + virtual int nexusModOrganizerID() const override; + virtual int nexusGameID() const override; public: // IPlugin interface From 129b13c5f1eeb0c87b26cd605909e02fae29430d Mon Sep 17 00:00:00 2001 From: Tannin Date: Mon, 28 Dec 2015 14:51:33 +0100 Subject: [PATCH 0198/1544] [game_fallout4] removed get-prefix from getters --- src/games/fallout4/src/CMakeLists.txt | 3 ++- src/games/fallout4/src/gamefallout4.cpp | 14 +++++++------- src/games/fallout4/src/gamefallout4.h | 12 ++++++------ 3 files changed, 15 insertions(+), 14 deletions(-) diff --git a/src/games/fallout4/src/CMakeLists.txt b/src/games/fallout4/src/CMakeLists.txt index 08e9431d..a0c7f656 100644 --- a/src/games/fallout4/src/CMakeLists.txt +++ b/src/games/fallout4/src/CMakeLists.txt @@ -40,10 +40,11 @@ TARGET_LINK_LIBRARIES(${PROJ_NAME} Qt5::Widgets ${Boost_LIBRARIES} uibase + Version gameGamebryo) SET_TARGET_PROPERTIES(${PROJ_NAME} PROPERTIES COMPILE_FLAGS /GL) -SET_TARGET_PROPERTIES(${PROJ_NAME} PROPERTIES LINK_FLAGS_RELWITHDEBINFO "/LTCG /LARGEADDRESSAWARE /OPT:REF /OPT:ICF") +SET_TARGET_PROPERTIES(${PROJ_NAME} PROPERTIES LINK_FLAGS_RELWITHDEBINFO "/LARGEADDRESSAWARE ${OPTIMIZE_LINK_FLAGS}") QT5_USE_MODULES(${PROJ_NAME} Widgets) diff --git a/src/games/fallout4/src/gamefallout4.cpp b/src/games/fallout4/src/gamefallout4.cpp index 8482df89..35160c0c 100644 --- a/src/games/fallout4/src/gamefallout4.cpp +++ b/src/games/fallout4/src/gamefallout4.cpp @@ -54,7 +54,7 @@ QList GameFallout4::executables() const { return QList() << ExecutableInfo("F4SE", findInGameFolder(m_ScriptExtender->loaderName())) - << ExecutableInfo("Fallout 4", findInGameFolder(getBinaryName())) + << ExecutableInfo("Fallout 4", findInGameFolder(binaryName())) << ExecutableInfo("Fallout Launcher", findInGameFolder(getLauncherName())) << ExecutableInfo("LOOT", getLootPath()) ; @@ -132,7 +132,7 @@ QString GameFallout4::steamAPPId() const return "377160"; } -QStringList GameFallout4::getPrimaryPlugins() const +QStringList GameFallout4::primaryPlugins() const { return { "fallout4.esm" }; } @@ -142,17 +142,17 @@ QStringList GameFallout4::gameVariants() const return { "Regular" }; } -QString GameFallout4::getGameShortName() const +QString GameFallout4::gameShortName() const { return "Fallout4"; } -QStringList GameFallout4::getIniFiles() const +QStringList GameFallout4::iniFiles() const { return { "fallout4.ini", "fallout4prefs.ini" }; } -QStringList GameFallout4::getDLCPlugins() const +QStringList GameFallout4::DLCPlugins() const { return {}; } @@ -160,12 +160,12 @@ QStringList GameFallout4::getDLCPlugins() const //what load order mechanism? // virtual LoadOrderMechanism getLoadOrderMechanism() const = 0; -int GameFallout4::getNexusModOrganizerID() const +int GameFallout4::nexusModOrganizerID() const { return 0; //... } -int GameFallout4::getNexusGameID() const +int GameFallout4::nexusGameID() const { return 1151; } diff --git a/src/games/fallout4/src/gamefallout4.h b/src/games/fallout4/src/gamefallout4.h index 612a37df..c1884e55 100644 --- a/src/games/fallout4/src/gamefallout4.h +++ b/src/games/fallout4/src/gamefallout4.h @@ -23,15 +23,15 @@ public: // IPluginGame interface virtual void initializeProfile(const QDir &path, ProfileSettings settings) const override; virtual QString savegameExtension() const override; virtual QString steamAPPId() const override; - virtual QStringList getPrimaryPlugins() const override; + virtual QStringList primaryPlugins() const override; virtual QStringList gameVariants() const override; - virtual QString getGameShortName() const override; - virtual QStringList getIniFiles() const override; - virtual QStringList getDLCPlugins() const override; + virtual QString gameShortName() const override; + virtual QStringList iniFiles() const override; + virtual QStringList DLCPlugins() const override; //what load order mechanism? // virtual LoadOrderMechanism getLoadOrderMechanism() const = 0; - virtual int getNexusModOrganizerID() const override; - virtual int getNexusGameID() const override; + virtual int nexusModOrganizerID() const override; + virtual int nexusGameID() const override; public: // IPlugin interface From 601b9d9610e0833bb3b1e109327e07df5c936b3a Mon Sep 17 00:00:00 2001 From: Tannin Date: Sun, 10 Jan 2016 19:53:06 +0100 Subject: [PATCH 0199/1544] [game_fallout3] added missing link to version-library in cmake script --- src/games/fallout3/src/CMakeLists.txt | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/src/games/fallout3/src/CMakeLists.txt b/src/games/fallout3/src/CMakeLists.txt index 08e9431d..be1bb063 100644 --- a/src/games/fallout3/src/CMakeLists.txt +++ b/src/games/fallout3/src/CMakeLists.txt @@ -40,7 +40,8 @@ TARGET_LINK_LIBRARIES(${PROJ_NAME} Qt5::Widgets ${Boost_LIBRARIES} uibase - gameGamebryo) + gameGamebryo + Version) SET_TARGET_PROPERTIES(${PROJ_NAME} PROPERTIES COMPILE_FLAGS /GL) SET_TARGET_PROPERTIES(${PROJ_NAME} PROPERTIES LINK_FLAGS_RELWITHDEBINFO "/LTCG /LARGEADDRESSAWARE /OPT:REF /OPT:ICF") From 39464d5e49e97c9b670d4be2ba5c23e5934b4688 Mon Sep 17 00:00:00 2001 From: Tannin Date: Sun, 10 Jan 2016 19:53:42 +0100 Subject: [PATCH 0200/1544] [game_skyrim] added missing link to version-library in cmake script --- src/games/skyrim/src/CMakeLists.txt | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/src/games/skyrim/src/CMakeLists.txt b/src/games/skyrim/src/CMakeLists.txt index 08e9431d..e3e757f0 100644 --- a/src/games/skyrim/src/CMakeLists.txt +++ b/src/games/skyrim/src/CMakeLists.txt @@ -1,4 +1,4 @@ -CMAKE_MINIMUM_REQUIRED (VERSION 2.8) +CMAKE_MINIMUM_REQUIRED (VERSION 1.8) CMAKE_POLICY(SET CMP0020 NEW) @@ -34,13 +34,15 @@ INCLUDE_DIRECTORIES(${project_path}/uibase/src LINK_DIRECTORIES(${project_path}/uibase/build/src ${lib_path}) +ADD_DEFINITIONS(-DUNICODE -D_UNICODE) ADD_LIBRARY(${PROJ_NAME} SHARED ${${PROJ_NAME}_HDRS} ${${PROJ_NAME}_SRCS} ${${PROJ_NAME}_UIHDRS}) TARGET_LINK_LIBRARIES(${PROJ_NAME} Qt5::Widgets ${Boost_LIBRARIES} uibase - gameGamebryo) + gameGamebryo + version) SET_TARGET_PROPERTIES(${PROJ_NAME} PROPERTIES COMPILE_FLAGS /GL) SET_TARGET_PROPERTIES(${PROJ_NAME} PROPERTIES LINK_FLAGS_RELWITHDEBINFO "/LTCG /LARGEADDRESSAWARE /OPT:REF /OPT:ICF") From 10a727d31c23e9fb77e5e3a64c530d7bc43e3bb3 Mon Sep 17 00:00:00 2001 From: Thomas Tanner Date: Sun, 24 Jan 2016 15:18:54 +0000 Subject: [PATCH 0201/1544] [game_fallout3] Removing the 'get' in all function names and making FO4 plugin build --- src/games/fallout3/src/gamefallout3.cpp | 14 +++++++------- src/games/fallout3/src/gamefallout3.h | 12 ++++++------ 2 files changed, 13 insertions(+), 13 deletions(-) diff --git a/src/games/fallout3/src/gamefallout3.cpp b/src/games/fallout3/src/gamefallout3.cpp index 1a49320c..5434c9f0 100644 --- a/src/games/fallout3/src/gamefallout3.cpp +++ b/src/games/fallout3/src/gamefallout3.cpp @@ -55,7 +55,7 @@ QList GameFallout3::executables() const { return QList() << ExecutableInfo("FOSE", findInGameFolder(m_ScriptExtender->loaderName())) - << ExecutableInfo("Fallout 3", findInGameFolder(getBinaryName())) + << ExecutableInfo("Fallout 3", findInGameFolder(binaryName())) << ExecutableInfo("Fallout Mod Manager", findInGameFolder("fomm/fomm.exe")) << ExecutableInfo("Construction Kit", findInGameFolder("geck.exe")) << ExecutableInfo("Fallout Launcher", findInGameFolder(getLauncherName())) @@ -140,7 +140,7 @@ QString GameFallout3::steamAPPId() const } } -QStringList GameFallout3::getPrimaryPlugins() const +QStringList GameFallout3::primaryPlugins() const { return { "fallout3.esm" }; } @@ -151,27 +151,27 @@ QStringList GameFallout3::gameVariants() const return { "Regular", "Game Of The Year" }; } -QString GameFallout3::getGameShortName() const +QString GameFallout3::gameShortName() const { return "Fallout3"; } -QStringList GameFallout3::getIniFiles() const +QStringList GameFallout3::iniFiles() const { return { "fallout.ini", "falloutprefs.ini" }; } -QStringList GameFallout3::getDLCPlugins() const +QStringList GameFallout3::DLCPlugins() const { return { "ThePitt.esm", "Anchorage.esm", "BrokenSteel.esm", "PointLookout.esm", "Zeta.esm" }; } -int GameFallout3::getNexusModOrganizerID() const +int GameFallout3::nexusModOrganizerID() const { return 16348; } -int GameFallout3::getNexusGameID() const +int GameFallout3::nexusGameID() const { return 120; } diff --git a/src/games/fallout3/src/gamefallout3.h b/src/games/fallout3/src/gamefallout3.h index 2e4fc464..0d76b0a3 100644 --- a/src/games/fallout3/src/gamefallout3.h +++ b/src/games/fallout3/src/gamefallout3.h @@ -23,13 +23,13 @@ public: // IPluginGame interface virtual void initializeProfile(const QDir &path, ProfileSettings settings) const override; virtual QString savegameExtension() const override; virtual QString steamAPPId() const override; - virtual QStringList getPrimaryPlugins() const override; + virtual QStringList primaryPlugins() const override; virtual QStringList gameVariants() const; - virtual QString getGameShortName() const override; - virtual QStringList getIniFiles() const override; - virtual QStringList getDLCPlugins() const override; - virtual int getNexusModOrganizerID() const override; - virtual int getNexusGameID() const override; + virtual QString gameShortName() const override; + virtual QStringList iniFiles() const override; + virtual QStringList DLCPlugins() const override; + virtual int nexusModOrganizerID() const override; + virtual int nexusGameID() const override; public: // IPlugin interface From 2bf5aefadd81f4666e1a71e8edfff38b9c568a45 Mon Sep 17 00:00:00 2001 From: Thomas Tanner Date: Sun, 24 Jan 2016 15:19:09 +0000 Subject: [PATCH 0202/1544] [game_falloutnv] Removing the 'get' in all function names and making FO4 plugin build --- src/games/falloutnv/src/gamefalloutnv.cpp | 14 +++++++------- src/games/falloutnv/src/gamefalloutnv.h | 12 ++++++------ 2 files changed, 13 insertions(+), 13 deletions(-) diff --git a/src/games/falloutnv/src/gamefalloutnv.cpp b/src/games/falloutnv/src/gamefalloutnv.cpp index bd16daa9..92dd4d70 100644 --- a/src/games/falloutnv/src/gamefalloutnv.cpp +++ b/src/games/falloutnv/src/gamefalloutnv.cpp @@ -53,7 +53,7 @@ QList GameFalloutNV::executables() const { return QList() << ExecutableInfo("NVSE", findInGameFolder(m_ScriptExtender->loaderName())) - << ExecutableInfo("New Vegas", findInGameFolder(getBinaryName())) + << ExecutableInfo("New Vegas", findInGameFolder(binaryName())) << ExecutableInfo("Fallout Mod Manager", findInGameFolder("fomm/fomm.exe")) << ExecutableInfo("Construction Kit", findInGameFolder("geck.exe")) << ExecutableInfo("Fallout Launcher", findInGameFolder(getLauncherName())) @@ -136,34 +136,34 @@ QString GameFalloutNV::steamAPPId() const return "22380"; } -QStringList GameFalloutNV::getPrimaryPlugins() const +QStringList GameFalloutNV::primaryPlugins() const { return { "falloutnv.esm" }; } -QString GameFalloutNV::getGameShortName() const +QString GameFalloutNV::gameShortName() const { return "FalloutNV"; } -QStringList GameFalloutNV::getIniFiles() const +QStringList GameFalloutNV::iniFiles() const { return { "fallout.ini", "falloutprefs.ini" }; } -QStringList GameFalloutNV::getDLCPlugins() const +QStringList GameFalloutNV::DLCPlugins() const { return { "DeadMoney.esm", "HonestHearts.esm", "OldWorldBlues.esm", "LonesomeRoad.esm", "GunRunnersArsenal.esm", "CaravanPack.esm", "ClassicPack.esm", "MercenaryPack.esm", "TribalPack.esm" }; } -int GameFalloutNV::getNexusModOrganizerID() const +int GameFalloutNV::nexusModOrganizerID() const { return 42572; } -int GameFalloutNV::getNexusGameID() const +int GameFalloutNV::nexusGameID() const { return 130; } diff --git a/src/games/falloutnv/src/gamefalloutnv.h b/src/games/falloutnv/src/gamefalloutnv.h index 5335a0b5..cdd96ba5 100644 --- a/src/games/falloutnv/src/gamefalloutnv.h +++ b/src/games/falloutnv/src/gamefalloutnv.h @@ -23,12 +23,12 @@ public: // IPluginGame interface virtual void initializeProfile(const QDir &path, ProfileSettings settings) const override; virtual QString savegameExtension() const override; virtual QString steamAPPId() const override; - virtual QStringList getPrimaryPlugins() const override; - virtual QString getGameShortName() const override; - virtual QStringList getIniFiles() const override; - virtual QStringList getDLCPlugins() const override; - virtual int getNexusModOrganizerID() const override; - virtual int getNexusGameID() const override; + virtual QStringList primaryPlugins() const override; + virtual QString gameShortName() const override; + virtual QStringList iniFiles() const override; + virtual QStringList DLCPlugins() const override; + virtual int nexusModOrganizerID() const override; + virtual int nexusGameID() const override; public: // IPlugin interface From 4487538cad3279eff3a37463d5e4ab3892988874 Mon Sep 17 00:00:00 2001 From: Thomas Tanner Date: Sun, 24 Jan 2016 15:21:06 +0000 Subject: [PATCH 0203/1544] [game_oblivion] Removing the 'get' in all function names and making FO4 plugin build --- src/games/oblivion/src/gameoblivion.cpp | 14 +++++++------- src/games/oblivion/src/gameoblivion.h | 12 ++++++------ 2 files changed, 13 insertions(+), 13 deletions(-) diff --git a/src/games/oblivion/src/gameoblivion.cpp b/src/games/oblivion/src/gameoblivion.cpp index 29723ed7..2bb00f77 100644 --- a/src/games/oblivion/src/gameoblivion.cpp +++ b/src/games/oblivion/src/gameoblivion.cpp @@ -54,7 +54,7 @@ QList GameOblivion::executables() const { return QList() << ExecutableInfo("OBSE", findInGameFolder(m_ScriptExtender->loaderName())) - << ExecutableInfo("Oblivion", findInGameFolder(getBinaryName())) + << ExecutableInfo("Oblivion", findInGameFolder(binaryName())) << ExecutableInfo("Oblivion Launcher", findInGameFolder(getLauncherName())) << ExecutableInfo("Oblivion Mod Manager", findInGameFolder("OblivionModManager.exe")) << ExecutableInfo("BOSS", findInGameFolder("BOSS/BOSS.exe")) @@ -137,22 +137,22 @@ QString GameOblivion::steamAPPId() const return "22330"; } -QStringList GameOblivion::getPrimaryPlugins() const +QStringList GameOblivion::primaryPlugins() const { return { "oblivion.esm", "update.esm" }; } -QString GameOblivion::getGameShortName() const +QString GameOblivion::gameShortName() const { return "Oblivion"; } -QStringList GameOblivion::getIniFiles() const +QStringList GameOblivion::iniFiles() const { return { "oblivion.ini", "oblivionprefs.ini" }; } -QStringList GameOblivion::getDLCPlugins() const +QStringList GameOblivion::DLCPlugins() const { return { "DLCShiveringIsles.esp", "Knights.esp", "DLCFrostcrag.esp", "DLCSpellTomes.esp", "DLCMehrunesRazor.esp", "DLCOrrery.esp", @@ -160,12 +160,12 @@ QStringList GameOblivion::getDLCPlugins() const } -int GameOblivion::getNexusModOrganizerID() const +int GameOblivion::nexusModOrganizerID() const { return 38277; } -int GameOblivion::getNexusGameID() const +int GameOblivion::nexusGameID() const { return 101; } diff --git a/src/games/oblivion/src/gameoblivion.h b/src/games/oblivion/src/gameoblivion.h index e9b795d2..52e60ff3 100644 --- a/src/games/oblivion/src/gameoblivion.h +++ b/src/games/oblivion/src/gameoblivion.h @@ -23,12 +23,12 @@ public: // IPluginGame interface virtual void initializeProfile(const QDir &path, ProfileSettings settings) const override; virtual QString savegameExtension() const override; virtual QString steamAPPId() const override; - virtual QStringList getPrimaryPlugins() const override; - virtual QString getGameShortName() const override; - virtual QStringList getIniFiles() const override; - virtual QStringList getDLCPlugins() const override; - virtual int getNexusModOrganizerID() const override; - virtual int getNexusGameID() const override; + virtual QStringList primaryPlugins() const override; + virtual QString gameShortName() const override; + virtual QStringList iniFiles() const override; + virtual QStringList DLCPlugins() const override; + virtual int nexusModOrganizerID() const override; + virtual int nexusGameID() const override; public: // IPlugin interface From 8c024c0766a1aaada5a0cac1185cf02f2da2f42c Mon Sep 17 00:00:00 2001 From: Thomas Tanner Date: Sun, 24 Jan 2016 15:21:19 +0000 Subject: [PATCH 0204/1544] [game_skyrim] Removing the 'get' in all function names and making FO4 plugin build --- src/games/skyrim/src/gameskyrim.cpp | 20 ++++++++++---------- src/games/skyrim/src/gameskyrim.h | 16 ++++++++-------- 2 files changed, 18 insertions(+), 18 deletions(-) diff --git a/src/games/skyrim/src/gameskyrim.cpp b/src/games/skyrim/src/gameskyrim.cpp index 567f8937..110b8723 100644 --- a/src/games/skyrim/src/gameskyrim.cpp +++ b/src/games/skyrim/src/gameskyrim.cpp @@ -62,7 +62,7 @@ QList GameSkyrim::executables() const return QList() << ExecutableInfo("SKSE", findInGameFolder(m_ScriptExtender->loaderName())) << ExecutableInfo("SBW", findInGameFolder("SBW.exe")) - << ExecutableInfo("Skyrim", findInGameFolder(getBinaryName())) + << ExecutableInfo("Skyrim", findInGameFolder(binaryName())) << ExecutableInfo("Skyrim Launcher", findInGameFolder(getLauncherName())) << ExecutableInfo("BOSS", findInGameFolder("BOSS/BOSS.exe")) << ExecutableInfo("LOOT", getLootPath()) @@ -144,27 +144,27 @@ QString GameSkyrim::steamAPPId() const return "72850"; } -QStringList GameSkyrim::getPrimaryPlugins() const +QStringList GameSkyrim::primaryPlugins() const { return { "skyrim.esm", "update.esm" }; } -QString GameSkyrim::getBinaryName() const +QString GameSkyrim::binaryName() const { return "TESV.exe"; } -QString GameSkyrim::getGameShortName() const +QString GameSkyrim::gameShortName() const { return "Skyrim"; } -QStringList GameSkyrim::getIniFiles() const +QStringList GameSkyrim::iniFiles() const { return { "skyrim.ini", "skyrimprefs.ini" }; } -QStringList GameSkyrim::getDLCPlugins() const +QStringList GameSkyrim::DLCPlugins() const { return { "Dawnguard.esm", "Dragonborn.esm", "HearthFires.esm", "HighResTexturePack01.esp", "HighResTexturePack02.esp", "HighResTexturePack03.esp" }; @@ -200,10 +200,10 @@ VS_FIXEDFILEINFO GetFileVersion(const std::wstring &fileName) } -IPluginGame::LoadOrderMechanism GameSkyrim::getLoadOrderMechanism() const +IPluginGame::LoadOrderMechanism GameSkyrim::loadOrderMechanism() const { try { - std::wstring fileName = gameDirectory().absoluteFilePath(getBinaryName()).toStdWString().c_str(); + std::wstring fileName = gameDirectory().absoluteFilePath(binaryName()).toStdWString().c_str(); VS_FIXEDFILEINFO versionInfo = ::GetFileVersion(fileName); if ((versionInfo.dwFileVersionMS > 0x10004) || // version >= 1.5.x? ((versionInfo.dwFileVersionMS == 0x10004) && (versionInfo.dwFileVersionLS >= 0x1A0000))) { // version >= ?.4.26 @@ -216,12 +216,12 @@ IPluginGame::LoadOrderMechanism GameSkyrim::getLoadOrderMechanism() const } -int GameSkyrim::getNexusModOrganizerID() const +int GameSkyrim::nexusModOrganizerID() const { return 1334; } -int GameSkyrim::getNexusGameID() const +int GameSkyrim::nexusGameID() const { return 110; } diff --git a/src/games/skyrim/src/gameskyrim.h b/src/games/skyrim/src/gameskyrim.h index ed8bef6f..e0730b50 100644 --- a/src/games/skyrim/src/gameskyrim.h +++ b/src/games/skyrim/src/gameskyrim.h @@ -23,14 +23,14 @@ public: // IPluginGame interface virtual void initializeProfile(const QDir &path, ProfileSettings settings) const override; virtual QString savegameExtension() const override; virtual QString steamAPPId() const override; - virtual QStringList getPrimaryPlugins() const override; - virtual QString getBinaryName() const override; - virtual QString getGameShortName() const override; - virtual QStringList getIniFiles() const override; - virtual QStringList getDLCPlugins() const override; - virtual LoadOrderMechanism getLoadOrderMechanism() const override; - virtual int getNexusModOrganizerID() const override; - virtual int getNexusGameID() const override; + virtual QStringList primaryPlugins() const override; + virtual QString binaryName() const override; + virtual QString gameShortName() const override; + virtual QStringList iniFiles() const override; + virtual QStringList DLCPlugins() const override; + virtual LoadOrderMechanism loadOrderMechanism() const override; + virtual int nexusModOrganizerID() const override; + virtual int nexusGameID() const override; public: // IPlugin interface From 668d16c2e4a2271bed2afafb7889083221a8f450 Mon Sep 17 00:00:00 2001 From: Thomas Tanner Date: Sun, 24 Jan 2016 18:09:36 +0000 Subject: [PATCH 0205/1544] [game_fallout4vr] Upate from mainline and remove hackies --- src/games/fallout4vr/src/gamefallout4.cpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/games/fallout4vr/src/gamefallout4.cpp b/src/games/fallout4vr/src/gamefallout4.cpp index 19738365..9dcdf1b4 100644 --- a/src/games/fallout4vr/src/gamefallout4.cpp +++ b/src/games/fallout4vr/src/gamefallout4.cpp @@ -7,7 +7,7 @@ #include #include "iplugingame.h" #include -//**#include +#include #include "versioninfo.h" #include @@ -33,7 +33,7 @@ bool GameFallout4::init(IOrganizer *moInfo) } m_ScriptExtender = std::shared_ptr(new Fallout4ScriptExtender(this)); m_DataArchives = std::shared_ptr(new Fallout4DataArchives()); -//** m_LocalSavegames.reset(new GamebryoLocalSavegames(myGamesPath(), "Fallout4.ini")); + m_LocalSavegames.reset(new GamebryoLocalSavegames(myGamesPath(), "Fallout4.ini")); m_SaveGameInfo = std::shared_ptr(new Fallout4SaveGameInfo(this)); return true; } From 96886f290d290bc45a4f8c62bea0ac8a2330685c Mon Sep 17 00:00:00 2001 From: Thomas Tanner Date: Sun, 24 Jan 2016 18:09:36 +0000 Subject: [PATCH 0206/1544] [game_fallout76] Upate from mainline and remove hackies --- src/games/fallout76/src/gamefallout4.cpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/games/fallout76/src/gamefallout4.cpp b/src/games/fallout76/src/gamefallout4.cpp index 19738365..9dcdf1b4 100644 --- a/src/games/fallout76/src/gamefallout4.cpp +++ b/src/games/fallout76/src/gamefallout4.cpp @@ -7,7 +7,7 @@ #include #include "iplugingame.h" #include -//**#include +#include #include "versioninfo.h" #include @@ -33,7 +33,7 @@ bool GameFallout4::init(IOrganizer *moInfo) } m_ScriptExtender = std::shared_ptr(new Fallout4ScriptExtender(this)); m_DataArchives = std::shared_ptr(new Fallout4DataArchives()); -//** m_LocalSavegames.reset(new GamebryoLocalSavegames(myGamesPath(), "Fallout4.ini")); + m_LocalSavegames.reset(new GamebryoLocalSavegames(myGamesPath(), "Fallout4.ini")); m_SaveGameInfo = std::shared_ptr(new Fallout4SaveGameInfo(this)); return true; } From bffffe1f25bf2ae395fd5e4132ecf8bfa9557f1c Mon Sep 17 00:00:00 2001 From: Thomas Tanner Date: Sun, 24 Jan 2016 18:09:36 +0000 Subject: [PATCH 0207/1544] [game_fallout4] Upate from mainline and remove hackies --- src/games/fallout4/src/gamefallout4.cpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/games/fallout4/src/gamefallout4.cpp b/src/games/fallout4/src/gamefallout4.cpp index 19738365..9dcdf1b4 100644 --- a/src/games/fallout4/src/gamefallout4.cpp +++ b/src/games/fallout4/src/gamefallout4.cpp @@ -7,7 +7,7 @@ #include #include "iplugingame.h" #include -//**#include +#include #include "versioninfo.h" #include @@ -33,7 +33,7 @@ bool GameFallout4::init(IOrganizer *moInfo) } m_ScriptExtender = std::shared_ptr(new Fallout4ScriptExtender(this)); m_DataArchives = std::shared_ptr(new Fallout4DataArchives()); -//** m_LocalSavegames.reset(new GamebryoLocalSavegames(myGamesPath(), "Fallout4.ini")); + m_LocalSavegames.reset(new GamebryoLocalSavegames(myGamesPath(), "Fallout4.ini")); m_SaveGameInfo = std::shared_ptr(new Fallout4SaveGameInfo(this)); return true; } From f05e6b3240cf3eaef1bcfe0d24fd77b50866f154 Mon Sep 17 00:00:00 2001 From: Tannin Date: Tue, 9 Feb 2016 19:37:30 +0100 Subject: [PATCH 0208/1544] [game_fallout3] removed get prefix from getters --- src/games/fallout3/src/gamefallout3.cpp | 14 +++++++------- src/games/fallout3/src/gamefallout3.h | 12 ++++++------ 2 files changed, 13 insertions(+), 13 deletions(-) diff --git a/src/games/fallout3/src/gamefallout3.cpp b/src/games/fallout3/src/gamefallout3.cpp index 1a49320c..5434c9f0 100644 --- a/src/games/fallout3/src/gamefallout3.cpp +++ b/src/games/fallout3/src/gamefallout3.cpp @@ -55,7 +55,7 @@ QList GameFallout3::executables() const { return QList() << ExecutableInfo("FOSE", findInGameFolder(m_ScriptExtender->loaderName())) - << ExecutableInfo("Fallout 3", findInGameFolder(getBinaryName())) + << ExecutableInfo("Fallout 3", findInGameFolder(binaryName())) << ExecutableInfo("Fallout Mod Manager", findInGameFolder("fomm/fomm.exe")) << ExecutableInfo("Construction Kit", findInGameFolder("geck.exe")) << ExecutableInfo("Fallout Launcher", findInGameFolder(getLauncherName())) @@ -140,7 +140,7 @@ QString GameFallout3::steamAPPId() const } } -QStringList GameFallout3::getPrimaryPlugins() const +QStringList GameFallout3::primaryPlugins() const { return { "fallout3.esm" }; } @@ -151,27 +151,27 @@ QStringList GameFallout3::gameVariants() const return { "Regular", "Game Of The Year" }; } -QString GameFallout3::getGameShortName() const +QString GameFallout3::gameShortName() const { return "Fallout3"; } -QStringList GameFallout3::getIniFiles() const +QStringList GameFallout3::iniFiles() const { return { "fallout.ini", "falloutprefs.ini" }; } -QStringList GameFallout3::getDLCPlugins() const +QStringList GameFallout3::DLCPlugins() const { return { "ThePitt.esm", "Anchorage.esm", "BrokenSteel.esm", "PointLookout.esm", "Zeta.esm" }; } -int GameFallout3::getNexusModOrganizerID() const +int GameFallout3::nexusModOrganizerID() const { return 16348; } -int GameFallout3::getNexusGameID() const +int GameFallout3::nexusGameID() const { return 120; } diff --git a/src/games/fallout3/src/gamefallout3.h b/src/games/fallout3/src/gamefallout3.h index 2e4fc464..0d76b0a3 100644 --- a/src/games/fallout3/src/gamefallout3.h +++ b/src/games/fallout3/src/gamefallout3.h @@ -23,13 +23,13 @@ public: // IPluginGame interface virtual void initializeProfile(const QDir &path, ProfileSettings settings) const override; virtual QString savegameExtension() const override; virtual QString steamAPPId() const override; - virtual QStringList getPrimaryPlugins() const override; + virtual QStringList primaryPlugins() const override; virtual QStringList gameVariants() const; - virtual QString getGameShortName() const override; - virtual QStringList getIniFiles() const override; - virtual QStringList getDLCPlugins() const override; - virtual int getNexusModOrganizerID() const override; - virtual int getNexusGameID() const override; + virtual QString gameShortName() const override; + virtual QStringList iniFiles() const override; + virtual QStringList DLCPlugins() const override; + virtual int nexusModOrganizerID() const override; + virtual int nexusGameID() const override; public: // IPlugin interface From ac685484b447b88fa4f3c940c79e488cc112d53d Mon Sep 17 00:00:00 2001 From: Tannin Date: Tue, 9 Feb 2016 19:38:24 +0100 Subject: [PATCH 0209/1544] [game_fallout3] renamed project (and thus the output filename) --- src/games/fallout3/CMakeLists.txt | 4 ++-- src/games/fallout3/src/gamefallout3.h | 2 -- 2 files changed, 2 insertions(+), 4 deletions(-) diff --git a/src/games/fallout3/CMakeLists.txt b/src/games/fallout3/CMakeLists.txt index 4e429db1..148045e3 100644 --- a/src/games/fallout3/CMakeLists.txt +++ b/src/games/fallout3/CMakeLists.txt @@ -1,6 +1,6 @@ CMAKE_MINIMUM_REQUIRED(VERSION 2.8) -SET(PROJ_NAME gameFallout3) +SET(PROJ_NAME game_fallout3) PROJECT(${PROJ_NAME}) @@ -12,4 +12,4 @@ LIST(APPEND CMAKE_PREFIX_PATH ${DEPENDENCIES_DIR}/qt5/lib/cmake) FILE(GLOB_RECURSE BOOST_ROOT ${DEPENDENCIES_DIR}/boost*/project-config.jam) GET_FILENAME_COMPONENT(BOOST_ROOT ${BOOST_ROOT} DIRECTORY) -ADD_SUBDIRECTORY(src) \ No newline at end of file +ADD_SUBDIRECTORY(src) diff --git a/src/games/fallout3/src/gamefallout3.h b/src/games/fallout3/src/gamefallout3.h index 0d76b0a3..40334828 100644 --- a/src/games/fallout3/src/gamefallout3.h +++ b/src/games/fallout3/src/gamefallout3.h @@ -6,9 +6,7 @@ class GameFallout3 : public GameGamebryo { Q_OBJECT -#if QT_VERSION >= QT_VERSION_CHECK(5,0,0) Q_PLUGIN_METADATA(IID "org.tannin.GameFallout3" FILE "gamefallout3.json") -#endif public: From 9f78f9f517781721863d21609a68f5ea13271da1 Mon Sep 17 00:00:00 2001 From: Tannin Date: Tue, 9 Feb 2016 19:39:03 +0100 Subject: [PATCH 0210/1544] [game_falloutnv] removed get prefix from getters --- src/games/falloutnv/src/gamefalloutnv.cpp | 14 +++++++------- src/games/falloutnv/src/gamefalloutnv.h | 12 ++++++------ 2 files changed, 13 insertions(+), 13 deletions(-) diff --git a/src/games/falloutnv/src/gamefalloutnv.cpp b/src/games/falloutnv/src/gamefalloutnv.cpp index bd16daa9..92dd4d70 100644 --- a/src/games/falloutnv/src/gamefalloutnv.cpp +++ b/src/games/falloutnv/src/gamefalloutnv.cpp @@ -53,7 +53,7 @@ QList GameFalloutNV::executables() const { return QList() << ExecutableInfo("NVSE", findInGameFolder(m_ScriptExtender->loaderName())) - << ExecutableInfo("New Vegas", findInGameFolder(getBinaryName())) + << ExecutableInfo("New Vegas", findInGameFolder(binaryName())) << ExecutableInfo("Fallout Mod Manager", findInGameFolder("fomm/fomm.exe")) << ExecutableInfo("Construction Kit", findInGameFolder("geck.exe")) << ExecutableInfo("Fallout Launcher", findInGameFolder(getLauncherName())) @@ -136,34 +136,34 @@ QString GameFalloutNV::steamAPPId() const return "22380"; } -QStringList GameFalloutNV::getPrimaryPlugins() const +QStringList GameFalloutNV::primaryPlugins() const { return { "falloutnv.esm" }; } -QString GameFalloutNV::getGameShortName() const +QString GameFalloutNV::gameShortName() const { return "FalloutNV"; } -QStringList GameFalloutNV::getIniFiles() const +QStringList GameFalloutNV::iniFiles() const { return { "fallout.ini", "falloutprefs.ini" }; } -QStringList GameFalloutNV::getDLCPlugins() const +QStringList GameFalloutNV::DLCPlugins() const { return { "DeadMoney.esm", "HonestHearts.esm", "OldWorldBlues.esm", "LonesomeRoad.esm", "GunRunnersArsenal.esm", "CaravanPack.esm", "ClassicPack.esm", "MercenaryPack.esm", "TribalPack.esm" }; } -int GameFalloutNV::getNexusModOrganizerID() const +int GameFalloutNV::nexusModOrganizerID() const { return 42572; } -int GameFalloutNV::getNexusGameID() const +int GameFalloutNV::nexusGameID() const { return 130; } diff --git a/src/games/falloutnv/src/gamefalloutnv.h b/src/games/falloutnv/src/gamefalloutnv.h index 5335a0b5..cdd96ba5 100644 --- a/src/games/falloutnv/src/gamefalloutnv.h +++ b/src/games/falloutnv/src/gamefalloutnv.h @@ -23,12 +23,12 @@ public: // IPluginGame interface virtual void initializeProfile(const QDir &path, ProfileSettings settings) const override; virtual QString savegameExtension() const override; virtual QString steamAPPId() const override; - virtual QStringList getPrimaryPlugins() const override; - virtual QString getGameShortName() const override; - virtual QStringList getIniFiles() const override; - virtual QStringList getDLCPlugins() const override; - virtual int getNexusModOrganizerID() const override; - virtual int getNexusGameID() const override; + virtual QStringList primaryPlugins() const override; + virtual QString gameShortName() const override; + virtual QStringList iniFiles() const override; + virtual QStringList DLCPlugins() const override; + virtual int nexusModOrganizerID() const override; + virtual int nexusGameID() const override; public: // IPlugin interface From e9b7ccbbaf89ed886d3e04f5141982a69dba5641 Mon Sep 17 00:00:00 2001 From: Tannin Date: Tue, 9 Feb 2016 19:39:29 +0100 Subject: [PATCH 0211/1544] [game_falloutnv] renamed project (and thus the output filename) --- src/games/falloutnv/CMakeLists.txt | 4 ++-- src/games/falloutnv/src/CMakeLists.txt | 3 ++- 2 files changed, 4 insertions(+), 3 deletions(-) diff --git a/src/games/falloutnv/CMakeLists.txt b/src/games/falloutnv/CMakeLists.txt index cc6fe23e..eafe54e4 100644 --- a/src/games/falloutnv/CMakeLists.txt +++ b/src/games/falloutnv/CMakeLists.txt @@ -1,6 +1,6 @@ CMAKE_MINIMUM_REQUIRED(VERSION 2.8) -SET(PROJ_NAME gameFalloutNV) +SET(PROJ_NAME game_falloutNV) PROJECT(${PROJ_NAME}) @@ -12,4 +12,4 @@ LIST(APPEND CMAKE_PREFIX_PATH ${DEPENDENCIES_DIR}/qt5/lib/cmake) FILE(GLOB_RECURSE BOOST_ROOT ${DEPENDENCIES_DIR}/boost*/project-config.jam) GET_FILENAME_COMPONENT(BOOST_ROOT ${BOOST_ROOT} DIRECTORY) -ADD_SUBDIRECTORY(src) \ No newline at end of file +ADD_SUBDIRECTORY(src) diff --git a/src/games/falloutnv/src/CMakeLists.txt b/src/games/falloutnv/src/CMakeLists.txt index 08e9431d..be1bb063 100644 --- a/src/games/falloutnv/src/CMakeLists.txt +++ b/src/games/falloutnv/src/CMakeLists.txt @@ -40,7 +40,8 @@ TARGET_LINK_LIBRARIES(${PROJ_NAME} Qt5::Widgets ${Boost_LIBRARIES} uibase - gameGamebryo) + gameGamebryo + Version) SET_TARGET_PROPERTIES(${PROJ_NAME} PROPERTIES COMPILE_FLAGS /GL) SET_TARGET_PROPERTIES(${PROJ_NAME} PROPERTIES LINK_FLAGS_RELWITHDEBINFO "/LTCG /LARGEADDRESSAWARE /OPT:REF /OPT:ICF") From c8ffa0769f1d328623eee3793e717b5c2675b22c Mon Sep 17 00:00:00 2001 From: Tannin Date: Tue, 9 Feb 2016 19:40:10 +0100 Subject: [PATCH 0212/1544] [game_fallout4vr] renamed project (and thus the output filename) --- src/games/fallout4vr/CMakeLists.txt | 2 +- src/games/fallout4vr/src/gamefallout4.h | 1 + 2 files changed, 2 insertions(+), 1 deletion(-) diff --git a/src/games/fallout4vr/CMakeLists.txt b/src/games/fallout4vr/CMakeLists.txt index 64470f51..59c4d455 100644 --- a/src/games/fallout4vr/CMakeLists.txt +++ b/src/games/fallout4vr/CMakeLists.txt @@ -1,6 +1,6 @@ CMAKE_MINIMUM_REQUIRED(VERSION 2.8) -SET(PROJ_NAME gameFallout4) +SET(PROJ_NAME game_fallout4) PROJECT(${PROJ_NAME}) diff --git a/src/games/fallout4vr/src/gamefallout4.h b/src/games/fallout4vr/src/gamefallout4.h index c1884e55..bf5ab8dd 100644 --- a/src/games/fallout4vr/src/gamefallout4.h +++ b/src/games/fallout4vr/src/gamefallout4.h @@ -8,6 +8,7 @@ class GameFallout4 : public GameGamebryo { Q_OBJECT + Q_PLUGIN_METADATA(IID "org.tannin.GameFallout4" FILE "gamefallout4.json") public: From ea30b1d0a75b5e1cc732e89d222d7262c92bdd45 Mon Sep 17 00:00:00 2001 From: Tannin Date: Tue, 9 Feb 2016 19:40:10 +0100 Subject: [PATCH 0213/1544] [game_fallout76] renamed project (and thus the output filename) --- src/games/fallout76/CMakeLists.txt | 2 +- src/games/fallout76/src/gamefallout4.h | 1 + 2 files changed, 2 insertions(+), 1 deletion(-) diff --git a/src/games/fallout76/CMakeLists.txt b/src/games/fallout76/CMakeLists.txt index 64470f51..59c4d455 100644 --- a/src/games/fallout76/CMakeLists.txt +++ b/src/games/fallout76/CMakeLists.txt @@ -1,6 +1,6 @@ CMAKE_MINIMUM_REQUIRED(VERSION 2.8) -SET(PROJ_NAME gameFallout4) +SET(PROJ_NAME game_fallout4) PROJECT(${PROJ_NAME}) diff --git a/src/games/fallout76/src/gamefallout4.h b/src/games/fallout76/src/gamefallout4.h index c1884e55..bf5ab8dd 100644 --- a/src/games/fallout76/src/gamefallout4.h +++ b/src/games/fallout76/src/gamefallout4.h @@ -8,6 +8,7 @@ class GameFallout4 : public GameGamebryo { Q_OBJECT + Q_PLUGIN_METADATA(IID "org.tannin.GameFallout4" FILE "gamefallout4.json") public: From fe71661f6847ed73cadcccf4ab0dd520938d8474 Mon Sep 17 00:00:00 2001 From: Tannin Date: Tue, 9 Feb 2016 19:40:10 +0100 Subject: [PATCH 0214/1544] [game_fallout4] renamed project (and thus the output filename) --- src/games/fallout4/CMakeLists.txt | 2 +- src/games/fallout4/src/gamefallout4.h | 1 + 2 files changed, 2 insertions(+), 1 deletion(-) diff --git a/src/games/fallout4/CMakeLists.txt b/src/games/fallout4/CMakeLists.txt index 64470f51..59c4d455 100644 --- a/src/games/fallout4/CMakeLists.txt +++ b/src/games/fallout4/CMakeLists.txt @@ -1,6 +1,6 @@ CMAKE_MINIMUM_REQUIRED(VERSION 2.8) -SET(PROJ_NAME gameFallout4) +SET(PROJ_NAME game_fallout4) PROJECT(${PROJ_NAME}) diff --git a/src/games/fallout4/src/gamefallout4.h b/src/games/fallout4/src/gamefallout4.h index c1884e55..bf5ab8dd 100644 --- a/src/games/fallout4/src/gamefallout4.h +++ b/src/games/fallout4/src/gamefallout4.h @@ -8,6 +8,7 @@ class GameFallout4 : public GameGamebryo { Q_OBJECT + Q_PLUGIN_METADATA(IID "org.tannin.GameFallout4" FILE "gamefallout4.json") public: From 279be67ac3123950844d64e48ecffeaa281071b2 Mon Sep 17 00:00:00 2001 From: Tannin Date: Tue, 9 Feb 2016 19:40:57 +0100 Subject: [PATCH 0215/1544] [game_skyrim] removed get prefix from getters --- src/games/skyrim/src/gameskyrim.cpp | 20 ++++++++++---------- src/games/skyrim/src/gameskyrim.h | 16 ++++++++-------- 2 files changed, 18 insertions(+), 18 deletions(-) diff --git a/src/games/skyrim/src/gameskyrim.cpp b/src/games/skyrim/src/gameskyrim.cpp index 567f8937..110b8723 100644 --- a/src/games/skyrim/src/gameskyrim.cpp +++ b/src/games/skyrim/src/gameskyrim.cpp @@ -62,7 +62,7 @@ QList GameSkyrim::executables() const return QList() << ExecutableInfo("SKSE", findInGameFolder(m_ScriptExtender->loaderName())) << ExecutableInfo("SBW", findInGameFolder("SBW.exe")) - << ExecutableInfo("Skyrim", findInGameFolder(getBinaryName())) + << ExecutableInfo("Skyrim", findInGameFolder(binaryName())) << ExecutableInfo("Skyrim Launcher", findInGameFolder(getLauncherName())) << ExecutableInfo("BOSS", findInGameFolder("BOSS/BOSS.exe")) << ExecutableInfo("LOOT", getLootPath()) @@ -144,27 +144,27 @@ QString GameSkyrim::steamAPPId() const return "72850"; } -QStringList GameSkyrim::getPrimaryPlugins() const +QStringList GameSkyrim::primaryPlugins() const { return { "skyrim.esm", "update.esm" }; } -QString GameSkyrim::getBinaryName() const +QString GameSkyrim::binaryName() const { return "TESV.exe"; } -QString GameSkyrim::getGameShortName() const +QString GameSkyrim::gameShortName() const { return "Skyrim"; } -QStringList GameSkyrim::getIniFiles() const +QStringList GameSkyrim::iniFiles() const { return { "skyrim.ini", "skyrimprefs.ini" }; } -QStringList GameSkyrim::getDLCPlugins() const +QStringList GameSkyrim::DLCPlugins() const { return { "Dawnguard.esm", "Dragonborn.esm", "HearthFires.esm", "HighResTexturePack01.esp", "HighResTexturePack02.esp", "HighResTexturePack03.esp" }; @@ -200,10 +200,10 @@ VS_FIXEDFILEINFO GetFileVersion(const std::wstring &fileName) } -IPluginGame::LoadOrderMechanism GameSkyrim::getLoadOrderMechanism() const +IPluginGame::LoadOrderMechanism GameSkyrim::loadOrderMechanism() const { try { - std::wstring fileName = gameDirectory().absoluteFilePath(getBinaryName()).toStdWString().c_str(); + std::wstring fileName = gameDirectory().absoluteFilePath(binaryName()).toStdWString().c_str(); VS_FIXEDFILEINFO versionInfo = ::GetFileVersion(fileName); if ((versionInfo.dwFileVersionMS > 0x10004) || // version >= 1.5.x? ((versionInfo.dwFileVersionMS == 0x10004) && (versionInfo.dwFileVersionLS >= 0x1A0000))) { // version >= ?.4.26 @@ -216,12 +216,12 @@ IPluginGame::LoadOrderMechanism GameSkyrim::getLoadOrderMechanism() const } -int GameSkyrim::getNexusModOrganizerID() const +int GameSkyrim::nexusModOrganizerID() const { return 1334; } -int GameSkyrim::getNexusGameID() const +int GameSkyrim::nexusGameID() const { return 110; } diff --git a/src/games/skyrim/src/gameskyrim.h b/src/games/skyrim/src/gameskyrim.h index ed8bef6f..e0730b50 100644 --- a/src/games/skyrim/src/gameskyrim.h +++ b/src/games/skyrim/src/gameskyrim.h @@ -23,14 +23,14 @@ public: // IPluginGame interface virtual void initializeProfile(const QDir &path, ProfileSettings settings) const override; virtual QString savegameExtension() const override; virtual QString steamAPPId() const override; - virtual QStringList getPrimaryPlugins() const override; - virtual QString getBinaryName() const override; - virtual QString getGameShortName() const override; - virtual QStringList getIniFiles() const override; - virtual QStringList getDLCPlugins() const override; - virtual LoadOrderMechanism getLoadOrderMechanism() const override; - virtual int getNexusModOrganizerID() const override; - virtual int getNexusGameID() const override; + virtual QStringList primaryPlugins() const override; + virtual QString binaryName() const override; + virtual QString gameShortName() const override; + virtual QStringList iniFiles() const override; + virtual QStringList DLCPlugins() const override; + virtual LoadOrderMechanism loadOrderMechanism() const override; + virtual int nexusModOrganizerID() const override; + virtual int nexusGameID() const override; public: // IPlugin interface From 5bd1503ef9824fa94be4f26d559ea56a0b17c618 Mon Sep 17 00:00:00 2001 From: Tannin Date: Tue, 9 Feb 2016 19:41:02 +0100 Subject: [PATCH 0216/1544] [game_skyrim] renamed project (and thus the output filename) --- src/games/skyrim/CMakeLists.txt | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/games/skyrim/CMakeLists.txt b/src/games/skyrim/CMakeLists.txt index 3bc9735b..17385b05 100644 --- a/src/games/skyrim/CMakeLists.txt +++ b/src/games/skyrim/CMakeLists.txt @@ -1,6 +1,6 @@ CMAKE_MINIMUM_REQUIRED(VERSION 2.8) -SET(PROJ_NAME gameSkyrim) +SET(PROJ_NAME game_skyrim) PROJECT(${PROJ_NAME}) @@ -12,4 +12,4 @@ LIST(APPEND CMAKE_PREFIX_PATH ${DEPENDENCIES_DIR}/qt5/lib/cmake) FILE(GLOB_RECURSE BOOST_ROOT ${DEPENDENCIES_DIR}/boost*/project-config.jam) GET_FILENAME_COMPONENT(BOOST_ROOT ${BOOST_ROOT} DIRECTORY) -ADD_SUBDIRECTORY(src) \ No newline at end of file +ADD_SUBDIRECTORY(src) From 8d6c2f9c173e5ea0a1a64807bb0a70d303821b12 Mon Sep 17 00:00:00 2001 From: Tannin Date: Tue, 9 Feb 2016 19:41:29 +0100 Subject: [PATCH 0217/1544] [game_oblivion] removed get prefix from getters --- src/games/oblivion/src/gameoblivion.cpp | 14 +++++++------- src/games/oblivion/src/gameoblivion.h | 12 ++++++------ 2 files changed, 13 insertions(+), 13 deletions(-) diff --git a/src/games/oblivion/src/gameoblivion.cpp b/src/games/oblivion/src/gameoblivion.cpp index 29723ed7..2bb00f77 100644 --- a/src/games/oblivion/src/gameoblivion.cpp +++ b/src/games/oblivion/src/gameoblivion.cpp @@ -54,7 +54,7 @@ QList GameOblivion::executables() const { return QList() << ExecutableInfo("OBSE", findInGameFolder(m_ScriptExtender->loaderName())) - << ExecutableInfo("Oblivion", findInGameFolder(getBinaryName())) + << ExecutableInfo("Oblivion", findInGameFolder(binaryName())) << ExecutableInfo("Oblivion Launcher", findInGameFolder(getLauncherName())) << ExecutableInfo("Oblivion Mod Manager", findInGameFolder("OblivionModManager.exe")) << ExecutableInfo("BOSS", findInGameFolder("BOSS/BOSS.exe")) @@ -137,22 +137,22 @@ QString GameOblivion::steamAPPId() const return "22330"; } -QStringList GameOblivion::getPrimaryPlugins() const +QStringList GameOblivion::primaryPlugins() const { return { "oblivion.esm", "update.esm" }; } -QString GameOblivion::getGameShortName() const +QString GameOblivion::gameShortName() const { return "Oblivion"; } -QStringList GameOblivion::getIniFiles() const +QStringList GameOblivion::iniFiles() const { return { "oblivion.ini", "oblivionprefs.ini" }; } -QStringList GameOblivion::getDLCPlugins() const +QStringList GameOblivion::DLCPlugins() const { return { "DLCShiveringIsles.esp", "Knights.esp", "DLCFrostcrag.esp", "DLCSpellTomes.esp", "DLCMehrunesRazor.esp", "DLCOrrery.esp", @@ -160,12 +160,12 @@ QStringList GameOblivion::getDLCPlugins() const } -int GameOblivion::getNexusModOrganizerID() const +int GameOblivion::nexusModOrganizerID() const { return 38277; } -int GameOblivion::getNexusGameID() const +int GameOblivion::nexusGameID() const { return 101; } diff --git a/src/games/oblivion/src/gameoblivion.h b/src/games/oblivion/src/gameoblivion.h index e9b795d2..52e60ff3 100644 --- a/src/games/oblivion/src/gameoblivion.h +++ b/src/games/oblivion/src/gameoblivion.h @@ -23,12 +23,12 @@ public: // IPluginGame interface virtual void initializeProfile(const QDir &path, ProfileSettings settings) const override; virtual QString savegameExtension() const override; virtual QString steamAPPId() const override; - virtual QStringList getPrimaryPlugins() const override; - virtual QString getGameShortName() const override; - virtual QStringList getIniFiles() const override; - virtual QStringList getDLCPlugins() const override; - virtual int getNexusModOrganizerID() const override; - virtual int getNexusGameID() const override; + virtual QStringList primaryPlugins() const override; + virtual QString gameShortName() const override; + virtual QStringList iniFiles() const override; + virtual QStringList DLCPlugins() const override; + virtual int nexusModOrganizerID() const override; + virtual int nexusGameID() const override; public: // IPlugin interface From 473220342d6347e09ba1618561d0b9294df46209 Mon Sep 17 00:00:00 2001 From: Tannin Date: Tue, 9 Feb 2016 19:41:34 +0100 Subject: [PATCH 0218/1544] [game_oblivion] renamed project (and thus the output filename) --- src/games/oblivion/CMakeLists.txt | 4 ++-- src/games/oblivion/src/CMakeLists.txt | 3 ++- 2 files changed, 4 insertions(+), 3 deletions(-) diff --git a/src/games/oblivion/CMakeLists.txt b/src/games/oblivion/CMakeLists.txt index 6b0177ed..fb17c159 100644 --- a/src/games/oblivion/CMakeLists.txt +++ b/src/games/oblivion/CMakeLists.txt @@ -1,6 +1,6 @@ CMAKE_MINIMUM_REQUIRED(VERSION 2.8) -SET(PROJ_NAME gameOblivion) +SET(PROJ_NAME game_oblivion) PROJECT(${PROJ_NAME}) @@ -12,4 +12,4 @@ LIST(APPEND CMAKE_PREFIX_PATH ${DEPENDENCIES_DIR}/qt5/lib/cmake) FILE(GLOB_RECURSE BOOST_ROOT ${DEPENDENCIES_DIR}/boost*/project-config.jam) GET_FILENAME_COMPONENT(BOOST_ROOT ${BOOST_ROOT} DIRECTORY) -ADD_SUBDIRECTORY(src) \ No newline at end of file +ADD_SUBDIRECTORY(src) diff --git a/src/games/oblivion/src/CMakeLists.txt b/src/games/oblivion/src/CMakeLists.txt index 08e9431d..2685b0ec 100644 --- a/src/games/oblivion/src/CMakeLists.txt +++ b/src/games/oblivion/src/CMakeLists.txt @@ -40,7 +40,8 @@ TARGET_LINK_LIBRARIES(${PROJ_NAME} Qt5::Widgets ${Boost_LIBRARIES} uibase - gameGamebryo) + gameGamebryo + version) SET_TARGET_PROPERTIES(${PROJ_NAME} PROPERTIES COMPILE_FLAGS /GL) SET_TARGET_PROPERTIES(${PROJ_NAME} PROPERTIES LINK_FLAGS_RELWITHDEBINFO "/LTCG /LARGEADDRESSAWARE /OPT:REF /OPT:ICF") From b060363750c8644f7bab73c63084301210217bfc Mon Sep 17 00:00:00 2001 From: Tannin Date: Tue, 9 Feb 2016 19:42:10 +0100 Subject: [PATCH 0219/1544] renamed project --- CMakeLists.txt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/CMakeLists.txt b/CMakeLists.txt index 3ef35bb0..9e986c42 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -1,6 +1,6 @@ CMAKE_MINIMUM_REQUIRED(VERSION 2.8) -SET(PROJ_NAME gameGamebryo) +SET(PROJ_NAME game_gamebryo) PROJECT(${PROJ_NAME}) SET(DEPENDENCIES_DIR CACHE PATH "") From b6c42833d1d82eae885d981d026d120ded60661d Mon Sep 17 00:00:00 2001 From: Tannin Date: Wed, 2 Mar 2016 21:16:39 +0100 Subject: [PATCH 0220/1544] [game_fallout4vr] added splash --- src/games/fallout4vr/src/CMakeLists.txt | 9 +++++++-- src/games/fallout4vr/src/fallout4.qrc | 5 +++++ src/games/fallout4vr/src/gamefallout4.cpp | 5 +++-- src/games/fallout4vr/src/splash.png | Bin 0 -> 55418 bytes 4 files changed, 15 insertions(+), 4 deletions(-) create mode 100644 src/games/fallout4vr/src/fallout4.qrc create mode 100644 src/games/fallout4vr/src/splash.png diff --git a/src/games/fallout4vr/src/CMakeLists.txt b/src/games/fallout4vr/src/CMakeLists.txt index a0c7f656..a065ec74 100644 --- a/src/games/fallout4vr/src/CMakeLists.txt +++ b/src/games/fallout4vr/src/CMakeLists.txt @@ -6,12 +6,16 @@ FILE(GLOB ${PROJ_NAME}_SRCS *.cpp) FILE(GLOB ${PROJ_NAME}_HDRS *.h) FILE(GLOB ${PROJ_NAME}_FORMS *.ui) +SET(${PROJ_NAME}_QRCS + fallout4.qrc + ) SET(CMAKE_INCLUDE_CURRENT_DIR ON) SET(CMAKE_AUTOMOC ON) SET(CMAKE_AUTOUIC ON) FIND_PACKAGE(Qt5Widgets REQUIRED) QT5_WRAP_UI(${PROJ_NAME}_UIHDRS ${${PROJ_NAME}_FORMS}) +QT5_ADD_RESOURCES(${PROJ_NAME}_RCCPPS ${${PROJ_NAME}_QRCS}) SET(Boost_USE_STATIC_LIBS ON) SET(Boost_USE_MULTITHREADED ON) @@ -35,19 +39,20 @@ LINK_DIRECTORIES(${project_path}/uibase/build/src ${lib_path}) -ADD_LIBRARY(${PROJ_NAME} SHARED ${${PROJ_NAME}_HDRS} ${${PROJ_NAME}_SRCS} ${${PROJ_NAME}_UIHDRS}) +ADD_LIBRARY(${PROJ_NAME} SHARED ${${PROJ_NAME}_HDRS} ${${PROJ_NAME}_SRCS} ${${PROJ_NAME}_UIHDRS} ${${PROJ_NAME}_RCCPPS}) TARGET_LINK_LIBRARIES(${PROJ_NAME} Qt5::Widgets ${Boost_LIBRARIES} uibase Version - gameGamebryo) + game_gamebryo) SET_TARGET_PROPERTIES(${PROJ_NAME} PROPERTIES COMPILE_FLAGS /GL) SET_TARGET_PROPERTIES(${PROJ_NAME} PROPERTIES LINK_FLAGS_RELWITHDEBINFO "/LARGEADDRESSAWARE ${OPTIMIZE_LINK_FLAGS}") QT5_USE_MODULES(${PROJ_NAME} Widgets) + ############### ## Installation diff --git a/src/games/fallout4vr/src/fallout4.qrc b/src/games/fallout4vr/src/fallout4.qrc new file mode 100644 index 00000000..c8e52145 --- /dev/null +++ b/src/games/fallout4vr/src/fallout4.qrc @@ -0,0 +1,5 @@ + + + splash.png + + diff --git a/src/games/fallout4vr/src/gamefallout4.cpp b/src/games/fallout4vr/src/gamefallout4.cpp index 9dcdf1b4..52adb333 100644 --- a/src/games/fallout4vr/src/gamefallout4.cpp +++ b/src/games/fallout4vr/src/gamefallout4.cpp @@ -65,12 +65,13 @@ QString GameFallout4::author() const QString GameFallout4::description() const { - return tr("Adds support for the game Fallout 4"); + return tr("Adds support for the game Fallout 4.\n" + "Splash by %1").arg("nekoyoubi"); } MOBase::VersionInfo GameFallout4::version() const { - return VersionInfo(0, 1, 0, VersionInfo::RELEASE_BETA); + return VersionInfo(0, 2, 0, VersionInfo::RELEASE_BETA); } bool GameFallout4::isActive() const diff --git a/src/games/fallout4vr/src/splash.png b/src/games/fallout4vr/src/splash.png new file mode 100644 index 0000000000000000000000000000000000000000..2522871afd12baaffc532b57a91d30d66f69eed5 GIT binary patch literal 55418 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

eD(kHJ+eRlhXFjkK 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 Z`jYB*%T61HGB7YOc)I$ztaD0e0syF#mE!;a literal 0 HcmV?d00001 From 54221e8351e824d530e7a2c1b28174c3a8cac34f Mon Sep 17 00:00:00 2001 From: Tannin Date: Wed, 2 Mar 2016 21:16:39 +0100 Subject: [PATCH 0221/1544] [game_fallout76] added splash --- src/games/fallout76/src/CMakeLists.txt | 9 +++++++-- src/games/fallout76/src/fallout4.qrc | 5 +++++ src/games/fallout76/src/gamefallout4.cpp | 5 +++-- src/games/fallout76/src/splash.png | Bin 0 -> 55418 bytes 4 files changed, 15 insertions(+), 4 deletions(-) create mode 100644 src/games/fallout76/src/fallout4.qrc create mode 100644 src/games/fallout76/src/splash.png diff --git a/src/games/fallout76/src/CMakeLists.txt b/src/games/fallout76/src/CMakeLists.txt index a0c7f656..a065ec74 100644 --- a/src/games/fallout76/src/CMakeLists.txt +++ b/src/games/fallout76/src/CMakeLists.txt @@ -6,12 +6,16 @@ FILE(GLOB ${PROJ_NAME}_SRCS *.cpp) FILE(GLOB ${PROJ_NAME}_HDRS *.h) FILE(GLOB ${PROJ_NAME}_FORMS *.ui) +SET(${PROJ_NAME}_QRCS + fallout4.qrc + ) SET(CMAKE_INCLUDE_CURRENT_DIR ON) SET(CMAKE_AUTOMOC ON) SET(CMAKE_AUTOUIC ON) FIND_PACKAGE(Qt5Widgets REQUIRED) QT5_WRAP_UI(${PROJ_NAME}_UIHDRS ${${PROJ_NAME}_FORMS}) +QT5_ADD_RESOURCES(${PROJ_NAME}_RCCPPS ${${PROJ_NAME}_QRCS}) SET(Boost_USE_STATIC_LIBS ON) SET(Boost_USE_MULTITHREADED ON) @@ -35,19 +39,20 @@ LINK_DIRECTORIES(${project_path}/uibase/build/src ${lib_path}) -ADD_LIBRARY(${PROJ_NAME} SHARED ${${PROJ_NAME}_HDRS} ${${PROJ_NAME}_SRCS} ${${PROJ_NAME}_UIHDRS}) +ADD_LIBRARY(${PROJ_NAME} SHARED ${${PROJ_NAME}_HDRS} ${${PROJ_NAME}_SRCS} ${${PROJ_NAME}_UIHDRS} ${${PROJ_NAME}_RCCPPS}) TARGET_LINK_LIBRARIES(${PROJ_NAME} Qt5::Widgets ${Boost_LIBRARIES} uibase Version - gameGamebryo) + game_gamebryo) SET_TARGET_PROPERTIES(${PROJ_NAME} PROPERTIES COMPILE_FLAGS /GL) SET_TARGET_PROPERTIES(${PROJ_NAME} PROPERTIES LINK_FLAGS_RELWITHDEBINFO "/LARGEADDRESSAWARE ${OPTIMIZE_LINK_FLAGS}") QT5_USE_MODULES(${PROJ_NAME} Widgets) + ############### ## Installation diff --git a/src/games/fallout76/src/fallout4.qrc b/src/games/fallout76/src/fallout4.qrc new file mode 100644 index 00000000..c8e52145 --- /dev/null +++ b/src/games/fallout76/src/fallout4.qrc @@ -0,0 +1,5 @@ + + + splash.png + + diff --git a/src/games/fallout76/src/gamefallout4.cpp b/src/games/fallout76/src/gamefallout4.cpp index 9dcdf1b4..52adb333 100644 --- a/src/games/fallout76/src/gamefallout4.cpp +++ b/src/games/fallout76/src/gamefallout4.cpp @@ -65,12 +65,13 @@ QString GameFallout4::author() const QString GameFallout4::description() const { - return tr("Adds support for the game Fallout 4"); + return tr("Adds support for the game Fallout 4.\n" + "Splash by %1").arg("nekoyoubi"); } MOBase::VersionInfo GameFallout4::version() const { - return VersionInfo(0, 1, 0, VersionInfo::RELEASE_BETA); + return VersionInfo(0, 2, 0, VersionInfo::RELEASE_BETA); } bool GameFallout4::isActive() const diff --git a/src/games/fallout76/src/splash.png b/src/games/fallout76/src/splash.png new file mode 100644 index 0000000000000000000000000000000000000000..2522871afd12baaffc532b57a91d30d66f69eed5 GIT binary patch literal 55418 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

eD(kHJ+eRlhXFjkK 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 Z`jYB*%T61HGB7YOc)I$ztaD0e0syF#mE!;a literal 0 HcmV?d00001 From 30c67ac7eeec62492c123cc6c9aa27fc8bad9fb3 Mon Sep 17 00:00:00 2001 From: Tannin Date: Wed, 2 Mar 2016 21:16:39 +0100 Subject: [PATCH 0222/1544] [game_fallout4] added splash --- src/games/fallout4/src/CMakeLists.txt | 9 +++++++-- src/games/fallout4/src/fallout4.qrc | 5 +++++ src/games/fallout4/src/gamefallout4.cpp | 5 +++-- src/games/fallout4/src/splash.png | Bin 0 -> 55418 bytes 4 files changed, 15 insertions(+), 4 deletions(-) create mode 100644 src/games/fallout4/src/fallout4.qrc create mode 100644 src/games/fallout4/src/splash.png diff --git a/src/games/fallout4/src/CMakeLists.txt b/src/games/fallout4/src/CMakeLists.txt index a0c7f656..a065ec74 100644 --- a/src/games/fallout4/src/CMakeLists.txt +++ b/src/games/fallout4/src/CMakeLists.txt @@ -6,12 +6,16 @@ FILE(GLOB ${PROJ_NAME}_SRCS *.cpp) FILE(GLOB ${PROJ_NAME}_HDRS *.h) FILE(GLOB ${PROJ_NAME}_FORMS *.ui) +SET(${PROJ_NAME}_QRCS + fallout4.qrc + ) SET(CMAKE_INCLUDE_CURRENT_DIR ON) SET(CMAKE_AUTOMOC ON) SET(CMAKE_AUTOUIC ON) FIND_PACKAGE(Qt5Widgets REQUIRED) QT5_WRAP_UI(${PROJ_NAME}_UIHDRS ${${PROJ_NAME}_FORMS}) +QT5_ADD_RESOURCES(${PROJ_NAME}_RCCPPS ${${PROJ_NAME}_QRCS}) SET(Boost_USE_STATIC_LIBS ON) SET(Boost_USE_MULTITHREADED ON) @@ -35,19 +39,20 @@ LINK_DIRECTORIES(${project_path}/uibase/build/src ${lib_path}) -ADD_LIBRARY(${PROJ_NAME} SHARED ${${PROJ_NAME}_HDRS} ${${PROJ_NAME}_SRCS} ${${PROJ_NAME}_UIHDRS}) +ADD_LIBRARY(${PROJ_NAME} SHARED ${${PROJ_NAME}_HDRS} ${${PROJ_NAME}_SRCS} ${${PROJ_NAME}_UIHDRS} ${${PROJ_NAME}_RCCPPS}) TARGET_LINK_LIBRARIES(${PROJ_NAME} Qt5::Widgets ${Boost_LIBRARIES} uibase Version - gameGamebryo) + game_gamebryo) SET_TARGET_PROPERTIES(${PROJ_NAME} PROPERTIES COMPILE_FLAGS /GL) SET_TARGET_PROPERTIES(${PROJ_NAME} PROPERTIES LINK_FLAGS_RELWITHDEBINFO "/LARGEADDRESSAWARE ${OPTIMIZE_LINK_FLAGS}") QT5_USE_MODULES(${PROJ_NAME} Widgets) + ############### ## Installation diff --git a/src/games/fallout4/src/fallout4.qrc b/src/games/fallout4/src/fallout4.qrc new file mode 100644 index 00000000..c8e52145 --- /dev/null +++ b/src/games/fallout4/src/fallout4.qrc @@ -0,0 +1,5 @@ + + + splash.png + + diff --git a/src/games/fallout4/src/gamefallout4.cpp b/src/games/fallout4/src/gamefallout4.cpp index 9dcdf1b4..52adb333 100644 --- a/src/games/fallout4/src/gamefallout4.cpp +++ b/src/games/fallout4/src/gamefallout4.cpp @@ -65,12 +65,13 @@ QString GameFallout4::author() const QString GameFallout4::description() const { - return tr("Adds support for the game Fallout 4"); + return tr("Adds support for the game Fallout 4.\n" + "Splash by %1").arg("nekoyoubi"); } MOBase::VersionInfo GameFallout4::version() const { - return VersionInfo(0, 1, 0, VersionInfo::RELEASE_BETA); + return VersionInfo(0, 2, 0, VersionInfo::RELEASE_BETA); } bool GameFallout4::isActive() const diff --git a/src/games/fallout4/src/splash.png b/src/games/fallout4/src/splash.png new file mode 100644 index 0000000000000000000000000000000000000000..2522871afd12baaffc532b57a91d30d66f69eed5 GIT binary patch literal 55418 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

eD(kHJ+eRlhXFjkK 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 Z`jYB*%T61HGB7YOc)I$ztaD0e0syF#mE!;a literal 0 HcmV?d00001 From 9962b765b06636d1d6871c93ba35bfa90377929d Mon Sep 17 00:00:00 2001 From: Tannin Date: Fri, 6 May 2016 22:55:06 +0200 Subject: [PATCH 0223/1544] added functionality to read/write plugin files to game plugin --- src/CMakeLists.txt | 15 ++- src/gamebryogameplugins.cpp | 207 ++++++++++++++++++++++++++++++++++++ src/gamebryogameplugins.h | 45 ++++++++ src/gamegamebryo.cpp | 3 +- src/gamegamebryo.h | 4 +- 5 files changed, 268 insertions(+), 6 deletions(-) create mode 100644 src/gamebryogameplugins.cpp create mode 100644 src/gamebryogameplugins.h diff --git a/src/CMakeLists.txt b/src/CMakeLists.txt index de40470f..3b667be4 100644 --- a/src/CMakeLists.txt +++ b/src/CMakeLists.txt @@ -34,7 +34,6 @@ INCLUDE_DIRECTORIES(${project_path}/uibase/src ${project_path}/game_features/src) LINK_DIRECTORIES(${lib_path}) - ADD_LIBRARY(${PROJ_NAME} STATIC ${${PROJ_NAME}_HDRS} ${${PROJ_NAME}_SRCS} ${${PROJ_NAME}_UIHDRS}) TARGET_LINK_LIBRARIES(${PROJ_NAME} Qt5::Widgets @@ -42,8 +41,18 @@ TARGET_LINK_LIBRARIES(${PROJ_NAME} uibase Version) -SET_TARGET_PROPERTIES(${PROJ_NAME} PROPERTIES COMPILE_FLAGS /GL) -SET_TARGET_PROPERTIES(${PROJ_NAME} PROPERTIES LINK_FLAGS_RELWITHDEBINFO "/LARGEADDRESSAWARE ${OPTIMIZE_LINK_FLAGS}") +IF(MSVC) + SET_TARGET_PROPERTIES(${PROJ_NAME} PROPERTIES LINK_FLAGS "/LARGEADDRESSAWARE") +ELSE(MSVC) + SET_TARGET_PROPERTIES(${PROJ_NAME} PROPERTIES LINK_FLAGS "-std=c++11") +ENDIF(MSVC) + +IF (NOT "${OPTIMIZE_COMPILE_FLAGS}" STREQUAL "") + SET_TARGET_PROPERTIES(${PROJ_NAME} PROPERTIES COMPILE_FLAGS_RELWITHDEBINFO ${OPTIMIZE_COMPILE_FLAGS}) +ENDIF() +IF (NOT "${OPTIMIZE_LINK_FLAGS}" STREQUAL "") + SET_TARGET_PROPERTIES(${PROJ_NAME} PROPERTIES LINK_FLAGS_RELWITHDEBINFO ${OPTIMIZE_LINK_FLAGS}) +ENDIF() QT5_USE_MODULES(${PROJ_NAME} Widgets) diff --git a/src/gamebryogameplugins.cpp b/src/gamebryogameplugins.cpp new file mode 100644 index 00000000..f98a1841 --- /dev/null +++ b/src/gamebryogameplugins.cpp @@ -0,0 +1,207 @@ +#include "gamebryogameplugins.h" +#include +#include +#include +#include +#include + +#include +#include +#include +#include +#include + +using MOBase::IOrganizer; +using MOBase::IPluginList; +using MOBase::SafeWriteFile; +using MOBase::reportError; + +GamebryoGamePlugins::GamebryoGamePlugins(IOrganizer *organizer) + : m_Organizer(organizer) { + m_Utf8Codec = QTextCodec::codecForName("utf-8"); + m_LocalCodec = QTextCodec::codecForName("Windows-1252"); +} + +void GamebryoGamePlugins::writePluginLists(const IPluginList *pluginList) { + if (!m_LastRead.isValid()) { + // attempt to write uninitialized plugin lists + return; + } + + writePluginList(pluginList, + m_Organizer->profile()->absolutePath() + "/plugins.txt"); + writeLoadOrderList(pluginList, + m_Organizer->profile()->absolutePath() + "/loadorder.txt"); + + m_LastRead = QDateTime::currentDateTime(); +} + +void GamebryoGamePlugins::readPluginLists(MOBase::IPluginList *pluginList) { + QString loadOrderPath = + organizer()->profile()->absolutePath() + "/loadorder.txt"; + QString pluginsPath = organizer()->profile()->absolutePath() + "/plugins.txt"; + + bool loadOrderIsNew = !m_LastRead.isValid() || + QFileInfo(loadOrderPath).lastModified() > m_LastRead; + if (loadOrderIsNew) { + readLoadOrderList(pluginList, loadOrderPath); + readPluginList(pluginList, pluginsPath, false); + } else if (QFileInfo(pluginsPath).lastModified() > m_LastRead) { + // humm, it appears an outside source changed the plugins.txt but not the + // loadorder.txt. In this case we have to use plugins.txt as the base for + // the load order + readPluginList(pluginList, pluginsPath, true); + } + + m_LastRead = QDateTime::currentDateTime(); +} + +void GamebryoGamePlugins::writePluginList(const MOBase::IPluginList *pluginList, + const QString &filePath) { + return writeList(pluginList, filePath, false); +} + +void GamebryoGamePlugins::writeLoadOrderList( + const MOBase::IPluginList *pluginList, const QString &filePath) { + return writeList(pluginList, filePath, true); +} + +void GamebryoGamePlugins::writeList(const IPluginList *pluginList, + const QString &filePath, bool loadOrder) { + SafeWriteFile file(filePath); + + QTextCodec *textCodec = loadOrder ? utf8Codec() : localCodec(); + + file->resize(0); + + file->write(textCodec->fromUnicode( + "# This file was automatically generated by Mod Organizer.\r\n")); + + bool invalidFileNames = false; + int writtenCount = 0; + + QStringList plugins = pluginList->pluginNames(); + std::sort(plugins.begin(), plugins.end(), + [pluginList](const QString &lhs, const QString &rhs) { + return pluginList->priority(lhs) < pluginList->priority(rhs); + }); + + for (const QString &pluginName : plugins) { + if (loadOrder || + (pluginList->state(pluginName) == IPluginList::STATE_ACTIVE)) { + if (!textCodec->canEncode(pluginName)) { + invalidFileNames = true; + qCritical("invalid plugin name %s", qPrintable(pluginName)); + } else { + file->write(textCodec->fromUnicode(pluginName)); + } + file->write("\r\n"); + ++writtenCount; + } + } + + if (invalidFileNames) { + reportError(QObject::tr("Some of your plugins have invalid names! These " + "plugins can not be loaded by the game. Please see " + "mo_interface.log for a list of affected plugins " + "and rename them.")); + } + + if (writtenCount == 0) { + qWarning("plugin list would be empty, this is almost certainly wrong. Not " + "saving."); + } else { + if (file.commitIfDifferent(m_LastSaveHash[filePath])) { + qDebug("%s saved", qPrintable(QDir::toNativeSeparators(filePath))); + } + } +} + +bool GamebryoGamePlugins::readLoadOrderList(MOBase::IPluginList *pluginList, + const QString &filePath) { + QStringList pluginNames = organizer()->managedGame()->primaryPlugins(); + QFile file(filePath); + if (!file.open(QIODevice::ReadOnly)) { + // no load order stored, determine by date + pluginNames = pluginList->pluginNames(); + QDir dataDirectory = organizer()->managedGame()->dataDirectory(); + std::sort( + pluginNames.begin(), pluginNames.end(), + [&dataDirectory](const QString &lhs, const QString &rhs) { + return QFileInfo(dataDirectory.absoluteFilePath(lhs)).lastModified() > + QFileInfo(dataDirectory.absoluteFilePath(rhs)).lastModified(); + }); + } else { + ON_BLOCK_EXIT([&file]() { file.close(); }); + + if (file.size() == 0) { + // MO stores at least a header in the file. if it's completely empty the + // file is broken + return false; + } + 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 (!pluginNames.contains(modName)) { + pluginNames.append(modName); + } + } + } + } + pluginList->setLoadOrder(pluginNames); + + return true; +} + +bool GamebryoGamePlugins::readPluginList(MOBase::IPluginList *pluginList, + const QString &filePath, + bool useLoadOrder) { + QStringList plugins = pluginList->pluginNames(); + + QFile file(filePath); + if (!file.open(QIODevice::ReadOnly)) { + return false; + } + ON_BLOCK_EXIT([&]() { + qDebug("close %s", qPrintable(filePath)); + file.close(); + }); + + if (file.size() == 0) { + // MO stores at least a header in the file. if it's completely empty the + // file is broken + return false; + } + + QStringList loadOrder; + while (!file.atEnd()) { + QByteArray line = file.readLine(); + QString pluginName; + if ((line.size() > 0) && (line.at(0) != '#')) { + pluginName = m_LocalCodec->toUnicode(line.trimmed().constData()); + } + if (pluginName.size() > 0) { + pluginList->setState(pluginName, IPluginList::STATE_ACTIVE); + plugins.removeAll(pluginName); + loadOrder.append(pluginName); + } + } + + file.close(); + + // we removed each plugin found in the file, so what's left are inactive mods + for (const QString &pluginName : plugins) { + pluginList->setState(pluginName, IPluginList::STATE_INACTIVE); + } + + if (useLoadOrder) { + pluginList->setLoadOrder(loadOrder); + } + + return true; +} diff --git a/src/gamebryogameplugins.h b/src/gamebryogameplugins.h new file mode 100644 index 00000000..5676ed15 --- /dev/null +++ b/src/gamebryogameplugins.h @@ -0,0 +1,45 @@ +#ifndef GAMEBRYOGAMEPLUGINS_H +#define GAMEBRYOGAMEPLUGINS_H + + +#include +#include +#include +#include + +class GamebryoGamePlugins : public GamePlugins { +public: + GamebryoGamePlugins(MOBase::IOrganizer *organizer); + + virtual void writePluginLists(const MOBase::IPluginList *pluginList) override; + virtual void readPluginLists(MOBase::IPluginList *pluginList) override; + +protected: + QTextCodec *utf8Codec() const { return m_Utf8Codec; } + QTextCodec *localCodec() const { return m_LocalCodec; } + + MOBase::IOrganizer *organizer() const { return m_Organizer; } + + virtual void writePluginList(const MOBase::IPluginList *pluginList, + const QString &filePath); + virtual void writeLoadOrderList(const MOBase::IPluginList *pluginList, + const QString &filePath); + virtual bool readLoadOrderList(MOBase::IPluginList *pluginList, + const QString &filePath); + virtual bool readPluginList(MOBase::IPluginList *pluginList, + const QString &filePath, bool useLoadOrder); + +private: + void writeList(const MOBase::IPluginList *pluginList, const QString &filePath, + bool loadOrder); + +private: + MOBase::IOrganizer *m_Organizer; + QTextCodec *m_Utf8Codec; + QTextCodec *m_LocalCodec; + + QDateTime m_LastRead; + std::map m_LastSaveHash; +}; + +#endif // GAMEBRYOGAMEPLUGINS_H diff --git a/src/gamegamebryo.cpp b/src/gamegamebryo.cpp index 9af0354f..026f0b4e 100644 --- a/src/gamegamebryo.cpp +++ b/src/gamegamebryo.cpp @@ -257,7 +257,8 @@ std::map GameGamebryo::featureList() const { typeid(ScriptExtender), m_ScriptExtender.get() }, { typeid(DataArchives), m_DataArchives.get() }, { typeid(SaveGameInfo), m_SaveGameInfo.get() }, - { typeid(LocalSavegames), m_LocalSavegames.get() } + { typeid(LocalSavegames), m_LocalSavegames.get() }, + { typeid(GamePlugins), m_GamePlugins.get() } }; } diff --git a/src/gamegamebryo.h b/src/gamegamebryo.h index 7cbf603c..a502896a 100644 --- a/src/gamegamebryo.h +++ b/src/gamegamebryo.h @@ -10,6 +10,7 @@ class SaveGameInfo; class BSAInvalidation; class LocalSavegames; class ScriptExtender; +class GamePlugins; #include #include @@ -71,8 +72,6 @@ protected: QString getLauncherName() const; QFileInfo findInGameFolder(const QString &relativePath) const; - static QString getKnownFolderPath(REFKNOWNFOLDERID folderId, bool useDefault); - static QString getSpecialPath(const QString &name); QString myGamesPath() const; QString selectedVariant() const; QString getVersion(QString const &program) const; @@ -105,6 +104,7 @@ protected: std::shared_ptr m_BSAInvalidation { nullptr }; std::shared_ptr m_SaveGameInfo { nullptr }; std::shared_ptr m_LocalSavegames { nullptr }; + std::shared_ptr m_GamePlugins { nullptr }; private: From c9c48f16e84c6f5b31b3c1f1c2fab271ec0954a6 Mon Sep 17 00:00:00 2001 From: Tannin Date: Fri, 6 May 2016 22:59:19 +0200 Subject: [PATCH 0224/1544] [game_skyrim] api changes --- src/games/skyrim/src/CMakeLists.txt | 16 +++++++++++++--- src/games/skyrim/src/gameskyrim.cpp | 5 +++++ 2 files changed, 18 insertions(+), 3 deletions(-) diff --git a/src/games/skyrim/src/CMakeLists.txt b/src/games/skyrim/src/CMakeLists.txt index e3e757f0..9d1b6a1b 100644 --- a/src/games/skyrim/src/CMakeLists.txt +++ b/src/games/skyrim/src/CMakeLists.txt @@ -41,11 +41,21 @@ TARGET_LINK_LIBRARIES(${PROJ_NAME} Qt5::Widgets ${Boost_LIBRARIES} uibase - gameGamebryo + game_gamebryo version) -SET_TARGET_PROPERTIES(${PROJ_NAME} PROPERTIES COMPILE_FLAGS /GL) -SET_TARGET_PROPERTIES(${PROJ_NAME} PROPERTIES LINK_FLAGS_RELWITHDEBINFO "/LTCG /LARGEADDRESSAWARE /OPT:REF /OPT:ICF") +IF(MSVC) + SET_TARGET_PROPERTIES(${PROJ_NAME} PROPERTIES LINK_FLAGS "/LARGEADDRESSAWARE") +ELSE(MSVC) + SET_TARGET_PROPERTIES(${PROJ_NAME} PROPERTIES LINK_FLAGS "-std=c++11") +ENDIF(MSVC) + +IF (NOT "${OPTIMIZE_COMPILE_FLAGS}" STREQUAL "") + SET_TARGET_PROPERTIES(${PROJ_NAME} PROPERTIES COMPILE_FLAGS_RELWITHDEBINFO ${OPTIMIZE_COMPILE_FLAGS}) +ENDIF() +IF (NOT "${OPTIMIZE_LINK_FLAGS}" STREQUAL "") + SET_TARGET_PROPERTIES(${PROJ_NAME} PROPERTIES LINK_FLAGS_RELWITHDEBINFO ${OPTIMIZE_LINK_FLAGS}) +ENDIF() QT5_USE_MODULES(${PROJ_NAME} Widgets) diff --git a/src/games/skyrim/src/gameskyrim.cpp b/src/games/skyrim/src/gameskyrim.cpp index 1fe02387..e2766e12 100644 --- a/src/games/skyrim/src/gameskyrim.cpp +++ b/src/games/skyrim/src/gameskyrim.cpp @@ -8,6 +8,9 @@ #include "executableinfo.h" #include "pluginsetting.h" +#include +#include + #include #include #include @@ -38,6 +41,8 @@ bool GameSkyrim::init(IOrganizer *moInfo) m_DataArchives = std::shared_ptr(new SkyrimDataArchives()); m_BSAInvalidation = std::shared_ptr(new SkyrimBSAInvalidation(m_DataArchives, this)); m_SaveGameInfo = std::shared_ptr(new SkyrimSaveGameInfo(this)); + m_LocalSavegames.reset(new GamebryoLocalSavegames(myGamesPath(), "skyrim.ini")); + m_GamePlugins = std::shared_ptr(new GamebryoGamePlugins(moInfo)); return true; } From b658b9dda79fe5ce1ec58f8b9776edfcc5a1e39d Mon Sep 17 00:00:00 2001 From: Tannin Date: Fri, 6 May 2016 22:59:50 +0200 Subject: [PATCH 0225/1544] [game_oblivion] api changes --- src/games/oblivion/src/CMakeLists.txt | 16 +++++++++++++--- src/games/oblivion/src/gameoblivion.cpp | 4 ++++ src/games/oblivion/src/gameoblivion.h | 2 -- 3 files changed, 17 insertions(+), 5 deletions(-) diff --git a/src/games/oblivion/src/CMakeLists.txt b/src/games/oblivion/src/CMakeLists.txt index 2685b0ec..4b29021f 100644 --- a/src/games/oblivion/src/CMakeLists.txt +++ b/src/games/oblivion/src/CMakeLists.txt @@ -40,11 +40,21 @@ TARGET_LINK_LIBRARIES(${PROJ_NAME} Qt5::Widgets ${Boost_LIBRARIES} uibase - gameGamebryo + game_gamebryo version) -SET_TARGET_PROPERTIES(${PROJ_NAME} PROPERTIES COMPILE_FLAGS /GL) -SET_TARGET_PROPERTIES(${PROJ_NAME} PROPERTIES LINK_FLAGS_RELWITHDEBINFO "/LTCG /LARGEADDRESSAWARE /OPT:REF /OPT:ICF") +IF(MSVC) + SET_TARGET_PROPERTIES(${PROJ_NAME} PROPERTIES LINK_FLAGS "/LARGEADDRESSAWARE") +ELSE(MSVC) + SET_TARGET_PROPERTIES(${PROJ_NAME} PROPERTIES LINK_FLAGS "-std=c++11") +ENDIF(MSVC) + +IF (NOT "${OPTIMIZE_COMPILE_FLAGS}" STREQUAL "") + SET_TARGET_PROPERTIES(${PROJ_NAME} PROPERTIES COMPILE_FLAGS_RELWITHDEBINFO ${OPTIMIZE_COMPILE_FLAGS}) +ENDIF() +IF (NOT "${OPTIMIZE_LINK_FLAGS}" STREQUAL "") + SET_TARGET_PROPERTIES(${PROJ_NAME} PROPERTIES LINK_FLAGS_RELWITHDEBINFO ${OPTIMIZE_LINK_FLAGS}) +ENDIF() QT5_USE_MODULES(${PROJ_NAME} Widgets) diff --git a/src/games/oblivion/src/gameoblivion.cpp b/src/games/oblivion/src/gameoblivion.cpp index 390300a5..068cdd1b 100644 --- a/src/games/oblivion/src/gameoblivion.cpp +++ b/src/games/oblivion/src/gameoblivion.cpp @@ -7,6 +7,8 @@ #include "pluginsetting.h" #include "executableinfo.h" +#include +#include #include #include @@ -29,6 +31,8 @@ bool GameOblivion::init(IOrganizer *moInfo) m_DataArchives = std::shared_ptr(new OblivionDataArchives()); m_BSAInvalidation = std::shared_ptr(new OblivionBSAInvalidation(m_DataArchives, this)); m_SaveGameInfo = std::shared_ptr(new OblivionSaveGameInfo(this)); + m_LocalSavegames.reset(new GamebryoLocalSavegames(myGamesPath(), "oblivion.ini")); + m_GamePlugins = std::shared_ptr(new GamebryoGamePlugins(moInfo)); return true; } diff --git a/src/games/oblivion/src/gameoblivion.h b/src/games/oblivion/src/gameoblivion.h index 736269b9..4ddf0712 100644 --- a/src/games/oblivion/src/gameoblivion.h +++ b/src/games/oblivion/src/gameoblivion.h @@ -9,9 +9,7 @@ class GameOblivion : public GameGamebryo { Q_OBJECT -#if QT_VERSION >= QT_VERSION_CHECK(5,0,0) Q_PLUGIN_METADATA(IID "org.tannin.GameOblivion" FILE "gameoblivion.json") -#endif public: From 1edcc9ff1da1263f0b0d0d713c4963a25c3297a2 Mon Sep 17 00:00:00 2001 From: Tannin Date: Fri, 6 May 2016 23:00:19 +0200 Subject: [PATCH 0226/1544] [game_fallout3] api changes --- src/games/fallout3/src/CMakeLists.txt | 16 +++++++++++++--- src/games/fallout3/src/gamefallout3.cpp | 4 ++++ 2 files changed, 17 insertions(+), 3 deletions(-) diff --git a/src/games/fallout3/src/CMakeLists.txt b/src/games/fallout3/src/CMakeLists.txt index be1bb063..338e83b7 100644 --- a/src/games/fallout3/src/CMakeLists.txt +++ b/src/games/fallout3/src/CMakeLists.txt @@ -40,11 +40,21 @@ TARGET_LINK_LIBRARIES(${PROJ_NAME} Qt5::Widgets ${Boost_LIBRARIES} uibase - gameGamebryo + game_gamebryo Version) -SET_TARGET_PROPERTIES(${PROJ_NAME} PROPERTIES COMPILE_FLAGS /GL) -SET_TARGET_PROPERTIES(${PROJ_NAME} PROPERTIES LINK_FLAGS_RELWITHDEBINFO "/LTCG /LARGEADDRESSAWARE /OPT:REF /OPT:ICF") +IF(MSVC) + SET_TARGET_PROPERTIES(${PROJ_NAME} PROPERTIES LINK_FLAGS "/LARGEADDRESSAWARE") +ELSE(MSVC) + SET_TARGET_PROPERTIES(${PROJ_NAME} PROPERTIES LINK_FLAGS "-std=c++11") +ENDIF(MSVC) + +IF (NOT "${OPTIMIZE_COMPILE_FLAGS}" STREQUAL "") + SET_TARGET_PROPERTIES(${PROJ_NAME} PROPERTIES COMPILE_FLAGS_RELWITHDEBINFO ${OPTIMIZE_COMPILE_FLAGS}) +ENDIF() +IF (NOT "${OPTIMIZE_LINK_FLAGS}" STREQUAL "") + SET_TARGET_PROPERTIES(${PROJ_NAME} PROPERTIES LINK_FLAGS_RELWITHDEBINFO ${OPTIMIZE_LINK_FLAGS}) +ENDIF() QT5_USE_MODULES(${PROJ_NAME} Widgets) diff --git a/src/games/fallout3/src/gamefallout3.cpp b/src/games/fallout3/src/gamefallout3.cpp index 8e32d00c..b3d058af 100644 --- a/src/games/fallout3/src/gamefallout3.cpp +++ b/src/games/fallout3/src/gamefallout3.cpp @@ -8,6 +8,8 @@ #include "executableinfo.h" #include "pluginsetting.h" #include "versioninfo.h" +#include +#include #include #include @@ -34,6 +36,8 @@ bool GameFallout3::init(IOrganizer *moInfo) m_DataArchives = std::shared_ptr(new Fallout3DataArchives()); m_BSAInvalidation = std::shared_ptr(new Fallout3BSAInvalidation(m_DataArchives, this)); m_SaveGameInfo = std::shared_ptr(new Fallout3SaveGameInfo(this)); + m_LocalSavegames.reset(new GamebryoLocalSavegames(myGamesPath(), "fallout.ini")); + m_GamePlugins = std::shared_ptr(new GamebryoGamePlugins(this)); return true; } From ea422d423679aca6df2cb18ba7ebb4a94ffad61d Mon Sep 17 00:00:00 2001 From: Tannin Date: Fri, 6 May 2016 23:01:24 +0200 Subject: [PATCH 0227/1544] [game_falloutnv] api changes --- src/games/falloutnv/src/CMakeLists.txt | 16 +++++++++++++--- src/games/falloutnv/src/gamefalloutnv.cpp | 4 ++++ 2 files changed, 17 insertions(+), 3 deletions(-) diff --git a/src/games/falloutnv/src/CMakeLists.txt b/src/games/falloutnv/src/CMakeLists.txt index be1bb063..338e83b7 100644 --- a/src/games/falloutnv/src/CMakeLists.txt +++ b/src/games/falloutnv/src/CMakeLists.txt @@ -40,11 +40,21 @@ TARGET_LINK_LIBRARIES(${PROJ_NAME} Qt5::Widgets ${Boost_LIBRARIES} uibase - gameGamebryo + game_gamebryo Version) -SET_TARGET_PROPERTIES(${PROJ_NAME} PROPERTIES COMPILE_FLAGS /GL) -SET_TARGET_PROPERTIES(${PROJ_NAME} PROPERTIES LINK_FLAGS_RELWITHDEBINFO "/LTCG /LARGEADDRESSAWARE /OPT:REF /OPT:ICF") +IF(MSVC) + SET_TARGET_PROPERTIES(${PROJ_NAME} PROPERTIES LINK_FLAGS "/LARGEADDRESSAWARE") +ELSE(MSVC) + SET_TARGET_PROPERTIES(${PROJ_NAME} PROPERTIES LINK_FLAGS "-std=c++11") +ENDIF(MSVC) + +IF (NOT "${OPTIMIZE_COMPILE_FLAGS}" STREQUAL "") + SET_TARGET_PROPERTIES(${PROJ_NAME} PROPERTIES COMPILE_FLAGS_RELWITHDEBINFO ${OPTIMIZE_COMPILE_FLAGS}) +ENDIF() +IF (NOT "${OPTIMIZE_LINK_FLAGS}" STREQUAL "") + SET_TARGET_PROPERTIES(${PROJ_NAME} PROPERTIES LINK_FLAGS_RELWITHDEBINFO ${OPTIMIZE_LINK_FLAGS}) +ENDIF() QT5_USE_MODULES(${PROJ_NAME} Widgets) diff --git a/src/games/falloutnv/src/gamefalloutnv.cpp b/src/games/falloutnv/src/gamefalloutnv.cpp index d9821242..2c39ac94 100644 --- a/src/games/falloutnv/src/gamefalloutnv.cpp +++ b/src/games/falloutnv/src/gamefalloutnv.cpp @@ -8,6 +8,8 @@ #include "executableinfo.h" #include "pluginsetting.h" #include "versioninfo.h" +#include +#include #include #include @@ -34,6 +36,8 @@ bool GameFalloutNV::init(IOrganizer *moInfo) m_DataArchives = std::shared_ptr(new FalloutNVDataArchives()); m_BSAInvalidation = std::shared_ptr(new FalloutNVBSAInvalidation(m_DataArchives, this)); m_SaveGameInfo = std::shared_ptr(new FalloutNVSaveGameInfo(this)); + m_LocalSavegames.reset(new GamebryoLocalSavegames(myGamesPath(), "fallout.ini")); + m_GamePlugins = std::shared_ptr(new GamebryoGamePlugins(this)); return true; } From c4b4278732a0fca4e88236d94b7d62e597955cf8 Mon Sep 17 00:00:00 2001 From: Tannin Date: Sat, 7 May 2016 19:41:13 +0200 Subject: [PATCH 0228/1544] fixed load order broken after external application updates only plugins.txt loadorder.txt --- src/gamebryogameplugins.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/gamebryogameplugins.cpp b/src/gamebryogameplugins.cpp index f98a1841..1ca0fb70 100644 --- a/src/gamebryogameplugins.cpp +++ b/src/gamebryogameplugins.cpp @@ -147,7 +147,7 @@ bool GamebryoGamePlugins::readLoadOrderList(MOBase::IPluginList *pluginList, } if (modName.size() > 0) { - if (!pluginNames.contains(modName)) { + if (!pluginNames.contains(modName, Qt::CaseInsensitive)) { pluginNames.append(modName); } } From 62b03439eb6149507a5746f75eb8ceec7afff30b Mon Sep 17 00:00:00 2001 From: Tannin Date: Sat, 7 May 2016 19:44:11 +0200 Subject: [PATCH 0229/1544] [game_fallout4vr] implemented new plugins.txt format and set correct load order mechanism --- src/games/fallout4vr/src/CMakeLists.txt | 14 +- .../fallout4vr/src/fallout4gameplugins.cpp | 126 ++++++++++++++++++ .../fallout4vr/src/fallout4gameplugins.h | 27 ++++ src/games/fallout4vr/src/gamefallout4.cpp | 15 ++- src/games/fallout4vr/src/gamefallout4.h | 3 +- 5 files changed, 177 insertions(+), 8 deletions(-) create mode 100644 src/games/fallout4vr/src/fallout4gameplugins.cpp create mode 100644 src/games/fallout4vr/src/fallout4gameplugins.h diff --git a/src/games/fallout4vr/src/CMakeLists.txt b/src/games/fallout4vr/src/CMakeLists.txt index a065ec74..9fac2d01 100644 --- a/src/games/fallout4vr/src/CMakeLists.txt +++ b/src/games/fallout4vr/src/CMakeLists.txt @@ -47,8 +47,18 @@ TARGET_LINK_LIBRARIES(${PROJ_NAME} Version game_gamebryo) -SET_TARGET_PROPERTIES(${PROJ_NAME} PROPERTIES COMPILE_FLAGS /GL) -SET_TARGET_PROPERTIES(${PROJ_NAME} PROPERTIES LINK_FLAGS_RELWITHDEBINFO "/LARGEADDRESSAWARE ${OPTIMIZE_LINK_FLAGS}") +IF(MSVC) + SET_TARGET_PROPERTIES(${PROJ_NAME} PROPERTIES LINK_FLAGS "/LARGEADDRESSAWARE") +ELSE(MSVC) + SET_TARGET_PROPERTIES(${PROJ_NAME} PROPERTIES LINK_FLAGS "-std=c++11") +ENDIF(MSVC) + +IF (NOT "${OPTIMIZE_COMPILE_FLAGS}" STREQUAL "") + SET_TARGET_PROPERTIES(${PROJ_NAME} PROPERTIES COMPILE_FLAGS_RELWITHDEBINFO ${OPTIMIZE_COMPILE_FLAGS}) +ENDIF() +IF (NOT "${OPTIMIZE_LINK_FLAGS}" STREQUAL "") + SET_TARGET_PROPERTIES(${PROJ_NAME} PROPERTIES LINK_FLAGS_RELWITHDEBINFO ${OPTIMIZE_LINK_FLAGS}) +ENDIF() QT5_USE_MODULES(${PROJ_NAME} Widgets) diff --git a/src/games/fallout4vr/src/fallout4gameplugins.cpp b/src/games/fallout4vr/src/fallout4gameplugins.cpp new file mode 100644 index 00000000..1d2e8546 --- /dev/null +++ b/src/games/fallout4vr/src/fallout4gameplugins.cpp @@ -0,0 +1,126 @@ +#include "fallout4gameplugins.h" +#include +#include +#include +#include +#include + +#include +#include +#include + + +using MOBase::IPluginGame; +using MOBase::IPluginList; +using MOBase::IOrganizer; +using MOBase::SafeWriteFile; +using MOBase::reportError; + +static const std::set OFFICIAL_FILES{"fallout4.esm", "dlcrobot.esm", + "dlcworkshop01.esm"}; + +Fallout4GamePlugins::Fallout4GamePlugins(IOrganizer *organizer) + : GamebryoGamePlugins(organizer) +{ +} + +void Fallout4GamePlugins::writePluginList(const IPluginList *pluginList, + const QString &filePath) { + SafeWriteFile file(filePath); + + QTextCodec *textCodec = localCodec(); + + file->resize(0); + + file->write(textCodec->fromUnicode( + "# This file was automatically generated by Mod Organizer.\r\n")); + + bool invalidFileNames = false; + int writtenCount = 0; + + QStringList plugins = pluginList->pluginNames(); + std::sort(plugins.begin(), plugins.end(), + [pluginList](const QString &lhs, const QString &rhs) { + return pluginList->priority(lhs) < pluginList->priority(rhs); + }); + + for (const QString &pluginName : plugins) { + if (pluginList->state(pluginName) == IPluginList::STATE_ACTIVE) { + if (!textCodec->canEncode(pluginName)) { + invalidFileNames = true; + qCritical("invalid plugin name %s", qPrintable(pluginName)); + } else { + file->write("*"); + file->write(textCodec->fromUnicode(pluginName)); + } + file->write("\r\n"); + ++writtenCount; + } + } + + if (invalidFileNames) { + reportError(QObject::tr("Some of your plugins have invalid names! These " + "plugins can not be loaded by the game. Please see " + "mo_interface.log for a list of affected plugins " + "and rename them.")); + } + + if (file.commitIfDifferent(m_LastSaveHash[filePath])) { + qDebug("%s saved", qPrintable(QDir::toNativeSeparators(filePath))); + } +} + +bool Fallout4GamePlugins::readPluginList(MOBase::IPluginList *pluginList, + const QString &filePath, + bool useLoadOrder) +{ + QStringList plugins; + + for (const QString &pluginName : OFFICIAL_FILES) { + pluginList->setState(pluginName, IPluginList::STATE_ACTIVE); + } + + QFile file(filePath); + if (!file.open(QIODevice::ReadOnly)) { + return false; + } + ON_BLOCK_EXIT([&]() { file.close(); }); + + if (file.size() == 0) { + // MO stores at least a header in the file. if it's completely empty the + // file is broken + return false; + } + + QStringList loadOrder = organizer()->managedGame()->primaryPlugins(); + while (!file.atEnd()) { + QByteArray line = file.readLine(); + QString pluginName; + if ((line.size() > 0) && (line.at(0) != '#')) { + pluginName = localCodec()->toUnicode(line.trimmed().constData()); + } + if (pluginName.startsWith('*')) { + pluginName.remove(0, 1); + } + if (pluginName.size() > 0) { + pluginList->setState(pluginName, IPluginList::STATE_ACTIVE); + plugins.removeAll(pluginName); + if (!loadOrder.contains(pluginName, Qt::CaseInsensitive)) { + loadOrder.append(pluginName); + } + } + } + + file.close(); + + // we removed each plugin found in the file, so what's left are inactive mods + for (const QString &pluginName : plugins) { + pluginList->setState(pluginName, IPluginList::STATE_INACTIVE); + } + + if (useLoadOrder) { + pluginList->setLoadOrder(loadOrder); + } + + return true; +} diff --git a/src/games/fallout4vr/src/fallout4gameplugins.h b/src/games/fallout4vr/src/fallout4gameplugins.h new file mode 100644 index 00000000..1e3aef1f --- /dev/null +++ b/src/games/fallout4vr/src/fallout4gameplugins.h @@ -0,0 +1,27 @@ +#ifndef FALLOUT4GAMEPLUGINS_H +#define FALLOUT4GAMEPLUGINS_H + + +#include +#include +#include +#include + + +class Fallout4GamePlugins : public GamebryoGamePlugins +{ +public: + Fallout4GamePlugins(MOBase::IOrganizer *organizer); + +protected: + virtual void writePluginList(const MOBase::IPluginList *pluginList, + const QString &filePath) override; + virtual bool readPluginList(MOBase::IPluginList *pluginList, + const QString &filePath, + bool useLoadOrder) override; + +private: + std::map m_LastSaveHash; +}; + +#endif // FALLOUT4GAMEPLUGINS_H diff --git a/src/games/fallout4vr/src/gamefallout4.cpp b/src/games/fallout4vr/src/gamefallout4.cpp index 52adb333..4790d965 100644 --- a/src/games/fallout4vr/src/gamefallout4.cpp +++ b/src/games/fallout4vr/src/gamefallout4.cpp @@ -3,11 +3,13 @@ #include "fallout4dataarchives.h" #include "fallout4scriptextender.h" #include "fallout4savegameinfo.h" +#include "fallout4gameplugins.h" #include #include "iplugingame.h" #include #include +#include #include "versioninfo.h" #include @@ -31,10 +33,13 @@ bool GameFallout4::init(IOrganizer *moInfo) if (!GameGamebryo::init(moInfo)) { return false; } + m_ScriptExtender = std::shared_ptr(new Fallout4ScriptExtender(this)); m_DataArchives = std::shared_ptr(new Fallout4DataArchives()); m_LocalSavegames.reset(new GamebryoLocalSavegames(myGamesPath(), "Fallout4.ini")); m_SaveGameInfo = std::shared_ptr(new Fallout4SaveGameInfo(this)); + m_GamePlugins = std::shared_ptr(new Fallout4GamePlugins(moInfo)); + return true; } @@ -71,7 +76,7 @@ QString GameFallout4::description() const MOBase::VersionInfo GameFallout4::version() const { - return VersionInfo(0, 2, 0, VersionInfo::RELEASE_BETA); + return VersionInfo(0, 3, 0, VersionInfo::RELEASE_BETA); } bool GameFallout4::isActive() const @@ -115,7 +120,7 @@ QString GameFallout4::steamAPPId() const QStringList GameFallout4::primaryPlugins() const { - return { "fallout4.esm" }; + return { "fallout4.esm", "dlcrobot.esm", "dlcworkshop01.esm" }; } QStringList GameFallout4::gameVariants() const @@ -138,8 +143,10 @@ QStringList GameFallout4::DLCPlugins() const return {}; } -//what load order mechanism? -// virtual LoadOrderMechanism getLoadOrderMechanism() const = 0; +IPluginGame::LoadOrderMechanism GameFallout4::loadOrderMechanism() const +{ + return IPluginGame::LoadOrderMechanism::PluginsTxt; +} int GameFallout4::nexusModOrganizerID() const { diff --git a/src/games/fallout4vr/src/gamefallout4.h b/src/games/fallout4vr/src/gamefallout4.h index d4bcbaeb..ca59561d 100644 --- a/src/games/fallout4vr/src/gamefallout4.h +++ b/src/games/fallout4vr/src/gamefallout4.h @@ -31,8 +31,7 @@ public: // IPluginGame interface virtual QString gameShortName() const override; virtual QStringList iniFiles() const override; virtual QStringList DLCPlugins() const override; -//what load order mechanism? -// virtual LoadOrderMechanism getLoadOrderMechanism() const = 0; + virtual LoadOrderMechanism loadOrderMechanism() const override; virtual int nexusModOrganizerID() const override; virtual int nexusGameID() const override; From 2b3d8b3082bcb45df10a90c24b960ad3ec85c89b Mon Sep 17 00:00:00 2001 From: Tannin Date: Sat, 7 May 2016 19:44:11 +0200 Subject: [PATCH 0230/1544] [game_fallout76] implemented new plugins.txt format and set correct load order mechanism --- src/games/fallout76/src/CMakeLists.txt | 14 +- .../fallout76/src/fallout4gameplugins.cpp | 126 ++++++++++++++++++ src/games/fallout76/src/fallout4gameplugins.h | 27 ++++ src/games/fallout76/src/gamefallout4.cpp | 15 ++- src/games/fallout76/src/gamefallout4.h | 3 +- 5 files changed, 177 insertions(+), 8 deletions(-) create mode 100644 src/games/fallout76/src/fallout4gameplugins.cpp create mode 100644 src/games/fallout76/src/fallout4gameplugins.h diff --git a/src/games/fallout76/src/CMakeLists.txt b/src/games/fallout76/src/CMakeLists.txt index a065ec74..9fac2d01 100644 --- a/src/games/fallout76/src/CMakeLists.txt +++ b/src/games/fallout76/src/CMakeLists.txt @@ -47,8 +47,18 @@ TARGET_LINK_LIBRARIES(${PROJ_NAME} Version game_gamebryo) -SET_TARGET_PROPERTIES(${PROJ_NAME} PROPERTIES COMPILE_FLAGS /GL) -SET_TARGET_PROPERTIES(${PROJ_NAME} PROPERTIES LINK_FLAGS_RELWITHDEBINFO "/LARGEADDRESSAWARE ${OPTIMIZE_LINK_FLAGS}") +IF(MSVC) + SET_TARGET_PROPERTIES(${PROJ_NAME} PROPERTIES LINK_FLAGS "/LARGEADDRESSAWARE") +ELSE(MSVC) + SET_TARGET_PROPERTIES(${PROJ_NAME} PROPERTIES LINK_FLAGS "-std=c++11") +ENDIF(MSVC) + +IF (NOT "${OPTIMIZE_COMPILE_FLAGS}" STREQUAL "") + SET_TARGET_PROPERTIES(${PROJ_NAME} PROPERTIES COMPILE_FLAGS_RELWITHDEBINFO ${OPTIMIZE_COMPILE_FLAGS}) +ENDIF() +IF (NOT "${OPTIMIZE_LINK_FLAGS}" STREQUAL "") + SET_TARGET_PROPERTIES(${PROJ_NAME} PROPERTIES LINK_FLAGS_RELWITHDEBINFO ${OPTIMIZE_LINK_FLAGS}) +ENDIF() QT5_USE_MODULES(${PROJ_NAME} Widgets) diff --git a/src/games/fallout76/src/fallout4gameplugins.cpp b/src/games/fallout76/src/fallout4gameplugins.cpp new file mode 100644 index 00000000..1d2e8546 --- /dev/null +++ b/src/games/fallout76/src/fallout4gameplugins.cpp @@ -0,0 +1,126 @@ +#include "fallout4gameplugins.h" +#include +#include +#include +#include +#include + +#include +#include +#include + + +using MOBase::IPluginGame; +using MOBase::IPluginList; +using MOBase::IOrganizer; +using MOBase::SafeWriteFile; +using MOBase::reportError; + +static const std::set OFFICIAL_FILES{"fallout4.esm", "dlcrobot.esm", + "dlcworkshop01.esm"}; + +Fallout4GamePlugins::Fallout4GamePlugins(IOrganizer *organizer) + : GamebryoGamePlugins(organizer) +{ +} + +void Fallout4GamePlugins::writePluginList(const IPluginList *pluginList, + const QString &filePath) { + SafeWriteFile file(filePath); + + QTextCodec *textCodec = localCodec(); + + file->resize(0); + + file->write(textCodec->fromUnicode( + "# This file was automatically generated by Mod Organizer.\r\n")); + + bool invalidFileNames = false; + int writtenCount = 0; + + QStringList plugins = pluginList->pluginNames(); + std::sort(plugins.begin(), plugins.end(), + [pluginList](const QString &lhs, const QString &rhs) { + return pluginList->priority(lhs) < pluginList->priority(rhs); + }); + + for (const QString &pluginName : plugins) { + if (pluginList->state(pluginName) == IPluginList::STATE_ACTIVE) { + if (!textCodec->canEncode(pluginName)) { + invalidFileNames = true; + qCritical("invalid plugin name %s", qPrintable(pluginName)); + } else { + file->write("*"); + file->write(textCodec->fromUnicode(pluginName)); + } + file->write("\r\n"); + ++writtenCount; + } + } + + if (invalidFileNames) { + reportError(QObject::tr("Some of your plugins have invalid names! These " + "plugins can not be loaded by the game. Please see " + "mo_interface.log for a list of affected plugins " + "and rename them.")); + } + + if (file.commitIfDifferent(m_LastSaveHash[filePath])) { + qDebug("%s saved", qPrintable(QDir::toNativeSeparators(filePath))); + } +} + +bool Fallout4GamePlugins::readPluginList(MOBase::IPluginList *pluginList, + const QString &filePath, + bool useLoadOrder) +{ + QStringList plugins; + + for (const QString &pluginName : OFFICIAL_FILES) { + pluginList->setState(pluginName, IPluginList::STATE_ACTIVE); + } + + QFile file(filePath); + if (!file.open(QIODevice::ReadOnly)) { + return false; + } + ON_BLOCK_EXIT([&]() { file.close(); }); + + if (file.size() == 0) { + // MO stores at least a header in the file. if it's completely empty the + // file is broken + return false; + } + + QStringList loadOrder = organizer()->managedGame()->primaryPlugins(); + while (!file.atEnd()) { + QByteArray line = file.readLine(); + QString pluginName; + if ((line.size() > 0) && (line.at(0) != '#')) { + pluginName = localCodec()->toUnicode(line.trimmed().constData()); + } + if (pluginName.startsWith('*')) { + pluginName.remove(0, 1); + } + if (pluginName.size() > 0) { + pluginList->setState(pluginName, IPluginList::STATE_ACTIVE); + plugins.removeAll(pluginName); + if (!loadOrder.contains(pluginName, Qt::CaseInsensitive)) { + loadOrder.append(pluginName); + } + } + } + + file.close(); + + // we removed each plugin found in the file, so what's left are inactive mods + for (const QString &pluginName : plugins) { + pluginList->setState(pluginName, IPluginList::STATE_INACTIVE); + } + + if (useLoadOrder) { + pluginList->setLoadOrder(loadOrder); + } + + return true; +} diff --git a/src/games/fallout76/src/fallout4gameplugins.h b/src/games/fallout76/src/fallout4gameplugins.h new file mode 100644 index 00000000..1e3aef1f --- /dev/null +++ b/src/games/fallout76/src/fallout4gameplugins.h @@ -0,0 +1,27 @@ +#ifndef FALLOUT4GAMEPLUGINS_H +#define FALLOUT4GAMEPLUGINS_H + + +#include +#include +#include +#include + + +class Fallout4GamePlugins : public GamebryoGamePlugins +{ +public: + Fallout4GamePlugins(MOBase::IOrganizer *organizer); + +protected: + virtual void writePluginList(const MOBase::IPluginList *pluginList, + const QString &filePath) override; + virtual bool readPluginList(MOBase::IPluginList *pluginList, + const QString &filePath, + bool useLoadOrder) override; + +private: + std::map m_LastSaveHash; +}; + +#endif // FALLOUT4GAMEPLUGINS_H diff --git a/src/games/fallout76/src/gamefallout4.cpp b/src/games/fallout76/src/gamefallout4.cpp index 52adb333..4790d965 100644 --- a/src/games/fallout76/src/gamefallout4.cpp +++ b/src/games/fallout76/src/gamefallout4.cpp @@ -3,11 +3,13 @@ #include "fallout4dataarchives.h" #include "fallout4scriptextender.h" #include "fallout4savegameinfo.h" +#include "fallout4gameplugins.h" #include #include "iplugingame.h" #include #include +#include #include "versioninfo.h" #include @@ -31,10 +33,13 @@ bool GameFallout4::init(IOrganizer *moInfo) if (!GameGamebryo::init(moInfo)) { return false; } + m_ScriptExtender = std::shared_ptr(new Fallout4ScriptExtender(this)); m_DataArchives = std::shared_ptr(new Fallout4DataArchives()); m_LocalSavegames.reset(new GamebryoLocalSavegames(myGamesPath(), "Fallout4.ini")); m_SaveGameInfo = std::shared_ptr(new Fallout4SaveGameInfo(this)); + m_GamePlugins = std::shared_ptr(new Fallout4GamePlugins(moInfo)); + return true; } @@ -71,7 +76,7 @@ QString GameFallout4::description() const MOBase::VersionInfo GameFallout4::version() const { - return VersionInfo(0, 2, 0, VersionInfo::RELEASE_BETA); + return VersionInfo(0, 3, 0, VersionInfo::RELEASE_BETA); } bool GameFallout4::isActive() const @@ -115,7 +120,7 @@ QString GameFallout4::steamAPPId() const QStringList GameFallout4::primaryPlugins() const { - return { "fallout4.esm" }; + return { "fallout4.esm", "dlcrobot.esm", "dlcworkshop01.esm" }; } QStringList GameFallout4::gameVariants() const @@ -138,8 +143,10 @@ QStringList GameFallout4::DLCPlugins() const return {}; } -//what load order mechanism? -// virtual LoadOrderMechanism getLoadOrderMechanism() const = 0; +IPluginGame::LoadOrderMechanism GameFallout4::loadOrderMechanism() const +{ + return IPluginGame::LoadOrderMechanism::PluginsTxt; +} int GameFallout4::nexusModOrganizerID() const { diff --git a/src/games/fallout76/src/gamefallout4.h b/src/games/fallout76/src/gamefallout4.h index d4bcbaeb..ca59561d 100644 --- a/src/games/fallout76/src/gamefallout4.h +++ b/src/games/fallout76/src/gamefallout4.h @@ -31,8 +31,7 @@ public: // IPluginGame interface virtual QString gameShortName() const override; virtual QStringList iniFiles() const override; virtual QStringList DLCPlugins() const override; -//what load order mechanism? -// virtual LoadOrderMechanism getLoadOrderMechanism() const = 0; + virtual LoadOrderMechanism loadOrderMechanism() const override; virtual int nexusModOrganizerID() const override; virtual int nexusGameID() const override; From 3f4bb1cda867941b536d4492b411c9d6303f2527 Mon Sep 17 00:00:00 2001 From: Tannin Date: Sat, 7 May 2016 19:44:11 +0200 Subject: [PATCH 0231/1544] [game_fallout4] implemented new plugins.txt format and set correct load order mechanism --- src/games/fallout4/src/CMakeLists.txt | 14 +- .../fallout4/src/fallout4gameplugins.cpp | 126 ++++++++++++++++++ src/games/fallout4/src/fallout4gameplugins.h | 27 ++++ src/games/fallout4/src/gamefallout4.cpp | 15 ++- src/games/fallout4/src/gamefallout4.h | 3 +- 5 files changed, 177 insertions(+), 8 deletions(-) create mode 100644 src/games/fallout4/src/fallout4gameplugins.cpp create mode 100644 src/games/fallout4/src/fallout4gameplugins.h diff --git a/src/games/fallout4/src/CMakeLists.txt b/src/games/fallout4/src/CMakeLists.txt index a065ec74..9fac2d01 100644 --- a/src/games/fallout4/src/CMakeLists.txt +++ b/src/games/fallout4/src/CMakeLists.txt @@ -47,8 +47,18 @@ TARGET_LINK_LIBRARIES(${PROJ_NAME} Version game_gamebryo) -SET_TARGET_PROPERTIES(${PROJ_NAME} PROPERTIES COMPILE_FLAGS /GL) -SET_TARGET_PROPERTIES(${PROJ_NAME} PROPERTIES LINK_FLAGS_RELWITHDEBINFO "/LARGEADDRESSAWARE ${OPTIMIZE_LINK_FLAGS}") +IF(MSVC) + SET_TARGET_PROPERTIES(${PROJ_NAME} PROPERTIES LINK_FLAGS "/LARGEADDRESSAWARE") +ELSE(MSVC) + SET_TARGET_PROPERTIES(${PROJ_NAME} PROPERTIES LINK_FLAGS "-std=c++11") +ENDIF(MSVC) + +IF (NOT "${OPTIMIZE_COMPILE_FLAGS}" STREQUAL "") + SET_TARGET_PROPERTIES(${PROJ_NAME} PROPERTIES COMPILE_FLAGS_RELWITHDEBINFO ${OPTIMIZE_COMPILE_FLAGS}) +ENDIF() +IF (NOT "${OPTIMIZE_LINK_FLAGS}" STREQUAL "") + SET_TARGET_PROPERTIES(${PROJ_NAME} PROPERTIES LINK_FLAGS_RELWITHDEBINFO ${OPTIMIZE_LINK_FLAGS}) +ENDIF() QT5_USE_MODULES(${PROJ_NAME} Widgets) diff --git a/src/games/fallout4/src/fallout4gameplugins.cpp b/src/games/fallout4/src/fallout4gameplugins.cpp new file mode 100644 index 00000000..1d2e8546 --- /dev/null +++ b/src/games/fallout4/src/fallout4gameplugins.cpp @@ -0,0 +1,126 @@ +#include "fallout4gameplugins.h" +#include +#include +#include +#include +#include + +#include +#include +#include + + +using MOBase::IPluginGame; +using MOBase::IPluginList; +using MOBase::IOrganizer; +using MOBase::SafeWriteFile; +using MOBase::reportError; + +static const std::set OFFICIAL_FILES{"fallout4.esm", "dlcrobot.esm", + "dlcworkshop01.esm"}; + +Fallout4GamePlugins::Fallout4GamePlugins(IOrganizer *organizer) + : GamebryoGamePlugins(organizer) +{ +} + +void Fallout4GamePlugins::writePluginList(const IPluginList *pluginList, + const QString &filePath) { + SafeWriteFile file(filePath); + + QTextCodec *textCodec = localCodec(); + + file->resize(0); + + file->write(textCodec->fromUnicode( + "# This file was automatically generated by Mod Organizer.\r\n")); + + bool invalidFileNames = false; + int writtenCount = 0; + + QStringList plugins = pluginList->pluginNames(); + std::sort(plugins.begin(), plugins.end(), + [pluginList](const QString &lhs, const QString &rhs) { + return pluginList->priority(lhs) < pluginList->priority(rhs); + }); + + for (const QString &pluginName : plugins) { + if (pluginList->state(pluginName) == IPluginList::STATE_ACTIVE) { + if (!textCodec->canEncode(pluginName)) { + invalidFileNames = true; + qCritical("invalid plugin name %s", qPrintable(pluginName)); + } else { + file->write("*"); + file->write(textCodec->fromUnicode(pluginName)); + } + file->write("\r\n"); + ++writtenCount; + } + } + + if (invalidFileNames) { + reportError(QObject::tr("Some of your plugins have invalid names! These " + "plugins can not be loaded by the game. Please see " + "mo_interface.log for a list of affected plugins " + "and rename them.")); + } + + if (file.commitIfDifferent(m_LastSaveHash[filePath])) { + qDebug("%s saved", qPrintable(QDir::toNativeSeparators(filePath))); + } +} + +bool Fallout4GamePlugins::readPluginList(MOBase::IPluginList *pluginList, + const QString &filePath, + bool useLoadOrder) +{ + QStringList plugins; + + for (const QString &pluginName : OFFICIAL_FILES) { + pluginList->setState(pluginName, IPluginList::STATE_ACTIVE); + } + + QFile file(filePath); + if (!file.open(QIODevice::ReadOnly)) { + return false; + } + ON_BLOCK_EXIT([&]() { file.close(); }); + + if (file.size() == 0) { + // MO stores at least a header in the file. if it's completely empty the + // file is broken + return false; + } + + QStringList loadOrder = organizer()->managedGame()->primaryPlugins(); + while (!file.atEnd()) { + QByteArray line = file.readLine(); + QString pluginName; + if ((line.size() > 0) && (line.at(0) != '#')) { + pluginName = localCodec()->toUnicode(line.trimmed().constData()); + } + if (pluginName.startsWith('*')) { + pluginName.remove(0, 1); + } + if (pluginName.size() > 0) { + pluginList->setState(pluginName, IPluginList::STATE_ACTIVE); + plugins.removeAll(pluginName); + if (!loadOrder.contains(pluginName, Qt::CaseInsensitive)) { + loadOrder.append(pluginName); + } + } + } + + file.close(); + + // we removed each plugin found in the file, so what's left are inactive mods + for (const QString &pluginName : plugins) { + pluginList->setState(pluginName, IPluginList::STATE_INACTIVE); + } + + if (useLoadOrder) { + pluginList->setLoadOrder(loadOrder); + } + + return true; +} diff --git a/src/games/fallout4/src/fallout4gameplugins.h b/src/games/fallout4/src/fallout4gameplugins.h new file mode 100644 index 00000000..1e3aef1f --- /dev/null +++ b/src/games/fallout4/src/fallout4gameplugins.h @@ -0,0 +1,27 @@ +#ifndef FALLOUT4GAMEPLUGINS_H +#define FALLOUT4GAMEPLUGINS_H + + +#include +#include +#include +#include + + +class Fallout4GamePlugins : public GamebryoGamePlugins +{ +public: + Fallout4GamePlugins(MOBase::IOrganizer *organizer); + +protected: + virtual void writePluginList(const MOBase::IPluginList *pluginList, + const QString &filePath) override; + virtual bool readPluginList(MOBase::IPluginList *pluginList, + const QString &filePath, + bool useLoadOrder) override; + +private: + std::map m_LastSaveHash; +}; + +#endif // FALLOUT4GAMEPLUGINS_H diff --git a/src/games/fallout4/src/gamefallout4.cpp b/src/games/fallout4/src/gamefallout4.cpp index 52adb333..4790d965 100644 --- a/src/games/fallout4/src/gamefallout4.cpp +++ b/src/games/fallout4/src/gamefallout4.cpp @@ -3,11 +3,13 @@ #include "fallout4dataarchives.h" #include "fallout4scriptextender.h" #include "fallout4savegameinfo.h" +#include "fallout4gameplugins.h" #include #include "iplugingame.h" #include #include +#include #include "versioninfo.h" #include @@ -31,10 +33,13 @@ bool GameFallout4::init(IOrganizer *moInfo) if (!GameGamebryo::init(moInfo)) { return false; } + m_ScriptExtender = std::shared_ptr(new Fallout4ScriptExtender(this)); m_DataArchives = std::shared_ptr(new Fallout4DataArchives()); m_LocalSavegames.reset(new GamebryoLocalSavegames(myGamesPath(), "Fallout4.ini")); m_SaveGameInfo = std::shared_ptr(new Fallout4SaveGameInfo(this)); + m_GamePlugins = std::shared_ptr(new Fallout4GamePlugins(moInfo)); + return true; } @@ -71,7 +76,7 @@ QString GameFallout4::description() const MOBase::VersionInfo GameFallout4::version() const { - return VersionInfo(0, 2, 0, VersionInfo::RELEASE_BETA); + return VersionInfo(0, 3, 0, VersionInfo::RELEASE_BETA); } bool GameFallout4::isActive() const @@ -115,7 +120,7 @@ QString GameFallout4::steamAPPId() const QStringList GameFallout4::primaryPlugins() const { - return { "fallout4.esm" }; + return { "fallout4.esm", "dlcrobot.esm", "dlcworkshop01.esm" }; } QStringList GameFallout4::gameVariants() const @@ -138,8 +143,10 @@ QStringList GameFallout4::DLCPlugins() const return {}; } -//what load order mechanism? -// virtual LoadOrderMechanism getLoadOrderMechanism() const = 0; +IPluginGame::LoadOrderMechanism GameFallout4::loadOrderMechanism() const +{ + return IPluginGame::LoadOrderMechanism::PluginsTxt; +} int GameFallout4::nexusModOrganizerID() const { diff --git a/src/games/fallout4/src/gamefallout4.h b/src/games/fallout4/src/gamefallout4.h index d4bcbaeb..ca59561d 100644 --- a/src/games/fallout4/src/gamefallout4.h +++ b/src/games/fallout4/src/gamefallout4.h @@ -31,8 +31,7 @@ public: // IPluginGame interface virtual QString gameShortName() const override; virtual QStringList iniFiles() const override; virtual QStringList DLCPlugins() const override; -//what load order mechanism? -// virtual LoadOrderMechanism getLoadOrderMechanism() const = 0; + virtual LoadOrderMechanism loadOrderMechanism() const override; virtual int nexusModOrganizerID() const override; virtual int nexusGameID() const override; From a66c72acffc5caf5fb96cd8d9b3ed77ba5e18770 Mon Sep 17 00:00:00 2001 From: Tannin Date: Mon, 9 May 2016 20:37:35 +0200 Subject: [PATCH 0232/1544] [game_fallout3] updated to current api --- src/games/fallout3/src/gamefallout3.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/games/fallout3/src/gamefallout3.cpp b/src/games/fallout3/src/gamefallout3.cpp index b3d058af..b120667c 100644 --- a/src/games/fallout3/src/gamefallout3.cpp +++ b/src/games/fallout3/src/gamefallout3.cpp @@ -37,7 +37,7 @@ bool GameFallout3::init(IOrganizer *moInfo) m_BSAInvalidation = std::shared_ptr(new Fallout3BSAInvalidation(m_DataArchives, this)); m_SaveGameInfo = std::shared_ptr(new Fallout3SaveGameInfo(this)); m_LocalSavegames.reset(new GamebryoLocalSavegames(myGamesPath(), "fallout.ini")); - m_GamePlugins = std::shared_ptr(new GamebryoGamePlugins(this)); + m_GamePlugins = std::shared_ptr(new GamebryoGamePlugins(moInfo)); return true; } From 8a98c7639b1a8f34dcf0b2c07cd713c3555e8341 Mon Sep 17 00:00:00 2001 From: Tannin Date: Mon, 9 May 2016 20:37:51 +0200 Subject: [PATCH 0233/1544] [game_falloutnv] updated to current api --- src/games/falloutnv/src/gamefalloutnv.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/games/falloutnv/src/gamefalloutnv.cpp b/src/games/falloutnv/src/gamefalloutnv.cpp index 2c39ac94..7e229903 100644 --- a/src/games/falloutnv/src/gamefalloutnv.cpp +++ b/src/games/falloutnv/src/gamefalloutnv.cpp @@ -37,7 +37,7 @@ bool GameFalloutNV::init(IOrganizer *moInfo) m_BSAInvalidation = std::shared_ptr(new FalloutNVBSAInvalidation(m_DataArchives, this)); m_SaveGameInfo = std::shared_ptr(new FalloutNVSaveGameInfo(this)); m_LocalSavegames.reset(new GamebryoLocalSavegames(myGamesPath(), "fallout.ini")); - m_GamePlugins = std::shared_ptr(new GamebryoGamePlugins(this)); + m_GamePlugins = std::shared_ptr(new GamebryoGamePlugins(moInfo)); return true; } From b5692121d28442310e7ee65531883861b81ea5f8 Mon Sep 17 00:00:00 2001 From: Tannin Date: Wed, 11 May 2016 21:17:47 +0200 Subject: [PATCH 0234/1544] fixed plugin list wasn't re-read after switching profiles --- src/gamebryogameplugins.cpp | 16 ++++++++++------ 1 file changed, 10 insertions(+), 6 deletions(-) diff --git a/src/gamebryogameplugins.cpp b/src/gamebryogameplugins.cpp index 1ca0fb70..10f39688 100644 --- a/src/gamebryogameplugins.cpp +++ b/src/gamebryogameplugins.cpp @@ -42,14 +42,18 @@ void GamebryoGamePlugins::readPluginLists(MOBase::IPluginList *pluginList) { QString pluginsPath = organizer()->profile()->absolutePath() + "/plugins.txt"; bool loadOrderIsNew = !m_LastRead.isValid() || - QFileInfo(loadOrderPath).lastModified() > m_LastRead; - if (loadOrderIsNew) { + QFileInfo(loadOrderPath).lastModified() > m_LastRead; + bool pluginsIsNew = !m_LastRead.isValid() || + QFileInfo(pluginsPath).lastModified() > m_LastRead; + + if (loadOrderIsNew || !pluginsIsNew) { + // read both files if they are both new or both older than the last read readLoadOrderList(pluginList, loadOrderPath); readPluginList(pluginList, pluginsPath, false); - } else if (QFileInfo(pluginsPath).lastModified() > m_LastRead) { - // humm, it appears an outside source changed the plugins.txt but not the - // loadorder.txt. In this case we have to use plugins.txt as the base for - // the load order + } else { + // if the plugin list is new but the load order isn't, this probably means + // an external tool that handles only the plugins.txt has been run in the + // meantime. We have to use plugins.txt for the load order as well. readPluginList(pluginList, pluginsPath, true); } From 244eff6d659c1afff02ee6b2bd4a4cfa903cef82 Mon Sep 17 00:00:00 2001 From: Tannin Date: Wed, 11 May 2016 21:19:12 +0200 Subject: [PATCH 0235/1544] [game_fallout4vr] added creation kit to automatically detected executables --- src/games/fallout4vr/src/fallout4gameplugins.cpp | 2 ++ src/games/fallout4vr/src/gamefallout4.cpp | 1 + 2 files changed, 3 insertions(+) diff --git a/src/games/fallout4vr/src/fallout4gameplugins.cpp b/src/games/fallout4vr/src/fallout4gameplugins.cpp index 1d2e8546..56d7d154 100644 --- a/src/games/fallout4vr/src/fallout4gameplugins.cpp +++ b/src/games/fallout4vr/src/fallout4gameplugins.cpp @@ -82,6 +82,7 @@ bool Fallout4GamePlugins::readPluginList(MOBase::IPluginList *pluginList, QFile file(filePath); if (!file.open(QIODevice::ReadOnly)) { + qWarning("%s not found", qPrintable(filePath)); return false; } ON_BLOCK_EXIT([&]() { file.close(); }); @@ -89,6 +90,7 @@ bool Fallout4GamePlugins::readPluginList(MOBase::IPluginList *pluginList, if (file.size() == 0) { // MO stores at least a header in the file. if it's completely empty the // file is broken + qWarning("%s empty", qPrintable(filePath)); return false; } diff --git a/src/games/fallout4vr/src/gamefallout4.cpp b/src/games/fallout4vr/src/gamefallout4.cpp index 4790d965..25678101 100644 --- a/src/games/fallout4vr/src/gamefallout4.cpp +++ b/src/games/fallout4vr/src/gamefallout4.cpp @@ -54,6 +54,7 @@ QList GameFallout4::executables() const << ExecutableInfo("F4SE", findInGameFolder(m_ScriptExtender->loaderName())) << ExecutableInfo("Fallout 4", findInGameFolder(binaryName())) << ExecutableInfo("Fallout Launcher", findInGameFolder(getLauncherName())) + << ExecutableInfo("Creation Kit", findInGameFolder("CreationKit.exe")) << ExecutableInfo("LOOT", getLootPath()) ; } From 77177a6c53ce8893d0a5a7055cb104f07afac4fa Mon Sep 17 00:00:00 2001 From: Tannin Date: Wed, 11 May 2016 21:19:12 +0200 Subject: [PATCH 0236/1544] [game_fallout76] added creation kit to automatically detected executables --- src/games/fallout76/src/fallout4gameplugins.cpp | 2 ++ src/games/fallout76/src/gamefallout4.cpp | 1 + 2 files changed, 3 insertions(+) diff --git a/src/games/fallout76/src/fallout4gameplugins.cpp b/src/games/fallout76/src/fallout4gameplugins.cpp index 1d2e8546..56d7d154 100644 --- a/src/games/fallout76/src/fallout4gameplugins.cpp +++ b/src/games/fallout76/src/fallout4gameplugins.cpp @@ -82,6 +82,7 @@ bool Fallout4GamePlugins::readPluginList(MOBase::IPluginList *pluginList, QFile file(filePath); if (!file.open(QIODevice::ReadOnly)) { + qWarning("%s not found", qPrintable(filePath)); return false; } ON_BLOCK_EXIT([&]() { file.close(); }); @@ -89,6 +90,7 @@ bool Fallout4GamePlugins::readPluginList(MOBase::IPluginList *pluginList, if (file.size() == 0) { // MO stores at least a header in the file. if it's completely empty the // file is broken + qWarning("%s empty", qPrintable(filePath)); return false; } diff --git a/src/games/fallout76/src/gamefallout4.cpp b/src/games/fallout76/src/gamefallout4.cpp index 4790d965..25678101 100644 --- a/src/games/fallout76/src/gamefallout4.cpp +++ b/src/games/fallout76/src/gamefallout4.cpp @@ -54,6 +54,7 @@ QList GameFallout4::executables() const << ExecutableInfo("F4SE", findInGameFolder(m_ScriptExtender->loaderName())) << ExecutableInfo("Fallout 4", findInGameFolder(binaryName())) << ExecutableInfo("Fallout Launcher", findInGameFolder(getLauncherName())) + << ExecutableInfo("Creation Kit", findInGameFolder("CreationKit.exe")) << ExecutableInfo("LOOT", getLootPath()) ; } From 4c1c4f98b97e90e31b50ce9251642027bebd7b80 Mon Sep 17 00:00:00 2001 From: Tannin Date: Wed, 11 May 2016 21:19:12 +0200 Subject: [PATCH 0237/1544] [game_fallout4] added creation kit to automatically detected executables --- src/games/fallout4/src/fallout4gameplugins.cpp | 2 ++ src/games/fallout4/src/gamefallout4.cpp | 1 + 2 files changed, 3 insertions(+) diff --git a/src/games/fallout4/src/fallout4gameplugins.cpp b/src/games/fallout4/src/fallout4gameplugins.cpp index 1d2e8546..56d7d154 100644 --- a/src/games/fallout4/src/fallout4gameplugins.cpp +++ b/src/games/fallout4/src/fallout4gameplugins.cpp @@ -82,6 +82,7 @@ bool Fallout4GamePlugins::readPluginList(MOBase::IPluginList *pluginList, QFile file(filePath); if (!file.open(QIODevice::ReadOnly)) { + qWarning("%s not found", qPrintable(filePath)); return false; } ON_BLOCK_EXIT([&]() { file.close(); }); @@ -89,6 +90,7 @@ bool Fallout4GamePlugins::readPluginList(MOBase::IPluginList *pluginList, if (file.size() == 0) { // MO stores at least a header in the file. if it's completely empty the // file is broken + qWarning("%s empty", qPrintable(filePath)); return false; } diff --git a/src/games/fallout4/src/gamefallout4.cpp b/src/games/fallout4/src/gamefallout4.cpp index 4790d965..25678101 100644 --- a/src/games/fallout4/src/gamefallout4.cpp +++ b/src/games/fallout4/src/gamefallout4.cpp @@ -54,6 +54,7 @@ QList GameFallout4::executables() const << ExecutableInfo("F4SE", findInGameFolder(m_ScriptExtender->loaderName())) << ExecutableInfo("Fallout 4", findInGameFolder(binaryName())) << ExecutableInfo("Fallout Launcher", findInGameFolder(getLauncherName())) + << ExecutableInfo("Creation Kit", findInGameFolder("CreationKit.exe")) << ExecutableInfo("LOOT", getLootPath()) ; } From e84be4ea21c961b0aac13605d3b37b8e098cbf08 Mon Sep 17 00:00:00 2001 From: Tannin Date: Sat, 4 Jun 2016 20:11:10 +0200 Subject: [PATCH 0238/1544] [game_fallout4vr] support for far harbor --- src/games/fallout4vr/src/fallout4gameplugins.cpp | 4 ++-- src/games/fallout4vr/src/gamefallout4.cpp | 5 ++--- 2 files changed, 4 insertions(+), 5 deletions(-) diff --git a/src/games/fallout4vr/src/fallout4gameplugins.cpp b/src/games/fallout4vr/src/fallout4gameplugins.cpp index 56d7d154..d8c554ba 100644 --- a/src/games/fallout4vr/src/fallout4gameplugins.cpp +++ b/src/games/fallout4vr/src/fallout4gameplugins.cpp @@ -16,8 +16,8 @@ using MOBase::IOrganizer; using MOBase::SafeWriteFile; using MOBase::reportError; -static const std::set OFFICIAL_FILES{"fallout4.esm", "dlcrobot.esm", - "dlcworkshop01.esm"}; +static const std::set OFFICIAL_FILES{ + "fallout4.esm", "dlcrobot.esm", "dlcworkshop01.esm", "dlccoast.esm"}; Fallout4GamePlugins::Fallout4GamePlugins(IOrganizer *organizer) : GamebryoGamePlugins(organizer) diff --git a/src/games/fallout4vr/src/gamefallout4.cpp b/src/games/fallout4vr/src/gamefallout4.cpp index 25678101..42ba097d 100644 --- a/src/games/fallout4vr/src/gamefallout4.cpp +++ b/src/games/fallout4vr/src/gamefallout4.cpp @@ -119,9 +119,8 @@ QString GameFallout4::steamAPPId() const return "377160"; } -QStringList GameFallout4::primaryPlugins() const -{ - return { "fallout4.esm", "dlcrobot.esm", "dlcworkshop01.esm" }; +QStringList GameFallout4::primaryPlugins() const { + return {"fallout4.esm", "dlcrobot.esm", "dlcworkshop01.esm", "dlccoast.esm"}; } QStringList GameFallout4::gameVariants() const From 1e029a534f766d95fbecee7680926ac5250c019f Mon Sep 17 00:00:00 2001 From: Tannin Date: Sat, 4 Jun 2016 20:11:10 +0200 Subject: [PATCH 0239/1544] [game_fallout76] support for far harbor --- src/games/fallout76/src/fallout4gameplugins.cpp | 4 ++-- src/games/fallout76/src/gamefallout4.cpp | 5 ++--- 2 files changed, 4 insertions(+), 5 deletions(-) diff --git a/src/games/fallout76/src/fallout4gameplugins.cpp b/src/games/fallout76/src/fallout4gameplugins.cpp index 56d7d154..d8c554ba 100644 --- a/src/games/fallout76/src/fallout4gameplugins.cpp +++ b/src/games/fallout76/src/fallout4gameplugins.cpp @@ -16,8 +16,8 @@ using MOBase::IOrganizer; using MOBase::SafeWriteFile; using MOBase::reportError; -static const std::set OFFICIAL_FILES{"fallout4.esm", "dlcrobot.esm", - "dlcworkshop01.esm"}; +static const std::set OFFICIAL_FILES{ + "fallout4.esm", "dlcrobot.esm", "dlcworkshop01.esm", "dlccoast.esm"}; Fallout4GamePlugins::Fallout4GamePlugins(IOrganizer *organizer) : GamebryoGamePlugins(organizer) diff --git a/src/games/fallout76/src/gamefallout4.cpp b/src/games/fallout76/src/gamefallout4.cpp index 25678101..42ba097d 100644 --- a/src/games/fallout76/src/gamefallout4.cpp +++ b/src/games/fallout76/src/gamefallout4.cpp @@ -119,9 +119,8 @@ QString GameFallout4::steamAPPId() const return "377160"; } -QStringList GameFallout4::primaryPlugins() const -{ - return { "fallout4.esm", "dlcrobot.esm", "dlcworkshop01.esm" }; +QStringList GameFallout4::primaryPlugins() const { + return {"fallout4.esm", "dlcrobot.esm", "dlcworkshop01.esm", "dlccoast.esm"}; } QStringList GameFallout4::gameVariants() const From bac1b83dc1d0c39734a39b46feda5655123a42cc Mon Sep 17 00:00:00 2001 From: Tannin Date: Sat, 4 Jun 2016 20:11:10 +0200 Subject: [PATCH 0240/1544] [game_fallout4] support for far harbor --- src/games/fallout4/src/fallout4gameplugins.cpp | 4 ++-- src/games/fallout4/src/gamefallout4.cpp | 5 ++--- 2 files changed, 4 insertions(+), 5 deletions(-) diff --git a/src/games/fallout4/src/fallout4gameplugins.cpp b/src/games/fallout4/src/fallout4gameplugins.cpp index 56d7d154..d8c554ba 100644 --- a/src/games/fallout4/src/fallout4gameplugins.cpp +++ b/src/games/fallout4/src/fallout4gameplugins.cpp @@ -16,8 +16,8 @@ using MOBase::IOrganizer; using MOBase::SafeWriteFile; using MOBase::reportError; -static const std::set OFFICIAL_FILES{"fallout4.esm", "dlcrobot.esm", - "dlcworkshop01.esm"}; +static const std::set OFFICIAL_FILES{ + "fallout4.esm", "dlcrobot.esm", "dlcworkshop01.esm", "dlccoast.esm"}; Fallout4GamePlugins::Fallout4GamePlugins(IOrganizer *organizer) : GamebryoGamePlugins(organizer) diff --git a/src/games/fallout4/src/gamefallout4.cpp b/src/games/fallout4/src/gamefallout4.cpp index 25678101..42ba097d 100644 --- a/src/games/fallout4/src/gamefallout4.cpp +++ b/src/games/fallout4/src/gamefallout4.cpp @@ -119,9 +119,8 @@ QString GameFallout4::steamAPPId() const return "377160"; } -QStringList GameFallout4::primaryPlugins() const -{ - return { "fallout4.esm", "dlcrobot.esm", "dlcworkshop01.esm" }; +QStringList GameFallout4::primaryPlugins() const { + return {"fallout4.esm", "dlcrobot.esm", "dlcworkshop01.esm", "dlccoast.esm"}; } QStringList GameFallout4::gameVariants() const From ea22b4be96fab2ad4692c0df408bba34b793ac79 Mon Sep 17 00:00:00 2001 From: Tannin Date: Sat, 4 Jun 2016 20:16:56 +0200 Subject: [PATCH 0241/1544] [game_fallout4vr] bugfix: error messages if a dlc isn't installed --- src/games/fallout4vr/src/fallout4gameplugins.cpp | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/src/games/fallout4vr/src/fallout4gameplugins.cpp b/src/games/fallout4vr/src/fallout4gameplugins.cpp index d8c554ba..85bcbe4f 100644 --- a/src/games/fallout4vr/src/fallout4gameplugins.cpp +++ b/src/games/fallout4vr/src/fallout4gameplugins.cpp @@ -77,7 +77,9 @@ bool Fallout4GamePlugins::readPluginList(MOBase::IPluginList *pluginList, QStringList plugins; for (const QString &pluginName : OFFICIAL_FILES) { - pluginList->setState(pluginName, IPluginList::STATE_ACTIVE); + if (pluginList->state(pluginName) != IPluginList::STATE_MISSING) { + pluginList->setState(pluginName, IPluginList::STATE_ACTIVE); + } } QFile file(filePath); From 00f26964452990a2890bf2c45906f05756f0cca1 Mon Sep 17 00:00:00 2001 From: Tannin Date: Sat, 4 Jun 2016 20:16:56 +0200 Subject: [PATCH 0242/1544] [game_fallout76] bugfix: error messages if a dlc isn't installed --- src/games/fallout76/src/fallout4gameplugins.cpp | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/src/games/fallout76/src/fallout4gameplugins.cpp b/src/games/fallout76/src/fallout4gameplugins.cpp index d8c554ba..85bcbe4f 100644 --- a/src/games/fallout76/src/fallout4gameplugins.cpp +++ b/src/games/fallout76/src/fallout4gameplugins.cpp @@ -77,7 +77,9 @@ bool Fallout4GamePlugins::readPluginList(MOBase::IPluginList *pluginList, QStringList plugins; for (const QString &pluginName : OFFICIAL_FILES) { - pluginList->setState(pluginName, IPluginList::STATE_ACTIVE); + if (pluginList->state(pluginName) != IPluginList::STATE_MISSING) { + pluginList->setState(pluginName, IPluginList::STATE_ACTIVE); + } } QFile file(filePath); From 252517c00caa5d4326bdf9f12939e06ae21d3cc4 Mon Sep 17 00:00:00 2001 From: Tannin Date: Sat, 4 Jun 2016 20:16:56 +0200 Subject: [PATCH 0243/1544] [game_fallout4] bugfix: error messages if a dlc isn't installed --- src/games/fallout4/src/fallout4gameplugins.cpp | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/src/games/fallout4/src/fallout4gameplugins.cpp b/src/games/fallout4/src/fallout4gameplugins.cpp index d8c554ba..85bcbe4f 100644 --- a/src/games/fallout4/src/fallout4gameplugins.cpp +++ b/src/games/fallout4/src/fallout4gameplugins.cpp @@ -77,7 +77,9 @@ bool Fallout4GamePlugins::readPluginList(MOBase::IPluginList *pluginList, QStringList plugins; for (const QString &pluginName : OFFICIAL_FILES) { - pluginList->setState(pluginName, IPluginList::STATE_ACTIVE); + if (pluginList->state(pluginName) != IPluginList::STATE_MISSING) { + pluginList->setState(pluginName, IPluginList::STATE_ACTIVE); + } } QFile file(filePath); From f143933a01c063de5906f2ae9b0c9402bb01d612 Mon Sep 17 00:00:00 2001 From: Tannin Date: Sat, 4 Jun 2016 20:17:56 +0200 Subject: [PATCH 0244/1544] [game_fallout4vr] translation --- src/games/fallout4vr/src/CMakeLists.txt | 4 +++- src/games/fallout4vr/src/game_fallout4_en.ts | 21 ++++++++++++++++++++ 2 files changed, 24 insertions(+), 1 deletion(-) create mode 100644 src/games/fallout4vr/src/game_fallout4_en.ts diff --git a/src/games/fallout4vr/src/CMakeLists.txt b/src/games/fallout4vr/src/CMakeLists.txt index 9fac2d01..7d3c4a88 100644 --- a/src/games/fallout4vr/src/CMakeLists.txt +++ b/src/games/fallout4vr/src/CMakeLists.txt @@ -16,6 +16,8 @@ SET(CMAKE_AUTOUIC ON) FIND_PACKAGE(Qt5Widgets REQUIRED) QT5_WRAP_UI(${PROJ_NAME}_UIHDRS ${${PROJ_NAME}_FORMS}) QT5_ADD_RESOURCES(${PROJ_NAME}_RCCPPS ${${PROJ_NAME}_QRCS}) +FIND_PACKAGE(Qt5LinguistTools) +QT5_CREATE_TRANSLATION(${PROJ_NAME}_translations_qm ${CMAKE_SOURCE_DIR}/src ${CMAKE_SOURCE_DIR}/src/${PROJ_NAME}_en.ts) SET(Boost_USE_STATIC_LIBS ON) SET(Boost_USE_MULTITHREADED ON) @@ -39,7 +41,7 @@ LINK_DIRECTORIES(${project_path}/uibase/build/src ${lib_path}) -ADD_LIBRARY(${PROJ_NAME} SHARED ${${PROJ_NAME}_HDRS} ${${PROJ_NAME}_SRCS} ${${PROJ_NAME}_UIHDRS} ${${PROJ_NAME}_RCCPPS}) +ADD_LIBRARY(${PROJ_NAME} SHARED ${${PROJ_NAME}_HDRS} ${${PROJ_NAME}_SRCS} ${${PROJ_NAME}_UIHDRS} ${${PROJ_NAME}_RCCPPS} ${${PROJ_NAME}_translations_qm}) TARGET_LINK_LIBRARIES(${PROJ_NAME} Qt5::Widgets ${Boost_LIBRARIES} diff --git a/src/games/fallout4vr/src/game_fallout4_en.ts b/src/games/fallout4vr/src/game_fallout4_en.ts new file mode 100644 index 00000000..d7b7d990 --- /dev/null +++ b/src/games/fallout4vr/src/game_fallout4_en.ts @@ -0,0 +1,21 @@ + + + + + GameFallout4 + + + Adds support for the game Fallout 4. +Splash by %1 + + + + + QObject + + + Some of your plugins have invalid names! These plugins can not be loaded by the game. Please see mo_interface.log for a list of affected plugins and rename them. + + + + From 53d337e8f63922a9a595e1fa7081882471da62f0 Mon Sep 17 00:00:00 2001 From: Tannin Date: Sat, 4 Jun 2016 20:17:56 +0200 Subject: [PATCH 0245/1544] [game_fallout76] translation --- src/games/fallout76/src/CMakeLists.txt | 4 +++- src/games/fallout76/src/game_fallout4_en.ts | 21 +++++++++++++++++++++ 2 files changed, 24 insertions(+), 1 deletion(-) create mode 100644 src/games/fallout76/src/game_fallout4_en.ts diff --git a/src/games/fallout76/src/CMakeLists.txt b/src/games/fallout76/src/CMakeLists.txt index 9fac2d01..7d3c4a88 100644 --- a/src/games/fallout76/src/CMakeLists.txt +++ b/src/games/fallout76/src/CMakeLists.txt @@ -16,6 +16,8 @@ SET(CMAKE_AUTOUIC ON) FIND_PACKAGE(Qt5Widgets REQUIRED) QT5_WRAP_UI(${PROJ_NAME}_UIHDRS ${${PROJ_NAME}_FORMS}) QT5_ADD_RESOURCES(${PROJ_NAME}_RCCPPS ${${PROJ_NAME}_QRCS}) +FIND_PACKAGE(Qt5LinguistTools) +QT5_CREATE_TRANSLATION(${PROJ_NAME}_translations_qm ${CMAKE_SOURCE_DIR}/src ${CMAKE_SOURCE_DIR}/src/${PROJ_NAME}_en.ts) SET(Boost_USE_STATIC_LIBS ON) SET(Boost_USE_MULTITHREADED ON) @@ -39,7 +41,7 @@ LINK_DIRECTORIES(${project_path}/uibase/build/src ${lib_path}) -ADD_LIBRARY(${PROJ_NAME} SHARED ${${PROJ_NAME}_HDRS} ${${PROJ_NAME}_SRCS} ${${PROJ_NAME}_UIHDRS} ${${PROJ_NAME}_RCCPPS}) +ADD_LIBRARY(${PROJ_NAME} SHARED ${${PROJ_NAME}_HDRS} ${${PROJ_NAME}_SRCS} ${${PROJ_NAME}_UIHDRS} ${${PROJ_NAME}_RCCPPS} ${${PROJ_NAME}_translations_qm}) TARGET_LINK_LIBRARIES(${PROJ_NAME} Qt5::Widgets ${Boost_LIBRARIES} diff --git a/src/games/fallout76/src/game_fallout4_en.ts b/src/games/fallout76/src/game_fallout4_en.ts new file mode 100644 index 00000000..d7b7d990 --- /dev/null +++ b/src/games/fallout76/src/game_fallout4_en.ts @@ -0,0 +1,21 @@ + + + + + GameFallout4 + + + Adds support for the game Fallout 4. +Splash by %1 + + + + + QObject + + + Some of your plugins have invalid names! These plugins can not be loaded by the game. Please see mo_interface.log for a list of affected plugins and rename them. + + + + From a07ffe53a8793877587760e7c32620c5bc281b0e Mon Sep 17 00:00:00 2001 From: Tannin Date: Sat, 4 Jun 2016 20:17:56 +0200 Subject: [PATCH 0246/1544] [game_fallout4] translation --- src/games/fallout4/src/CMakeLists.txt | 4 +++- src/games/fallout4/src/game_fallout4_en.ts | 21 +++++++++++++++++++++ 2 files changed, 24 insertions(+), 1 deletion(-) create mode 100644 src/games/fallout4/src/game_fallout4_en.ts diff --git a/src/games/fallout4/src/CMakeLists.txt b/src/games/fallout4/src/CMakeLists.txt index 9fac2d01..7d3c4a88 100644 --- a/src/games/fallout4/src/CMakeLists.txt +++ b/src/games/fallout4/src/CMakeLists.txt @@ -16,6 +16,8 @@ SET(CMAKE_AUTOUIC ON) FIND_PACKAGE(Qt5Widgets REQUIRED) QT5_WRAP_UI(${PROJ_NAME}_UIHDRS ${${PROJ_NAME}_FORMS}) QT5_ADD_RESOURCES(${PROJ_NAME}_RCCPPS ${${PROJ_NAME}_QRCS}) +FIND_PACKAGE(Qt5LinguistTools) +QT5_CREATE_TRANSLATION(${PROJ_NAME}_translations_qm ${CMAKE_SOURCE_DIR}/src ${CMAKE_SOURCE_DIR}/src/${PROJ_NAME}_en.ts) SET(Boost_USE_STATIC_LIBS ON) SET(Boost_USE_MULTITHREADED ON) @@ -39,7 +41,7 @@ LINK_DIRECTORIES(${project_path}/uibase/build/src ${lib_path}) -ADD_LIBRARY(${PROJ_NAME} SHARED ${${PROJ_NAME}_HDRS} ${${PROJ_NAME}_SRCS} ${${PROJ_NAME}_UIHDRS} ${${PROJ_NAME}_RCCPPS}) +ADD_LIBRARY(${PROJ_NAME} SHARED ${${PROJ_NAME}_HDRS} ${${PROJ_NAME}_SRCS} ${${PROJ_NAME}_UIHDRS} ${${PROJ_NAME}_RCCPPS} ${${PROJ_NAME}_translations_qm}) TARGET_LINK_LIBRARIES(${PROJ_NAME} Qt5::Widgets ${Boost_LIBRARIES} diff --git a/src/games/fallout4/src/game_fallout4_en.ts b/src/games/fallout4/src/game_fallout4_en.ts new file mode 100644 index 00000000..d7b7d990 --- /dev/null +++ b/src/games/fallout4/src/game_fallout4_en.ts @@ -0,0 +1,21 @@ + + + + + GameFallout4 + + + Adds support for the game Fallout 4. +Splash by %1 + + + + + QObject + + + Some of your plugins have invalid names! These plugins can not be loaded by the game. Please see mo_interface.log for a list of affected plugins and rename them. + + + + From 5ab1205cc2b43c7cee2e13fd48df7d726aa05952 Mon Sep 17 00:00:00 2001 From: Tannin Date: Sat, 4 Jun 2016 20:31:47 +0200 Subject: [PATCH 0247/1544] [game_fallout3] translation --- src/games/fallout3/src/CMakeLists.txt | 4 +++- src/games/fallout3/src/game_fallout3_en.ts | 12 ++++++++++++ 2 files changed, 15 insertions(+), 1 deletion(-) create mode 100644 src/games/fallout3/src/game_fallout3_en.ts diff --git a/src/games/fallout3/src/CMakeLists.txt b/src/games/fallout3/src/CMakeLists.txt index 338e83b7..b251bd6f 100644 --- a/src/games/fallout3/src/CMakeLists.txt +++ b/src/games/fallout3/src/CMakeLists.txt @@ -12,6 +12,8 @@ SET(CMAKE_AUTOMOC ON) SET(CMAKE_AUTOUIC ON) FIND_PACKAGE(Qt5Widgets REQUIRED) QT5_WRAP_UI(${PROJ_NAME}_UIHDRS ${${PROJ_NAME}_FORMS}) +FIND_PACKAGE(Qt5LinguistTools) +QT5_CREATE_TRANSLATION(${PROJ_NAME}_translations_qm ${CMAKE_SOURCE_DIR}/src ${CMAKE_SOURCE_DIR}/src/${PROJ_NAME}_en.ts) SET(Boost_USE_STATIC_LIBS ON) SET(Boost_USE_MULTITHREADED ON) @@ -35,7 +37,7 @@ LINK_DIRECTORIES(${project_path}/uibase/build/src ${lib_path}) -ADD_LIBRARY(${PROJ_NAME} SHARED ${${PROJ_NAME}_HDRS} ${${PROJ_NAME}_SRCS} ${${PROJ_NAME}_UIHDRS}) +ADD_LIBRARY(${PROJ_NAME} SHARED ${${PROJ_NAME}_HDRS} ${${PROJ_NAME}_SRCS} ${${PROJ_NAME}_UIHDRS} ${${PROJ_NAME}_translations_qm}) TARGET_LINK_LIBRARIES(${PROJ_NAME} Qt5::Widgets ${Boost_LIBRARIES} diff --git a/src/games/fallout3/src/game_fallout3_en.ts b/src/games/fallout3/src/game_fallout3_en.ts new file mode 100644 index 00000000..7e6aab8e --- /dev/null +++ b/src/games/fallout3/src/game_fallout3_en.ts @@ -0,0 +1,12 @@ + + + + + GameFallout3 + + + Adds support for the game Fallout 3s + + + + From 0c80aadad247292c432637cfc1be0e6649e95c85 Mon Sep 17 00:00:00 2001 From: Tannin Date: Sat, 4 Jun 2016 20:32:32 +0200 Subject: [PATCH 0248/1544] [game_falloutnv] translation --- src/games/falloutnv/src/CMakeLists.txt | 4 +++- src/games/falloutnv/src/game_falloutNV_en.ts | 12 ++++++++++++ 2 files changed, 15 insertions(+), 1 deletion(-) create mode 100644 src/games/falloutnv/src/game_falloutNV_en.ts diff --git a/src/games/falloutnv/src/CMakeLists.txt b/src/games/falloutnv/src/CMakeLists.txt index 338e83b7..b251bd6f 100644 --- a/src/games/falloutnv/src/CMakeLists.txt +++ b/src/games/falloutnv/src/CMakeLists.txt @@ -12,6 +12,8 @@ SET(CMAKE_AUTOMOC ON) SET(CMAKE_AUTOUIC ON) FIND_PACKAGE(Qt5Widgets REQUIRED) QT5_WRAP_UI(${PROJ_NAME}_UIHDRS ${${PROJ_NAME}_FORMS}) +FIND_PACKAGE(Qt5LinguistTools) +QT5_CREATE_TRANSLATION(${PROJ_NAME}_translations_qm ${CMAKE_SOURCE_DIR}/src ${CMAKE_SOURCE_DIR}/src/${PROJ_NAME}_en.ts) SET(Boost_USE_STATIC_LIBS ON) SET(Boost_USE_MULTITHREADED ON) @@ -35,7 +37,7 @@ LINK_DIRECTORIES(${project_path}/uibase/build/src ${lib_path}) -ADD_LIBRARY(${PROJ_NAME} SHARED ${${PROJ_NAME}_HDRS} ${${PROJ_NAME}_SRCS} ${${PROJ_NAME}_UIHDRS}) +ADD_LIBRARY(${PROJ_NAME} SHARED ${${PROJ_NAME}_HDRS} ${${PROJ_NAME}_SRCS} ${${PROJ_NAME}_UIHDRS} ${${PROJ_NAME}_translations_qm}) TARGET_LINK_LIBRARIES(${PROJ_NAME} Qt5::Widgets ${Boost_LIBRARIES} diff --git a/src/games/falloutnv/src/game_falloutNV_en.ts b/src/games/falloutnv/src/game_falloutNV_en.ts new file mode 100644 index 00000000..32211e31 --- /dev/null +++ b/src/games/falloutnv/src/game_falloutNV_en.ts @@ -0,0 +1,12 @@ + + + + + GameFalloutNV + + + Adds support for the game Fallout New Vegas + + + + From 969240e7ee1424fce154ebda4a1c4db359539865 Mon Sep 17 00:00:00 2001 From: Tannin Date: Sat, 4 Jun 2016 20:33:46 +0200 Subject: [PATCH 0249/1544] [game_oblivion] translation --- src/games/oblivion/src/CMakeLists.txt | 4 +++- src/games/oblivion/src/game_oblivion_en.ts | 12 ++++++++++++ 2 files changed, 15 insertions(+), 1 deletion(-) create mode 100644 src/games/oblivion/src/game_oblivion_en.ts diff --git a/src/games/oblivion/src/CMakeLists.txt b/src/games/oblivion/src/CMakeLists.txt index 4b29021f..79288345 100644 --- a/src/games/oblivion/src/CMakeLists.txt +++ b/src/games/oblivion/src/CMakeLists.txt @@ -12,6 +12,8 @@ SET(CMAKE_AUTOMOC ON) SET(CMAKE_AUTOUIC ON) FIND_PACKAGE(Qt5Widgets REQUIRED) QT5_WRAP_UI(${PROJ_NAME}_UIHDRS ${${PROJ_NAME}_FORMS}) +FIND_PACKAGE(Qt5LinguistTools) +QT5_CREATE_TRANSLATION(${PROJ_NAME}_translations_qm ${CMAKE_SOURCE_DIR}/src ${CMAKE_SOURCE_DIR}/src/${PROJ_NAME}_en.ts) SET(Boost_USE_STATIC_LIBS ON) SET(Boost_USE_MULTITHREADED ON) @@ -35,7 +37,7 @@ LINK_DIRECTORIES(${project_path}/uibase/build/src ${lib_path}) -ADD_LIBRARY(${PROJ_NAME} SHARED ${${PROJ_NAME}_HDRS} ${${PROJ_NAME}_SRCS} ${${PROJ_NAME}_UIHDRS}) +ADD_LIBRARY(${PROJ_NAME} SHARED ${${PROJ_NAME}_HDRS} ${${PROJ_NAME}_SRCS} ${${PROJ_NAME}_UIHDRS} ${${PROJ_NAME}_translations_qm}) TARGET_LINK_LIBRARIES(${PROJ_NAME} Qt5::Widgets ${Boost_LIBRARIES} diff --git a/src/games/oblivion/src/game_oblivion_en.ts b/src/games/oblivion/src/game_oblivion_en.ts new file mode 100644 index 00000000..e0978554 --- /dev/null +++ b/src/games/oblivion/src/game_oblivion_en.ts @@ -0,0 +1,12 @@ + + + + + GameOblivion + + + Adds support for the game Oblivion + + + + From 5d9ac8559052cf44c9accc3ae68a7d154d805ca3 Mon Sep 17 00:00:00 2001 From: Tannin Date: Sat, 4 Jun 2016 20:34:30 +0200 Subject: [PATCH 0250/1544] [game_skyrim] translation --- src/games/skyrim/src/CMakeLists.txt | 4 +++- src/games/skyrim/src/game_skyrim_en.ts | 12 ++++++++++++ 2 files changed, 15 insertions(+), 1 deletion(-) create mode 100644 src/games/skyrim/src/game_skyrim_en.ts diff --git a/src/games/skyrim/src/CMakeLists.txt b/src/games/skyrim/src/CMakeLists.txt index 9d1b6a1b..60bf0b9e 100644 --- a/src/games/skyrim/src/CMakeLists.txt +++ b/src/games/skyrim/src/CMakeLists.txt @@ -12,6 +12,8 @@ SET(CMAKE_AUTOMOC ON) SET(CMAKE_AUTOUIC ON) FIND_PACKAGE(Qt5Widgets REQUIRED) QT5_WRAP_UI(${PROJ_NAME}_UIHDRS ${${PROJ_NAME}_FORMS}) +FIND_PACKAGE(Qt5LinguistTools) +QT5_CREATE_TRANSLATION(${PROJ_NAME}_translations_qm ${CMAKE_SOURCE_DIR}/src ${CMAKE_SOURCE_DIR}/src/${PROJ_NAME}_en.ts) SET(Boost_USE_STATIC_LIBS ON) SET(Boost_USE_MULTITHREADED ON) @@ -36,7 +38,7 @@ LINK_DIRECTORIES(${project_path}/uibase/build/src ADD_DEFINITIONS(-DUNICODE -D_UNICODE) -ADD_LIBRARY(${PROJ_NAME} SHARED ${${PROJ_NAME}_HDRS} ${${PROJ_NAME}_SRCS} ${${PROJ_NAME}_UIHDRS}) +ADD_LIBRARY(${PROJ_NAME} SHARED ${${PROJ_NAME}_HDRS} ${${PROJ_NAME}_SRCS} ${${PROJ_NAME}_UIHDRS} ${${PROJ_NAME}_translations_qm}) TARGET_LINK_LIBRARIES(${PROJ_NAME} Qt5::Widgets ${Boost_LIBRARIES} diff --git a/src/games/skyrim/src/game_skyrim_en.ts b/src/games/skyrim/src/game_skyrim_en.ts new file mode 100644 index 00000000..da6d9d08 --- /dev/null +++ b/src/games/skyrim/src/game_skyrim_en.ts @@ -0,0 +1,12 @@ + + + + + GameSkyrim + + + Adds support for the game Skyrim + + + + From 6817e981d104efb16e846ae499046f42af903cbf Mon Sep 17 00:00:00 2001 From: Tannin Date: Sun, 5 Jun 2016 12:23:08 +0200 Subject: [PATCH 0251/1544] [game_fallout4vr] bugfix: plugins were never deactivated on loading a plugin list --- src/games/fallout4vr/src/fallout4gameplugins.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/games/fallout4vr/src/fallout4gameplugins.cpp b/src/games/fallout4vr/src/fallout4gameplugins.cpp index 85bcbe4f..482e127d 100644 --- a/src/games/fallout4vr/src/fallout4gameplugins.cpp +++ b/src/games/fallout4vr/src/fallout4gameplugins.cpp @@ -74,7 +74,7 @@ bool Fallout4GamePlugins::readPluginList(MOBase::IPluginList *pluginList, const QString &filePath, bool useLoadOrder) { - QStringList plugins; + QStringList plugins = pluginList->pluginNames(); for (const QString &pluginName : OFFICIAL_FILES) { if (pluginList->state(pluginName) != IPluginList::STATE_MISSING) { From 5ff92fed4985efb94d0414063253fb50755de2b5 Mon Sep 17 00:00:00 2001 From: Tannin Date: Sun, 5 Jun 2016 12:23:08 +0200 Subject: [PATCH 0252/1544] [game_fallout76] bugfix: plugins were never deactivated on loading a plugin list --- src/games/fallout76/src/fallout4gameplugins.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/games/fallout76/src/fallout4gameplugins.cpp b/src/games/fallout76/src/fallout4gameplugins.cpp index 85bcbe4f..482e127d 100644 --- a/src/games/fallout76/src/fallout4gameplugins.cpp +++ b/src/games/fallout76/src/fallout4gameplugins.cpp @@ -74,7 +74,7 @@ bool Fallout4GamePlugins::readPluginList(MOBase::IPluginList *pluginList, const QString &filePath, bool useLoadOrder) { - QStringList plugins; + QStringList plugins = pluginList->pluginNames(); for (const QString &pluginName : OFFICIAL_FILES) { if (pluginList->state(pluginName) != IPluginList::STATE_MISSING) { From 48f25204a0e9fa674031b1217fea23b6a03afd96 Mon Sep 17 00:00:00 2001 From: Tannin Date: Sun, 5 Jun 2016 12:23:08 +0200 Subject: [PATCH 0253/1544] [game_fallout4] bugfix: plugins were never deactivated on loading a plugin list --- src/games/fallout4/src/fallout4gameplugins.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/games/fallout4/src/fallout4gameplugins.cpp b/src/games/fallout4/src/fallout4gameplugins.cpp index 85bcbe4f..482e127d 100644 --- a/src/games/fallout4/src/fallout4gameplugins.cpp +++ b/src/games/fallout4/src/fallout4gameplugins.cpp @@ -74,7 +74,7 @@ bool Fallout4GamePlugins::readPluginList(MOBase::IPluginList *pluginList, const QString &filePath, bool useLoadOrder) { - QStringList plugins; + QStringList plugins = pluginList->pluginNames(); for (const QString &pluginName : OFFICIAL_FILES) { if (pluginList->state(pluginName) != IPluginList::STATE_MISSING) { From 1f12cc8ab94a052e0fb5b83ec9c14723a4ce4621 Mon Sep 17 00:00:00 2001 From: Tannin Date: Sun, 19 Jun 2016 15:51:57 +0200 Subject: [PATCH 0254/1544] added unmanaged-mods feature and reorganized the featurelist code a bit --- src/gamebryobsainvalidation.cpp | 2 +- src/gamebryobsainvalidation.h | 4 +-- src/gamebryounmanagedmods.cpp | 54 +++++++++++++++++++++++++++++++++ src/gamebryounmanagedmods.h | 27 +++++++++++++++++ src/gamegamebryo.cpp | 28 ++++++----------- src/gamegamebryo.h | 10 ++++++ 6 files changed, 104 insertions(+), 21 deletions(-) create mode 100644 src/gamebryounmanagedmods.cpp create mode 100644 src/gamebryounmanagedmods.h diff --git a/src/gamebryobsainvalidation.cpp b/src/gamebryobsainvalidation.cpp index dfc9484f..aa4bfa06 100644 --- a/src/gamebryobsainvalidation.cpp +++ b/src/gamebryobsainvalidation.cpp @@ -13,7 +13,7 @@ #include -GamebryoBSAInvalidation::GamebryoBSAInvalidation(const std::shared_ptr &dataArchives +GamebryoBSAInvalidation::GamebryoBSAInvalidation(DataArchives *dataArchives , const QString &iniFilename , MOBase::IPluginGame const *game) : m_DataArchives(dataArchives) diff --git a/src/gamebryobsainvalidation.h b/src/gamebryobsainvalidation.h index 99a988d7..45bfaf8b 100644 --- a/src/gamebryobsainvalidation.h +++ b/src/gamebryobsainvalidation.h @@ -15,7 +15,7 @@ class GamebryoBSAInvalidation : public BSAInvalidation { public: - GamebryoBSAInvalidation(const std::shared_ptr &dataArchives, + GamebryoBSAInvalidation(DataArchives *dataArchives, const QString &iniFilename, MOBase::IPluginGame const *game); @@ -30,7 +30,7 @@ private: private: - std::shared_ptr m_DataArchives; + DataArchives *m_DataArchives; QString m_IniFileName; MOBase::IPluginGame const *m_Game; diff --git a/src/gamebryounmanagedmods.cpp b/src/gamebryounmanagedmods.cpp new file mode 100644 index 00000000..7ad3c3cf --- /dev/null +++ b/src/gamebryounmanagedmods.cpp @@ -0,0 +1,54 @@ +#include "gamebryounmanagedmods.h" +#include "gamegamebryo.h" +#include + + +GamebryoUnmangedMods::GamebryoUnmangedMods(const GameGamebryo *game) + : m_Game(game) +{} + +GamebryoUnmangedMods::~GamebryoUnmangedMods() +{} + +QStringList GamebryoUnmangedMods::mods(bool onlyOfficial) const { + QStringList result; + + QStringList dlcPlugins = m_Game->DLCPlugins(); + QStringList mainPlugins = m_Game->primaryPlugins(); + + QDir dataDir(m_Game->dataDirectory()); + for (const QString &fileName : dataDir.entryList({"*.esp", "*.esm"})) { + if (!mainPlugins.contains(fileName, Qt::CaseInsensitive) && + (!onlyOfficial || dlcPlugins.contains(fileName, Qt::CaseInsensitive))) { + QFileInfo file(fileName); + result.append(file.baseName()); + } + } + + return result; +} + +QString GamebryoUnmangedMods::displayName(const QString &modName) const { + return modName; +} + +QFileInfo GamebryoUnmangedMods::referenceFile(const QString &modName) const { + QFileInfoList files = + m_Game->dataDirectory().entryInfoList(QStringList() << modName + ".es*"); + if (files.size() > 0) { + return files.at(0); + } else { + return QFileInfo(); + } +} + +QStringList GamebryoUnmangedMods::secondaryFiles(const QString &modName) const { + QStringList archives; + QDir dataDir = m_Game->dataDirectory(); + for (const QString &archiveName : + dataDir.entryList({modName + "*.bsa"})) { + archives.append(dataDir.absoluteFilePath(archiveName)); + } + return archives; +} + diff --git a/src/gamebryounmanagedmods.h b/src/gamebryounmanagedmods.h new file mode 100644 index 00000000..86a7334a --- /dev/null +++ b/src/gamebryounmanagedmods.h @@ -0,0 +1,27 @@ +#ifndef GAMEBRYOUNMANAGEDMODS_H +#define GAMEBRYOUNMANAGEDMODS_H + + +#include + +class GameGamebryo; + +class GamebryoUnmangedMods : public UnmanagedMods { +public: + GamebryoUnmangedMods(const GameGamebryo *game); + ~GamebryoUnmangedMods(); + + virtual QStringList mods(bool onlyOfficial) const override; + virtual QString displayName(const QString &modName) const override; + virtual QFileInfo referenceFile(const QString &modName) const override; + virtual QStringList secondaryFiles(const QString &modName) const override; +protected: + const GameGamebryo *game() const { return m_Game; } +private: + const GameGamebryo *m_Game; + +}; + + + +#endif // GAMEBRYOUNMANAGEDMODS_H diff --git a/src/gamegamebryo.cpp b/src/gamegamebryo.cpp index 026f0b4e..1102201f 100644 --- a/src/gamegamebryo.cpp +++ b/src/gamegamebryo.cpp @@ -252,14 +252,7 @@ QString GameGamebryo::myGamesPath() const std::map GameGamebryo::featureList() const { - return { - { typeid(BSAInvalidation), m_BSAInvalidation.get() }, - { typeid(ScriptExtender), m_ScriptExtender.get() }, - { typeid(DataArchives), m_DataArchives.get() }, - { typeid(SaveGameInfo), m_SaveGameInfo.get() }, - { typeid(LocalSavegames), m_LocalSavegames.get() }, - { typeid(GamePlugins), m_GamePlugins.get() } - }; + return m_FeatureList; } QString GameGamebryo::localAppFolder() @@ -272,18 +265,17 @@ QString GameGamebryo::localAppFolder() return result; } -/*static*/void GameGamebryo::copyToProfile(QString const &sourcePath, - QDir const &destinationDirectory, - QString const &sourceFileName) -{ - copyToProfile(sourcePath, destinationDirectory, sourceFileName, sourceFileName); +void GameGamebryo::copyToProfile(QString const &sourcePath, + QDir const &destinationDirectory, + QString const &sourceFileName) { + copyToProfile(sourcePath, destinationDirectory, sourceFileName, + sourceFileName); } -/*static*/void GameGamebryo::copyToProfile(QString const &sourcePath, - QDir const &destinationDirectory, - QString const &sourceFileName, - QString const &destinationFileName) -{ +void GameGamebryo::copyToProfile(QString const &sourcePath, + QDir const &destinationDirectory, + QString const &sourceFileName, + QString const &destinationFileName) { QString filePath = destinationDirectory.absoluteFilePath(destinationFileName); if (!QFileInfo(filePath).exists()) { if (!MOBase::shellCopy(sourcePath + "/" + sourceFileName, filePath)) { diff --git a/src/gamegamebryo.h b/src/gamegamebryo.h index a502896a..76bc398f 100644 --- a/src/gamegamebryo.h +++ b/src/gamegamebryo.h @@ -11,6 +11,7 @@ class BSAInvalidation; class LocalSavegames; class ScriptExtender; class GamePlugins; +class UnmanagedMods; #include #include @@ -99,12 +100,19 @@ protected: //These should be implemented by anything that uses gamebryo (I think) //(and if they don't, it'll be a null pointer and won't look implemented, //so that's fine too). + /* std::shared_ptr m_ScriptExtender { nullptr }; std::shared_ptr m_DataArchives { nullptr }; std::shared_ptr m_BSAInvalidation { nullptr }; std::shared_ptr m_SaveGameInfo { nullptr }; std::shared_ptr m_LocalSavegames { nullptr }; std::shared_ptr m_GamePlugins { nullptr }; + std::shared_ptr m_UnmanagedMods { nullptr };*/ + + template + void registerFeature(T *type) { + m_FeatureList[std::type_index(typeid(T))] = type; + } private: @@ -119,6 +127,8 @@ private: MOBase::IOrganizer *m_Organizer; + std::map m_FeatureList; + }; #endif // GAMEGAMEBRYO_H From e90ee26cb4238b9dac0b41797720fece0f064da1 Mon Sep 17 00:00:00 2001 From: Tannin Date: Sun, 19 Jun 2016 15:52:43 +0200 Subject: [PATCH 0255/1544] [game_fallout4vr] added fo4 implementation of unmanaged mods --- .../fallout4vr/src/fallout4unmanagedmods.cpp | 34 +++++++++++++++++++ .../fallout4vr/src/fallout4unmanagedmods.h | 20 +++++++++++ src/games/fallout4vr/src/game_fallout4_en.ts | 2 +- src/games/fallout4vr/src/gamefallout4.cpp | 18 +++++----- 4 files changed, 65 insertions(+), 9 deletions(-) create mode 100644 src/games/fallout4vr/src/fallout4unmanagedmods.cpp create mode 100644 src/games/fallout4vr/src/fallout4unmanagedmods.h diff --git a/src/games/fallout4vr/src/fallout4unmanagedmods.cpp b/src/games/fallout4vr/src/fallout4unmanagedmods.cpp new file mode 100644 index 00000000..066da881 --- /dev/null +++ b/src/games/fallout4vr/src/fallout4unmanagedmods.cpp @@ -0,0 +1,34 @@ +#include "fallout4unmanagedmods.h" + + +Fallout4UnmangedMods::Fallout4UnmangedMods(const GameGamebryo *game) + : GamebryoUnmangedMods(game) +{} + +Fallout4UnmangedMods::~Fallout4UnmangedMods() +{} + +QStringList Fallout4UnmangedMods::secondaryFiles(const QString &modName) const { + // file extension in FO4 is .ba2 instead of bsa + QStringList archives; + QDir dataDir = game()->dataDirectory(); + for (const QString &archiveName : dataDir.entryList({modName + "*.ba2"})) { + archives.append(dataDir.absoluteFilePath(archiveName)); + } + return archives; +} + +QString Fallout4UnmangedMods::displayName(const QString &modName) const +{ + // unlike in earlier games, in fallout 4 the file name doesn't correspond to + // the public name + if (modName.compare("dlcrobot", Qt::CaseInsensitive) == 0) { + return "Automatron"; + } else if (modName.compare("dlcworkshop01", Qt::CaseInsensitive) == 0) { + return "Wasteland Workshop"; + } else if (modName.compare("dlccoast", Qt::CaseInsensitive) == 0) { + return "Far Harbor"; + } else { + return modName; + } +} diff --git a/src/games/fallout4vr/src/fallout4unmanagedmods.h b/src/games/fallout4vr/src/fallout4unmanagedmods.h new file mode 100644 index 00000000..92149c73 --- /dev/null +++ b/src/games/fallout4vr/src/fallout4unmanagedmods.h @@ -0,0 +1,20 @@ +#ifndef FALLOUT4UNMANAGEDMODS_H +#define FALLOUT4UNMANAGEDMODS_H + + +#include "gamebryounmanagedmods.h" +#include + + +class Fallout4UnmangedMods : public GamebryoUnmangedMods { +public: + Fallout4UnmangedMods(const GameGamebryo *game); + ~Fallout4UnmangedMods(); + + virtual QStringList secondaryFiles(const QString &modName) const override; + virtual QString displayName(const QString &modName) const override; +}; + + + +#endif // FALLOUT4UNMANAGEDMODS_H diff --git a/src/games/fallout4vr/src/game_fallout4_en.ts b/src/games/fallout4vr/src/game_fallout4_en.ts index d7b7d990..4de40ceb 100644 --- a/src/games/fallout4vr/src/game_fallout4_en.ts +++ b/src/games/fallout4vr/src/game_fallout4_en.ts @@ -4,7 +4,7 @@ GameFallout4 - + Adds support for the game Fallout 4. Splash by %1 diff --git a/src/games/fallout4vr/src/gamefallout4.cpp b/src/games/fallout4vr/src/gamefallout4.cpp index 42ba097d..a21261fe 100644 --- a/src/games/fallout4vr/src/gamefallout4.cpp +++ b/src/games/fallout4vr/src/gamefallout4.cpp @@ -4,6 +4,7 @@ #include "fallout4scriptextender.h" #include "fallout4savegameinfo.h" #include "fallout4gameplugins.h" +#include "fallout4unmanagedmods.h" #include #include "iplugingame.h" @@ -34,11 +35,12 @@ bool GameFallout4::init(IOrganizer *moInfo) return false; } - m_ScriptExtender = std::shared_ptr(new Fallout4ScriptExtender(this)); - m_DataArchives = std::shared_ptr(new Fallout4DataArchives()); - m_LocalSavegames.reset(new GamebryoLocalSavegames(myGamesPath(), "Fallout4.ini")); - m_SaveGameInfo = std::shared_ptr(new Fallout4SaveGameInfo(this)); - m_GamePlugins = std::shared_ptr(new Fallout4GamePlugins(moInfo)); + registerFeature(new Fallout4ScriptExtender(this)); + registerFeature(new Fallout4DataArchives()); + registerFeature(new GamebryoLocalSavegames(myGamesPath(), "Fallout4.ini")); + registerFeature(new Fallout4SaveGameInfo(this)); + registerFeature(new Fallout4GamePlugins(moInfo)); + registerFeature(new Fallout4UnmangedMods(this)); return true; } @@ -51,7 +53,7 @@ QString GameFallout4::gameName() const QList GameFallout4::executables() const { return QList() - << ExecutableInfo("F4SE", findInGameFolder(m_ScriptExtender->loaderName())) + << ExecutableInfo("F4SE", findInGameFolder(feature()->loaderName())) << ExecutableInfo("Fallout 4", findInGameFolder(binaryName())) << ExecutableInfo("Fallout Launcher", findInGameFolder(getLauncherName())) << ExecutableInfo("Creation Kit", findInGameFolder("CreationKit.exe")) @@ -120,7 +122,7 @@ QString GameFallout4::steamAPPId() const } QStringList GameFallout4::primaryPlugins() const { - return {"fallout4.esm", "dlcrobot.esm", "dlcworkshop01.esm", "dlccoast.esm"}; + return {"fallout4.esm"}; } QStringList GameFallout4::gameVariants() const @@ -140,7 +142,7 @@ QStringList GameFallout4::iniFiles() const QStringList GameFallout4::DLCPlugins() const { - return {}; + return {"dlcrobot.esm", "dlcworkshop01.esm", "dlccoast.esm"}; } IPluginGame::LoadOrderMechanism GameFallout4::loadOrderMechanism() const From 79a6870ffd8814bfda942b3c14c8e964fe54b584 Mon Sep 17 00:00:00 2001 From: Tannin Date: Sun, 19 Jun 2016 15:52:43 +0200 Subject: [PATCH 0256/1544] [game_fallout76] added fo4 implementation of unmanaged mods --- .../fallout76/src/fallout4unmanagedmods.cpp | 34 +++++++++++++++++++ .../fallout76/src/fallout4unmanagedmods.h | 20 +++++++++++ src/games/fallout76/src/game_fallout4_en.ts | 2 +- src/games/fallout76/src/gamefallout4.cpp | 18 +++++----- 4 files changed, 65 insertions(+), 9 deletions(-) create mode 100644 src/games/fallout76/src/fallout4unmanagedmods.cpp create mode 100644 src/games/fallout76/src/fallout4unmanagedmods.h diff --git a/src/games/fallout76/src/fallout4unmanagedmods.cpp b/src/games/fallout76/src/fallout4unmanagedmods.cpp new file mode 100644 index 00000000..066da881 --- /dev/null +++ b/src/games/fallout76/src/fallout4unmanagedmods.cpp @@ -0,0 +1,34 @@ +#include "fallout4unmanagedmods.h" + + +Fallout4UnmangedMods::Fallout4UnmangedMods(const GameGamebryo *game) + : GamebryoUnmangedMods(game) +{} + +Fallout4UnmangedMods::~Fallout4UnmangedMods() +{} + +QStringList Fallout4UnmangedMods::secondaryFiles(const QString &modName) const { + // file extension in FO4 is .ba2 instead of bsa + QStringList archives; + QDir dataDir = game()->dataDirectory(); + for (const QString &archiveName : dataDir.entryList({modName + "*.ba2"})) { + archives.append(dataDir.absoluteFilePath(archiveName)); + } + return archives; +} + +QString Fallout4UnmangedMods::displayName(const QString &modName) const +{ + // unlike in earlier games, in fallout 4 the file name doesn't correspond to + // the public name + if (modName.compare("dlcrobot", Qt::CaseInsensitive) == 0) { + return "Automatron"; + } else if (modName.compare("dlcworkshop01", Qt::CaseInsensitive) == 0) { + return "Wasteland Workshop"; + } else if (modName.compare("dlccoast", Qt::CaseInsensitive) == 0) { + return "Far Harbor"; + } else { + return modName; + } +} diff --git a/src/games/fallout76/src/fallout4unmanagedmods.h b/src/games/fallout76/src/fallout4unmanagedmods.h new file mode 100644 index 00000000..92149c73 --- /dev/null +++ b/src/games/fallout76/src/fallout4unmanagedmods.h @@ -0,0 +1,20 @@ +#ifndef FALLOUT4UNMANAGEDMODS_H +#define FALLOUT4UNMANAGEDMODS_H + + +#include "gamebryounmanagedmods.h" +#include + + +class Fallout4UnmangedMods : public GamebryoUnmangedMods { +public: + Fallout4UnmangedMods(const GameGamebryo *game); + ~Fallout4UnmangedMods(); + + virtual QStringList secondaryFiles(const QString &modName) const override; + virtual QString displayName(const QString &modName) const override; +}; + + + +#endif // FALLOUT4UNMANAGEDMODS_H diff --git a/src/games/fallout76/src/game_fallout4_en.ts b/src/games/fallout76/src/game_fallout4_en.ts index d7b7d990..4de40ceb 100644 --- a/src/games/fallout76/src/game_fallout4_en.ts +++ b/src/games/fallout76/src/game_fallout4_en.ts @@ -4,7 +4,7 @@ GameFallout4 - + Adds support for the game Fallout 4. Splash by %1 diff --git a/src/games/fallout76/src/gamefallout4.cpp b/src/games/fallout76/src/gamefallout4.cpp index 42ba097d..a21261fe 100644 --- a/src/games/fallout76/src/gamefallout4.cpp +++ b/src/games/fallout76/src/gamefallout4.cpp @@ -4,6 +4,7 @@ #include "fallout4scriptextender.h" #include "fallout4savegameinfo.h" #include "fallout4gameplugins.h" +#include "fallout4unmanagedmods.h" #include #include "iplugingame.h" @@ -34,11 +35,12 @@ bool GameFallout4::init(IOrganizer *moInfo) return false; } - m_ScriptExtender = std::shared_ptr(new Fallout4ScriptExtender(this)); - m_DataArchives = std::shared_ptr(new Fallout4DataArchives()); - m_LocalSavegames.reset(new GamebryoLocalSavegames(myGamesPath(), "Fallout4.ini")); - m_SaveGameInfo = std::shared_ptr(new Fallout4SaveGameInfo(this)); - m_GamePlugins = std::shared_ptr(new Fallout4GamePlugins(moInfo)); + registerFeature(new Fallout4ScriptExtender(this)); + registerFeature(new Fallout4DataArchives()); + registerFeature(new GamebryoLocalSavegames(myGamesPath(), "Fallout4.ini")); + registerFeature(new Fallout4SaveGameInfo(this)); + registerFeature(new Fallout4GamePlugins(moInfo)); + registerFeature(new Fallout4UnmangedMods(this)); return true; } @@ -51,7 +53,7 @@ QString GameFallout4::gameName() const QList GameFallout4::executables() const { return QList() - << ExecutableInfo("F4SE", findInGameFolder(m_ScriptExtender->loaderName())) + << ExecutableInfo("F4SE", findInGameFolder(feature()->loaderName())) << ExecutableInfo("Fallout 4", findInGameFolder(binaryName())) << ExecutableInfo("Fallout Launcher", findInGameFolder(getLauncherName())) << ExecutableInfo("Creation Kit", findInGameFolder("CreationKit.exe")) @@ -120,7 +122,7 @@ QString GameFallout4::steamAPPId() const } QStringList GameFallout4::primaryPlugins() const { - return {"fallout4.esm", "dlcrobot.esm", "dlcworkshop01.esm", "dlccoast.esm"}; + return {"fallout4.esm"}; } QStringList GameFallout4::gameVariants() const @@ -140,7 +142,7 @@ QStringList GameFallout4::iniFiles() const QStringList GameFallout4::DLCPlugins() const { - return {}; + return {"dlcrobot.esm", "dlcworkshop01.esm", "dlccoast.esm"}; } IPluginGame::LoadOrderMechanism GameFallout4::loadOrderMechanism() const From 457dca723b6a9669e766483a5fe8b393585e89c7 Mon Sep 17 00:00:00 2001 From: Tannin Date: Sun, 19 Jun 2016 15:52:43 +0200 Subject: [PATCH 0257/1544] [game_fallout4] added fo4 implementation of unmanaged mods --- .../fallout4/src/fallout4unmanagedmods.cpp | 34 +++++++++++++++++++ .../fallout4/src/fallout4unmanagedmods.h | 20 +++++++++++ src/games/fallout4/src/game_fallout4_en.ts | 2 +- src/games/fallout4/src/gamefallout4.cpp | 18 +++++----- 4 files changed, 65 insertions(+), 9 deletions(-) create mode 100644 src/games/fallout4/src/fallout4unmanagedmods.cpp create mode 100644 src/games/fallout4/src/fallout4unmanagedmods.h diff --git a/src/games/fallout4/src/fallout4unmanagedmods.cpp b/src/games/fallout4/src/fallout4unmanagedmods.cpp new file mode 100644 index 00000000..066da881 --- /dev/null +++ b/src/games/fallout4/src/fallout4unmanagedmods.cpp @@ -0,0 +1,34 @@ +#include "fallout4unmanagedmods.h" + + +Fallout4UnmangedMods::Fallout4UnmangedMods(const GameGamebryo *game) + : GamebryoUnmangedMods(game) +{} + +Fallout4UnmangedMods::~Fallout4UnmangedMods() +{} + +QStringList Fallout4UnmangedMods::secondaryFiles(const QString &modName) const { + // file extension in FO4 is .ba2 instead of bsa + QStringList archives; + QDir dataDir = game()->dataDirectory(); + for (const QString &archiveName : dataDir.entryList({modName + "*.ba2"})) { + archives.append(dataDir.absoluteFilePath(archiveName)); + } + return archives; +} + +QString Fallout4UnmangedMods::displayName(const QString &modName) const +{ + // unlike in earlier games, in fallout 4 the file name doesn't correspond to + // the public name + if (modName.compare("dlcrobot", Qt::CaseInsensitive) == 0) { + return "Automatron"; + } else if (modName.compare("dlcworkshop01", Qt::CaseInsensitive) == 0) { + return "Wasteland Workshop"; + } else if (modName.compare("dlccoast", Qt::CaseInsensitive) == 0) { + return "Far Harbor"; + } else { + return modName; + } +} diff --git a/src/games/fallout4/src/fallout4unmanagedmods.h b/src/games/fallout4/src/fallout4unmanagedmods.h new file mode 100644 index 00000000..92149c73 --- /dev/null +++ b/src/games/fallout4/src/fallout4unmanagedmods.h @@ -0,0 +1,20 @@ +#ifndef FALLOUT4UNMANAGEDMODS_H +#define FALLOUT4UNMANAGEDMODS_H + + +#include "gamebryounmanagedmods.h" +#include + + +class Fallout4UnmangedMods : public GamebryoUnmangedMods { +public: + Fallout4UnmangedMods(const GameGamebryo *game); + ~Fallout4UnmangedMods(); + + virtual QStringList secondaryFiles(const QString &modName) const override; + virtual QString displayName(const QString &modName) const override; +}; + + + +#endif // FALLOUT4UNMANAGEDMODS_H diff --git a/src/games/fallout4/src/game_fallout4_en.ts b/src/games/fallout4/src/game_fallout4_en.ts index d7b7d990..4de40ceb 100644 --- a/src/games/fallout4/src/game_fallout4_en.ts +++ b/src/games/fallout4/src/game_fallout4_en.ts @@ -4,7 +4,7 @@ GameFallout4 - + Adds support for the game Fallout 4. Splash by %1 diff --git a/src/games/fallout4/src/gamefallout4.cpp b/src/games/fallout4/src/gamefallout4.cpp index 42ba097d..a21261fe 100644 --- a/src/games/fallout4/src/gamefallout4.cpp +++ b/src/games/fallout4/src/gamefallout4.cpp @@ -4,6 +4,7 @@ #include "fallout4scriptextender.h" #include "fallout4savegameinfo.h" #include "fallout4gameplugins.h" +#include "fallout4unmanagedmods.h" #include #include "iplugingame.h" @@ -34,11 +35,12 @@ bool GameFallout4::init(IOrganizer *moInfo) return false; } - m_ScriptExtender = std::shared_ptr(new Fallout4ScriptExtender(this)); - m_DataArchives = std::shared_ptr(new Fallout4DataArchives()); - m_LocalSavegames.reset(new GamebryoLocalSavegames(myGamesPath(), "Fallout4.ini")); - m_SaveGameInfo = std::shared_ptr(new Fallout4SaveGameInfo(this)); - m_GamePlugins = std::shared_ptr(new Fallout4GamePlugins(moInfo)); + registerFeature(new Fallout4ScriptExtender(this)); + registerFeature(new Fallout4DataArchives()); + registerFeature(new GamebryoLocalSavegames(myGamesPath(), "Fallout4.ini")); + registerFeature(new Fallout4SaveGameInfo(this)); + registerFeature(new Fallout4GamePlugins(moInfo)); + registerFeature(new Fallout4UnmangedMods(this)); return true; } @@ -51,7 +53,7 @@ QString GameFallout4::gameName() const QList GameFallout4::executables() const { return QList() - << ExecutableInfo("F4SE", findInGameFolder(m_ScriptExtender->loaderName())) + << ExecutableInfo("F4SE", findInGameFolder(feature()->loaderName())) << ExecutableInfo("Fallout 4", findInGameFolder(binaryName())) << ExecutableInfo("Fallout Launcher", findInGameFolder(getLauncherName())) << ExecutableInfo("Creation Kit", findInGameFolder("CreationKit.exe")) @@ -120,7 +122,7 @@ QString GameFallout4::steamAPPId() const } QStringList GameFallout4::primaryPlugins() const { - return {"fallout4.esm", "dlcrobot.esm", "dlcworkshop01.esm", "dlccoast.esm"}; + return {"fallout4.esm"}; } QStringList GameFallout4::gameVariants() const @@ -140,7 +142,7 @@ QStringList GameFallout4::iniFiles() const QStringList GameFallout4::DLCPlugins() const { - return {}; + return {"dlcrobot.esm", "dlcworkshop01.esm", "dlccoast.esm"}; } IPluginGame::LoadOrderMechanism GameFallout4::loadOrderMechanism() const From d4e83df72cedc577131b89c87e4a0a5c88925f7f Mon Sep 17 00:00:00 2001 From: Tannin Date: Sun, 19 Jun 2016 15:53:09 +0200 Subject: [PATCH 0258/1544] [game_fallout3] updated to changed interface --- .../fallout3/src/fallout3bsainvalidation.cpp | 2 +- src/games/fallout3/src/fallout3bsainvalidation.h | 2 +- src/games/fallout3/src/game_fallout3_en.ts | 2 +- src/games/fallout3/src/gamefallout3.cpp | 16 +++++++++------- 4 files changed, 12 insertions(+), 10 deletions(-) diff --git a/src/games/fallout3/src/fallout3bsainvalidation.cpp b/src/games/fallout3/src/fallout3bsainvalidation.cpp index 9fde6f05..a55dec33 100644 --- a/src/games/fallout3/src/fallout3bsainvalidation.cpp +++ b/src/games/fallout3/src/fallout3bsainvalidation.cpp @@ -1,6 +1,6 @@ #include "fallout3bsainvalidation.h" -Fallout3BSAInvalidation::Fallout3BSAInvalidation(const std::shared_ptr &dataArchives, MOBase::IPluginGame const *game) +Fallout3BSAInvalidation::Fallout3BSAInvalidation(DataArchives *dataArchives, MOBase::IPluginGame const *game) : GamebryoBSAInvalidation(dataArchives, "fallout.ini", game) { } diff --git a/src/games/fallout3/src/fallout3bsainvalidation.h b/src/games/fallout3/src/fallout3bsainvalidation.h index 2ae7a212..16f0c656 100644 --- a/src/games/fallout3/src/fallout3bsainvalidation.h +++ b/src/games/fallout3/src/fallout3bsainvalidation.h @@ -11,7 +11,7 @@ class Fallout3BSAInvalidation : public GamebryoBSAInvalidation { public: - Fallout3BSAInvalidation(const std::shared_ptr &dataArchives, MOBase::IPluginGame const *game); + Fallout3BSAInvalidation(DataArchives *dataArchives, MOBase::IPluginGame const *game); private: diff --git a/src/games/fallout3/src/game_fallout3_en.ts b/src/games/fallout3/src/game_fallout3_en.ts index 7e6aab8e..db164c9f 100644 --- a/src/games/fallout3/src/game_fallout3_en.ts +++ b/src/games/fallout3/src/game_fallout3_en.ts @@ -4,7 +4,7 @@ GameFallout3 - + Adds support for the game Fallout 3s diff --git a/src/games/fallout3/src/gamefallout3.cpp b/src/games/fallout3/src/gamefallout3.cpp index b120667c..cdf9bd3f 100644 --- a/src/games/fallout3/src/gamefallout3.cpp +++ b/src/games/fallout3/src/gamefallout3.cpp @@ -10,6 +10,7 @@ #include "versioninfo.h" #include #include +#include #include #include @@ -32,12 +33,13 @@ bool GameFallout3::init(IOrganizer *moInfo) if (!GameGamebryo::init(moInfo)) { return false; } - m_ScriptExtender = std::shared_ptr(new Fallout3ScriptExtender(this)); - m_DataArchives = std::shared_ptr(new Fallout3DataArchives()); - m_BSAInvalidation = std::shared_ptr(new Fallout3BSAInvalidation(m_DataArchives, this)); - m_SaveGameInfo = std::shared_ptr(new Fallout3SaveGameInfo(this)); - m_LocalSavegames.reset(new GamebryoLocalSavegames(myGamesPath(), "fallout.ini")); - m_GamePlugins = std::shared_ptr(new GamebryoGamePlugins(moInfo)); + registerFeature(new Fallout3ScriptExtender(this)); + registerFeature(new Fallout3DataArchives()); + registerFeature(new Fallout3BSAInvalidation(feature(), this)); + registerFeature(new Fallout3SaveGameInfo(this)); + registerFeature(new GamebryoLocalSavegames(myGamesPath(), "fallout.ini")); + registerFeature(new GamebryoGamePlugins(moInfo)); + registerFeature(new GamebryoUnmangedMods(this)); return true; } @@ -49,7 +51,7 @@ QString GameFallout3::gameName() const QList GameFallout3::executables() const { return QList() - << ExecutableInfo("FOSE", findInGameFolder(m_ScriptExtender->loaderName())) + << ExecutableInfo("FOSE", findInGameFolder(feature()->loaderName())) << ExecutableInfo("Fallout 3", findInGameFolder(binaryName())) << ExecutableInfo("Fallout Mod Manager", findInGameFolder("fomm/fomm.exe")) << ExecutableInfo("Construction Kit", findInGameFolder("geck.exe")) From 347d532155f3b30a05697bc3c88bd28532fd47b4 Mon Sep 17 00:00:00 2001 From: Tannin Date: Sun, 19 Jun 2016 15:53:34 +0200 Subject: [PATCH 0259/1544] [game_falloutnv] updated to changed interface --- .../falloutnv/src/falloutnvbsainvalidation.cpp | 2 +- .../falloutnv/src/falloutnvbsainvalidation.h | 2 +- src/games/falloutnv/src/game_falloutNV_en.ts | 2 +- src/games/falloutnv/src/gamefalloutnv.cpp | 16 +++++++++------- 4 files changed, 12 insertions(+), 10 deletions(-) diff --git a/src/games/falloutnv/src/falloutnvbsainvalidation.cpp b/src/games/falloutnv/src/falloutnvbsainvalidation.cpp index a742c32c..5066e61f 100644 --- a/src/games/falloutnv/src/falloutnvbsainvalidation.cpp +++ b/src/games/falloutnv/src/falloutnvbsainvalidation.cpp @@ -1,6 +1,6 @@ #include "falloutnvbsainvalidation.h" -FalloutNVBSAInvalidation::FalloutNVBSAInvalidation(const std::shared_ptr &dataArchives, MOBase::IPluginGame const *game) +FalloutNVBSAInvalidation::FalloutNVBSAInvalidation(DataArchives *dataArchives, MOBase::IPluginGame const *game) : GamebryoBSAInvalidation(dataArchives, "fallout.ini", game) { } diff --git a/src/games/falloutnv/src/falloutnvbsainvalidation.h b/src/games/falloutnv/src/falloutnvbsainvalidation.h index 215141b0..3f2dcd5f 100644 --- a/src/games/falloutnv/src/falloutnvbsainvalidation.h +++ b/src/games/falloutnv/src/falloutnvbsainvalidation.h @@ -11,7 +11,7 @@ class FalloutNVBSAInvalidation : public GamebryoBSAInvalidation { public: - FalloutNVBSAInvalidation(const std::shared_ptr &dataArchives, MOBase::IPluginGame const *game); + FalloutNVBSAInvalidation(DataArchives *dataArchives, MOBase::IPluginGame const *game); private: diff --git a/src/games/falloutnv/src/game_falloutNV_en.ts b/src/games/falloutnv/src/game_falloutNV_en.ts index 32211e31..b1111848 100644 --- a/src/games/falloutnv/src/game_falloutNV_en.ts +++ b/src/games/falloutnv/src/game_falloutNV_en.ts @@ -4,7 +4,7 @@ GameFalloutNV - + Adds support for the game Fallout New Vegas diff --git a/src/games/falloutnv/src/gamefalloutnv.cpp b/src/games/falloutnv/src/gamefalloutnv.cpp index 7e229903..658b9490 100644 --- a/src/games/falloutnv/src/gamefalloutnv.cpp +++ b/src/games/falloutnv/src/gamefalloutnv.cpp @@ -10,6 +10,7 @@ #include "versioninfo.h" #include #include +#include #include #include @@ -32,12 +33,13 @@ bool GameFalloutNV::init(IOrganizer *moInfo) if (!GameGamebryo::init(moInfo)) { return false; } - m_ScriptExtender = std::shared_ptr(new FalloutNVScriptExtender(this)); - m_DataArchives = std::shared_ptr(new FalloutNVDataArchives()); - m_BSAInvalidation = std::shared_ptr(new FalloutNVBSAInvalidation(m_DataArchives, this)); - m_SaveGameInfo = std::shared_ptr(new FalloutNVSaveGameInfo(this)); - m_LocalSavegames.reset(new GamebryoLocalSavegames(myGamesPath(), "fallout.ini")); - m_GamePlugins = std::shared_ptr(new GamebryoGamePlugins(moInfo)); + registerFeature(new FalloutNVScriptExtender(this)); + registerFeature(new FalloutNVDataArchives()); + registerFeature(new FalloutNVBSAInvalidation(feature(), this)); + registerFeature(new FalloutNVSaveGameInfo(this)); + registerFeature(new GamebryoLocalSavegames(myGamesPath(), "fallout.ini")); + registerFeature(new GamebryoGamePlugins(moInfo)); + registerFeature(new GamebryoUnmangedMods(this)); return true; } @@ -49,7 +51,7 @@ QString GameFalloutNV::gameName() const QList GameFalloutNV::executables() const { return QList() - << ExecutableInfo("NVSE", findInGameFolder(m_ScriptExtender->loaderName())) + << ExecutableInfo("NVSE", findInGameFolder(feature()->loaderName())) << ExecutableInfo("New Vegas", findInGameFolder(binaryName())) << ExecutableInfo("Fallout Mod Manager", findInGameFolder("fomm/fomm.exe")) << ExecutableInfo("Construction Kit", findInGameFolder("geck.exe")) From f24aeeaba70b3d83ad6665e9693f730d868a20ce Mon Sep 17 00:00:00 2001 From: Tannin Date: Sun, 19 Jun 2016 15:53:44 +0200 Subject: [PATCH 0260/1544] [game_oblivion] updated to changed interface --- src/games/oblivion/src/game_oblivion_en.ts | 2 +- src/games/oblivion/src/gameoblivion.cpp | 16 +++++++++------- .../oblivion/src/oblivionbsainvalidation.cpp | 2 +- src/games/oblivion/src/oblivionbsainvalidation.h | 2 +- 4 files changed, 12 insertions(+), 10 deletions(-) diff --git a/src/games/oblivion/src/game_oblivion_en.ts b/src/games/oblivion/src/game_oblivion_en.ts index e0978554..8110ae36 100644 --- a/src/games/oblivion/src/game_oblivion_en.ts +++ b/src/games/oblivion/src/game_oblivion_en.ts @@ -4,7 +4,7 @@ GameOblivion - + Adds support for the game Oblivion diff --git a/src/games/oblivion/src/gameoblivion.cpp b/src/games/oblivion/src/gameoblivion.cpp index 068cdd1b..ddc67856 100644 --- a/src/games/oblivion/src/gameoblivion.cpp +++ b/src/games/oblivion/src/gameoblivion.cpp @@ -9,6 +9,7 @@ #include "executableinfo.h" #include #include +#include #include #include @@ -27,12 +28,13 @@ bool GameOblivion::init(IOrganizer *moInfo) if (!GameGamebryo::init(moInfo)) { return false; } - m_ScriptExtender = std::shared_ptr(new OblivionScriptExtender(this)); - m_DataArchives = std::shared_ptr(new OblivionDataArchives()); - m_BSAInvalidation = std::shared_ptr(new OblivionBSAInvalidation(m_DataArchives, this)); - m_SaveGameInfo = std::shared_ptr(new OblivionSaveGameInfo(this)); - m_LocalSavegames.reset(new GamebryoLocalSavegames(myGamesPath(), "oblivion.ini")); - m_GamePlugins = std::shared_ptr(new GamebryoGamePlugins(moInfo)); + registerFeature(new OblivionScriptExtender(this)); + registerFeature(new OblivionDataArchives()); + registerFeature(new OblivionBSAInvalidation(feature(), this)); + registerFeature(new OblivionSaveGameInfo(this)); + registerFeature(new GamebryoLocalSavegames(myGamesPath(), "oblivion.ini")); + registerFeature(new GamebryoGamePlugins(moInfo)); + registerFeature(new GamebryoUnmangedMods(this)); return true; } @@ -44,7 +46,7 @@ QString GameOblivion::gameName() const QList GameOblivion::executables() const { return QList() - << ExecutableInfo("OBSE", findInGameFolder(m_ScriptExtender->loaderName())) + << ExecutableInfo("OBSE", findInGameFolder(feature()->loaderName())) << ExecutableInfo("Oblivion", findInGameFolder(binaryName())) << ExecutableInfo("Oblivion Launcher", findInGameFolder(getLauncherName())) << ExecutableInfo("Oblivion Mod Manager", findInGameFolder("OblivionModManager.exe")) diff --git a/src/games/oblivion/src/oblivionbsainvalidation.cpp b/src/games/oblivion/src/oblivionbsainvalidation.cpp index 71806d02..fb275a2d 100644 --- a/src/games/oblivion/src/oblivionbsainvalidation.cpp +++ b/src/games/oblivion/src/oblivionbsainvalidation.cpp @@ -1,7 +1,7 @@ #include "oblivionbsainvalidation.h" -OblivionBSAInvalidation::OblivionBSAInvalidation(const std::shared_ptr &dataArchives, MOBase::IPluginGame const *game) +OblivionBSAInvalidation::OblivionBSAInvalidation(DataArchives *dataArchives, MOBase::IPluginGame const *game) : GamebryoBSAInvalidation(dataArchives, "oblivion.ini", game) { } diff --git a/src/games/oblivion/src/oblivionbsainvalidation.h b/src/games/oblivion/src/oblivionbsainvalidation.h index e4862f68..96a6fa8e 100644 --- a/src/games/oblivion/src/oblivionbsainvalidation.h +++ b/src/games/oblivion/src/oblivionbsainvalidation.h @@ -11,7 +11,7 @@ class OblivionBSAInvalidation : public GamebryoBSAInvalidation { public: - OblivionBSAInvalidation(const std::shared_ptr &dataArchives, MOBase::IPluginGame const *game); + OblivionBSAInvalidation(DataArchives *dataArchives, MOBase::IPluginGame const *game); private: From e6a9897db5f7f02f74c43efae86bbf831a6bc261 Mon Sep 17 00:00:00 2001 From: Tannin Date: Sun, 19 Jun 2016 15:54:07 +0200 Subject: [PATCH 0261/1544] [game_skyrim] updated to changed interface --- src/games/skyrim/src/game_skyrim_en.ts | 2 +- src/games/skyrim/src/gameskyrim.cpp | 16 +++++++++------- src/games/skyrim/src/skyrimbsainvalidation.cpp | 2 +- src/games/skyrim/src/skyrimbsainvalidation.h | 2 +- 4 files changed, 12 insertions(+), 10 deletions(-) diff --git a/src/games/skyrim/src/game_skyrim_en.ts b/src/games/skyrim/src/game_skyrim_en.ts index da6d9d08..d59eced1 100644 --- a/src/games/skyrim/src/game_skyrim_en.ts +++ b/src/games/skyrim/src/game_skyrim_en.ts @@ -4,7 +4,7 @@ GameSkyrim - + Adds support for the game Skyrim diff --git a/src/games/skyrim/src/gameskyrim.cpp b/src/games/skyrim/src/gameskyrim.cpp index e2766e12..58720b35 100644 --- a/src/games/skyrim/src/gameskyrim.cpp +++ b/src/games/skyrim/src/gameskyrim.cpp @@ -10,6 +10,7 @@ #include #include +#include #include #include @@ -37,12 +38,13 @@ bool GameSkyrim::init(IOrganizer *moInfo) if (!GameGamebryo::init(moInfo)) { return false; } - m_ScriptExtender = std::shared_ptr(new SkyrimScriptExtender(this)); - m_DataArchives = std::shared_ptr(new SkyrimDataArchives()); - m_BSAInvalidation = std::shared_ptr(new SkyrimBSAInvalidation(m_DataArchives, this)); - m_SaveGameInfo = std::shared_ptr(new SkyrimSaveGameInfo(this)); - m_LocalSavegames.reset(new GamebryoLocalSavegames(myGamesPath(), "skyrim.ini")); - m_GamePlugins = std::shared_ptr(new GamebryoGamePlugins(moInfo)); + registerFeature(new SkyrimScriptExtender(this)); + registerFeature(new SkyrimDataArchives()); + registerFeature(new SkyrimBSAInvalidation(feature(), this)); + registerFeature(new SkyrimSaveGameInfo(this)); + registerFeature(new GamebryoLocalSavegames(myGamesPath(), "skyrim.ini")); + registerFeature(new GamebryoGamePlugins(moInfo)); + registerFeature(new GamebryoUnmangedMods(this)); return true; } @@ -54,7 +56,7 @@ QString GameSkyrim::gameName() const QList GameSkyrim::executables() const { return QList() - << ExecutableInfo("SKSE", findInGameFolder(m_ScriptExtender->loaderName())) + << ExecutableInfo("SKSE", findInGameFolder(feature()->loaderName())) << ExecutableInfo("SBW", findInGameFolder("SBW.exe")) << ExecutableInfo("Skyrim", findInGameFolder(binaryName())) << ExecutableInfo("Skyrim Launcher", findInGameFolder(getLauncherName())) diff --git a/src/games/skyrim/src/skyrimbsainvalidation.cpp b/src/games/skyrim/src/skyrimbsainvalidation.cpp index 9d2be945..adab711b 100644 --- a/src/games/skyrim/src/skyrimbsainvalidation.cpp +++ b/src/games/skyrim/src/skyrimbsainvalidation.cpp @@ -1,6 +1,6 @@ #include "skyrimbsainvalidation.h" -SkyrimBSAInvalidation::SkyrimBSAInvalidation(const std::shared_ptr &dataArchives, MOBase::IPluginGame const *game) +SkyrimBSAInvalidation::SkyrimBSAInvalidation(DataArchives *dataArchives, MOBase::IPluginGame const *game) : GamebryoBSAInvalidation(dataArchives, "skyrim.ini", game) { } diff --git a/src/games/skyrim/src/skyrimbsainvalidation.h b/src/games/skyrim/src/skyrimbsainvalidation.h index b03ffd8d..0dbb5ff5 100644 --- a/src/games/skyrim/src/skyrimbsainvalidation.h +++ b/src/games/skyrim/src/skyrimbsainvalidation.h @@ -11,7 +11,7 @@ class SkyrimBSAInvalidation : public GamebryoBSAInvalidation { public: - SkyrimBSAInvalidation(const std::shared_ptr &dataArchives, MOBase::IPluginGame const *game); + SkyrimBSAInvalidation(DataArchives *dataArchives, MOBase::IPluginGame const *game); private: From c2e4b86f8912b52b47b34e48e19dc45dc8ef623c Mon Sep 17 00:00:00 2001 From: EmberQuill Date: Wed, 31 Aug 2016 22:09:36 -0400 Subject: [PATCH 0262/1544] [game_fallout4vr] Support new DLC --- src/games/fallout4vr/src/fallout4gameplugins.cpp | 3 ++- src/games/fallout4vr/src/fallout4unmanagedmods.cpp | 6 ++++++ src/games/fallout4vr/src/gamefallout4.cpp | 3 ++- 3 files changed, 10 insertions(+), 2 deletions(-) diff --git a/src/games/fallout4vr/src/fallout4gameplugins.cpp b/src/games/fallout4vr/src/fallout4gameplugins.cpp index 482e127d..e70e7d19 100644 --- a/src/games/fallout4vr/src/fallout4gameplugins.cpp +++ b/src/games/fallout4vr/src/fallout4gameplugins.cpp @@ -17,7 +17,8 @@ using MOBase::SafeWriteFile; using MOBase::reportError; static const std::set OFFICIAL_FILES{ - "fallout4.esm", "dlcrobot.esm", "dlcworkshop01.esm", "dlccoast.esm"}; + "fallout4.esm", "dlcrobot.esm", "dlcworkshop01.esm", "dlccoast.esm", + "dlcworkshop02.esm", "dlcworkshop03.esm", "dlcnukaworld.esm"}; Fallout4GamePlugins::Fallout4GamePlugins(IOrganizer *organizer) : GamebryoGamePlugins(organizer) diff --git a/src/games/fallout4vr/src/fallout4unmanagedmods.cpp b/src/games/fallout4vr/src/fallout4unmanagedmods.cpp index 066da881..3bb279fe 100644 --- a/src/games/fallout4vr/src/fallout4unmanagedmods.cpp +++ b/src/games/fallout4vr/src/fallout4unmanagedmods.cpp @@ -28,6 +28,12 @@ QString Fallout4UnmangedMods::displayName(const QString &modName) const return "Wasteland Workshop"; } else if (modName.compare("dlccoast", Qt::CaseInsensitive) == 0) { return "Far Harbor"; + } else if (modName.compare("dlcworkshop02", Qt::CaseInsensitive) == 0) { + return "Contraptions Workshop"; + } else if (modName.compare("dlcworkshop03", Qt::CaseInsensitive) == 0) { + return "Vault-Tec Workshop"; + } else if (modName.compare("dlcnukaworld", Qt::CaseInsensitive) == 0) { + return "Nuka-World"; } else { return modName; } diff --git a/src/games/fallout4vr/src/gamefallout4.cpp b/src/games/fallout4vr/src/gamefallout4.cpp index a21261fe..3da5681f 100644 --- a/src/games/fallout4vr/src/gamefallout4.cpp +++ b/src/games/fallout4vr/src/gamefallout4.cpp @@ -142,7 +142,8 @@ QStringList GameFallout4::iniFiles() const QStringList GameFallout4::DLCPlugins() const { - return {"dlcrobot.esm", "dlcworkshop01.esm", "dlccoast.esm"}; + return {"dlcrobot.esm", "dlcworkshop01.esm", "dlccoast.esm", + "dlcworkshop02.esm", "dlcworkshop03.esm", "dlcnukaworld.esm"}; } IPluginGame::LoadOrderMechanism GameFallout4::loadOrderMechanism() const From e92b66186cb6d1a82cc7ca874ec052b8ab1e50ac Mon Sep 17 00:00:00 2001 From: EmberQuill Date: Wed, 31 Aug 2016 22:09:36 -0400 Subject: [PATCH 0263/1544] [game_fallout76] Support new DLC --- src/games/fallout76/src/fallout4gameplugins.cpp | 3 ++- src/games/fallout76/src/fallout4unmanagedmods.cpp | 6 ++++++ src/games/fallout76/src/gamefallout4.cpp | 3 ++- 3 files changed, 10 insertions(+), 2 deletions(-) diff --git a/src/games/fallout76/src/fallout4gameplugins.cpp b/src/games/fallout76/src/fallout4gameplugins.cpp index 482e127d..e70e7d19 100644 --- a/src/games/fallout76/src/fallout4gameplugins.cpp +++ b/src/games/fallout76/src/fallout4gameplugins.cpp @@ -17,7 +17,8 @@ using MOBase::SafeWriteFile; using MOBase::reportError; static const std::set OFFICIAL_FILES{ - "fallout4.esm", "dlcrobot.esm", "dlcworkshop01.esm", "dlccoast.esm"}; + "fallout4.esm", "dlcrobot.esm", "dlcworkshop01.esm", "dlccoast.esm", + "dlcworkshop02.esm", "dlcworkshop03.esm", "dlcnukaworld.esm"}; Fallout4GamePlugins::Fallout4GamePlugins(IOrganizer *organizer) : GamebryoGamePlugins(organizer) diff --git a/src/games/fallout76/src/fallout4unmanagedmods.cpp b/src/games/fallout76/src/fallout4unmanagedmods.cpp index 066da881..3bb279fe 100644 --- a/src/games/fallout76/src/fallout4unmanagedmods.cpp +++ b/src/games/fallout76/src/fallout4unmanagedmods.cpp @@ -28,6 +28,12 @@ QString Fallout4UnmangedMods::displayName(const QString &modName) const return "Wasteland Workshop"; } else if (modName.compare("dlccoast", Qt::CaseInsensitive) == 0) { return "Far Harbor"; + } else if (modName.compare("dlcworkshop02", Qt::CaseInsensitive) == 0) { + return "Contraptions Workshop"; + } else if (modName.compare("dlcworkshop03", Qt::CaseInsensitive) == 0) { + return "Vault-Tec Workshop"; + } else if (modName.compare("dlcnukaworld", Qt::CaseInsensitive) == 0) { + return "Nuka-World"; } else { return modName; } diff --git a/src/games/fallout76/src/gamefallout4.cpp b/src/games/fallout76/src/gamefallout4.cpp index a21261fe..3da5681f 100644 --- a/src/games/fallout76/src/gamefallout4.cpp +++ b/src/games/fallout76/src/gamefallout4.cpp @@ -142,7 +142,8 @@ QStringList GameFallout4::iniFiles() const QStringList GameFallout4::DLCPlugins() const { - return {"dlcrobot.esm", "dlcworkshop01.esm", "dlccoast.esm"}; + return {"dlcrobot.esm", "dlcworkshop01.esm", "dlccoast.esm", + "dlcworkshop02.esm", "dlcworkshop03.esm", "dlcnukaworld.esm"}; } IPluginGame::LoadOrderMechanism GameFallout4::loadOrderMechanism() const From 26c5197a7fa56d9823ba31765581c3b204f1b696 Mon Sep 17 00:00:00 2001 From: EmberQuill Date: Wed, 31 Aug 2016 22:09:36 -0400 Subject: [PATCH 0264/1544] [game_fallout4] Support new DLC --- src/games/fallout4/src/fallout4gameplugins.cpp | 3 ++- src/games/fallout4/src/fallout4unmanagedmods.cpp | 6 ++++++ src/games/fallout4/src/gamefallout4.cpp | 3 ++- 3 files changed, 10 insertions(+), 2 deletions(-) diff --git a/src/games/fallout4/src/fallout4gameplugins.cpp b/src/games/fallout4/src/fallout4gameplugins.cpp index 482e127d..e70e7d19 100644 --- a/src/games/fallout4/src/fallout4gameplugins.cpp +++ b/src/games/fallout4/src/fallout4gameplugins.cpp @@ -17,7 +17,8 @@ using MOBase::SafeWriteFile; using MOBase::reportError; static const std::set OFFICIAL_FILES{ - "fallout4.esm", "dlcrobot.esm", "dlcworkshop01.esm", "dlccoast.esm"}; + "fallout4.esm", "dlcrobot.esm", "dlcworkshop01.esm", "dlccoast.esm", + "dlcworkshop02.esm", "dlcworkshop03.esm", "dlcnukaworld.esm"}; Fallout4GamePlugins::Fallout4GamePlugins(IOrganizer *organizer) : GamebryoGamePlugins(organizer) diff --git a/src/games/fallout4/src/fallout4unmanagedmods.cpp b/src/games/fallout4/src/fallout4unmanagedmods.cpp index 066da881..3bb279fe 100644 --- a/src/games/fallout4/src/fallout4unmanagedmods.cpp +++ b/src/games/fallout4/src/fallout4unmanagedmods.cpp @@ -28,6 +28,12 @@ QString Fallout4UnmangedMods::displayName(const QString &modName) const return "Wasteland Workshop"; } else if (modName.compare("dlccoast", Qt::CaseInsensitive) == 0) { return "Far Harbor"; + } else if (modName.compare("dlcworkshop02", Qt::CaseInsensitive) == 0) { + return "Contraptions Workshop"; + } else if (modName.compare("dlcworkshop03", Qt::CaseInsensitive) == 0) { + return "Vault-Tec Workshop"; + } else if (modName.compare("dlcnukaworld", Qt::CaseInsensitive) == 0) { + return "Nuka-World"; } else { return modName; } diff --git a/src/games/fallout4/src/gamefallout4.cpp b/src/games/fallout4/src/gamefallout4.cpp index a21261fe..3da5681f 100644 --- a/src/games/fallout4/src/gamefallout4.cpp +++ b/src/games/fallout4/src/gamefallout4.cpp @@ -142,7 +142,8 @@ QStringList GameFallout4::iniFiles() const QStringList GameFallout4::DLCPlugins() const { - return {"dlcrobot.esm", "dlcworkshop01.esm", "dlccoast.esm"}; + return {"dlcrobot.esm", "dlcworkshop01.esm", "dlccoast.esm", + "dlcworkshop02.esm", "dlcworkshop03.esm", "dlcnukaworld.esm"}; } IPluginGame::LoadOrderMechanism GameFallout4::loadOrderMechanism() const From 4b78dd7e3dab306ae8c5fdc7100f91ce72d9eb9b Mon Sep 17 00:00:00 2001 From: Grant Kim Date: Thu, 3 Nov 2016 05:04:17 +0900 Subject: [PATCH 0265/1544] [game_skyrimse] First commit --- src/games/skyrimse/.gitignore | 4 + src/games/skyrimse/CMakeLists.txt | 15 + src/games/skyrimse/src/CMakeLists.txt | 68 ++++ src/games/skyrimse/src/SConscript | 13 + src/games/skyrimse/src/game_skyrimse_en.ts | 30 ++ src/games/skyrimse/src/gameskyrimse.cpp | 320 ++++++++++++++++++ src/games/skyrimse/src/gameskyrimse.h | 71 ++++ src/games/skyrimse/src/gameskyrimse.json | 1 + src/games/skyrimse/src/gameskyrimse.pro | 50 +++ .../skyrimse/src/skyrimsedataarchives.cpp | 54 +++ src/games/skyrimse/src/skyrimsedataarchives.h | 24 ++ .../skyrimse/src/skyrimsegameplugins.cpp | 135 ++++++++ src/games/skyrimse/src/skyrimsegameplugins.h | 27 ++ src/games/skyrimse/src/skyrimsesavegame.cpp | 43 +++ src/games/skyrimse/src/skyrimsesavegame.h | 14 + .../skyrimse/src/skyrimsesavegameinfo.cpp | 19 ++ src/games/skyrimse/src/skyrimsesavegameinfo.h | 17 + .../skyrimse/src/skyrimsescriptextender.cpp | 19 ++ .../skyrimse/src/skyrimsescriptextender.h | 19 ++ .../skyrimse/src/skyrimseunmanagedmods.cpp | 34 ++ .../skyrimse/src/skyrimseunmanagedmods.h | 20 ++ 21 files changed, 997 insertions(+) create mode 100644 src/games/skyrimse/.gitignore create mode 100644 src/games/skyrimse/CMakeLists.txt create mode 100644 src/games/skyrimse/src/CMakeLists.txt create mode 100644 src/games/skyrimse/src/SConscript create mode 100644 src/games/skyrimse/src/game_skyrimse_en.ts create mode 100644 src/games/skyrimse/src/gameskyrimse.cpp create mode 100644 src/games/skyrimse/src/gameskyrimse.h create mode 100644 src/games/skyrimse/src/gameskyrimse.json create mode 100644 src/games/skyrimse/src/gameskyrimse.pro create mode 100644 src/games/skyrimse/src/skyrimsedataarchives.cpp create mode 100644 src/games/skyrimse/src/skyrimsedataarchives.h create mode 100644 src/games/skyrimse/src/skyrimsegameplugins.cpp create mode 100644 src/games/skyrimse/src/skyrimsegameplugins.h create mode 100644 src/games/skyrimse/src/skyrimsesavegame.cpp create mode 100644 src/games/skyrimse/src/skyrimsesavegame.h create mode 100644 src/games/skyrimse/src/skyrimsesavegameinfo.cpp create mode 100644 src/games/skyrimse/src/skyrimsesavegameinfo.h create mode 100644 src/games/skyrimse/src/skyrimsescriptextender.cpp create mode 100644 src/games/skyrimse/src/skyrimsescriptextender.h create mode 100644 src/games/skyrimse/src/skyrimseunmanagedmods.cpp create mode 100644 src/games/skyrimse/src/skyrimseunmanagedmods.h diff --git a/src/games/skyrimse/.gitignore b/src/games/skyrimse/.gitignore new file mode 100644 index 00000000..bcc50d34 --- /dev/null +++ b/src/games/skyrimse/.gitignore @@ -0,0 +1,4 @@ +CMakeLists.txt.user +edit +build +std*.log diff --git a/src/games/skyrimse/CMakeLists.txt b/src/games/skyrimse/CMakeLists.txt new file mode 100644 index 00000000..4cbb9dbe --- /dev/null +++ b/src/games/skyrimse/CMakeLists.txt @@ -0,0 +1,15 @@ +#CMAKE_MINIMUM_REQUIRED(VERSION 2.8) + +SET(PROJ_NAME game_skyrimse) + +PROJECT(${PROJ_NAME}) + +SET(DEPENDENCIES_DIR CACHE PATH "") + +# hint to find qt in dependencies path +LIST(APPEND CMAKE_PREFIX_PATH ${DEPENDENCIES_DIR}/qt5/lib/cmake) + +FILE(GLOB_RECURSE BOOST_ROOT ${DEPENDENCIES_DIR}/boost*/project-config.jam) +GET_FILENAME_COMPONENT(BOOST_ROOT ${BOOST_ROOT} DIRECTORY) + +ADD_SUBDIRECTORY(src) diff --git a/src/games/skyrimse/src/CMakeLists.txt b/src/games/skyrimse/src/CMakeLists.txt new file mode 100644 index 00000000..c01ddda8 --- /dev/null +++ b/src/games/skyrimse/src/CMakeLists.txt @@ -0,0 +1,68 @@ +CMAKE_MINIMUM_REQUIRED (VERSION 2.8) + +CMAKE_POLICY(SET CMP0020 NEW) + +FILE(GLOB ${PROJ_NAME}_SRCS *.cpp) +FILE(GLOB ${PROJ_NAME}_HDRS *.h) +FILE(GLOB ${PROJ_NAME}_FORMS *.ui) + +SET(CMAKE_INCLUDE_CURRENT_DIR ON) +SET(CMAKE_AUTOMOC ON) +SET(CMAKE_AUTOUIC ON) +FIND_PACKAGE(Qt5Widgets REQUIRED) +QT5_WRAP_UI(${PROJ_NAME}_UIHDRS ${${PROJ_NAME}_FORMS}) +FIND_PACKAGE(Qt5LinguistTools) +QT5_CREATE_TRANSLATION(${PROJ_NAME}_translations_qm ${CMAKE_SOURCE_DIR}/src ${CMAKE_SOURCE_DIR}/src/${PROJ_NAME}_en.ts) + +SET(Boost_USE_STATIC_LIBS ON) +SET(Boost_USE_MULTITHREADED ON) +SET(Boost_USE_STATIC_RUNTIME OFF) +FIND_PACKAGE(Boost) + +IF (Boost_FOUND) + INCLUDE_DIRECTORIES(${Boost_INCLUDE_DIRS}) +ENDIF () + +SET(default_project_path "${CMAKE_SOURCE_DIR}/..") +GET_FILENAME_COMPONENT(${default_project_path} ${default_project_path} REALPATH) + +SET(project_path "${default_project_path}" CACHE PATH "path to the other mo projects") +SET(lib_path "${project_path}/../../install/libs") + +INCLUDE_DIRECTORIES(${project_path}/../modorganizer-uibase/src + ${project_path}/../modorganizer-game_features/src + ${project_path}/../modorganizer-game_gamebryo/src) +LINK_DIRECTORIES(${project_path}/lib + ${lib_path}) + + +ADD_LIBRARY(${PROJ_NAME} SHARED ${${PROJ_NAME}_HDRS} ${${PROJ_NAME}_SRCS} ${${PROJ_NAME}_UIHDRS} ${${PROJ_NAME}_RCCPPS} ${${PROJ_NAME}_translations_qm}) +TARGET_LINK_LIBRARIES(${PROJ_NAME} + Qt5::Widgets + ${Boost_LIBRARIES} + uibase + Version + game_gamebryo) + +IF(MSVC) + SET_TARGET_PROPERTIES(${PROJ_NAME} PROPERTIES LINK_FLAGS "/LARGEADDRESSAWARE") +ELSE(MSVC) + SET_TARGET_PROPERTIES(${PROJ_NAME} PROPERTIES LINK_FLAGS "-std=c++11") +ENDIF(MSVC) + +IF (NOT "${OPTIMIZE_COMPILE_FLAGS}" STREQUAL "") + SET_TARGET_PROPERTIES(${PROJ_NAME} PROPERTIES COMPILE_FLAGS_RELWITHDEBINFO ${OPTIMIZE_COMPILE_FLAGS}) +ENDIF() +IF (NOT "${OPTIMIZE_LINK_FLAGS}" STREQUAL "") + SET_TARGET_PROPERTIES(${PROJ_NAME} PROPERTIES LINK_FLAGS_RELWITHDEBINFO ${OPTIMIZE_LINK_FLAGS}) +ENDIF() + +QT5_USE_MODULES(${PROJ_NAME} Widgets) + + +############### +## Installation + +INSTALL(TARGETS ${PROJ_NAME} + RUNTIME DESTINATION bin/plugins) +INSTALL(FILES ${CMAKE_CURRENT_BINARY_DIR}/${PROJ_NAME}.pdb DESTINATION pdb) diff --git a/src/games/skyrimse/src/SConscript b/src/games/skyrimse/src/SConscript new file mode 100644 index 00000000..287c3242 --- /dev/null +++ b/src/games/skyrimse/src/SConscript @@ -0,0 +1,13 @@ +Import('qt_env') + +env = qt_env.Clone() + +env.AppendUnique(CPPDEFINES = [ 'GAMESKYRIMSE_LIBRARY' ]) + +env.RequiresGamebryo() + +lib = env.SharedLibrary('gameSkyrimSE', env.Glob('*.cpp')) +env.InstallModule(lib) + +res = env['QT_USED_MODULES'] +Return('res') diff --git a/src/games/skyrimse/src/game_skyrimse_en.ts b/src/games/skyrimse/src/game_skyrimse_en.ts new file mode 100644 index 00000000..e770d773 --- /dev/null +++ b/src/games/skyrimse/src/game_skyrimse_en.ts @@ -0,0 +1,30 @@ + + + + + GameSkyrimSE + + + Adds support for the game Skyrim Special Edition. + + + + + QObject + + + failed to query registry path (preflight): %1 + + + + + failed to query registry path (read): %1 + + + + + Some of your plugins have invalid names! These plugins can not be loaded by the game. Please see mo_interface.log for a list of affected plugins and rename them. + + + + diff --git a/src/games/skyrimse/src/gameskyrimse.cpp b/src/games/skyrimse/src/gameskyrimse.cpp new file mode 100644 index 00000000..65ff444c --- /dev/null +++ b/src/games/skyrimse/src/gameskyrimse.cpp @@ -0,0 +1,320 @@ +#include "gameskyrimse.h" + +#include "skyrimsedataarchives.h" +#include "skyrimsescriptextender.h" +#include "skyrimsesavegameinfo.h" +#include "skyrimsegameplugins.h" +#include "skyrimseunmanagedmods.h" + +#include +#include "iplugingame.h" +#include +#include +#include +#include "versioninfo.h" + +#include +#include +#include +#include +#include +#include +#include + +#include + + +#include "utility.h" +#include +#include +#include "scopeguard.h" +namespace { + + std::unique_ptr getRegValue(HKEY key, LPCWSTR path, LPCWSTR value, + DWORD flags, LPDWORD type = nullptr) + { + DWORD size = 0; + HKEY subKey; + LONG res = ::RegOpenKeyExW(key, path, 0, + KEY_QUERY_VALUE | KEY_WOW64_32KEY, &subKey); + if (res != ERROR_SUCCESS) { + return std::unique_ptr(); + } + res = ::RegGetValueW(subKey, L"", value, flags, type, nullptr, &size); + if (res == ERROR_FILE_NOT_FOUND || res == ERROR_UNSUPPORTED_TYPE) { + return std::unique_ptr(); + } + if (res != ERROR_SUCCESS && res != ERROR_MORE_DATA) { + throw MOBase::MyException(QObject::tr("failed to query registry path (preflight): %1").arg(res, 0, 16)); + } + + std::unique_ptr result(new BYTE[size]); + res = ::RegGetValueW(subKey, L"", value, flags, type, result.get(), &size); + + if (res != ERROR_SUCCESS) { + throw MOBase::MyException(QObject::tr("failed to query registry path (read): %1").arg(res, 0, 16)); + } + + return result; + } + + QString findInRegistry(HKEY baseKey, LPCWSTR path, LPCWSTR value) + { + std::unique_ptr buffer = getRegValue(baseKey, path, value, RRF_RT_REG_SZ | RRF_NOEXPAND); + + return QString::fromUtf16(reinterpret_cast(buffer.get())); + } + + QString getKnownFolderPath(REFKNOWNFOLDERID folderId, bool useDefault) + { + PWSTR path = nullptr; + ON_BLOCK_EXIT([&]() { + if (path != nullptr) ::CoTaskMemFree(path); + }); + + if (::SHGetKnownFolderPath(folderId, useDefault ? KF_FLAG_DEFAULT_PATH : 0, NULL, &path) == S_OK) { + return QDir::fromNativeSeparators(QString::fromWCharArray(path)); + } + else { + return QString(); + } + } + + + QString getSpecialPath(const QString &name) + { + QString base = findInRegistry(HKEY_CURRENT_USER, + L"Software\\Microsoft\\Windows\\CurrentVersion\\Explorer\\User Shell Folders", + name.toStdWString().c_str()); + + WCHAR temp[MAX_PATH]; + if (::ExpandEnvironmentStringsW(base.toStdWString().c_str(), temp, MAX_PATH) != 0) { + return QString::fromWCharArray(temp); + } + else { + return base; + } + } + + QString determineMyGamesPath(const QString &gameName) + { + // a) this is the way it should work. get the configured My Documents directory + QString result = getKnownFolderPath(FOLDERID_Documents, false); + + // b) if there is no directory there, look in the default directory + if (result.isEmpty() + || !QFileInfo(result + "/My Games/" + gameName).exists()) { + result = getKnownFolderPath(FOLDERID_Documents, true); + } + // c) finally, look in the registry. This is discouraged + if (result.isEmpty() + || !QFileInfo(result + "/My Games/" + gameName).exists()) { + result = getSpecialPath("Personal"); + } + + return result + "/My Games/" + gameName; + } + + +} + + +using namespace MOBase; + +GameSkyrimSE::GameSkyrimSE() +{ +} + +void GameSkyrimSE::setGamePath(const QString &path) +{ + m_GamePath = path; +} + +QDir GameSkyrimSE::documentsDirectory() const +{ + return m_MyGamesPath; +} + +QString GameSkyrimSE::identifyGamePath() const +{ + QString path = "Software\\Bethesda Softworks\\" + gameName(); + return findInRegistry(HKEY_LOCAL_MACHINE, path.toStdWString().c_str(), L"Installed Path"); +} + +QDir GameSkyrimSE::savesDirectory() const +{ + return QDir(m_MyGamesPath + "/Saves"); +} + +QString GameSkyrimSE::myGamesPath() const +{ + return m_MyGamesPath; +} + +bool GameSkyrimSE::isInstalled() const +{ + return !m_GamePath.isEmpty(); +} + +bool GameSkyrimSE::init(IOrganizer *moInfo) +{ + if (!GameGamebryo::init(moInfo)) { + return false; + } + + m_Organizer = moInfo; + m_GamePath = GameSkyrimSE::identifyGamePath(); + m_MyGamesPath = determineMyGamesPath(gameName()); + + + registerFeature(new SkyrimSEScriptExtender(this)); + registerFeature(new SkyrimSEDataArchives()); + registerFeature(new GamebryoLocalSavegames(myGamesPath(), "Skyrim.ini")); + registerFeature(new SkyrimSESaveGameInfo(this)); + registerFeature(new SkyrimSEGamePlugins(moInfo)); + registerFeature(new SkyrimSEUnmangedMods(this)); + + return true; +} + + + +QString GameSkyrimSE::gameName() const +{ + return "Skyrim Special Edition"; +} + +QList GameSkyrimSE::executables() const +{ + return QList() + << ExecutableInfo("SKSE", findInGameFolder(feature()->loaderName())) + << ExecutableInfo("Skyrim Special Edition", findInGameFolder(binaryName())) + << ExecutableInfo("Skyrim Special Edition Launcher", findInGameFolder(getLauncherName())) + << ExecutableInfo("Creation Kit", findInGameFolder("CreationKit.exe")) + << ExecutableInfo("LOOT", getLootPath()) + ; +} + +QFileInfo GameSkyrimSE::findInGameFolder(const QString &relativePath) const +{ + return QFileInfo(m_GamePath + "/" + relativePath); +} + +QString GameSkyrimSE::name() const +{ + return "Skyrim Special Edition Support Plugin"; +} + +QString GameSkyrimSE::author() const +{ + return "Archost"; +} + +QString GameSkyrimSE::description() const +{ + return tr("Adds support for the game Skyrim Special Edition."); +} + +MOBase::VersionInfo GameSkyrimSE::version() const +{ + return VersionInfo(0, 1, 4, VersionInfo::RELEASE_ALPHA); +} + +bool GameSkyrimSE::isActive() const +{ + return qApp->property("managed_game").value() == this; +} + +QList GameSkyrimSE::settings() const +{ + return QList(); +} + +void GameSkyrimSE::initializeProfile(const QDir &path, ProfileSettings settings) const +{ + if (settings.testFlag(IPluginGame::MODS)) { + copyToProfile(localAppFolder() + "/Skyrim Special Edition", path, "plugins.txt"); + copyToProfile(localAppFolder() + "/Skyrim Special Edition", path, "loadorder.txt"); + } + + if (settings.testFlag(IPluginGame::CONFIGURATION)) { + if (settings.testFlag(IPluginGame::PREFER_DEFAULTS) + || !QFileInfo(myGamesPath() + "/skyrim.ini").exists()) { + copyToProfile(gameDirectory().absolutePath(), path, "skyrim_default.ini", "skyrim.ini"); + } + else { + copyToProfile(myGamesPath(), path, "skyrim.ini"); + } + + copyToProfile(myGamesPath(), path, "skyrimprefs.ini"); + } +} + +QString GameSkyrimSE::savegameExtension() const +{ + return "ess"; +} + +QString GameSkyrimSE::steamAPPId() const +{ + return "489830"; +} + +QStringList GameSkyrimSE::primaryPlugins() const { + return{ "skyrim.esm", "update.esm", };// }; +} + +QStringList GameSkyrimSE::gameVariants() const +{ + return{ "Regular" }; +} + +QString GameSkyrimSE::gameShortName() const +{ + return "SkyrimSE"; +} + +QStringList GameSkyrimSE::iniFiles() const +{ + return{ "skyrim.ini", "skyrimprefs.ini" }; +} + +QStringList GameSkyrimSE::DLCPlugins() const +{ + return{ "dawnguard.esm", "hearthfires.esm", "dragonborn.esm" }; +} + +IPluginGame::LoadOrderMechanism GameSkyrimSE::loadOrderMechanism() const +{ + return IPluginGame::LoadOrderMechanism::PluginsTxt; +} + +int GameSkyrimSE::nexusModOrganizerID() const +{ + return 1704; //... Should be 0? +} + +int GameSkyrimSE::nexusGameID() const +{ + return 1704; //1704 +} + +QDir GameSkyrimSE::gameDirectory() const +{ + return QDir(m_GamePath); +} + +// Not to delete all the spaces... +MappingType GameSkyrimSE::mappings() const +{ + MappingType result; + + for (const QString &profileFile : { "plugins.txt", "loadorder.txt" }) { + result.push_back({ m_Organizer->profilePath() + "/" + profileFile, + localAppFolder() + "/" + gameName() + "/" + profileFile, + false }); + } + + return result; +} + diff --git a/src/games/skyrimse/src/gameskyrimse.h b/src/games/skyrimse/src/gameskyrimse.h new file mode 100644 index 00000000..c2a9d105 --- /dev/null +++ b/src/games/skyrimse/src/gameskyrimse.h @@ -0,0 +1,71 @@ +#ifndef _GAMESKYRIMSE_H +#define _GAMESKYRIMSE_H + + +#include "gamegamebryo.h" + +#include +#include + +class GameSkyrimSE : public GameGamebryo +{ + Q_OBJECT + + Q_PLUGIN_METADATA(IID "com.soundcontactstudio.GameSkyrimSE" FILE "gameskyrimse.json") + +public: + + GameSkyrimSE(); + + virtual bool init(MOBase::IOrganizer *moInfo) override; + +public: // IPluginGame interface + + virtual QString gameName() const override; + + virtual QList executables() const override; + virtual void initializeProfile(const QDir &path, ProfileSettings settings) const override; + virtual QString savegameExtension() const override; + virtual QString steamAPPId() const override; + virtual QStringList primaryPlugins() const override; + virtual QStringList gameVariants() const override; + virtual QString gameShortName() const override; + virtual QStringList iniFiles() const override; + virtual QStringList DLCPlugins() const override; + virtual LoadOrderMechanism loadOrderMechanism() const override; + virtual int nexusModOrganizerID() const override; + virtual int nexusGameID() 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 author() const override; + virtual QString description() const override; + virtual MOBase::VersionInfo version() const override; + virtual bool isActive() const override; + virtual QList settings() const override; + + +protected: + QDir documentsDirectory() const; + QDir savesDirectory() const; + QFileInfo findInGameFolder(const QString &relativePath) const; + QString myGamesPath() const; + +public: // IPluginFileMapper + virtual MappingType mappings() const; + + +private: + MOBase::IOrganizer *m_Organizer; + QString identifyGamePath() const; + QString m_GamePath; + QString m_MyGamesPath; + +}; + +#endif // _GAMESKYRIMSE_H diff --git a/src/games/skyrimse/src/gameskyrimse.json b/src/games/skyrimse/src/gameskyrimse.json new file mode 100644 index 00000000..0967ef42 --- /dev/null +++ b/src/games/skyrimse/src/gameskyrimse.json @@ -0,0 +1 @@ +{} diff --git a/src/games/skyrimse/src/gameskyrimse.pro b/src/games/skyrimse/src/gameskyrimse.pro new file mode 100644 index 00000000..8636c0fd --- /dev/null +++ b/src/games/skyrimse/src/gameskyrimse.pro @@ -0,0 +1,50 @@ +#------------------------------------------------- +# +# Project created by QtCreator 2016-10-28T12:24:19 +# +#------------------------------------------------- + + +TARGET = gameSkyrimSE +TEMPLATE = lib + +CONFIG += plugins +CONFIG += dll + +DEFINES += GAMESKYRIMSE_LIBRARY + +SOURCES += gameskyrimse.cpp \ + skyrimsebsainvalidation.cpp \ + skyrimsescriptextender.cpp \ + skyrimsedataarchives.cpp \ + skyrimsesavegame.cpp \ + skyrimsesavegameinfo.cpp + +HEADERS += gameskyrimse.h \ + skyrimsebsainvalidation.h \ + skyrimsescriptextender.h \ + skyrimsedataarchives.h \ + skyrimsesavegame.h \ + skyrimsesavegameinfo.h + +CONFIG(debug, debug|release) { + LIBS += -L"$${OUT_PWD}/../gameGamebryo/debug" + PRE_TARGETDEPS += \ + $$OUT_PWD/../gameGamebryo/debug/gameGamebryo.lib +} else { + LIBS += -L"$${OUT_PWD}/../gameGamebryo/release" + PRE_TARGETDEPS += \ + $$OUT_PWD/../gameGamebryo/release/gameGamebryo.lib +} + +include(../plugin_template.pri) + +INCLUDEPATH += "$${BOOSTPATH}" "$${PWD}/../gamefeatures" "$${PWD}/../gamegamebryo" + +LIBS += -ladvapi32 -lole32 -lgameGamebryo + +OTHER_FILES += \ + gameskyrimse.json\ + SConscript \ + CMakeLists.txt + diff --git a/src/games/skyrimse/src/skyrimsedataarchives.cpp b/src/games/skyrimse/src/skyrimsedataarchives.cpp new file mode 100644 index 00000000..455d46a3 --- /dev/null +++ b/src/games/skyrimse/src/skyrimsedataarchives.cpp @@ -0,0 +1,54 @@ +#include "skyrimSEdataarchives.h" + +#include "iprofile.h" +#include + +#include + + +QStringList SkyrimSEDataArchives::vanillaArchives() const +{ + return{ "Skyrim - Textures0.bsa" + , "Skyrim - Textures1.bsa" + , "Skyrim - Textures2.bsa" + , "Skyrim - Textures3.bsa" + , "Skyrim - Textures4.bsa" + , "Skyrim - Textures5.bsa" + , "Skyrim - Textures6.bsa" + , "Skyrim - Textures7.bsa" + , "Skyrim - Textures8.bsa" + , "Skyrim - Meshes0.bsa" + , "Skyrim - Meshes1.bsa" + , "Skyrim - Voices_en0.bsa" + , "Skyrim - Sounds.bsa" + , "Skyrim - Interface.bsa" + , "Skyrim - Animations.bsa" + , "Skyrim - Shaders.bsa" + , "Skyrim - Misc.bsa" }; +} + + +QStringList SkyrimSEDataArchives::archives(const MOBase::IProfile *profile) const +{ + QStringList result; + + QString iniFile = QDir(profile->absolutePath()).absoluteFilePath("skyrim.ini"); + result.append(getArchivesFromKey(iniFile, "SResourceArchiveList")); + result.append(getArchivesFromKey(iniFile, "SResourceArchiveList2")); + + return result; +} + +void SkyrimSEDataArchives::writeArchiveList(MOBase::IProfile *profile, const QStringList &before) +{ + QString list = before.join(", "); + + QString iniFile = QDir(profile->absolutePath()).absoluteFilePath("skyrim.ini"); + if (list.length() > 255) { + int splitIdx = list.lastIndexOf(",", 256); + setArchivesToKey(iniFile, "SResourceArchiveList", list.mid(0, splitIdx)); + setArchivesToKey(iniFile, "SResourceArchiveList2", list.mid(splitIdx + 2)); + } else { + setArchivesToKey(iniFile, "SResourceArchiveList", list); + } +} diff --git a/src/games/skyrimse/src/skyrimsedataarchives.h b/src/games/skyrimse/src/skyrimsedataarchives.h new file mode 100644 index 00000000..6ba4fb6d --- /dev/null +++ b/src/games/skyrimse/src/skyrimsedataarchives.h @@ -0,0 +1,24 @@ +#ifndef _SKYRIMSEDATAARCHIVES_H +#define _SKYRIMSEDATAARCHIVES_H + +#include "gamebryodataarchives.h" + +namespace MOBase { class IProfile; } + +#include + +class SkyrimSEDataArchives : public GamebryoDataArchives +{ + +public: + + 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 // _SKYRIMSEDATAARCHIVES_H diff --git a/src/games/skyrimse/src/skyrimsegameplugins.cpp b/src/games/skyrimse/src/skyrimsegameplugins.cpp new file mode 100644 index 00000000..5b0f1e19 --- /dev/null +++ b/src/games/skyrimse/src/skyrimsegameplugins.cpp @@ -0,0 +1,135 @@ +#include "skyrimSEgameplugins.h" +#include +#include +#include +#include +#include + +#include +#include +#include + + +using MOBase::IPluginGame; +using MOBase::IPluginList; +using MOBase::IOrganizer; +using MOBase::SafeWriteFile; +using MOBase::reportError; + +static const std::set OFFICIAL_FILES{ + "skyrim.esm", "update.esm", "Dawnguard.esm", "HearthFires.esm", "Dragonborn.esm"}; + +SkyrimSEGamePlugins::SkyrimSEGamePlugins(IOrganizer *organizer) + : GamebryoGamePlugins(organizer) +{ +} + +void SkyrimSEGamePlugins::writePluginList(const IPluginList *pluginList, + const QString &filePath) { + SafeWriteFile file(filePath); + + QTextCodec *textCodec = localCodec(); + + file->resize(0); + + file->write(textCodec->fromUnicode( + "# This file was automatically generated by Mod Organizer.\r\n")); + + bool invalidFileNames = false; + int writtenCount = 0; + + QStringList plugins = pluginList->pluginNames(); + std::sort(plugins.begin(), plugins.end(), + [pluginList](const QString &lhs, const QString &rhs) { + return pluginList->priority(lhs) < pluginList->priority(rhs); + }); + + + //TODO: do not write plugins in OFFICIAL_FILES container + for (const QString &pluginName : plugins) { + if (pluginList->state(pluginName) == IPluginList::STATE_ACTIVE) { + if (!textCodec->canEncode(pluginName)) { + invalidFileNames = true; + qCritical("invalid plugin name %s", qPrintable(pluginName)); + } + else + { + file->write("*"); + file->write(textCodec->fromUnicode(pluginName)); + + } + file->write("\r\n"); + ++writtenCount; + } + } + + if (invalidFileNames) { + reportError(QObject::tr("Some of your plugins have invalid names! These " + "plugins can not be loaded by the game. Please see " + "mo_interface.log for a list of affected plugins " + "and rename them.")); + } + + if (file.commitIfDifferent(m_LastSaveHash[filePath])) { + qDebug("%s saved", qPrintable(QDir::toNativeSeparators(filePath))); + } +} + +bool SkyrimSEGamePlugins::readPluginList(MOBase::IPluginList *pluginList, + const QString &filePath, + bool useLoadOrder) +{ + QStringList plugins = pluginList->pluginNames(); + + for (const QString &pluginName : OFFICIAL_FILES) { + if (pluginList->state(pluginName) != IPluginList::STATE_MISSING) { + pluginList->setState(pluginName, IPluginList::STATE_ACTIVE); + } + } + + QFile file(filePath); + if (!file.open(QIODevice::ReadOnly)) { + qWarning("%s not found", qPrintable(filePath)); + return false; + } + ON_BLOCK_EXIT([&]() { file.close(); }); + + if (file.size() == 0) { + // MO stores at least a header in the file. if it's completely empty the + // file is broken + qWarning("%s empty", qPrintable(filePath)); + return false; + } + + QStringList loadOrder = organizer()->managedGame()->primaryPlugins(); + while (!file.atEnd()) { + QByteArray line = file.readLine(); + QString pluginName; + if ((line.size() > 0) && (line.at(0) != '#')) { + pluginName = localCodec()->toUnicode(line.trimmed().constData()); + } + if (pluginName.startsWith('*')) { + pluginName.remove(0, 1); + } + if (pluginName.size() > 0) { + pluginList->setState(pluginName, IPluginList::STATE_ACTIVE); + plugins.removeAll(pluginName); + if (!loadOrder.contains(pluginName, Qt::CaseInsensitive)) { + loadOrder.append(pluginName); + } + } + } + + file.close(); + + // we removed each plugin found in the file, so what's left are inactive mods + for (const QString &pluginName : plugins) { + pluginList->setState(pluginName, IPluginList::STATE_INACTIVE); + } + + if (useLoadOrder) { + pluginList->setLoadOrder(loadOrder); + } + + return true; +} diff --git a/src/games/skyrimse/src/skyrimsegameplugins.h b/src/games/skyrimse/src/skyrimsegameplugins.h new file mode 100644 index 00000000..ecf733d2 --- /dev/null +++ b/src/games/skyrimse/src/skyrimsegameplugins.h @@ -0,0 +1,27 @@ +#ifndef _SKYRIMSEGAMEPLUGINS_H +#define _SKYRIMSEGAMEPLUGINS_H + + +#include +#include +#include +#include + + +class SkyrimSEGamePlugins : public GamebryoGamePlugins +{ +public: + SkyrimSEGamePlugins(MOBase::IOrganizer *organizer); + +protected: + virtual void writePluginList(const MOBase::IPluginList *pluginList, + const QString &filePath) override; + virtual bool readPluginList(MOBase::IPluginList *pluginList, + const QString &filePath, + bool useLoadOrder) override; + +private: + std::map m_LastSaveHash; +}; + +#endif // _SKYRIMSEGAMEPLUGINS_H diff --git a/src/games/skyrimse/src/skyrimsesavegame.cpp b/src/games/skyrimse/src/skyrimsesavegame.cpp new file mode 100644 index 00000000..d96b9d2c --- /dev/null +++ b/src/games/skyrimse/src/skyrimsesavegame.cpp @@ -0,0 +1,43 @@ +#include "skyrimSEsavegame.h" + +#include + +SkyrimSESaveGame::SkyrimSESaveGame(QString const &fileName, MOBase::IPluginGame const *game) : + GamebryoSaveGame(fileName, game) +{ + FileWrapper file(this, "TESV_SAVEGAME"); //10bytes + file.skip(); // header size "TESV_SAVEGAME" + file.skip(); // header version 74. Original Skyrim is 79 + file.read(m_SaveNumber); + + file.read(m_PCName); + + unsigned long temp; + file.read(temp); + m_PCLevel = static_cast(temp); + + file.read(m_PCLocation); + + QString timeOfDay; + file.read(timeOfDay); + + QString race; + file.read(race); // race name (i.e. BretonRace) + + file.skip(); // Player gender (0 = male) + file.skip(2); // experience gathered, experience required + + FILETIME ftime; + file.read(ftime); //filetime + //A file time is a 64-bit value that represents the number of 100-nanosecond + //intervals that have elapsed since 12:00 A.M. January 1, 1601 Coordinated Universal Time (UTC). + //So we need to convert that to something useful + SYSTEMTIME ctime; + ::FileTimeToSystemTime(&ftime, &ctime); + + setCreationTime(ctime); + file.readImage(320, true); //format has changed 320 px(?) 8888BGRX (24bit + 8bit alpha) px format BGR (flipped) + file.skip(); // form version + file.skip(); // plugin info size + file.readPlugins(); +} diff --git a/src/games/skyrimse/src/skyrimsesavegame.h b/src/games/skyrimse/src/skyrimsesavegame.h new file mode 100644 index 00000000..79e78657 --- /dev/null +++ b/src/games/skyrimse/src/skyrimsesavegame.h @@ -0,0 +1,14 @@ +#ifndef _SKYRIMSESAVEGAME_H +#define _SKYRIMSESAVEGAME_H + +#include "gamebryosavegame.h" + +namespace MOBase { class IPluginGame; } + +class SkyrimSESaveGame : public GamebryoSaveGame +{ +public: + SkyrimSESaveGame(QString const &fileName, MOBase::IPluginGame const *game); +}; + +#endif // _SKYRIMSESAVEGAME_H diff --git a/src/games/skyrimse/src/skyrimsesavegameinfo.cpp b/src/games/skyrimse/src/skyrimsesavegameinfo.cpp new file mode 100644 index 00000000..c5339c07 --- /dev/null +++ b/src/games/skyrimse/src/skyrimsesavegameinfo.cpp @@ -0,0 +1,19 @@ +#include "skyrimSEsavegameinfo.h" + +#include "skyrimSEsavegame.h" +#include "gamegamebryo.h" + +SkyrimSESaveGameInfo::SkyrimSESaveGameInfo(GameGamebryo const *game) : + GamebryoSaveGameInfo(game) +{ +} + +SkyrimSESaveGameInfo::~SkyrimSESaveGameInfo() +{ +} + +const MOBase::ISaveGame *SkyrimSESaveGameInfo::getSaveGameInfo(const QString &file) const +{ + return new SkyrimSESaveGame(file, m_Game); +} + diff --git a/src/games/skyrimse/src/skyrimsesavegameinfo.h b/src/games/skyrimse/src/skyrimsesavegameinfo.h new file mode 100644 index 00000000..c1a8fe3f --- /dev/null +++ b/src/games/skyrimse/src/skyrimsesavegameinfo.h @@ -0,0 +1,17 @@ +#ifndef _SKYRIMSAVEGAMEINFO_H +#define _SKYRIMSAVEGAMEINFO_H + +#include "gamebryosavegameinfo.h" + +class GameGamebryo; + +class SkyrimSESaveGameInfo : public GamebryoSaveGameInfo +{ +public: + SkyrimSESaveGameInfo(GameGamebryo const *game); + ~SkyrimSESaveGameInfo(); + + virtual MOBase::ISaveGame const *getSaveGameInfo(QString const &file) const override; +}; + +#endif // _SKYRIMSAVEGAMEINFO_H diff --git a/src/games/skyrimse/src/skyrimsescriptextender.cpp b/src/games/skyrimse/src/skyrimsescriptextender.cpp new file mode 100644 index 00000000..d2e9b586 --- /dev/null +++ b/src/games/skyrimse/src/skyrimsescriptextender.cpp @@ -0,0 +1,19 @@ +#include "skyrimSEscriptextender.h" + +#include +#include + +SkyrimSEScriptExtender::SkyrimSEScriptExtender(GameGamebryo const *game) : + GamebryoScriptExtender(game) +{ +} + +QString SkyrimSEScriptExtender::name() const +{ + return "sksese"; +} + +QStringList SkyrimSEScriptExtender::saveGameAttachmentExtensions() const +{ + return { }; +} diff --git a/src/games/skyrimse/src/skyrimsescriptextender.h b/src/games/skyrimse/src/skyrimsescriptextender.h new file mode 100644 index 00000000..5a338184 --- /dev/null +++ b/src/games/skyrimse/src/skyrimsescriptextender.h @@ -0,0 +1,19 @@ +#ifndef _SKYRIMSESCRIPTEXTENDER_H +#define _SKYRIMSESCRIPTEXTENDER_H + +#include "gamebryoscriptextender.h" + +class GameGamebryo; + +class SkyrimSEScriptExtender : public GamebryoScriptExtender +{ +public: + SkyrimSEScriptExtender(GameGamebryo const *game); + + virtual QString name() const override; + + virtual QStringList saveGameAttachmentExtensions() const override; + +}; + +#endif // _SKYRIMSESCRIPTEXTENDER_H diff --git a/src/games/skyrimse/src/skyrimseunmanagedmods.cpp b/src/games/skyrimse/src/skyrimseunmanagedmods.cpp new file mode 100644 index 00000000..be6d4b72 --- /dev/null +++ b/src/games/skyrimse/src/skyrimseunmanagedmods.cpp @@ -0,0 +1,34 @@ +#include "skyrimSEunmanagedmods.h" + + +SkyrimSEUnmangedMods::SkyrimSEUnmangedMods(const GameGamebryo *game) + : GamebryoUnmangedMods(game) +{} + +SkyrimSEUnmangedMods::~SkyrimSEUnmangedMods() +{} + + +//not necessary TODO: Remove +QStringList SkyrimSEUnmangedMods::secondaryFiles(const QString &modName) const { + QStringList archives; + QDir dataDir = game()->dataDirectory(); + for (const QString &archiveName : dataDir.entryList({modName + "*.bsa"})) { + archives.append(dataDir.absoluteFilePath(archiveName)); + } + return archives; +} +// not necessary TOOD: remove +QString SkyrimSEUnmangedMods::displayName(const QString &modName) const +{ + if (modName.compare("hearthfires", Qt::CaseInsensitive) == 0) + { + return "Hearthfire"; + } + else + { + return modName; + } + +} + diff --git a/src/games/skyrimse/src/skyrimseunmanagedmods.h b/src/games/skyrimse/src/skyrimseunmanagedmods.h new file mode 100644 index 00000000..a39f6c87 --- /dev/null +++ b/src/games/skyrimse/src/skyrimseunmanagedmods.h @@ -0,0 +1,20 @@ +#ifndef _SKYRIMSEUNMANAGEDMODS_H +#define _SKYRIMSEUNMANAGEDMODS_H + + +#include "gamebryounmanagedmods.h" +#include + + +class SkyrimSEUnmangedMods : public GamebryoUnmangedMods { +public: + SkyrimSEUnmangedMods(const GameGamebryo *game); + ~SkyrimSEUnmangedMods(); + + virtual QStringList secondaryFiles(const QString &modName) const override; + virtual QString displayName(const QString &modName) const override; +}; + + + +#endif // _SKYRIMSEUNMANAGEDMODS_H From b4b011e2e3fa9aeb4b77863b149fa047edad7822 Mon Sep 17 00:00:00 2001 From: Brian Munro Date: Sat, 26 Nov 2016 16:30:07 +0200 Subject: [PATCH 0266/1544] [game_skyrimse] Updated cmakelist to work with umbrella build system. --- src/games/skyrimse/CMakeLists.txt | 2 +- src/games/skyrimse/src/CMakeLists.txt | 17 +++++++++-------- 2 files changed, 10 insertions(+), 9 deletions(-) diff --git a/src/games/skyrimse/CMakeLists.txt b/src/games/skyrimse/CMakeLists.txt index 4cbb9dbe..5cd411b9 100644 --- a/src/games/skyrimse/CMakeLists.txt +++ b/src/games/skyrimse/CMakeLists.txt @@ -1,4 +1,4 @@ -#CMAKE_MINIMUM_REQUIRED(VERSION 2.8) +CMAKE_MINIMUM_REQUIRED(VERSION 2.8) SET(PROJ_NAME game_skyrimse) diff --git a/src/games/skyrimse/src/CMakeLists.txt b/src/games/skyrimse/src/CMakeLists.txt index c01ddda8..cd5a5946 100644 --- a/src/games/skyrimse/src/CMakeLists.txt +++ b/src/games/skyrimse/src/CMakeLists.txt @@ -6,6 +6,7 @@ FILE(GLOB ${PROJ_NAME}_SRCS *.cpp) FILE(GLOB ${PROJ_NAME}_HDRS *.h) FILE(GLOB ${PROJ_NAME}_FORMS *.ui) + SET(CMAKE_INCLUDE_CURRENT_DIR ON) SET(CMAKE_AUTOMOC ON) SET(CMAKE_AUTOUIC ON) @@ -29,20 +30,21 @@ GET_FILENAME_COMPONENT(${default_project_path} ${default_project_path} REALPATH) SET(project_path "${default_project_path}" CACHE PATH "path to the other mo projects") SET(lib_path "${project_path}/../../install/libs") -INCLUDE_DIRECTORIES(${project_path}/../modorganizer-uibase/src - ${project_path}/../modorganizer-game_features/src - ${project_path}/../modorganizer-game_gamebryo/src) -LINK_DIRECTORIES(${project_path}/lib +INCLUDE_DIRECTORIES(${project_path}/uibase/src + ${project_path}/game_features/src + ${project_path}/game_gamebryo/src) +LINK_DIRECTORIES(${project_path}/uibase/build/src ${lib_path}) +ADD_DEFINITIONS(-DUNICODE -D_UNICODE) -ADD_LIBRARY(${PROJ_NAME} SHARED ${${PROJ_NAME}_HDRS} ${${PROJ_NAME}_SRCS} ${${PROJ_NAME}_UIHDRS} ${${PROJ_NAME}_RCCPPS} ${${PROJ_NAME}_translations_qm}) +ADD_LIBRARY(${PROJ_NAME} SHARED ${${PROJ_NAME}_HDRS} ${${PROJ_NAME}_SRCS} ${${PROJ_NAME}_UIHDRS} ${${PROJ_NAME}_translations_qm}) TARGET_LINK_LIBRARIES(${PROJ_NAME} Qt5::Widgets ${Boost_LIBRARIES} uibase - Version - game_gamebryo) + game_gamebryo + version) IF(MSVC) SET_TARGET_PROPERTIES(${PROJ_NAME} PROPERTIES LINK_FLAGS "/LARGEADDRESSAWARE") @@ -59,7 +61,6 @@ ENDIF() QT5_USE_MODULES(${PROJ_NAME} Widgets) - ############### ## Installation From 94582c690e851afd2454b05583653986eb31072a Mon Sep 17 00:00:00 2001 From: lepresidente Date: Sun, 4 Dec 2016 17:56:56 +0200 Subject: [PATCH 0267/1544] [game_skyrimse] API change where Nexus Name is unique. --- src/games/skyrimse/src/gameskyrimse.cpp | 6 ++++++ src/games/skyrimse/src/gameskyrimse.h | 1 + 2 files changed, 7 insertions(+) diff --git a/src/games/skyrimse/src/gameskyrimse.cpp b/src/games/skyrimse/src/gameskyrimse.cpp index 65ff444c..7373798b 100644 --- a/src/games/skyrimse/src/gameskyrimse.cpp +++ b/src/games/skyrimse/src/gameskyrimse.cpp @@ -274,6 +274,12 @@ QString GameSkyrimSE::gameShortName() const return "SkyrimSE"; } +QString GameSkyrimSE::gameNexusName() const +{ + return "skyrimspecialedition"; +} + + QStringList GameSkyrimSE::iniFiles() const { return{ "skyrim.ini", "skyrimprefs.ini" }; diff --git a/src/games/skyrimse/src/gameskyrimse.h b/src/games/skyrimse/src/gameskyrimse.h index c2a9d105..fd9b1afe 100644 --- a/src/games/skyrimse/src/gameskyrimse.h +++ b/src/games/skyrimse/src/gameskyrimse.h @@ -30,6 +30,7 @@ public: // IPluginGame interface virtual QStringList primaryPlugins() const override; virtual QStringList gameVariants() const override; virtual QString gameShortName() const override; + virtual QString gameNexusName() const override; virtual QStringList iniFiles() const override; virtual QStringList DLCPlugins() const override; virtual LoadOrderMechanism loadOrderMechanism() const override; From 9fb688e077d20ffe26e2792510e7145425cee356 Mon Sep 17 00:00:00 2001 From: lepresidente Date: Sun, 4 Dec 2016 17:57:27 +0200 Subject: [PATCH 0268/1544] [game_oblivion] API change where Nexus Name is unique. --- src/games/oblivion/src/gameoblivion.cpp | 6 ++++++ src/games/oblivion/src/gameoblivion.h | 1 + 2 files changed, 7 insertions(+) diff --git a/src/games/oblivion/src/gameoblivion.cpp b/src/games/oblivion/src/gameoblivion.cpp index ddc67856..fc9cb354 100644 --- a/src/games/oblivion/src/gameoblivion.cpp +++ b/src/games/oblivion/src/gameoblivion.cpp @@ -125,6 +125,12 @@ QString GameOblivion::gameShortName() const return "Oblivion"; } +QString GameOblivion::gameNexusName() const +{ + return "Oblivion"; +} + + QStringList GameOblivion::iniFiles() const { return { "oblivion.ini", "oblivionprefs.ini" }; diff --git a/src/games/oblivion/src/gameoblivion.h b/src/games/oblivion/src/gameoblivion.h index 4ddf0712..91b08be5 100644 --- a/src/games/oblivion/src/gameoblivion.h +++ b/src/games/oblivion/src/gameoblivion.h @@ -26,6 +26,7 @@ public: // IPluginGame interface virtual QString steamAPPId() const override; virtual QStringList primaryPlugins() const override; virtual QString gameShortName() const override; + virtual QString gameNexusName() const override; virtual QStringList iniFiles() const override; virtual QStringList DLCPlugins() const override; virtual int nexusModOrganizerID() const override; From 96f699e5eb6a4050221f02b753ee4bcac0e279a3 Mon Sep 17 00:00:00 2001 From: lepresidente Date: Sun, 4 Dec 2016 17:57:37 +0200 Subject: [PATCH 0269/1544] [game_falloutnv] API change where Nexus Name is unique. --- src/games/falloutnv/src/gamefalloutnv.cpp | 5 +++++ src/games/falloutnv/src/gamefalloutnv.h | 1 + 2 files changed, 6 insertions(+) diff --git a/src/games/falloutnv/src/gamefalloutnv.cpp b/src/games/falloutnv/src/gamefalloutnv.cpp index 658b9490..d1f37b3e 100644 --- a/src/games/falloutnv/src/gamefalloutnv.cpp +++ b/src/games/falloutnv/src/gamefalloutnv.cpp @@ -130,6 +130,11 @@ QString GameFalloutNV::gameShortName() const return "FalloutNV"; } +QString GameFalloutNV::gameNexusName() const +{ + return "FalloutNV"; +} + QStringList GameFalloutNV::iniFiles() const { return { "fallout.ini", "falloutprefs.ini" }; diff --git a/src/games/falloutnv/src/gamefalloutnv.h b/src/games/falloutnv/src/gamefalloutnv.h index 4ba4f870..e53bfd51 100644 --- a/src/games/falloutnv/src/gamefalloutnv.h +++ b/src/games/falloutnv/src/gamefalloutnv.h @@ -28,6 +28,7 @@ public: // IPluginGame interface virtual QString steamAPPId() const override; virtual QStringList primaryPlugins() const override; virtual QString gameShortName() const override; + virtual QString gameNexusName() const override; virtual QStringList iniFiles() const override; virtual QStringList DLCPlugins() const override; virtual int nexusModOrganizerID() const override; From eafb0b27860128412defa2e1eb1e26d996d7be1f Mon Sep 17 00:00:00 2001 From: lepresidente Date: Sun, 4 Dec 2016 17:57:46 +0200 Subject: [PATCH 0270/1544] [game_fallout4vr] API change where Nexus Name is unique. --- src/games/fallout4vr/src/gamefallout4.cpp | 5 +++++ src/games/fallout4vr/src/gamefallout4.h | 1 + 2 files changed, 6 insertions(+) diff --git a/src/games/fallout4vr/src/gamefallout4.cpp b/src/games/fallout4vr/src/gamefallout4.cpp index a21261fe..6958c4ae 100644 --- a/src/games/fallout4vr/src/gamefallout4.cpp +++ b/src/games/fallout4vr/src/gamefallout4.cpp @@ -135,6 +135,11 @@ QString GameFallout4::gameShortName() const return "Fallout4"; } +QString GameFallout4::gameNexusName() const +{ + return "Fallout4"; +} + QStringList GameFallout4::iniFiles() const { return { "fallout4.ini", "fallout4prefs.ini" }; diff --git a/src/games/fallout4vr/src/gamefallout4.h b/src/games/fallout4vr/src/gamefallout4.h index ca59561d..655bc197 100644 --- a/src/games/fallout4vr/src/gamefallout4.h +++ b/src/games/fallout4vr/src/gamefallout4.h @@ -29,6 +29,7 @@ public: // IPluginGame interface virtual QStringList primaryPlugins() const override; virtual QStringList gameVariants() const override; virtual QString gameShortName() const override; + virtual QString gameNexusName() const override; virtual QStringList iniFiles() const override; virtual QStringList DLCPlugins() const override; virtual LoadOrderMechanism loadOrderMechanism() const override; From 1f612cafce2cd5c384ac20965a7398d301136527 Mon Sep 17 00:00:00 2001 From: lepresidente Date: Sun, 4 Dec 2016 17:57:46 +0200 Subject: [PATCH 0271/1544] [game_fallout76] API change where Nexus Name is unique. --- src/games/fallout76/src/gamefallout4.cpp | 5 +++++ src/games/fallout76/src/gamefallout4.h | 1 + 2 files changed, 6 insertions(+) diff --git a/src/games/fallout76/src/gamefallout4.cpp b/src/games/fallout76/src/gamefallout4.cpp index a21261fe..6958c4ae 100644 --- a/src/games/fallout76/src/gamefallout4.cpp +++ b/src/games/fallout76/src/gamefallout4.cpp @@ -135,6 +135,11 @@ QString GameFallout4::gameShortName() const return "Fallout4"; } +QString GameFallout4::gameNexusName() const +{ + return "Fallout4"; +} + QStringList GameFallout4::iniFiles() const { return { "fallout4.ini", "fallout4prefs.ini" }; diff --git a/src/games/fallout76/src/gamefallout4.h b/src/games/fallout76/src/gamefallout4.h index ca59561d..655bc197 100644 --- a/src/games/fallout76/src/gamefallout4.h +++ b/src/games/fallout76/src/gamefallout4.h @@ -29,6 +29,7 @@ public: // IPluginGame interface virtual QStringList primaryPlugins() const override; virtual QStringList gameVariants() const override; virtual QString gameShortName() const override; + virtual QString gameNexusName() const override; virtual QStringList iniFiles() const override; virtual QStringList DLCPlugins() const override; virtual LoadOrderMechanism loadOrderMechanism() const override; From f6a45d0314b204eee1e2a57bed715ac85428b7e0 Mon Sep 17 00:00:00 2001 From: lepresidente Date: Sun, 4 Dec 2016 17:57:46 +0200 Subject: [PATCH 0272/1544] [game_fallout4] API change where Nexus Name is unique. --- src/games/fallout4/src/gamefallout4.cpp | 5 +++++ src/games/fallout4/src/gamefallout4.h | 1 + 2 files changed, 6 insertions(+) diff --git a/src/games/fallout4/src/gamefallout4.cpp b/src/games/fallout4/src/gamefallout4.cpp index a21261fe..6958c4ae 100644 --- a/src/games/fallout4/src/gamefallout4.cpp +++ b/src/games/fallout4/src/gamefallout4.cpp @@ -135,6 +135,11 @@ QString GameFallout4::gameShortName() const return "Fallout4"; } +QString GameFallout4::gameNexusName() const +{ + return "Fallout4"; +} + QStringList GameFallout4::iniFiles() const { return { "fallout4.ini", "fallout4prefs.ini" }; diff --git a/src/games/fallout4/src/gamefallout4.h b/src/games/fallout4/src/gamefallout4.h index ca59561d..655bc197 100644 --- a/src/games/fallout4/src/gamefallout4.h +++ b/src/games/fallout4/src/gamefallout4.h @@ -29,6 +29,7 @@ public: // IPluginGame interface virtual QStringList primaryPlugins() const override; virtual QStringList gameVariants() const override; virtual QString gameShortName() const override; + virtual QString gameNexusName() const override; virtual QStringList iniFiles() const override; virtual QStringList DLCPlugins() const override; virtual LoadOrderMechanism loadOrderMechanism() const override; From 089410b6b7ba4dd36ceeb8e89cf0553316731b87 Mon Sep 17 00:00:00 2001 From: lepresidente Date: Sun, 4 Dec 2016 17:57:51 +0200 Subject: [PATCH 0273/1544] [game_fallout3] API change where Nexus Name is unique. --- src/games/fallout3/src/gamefallout3.cpp | 6 ++++++ src/games/fallout3/src/gamefallout3.h | 1 + 2 files changed, 7 insertions(+) diff --git a/src/games/fallout3/src/gamefallout3.cpp b/src/games/fallout3/src/gamefallout3.cpp index cdf9bd3f..d4900d50 100644 --- a/src/games/fallout3/src/gamefallout3.cpp +++ b/src/games/fallout3/src/gamefallout3.cpp @@ -140,6 +140,12 @@ QString GameFallout3::gameShortName() const return "Fallout3"; } +QString GameFallout3::gameNexusName() const +{ + return "Fallout3"; +} + + QStringList GameFallout3::iniFiles() const { return { "fallout.ini", "falloutprefs.ini" }; diff --git a/src/games/fallout3/src/gamefallout3.h b/src/games/fallout3/src/gamefallout3.h index a59a3376..d5401582 100644 --- a/src/games/fallout3/src/gamefallout3.h +++ b/src/games/fallout3/src/gamefallout3.h @@ -27,6 +27,7 @@ public: // IPluginGame interface virtual QStringList primaryPlugins() const override; virtual QStringList gameVariants() const; virtual QString gameShortName() const override; + virtual QString gameNexusName() const override; virtual QStringList iniFiles() const override; virtual QStringList DLCPlugins() const override; virtual int nexusModOrganizerID() const override; From eecad558e2bc9cc793b978b4c3ffa46b473fd763 Mon Sep 17 00:00:00 2001 From: lepresidente Date: Sun, 4 Dec 2016 17:59:08 +0200 Subject: [PATCH 0274/1544] [game_skyrim] API change where Nexus Name is unique. --- src/games/skyrim/src/gameskyrim.cpp | 6 ++++++ src/games/skyrim/src/gameskyrim.h | 1 + 2 files changed, 7 insertions(+) diff --git a/src/games/skyrim/src/gameskyrim.cpp b/src/games/skyrim/src/gameskyrim.cpp index 58720b35..6b1c59f8 100644 --- a/src/games/skyrim/src/gameskyrim.cpp +++ b/src/games/skyrim/src/gameskyrim.cpp @@ -140,6 +140,12 @@ QString GameSkyrim::gameShortName() const return "Skyrim"; } +QString GameSkyrim::gameNexusName() const +{ + return "Skyrim"; +} + + QStringList GameSkyrim::iniFiles() const { return { "skyrim.ini", "skyrimprefs.ini" }; diff --git a/src/games/skyrim/src/gameskyrim.h b/src/games/skyrim/src/gameskyrim.h index 01ba2458..fd299550 100644 --- a/src/games/skyrim/src/gameskyrim.h +++ b/src/games/skyrim/src/gameskyrim.h @@ -29,6 +29,7 @@ public: // IPluginGame interface virtual QStringList primaryPlugins() const override; virtual QString binaryName() const override; virtual QString gameShortName() const override; + virtual QString gameNexusName() const override; virtual QStringList iniFiles() const override; virtual QStringList DLCPlugins() const override; virtual LoadOrderMechanism loadOrderMechanism() const override; From 93fc011148332faff9328ad1dbbba46f9c7e88b4 Mon Sep 17 00:00:00 2001 From: Zanoth Date: Tue, 13 Dec 2016 17:30:13 -0600 Subject: [PATCH 0275/1544] [game_skyrimse] Fixed Image colours, most of the save-time, and the plugin listing Figured out a few of the changes to the savefile, Apparently the filetime that the program reads is innacurate and about 6 hours ahead. It's now mostly correct. The Image problem occured because there was just nonsense directly before the image started, but after the dimensions. The plugins seem to start a variable number of bytes after the image ends, but I used the presence of two 0 bytes in a row to determine the location in the save to start reading the plugins. --- src/games/skyrimse/src/skyrimsesavegame.cpp | 41 +++++++++++++++++++-- 1 file changed, 38 insertions(+), 3 deletions(-) diff --git a/src/games/skyrimse/src/skyrimsesavegame.cpp b/src/games/skyrimse/src/skyrimsesavegame.cpp index d96b9d2c..eddc173d 100644 --- a/src/games/skyrimse/src/skyrimsesavegame.cpp +++ b/src/games/skyrimse/src/skyrimsesavegame.cpp @@ -32,12 +32,47 @@ SkyrimSESaveGame::SkyrimSESaveGame(QString const &fileName, MOBase::IPluginGame //A file time is a 64-bit value that represents the number of 100-nanosecond //intervals that have elapsed since 12:00 A.M. January 1, 1601 Coordinated Universal Time (UTC). //So we need to convert that to something useful + + //For some reason, the file time is off by about 6 hours. + //So we need to subtract those 6 hours from the filetime. + _ULARGE_INTEGER time; + time.LowPart=ftime.dwLowDateTime; + time.HighPart=ftime.dwHighDateTime; + time.QuadPart-=2.16e11; + ftime.dwHighDateTime=time.HighPart; + ftime.dwLowDateTime=time.LowPart; + SYSTEMTIME ctime; ::FileTimeToSystemTime(&ftime, &ctime); setCreationTime(ctime); - file.readImage(320, true); //format has changed 320 px(?) 8888BGRX (24bit + 8bit alpha) px format BGR (flipped) - file.skip(); // form version - file.skip(); // plugin info size + //file.skip(); + + unsigned long width; + unsigned long height; + file.read(width); + file.read(height); + + //Skip the 2 empty bytes before the image begins. + //This is why we aren't using the readImage(scale,alpha) + //variant. + file.skip(); + + file.readImage(width,height,320,true); + //file.readImage(320,true); + //file.readImage(320, 4, QImage::Format_RGBA8888, false); //format has changed 320 px(?) 8888BGRX (24bit + 8bit alpha) px format BGR (flipped) + //file.readImage(320, 192,0, 4, QImage::Format_RGBA8888, false); + + //Skip a single byte to get it to the right location + file.skip(); // form version + + //Skip 2 bytes at a time until both bytes are 0 + unsigned short testIsZero; + do{ + file.read(testIsZero); + }while(testIsZero!=0); + + //file.skip(); // plugin info size + //Now in correct location to read plugins. file.readPlugins(); } From 54a0049ec153cd01fa5301d33e5a16c7259d9cfc Mon Sep 17 00:00:00 2001 From: Zanoth Date: Tue, 13 Dec 2016 22:57:06 -0600 Subject: [PATCH 0276/1544] [game_skyrimse] Removed the call to readPlugins() due to problems Until Bethesda fixes the save files, or someone figures out how Bethesda reads them properly, We can't get the missing plugins list to work. --- src/games/skyrimse/src/skyrimsesavegame.cpp | 19 +++++++------------ 1 file changed, 7 insertions(+), 12 deletions(-) diff --git a/src/games/skyrimse/src/skyrimsesavegame.cpp b/src/games/skyrimse/src/skyrimsesavegame.cpp index eddc173d..382b0323 100644 --- a/src/games/skyrimse/src/skyrimsesavegame.cpp +++ b/src/games/skyrimse/src/skyrimsesavegame.cpp @@ -59,20 +59,15 @@ SkyrimSESaveGame::SkyrimSESaveGame(QString const &fileName, MOBase::IPluginGame file.skip(); file.readImage(width,height,320,true); - //file.readImage(320,true); - //file.readImage(320, 4, QImage::Format_RGBA8888, false); //format has changed 320 px(?) 8888BGRX (24bit + 8bit alpha) px format BGR (flipped) - //file.readImage(320, 192,0, 4, QImage::Format_RGBA8888, false); - - //Skip a single byte to get it to the right location + + //Skip reading the plugins altogether, due to problems with the save files. + m_Plugins.push_back("Not Working due to save game weirdness"); + /* //Skip a single byte to get it to the right location file.skip(); // form version - - //Skip 2 bytes at a time until both bytes are 0 - unsigned short testIsZero; - do{ - file.read(testIsZero); - }while(testIsZero!=0); + //Need to skip 14 more bytes + file.skip(7); //file.skip(); // plugin info size //Now in correct location to read plugins. - file.readPlugins(); + file.readPlugins();// */ } From 5339a40b883e2568471c0d489fccd61e917a1f3d Mon Sep 17 00:00:00 2001 From: LePresidente Date: Tue, 20 Dec 2016 03:27:16 -0800 Subject: [PATCH 0277/1544] [game_skyrimse] Version Bump, Fixed Screenshots --- src/games/skyrimse/src/gameskyrimse.cpp | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/src/games/skyrimse/src/gameskyrimse.cpp b/src/games/skyrimse/src/gameskyrimse.cpp index 7373798b..b826951c 100644 --- a/src/games/skyrimse/src/gameskyrimse.cpp +++ b/src/games/skyrimse/src/gameskyrimse.cpp @@ -207,7 +207,7 @@ QString GameSkyrimSE::name() const QString GameSkyrimSE::author() const { - return "Archost"; + return "Archost & ZachHaber"; } QString GameSkyrimSE::description() const @@ -217,7 +217,7 @@ QString GameSkyrimSE::description() const MOBase::VersionInfo GameSkyrimSE::version() const { - return VersionInfo(0, 1, 4, VersionInfo::RELEASE_ALPHA); + return VersionInfo(0, 1, 5, VersionInfo::RELEASE_ALPHA); } bool GameSkyrimSE::isActive() const @@ -261,7 +261,7 @@ QString GameSkyrimSE::steamAPPId() const } QStringList GameSkyrimSE::primaryPlugins() const { - return{ "skyrim.esm", "update.esm", };// }; + return{ "skyrim.esm", "update.esm", "dawnguard.esm", "hearthfires.esm", "dragonborn.esm" };// }; } QStringList GameSkyrimSE::gameVariants() const @@ -287,7 +287,7 @@ QStringList GameSkyrimSE::iniFiles() const QStringList GameSkyrimSE::DLCPlugins() const { - return{ "dawnguard.esm", "hearthfires.esm", "dragonborn.esm" }; + return{ "" }; } IPluginGame::LoadOrderMechanism GameSkyrimSE::loadOrderMechanism() const @@ -297,7 +297,7 @@ IPluginGame::LoadOrderMechanism GameSkyrimSE::loadOrderMechanism() const int GameSkyrimSE::nexusModOrganizerID() const { - return 1704; //... Should be 0? + return 6194; //... Should be 0? } int GameSkyrimSE::nexusGameID() const From d00f6a507ad52aac703d4dab50212fd70d3dbe55 Mon Sep 17 00:00:00 2001 From: ZachHaber Date: Sun, 25 Dec 2016 18:14:09 -0600 Subject: [PATCH 0278/1544] First Attempt at reading plugins with lz4 compression Since no one has seen a savefile with zlib compression, I am ignoring that until someone does, so I can actually view the save file to determine if it works. I'm not using the stream functionality of lz4 decompression currently due to that being rather confusing. It also isn't too slow to do it this way. --- CMakeLists.txt | 2 ++ src/CMakeLists.txt | 5 +++- src/gamebryosavegame.cpp | 57 +++++++++++++++++++++++++++++++++++----- src/gamebryosavegame.h | 3 ++- 4 files changed, 58 insertions(+), 9 deletions(-) diff --git a/CMakeLists.txt b/CMakeLists.txt index 9e986c42..cc5453b8 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -8,6 +8,8 @@ SET(DEPENDENCIES_DIR CACHE PATH "") # hint to find qt in dependencies path LIST(APPEND CMAKE_PREFIX_PATH ${DEPENDENCIES_DIR}/qt5/lib/cmake) +LIST(APPEND CMAKE_PREFIX_PATH ${DEPENDENCIES_DIR}/lz4/dll) + FILE(GLOB_RECURSE BOOST_ROOT ${DEPENDENCIES_DIR}/boost*/project-config.jam) GET_FILENAME_COMPONENT(BOOST_ROOT ${BOOST_ROOT} DIRECTORY) diff --git a/src/CMakeLists.txt b/src/CMakeLists.txt index 3b667be4..f83f669d 100644 --- a/src/CMakeLists.txt +++ b/src/CMakeLists.txt @@ -32,13 +32,16 @@ SET(plugin_path "${project_path}") INCLUDE_DIRECTORIES(${project_path}/uibase/src ${project_path}/game_features/src) -LINK_DIRECTORIES(${lib_path}) + ${project_path}/../lz4/include) +LINK_DIRECTORIES(${lib_path} + ${project_path}/../lz4/dll) ADD_LIBRARY(${PROJ_NAME} STATIC ${${PROJ_NAME}_HDRS} ${${PROJ_NAME}_SRCS} ${${PROJ_NAME}_UIHDRS}) TARGET_LINK_LIBRARIES(${PROJ_NAME} Qt5::Widgets ${Boost_LIBRARIES} uibase + liblz4 Version) IF(MSVC) diff --git a/src/gamebryosavegame.cpp b/src/gamebryosavegame.cpp index 7f8f3c88..681d49a8 100644 --- a/src/gamebryosavegame.cpp +++ b/src/gamebryosavegame.cpp @@ -10,6 +10,7 @@ #include #include +#include #include #include @@ -158,13 +159,55 @@ void GamebryoSaveGame::FileWrapper::readImage(unsigned long width, unsigned long } } -void GamebryoSaveGame::FileWrapper::readPlugins() +void GamebryoSaveGame::FileWrapper::readPlugins(int bytesToIgnore) { - unsigned char count; - read(count); - for (std::size_t i = 0; i < count; ++i) { - QString name; - read(name); - m_Game->m_Plugins.push_back(name); + if(compressionType==0){ + if(bytesToIgnore>0)//Just to make certain + skip(bytesToIgnore); + unsigned char count; + read(count); + m_Game->m_Plugins.reserve(count); + for (std::size_t i = 0; i < count; ++i) { + QString name; + read(name); + m_Game->m_Plugins.push_back(name); + } + }else if(compressionType==1){ + m_Game->m_Plugins.push_back("Please create an issue on the MO github labeled \"Found zlib Compressed\" with your savefile attached"); + }else if(compressionType==2){ + unsigned long maxUncompressedSize; + read(maxUncompressedSize); + unsigned long compressedSize; + read(compressedSize); + char* compressed=new char[compressedSize]; + read(compressed,compressedSize); + + //Using this maxPluginSize (2 byte limit on the length in bytes of the plugin names, with those same 2 bytes added in + //and there is a maximum of 255 or so plugins possible with an extra 5 bytes from the empty space.) + //to decrease the amount of data that has to be read in each savefile. Total is 16711940 (it wouldn't let me write it out in + //an equation + + //unsigned long uncompressedSize=(65537)*255+5‬; + unsigned long uncompressedSize=16711940; + char * decompressed=new char[uncompressedSize]; + LZ4_decompress_safe_partial(compressed,decompressed,compressedSize,uncompressedSize,maxUncompressedSize); + delete[] compressed; + + QDataStream data(QByteArray(decompressed,uncompressedSize)); + delete[] decompressed; + data.skipRawData(bytesToIgnore); + + //unsigned long loc=7; + //unsigned char count=decompressed[loc++]; + unsigned char count; + read(data,count); + //data.read(reinterpret_cast(&count),sizeof(count)); + m_Game->m_Plugins.reserve(count); + for(std::size_t i=0;im_Plugins.push_back(name); + } + } } diff --git a/src/gamebryosavegame.h b/src/gamebryosavegame.h index 7d103419..30515854 100644 --- a/src/gamebryosavegame.h +++ b/src/gamebryosavegame.h @@ -89,7 +89,7 @@ protected: void readImage(unsigned long width, unsigned long height, int scale = 0, bool alpha = false); /* Read the plugin list */ - void readPlugins(); + void readPlugins(int bytesToIgnore=0); /* Set the creation time from a system date */ void setCreationTime(::_SYSTEMTIME const &); @@ -112,6 +112,7 @@ protected: QStringList m_Plugins; QImage m_Screenshot; MOBase::IPluginGame const *m_Game; + unsigned short compressionType; }; template <> void GamebryoSaveGame::FileWrapper::read(QString &); From 10baa07746f940c4843301a36064e53b4f30f04d Mon Sep 17 00:00:00 2001 From: ZachHaber Date: Sun, 25 Dec 2016 18:26:23 -0600 Subject: [PATCH 0279/1544] [game_skyrimse] Reading Plugins Using changes to Gamebryo " --- src/games/skyrimse/src/skyrimsesavegame.cpp | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/src/games/skyrimse/src/skyrimsesavegame.cpp b/src/games/skyrimse/src/skyrimsesavegame.cpp index 382b0323..29050cba 100644 --- a/src/games/skyrimse/src/skyrimsesavegame.cpp +++ b/src/games/skyrimse/src/skyrimsesavegame.cpp @@ -56,18 +56,19 @@ SkyrimSESaveGame::SkyrimSESaveGame(QString const &fileName, MOBase::IPluginGame //Skip the 2 empty bytes before the image begins. //This is why we aren't using the readImage(scale,alpha) //variant. - file.skip(); + //file.skip(); + file.read(compressionType); file.readImage(width,height,320,true); //Skip reading the plugins altogether, due to problems with the save files. - m_Plugins.push_back("Not Working due to save game weirdness"); + //m_Plugins.push_back("Not Working due to save game weirdness"); /* //Skip a single byte to get it to the right location file.skip(); // form version //Need to skip 14 more bytes file.skip(7); - //file.skip(); // plugin info size //Now in correct location to read plugins. file.readPlugins();// */ + file.readPlugins(5); } From 4e2d460342e36711afebe9b6eb45d11e09fe531d Mon Sep 17 00:00:00 2001 From: ZachHaber Date: Tue, 27 Dec 2016 15:19:42 -0600 Subject: [PATCH 0280/1544] [game_fallout3] Support Changes to gamebryo Add lz4 library linkage --- src/games/fallout3/CMakeLists.txt | 1 + src/games/fallout3/src/CMakeLists.txt | 4 +++- 2 files changed, 4 insertions(+), 1 deletion(-) diff --git a/src/games/fallout3/CMakeLists.txt b/src/games/fallout3/CMakeLists.txt index 148045e3..50472868 100644 --- a/src/games/fallout3/CMakeLists.txt +++ b/src/games/fallout3/CMakeLists.txt @@ -8,6 +8,7 @@ SET(DEPENDENCIES_DIR CACHE PATH "") # hint to find qt in dependencies path LIST(APPEND CMAKE_PREFIX_PATH ${DEPENDENCIES_DIR}/qt5/lib/cmake) +LIST(APPEND CMAKE_PREFIX_PATH ${DEPENDENCIES_DIR}/lz4/dll) FILE(GLOB_RECURSE BOOST_ROOT ${DEPENDENCIES_DIR}/boost*/project-config.jam) GET_FILENAME_COMPONENT(BOOST_ROOT ${BOOST_ROOT} DIRECTORY) diff --git a/src/games/fallout3/src/CMakeLists.txt b/src/games/fallout3/src/CMakeLists.txt index b251bd6f..3cd43312 100644 --- a/src/games/fallout3/src/CMakeLists.txt +++ b/src/games/fallout3/src/CMakeLists.txt @@ -34,7 +34,8 @@ INCLUDE_DIRECTORIES(${project_path}/uibase/src ${project_path}/game_features/src ${project_path}/game_gamebryo/src) LINK_DIRECTORIES(${project_path}/uibase/build/src - ${lib_path}) + ${lib_path} + ${project_path}/../lz4/dll) ADD_LIBRARY(${PROJ_NAME} SHARED ${${PROJ_NAME}_HDRS} ${${PROJ_NAME}_SRCS} ${${PROJ_NAME}_UIHDRS} ${${PROJ_NAME}_translations_qm}) @@ -43,6 +44,7 @@ TARGET_LINK_LIBRARIES(${PROJ_NAME} ${Boost_LIBRARIES} uibase game_gamebryo + liblz4 Version) IF(MSVC) From 8b10212c97a05f51d61b7ce594a1b3a08edd66d4 Mon Sep 17 00:00:00 2001 From: ZachHaber Date: Tue, 27 Dec 2016 15:21:00 -0600 Subject: [PATCH 0281/1544] [game_fallout4vr] Support changes to Gambryo Adds lz4 linkage --- src/games/fallout4vr/CMakeLists.txt | 1 + src/games/fallout4vr/src/CMakeLists.txt | 4 +++- 2 files changed, 4 insertions(+), 1 deletion(-) diff --git a/src/games/fallout4vr/CMakeLists.txt b/src/games/fallout4vr/CMakeLists.txt index 59c4d455..a7c88e3b 100644 --- a/src/games/fallout4vr/CMakeLists.txt +++ b/src/games/fallout4vr/CMakeLists.txt @@ -8,6 +8,7 @@ SET(DEPENDENCIES_DIR CACHE PATH "") # hint to find qt in dependencies path LIST(APPEND CMAKE_PREFIX_PATH ${DEPENDENCIES_DIR}/qt5/lib/cmake) +LIST(APPEND CMAKE_PREFIX_PATH ${DEPENDENCIES_DIR}/lz4/dll) FILE(GLOB_RECURSE BOOST_ROOT ${DEPENDENCIES_DIR}/boost*/project-config.jam) GET_FILENAME_COMPONENT(BOOST_ROOT ${BOOST_ROOT} DIRECTORY) diff --git a/src/games/fallout4vr/src/CMakeLists.txt b/src/games/fallout4vr/src/CMakeLists.txt index 7d3c4a88..9d978382 100644 --- a/src/games/fallout4vr/src/CMakeLists.txt +++ b/src/games/fallout4vr/src/CMakeLists.txt @@ -38,7 +38,8 @@ INCLUDE_DIRECTORIES(${project_path}/uibase/src ${project_path}/game_features/src ${project_path}/game_gamebryo/src) LINK_DIRECTORIES(${project_path}/uibase/build/src - ${lib_path}) + ${lib_path} + ${project_path}/../lz4/dll) ADD_LIBRARY(${PROJ_NAME} SHARED ${${PROJ_NAME}_HDRS} ${${PROJ_NAME}_SRCS} ${${PROJ_NAME}_UIHDRS} ${${PROJ_NAME}_RCCPPS} ${${PROJ_NAME}_translations_qm}) @@ -47,6 +48,7 @@ TARGET_LINK_LIBRARIES(${PROJ_NAME} ${Boost_LIBRARIES} uibase Version + liblz4 game_gamebryo) IF(MSVC) From c9ecc5c15aa8e4a58e68978b3f2dbc8ac84ff186 Mon Sep 17 00:00:00 2001 From: ZachHaber Date: Tue, 27 Dec 2016 15:21:00 -0600 Subject: [PATCH 0282/1544] [game_fallout76] Support changes to Gambryo Adds lz4 linkage --- src/games/fallout76/CMakeLists.txt | 1 + src/games/fallout76/src/CMakeLists.txt | 4 +++- 2 files changed, 4 insertions(+), 1 deletion(-) diff --git a/src/games/fallout76/CMakeLists.txt b/src/games/fallout76/CMakeLists.txt index 59c4d455..a7c88e3b 100644 --- a/src/games/fallout76/CMakeLists.txt +++ b/src/games/fallout76/CMakeLists.txt @@ -8,6 +8,7 @@ SET(DEPENDENCIES_DIR CACHE PATH "") # hint to find qt in dependencies path LIST(APPEND CMAKE_PREFIX_PATH ${DEPENDENCIES_DIR}/qt5/lib/cmake) +LIST(APPEND CMAKE_PREFIX_PATH ${DEPENDENCIES_DIR}/lz4/dll) FILE(GLOB_RECURSE BOOST_ROOT ${DEPENDENCIES_DIR}/boost*/project-config.jam) GET_FILENAME_COMPONENT(BOOST_ROOT ${BOOST_ROOT} DIRECTORY) diff --git a/src/games/fallout76/src/CMakeLists.txt b/src/games/fallout76/src/CMakeLists.txt index 7d3c4a88..9d978382 100644 --- a/src/games/fallout76/src/CMakeLists.txt +++ b/src/games/fallout76/src/CMakeLists.txt @@ -38,7 +38,8 @@ INCLUDE_DIRECTORIES(${project_path}/uibase/src ${project_path}/game_features/src ${project_path}/game_gamebryo/src) LINK_DIRECTORIES(${project_path}/uibase/build/src - ${lib_path}) + ${lib_path} + ${project_path}/../lz4/dll) ADD_LIBRARY(${PROJ_NAME} SHARED ${${PROJ_NAME}_HDRS} ${${PROJ_NAME}_SRCS} ${${PROJ_NAME}_UIHDRS} ${${PROJ_NAME}_RCCPPS} ${${PROJ_NAME}_translations_qm}) @@ -47,6 +48,7 @@ TARGET_LINK_LIBRARIES(${PROJ_NAME} ${Boost_LIBRARIES} uibase Version + liblz4 game_gamebryo) IF(MSVC) From 3d7dc2bd720a1e0572c7abfe73cdc635a1f57350 Mon Sep 17 00:00:00 2001 From: ZachHaber Date: Tue, 27 Dec 2016 15:21:00 -0600 Subject: [PATCH 0283/1544] [game_fallout4] Support changes to Gambryo Adds lz4 linkage --- src/games/fallout4/CMakeLists.txt | 1 + src/games/fallout4/src/CMakeLists.txt | 4 +++- 2 files changed, 4 insertions(+), 1 deletion(-) diff --git a/src/games/fallout4/CMakeLists.txt b/src/games/fallout4/CMakeLists.txt index 59c4d455..a7c88e3b 100644 --- a/src/games/fallout4/CMakeLists.txt +++ b/src/games/fallout4/CMakeLists.txt @@ -8,6 +8,7 @@ SET(DEPENDENCIES_DIR CACHE PATH "") # hint to find qt in dependencies path LIST(APPEND CMAKE_PREFIX_PATH ${DEPENDENCIES_DIR}/qt5/lib/cmake) +LIST(APPEND CMAKE_PREFIX_PATH ${DEPENDENCIES_DIR}/lz4/dll) FILE(GLOB_RECURSE BOOST_ROOT ${DEPENDENCIES_DIR}/boost*/project-config.jam) GET_FILENAME_COMPONENT(BOOST_ROOT ${BOOST_ROOT} DIRECTORY) diff --git a/src/games/fallout4/src/CMakeLists.txt b/src/games/fallout4/src/CMakeLists.txt index 7d3c4a88..9d978382 100644 --- a/src/games/fallout4/src/CMakeLists.txt +++ b/src/games/fallout4/src/CMakeLists.txt @@ -38,7 +38,8 @@ INCLUDE_DIRECTORIES(${project_path}/uibase/src ${project_path}/game_features/src ${project_path}/game_gamebryo/src) LINK_DIRECTORIES(${project_path}/uibase/build/src - ${lib_path}) + ${lib_path} + ${project_path}/../lz4/dll) ADD_LIBRARY(${PROJ_NAME} SHARED ${${PROJ_NAME}_HDRS} ${${PROJ_NAME}_SRCS} ${${PROJ_NAME}_UIHDRS} ${${PROJ_NAME}_RCCPPS} ${${PROJ_NAME}_translations_qm}) @@ -47,6 +48,7 @@ TARGET_LINK_LIBRARIES(${PROJ_NAME} ${Boost_LIBRARIES} uibase Version + liblz4 game_gamebryo) IF(MSVC) From e1fa13915ac649ce8e6ea511fc9998ab9293aecb Mon Sep 17 00:00:00 2001 From: ZachHaber Date: Tue, 27 Dec 2016 15:21:39 -0600 Subject: [PATCH 0284/1544] [game_falloutnv] Support changes to Gambryo Adds lz4 linkage --- src/games/falloutnv/CMakeLists.txt | 2 ++ src/games/falloutnv/src/CMakeLists.txt | 4 +++- 2 files changed, 5 insertions(+), 1 deletion(-) diff --git a/src/games/falloutnv/CMakeLists.txt b/src/games/falloutnv/CMakeLists.txt index eafe54e4..6a9e25f6 100644 --- a/src/games/falloutnv/CMakeLists.txt +++ b/src/games/falloutnv/CMakeLists.txt @@ -9,6 +9,8 @@ SET(DEPENDENCIES_DIR CACHE PATH "") # hint to find qt in dependencies path LIST(APPEND CMAKE_PREFIX_PATH ${DEPENDENCIES_DIR}/qt5/lib/cmake) +LIST(APPEND CMAKE_PREFIX_PATH ${DEPENDENCIES_DIR}/lz4/dll) + FILE(GLOB_RECURSE BOOST_ROOT ${DEPENDENCIES_DIR}/boost*/project-config.jam) GET_FILENAME_COMPONENT(BOOST_ROOT ${BOOST_ROOT} DIRECTORY) diff --git a/src/games/falloutnv/src/CMakeLists.txt b/src/games/falloutnv/src/CMakeLists.txt index b251bd6f..3cd43312 100644 --- a/src/games/falloutnv/src/CMakeLists.txt +++ b/src/games/falloutnv/src/CMakeLists.txt @@ -34,7 +34,8 @@ INCLUDE_DIRECTORIES(${project_path}/uibase/src ${project_path}/game_features/src ${project_path}/game_gamebryo/src) LINK_DIRECTORIES(${project_path}/uibase/build/src - ${lib_path}) + ${lib_path} + ${project_path}/../lz4/dll) ADD_LIBRARY(${PROJ_NAME} SHARED ${${PROJ_NAME}_HDRS} ${${PROJ_NAME}_SRCS} ${${PROJ_NAME}_UIHDRS} ${${PROJ_NAME}_translations_qm}) @@ -43,6 +44,7 @@ TARGET_LINK_LIBRARIES(${PROJ_NAME} ${Boost_LIBRARIES} uibase game_gamebryo + liblz4 Version) IF(MSVC) From e7a51147b47af5ab53c3cf7d29880fb4d5f96b1a Mon Sep 17 00:00:00 2001 From: ZachHaber Date: Tue, 27 Dec 2016 15:22:37 -0600 Subject: [PATCH 0285/1544] [game_oblivion] Support changes to Gambryo Add lz4 linkage --- src/games/oblivion/CMakeLists.txt | 1 + src/games/oblivion/src/CMakeLists.txt | 4 +++- 2 files changed, 4 insertions(+), 1 deletion(-) diff --git a/src/games/oblivion/CMakeLists.txt b/src/games/oblivion/CMakeLists.txt index fb17c159..bcd2bc6c 100644 --- a/src/games/oblivion/CMakeLists.txt +++ b/src/games/oblivion/CMakeLists.txt @@ -8,6 +8,7 @@ SET(DEPENDENCIES_DIR CACHE PATH "") # hint to find qt in dependencies path LIST(APPEND CMAKE_PREFIX_PATH ${DEPENDENCIES_DIR}/qt5/lib/cmake) +LIST(APPEND CMAKE_PREFIX_PATH ${DEPENDENCIES_DIR}/lz4/dll) FILE(GLOB_RECURSE BOOST_ROOT ${DEPENDENCIES_DIR}/boost*/project-config.jam) GET_FILENAME_COMPONENT(BOOST_ROOT ${BOOST_ROOT} DIRECTORY) diff --git a/src/games/oblivion/src/CMakeLists.txt b/src/games/oblivion/src/CMakeLists.txt index 79288345..2aac741b 100644 --- a/src/games/oblivion/src/CMakeLists.txt +++ b/src/games/oblivion/src/CMakeLists.txt @@ -34,7 +34,8 @@ INCLUDE_DIRECTORIES(${project_path}/uibase/src ${project_path}/game_features/src ${project_path}/game_gamebryo/src) LINK_DIRECTORIES(${project_path}/uibase/build/src - ${lib_path}) + ${lib_path} + ${project_path}/../lz4/dll) ADD_LIBRARY(${PROJ_NAME} SHARED ${${PROJ_NAME}_HDRS} ${${PROJ_NAME}_SRCS} ${${PROJ_NAME}_UIHDRS} ${${PROJ_NAME}_translations_qm}) @@ -43,6 +44,7 @@ TARGET_LINK_LIBRARIES(${PROJ_NAME} ${Boost_LIBRARIES} uibase game_gamebryo + liblz4 version) IF(MSVC) From 09ea1ed480ef6616087b0bb7926cbf17cea201b6 Mon Sep 17 00:00:00 2001 From: ZachHaber Date: Tue, 27 Dec 2016 15:23:15 -0600 Subject: [PATCH 0286/1544] [game_skyrim] Support changes to Gamebryo Adds lz4 linkage --- src/games/skyrim/CMakeLists.txt | 1 + src/games/skyrim/src/CMakeLists.txt | 4 +++- 2 files changed, 4 insertions(+), 1 deletion(-) diff --git a/src/games/skyrim/CMakeLists.txt b/src/games/skyrim/CMakeLists.txt index 17385b05..4cf2c85b 100644 --- a/src/games/skyrim/CMakeLists.txt +++ b/src/games/skyrim/CMakeLists.txt @@ -8,6 +8,7 @@ SET(DEPENDENCIES_DIR CACHE PATH "") # hint to find qt in dependencies path LIST(APPEND CMAKE_PREFIX_PATH ${DEPENDENCIES_DIR}/qt5/lib/cmake) +LIST(APPEND CMAKE_PREFIX_PATH ${DEPENDENCIES_DIR}/lz4/dll) FILE(GLOB_RECURSE BOOST_ROOT ${DEPENDENCIES_DIR}/boost*/project-config.jam) GET_FILENAME_COMPONENT(BOOST_ROOT ${BOOST_ROOT} DIRECTORY) diff --git a/src/games/skyrim/src/CMakeLists.txt b/src/games/skyrim/src/CMakeLists.txt index 60bf0b9e..cc3b3dfe 100644 --- a/src/games/skyrim/src/CMakeLists.txt +++ b/src/games/skyrim/src/CMakeLists.txt @@ -34,7 +34,8 @@ INCLUDE_DIRECTORIES(${project_path}/uibase/src ${project_path}/game_features/src ${project_path}/game_gamebryo/src) LINK_DIRECTORIES(${project_path}/uibase/build/src - ${lib_path}) + ${lib_path} + ${project_path}/../lz4/dll) ADD_DEFINITIONS(-DUNICODE -D_UNICODE) @@ -44,6 +45,7 @@ TARGET_LINK_LIBRARIES(${PROJ_NAME} ${Boost_LIBRARIES} uibase game_gamebryo + liblz4 version) IF(MSVC) From 174e782df4b6b7dc6b212129a22d301cd168c8cf Mon Sep 17 00:00:00 2001 From: ZachHaber Date: Tue, 27 Dec 2016 15:55:46 -0600 Subject: [PATCH 0287/1544] Adding ability to read lz4 compressed files. And a minor change to the CMakeLists to bring it to similar tab policy. --- src/CMakeLists.txt | 4 ++-- src/gamebryosavegame.cpp | 37 ++++++++++++++++++++++++++++++------- src/gamebryosavegame.h | 1 + 3 files changed, 33 insertions(+), 9 deletions(-) diff --git a/src/CMakeLists.txt b/src/CMakeLists.txt index f83f669d..0d84ace7 100644 --- a/src/CMakeLists.txt +++ b/src/CMakeLists.txt @@ -31,8 +31,8 @@ SET(plugin_path "${project_path}") INCLUDE_DIRECTORIES(${project_path}/uibase/src - ${project_path}/game_features/src) - ${project_path}/../lz4/include) + ${project_path}/game_features/src + ${project_path}/../lz4/include) LINK_DIRECTORIES(${lib_path} ${project_path}/../lz4/dll) diff --git a/src/gamebryosavegame.cpp b/src/gamebryosavegame.cpp index 681d49a8..280bf26e 100644 --- a/src/gamebryosavegame.cpp +++ b/src/gamebryosavegame.cpp @@ -158,10 +158,33 @@ void GamebryoSaveGame::FileWrapper::readImage(unsigned long width, unsigned long m_Game->m_Screenshot = image.copy(); } } +void readQDataStream(QDataStream &data, void *buff, std::size_t length){ + int read = data.readRawData(static_cast(buff), static_cast(length)); + if (read != length) { + throw std::runtime_error("unexpected end of file"); + } +} +template void readQDataStream(QDataStream &data,T &value){ + int read = data.readRawData(reinterpret_cast(&value),sizeof(T)); + if (read != sizeof(T)) { + throw std::runtime_error("unexpected end of file"); + } +} +template <> void readQDataStream(QDataStream &data, QString &value) +{ + unsigned short length; + readQDataStream(data,length); + + std::vector buffer(length); + + readQDataStream(data, buffer.data(), length); + + value = QString::fromLatin1(buffer.data(), length); +} void GamebryoSaveGame::FileWrapper::readPlugins(int bytesToIgnore) { - if(compressionType==0){ + if(m_Game->compressionType==0){ if(bytesToIgnore>0)//Just to make certain skip(bytesToIgnore); unsigned char count; @@ -172,9 +195,9 @@ void GamebryoSaveGame::FileWrapper::readPlugins(int bytesToIgnore) read(name); m_Game->m_Plugins.push_back(name); } - }else if(compressionType==1){ + }else if(m_Game->compressionType==1){ m_Game->m_Plugins.push_back("Please create an issue on the MO github labeled \"Found zlib Compressed\" with your savefile attached"); - }else if(compressionType==2){ + }else if(m_Game->compressionType==2){ unsigned long maxUncompressedSize; read(maxUncompressedSize); unsigned long compressedSize; @@ -187,8 +210,8 @@ void GamebryoSaveGame::FileWrapper::readPlugins(int bytesToIgnore) //to decrease the amount of data that has to be read in each savefile. Total is 16711940 (it wouldn't let me write it out in //an equation - //unsigned long uncompressedSize=(65537)*255+5‬; - unsigned long uncompressedSize=16711940; + //unsigned long uncompressedSize=(65537)*255+bytesToIgnore‬; + unsigned long uncompressedSize=16711935+bytesToIgnore; char * decompressed=new char[uncompressedSize]; LZ4_decompress_safe_partial(compressed,decompressed,compressedSize,uncompressedSize,maxUncompressedSize); delete[] compressed; @@ -200,12 +223,12 @@ void GamebryoSaveGame::FileWrapper::readPlugins(int bytesToIgnore) //unsigned long loc=7; //unsigned char count=decompressed[loc++]; unsigned char count; - read(data,count); + readQDataStream(data,count); //data.read(reinterpret_cast(&count),sizeof(count)); m_Game->m_Plugins.reserve(count); for(std::size_t i=0;im_Plugins.push_back(name); } diff --git a/src/gamebryosavegame.h b/src/gamebryosavegame.h index 30515854..e48296c6 100644 --- a/src/gamebryosavegame.h +++ b/src/gamebryosavegame.h @@ -115,6 +115,7 @@ protected: unsigned short compressionType; }; + template <> void GamebryoSaveGame::FileWrapper::read(QString &); #endif // GAMEBRYOSAVEGAME_H From 50e05463b5bf1923ab42a3e1a7960b9efa2407aa Mon Sep 17 00:00:00 2001 From: ZachHaber Date: Tue, 27 Dec 2016 15:59:02 -0600 Subject: [PATCH 0288/1544] [game_skyrimse] Updated linkage for Gamebryo lz4 decompression --- src/games/skyrimse/CMakeLists.txt | 1 + src/games/skyrimse/src/CMakeLists.txt | 4 +++- 2 files changed, 4 insertions(+), 1 deletion(-) diff --git a/src/games/skyrimse/CMakeLists.txt b/src/games/skyrimse/CMakeLists.txt index 5cd411b9..d6bcbf1e 100644 --- a/src/games/skyrimse/CMakeLists.txt +++ b/src/games/skyrimse/CMakeLists.txt @@ -8,6 +8,7 @@ SET(DEPENDENCIES_DIR CACHE PATH "") # hint to find qt in dependencies path LIST(APPEND CMAKE_PREFIX_PATH ${DEPENDENCIES_DIR}/qt5/lib/cmake) +LIST(APPEND CMAKE_PREFIX_PATH ${DEPENDENCIES_DIR}/lz4/dll) FILE(GLOB_RECURSE BOOST_ROOT ${DEPENDENCIES_DIR}/boost*/project-config.jam) GET_FILENAME_COMPONENT(BOOST_ROOT ${BOOST_ROOT} DIRECTORY) diff --git a/src/games/skyrimse/src/CMakeLists.txt b/src/games/skyrimse/src/CMakeLists.txt index cd5a5946..b2e39a9f 100644 --- a/src/games/skyrimse/src/CMakeLists.txt +++ b/src/games/skyrimse/src/CMakeLists.txt @@ -34,7 +34,8 @@ INCLUDE_DIRECTORIES(${project_path}/uibase/src ${project_path}/game_features/src ${project_path}/game_gamebryo/src) LINK_DIRECTORIES(${project_path}/uibase/build/src - ${lib_path}) + ${lib_path} + ${project_path}/../lz4/dll) ADD_DEFINITIONS(-DUNICODE -D_UNICODE) @@ -44,6 +45,7 @@ TARGET_LINK_LIBRARIES(${PROJ_NAME} ${Boost_LIBRARIES} uibase game_gamebryo + liblz4 version) IF(MSVC) From 7a86feb954cb9a057b9e53b04e9612f4d63d010e Mon Sep 17 00:00:00 2001 From: Brian Munro Date: Thu, 5 Jan 2017 13:15:32 +0200 Subject: [PATCH 0289/1544] [game_falloutnv] Update gamefalloutnv.cpp fix for https://github.com/LePresidente/modorganizer/issues/15 --- src/games/falloutnv/src/gamefalloutnv.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/games/falloutnv/src/gamefalloutnv.cpp b/src/games/falloutnv/src/gamefalloutnv.cpp index d1f37b3e..8f10abcd 100644 --- a/src/games/falloutnv/src/gamefalloutnv.cpp +++ b/src/games/falloutnv/src/gamefalloutnv.cpp @@ -132,7 +132,7 @@ QString GameFalloutNV::gameShortName() const QString GameFalloutNV::gameNexusName() const { - return "FalloutNV"; + return "newvegas"; } QStringList GameFalloutNV::iniFiles() const From 1bba3d96edaeab76d832e6c676bce27e6fd413f0 Mon Sep 17 00:00:00 2001 From: Brian Munro Date: Thu, 12 Jan 2017 12:23:10 +0200 Subject: [PATCH 0290/1544] [game_skyrimse] Fixes: https://github.com/LePresidente/modorganizer/issues/7 --- .../skyrimse/src/skyrimsegameplugins.cpp | 61 ++++++++++++------- 1 file changed, 39 insertions(+), 22 deletions(-) diff --git a/src/games/skyrimse/src/skyrimsegameplugins.cpp b/src/games/skyrimse/src/skyrimsegameplugins.cpp index 5b0f1e19..b110b2e2 100644 --- a/src/games/skyrimse/src/skyrimsegameplugins.cpp +++ b/src/games/skyrimse/src/skyrimsegameplugins.cpp @@ -16,8 +16,8 @@ using MOBase::IOrganizer; using MOBase::SafeWriteFile; using MOBase::reportError; -static const std::set OFFICIAL_FILES{ - "skyrim.esm", "update.esm", "Dawnguard.esm", "HearthFires.esm", "Dragonborn.esm"}; +//static const std::set OFFICIAL_FILES{ +// "skyrim.esm", "update.esm", "Dawnguard.esm", "HearthFires.esm", "Dragonborn.esm"}; SkyrimSEGamePlugins::SkyrimSEGamePlugins(IOrganizer *organizer) : GamebryoGamePlugins(organizer) @@ -44,22 +44,36 @@ void SkyrimSEGamePlugins::writePluginList(const IPluginList *pluginList, return pluginList->priority(lhs) < pluginList->priority(rhs); }); - //TODO: do not write plugins in OFFICIAL_FILES container for (const QString &pluginName : plugins) { - if (pluginList->state(pluginName) == IPluginList::STATE_ACTIVE) { - if (!textCodec->canEncode(pluginName)) { - invalidFileNames = true; - qCritical("invalid plugin name %s", qPrintable(pluginName)); - } - else - { - file->write("*"); - file->write(textCodec->fromUnicode(pluginName)); + if (!organizer()->managedGame()->primaryPlugins().contains("pluginName",Qt::CaseInsensitive)) { + if (pluginList->state(pluginName) == IPluginList::STATE_ACTIVE) { + if (!textCodec->canEncode(pluginName)) { + invalidFileNames = true; + qCritical("invalid plugin name %s", qPrintable(pluginName)); + } + else + { + file->write("*"); + file->write(textCodec->fromUnicode(pluginName)); + } + file->write("\r\n"); + ++writtenCount; } - file->write("\r\n"); - ++writtenCount; + else + { + if (!textCodec->canEncode(pluginName)) { + invalidFileNames = true; + qCritical("invalid plugin name %s", qPrintable(pluginName)); + } + else + { + file->write(textCodec->fromUnicode(pluginName)); + } + file->write("\r\n"); + ++writtenCount; + } } } @@ -80,8 +94,9 @@ bool SkyrimSEGamePlugins::readPluginList(MOBase::IPluginList *pluginList, bool useLoadOrder) { QStringList plugins = pluginList->pluginNames(); + QStringList loadOrder = organizer()->managedGame()->primaryPlugins(); - for (const QString &pluginName : OFFICIAL_FILES) { + for (const QString &pluginName : loadOrder) { if (pluginList->state(pluginName) != IPluginList::STATE_MISSING) { pluginList->setState(pluginName, IPluginList::STATE_ACTIVE); } @@ -101,7 +116,6 @@ bool SkyrimSEGamePlugins::readPluginList(MOBase::IPluginList *pluginList, return false; } - QStringList loadOrder = organizer()->managedGame()->primaryPlugins(); while (!file.atEnd()) { QByteArray line = file.readLine(); QString pluginName; @@ -109,10 +123,13 @@ bool SkyrimSEGamePlugins::readPluginList(MOBase::IPluginList *pluginList, pluginName = localCodec()->toUnicode(line.trimmed().constData()); } if (pluginName.startsWith('*')) { - pluginName.remove(0, 1); + pluginName.remove(0, 1); } + else { + pluginList->setState(pluginName, IPluginList::STATE_INACTIVE); + } if (pluginName.size() > 0) { - pluginList->setState(pluginName, IPluginList::STATE_ACTIVE); + plugins.removeAll(pluginName); if (!loadOrder.contains(pluginName, Qt::CaseInsensitive)) { loadOrder.append(pluginName); @@ -122,10 +139,10 @@ bool SkyrimSEGamePlugins::readPluginList(MOBase::IPluginList *pluginList, file.close(); - // we removed each plugin found in the file, so what's left are inactive mods - for (const QString &pluginName : plugins) { - pluginList->setState(pluginName, IPluginList::STATE_INACTIVE); - } + // we removed each plugin found in the file, so what's left are inactive mods + // for (const QString &pluginName : plugins) { + // pluginList->setState(pluginName, IPluginList::STATE_INACTIVE); + // } if (useLoadOrder) { pluginList->setLoadOrder(loadOrder); From 5548b9a398499b9a4c78c008c9b38d58aea757fb Mon Sep 17 00:00:00 2001 From: Brian Munro Date: Thu, 12 Jan 2017 14:41:52 +0200 Subject: [PATCH 0291/1544] [game_skyrimse] Was not working as intended, fix attempt 2 --- .../skyrimse/src/skyrimsegameplugins.cpp | 36 ++++++++++++------- 1 file changed, 23 insertions(+), 13 deletions(-) diff --git a/src/games/skyrimse/src/skyrimsegameplugins.cpp b/src/games/skyrimse/src/skyrimsegameplugins.cpp index b110b2e2..de70d3df 100644 --- a/src/games/skyrimse/src/skyrimsegameplugins.cpp +++ b/src/games/skyrimse/src/skyrimsegameplugins.cpp @@ -44,9 +44,11 @@ void SkyrimSEGamePlugins::writePluginList(const IPluginList *pluginList, return pluginList->priority(lhs) < pluginList->priority(rhs); }); + QStringList PrimaryPlugins = organizer()->managedGame()->primaryPlugins(); + //TODO: do not write plugins in OFFICIAL_FILES container for (const QString &pluginName : plugins) { - if (!organizer()->managedGame()->primaryPlugins().contains("pluginName",Qt::CaseInsensitive)) { + if (!PrimaryPlugins.contains(pluginName,Qt::CaseInsensitive)) { if (pluginList->state(pluginName) == IPluginList::STATE_ACTIVE) { if (!textCodec->canEncode(pluginName)) { invalidFileNames = true; @@ -124,25 +126,33 @@ bool SkyrimSEGamePlugins::readPluginList(MOBase::IPluginList *pluginList, } if (pluginName.startsWith('*')) { pluginName.remove(0, 1); + if (pluginName.size() > 0) { + pluginList->setState(pluginName, IPluginList::STATE_ACTIVE); + plugins.removeAll(pluginName); + if (!loadOrder.contains(pluginName, Qt::CaseInsensitive)) { + loadOrder.append(pluginName); + } + } } - else { - pluginList->setState(pluginName, IPluginList::STATE_INACTIVE); + else + { + if (pluginName.size() > 0) { + pluginList->setState(pluginName, IPluginList::STATE_INACTIVE); + plugins.removeAll(pluginName); + if (!loadOrder.contains(pluginName, Qt::CaseInsensitive)) { + loadOrder.append(pluginName); + } + } } - if (pluginName.size() > 0) { - - plugins.removeAll(pluginName); - if (!loadOrder.contains(pluginName, Qt::CaseInsensitive)) { - loadOrder.append(pluginName); - } - } + } file.close(); // we removed each plugin found in the file, so what's left are inactive mods - // for (const QString &pluginName : plugins) { - // pluginList->setState(pluginName, IPluginList::STATE_INACTIVE); - // } + //for (const QString &pluginName : plugins) { + // pluginList->setState(pluginName, IPluginList::STATE_INACTIVE); + //} if (useLoadOrder) { pluginList->setLoadOrder(loadOrder); From 9d7e773bdf748127c1a7a8e8e10bb1081fcffb88 Mon Sep 17 00:00:00 2001 From: lepresidente Date: Sun, 5 Feb 2017 09:38:51 +0200 Subject: [PATCH 0292/1544] [game_fallout4vr] Fixed plugin names. --- src/games/fallout4vr/src/fallout4gameplugins.cpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/games/fallout4vr/src/fallout4gameplugins.cpp b/src/games/fallout4vr/src/fallout4gameplugins.cpp index e70e7d19..15b11c40 100644 --- a/src/games/fallout4vr/src/fallout4gameplugins.cpp +++ b/src/games/fallout4vr/src/fallout4gameplugins.cpp @@ -17,8 +17,8 @@ using MOBase::SafeWriteFile; using MOBase::reportError; static const std::set OFFICIAL_FILES{ - "fallout4.esm", "dlcrobot.esm", "dlcworkshop01.esm", "dlccoast.esm", - "dlcworkshop02.esm", "dlcworkshop03.esm", "dlcnukaworld.esm"}; + "Fallout4.esm", "DLCRobot.esm", "DLCworkshop01.esm", "DLCCoast.esm", + "DLCworkshop02.esm", "DLCworkshop03.esm", "DLCNukaWorld.esm"}; Fallout4GamePlugins::Fallout4GamePlugins(IOrganizer *organizer) : GamebryoGamePlugins(organizer) From b29e0d46cb4ef86dfaaca4611aee71635b06e548 Mon Sep 17 00:00:00 2001 From: lepresidente Date: Sun, 5 Feb 2017 09:38:51 +0200 Subject: [PATCH 0293/1544] [game_fallout76] Fixed plugin names. --- src/games/fallout76/src/fallout4gameplugins.cpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/games/fallout76/src/fallout4gameplugins.cpp b/src/games/fallout76/src/fallout4gameplugins.cpp index e70e7d19..15b11c40 100644 --- a/src/games/fallout76/src/fallout4gameplugins.cpp +++ b/src/games/fallout76/src/fallout4gameplugins.cpp @@ -17,8 +17,8 @@ using MOBase::SafeWriteFile; using MOBase::reportError; static const std::set OFFICIAL_FILES{ - "fallout4.esm", "dlcrobot.esm", "dlcworkshop01.esm", "dlccoast.esm", - "dlcworkshop02.esm", "dlcworkshop03.esm", "dlcnukaworld.esm"}; + "Fallout4.esm", "DLCRobot.esm", "DLCworkshop01.esm", "DLCCoast.esm", + "DLCworkshop02.esm", "DLCworkshop03.esm", "DLCNukaWorld.esm"}; Fallout4GamePlugins::Fallout4GamePlugins(IOrganizer *organizer) : GamebryoGamePlugins(organizer) From 687a4e4721d922fcce452e5bf94609106ba74680 Mon Sep 17 00:00:00 2001 From: lepresidente Date: Sun, 5 Feb 2017 09:38:51 +0200 Subject: [PATCH 0294/1544] [game_fallout4] Fixed plugin names. --- src/games/fallout4/src/fallout4gameplugins.cpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/games/fallout4/src/fallout4gameplugins.cpp b/src/games/fallout4/src/fallout4gameplugins.cpp index e70e7d19..15b11c40 100644 --- a/src/games/fallout4/src/fallout4gameplugins.cpp +++ b/src/games/fallout4/src/fallout4gameplugins.cpp @@ -17,8 +17,8 @@ using MOBase::SafeWriteFile; using MOBase::reportError; static const std::set OFFICIAL_FILES{ - "fallout4.esm", "dlcrobot.esm", "dlcworkshop01.esm", "dlccoast.esm", - "dlcworkshop02.esm", "dlcworkshop03.esm", "dlcnukaworld.esm"}; + "Fallout4.esm", "DLCRobot.esm", "DLCworkshop01.esm", "DLCCoast.esm", + "DLCworkshop02.esm", "DLCworkshop03.esm", "DLCNukaWorld.esm"}; Fallout4GamePlugins::Fallout4GamePlugins(IOrganizer *organizer) : GamebryoGamePlugins(organizer) From cbdb9cef547f4494ee781adcf3f836421cb33bc9 Mon Sep 17 00:00:00 2001 From: LePresidente Date: Sat, 6 May 2017 19:36:14 +0200 Subject: [PATCH 0295/1544] [game_fallout4vr] Fixes https://github.com/LePresidente/modorganizer/issues/12 --- .../fallout4vr/src/fallout4gameplugins.cpp | 83 ++++++++++++++----- 1 file changed, 64 insertions(+), 19 deletions(-) diff --git a/src/games/fallout4vr/src/fallout4gameplugins.cpp b/src/games/fallout4vr/src/fallout4gameplugins.cpp index 15b11c40..e68b7b18 100644 --- a/src/games/fallout4vr/src/fallout4gameplugins.cpp +++ b/src/games/fallout4vr/src/fallout4gameplugins.cpp @@ -45,17 +45,44 @@ void Fallout4GamePlugins::writePluginList(const IPluginList *pluginList, return pluginList->priority(lhs) < pluginList->priority(rhs); }); + QStringList PrimaryPlugins = organizer()->managedGame()->primaryPlugins(); + + for (auto f : OFFICIAL_FILES) { + if (!PrimaryPlugins.contains(f, Qt::CaseInsensitive)) { + PrimaryPlugins.append(f); + } + } + + //TODO: do not write plugins in OFFICIAL_FILES container for (const QString &pluginName : plugins) { - if (pluginList->state(pluginName) == IPluginList::STATE_ACTIVE) { - if (!textCodec->canEncode(pluginName)) { - invalidFileNames = true; - qCritical("invalid plugin name %s", qPrintable(pluginName)); - } else { - file->write("*"); - file->write(textCodec->fromUnicode(pluginName)); + if (!PrimaryPlugins.contains(pluginName,Qt::CaseInsensitive)) { + if (pluginList->state(pluginName) == IPluginList::STATE_ACTIVE) { + if (!textCodec->canEncode(pluginName)) { + invalidFileNames = true; + qCritical("invalid plugin name %s", qPrintable(pluginName)); + } + else + { + file->write("*"); + file->write(textCodec->fromUnicode(pluginName)); + + } + file->write("\r\n"); + ++writtenCount; } - file->write("\r\n"); - ++writtenCount; + else + { + if (!textCodec->canEncode(pluginName)) { + invalidFileNames = true; + qCritical("invalid plugin name %s", qPrintable(pluginName)); + } + else + { + file->write(textCodec->fromUnicode(pluginName)); + } + file->write("\r\n"); + ++writtenCount; + } } } @@ -76,10 +103,18 @@ bool Fallout4GamePlugins::readPluginList(MOBase::IPluginList *pluginList, bool useLoadOrder) { QStringList plugins = pluginList->pluginNames(); + QStringList loadOrder = organizer()->managedGame()->primaryPlugins(); - for (const QString &pluginName : OFFICIAL_FILES) { + for (auto f : OFFICIAL_FILES) { + if (!loadOrder.contains(f, Qt::CaseInsensitive)) { + loadOrder.append(f); + } + } + + for (const QString &pluginName : loadOrder) { if (pluginList->state(pluginName) != IPluginList::STATE_MISSING) { pluginList->setState(pluginName, IPluginList::STATE_ACTIVE); + plugins.removeAll(pluginName); } } @@ -97,7 +132,6 @@ bool Fallout4GamePlugins::readPluginList(MOBase::IPluginList *pluginList, return false; } - QStringList loadOrder = organizer()->managedGame()->primaryPlugins(); while (!file.atEnd()) { QByteArray line = file.readLine(); QString pluginName; @@ -105,15 +139,26 @@ bool Fallout4GamePlugins::readPluginList(MOBase::IPluginList *pluginList, pluginName = localCodec()->toUnicode(line.trimmed().constData()); } if (pluginName.startsWith('*')) { - pluginName.remove(0, 1); - } - if (pluginName.size() > 0) { - pluginList->setState(pluginName, IPluginList::STATE_ACTIVE); - plugins.removeAll(pluginName); - if (!loadOrder.contains(pluginName, Qt::CaseInsensitive)) { - loadOrder.append(pluginName); - } + pluginName.remove(0, 1); + if (pluginName.size() > 0) { + pluginList->setState(pluginName, IPluginList::STATE_ACTIVE); + plugins.removeAll(pluginName); + if (!loadOrder.contains(pluginName, Qt::CaseInsensitive)) { + loadOrder.append(pluginName); + } + } } + else + { + if (pluginName.size() > 0) { + pluginList->setState(pluginName, IPluginList::STATE_INACTIVE); + plugins.removeAll(pluginName); + if (!loadOrder.contains(pluginName, Qt::CaseInsensitive)) { + loadOrder.append(pluginName); + } + } + } + } file.close(); From 029bb5318c1cdd701fbda8620d534c983ba5fe17 Mon Sep 17 00:00:00 2001 From: LePresidente Date: Sat, 6 May 2017 19:36:14 +0200 Subject: [PATCH 0296/1544] [game_fallout76] Fixes https://github.com/LePresidente/modorganizer/issues/12 --- .../fallout76/src/fallout4gameplugins.cpp | 83 ++++++++++++++----- 1 file changed, 64 insertions(+), 19 deletions(-) diff --git a/src/games/fallout76/src/fallout4gameplugins.cpp b/src/games/fallout76/src/fallout4gameplugins.cpp index 15b11c40..e68b7b18 100644 --- a/src/games/fallout76/src/fallout4gameplugins.cpp +++ b/src/games/fallout76/src/fallout4gameplugins.cpp @@ -45,17 +45,44 @@ void Fallout4GamePlugins::writePluginList(const IPluginList *pluginList, return pluginList->priority(lhs) < pluginList->priority(rhs); }); + QStringList PrimaryPlugins = organizer()->managedGame()->primaryPlugins(); + + for (auto f : OFFICIAL_FILES) { + if (!PrimaryPlugins.contains(f, Qt::CaseInsensitive)) { + PrimaryPlugins.append(f); + } + } + + //TODO: do not write plugins in OFFICIAL_FILES container for (const QString &pluginName : plugins) { - if (pluginList->state(pluginName) == IPluginList::STATE_ACTIVE) { - if (!textCodec->canEncode(pluginName)) { - invalidFileNames = true; - qCritical("invalid plugin name %s", qPrintable(pluginName)); - } else { - file->write("*"); - file->write(textCodec->fromUnicode(pluginName)); + if (!PrimaryPlugins.contains(pluginName,Qt::CaseInsensitive)) { + if (pluginList->state(pluginName) == IPluginList::STATE_ACTIVE) { + if (!textCodec->canEncode(pluginName)) { + invalidFileNames = true; + qCritical("invalid plugin name %s", qPrintable(pluginName)); + } + else + { + file->write("*"); + file->write(textCodec->fromUnicode(pluginName)); + + } + file->write("\r\n"); + ++writtenCount; } - file->write("\r\n"); - ++writtenCount; + else + { + if (!textCodec->canEncode(pluginName)) { + invalidFileNames = true; + qCritical("invalid plugin name %s", qPrintable(pluginName)); + } + else + { + file->write(textCodec->fromUnicode(pluginName)); + } + file->write("\r\n"); + ++writtenCount; + } } } @@ -76,10 +103,18 @@ bool Fallout4GamePlugins::readPluginList(MOBase::IPluginList *pluginList, bool useLoadOrder) { QStringList plugins = pluginList->pluginNames(); + QStringList loadOrder = organizer()->managedGame()->primaryPlugins(); - for (const QString &pluginName : OFFICIAL_FILES) { + for (auto f : OFFICIAL_FILES) { + if (!loadOrder.contains(f, Qt::CaseInsensitive)) { + loadOrder.append(f); + } + } + + for (const QString &pluginName : loadOrder) { if (pluginList->state(pluginName) != IPluginList::STATE_MISSING) { pluginList->setState(pluginName, IPluginList::STATE_ACTIVE); + plugins.removeAll(pluginName); } } @@ -97,7 +132,6 @@ bool Fallout4GamePlugins::readPluginList(MOBase::IPluginList *pluginList, return false; } - QStringList loadOrder = organizer()->managedGame()->primaryPlugins(); while (!file.atEnd()) { QByteArray line = file.readLine(); QString pluginName; @@ -105,15 +139,26 @@ bool Fallout4GamePlugins::readPluginList(MOBase::IPluginList *pluginList, pluginName = localCodec()->toUnicode(line.trimmed().constData()); } if (pluginName.startsWith('*')) { - pluginName.remove(0, 1); - } - if (pluginName.size() > 0) { - pluginList->setState(pluginName, IPluginList::STATE_ACTIVE); - plugins.removeAll(pluginName); - if (!loadOrder.contains(pluginName, Qt::CaseInsensitive)) { - loadOrder.append(pluginName); - } + pluginName.remove(0, 1); + if (pluginName.size() > 0) { + pluginList->setState(pluginName, IPluginList::STATE_ACTIVE); + plugins.removeAll(pluginName); + if (!loadOrder.contains(pluginName, Qt::CaseInsensitive)) { + loadOrder.append(pluginName); + } + } } + else + { + if (pluginName.size() > 0) { + pluginList->setState(pluginName, IPluginList::STATE_INACTIVE); + plugins.removeAll(pluginName); + if (!loadOrder.contains(pluginName, Qt::CaseInsensitive)) { + loadOrder.append(pluginName); + } + } + } + } file.close(); From 9d42ecf2f8dc43ef6aaf20c20b6fa016c5cec8ea Mon Sep 17 00:00:00 2001 From: LePresidente Date: Sat, 6 May 2017 19:36:14 +0200 Subject: [PATCH 0297/1544] [game_fallout4] Fixes https://github.com/LePresidente/modorganizer/issues/12 --- .../fallout4/src/fallout4gameplugins.cpp | 83 ++++++++++++++----- 1 file changed, 64 insertions(+), 19 deletions(-) diff --git a/src/games/fallout4/src/fallout4gameplugins.cpp b/src/games/fallout4/src/fallout4gameplugins.cpp index 15b11c40..e68b7b18 100644 --- a/src/games/fallout4/src/fallout4gameplugins.cpp +++ b/src/games/fallout4/src/fallout4gameplugins.cpp @@ -45,17 +45,44 @@ void Fallout4GamePlugins::writePluginList(const IPluginList *pluginList, return pluginList->priority(lhs) < pluginList->priority(rhs); }); + QStringList PrimaryPlugins = organizer()->managedGame()->primaryPlugins(); + + for (auto f : OFFICIAL_FILES) { + if (!PrimaryPlugins.contains(f, Qt::CaseInsensitive)) { + PrimaryPlugins.append(f); + } + } + + //TODO: do not write plugins in OFFICIAL_FILES container for (const QString &pluginName : plugins) { - if (pluginList->state(pluginName) == IPluginList::STATE_ACTIVE) { - if (!textCodec->canEncode(pluginName)) { - invalidFileNames = true; - qCritical("invalid plugin name %s", qPrintable(pluginName)); - } else { - file->write("*"); - file->write(textCodec->fromUnicode(pluginName)); + if (!PrimaryPlugins.contains(pluginName,Qt::CaseInsensitive)) { + if (pluginList->state(pluginName) == IPluginList::STATE_ACTIVE) { + if (!textCodec->canEncode(pluginName)) { + invalidFileNames = true; + qCritical("invalid plugin name %s", qPrintable(pluginName)); + } + else + { + file->write("*"); + file->write(textCodec->fromUnicode(pluginName)); + + } + file->write("\r\n"); + ++writtenCount; } - file->write("\r\n"); - ++writtenCount; + else + { + if (!textCodec->canEncode(pluginName)) { + invalidFileNames = true; + qCritical("invalid plugin name %s", qPrintable(pluginName)); + } + else + { + file->write(textCodec->fromUnicode(pluginName)); + } + file->write("\r\n"); + ++writtenCount; + } } } @@ -76,10 +103,18 @@ bool Fallout4GamePlugins::readPluginList(MOBase::IPluginList *pluginList, bool useLoadOrder) { QStringList plugins = pluginList->pluginNames(); + QStringList loadOrder = organizer()->managedGame()->primaryPlugins(); - for (const QString &pluginName : OFFICIAL_FILES) { + for (auto f : OFFICIAL_FILES) { + if (!loadOrder.contains(f, Qt::CaseInsensitive)) { + loadOrder.append(f); + } + } + + for (const QString &pluginName : loadOrder) { if (pluginList->state(pluginName) != IPluginList::STATE_MISSING) { pluginList->setState(pluginName, IPluginList::STATE_ACTIVE); + plugins.removeAll(pluginName); } } @@ -97,7 +132,6 @@ bool Fallout4GamePlugins::readPluginList(MOBase::IPluginList *pluginList, return false; } - QStringList loadOrder = organizer()->managedGame()->primaryPlugins(); while (!file.atEnd()) { QByteArray line = file.readLine(); QString pluginName; @@ -105,15 +139,26 @@ bool Fallout4GamePlugins::readPluginList(MOBase::IPluginList *pluginList, pluginName = localCodec()->toUnicode(line.trimmed().constData()); } if (pluginName.startsWith('*')) { - pluginName.remove(0, 1); - } - if (pluginName.size() > 0) { - pluginList->setState(pluginName, IPluginList::STATE_ACTIVE); - plugins.removeAll(pluginName); - if (!loadOrder.contains(pluginName, Qt::CaseInsensitive)) { - loadOrder.append(pluginName); - } + pluginName.remove(0, 1); + if (pluginName.size() > 0) { + pluginList->setState(pluginName, IPluginList::STATE_ACTIVE); + plugins.removeAll(pluginName); + if (!loadOrder.contains(pluginName, Qt::CaseInsensitive)) { + loadOrder.append(pluginName); + } + } } + else + { + if (pluginName.size() > 0) { + pluginList->setState(pluginName, IPluginList::STATE_INACTIVE); + plugins.removeAll(pluginName); + if (!loadOrder.contains(pluginName, Qt::CaseInsensitive)) { + loadOrder.append(pluginName); + } + } + } + } file.close(); From 349b00b583e4f4c3e8ca8a3cda1039ceaa2156a6 Mon Sep 17 00:00:00 2001 From: LePresidente Date: Thu, 21 Sep 2017 16:53:50 +0200 Subject: [PATCH 0298/1544] [game_skyrimse] Updated cmakelists to get the QT5 location from the QT_ROOT variable, instead of expecting it in DEPENDENCIES_DIR. --- src/games/skyrimse/CMakeLists.txt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/games/skyrimse/CMakeLists.txt b/src/games/skyrimse/CMakeLists.txt index d6bcbf1e..d10ab54f 100644 --- a/src/games/skyrimse/CMakeLists.txt +++ b/src/games/skyrimse/CMakeLists.txt @@ -7,7 +7,7 @@ PROJECT(${PROJ_NAME}) SET(DEPENDENCIES_DIR CACHE PATH "") # hint to find qt in dependencies path -LIST(APPEND CMAKE_PREFIX_PATH ${DEPENDENCIES_DIR}/qt5/lib/cmake) +LIST(APPEND CMAKE_PREFIX_PATH ${QT_ROOT}/lib/cmake) LIST(APPEND CMAKE_PREFIX_PATH ${DEPENDENCIES_DIR}/lz4/dll) FILE(GLOB_RECURSE BOOST_ROOT ${DEPENDENCIES_DIR}/boost*/project-config.jam) From 540a781d66edb1e934cfe90e1702711fe2bf13d0 Mon Sep 17 00:00:00 2001 From: LePresidente Date: Thu, 21 Sep 2017 16:53:55 +0200 Subject: [PATCH 0299/1544] [game_skyrim] Updated cmakelists to get the QT5 location from the QT_ROOT variable, instead of expecting it in DEPENDENCIES_DIR. --- src/games/skyrim/CMakeLists.txt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/games/skyrim/CMakeLists.txt b/src/games/skyrim/CMakeLists.txt index 4cf2c85b..31d9b748 100644 --- a/src/games/skyrim/CMakeLists.txt +++ b/src/games/skyrim/CMakeLists.txt @@ -7,7 +7,7 @@ PROJECT(${PROJ_NAME}) SET(DEPENDENCIES_DIR CACHE PATH "") # hint to find qt in dependencies path -LIST(APPEND CMAKE_PREFIX_PATH ${DEPENDENCIES_DIR}/qt5/lib/cmake) +LIST(APPEND CMAKE_PREFIX_PATH ${QT_ROOT}/lib/cmake) LIST(APPEND CMAKE_PREFIX_PATH ${DEPENDENCIES_DIR}/lz4/dll) FILE(GLOB_RECURSE BOOST_ROOT ${DEPENDENCIES_DIR}/boost*/project-config.jam) From 05992f710dd8ab1d60532a13558d8385c960cd38 Mon Sep 17 00:00:00 2001 From: LePresidente Date: Thu, 21 Sep 2017 16:53:58 +0200 Subject: [PATCH 0300/1544] [game_oblivion] Updated cmakelists to get the QT5 location from the QT_ROOT variable, instead of expecting it in DEPENDENCIES_DIR. --- src/games/oblivion/CMakeLists.txt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/games/oblivion/CMakeLists.txt b/src/games/oblivion/CMakeLists.txt index bcd2bc6c..914f15e9 100644 --- a/src/games/oblivion/CMakeLists.txt +++ b/src/games/oblivion/CMakeLists.txt @@ -7,7 +7,7 @@ PROJECT(${PROJ_NAME}) SET(DEPENDENCIES_DIR CACHE PATH "") # hint to find qt in dependencies path -LIST(APPEND CMAKE_PREFIX_PATH ${DEPENDENCIES_DIR}/qt5/lib/cmake) +LIST(APPEND CMAKE_PREFIX_PATH ${QT_ROOT}/lib/cmake) LIST(APPEND CMAKE_PREFIX_PATH ${DEPENDENCIES_DIR}/lz4/dll) FILE(GLOB_RECURSE BOOST_ROOT ${DEPENDENCIES_DIR}/boost*/project-config.jam) From 5502415440bb1ef1a0108c498bd4030f819081e0 Mon Sep 17 00:00:00 2001 From: LePresidente Date: Thu, 21 Sep 2017 16:54:03 +0200 Subject: [PATCH 0301/1544] Updated cmakelists to get the QT5 location from the QT_ROOT variable, instead of expecting it in DEPENDENCIES_DIR. --- CMakeLists.txt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/CMakeLists.txt b/CMakeLists.txt index cc5453b8..584c342b 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -6,7 +6,7 @@ PROJECT(${PROJ_NAME}) SET(DEPENDENCIES_DIR CACHE PATH "") # hint to find qt in dependencies path -LIST(APPEND CMAKE_PREFIX_PATH ${DEPENDENCIES_DIR}/qt5/lib/cmake) +LIST(APPEND CMAKE_PREFIX_PATH ${QT_ROOT}/lib/cmake) LIST(APPEND CMAKE_PREFIX_PATH ${DEPENDENCIES_DIR}/lz4/dll) From 066bc1b6b63ee26d40364296fda5a41fb393bdb8 Mon Sep 17 00:00:00 2001 From: LePresidente Date: Thu, 21 Sep 2017 16:54:12 +0200 Subject: [PATCH 0302/1544] [game_falloutnv] Updated cmakelists to get the QT5 location from the QT_ROOT variable, instead of expecting it in DEPENDENCIES_DIR. --- src/games/falloutnv/CMakeLists.txt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/games/falloutnv/CMakeLists.txt b/src/games/falloutnv/CMakeLists.txt index 6a9e25f6..fc30c94e 100644 --- a/src/games/falloutnv/CMakeLists.txt +++ b/src/games/falloutnv/CMakeLists.txt @@ -7,7 +7,7 @@ PROJECT(${PROJ_NAME}) SET(DEPENDENCIES_DIR CACHE PATH "") # hint to find qt in dependencies path -LIST(APPEND CMAKE_PREFIX_PATH ${DEPENDENCIES_DIR}/qt5/lib/cmake) +LIST(APPEND CMAKE_PREFIX_PATH ${QT_ROOT}/lib/cmake) LIST(APPEND CMAKE_PREFIX_PATH ${DEPENDENCIES_DIR}/lz4/dll) From dd9859d6b8d2591a79c91132e51843f00edf59d2 Mon Sep 17 00:00:00 2001 From: LePresidente Date: Thu, 21 Sep 2017 16:54:16 +0200 Subject: [PATCH 0303/1544] [game_fallout4vr] Updated cmakelists to get the QT5 location from the QT_ROOT variable, instead of expecting it in DEPENDENCIES_DIR. --- src/games/fallout4vr/CMakeLists.txt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/games/fallout4vr/CMakeLists.txt b/src/games/fallout4vr/CMakeLists.txt index a7c88e3b..950d7a0c 100644 --- a/src/games/fallout4vr/CMakeLists.txt +++ b/src/games/fallout4vr/CMakeLists.txt @@ -7,7 +7,7 @@ PROJECT(${PROJ_NAME}) SET(DEPENDENCIES_DIR CACHE PATH "") # hint to find qt in dependencies path -LIST(APPEND CMAKE_PREFIX_PATH ${DEPENDENCIES_DIR}/qt5/lib/cmake) +LIST(APPEND CMAKE_PREFIX_PATH ${QT_ROOT}/lib/cmake) LIST(APPEND CMAKE_PREFIX_PATH ${DEPENDENCIES_DIR}/lz4/dll) FILE(GLOB_RECURSE BOOST_ROOT ${DEPENDENCIES_DIR}/boost*/project-config.jam) From 107fe73a66578c9880f78782fdc071954064bb9b Mon Sep 17 00:00:00 2001 From: LePresidente Date: Thu, 21 Sep 2017 16:54:16 +0200 Subject: [PATCH 0304/1544] [game_fallout76] Updated cmakelists to get the QT5 location from the QT_ROOT variable, instead of expecting it in DEPENDENCIES_DIR. --- src/games/fallout76/CMakeLists.txt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/games/fallout76/CMakeLists.txt b/src/games/fallout76/CMakeLists.txt index a7c88e3b..950d7a0c 100644 --- a/src/games/fallout76/CMakeLists.txt +++ b/src/games/fallout76/CMakeLists.txt @@ -7,7 +7,7 @@ PROJECT(${PROJ_NAME}) SET(DEPENDENCIES_DIR CACHE PATH "") # hint to find qt in dependencies path -LIST(APPEND CMAKE_PREFIX_PATH ${DEPENDENCIES_DIR}/qt5/lib/cmake) +LIST(APPEND CMAKE_PREFIX_PATH ${QT_ROOT}/lib/cmake) LIST(APPEND CMAKE_PREFIX_PATH ${DEPENDENCIES_DIR}/lz4/dll) FILE(GLOB_RECURSE BOOST_ROOT ${DEPENDENCIES_DIR}/boost*/project-config.jam) From 0fd112991fd30ac030e7aa58d7c217327984c72a Mon Sep 17 00:00:00 2001 From: LePresidente Date: Thu, 21 Sep 2017 16:54:16 +0200 Subject: [PATCH 0305/1544] [game_fallout4] Updated cmakelists to get the QT5 location from the QT_ROOT variable, instead of expecting it in DEPENDENCIES_DIR. --- src/games/fallout4/CMakeLists.txt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/games/fallout4/CMakeLists.txt b/src/games/fallout4/CMakeLists.txt index a7c88e3b..950d7a0c 100644 --- a/src/games/fallout4/CMakeLists.txt +++ b/src/games/fallout4/CMakeLists.txt @@ -7,7 +7,7 @@ PROJECT(${PROJ_NAME}) SET(DEPENDENCIES_DIR CACHE PATH "") # hint to find qt in dependencies path -LIST(APPEND CMAKE_PREFIX_PATH ${DEPENDENCIES_DIR}/qt5/lib/cmake) +LIST(APPEND CMAKE_PREFIX_PATH ${QT_ROOT}/lib/cmake) LIST(APPEND CMAKE_PREFIX_PATH ${DEPENDENCIES_DIR}/lz4/dll) FILE(GLOB_RECURSE BOOST_ROOT ${DEPENDENCIES_DIR}/boost*/project-config.jam) From 7005e7a0f6c8602bfeafebf469992f534c8abde7 Mon Sep 17 00:00:00 2001 From: LePresidente Date: Thu, 21 Sep 2017 16:54:20 +0200 Subject: [PATCH 0306/1544] [game_fallout3] Updated cmakelists to get the QT5 location from the QT_ROOT variable, instead of expecting it in DEPENDENCIES_DIR. --- src/games/fallout3/CMakeLists.txt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/games/fallout3/CMakeLists.txt b/src/games/fallout3/CMakeLists.txt index 50472868..da91acdd 100644 --- a/src/games/fallout3/CMakeLists.txt +++ b/src/games/fallout3/CMakeLists.txt @@ -7,7 +7,7 @@ PROJECT(${PROJ_NAME}) SET(DEPENDENCIES_DIR CACHE PATH "") # hint to find qt in dependencies path -LIST(APPEND CMAKE_PREFIX_PATH ${DEPENDENCIES_DIR}/qt5/lib/cmake) +LIST(APPEND CMAKE_PREFIX_PATH ${QT_ROOT}/lib/cmake) LIST(APPEND CMAKE_PREFIX_PATH ${DEPENDENCIES_DIR}/lz4/dll) FILE(GLOB_RECURSE BOOST_ROOT ${DEPENDENCIES_DIR}/boost*/project-config.jam) From c0edf5e6929824e07b57a1a699f51a7c22b6b48f Mon Sep 17 00:00:00 2001 From: Hugues92 Date: Thu, 19 Oct 2017 16:02:40 +0200 Subject: [PATCH 0307/1544] Allows plugins with .esl extension. Not actually game tested, only inside ModOrganizer UI and xEdit. --- src/gamebryosavegameinfo.cpp | 2 +- src/gamebryounmanagedmods.cpp | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/src/gamebryosavegameinfo.cpp b/src/gamebryosavegameinfo.cpp index 518de909..52992e96 100644 --- a/src/gamebryosavegameinfo.cpp +++ b/src/gamebryosavegameinfo.cpp @@ -41,7 +41,7 @@ GamebryoSaveGameInfo::MissingAssets GamebryoSaveGameInfo::getMissingAssets(QStri } //Find out any other mods that might contain the esp/esm - QStringList espFilter( { "*.esp", "*.esm" } ); + QStringList espFilter( { "*.esp", "*.esl", "*.esm" } ); QString dataDir(organizerCore->managedGame()->dataDirectory().absolutePath()); diff --git a/src/gamebryounmanagedmods.cpp b/src/gamebryounmanagedmods.cpp index 7ad3c3cf..80806d60 100644 --- a/src/gamebryounmanagedmods.cpp +++ b/src/gamebryounmanagedmods.cpp @@ -17,7 +17,7 @@ QStringList GamebryoUnmangedMods::mods(bool onlyOfficial) const { QStringList mainPlugins = m_Game->primaryPlugins(); QDir dataDir(m_Game->dataDirectory()); - for (const QString &fileName : dataDir.entryList({"*.esp", "*.esm"})) { + for (const QString &fileName : dataDir.entryList({ "*.esp", "*.esl", "*.esm"})) { if (!mainPlugins.contains(fileName, Qt::CaseInsensitive) && (!onlyOfficial || dlcPlugins.contains(fileName, Qt::CaseInsensitive))) { QFileInfo file(fileName); From 3db942bc97c7d7902b4ec5413f4ea388a8d68eba Mon Sep 17 00:00:00 2001 From: Hugues92 Date: Fri, 20 Oct 2017 13:13:27 +0200 Subject: [PATCH 0308/1544] [game_fallout4vr] Untested: Should update the save file format for Fallout 4 and Skyse SE to handle esl light plugins. --- src/games/fallout4vr/src/fallout4savegame.cpp | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) diff --git a/src/games/fallout4vr/src/fallout4savegame.cpp b/src/games/fallout4vr/src/fallout4savegame.cpp index 063eb5c7..e5bdc95b 100644 --- a/src/games/fallout4vr/src/fallout4savegame.cpp +++ b/src/games/fallout4vr/src/fallout4savegame.cpp @@ -7,7 +7,8 @@ Fallout4SaveGame::Fallout4SaveGame(QString const &fileName, MOBase::IPluginGame { FileWrapper file(this, "FO4_SAVEGAME"); file.skip(); // header size - file.skip(); // header version + uint32_t headerVersion; + file.read(headerVersion); // header version file.read(m_SaveNumber); file.read(m_PCName); @@ -37,8 +38,11 @@ Fallout4SaveGame::Fallout4SaveGame(QString const &fileName, MOBase::IPluginGame file.readImage(384, true); file.skip(); // form version - file.read(ignore); // game version + unsigned char gameVersion; + file.read(gameVersion); // game version file.skip(); // plugin info size file.readPlugins(); + if (headerVersion >= 15) + file.readLightPlugins(); } From 068a3219ad5521f9fba85656de3bf5409f500fdc Mon Sep 17 00:00:00 2001 From: Hugues92 Date: Fri, 20 Oct 2017 13:13:27 +0200 Subject: [PATCH 0309/1544] [game_fallout76] Untested: Should update the save file format for Fallout 4 and Skyse SE to handle esl light plugins. --- src/games/fallout76/src/fallout4savegame.cpp | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) diff --git a/src/games/fallout76/src/fallout4savegame.cpp b/src/games/fallout76/src/fallout4savegame.cpp index 063eb5c7..e5bdc95b 100644 --- a/src/games/fallout76/src/fallout4savegame.cpp +++ b/src/games/fallout76/src/fallout4savegame.cpp @@ -7,7 +7,8 @@ Fallout4SaveGame::Fallout4SaveGame(QString const &fileName, MOBase::IPluginGame { FileWrapper file(this, "FO4_SAVEGAME"); file.skip(); // header size - file.skip(); // header version + uint32_t headerVersion; + file.read(headerVersion); // header version file.read(m_SaveNumber); file.read(m_PCName); @@ -37,8 +38,11 @@ Fallout4SaveGame::Fallout4SaveGame(QString const &fileName, MOBase::IPluginGame file.readImage(384, true); file.skip(); // form version - file.read(ignore); // game version + unsigned char gameVersion; + file.read(gameVersion); // game version file.skip(); // plugin info size file.readPlugins(); + if (headerVersion >= 15) + file.readLightPlugins(); } From 229025c4408fec8e72277442fe8abe3190e74aa2 Mon Sep 17 00:00:00 2001 From: Hugues92 Date: Fri, 20 Oct 2017 13:13:27 +0200 Subject: [PATCH 0310/1544] [game_fallout4] Untested: Should update the save file format for Fallout 4 and Skyse SE to handle esl light plugins. --- src/games/fallout4/src/fallout4savegame.cpp | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) diff --git a/src/games/fallout4/src/fallout4savegame.cpp b/src/games/fallout4/src/fallout4savegame.cpp index 063eb5c7..e5bdc95b 100644 --- a/src/games/fallout4/src/fallout4savegame.cpp +++ b/src/games/fallout4/src/fallout4savegame.cpp @@ -7,7 +7,8 @@ Fallout4SaveGame::Fallout4SaveGame(QString const &fileName, MOBase::IPluginGame { FileWrapper file(this, "FO4_SAVEGAME"); file.skip(); // header size - file.skip(); // header version + uint32_t headerVersion; + file.read(headerVersion); // header version file.read(m_SaveNumber); file.read(m_PCName); @@ -37,8 +38,11 @@ Fallout4SaveGame::Fallout4SaveGame(QString const &fileName, MOBase::IPluginGame file.readImage(384, true); file.skip(); // form version - file.read(ignore); // game version + unsigned char gameVersion; + file.read(gameVersion); // game version file.skip(); // plugin info size file.readPlugins(); + if (headerVersion >= 15) + file.readLightPlugins(); } From 632f59e0d25bf88af00c7cebc2c48ba9fbf1a570 Mon Sep 17 00:00:00 2001 From: Hugues92 Date: Fri, 20 Oct 2017 13:14:22 +0200 Subject: [PATCH 0311/1544] Untested: Should update the save file format for Fallout 4 and Skyse SE to handle esl light plugins. --- src/gamebryosavegame.cpp | 156 ++++++++++++++++++++++------- src/gamebryosavegame.h | 19 +++- src/gamebryosavegameinfo.cpp | 11 ++ src/gamebryosavegameinfowidget.cpp | 16 +++ 4 files changed, 166 insertions(+), 36 deletions(-) diff --git a/src/gamebryosavegame.cpp b/src/gamebryosavegame.cpp index 280bf26e..0e11fae0 100644 --- a/src/gamebryosavegame.cpp +++ b/src/gamebryosavegame.cpp @@ -182,14 +182,94 @@ template <> void readQDataStream(QDataStream &data, QString &value) value = QString::fromLatin1(buffer.data(), length); } + +void GamebryoSaveGame::FileWrapper::closeCompressedData() +{ + if (m_Game->compressionType == 0) { + } + else if (m_Game->compressionType == 1) { + m_Game->m_Plugins.push_back("Please create an issue on the MO github labeled \"Found zlib Compressed\" with your savefile attached"); + } + else if (m_Game->compressionType == 2) { + delete[] m_Data; + } + else + m_Game->m_Plugins.push_back("Please create an issue on the MO github labeled \"Found unknown Compressed\" with your savefile attached"); +} + +bool GamebryoSaveGame::FileWrapper::openCompressedData(int bytesToIgnore) +{ + if (m_Game->compressionType == 0) { + if (bytesToIgnore>0)//Just to make certain + skip(bytesToIgnore); + return false; + } + else if (m_Game->compressionType == 1) { + m_Game->m_Plugins.push_back("Please create an issue on the MO github labeled \"Found zlib Compressed\" with your savefile attached"); + return false; + } + else if (m_Game->compressionType == 2) { + unsigned long maxUncompressedSize; + read(maxUncompressedSize); + unsigned long compressedSize; + read(compressedSize); + char* compressed = new char[compressedSize]; + read(compressed, compressedSize); + + //unsigned long uncompressedSize=(65537)*255+bytesToIgnore‬; + unsigned long uncompressedSize = 16711935 + bytesToIgnore; + char * decompressed = new char[uncompressedSize]; + LZ4_decompress_safe_partial(compressed, decompressed, compressedSize, uncompressedSize, maxUncompressedSize); + delete[] compressed; + + m_Data = new QDataStream(QByteArray(decompressed, uncompressedSize)); + m_Data->skipRawData(bytesToIgnore); + + return true; + + } + else { + m_Game->m_Plugins.push_back("Please create an issue on the MO github labeled \"Found unknown Compressed\" with your savefile attached"); + return false; + } +} + +unsigned char GamebryoSaveGame::FileWrapper::readSaveGameVersion(int bytesToIgnore) +{ + if (m_Game->compressionType == 0) { + if (bytesToIgnore>0)//Just to make certain + skip(bytesToIgnore); + unsigned char version; + read(version); + return version; + } + else if (m_Game->compressionType == 1) { + m_Game->m_Plugins.push_back("Please create an issue on the MO github labeled \"Found zlib Compressed\" with your savefile attached"); + return 0; + } + else if (m_Game->compressionType == 2) { + // decompression already done by readSaveGameVersion + m_Data->skipRawData(bytesToIgnore); + + unsigned char version; + readQDataStream(*m_Data, version); + return version; + + } + else { + m_Game->m_Plugins.push_back("Please create an issue on the MO github labeled \"Found unknown Compressed\" with your savefile attached"); + return 0; + } +} + void GamebryoSaveGame::FileWrapper::readPlugins(int bytesToIgnore) { if(m_Game->compressionType==0){ if(bytesToIgnore>0)//Just to make certain - skip(bytesToIgnore); - unsigned char count; + skip(bytesToIgnore); + unsigned char count; read(count); - m_Game->m_Plugins.reserve(count); + m_Game->m_Plugins.reserve(count); for (std::size_t i = 0; i < count; ++i) { QString name; read(name); @@ -198,39 +278,47 @@ void GamebryoSaveGame::FileWrapper::readPlugins(int bytesToIgnore) }else if(m_Game->compressionType==1){ m_Game->m_Plugins.push_back("Please create an issue on the MO github labeled \"Found zlib Compressed\" with your savefile attached"); }else if(m_Game->compressionType==2){ - unsigned long maxUncompressedSize; - read(maxUncompressedSize); - unsigned long compressedSize; - read(compressedSize); - char* compressed=new char[compressedSize]; - read(compressed,compressedSize); + m_Data->skipRawData(bytesToIgnore); - //Using this maxPluginSize (2 byte limit on the length in bytes of the plugin names, with those same 2 bytes added in - //and there is a maximum of 255 or so plugins possible with an extra 5 bytes from the empty space.) - //to decrease the amount of data that has to be read in each savefile. Total is 16711940 (it wouldn't let me write it out in - //an equation - - //unsigned long uncompressedSize=(65537)*255+bytesToIgnore‬; - unsigned long uncompressedSize=16711935+bytesToIgnore; - char * decompressed=new char[uncompressedSize]; - LZ4_decompress_safe_partial(compressed,decompressed,compressedSize,uncompressedSize,maxUncompressedSize); - delete[] compressed; - - QDataStream data(QByteArray(decompressed,uncompressedSize)); - delete[] decompressed; - data.skipRawData(bytesToIgnore); - - //unsigned long loc=7; - //unsigned char count=decompressed[loc++]; unsigned char count; - readQDataStream(data,count); - //data.read(reinterpret_cast(&count),sizeof(count)); + readQDataStream(*m_Data,count); m_Game->m_Plugins.reserve(count); - for(std::size_t i=0;im_Plugins.push_back(name); - } - + for(std::size_t i=0;im_Plugins.push_back(name); + } } } + +void GamebryoSaveGame::FileWrapper::readLightPlugins(int bytesToIgnore) +{ + if (m_Game->compressionType == 0) { + if (bytesToIgnore>0)//Just to make certain + skip(bytesToIgnore); + uint16_t count; + read(count); + m_Game->m_LightPlugins.reserve(count); + for (std::size_t i = 0; i < count; ++i) { + QString name; + read(name); + m_Game->m_LightPlugins.push_back(name); + } + } + else if (m_Game->compressionType == 1) { + m_Game->m_Plugins.push_back("Please create an issue on the MO github labeled \"Found zlib Compressed\" with your savefile attached"); + } + else if (m_Game->compressionType == 2) { + m_Data->skipRawData(bytesToIgnore); + + uint16_t count; + readQDataStream(*m_Data, count); + m_Game->m_LightPlugins.reserve(count); + for (std::size_t i = 0; im_LightPlugins.push_back(name); + } + + } +} diff --git a/src/gamebryosavegame.h b/src/gamebryosavegame.h index e48296c6..2cf55e99 100644 --- a/src/gamebryosavegame.h +++ b/src/gamebryosavegame.h @@ -37,6 +37,7 @@ public: QString getPCLocation() const { return m_PCLocation; } unsigned long getSaveNumber() const { return m_SaveNumber; } QStringList const &getPlugins() const { return m_Plugins; } + QStringList const &getLightPlugins() const { return m_LightPlugins; } QImage const &getScreenshot() const { return m_Screenshot; } protected: @@ -88,10 +89,22 @@ protected: /* Reads RGB image from save */ void readImage(unsigned long width, unsigned long height, int scale = 0, bool alpha = false); - /* Read the plugin list */ + /* uncompress the begining of the compressed block */ + bool openCompressedData(int bytesToIgnore = 0); + + /* frees the uncompressed block */ + void closeCompressedData(); + + /* Read the save game version in the compressed block */ + unsigned char readSaveGameVersion(int bytesToIgnore=0); + + /* Read the plugin list */ void readPlugins(int bytesToIgnore=0); - /* Set the creation time from a system date */ + /* Read the light plugin list */ + void readLightPlugins(int bytesToIgnore = 0); + + /* Set the creation time from a system date */ void setCreationTime(::_SYSTEMTIME const &); private: @@ -99,6 +112,7 @@ protected: QFile m_File; bool m_HasFieldMarkers; bool m_BZString; + QDataStream* m_Data; }; void setCreationTime(_SYSTEMTIME const &time); @@ -110,6 +124,7 @@ protected: unsigned long m_SaveNumber; QDateTime m_CreationTime; QStringList m_Plugins; + QStringList m_LightPlugins; QImage m_Screenshot; MOBase::IPluginGame const *m_Game; unsigned short compressionType; diff --git a/src/gamebryosavegameinfo.cpp b/src/gamebryosavegameinfo.cpp index 52992e96..946947bb 100644 --- a/src/gamebryosavegameinfo.cpp +++ b/src/gamebryosavegameinfo.cpp @@ -40,6 +40,17 @@ GamebryoSaveGameInfo::MissingAssets GamebryoSaveGameInfo::getMissingAssets(QStri } } + for (QString const &pluginName : save->getLightPlugins()) { + switch (organizerCore->pluginList()->state(pluginName)) { + case MOBase::IPluginList::STATE_INACTIVE: + missingAssets[pluginName] = ProvidingModules{ organizerCore->pluginList()->origin(pluginName) }; + break; + case MOBase::IPluginList::STATE_MISSING: + missingAssets[pluginName] = ProvidingModules(); + break; + } + } + //Find out any other mods that might contain the esp/esm QStringList espFilter( { "*.esp", "*.esl", "*.esm" } ); diff --git a/src/gamebryosavegameinfowidget.cpp b/src/gamebryosavegameinfowidget.cpp index b7e326b8..d06b697b 100644 --- a/src/gamebryosavegameinfowidget.cpp +++ b/src/gamebryosavegameinfowidget.cpp @@ -97,6 +97,22 @@ void GamebryoSaveGameInfoWidget::setSave(QString const &file) pluginLabel->setFont(contentFont); layout->addWidget(pluginLabel); } + for (QString const &pluginName : save->getLightPlugins()) { + if (pluginList->state(pluginName) == MOBase::IPluginList::STATE_ACTIVE) { + continue; + } + + ++count; + + if (count > 10) { + break; + } + + QLabel *pluginLabel = new QLabel(pluginName); + pluginLabel->setIndent(10); + pluginLabel->setFont(contentFont); + layout->addWidget(pluginLabel); + } if (count > 10) { QLabel *dotDotLabel = new QLabel("..."); dotDotLabel->setIndent(10); From dcef4c5f4568c4d7e2627e74d71469e146f11830 Mon Sep 17 00:00:00 2001 From: Hugues92 Date: Fri, 20 Oct 2017 13:15:40 +0200 Subject: [PATCH 0312/1544] [game_skyrimse] Untested: Should update the save file format for Fallout 4 and Skyse SE to handle esl light plugins. --- src/games/skyrimse/src/skyrimsesavegame.cpp | 24 +++++++++------------ 1 file changed, 10 insertions(+), 14 deletions(-) diff --git a/src/games/skyrimse/src/skyrimsesavegame.cpp b/src/games/skyrimse/src/skyrimsesavegame.cpp index 29050cba..bb822a3f 100644 --- a/src/games/skyrimse/src/skyrimsesavegame.cpp +++ b/src/games/skyrimse/src/skyrimsesavegame.cpp @@ -53,22 +53,18 @@ SkyrimSESaveGame::SkyrimSESaveGame(QString const &fileName, MOBase::IPluginGame file.read(width); file.read(height); - //Skip the 2 empty bytes before the image begins. - //This is why we aren't using the readImage(scale,alpha) - //variant. - //file.skip(); file.read(compressionType); file.readImage(width,height,320,true); - //Skip reading the plugins altogether, due to problems with the save files. - //m_Plugins.push_back("Not Working due to save game weirdness"); - /* //Skip a single byte to get it to the right location - file.skip(); // form version - //Need to skip 14 more bytes - file.skip(7); - //file.skip(); // plugin info size - //Now in correct location to read plugins. - file.readPlugins();// */ - file.readPlugins(5); + file.openCompressedData(); + + uint16_t saveGameVersion = file.readSaveGameVersion(); + + file.readPlugins(3); + + if (saveGameVersion >= 78) + file.readLightPlugins(); + + file.closeCompressedData(); } From c22a86178a7ba5ba1f1bccc8cd40c7d37b5af9d6 Mon Sep 17 00:00:00 2001 From: Jeremy Rimpo Date: Fri, 20 Oct 2017 20:27:04 -0500 Subject: [PATCH 0313/1544] [game_skyrimse] Basic ESL updates --- src/games/skyrimse/src/game_skyrimse_en.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/games/skyrimse/src/game_skyrimse_en.ts b/src/games/skyrimse/src/game_skyrimse_en.ts index e770d773..f1e83405 100644 --- a/src/games/skyrimse/src/game_skyrimse_en.ts +++ b/src/games/skyrimse/src/game_skyrimse_en.ts @@ -22,7 +22,7 @@ - + Some of your plugins have invalid names! These plugins can not be loaded by the game. Please see mo_interface.log for a list of affected plugins and rename them. From 9754bf58a8e7ed376784b9220e4b64e0e7f517ff Mon Sep 17 00:00:00 2001 From: Jeremy Rimpo Date: Fri, 20 Oct 2017 20:27:05 -0500 Subject: [PATCH 0314/1544] Basic ESL updates --- src/gamebryosavegameinfo.cpp | 4 ++-- src/gamebryounmanagedmods.cpp | 2 +- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/src/gamebryosavegameinfo.cpp b/src/gamebryosavegameinfo.cpp index 518de909..42fe1e62 100644 --- a/src/gamebryosavegameinfo.cpp +++ b/src/gamebryosavegameinfo.cpp @@ -40,8 +40,8 @@ GamebryoSaveGameInfo::MissingAssets GamebryoSaveGameInfo::getMissingAssets(QStri } } - //Find out any other mods that might contain the esp/esm - QStringList espFilter( { "*.esp", "*.esm" } ); + //Find out any other mods that might contain the esp/esm/esl + QStringList espFilter( { "*.esp", "*.esm", "*.esl"} ); QString dataDir(organizerCore->managedGame()->dataDirectory().absolutePath()); diff --git a/src/gamebryounmanagedmods.cpp b/src/gamebryounmanagedmods.cpp index 7ad3c3cf..c6afbd74 100644 --- a/src/gamebryounmanagedmods.cpp +++ b/src/gamebryounmanagedmods.cpp @@ -17,7 +17,7 @@ QStringList GamebryoUnmangedMods::mods(bool onlyOfficial) const { QStringList mainPlugins = m_Game->primaryPlugins(); QDir dataDir(m_Game->dataDirectory()); - for (const QString &fileName : dataDir.entryList({"*.esp", "*.esm"})) { + for (const QString &fileName : dataDir.entryList({"*.esp", "*.esm", "*.esl"})) { if (!mainPlugins.contains(fileName, Qt::CaseInsensitive) && (!onlyOfficial || dlcPlugins.contains(fileName, Qt::CaseInsensitive))) { QFileInfo file(fileName); From 142a590379d9ad272e17eda31f47fa0e069d32b0 Mon Sep 17 00:00:00 2001 From: Jeremy Rimpo Date: Fri, 20 Oct 2017 20:27:05 -0500 Subject: [PATCH 0315/1544] [game_fallout4vr] Basic ESL updates --- src/games/fallout4vr/src/game_fallout4_en.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/games/fallout4vr/src/game_fallout4_en.ts b/src/games/fallout4vr/src/game_fallout4_en.ts index 4de40ceb..7fd0409f 100644 --- a/src/games/fallout4vr/src/game_fallout4_en.ts +++ b/src/games/fallout4vr/src/game_fallout4_en.ts @@ -13,7 +13,7 @@ Splash by %1 QObject - + Some of your plugins have invalid names! These plugins can not be loaded by the game. Please see mo_interface.log for a list of affected plugins and rename them. From 2272cbe1741a3c418e1373decd355e1b013c2e39 Mon Sep 17 00:00:00 2001 From: Jeremy Rimpo Date: Fri, 20 Oct 2017 20:27:05 -0500 Subject: [PATCH 0316/1544] [game_fallout76] Basic ESL updates --- src/games/fallout76/src/game_fallout4_en.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/games/fallout76/src/game_fallout4_en.ts b/src/games/fallout76/src/game_fallout4_en.ts index 4de40ceb..7fd0409f 100644 --- a/src/games/fallout76/src/game_fallout4_en.ts +++ b/src/games/fallout76/src/game_fallout4_en.ts @@ -13,7 +13,7 @@ Splash by %1 QObject - + Some of your plugins have invalid names! These plugins can not be loaded by the game. Please see mo_interface.log for a list of affected plugins and rename them. From 50592e037e3bee382ec6ae407540d35aaf2ff95b Mon Sep 17 00:00:00 2001 From: Jeremy Rimpo Date: Fri, 20 Oct 2017 20:27:05 -0500 Subject: [PATCH 0317/1544] [game_fallout4] Basic ESL updates --- src/games/fallout4/src/game_fallout4_en.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/games/fallout4/src/game_fallout4_en.ts b/src/games/fallout4/src/game_fallout4_en.ts index 4de40ceb..7fd0409f 100644 --- a/src/games/fallout4/src/game_fallout4_en.ts +++ b/src/games/fallout4/src/game_fallout4_en.ts @@ -13,7 +13,7 @@ Splash by %1 QObject - + Some of your plugins have invalid names! These plugins can not be loaded by the game. Please see mo_interface.log for a list of affected plugins and rename them. From fafc42951ac306414e4d342b37537042ea829c8b Mon Sep 17 00:00:00 2001 From: Jeremy Rimpo Date: Sun, 22 Oct 2017 04:36:06 -0500 Subject: [PATCH 0318/1544] [game_skyrimse] Add Creation Kit ESLs to Primary Plugins lists (implicitly active) --- src/games/skyrimse/src/gameskyrimse.cpp | 12 ++++++++++-- 1 file changed, 10 insertions(+), 2 deletions(-) diff --git a/src/games/skyrimse/src/gameskyrimse.cpp b/src/games/skyrimse/src/gameskyrimse.cpp index b826951c..fe2e44bc 100644 --- a/src/games/skyrimse/src/gameskyrimse.cpp +++ b/src/games/skyrimse/src/gameskyrimse.cpp @@ -261,7 +261,11 @@ QString GameSkyrimSE::steamAPPId() const } QStringList GameSkyrimSE::primaryPlugins() const { - return{ "skyrim.esm", "update.esm", "dawnguard.esm", "hearthfires.esm", "dragonborn.esm" };// }; + return{ "skyrim.esm", "update.esm", "dawnguard.esm", "hearthfires.esm", "dragonborn.esm", + "ccbgssse002-exoticarrows.esl", "ccbgssse003-zombies.esl", "ccbgssse004-ruinsedge.esl", + "ccbgssse006-stendarshammer.esl", "ccbgssse007-chrysamere.esl", "ccbgssse010-petdwarvenarmoredmudcrab.esl", + "ccbgssse014-spellpack01.esl", "ccbgssse019-staffofsheogorath.esl", "ccmtysse001-knightsofthenine.esl", + "ccqdrsse001-survivalmode.esl" };// }; } QStringList GameSkyrimSE::gameVariants() const @@ -287,7 +291,11 @@ QStringList GameSkyrimSE::iniFiles() const QStringList GameSkyrimSE::DLCPlugins() const { - return{ "" }; + return{ "dawnguard.esm", "hearthfires.esm", "dragonborn.esm", + "ccbgssse002-exoticarrows.esl", "ccbgssse003-zombies.esl", "ccbgssse004-ruinsedge.esl", + "ccbgssse006-stendarshammer.esl", "ccbgssse007-chrysamere.esl", "ccbgssse010-petdwarvenarmoredmudcrab.esl", + "ccbgssse014-spellpack01.esl", "ccbgssse019-staffofsheogorath.esl", "ccmtysse001-knightsofthenine.esl", + "ccqdrsse001-survivalmode.esl" }; } IPluginGame::LoadOrderMechanism GameSkyrimSE::loadOrderMechanism() const From bac22f537c79c4b56f9ada3b6ded622e2420bf6e Mon Sep 17 00:00:00 2001 From: Jeremy Rimpo Date: Sun, 22 Oct 2017 04:36:37 -0500 Subject: [PATCH 0319/1544] [game_fallout4vr] Add Creation Kit ESLs to Primary Plugins lists (implicitly active) --- src/games/fallout4vr/src/gamefallout4.cpp | 21 ++++++++++++++++++--- 1 file changed, 18 insertions(+), 3 deletions(-) diff --git a/src/games/fallout4vr/src/gamefallout4.cpp b/src/games/fallout4vr/src/gamefallout4.cpp index 38e0a7b7..46f4beb4 100644 --- a/src/games/fallout4vr/src/gamefallout4.cpp +++ b/src/games/fallout4vr/src/gamefallout4.cpp @@ -122,7 +122,15 @@ QString GameFallout4::steamAPPId() const } QStringList GameFallout4::primaryPlugins() const { - return {"fallout4.esm"}; + return {"fallout4.esm", "dlcrobot.esm", "dlcworkshop01.esm", "dlccoast.esm", "dlcworkshop02.esm", "dlcworkshop03.esm", "dlcnukaworld.esm", + "ccbgsfo4001-pipboy(black).esl", "ccbgsfo4002-pipboy(blue).esl", "ccbgsfo4003-pipboy(camo01).esl", + "ccbgsfo4004-pipboy(camo02).esl", "ccbgsfo4006-pipboy(chrome).esl", "ccbgsfo4012-pipboy(red).esl", + "ccbgsfo4014-pipboy(white).esl", "ccbgsfo4016-prey.esl", "ccbgsfo4017-mauler.esl", "ccbgsfo4018-gaussrifleprototype.esl", + "ccbgsfo4019-chinesestealtharmor.esl", "ccbgsfo4020-powerarmorskin(black).esl", "ccbgsfo4022-powerarmorskin(camo01).esl", + "ccbgsfo4023-powerarmorskin(camo02).esl", "ccbgsfo4025-powerarmorskin(chrome).esl", "ccbgsfo4038-horsearmor.esl", + "ccbgsfo4039-tunnelsnakes.esl", "ccbgsfo4041-doommarinearmor.esl", "ccbgsfo4042-bfg.esl", + "ccbgsfo4043-doomchainsaw.esl", "ccbgsfo4044-hellfirepowerarmor.esl", "ccfsvfo4001-modularmilitarybackpack.esl", + "ccfsvfo4002-midcenturymodern.esl", "ccfrsfo4001-handmadeshotgun.esl", "cceejfo4001-decorationpack.esl"}; } QStringList GameFallout4::gameVariants() const @@ -147,8 +155,15 @@ QStringList GameFallout4::iniFiles() const QStringList GameFallout4::DLCPlugins() const { - return {"dlcrobot.esm", "dlcworkshop01.esm", "dlccoast.esm", - "dlcworkshop02.esm", "dlcworkshop03.esm", "dlcnukaworld.esm"}; + return {"dlcrobot.esm", "dlcworkshop01.esm", "dlccoast.esm", "dlcworkshop02.esm", "dlcworkshop03.esm", "dlcnukaworld.esm", + "ccbgsfo4001-pipboy(black).esl", "ccbgsfo4002-pipboy(blue).esl", "ccbgsfo4003-pipboy(camo01).esl", + "ccbgsfo4004-pipboy(camo02).esl", "ccbgsfo4006-pipboy(chrome).esl", "ccbgsfo4012-pipboy(red).esl", + "ccbgsfo4014-pipboy(white).esl", "ccbgsfo4016-prey.esl", "ccbgsfo4017-mauler.esl", "ccbgsfo4018-gaussrifleprototype.esl", + "ccbgsfo4019-chinesestealtharmor.esl", "ccbgsfo4020-powerarmorskin(black).esl", "ccbgsfo4022-powerarmorskin(camo01).esl", + "ccbgsfo4023-powerarmorskin(camo02).esl", "ccbgsfo4025-powerarmorskin(chrome).esl", "ccbgsfo4038-horsearmor.esl", + "ccbgsfo4039-tunnelsnakes.esl", "ccbgsfo4041-doommarinearmor.esl", "ccbgsfo4042-bfg.esl", + "ccbgsfo4043-doomchainsaw.esl", "ccbgsfo4044-hellfirepowerarmor.esl", "ccfsvfo4001-modularmilitarybackpack.esl", + "ccfsvfo4002-midcenturymodern.esl", "ccfrsfo4001-handmadeshotgun.esl", "cceejfo4001-decorationpack.esl"}; } IPluginGame::LoadOrderMechanism GameFallout4::loadOrderMechanism() const From b5da731c3161b3e4ee634554a7aef650839987a5 Mon Sep 17 00:00:00 2001 From: Jeremy Rimpo Date: Sun, 22 Oct 2017 04:36:37 -0500 Subject: [PATCH 0320/1544] [game_fallout76] Add Creation Kit ESLs to Primary Plugins lists (implicitly active) --- src/games/fallout76/src/gamefallout4.cpp | 21 ++++++++++++++++++--- 1 file changed, 18 insertions(+), 3 deletions(-) diff --git a/src/games/fallout76/src/gamefallout4.cpp b/src/games/fallout76/src/gamefallout4.cpp index 38e0a7b7..46f4beb4 100644 --- a/src/games/fallout76/src/gamefallout4.cpp +++ b/src/games/fallout76/src/gamefallout4.cpp @@ -122,7 +122,15 @@ QString GameFallout4::steamAPPId() const } QStringList GameFallout4::primaryPlugins() const { - return {"fallout4.esm"}; + return {"fallout4.esm", "dlcrobot.esm", "dlcworkshop01.esm", "dlccoast.esm", "dlcworkshop02.esm", "dlcworkshop03.esm", "dlcnukaworld.esm", + "ccbgsfo4001-pipboy(black).esl", "ccbgsfo4002-pipboy(blue).esl", "ccbgsfo4003-pipboy(camo01).esl", + "ccbgsfo4004-pipboy(camo02).esl", "ccbgsfo4006-pipboy(chrome).esl", "ccbgsfo4012-pipboy(red).esl", + "ccbgsfo4014-pipboy(white).esl", "ccbgsfo4016-prey.esl", "ccbgsfo4017-mauler.esl", "ccbgsfo4018-gaussrifleprototype.esl", + "ccbgsfo4019-chinesestealtharmor.esl", "ccbgsfo4020-powerarmorskin(black).esl", "ccbgsfo4022-powerarmorskin(camo01).esl", + "ccbgsfo4023-powerarmorskin(camo02).esl", "ccbgsfo4025-powerarmorskin(chrome).esl", "ccbgsfo4038-horsearmor.esl", + "ccbgsfo4039-tunnelsnakes.esl", "ccbgsfo4041-doommarinearmor.esl", "ccbgsfo4042-bfg.esl", + "ccbgsfo4043-doomchainsaw.esl", "ccbgsfo4044-hellfirepowerarmor.esl", "ccfsvfo4001-modularmilitarybackpack.esl", + "ccfsvfo4002-midcenturymodern.esl", "ccfrsfo4001-handmadeshotgun.esl", "cceejfo4001-decorationpack.esl"}; } QStringList GameFallout4::gameVariants() const @@ -147,8 +155,15 @@ QStringList GameFallout4::iniFiles() const QStringList GameFallout4::DLCPlugins() const { - return {"dlcrobot.esm", "dlcworkshop01.esm", "dlccoast.esm", - "dlcworkshop02.esm", "dlcworkshop03.esm", "dlcnukaworld.esm"}; + return {"dlcrobot.esm", "dlcworkshop01.esm", "dlccoast.esm", "dlcworkshop02.esm", "dlcworkshop03.esm", "dlcnukaworld.esm", + "ccbgsfo4001-pipboy(black).esl", "ccbgsfo4002-pipboy(blue).esl", "ccbgsfo4003-pipboy(camo01).esl", + "ccbgsfo4004-pipboy(camo02).esl", "ccbgsfo4006-pipboy(chrome).esl", "ccbgsfo4012-pipboy(red).esl", + "ccbgsfo4014-pipboy(white).esl", "ccbgsfo4016-prey.esl", "ccbgsfo4017-mauler.esl", "ccbgsfo4018-gaussrifleprototype.esl", + "ccbgsfo4019-chinesestealtharmor.esl", "ccbgsfo4020-powerarmorskin(black).esl", "ccbgsfo4022-powerarmorskin(camo01).esl", + "ccbgsfo4023-powerarmorskin(camo02).esl", "ccbgsfo4025-powerarmorskin(chrome).esl", "ccbgsfo4038-horsearmor.esl", + "ccbgsfo4039-tunnelsnakes.esl", "ccbgsfo4041-doommarinearmor.esl", "ccbgsfo4042-bfg.esl", + "ccbgsfo4043-doomchainsaw.esl", "ccbgsfo4044-hellfirepowerarmor.esl", "ccfsvfo4001-modularmilitarybackpack.esl", + "ccfsvfo4002-midcenturymodern.esl", "ccfrsfo4001-handmadeshotgun.esl", "cceejfo4001-decorationpack.esl"}; } IPluginGame::LoadOrderMechanism GameFallout4::loadOrderMechanism() const From 6d3ba228749fd28cd44eed63f29dca4615a89a80 Mon Sep 17 00:00:00 2001 From: Jeremy Rimpo Date: Sun, 22 Oct 2017 04:36:37 -0500 Subject: [PATCH 0321/1544] [game_fallout4] Add Creation Kit ESLs to Primary Plugins lists (implicitly active) --- src/games/fallout4/src/gamefallout4.cpp | 21 ++++++++++++++++++--- 1 file changed, 18 insertions(+), 3 deletions(-) diff --git a/src/games/fallout4/src/gamefallout4.cpp b/src/games/fallout4/src/gamefallout4.cpp index 38e0a7b7..46f4beb4 100644 --- a/src/games/fallout4/src/gamefallout4.cpp +++ b/src/games/fallout4/src/gamefallout4.cpp @@ -122,7 +122,15 @@ QString GameFallout4::steamAPPId() const } QStringList GameFallout4::primaryPlugins() const { - return {"fallout4.esm"}; + return {"fallout4.esm", "dlcrobot.esm", "dlcworkshop01.esm", "dlccoast.esm", "dlcworkshop02.esm", "dlcworkshop03.esm", "dlcnukaworld.esm", + "ccbgsfo4001-pipboy(black).esl", "ccbgsfo4002-pipboy(blue).esl", "ccbgsfo4003-pipboy(camo01).esl", + "ccbgsfo4004-pipboy(camo02).esl", "ccbgsfo4006-pipboy(chrome).esl", "ccbgsfo4012-pipboy(red).esl", + "ccbgsfo4014-pipboy(white).esl", "ccbgsfo4016-prey.esl", "ccbgsfo4017-mauler.esl", "ccbgsfo4018-gaussrifleprototype.esl", + "ccbgsfo4019-chinesestealtharmor.esl", "ccbgsfo4020-powerarmorskin(black).esl", "ccbgsfo4022-powerarmorskin(camo01).esl", + "ccbgsfo4023-powerarmorskin(camo02).esl", "ccbgsfo4025-powerarmorskin(chrome).esl", "ccbgsfo4038-horsearmor.esl", + "ccbgsfo4039-tunnelsnakes.esl", "ccbgsfo4041-doommarinearmor.esl", "ccbgsfo4042-bfg.esl", + "ccbgsfo4043-doomchainsaw.esl", "ccbgsfo4044-hellfirepowerarmor.esl", "ccfsvfo4001-modularmilitarybackpack.esl", + "ccfsvfo4002-midcenturymodern.esl", "ccfrsfo4001-handmadeshotgun.esl", "cceejfo4001-decorationpack.esl"}; } QStringList GameFallout4::gameVariants() const @@ -147,8 +155,15 @@ QStringList GameFallout4::iniFiles() const QStringList GameFallout4::DLCPlugins() const { - return {"dlcrobot.esm", "dlcworkshop01.esm", "dlccoast.esm", - "dlcworkshop02.esm", "dlcworkshop03.esm", "dlcnukaworld.esm"}; + return {"dlcrobot.esm", "dlcworkshop01.esm", "dlccoast.esm", "dlcworkshop02.esm", "dlcworkshop03.esm", "dlcnukaworld.esm", + "ccbgsfo4001-pipboy(black).esl", "ccbgsfo4002-pipboy(blue).esl", "ccbgsfo4003-pipboy(camo01).esl", + "ccbgsfo4004-pipboy(camo02).esl", "ccbgsfo4006-pipboy(chrome).esl", "ccbgsfo4012-pipboy(red).esl", + "ccbgsfo4014-pipboy(white).esl", "ccbgsfo4016-prey.esl", "ccbgsfo4017-mauler.esl", "ccbgsfo4018-gaussrifleprototype.esl", + "ccbgsfo4019-chinesestealtharmor.esl", "ccbgsfo4020-powerarmorskin(black).esl", "ccbgsfo4022-powerarmorskin(camo01).esl", + "ccbgsfo4023-powerarmorskin(camo02).esl", "ccbgsfo4025-powerarmorskin(chrome).esl", "ccbgsfo4038-horsearmor.esl", + "ccbgsfo4039-tunnelsnakes.esl", "ccbgsfo4041-doommarinearmor.esl", "ccbgsfo4042-bfg.esl", + "ccbgsfo4043-doomchainsaw.esl", "ccbgsfo4044-hellfirepowerarmor.esl", "ccfsvfo4001-modularmilitarybackpack.esl", + "ccfsvfo4002-midcenturymodern.esl", "ccfrsfo4001-handmadeshotgun.esl", "cceejfo4001-decorationpack.esl"}; } IPluginGame::LoadOrderMechanism GameFallout4::loadOrderMechanism() const From 60ad989d8aae1aca925e6b2da57c19ebbd638b01 Mon Sep 17 00:00:00 2001 From: Jeremy Rimpo Date: Mon, 23 Oct 2017 17:45:57 -0500 Subject: [PATCH 0322/1544] Fix delete [] on non-array --- src/gamebryosavegame.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/gamebryosavegame.cpp b/src/gamebryosavegame.cpp index 0e11fae0..99db7d5f 100644 --- a/src/gamebryosavegame.cpp +++ b/src/gamebryosavegame.cpp @@ -191,7 +191,7 @@ void GamebryoSaveGame::FileWrapper::closeCompressedData() m_Game->m_Plugins.push_back("Please create an issue on the MO github labeled \"Found zlib Compressed\" with your savefile attached"); } else if (m_Game->compressionType == 2) { - delete[] m_Data; + delete m_Data; } else m_Game->m_Plugins.push_back("Please create an issue on the MO github labeled \"Found unknown Compressed\" with your savefile attached"); From 580d32001fa8982e6e40f147b1e21fa3952a3372 Mon Sep 17 00:00:00 2001 From: Jeremy Rimpo Date: Mon, 23 Oct 2017 17:49:49 -0500 Subject: [PATCH 0323/1544] [game_skyrimse] Fix readPlugins offset --- src/games/skyrimse/src/skyrimsesavegame.cpp | 52 ++++++++++----------- 1 file changed, 26 insertions(+), 26 deletions(-) diff --git a/src/games/skyrimse/src/skyrimsesavegame.cpp b/src/games/skyrimse/src/skyrimsesavegame.cpp index bb822a3f..e12dea7b 100644 --- a/src/games/skyrimse/src/skyrimsesavegame.cpp +++ b/src/games/skyrimse/src/skyrimsesavegame.cpp @@ -32,39 +32,39 @@ SkyrimSESaveGame::SkyrimSESaveGame(QString const &fileName, MOBase::IPluginGame //A file time is a 64-bit value that represents the number of 100-nanosecond //intervals that have elapsed since 12:00 A.M. January 1, 1601 Coordinated Universal Time (UTC). //So we need to convert that to something useful - - //For some reason, the file time is off by about 6 hours. - //So we need to subtract those 6 hours from the filetime. - _ULARGE_INTEGER time; - time.LowPart=ftime.dwLowDateTime; - time.HighPart=ftime.dwHighDateTime; - time.QuadPart-=2.16e11; - ftime.dwHighDateTime=time.HighPart; - ftime.dwLowDateTime=time.LowPart; - + + //For some reason, the file time is off by about 6 hours. + //So we need to subtract those 6 hours from the filetime. + _ULARGE_INTEGER time; + time.LowPart=ftime.dwLowDateTime; + time.HighPart=ftime.dwHighDateTime; + time.QuadPart-=2.16e11; + ftime.dwHighDateTime=time.HighPart; + ftime.dwLowDateTime=time.LowPart; + SYSTEMTIME ctime; ::FileTimeToSystemTime(&ftime, &ctime); setCreationTime(ctime); - //file.skip(); - - unsigned long width; - unsigned long height; - file.read(width); - file.read(height); - - file.read(compressionType); - - file.readImage(width,height,320,true); + //file.skip(); - file.openCompressedData(); + unsigned long width; + unsigned long height; + file.read(width); + file.read(height); - uint16_t saveGameVersion = file.readSaveGameVersion(); + file.read(compressionType); - file.readPlugins(3); + file.readImage(width,height,320,true); - if (saveGameVersion >= 78) - file.readLightPlugins(); + file.openCompressedData(); - file.closeCompressedData(); + uint16_t saveGameVersion = file.readSaveGameVersion(); + + file.readPlugins(4); + + if (saveGameVersion >= 78) + file.readLightPlugins(); + + file.closeCompressedData(); } From 3f6e445fd72672f3301cef6e443ee8147ba0a3b5 Mon Sep 17 00:00:00 2001 From: Jeremy Rimpo Date: Mon, 23 Oct 2017 18:16:31 -0500 Subject: [PATCH 0324/1544] Add 'Missing ESLs' list and shorted max number - This could be combined but was currently inaccurate - May want to tweak the output for non ESL-enabled games --- src/gamebryosavegameinfowidget.cpp | 55 +++++++++++++++++++++--------- 1 file changed, 38 insertions(+), 17 deletions(-) diff --git a/src/gamebryosavegameinfowidget.cpp b/src/gamebryosavegameinfowidget.cpp index d06b697b..45845248 100644 --- a/src/gamebryosavegameinfowidget.cpp +++ b/src/gamebryosavegameinfowidget.cpp @@ -88,7 +88,7 @@ void GamebryoSaveGameInfoWidget::setSave(QString const &file) ++count; - if (count > 10) { + if (count > 7) { break; } @@ -97,22 +97,6 @@ void GamebryoSaveGameInfoWidget::setSave(QString const &file) pluginLabel->setFont(contentFont); layout->addWidget(pluginLabel); } - for (QString const &pluginName : save->getLightPlugins()) { - if (pluginList->state(pluginName) == MOBase::IPluginList::STATE_ACTIVE) { - continue; - } - - ++count; - - if (count > 10) { - break; - } - - QLabel *pluginLabel = new QLabel(pluginName); - pluginLabel->setIndent(10); - pluginLabel->setFont(contentFont); - layout->addWidget(pluginLabel); - } if (count > 10) { QLabel *dotDotLabel = new QLabel("..."); dotDotLabel->setIndent(10); @@ -125,4 +109,41 @@ void GamebryoSaveGameInfoWidget::setSave(QString const &file) dotDotLabel->setFont(contentFont); layout->addWidget(dotDotLabel); } + QLabel *headerEsl = new QLabel(tr("Missing ESLs")); + QFont headerEslFont = headerEsl->font(); + QFont contentEslFont = headerEslFont; + headerEslFont.setItalic(true); + contentEslFont.setBold(true); + contentEslFont.setPointSize(7); + headerEsl->setFont(headerEslFont); + layout->addWidget(headerEsl); + int countEsl = 0; + for (QString const &pluginName : save->getLightPlugins()) { + if (pluginList->state(pluginName) == MOBase::IPluginList::STATE_ACTIVE) { + continue; + } + + ++countEsl; + + if (countEsl > 7) { + break; + } + + QLabel *pluginLabel = new QLabel(pluginName); + pluginLabel->setIndent(10); + pluginLabel->setFont(contentFont); + layout->addWidget(pluginLabel); + } + if (countEsl > 7) { + QLabel *dotDotLabel = new QLabel("..."); + dotDotLabel->setIndent(10); + dotDotLabel->setFont(contentFont); + layout->addWidget(dotDotLabel); + } + if (countEsl == 0) { + QLabel *dotDotLabel = new QLabel(tr("None")); + dotDotLabel->setIndent(10); + dotDotLabel->setFont(contentFont); + layout->addWidget(dotDotLabel); + } } From 6a9e462fce72a4c7d29b75f8e338d387ec7f156d Mon Sep 17 00:00:00 2001 From: Jeremy Rimpo Date: Mon, 23 Oct 2017 21:22:18 -0500 Subject: [PATCH 0325/1544] Add an ESL enabled check --- src/gamebryosavegame.cpp | 5 +- src/gamebryosavegame.h | 4 +- src/gamebryosavegameinfowidget.cpp | 209 ++++++++++++++--------------- 3 files changed, 109 insertions(+), 109 deletions(-) diff --git a/src/gamebryosavegame.cpp b/src/gamebryosavegame.cpp index 99db7d5f..4692f179 100644 --- a/src/gamebryosavegame.cpp +++ b/src/gamebryosavegame.cpp @@ -15,10 +15,11 @@ #include #include -GamebryoSaveGame::GamebryoSaveGame(QString const &file, MOBase::IPluginGame const *game) : +GamebryoSaveGame::GamebryoSaveGame(QString const &file, MOBase::IPluginGame const *game, bool const lightEnabled) : m_FileName(file), m_CreationTime(QFileInfo(file).lastModified()), - m_Game(game) + m_Game(game), + m_LightEnabled(lightEnabled) { } diff --git a/src/gamebryosavegame.h b/src/gamebryosavegame.h index 2cf55e99..b8ff2a09 100644 --- a/src/gamebryosavegame.h +++ b/src/gamebryosavegame.h @@ -19,7 +19,7 @@ namespace MOBase { class IPluginGame; } class GamebryoSaveGame : public MOBase::ISaveGame { public: - GamebryoSaveGame(QString const &file, MOBase::IPluginGame const *game); + GamebryoSaveGame(QString const &file, MOBase::IPluginGame const *game, bool const lightEnabled = false); virtual ~GamebryoSaveGame(); @@ -39,6 +39,7 @@ public: QStringList const &getPlugins() const { return m_Plugins; } QStringList const &getLightPlugins() const { return m_LightPlugins; } QImage const &getScreenshot() const { return m_Screenshot; } + bool const &isLightEnabled() const { return m_LightEnabled; } protected: @@ -128,6 +129,7 @@ protected: QImage m_Screenshot; MOBase::IPluginGame const *m_Game; unsigned short compressionType; + bool m_LightEnabled; }; diff --git a/src/gamebryosavegameinfowidget.cpp b/src/gamebryosavegameinfowidget.cpp index 45845248..9b4b2a70 100644 --- a/src/gamebryosavegameinfowidget.cpp +++ b/src/gamebryosavegameinfowidget.cpp @@ -27,123 +27,120 @@ GamebryoSaveGameInfoWidget::GamebryoSaveGameInfoWidget(GamebryoSaveGameInfo const *info, QWidget *parent) - : MOBase::ISaveGameInfoWidget(parent) - , ui(new Ui::GamebryoSaveGameInfoWidget) - , m_Info(info) -{ - ui->setupUi(this); - this->setWindowFlags(Qt::ToolTip | Qt::BypassGraphicsProxyWidget); - setWindowOpacity(style()->styleHint(QStyle::SH_ToolTipLabel_Opacity, 0, this) / qreal(255.0)); - ui->gameFrame->setStyleSheet("background-color: transparent;"); + : MOBase::ISaveGameInfoWidget(parent), ui(new Ui::GamebryoSaveGameInfoWidget), m_Info(info) { + ui->setupUi(this); + this->setWindowFlags(Qt::ToolTip | Qt::BypassGraphicsProxyWidget); + setWindowOpacity(style()->styleHint(QStyle::SH_ToolTipLabel_Opacity, 0, this) / qreal(255.0)); + ui->gameFrame->setStyleSheet("background-color: transparent;"); - QVBoxLayout *gameLayout = new QVBoxLayout(); - gameLayout->setMargin(0); - gameLayout->setSpacing(2); - ui->gameFrame->setLayout(gameLayout); + QVBoxLayout *gameLayout = new QVBoxLayout(); + gameLayout->setMargin(0); + gameLayout->setSpacing(2); + ui->gameFrame->setLayout(gameLayout); } -GamebryoSaveGameInfoWidget::~GamebryoSaveGameInfoWidget() -{ - delete ui; +GamebryoSaveGameInfoWidget::~GamebryoSaveGameInfoWidget() { + delete ui; } -void GamebryoSaveGameInfoWidget::setSave(QString const &file) -{ - std::unique_ptr save( - std::move(dynamic_cast(m_Info->getSaveGameInfo(file)))); - ui->saveNumLabel->setText(QString("%1").arg(save->getSaveNumber())); - ui->characterLabel->setText(save->getPCName()); - ui->locationLabel->setText(save->getPCLocation()); - ui->levelLabel->setText(QString("%1").arg(save->getPCLevel())); - //This somewhat contorted code is because on my system at least, the - //old way of doing this appears to give short date and long time. - QDateTime t = save->getCreationTime(); - ui->dateLabel->setText(t.date().toString(Qt::DefaultLocaleShortDate) + " " + - t.time().toString(Qt::DefaultLocaleLongDate)); - ui->screenshotLabel->setPixmap(QPixmap::fromImage(save->getScreenshot())); - if (ui->gameFrame->layout() != nullptr) { - QLayoutItem *item = nullptr; - while ((item = ui->gameFrame->layout()->takeAt(0)) != nullptr) { - delete item->widget(); - delete item; - } - ui->gameFrame->layout()->setSizeConstraint(QLayout::SetFixedSize); - } - - QLayout *layout = ui->gameFrame->layout(); - QLabel *header = new QLabel(tr("Missing ESPs")); - QFont headerFont = header->font(); - QFont contentFont = headerFont; - headerFont.setItalic(true); - contentFont.setBold(true); - contentFont.setPointSize(7); - header->setFont(headerFont); - layout->addWidget(header); - int count = 0; - MOBase::IPluginList *pluginList = m_Info->m_Game->m_Organizer->pluginList(); - for (QString const &pluginName : save->getPlugins()) { - if (pluginList->state(pluginName) == MOBase::IPluginList::STATE_ACTIVE) { - continue; +void GamebryoSaveGameInfoWidget::setSave(QString const &file) { + std::unique_ptr < GamebryoSaveGame const> save( + std::move(dynamic_cast(m_Info->getSaveGameInfo(file)))); + ui->saveNumLabel->setText(QString("%1").arg(save->getSaveNumber())); + ui->characterLabel->setText(save->getPCName()); + ui->locationLabel->setText(save->getPCLocation()); + ui->levelLabel->setText(QString("%1").arg(save->getPCLevel())); + //This somewhat contorted code is because on my system at least, the + //old way of doing this appears to give short date and long time. + QDateTime t = save->getCreationTime(); + ui->dateLabel->setText(t.date().toString(Qt::DefaultLocaleShortDate) + " " + + t.time().toString(Qt::DefaultLocaleLongDate)); + ui->screenshotLabel->setPixmap(QPixmap::fromImage(save->getScreenshot())); + if (ui->gameFrame->layout() != nullptr) { + QLayoutItem *item = nullptr; + while ((item = ui->gameFrame->layout()->takeAt(0)) != nullptr) { + delete item->widget(); + delete item; + } + ui->gameFrame->layout()->setSizeConstraint(QLayout::SetFixedSize); } - ++count; + QLayout *layout = ui->gameFrame->layout(); + QLabel *header = new QLabel(tr("Missing ESPs")); + QFont headerFont = header->font(); + QFont contentFont = headerFont; + headerFont.setItalic(true); + contentFont.setBold(true); + contentFont.setPointSize(7); + header->setFont(headerFont); + layout->addWidget(header); + int count = 0; + MOBase::IPluginList *pluginList = m_Info->m_Game->m_Organizer->pluginList(); + for (QString const &pluginName : save->getPlugins()) { + if (pluginList->state(pluginName) == MOBase::IPluginList::STATE_ACTIVE) { + continue; + } + ++count; + + if (count > 7) { + break; + } + + QLabel *pluginLabel = new QLabel(pluginName); + pluginLabel->setIndent(10); + pluginLabel->setFont(contentFont); + layout->addWidget(pluginLabel); + } if (count > 7) { - break; + QLabel *dotDotLabel = new QLabel("..."); + dotDotLabel->setIndent(10); + dotDotLabel->setFont(contentFont); + layout->addWidget(dotDotLabel); } + if (count == 0) { + QLabel *dotDotLabel = new QLabel(tr("None")); + dotDotLabel->setIndent(10); + dotDotLabel->setFont(contentFont); + layout->addWidget(dotDotLabel); + } + if (save->isLightEnabled()) { + QLabel *headerEsl = new QLabel(tr("Missing ESLs")); + QFont headerEslFont = headerEsl->font(); + QFont contentEslFont = headerEslFont; + headerEslFont.setItalic(true); + contentEslFont.setBold(true); + contentEslFont.setPointSize(7); + headerEsl->setFont(headerEslFont); + layout->addWidget(headerEsl); + int countEsl = 0; + for (QString const &pluginName : save->getLightPlugins()) { + if (pluginList->state(pluginName) == MOBase::IPluginList::STATE_ACTIVE) { + continue; + } - QLabel *pluginLabel = new QLabel(pluginName); - pluginLabel->setIndent(10); - pluginLabel->setFont(contentFont); - layout->addWidget(pluginLabel); - } - if (count > 10) { - QLabel *dotDotLabel = new QLabel("..."); - dotDotLabel->setIndent(10); - dotDotLabel->setFont(contentFont); - layout->addWidget(dotDotLabel); - } - if (count == 0) { - QLabel *dotDotLabel = new QLabel(tr("None")); - dotDotLabel->setIndent(10); - dotDotLabel->setFont(contentFont); - layout->addWidget(dotDotLabel); - } - QLabel *headerEsl = new QLabel(tr("Missing ESLs")); - QFont headerEslFont = headerEsl->font(); - QFont contentEslFont = headerEslFont; - headerEslFont.setItalic(true); - contentEslFont.setBold(true); - contentEslFont.setPointSize(7); - headerEsl->setFont(headerEslFont); - layout->addWidget(headerEsl); - int countEsl = 0; - for (QString const &pluginName : save->getLightPlugins()) { - if (pluginList->state(pluginName) == MOBase::IPluginList::STATE_ACTIVE) { - continue; - } + ++countEsl; - ++countEsl; + if (countEsl > 7) { + break; + } - if (countEsl > 7) { - break; - } - - QLabel *pluginLabel = new QLabel(pluginName); - pluginLabel->setIndent(10); - pluginLabel->setFont(contentFont); - layout->addWidget(pluginLabel); - } - if (countEsl > 7) { - QLabel *dotDotLabel = new QLabel("..."); - dotDotLabel->setIndent(10); - dotDotLabel->setFont(contentFont); - layout->addWidget(dotDotLabel); - } - if (countEsl == 0) { - QLabel *dotDotLabel = new QLabel(tr("None")); - dotDotLabel->setIndent(10); - dotDotLabel->setFont(contentFont); - layout->addWidget(dotDotLabel); - } + QLabel *pluginLabel = new QLabel(pluginName); + pluginLabel->setIndent(10); + pluginLabel->setFont(contentFont); + layout->addWidget(pluginLabel); + } + if (countEsl > 7) { + QLabel *dotDotLabel = new QLabel("..."); + dotDotLabel->setIndent(10); + dotDotLabel->setFont(contentFont); + layout->addWidget(dotDotLabel); + } + if (countEsl == 0) { + QLabel *dotDotLabel = new QLabel(tr("None")); + dotDotLabel->setIndent(10); + dotDotLabel->setFont(contentFont); + layout->addWidget(dotDotLabel); + } + } } From a7d308a7a8c552c0eecab804ea548014c836893e Mon Sep 17 00:00:00 2001 From: Jeremy Rimpo Date: Mon, 23 Oct 2017 21:22:18 -0500 Subject: [PATCH 0326/1544] [game_skyrimse] Add an ESL enabled check --- src/games/skyrimse/src/skyrimsesavegame.cpp | 4 ++-- src/games/skyrimse/src/skyrimsesavegame.h | 2 +- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/src/games/skyrimse/src/skyrimsesavegame.cpp b/src/games/skyrimse/src/skyrimsesavegame.cpp index e12dea7b..571dfdbf 100644 --- a/src/games/skyrimse/src/skyrimsesavegame.cpp +++ b/src/games/skyrimse/src/skyrimsesavegame.cpp @@ -2,8 +2,8 @@ #include -SkyrimSESaveGame::SkyrimSESaveGame(QString const &fileName, MOBase::IPluginGame const *game) : - GamebryoSaveGame(fileName, game) +SkyrimSESaveGame::SkyrimSESaveGame(QString const &fileName, MOBase::IPluginGame const *game, bool const lightEnabled) : + GamebryoSaveGame(fileName, game, lightEnabled) { FileWrapper file(this, "TESV_SAVEGAME"); //10bytes file.skip(); // header size "TESV_SAVEGAME" diff --git a/src/games/skyrimse/src/skyrimsesavegame.h b/src/games/skyrimse/src/skyrimsesavegame.h index 79e78657..0fe7c3d7 100644 --- a/src/games/skyrimse/src/skyrimsesavegame.h +++ b/src/games/skyrimse/src/skyrimsesavegame.h @@ -8,7 +8,7 @@ namespace MOBase { class IPluginGame; } class SkyrimSESaveGame : public GamebryoSaveGame { public: - SkyrimSESaveGame(QString const &fileName, MOBase::IPluginGame const *game); + SkyrimSESaveGame(QString const &fileName, MOBase::IPluginGame const *game, bool const lightEnabled = true); }; #endif // _SKYRIMSESAVEGAME_H From c39e0a20af373d7572fce66b8c532c06a3515aa7 Mon Sep 17 00:00:00 2001 From: Jeremy Rimpo Date: Mon, 23 Oct 2017 21:22:19 -0500 Subject: [PATCH 0327/1544] [game_fallout4vr] Add an ESL enabled check --- src/games/fallout4vr/src/fallout4savegame.cpp | 4 ++-- src/games/fallout4vr/src/fallout4savegame.h | 2 +- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/src/games/fallout4vr/src/fallout4savegame.cpp b/src/games/fallout4vr/src/fallout4savegame.cpp index e5bdc95b..c8d1d9e6 100644 --- a/src/games/fallout4vr/src/fallout4savegame.cpp +++ b/src/games/fallout4vr/src/fallout4savegame.cpp @@ -2,8 +2,8 @@ #include -Fallout4SaveGame::Fallout4SaveGame(QString const &fileName, MOBase::IPluginGame const *game) : - GamebryoSaveGame(fileName, game) +Fallout4SaveGame::Fallout4SaveGame(QString const &fileName, MOBase::IPluginGame const *game, bool const lightEnabled) : + GamebryoSaveGame(fileName, game, lightEnabled) { FileWrapper file(this, "FO4_SAVEGAME"); file.skip(); // header size diff --git a/src/games/fallout4vr/src/fallout4savegame.h b/src/games/fallout4vr/src/fallout4savegame.h index d5d47e82..98dffc9f 100644 --- a/src/games/fallout4vr/src/fallout4savegame.h +++ b/src/games/fallout4vr/src/fallout4savegame.h @@ -8,7 +8,7 @@ namespace MOBase { class IPluginGame; } class Fallout4SaveGame : public GamebryoSaveGame { public: - Fallout4SaveGame(QString const &fileName, MOBase::IPluginGame const *game); + Fallout4SaveGame(QString const &fileName, MOBase::IPluginGame const *game, bool const lightEnabled = true); }; #endif // FALLOUT4SAVEGAME_H From 90afefc274a62ef3cdc3fb8ee139a6e380e49daf Mon Sep 17 00:00:00 2001 From: Jeremy Rimpo Date: Mon, 23 Oct 2017 21:22:19 -0500 Subject: [PATCH 0328/1544] [game_fallout76] Add an ESL enabled check --- src/games/fallout76/src/fallout4savegame.cpp | 4 ++-- src/games/fallout76/src/fallout4savegame.h | 2 +- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/src/games/fallout76/src/fallout4savegame.cpp b/src/games/fallout76/src/fallout4savegame.cpp index e5bdc95b..c8d1d9e6 100644 --- a/src/games/fallout76/src/fallout4savegame.cpp +++ b/src/games/fallout76/src/fallout4savegame.cpp @@ -2,8 +2,8 @@ #include -Fallout4SaveGame::Fallout4SaveGame(QString const &fileName, MOBase::IPluginGame const *game) : - GamebryoSaveGame(fileName, game) +Fallout4SaveGame::Fallout4SaveGame(QString const &fileName, MOBase::IPluginGame const *game, bool const lightEnabled) : + GamebryoSaveGame(fileName, game, lightEnabled) { FileWrapper file(this, "FO4_SAVEGAME"); file.skip(); // header size diff --git a/src/games/fallout76/src/fallout4savegame.h b/src/games/fallout76/src/fallout4savegame.h index d5d47e82..98dffc9f 100644 --- a/src/games/fallout76/src/fallout4savegame.h +++ b/src/games/fallout76/src/fallout4savegame.h @@ -8,7 +8,7 @@ namespace MOBase { class IPluginGame; } class Fallout4SaveGame : public GamebryoSaveGame { public: - Fallout4SaveGame(QString const &fileName, MOBase::IPluginGame const *game); + Fallout4SaveGame(QString const &fileName, MOBase::IPluginGame const *game, bool const lightEnabled = true); }; #endif // FALLOUT4SAVEGAME_H From cbd35439bc5d9c60dc72b7e99c9e2322102d64cd Mon Sep 17 00:00:00 2001 From: Jeremy Rimpo Date: Mon, 23 Oct 2017 21:22:19 -0500 Subject: [PATCH 0329/1544] [game_fallout4] Add an ESL enabled check --- src/games/fallout4/src/fallout4savegame.cpp | 4 ++-- src/games/fallout4/src/fallout4savegame.h | 2 +- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/src/games/fallout4/src/fallout4savegame.cpp b/src/games/fallout4/src/fallout4savegame.cpp index e5bdc95b..c8d1d9e6 100644 --- a/src/games/fallout4/src/fallout4savegame.cpp +++ b/src/games/fallout4/src/fallout4savegame.cpp @@ -2,8 +2,8 @@ #include -Fallout4SaveGame::Fallout4SaveGame(QString const &fileName, MOBase::IPluginGame const *game) : - GamebryoSaveGame(fileName, game) +Fallout4SaveGame::Fallout4SaveGame(QString const &fileName, MOBase::IPluginGame const *game, bool const lightEnabled) : + GamebryoSaveGame(fileName, game, lightEnabled) { FileWrapper file(this, "FO4_SAVEGAME"); file.skip(); // header size diff --git a/src/games/fallout4/src/fallout4savegame.h b/src/games/fallout4/src/fallout4savegame.h index d5d47e82..98dffc9f 100644 --- a/src/games/fallout4/src/fallout4savegame.h +++ b/src/games/fallout4/src/fallout4savegame.h @@ -8,7 +8,7 @@ namespace MOBase { class IPluginGame; } class Fallout4SaveGame : public GamebryoSaveGame { public: - Fallout4SaveGame(QString const &fileName, MOBase::IPluginGame const *game); + Fallout4SaveGame(QString const &fileName, MOBase::IPluginGame const *game, bool const lightEnabled = true); }; #endif // FALLOUT4SAVEGAME_H From 7674808d0b4cb35cd384e1f604f6f2e4e1fc1f5b Mon Sep 17 00:00:00 2001 From: Jeremy Rimpo Date: Mon, 23 Oct 2017 23:26:28 -0500 Subject: [PATCH 0330/1544] [game_fallout4vr] Stabilize FO4 save reader --- src/games/fallout4vr/src/fallout4savegame.cpp | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/src/games/fallout4vr/src/fallout4savegame.cpp b/src/games/fallout4vr/src/fallout4savegame.cpp index c8d1d9e6..ddd3f8d2 100644 --- a/src/games/fallout4vr/src/fallout4savegame.cpp +++ b/src/games/fallout4vr/src/fallout4savegame.cpp @@ -37,12 +37,12 @@ Fallout4SaveGame::Fallout4SaveGame(QString const &fileName, MOBase::IPluginGame file.readImage(384, true); - file.skip(); // form version - unsigned char gameVersion; - file.read(gameVersion); // game version - file.skip(); // plugin info size + file.skip(); // form version + QString gameVersion; + file.read(gameVersion); // game version + file.skip(); // plugin info size file.readPlugins(); - if (headerVersion >= 15) + if (headerVersion > 15) file.readLightPlugins(); } From efe141d82405a4d039be45ce05875eb4c23e4cf5 Mon Sep 17 00:00:00 2001 From: Jeremy Rimpo Date: Mon, 23 Oct 2017 23:26:28 -0500 Subject: [PATCH 0331/1544] [game_fallout76] Stabilize FO4 save reader --- src/games/fallout76/src/fallout4savegame.cpp | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/src/games/fallout76/src/fallout4savegame.cpp b/src/games/fallout76/src/fallout4savegame.cpp index c8d1d9e6..ddd3f8d2 100644 --- a/src/games/fallout76/src/fallout4savegame.cpp +++ b/src/games/fallout76/src/fallout4savegame.cpp @@ -37,12 +37,12 @@ Fallout4SaveGame::Fallout4SaveGame(QString const &fileName, MOBase::IPluginGame file.readImage(384, true); - file.skip(); // form version - unsigned char gameVersion; - file.read(gameVersion); // game version - file.skip(); // plugin info size + file.skip(); // form version + QString gameVersion; + file.read(gameVersion); // game version + file.skip(); // plugin info size file.readPlugins(); - if (headerVersion >= 15) + if (headerVersion > 15) file.readLightPlugins(); } From 3624950dd02098c8032e2bd6fcd259a9aefda617 Mon Sep 17 00:00:00 2001 From: Jeremy Rimpo Date: Mon, 23 Oct 2017 23:26:28 -0500 Subject: [PATCH 0332/1544] [game_fallout4] Stabilize FO4 save reader --- src/games/fallout4/src/fallout4savegame.cpp | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/src/games/fallout4/src/fallout4savegame.cpp b/src/games/fallout4/src/fallout4savegame.cpp index c8d1d9e6..ddd3f8d2 100644 --- a/src/games/fallout4/src/fallout4savegame.cpp +++ b/src/games/fallout4/src/fallout4savegame.cpp @@ -37,12 +37,12 @@ Fallout4SaveGame::Fallout4SaveGame(QString const &fileName, MOBase::IPluginGame file.readImage(384, true); - file.skip(); // form version - unsigned char gameVersion; - file.read(gameVersion); // game version - file.skip(); // plugin info size + file.skip(); // form version + QString gameVersion; + file.read(gameVersion); // game version + file.skip(); // plugin info size file.readPlugins(); - if (headerVersion >= 15) + if (headerVersion > 15) file.readLightPlugins(); } From 7257f70f9d6ee125354930a27c69594fc804945d Mon Sep 17 00:00:00 2001 From: LePresidente Date: Tue, 24 Oct 2017 14:33:14 +0200 Subject: [PATCH 0333/1544] [game_skyrimse] Changed gamename to lowercase to fix ini configurator. Changed name for skse binary. --- src/games/skyrimse/src/gameskyrimse.cpp | 2 +- src/games/skyrimse/src/skyrimsescriptextender.cpp | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/src/games/skyrimse/src/gameskyrimse.cpp b/src/games/skyrimse/src/gameskyrimse.cpp index fe2e44bc..3af9764c 100644 --- a/src/games/skyrimse/src/gameskyrimse.cpp +++ b/src/games/skyrimse/src/gameskyrimse.cpp @@ -275,7 +275,7 @@ QStringList GameSkyrimSE::gameVariants() const QString GameSkyrimSE::gameShortName() const { - return "SkyrimSE"; + return "skyrimse"; } QString GameSkyrimSE::gameNexusName() const diff --git a/src/games/skyrimse/src/skyrimsescriptextender.cpp b/src/games/skyrimse/src/skyrimsescriptextender.cpp index d2e9b586..0cbb1213 100644 --- a/src/games/skyrimse/src/skyrimsescriptextender.cpp +++ b/src/games/skyrimse/src/skyrimsescriptextender.cpp @@ -10,7 +10,7 @@ SkyrimSEScriptExtender::SkyrimSEScriptExtender(GameGamebryo const *game) : QString SkyrimSEScriptExtender::name() const { - return "sksese"; + return "skse64"; } QStringList SkyrimSEScriptExtender::saveGameAttachmentExtensions() const From 312edee9c07707aadf8a77e70d4c407d92738a5f Mon Sep 17 00:00:00 2001 From: LePresidente Date: Tue, 24 Oct 2017 14:37:25 +0200 Subject: [PATCH 0334/1544] [game_fallout4vr] Added fallout4custom.ini as a valid ini file. --- src/games/fallout4vr/src/gamefallout4.cpp | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/src/games/fallout4vr/src/gamefallout4.cpp b/src/games/fallout4vr/src/gamefallout4.cpp index 46f4beb4..f90ebffb 100644 --- a/src/games/fallout4vr/src/gamefallout4.cpp +++ b/src/games/fallout4vr/src/gamefallout4.cpp @@ -108,6 +108,7 @@ void GameFallout4::initializeProfile(const QDir &path, ProfileSettings settings) } copyToProfile(myGamesPath(), path, "fallout4prefs.ini"); + copyToProfile(myGamesPath(), path, "fallout4custom.ini"); } } @@ -150,7 +151,7 @@ QString GameFallout4::gameNexusName() const QStringList GameFallout4::iniFiles() const { - return { "fallout4.ini", "fallout4prefs.ini" }; + return { "fallout4.ini", "fallout4prefs.ini", "fallout4custom.ini" }; } QStringList GameFallout4::DLCPlugins() const From bcdb4616ad68ffafb5b1e253ef0f9b32388eb55b Mon Sep 17 00:00:00 2001 From: LePresidente Date: Tue, 24 Oct 2017 14:37:25 +0200 Subject: [PATCH 0335/1544] [game_fallout76] Added fallout4custom.ini as a valid ini file. --- src/games/fallout76/src/gamefallout4.cpp | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/src/games/fallout76/src/gamefallout4.cpp b/src/games/fallout76/src/gamefallout4.cpp index 46f4beb4..f90ebffb 100644 --- a/src/games/fallout76/src/gamefallout4.cpp +++ b/src/games/fallout76/src/gamefallout4.cpp @@ -108,6 +108,7 @@ void GameFallout4::initializeProfile(const QDir &path, ProfileSettings settings) } copyToProfile(myGamesPath(), path, "fallout4prefs.ini"); + copyToProfile(myGamesPath(), path, "fallout4custom.ini"); } } @@ -150,7 +151,7 @@ QString GameFallout4::gameNexusName() const QStringList GameFallout4::iniFiles() const { - return { "fallout4.ini", "fallout4prefs.ini" }; + return { "fallout4.ini", "fallout4prefs.ini", "fallout4custom.ini" }; } QStringList GameFallout4::DLCPlugins() const From f72df77978bdba5f2085a10088cb769138d8fc31 Mon Sep 17 00:00:00 2001 From: LePresidente Date: Tue, 24 Oct 2017 14:37:25 +0200 Subject: [PATCH 0336/1544] [game_fallout4] Added fallout4custom.ini as a valid ini file. --- src/games/fallout4/src/gamefallout4.cpp | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/src/games/fallout4/src/gamefallout4.cpp b/src/games/fallout4/src/gamefallout4.cpp index 46f4beb4..f90ebffb 100644 --- a/src/games/fallout4/src/gamefallout4.cpp +++ b/src/games/fallout4/src/gamefallout4.cpp @@ -108,6 +108,7 @@ void GameFallout4::initializeProfile(const QDir &path, ProfileSettings settings) } copyToProfile(myGamesPath(), path, "fallout4prefs.ini"); + copyToProfile(myGamesPath(), path, "fallout4custom.ini"); } } @@ -150,7 +151,7 @@ QString GameFallout4::gameNexusName() const QStringList GameFallout4::iniFiles() const { - return { "fallout4.ini", "fallout4prefs.ini" }; + return { "fallout4.ini", "fallout4prefs.ini", "fallout4custom.ini" }; } QStringList GameFallout4::DLCPlugins() const From d8943366d2683b591477fd2fe0bf4cf49328d191 Mon Sep 17 00:00:00 2001 From: Jeremy Rimpo Date: Thu, 26 Oct 2017 16:29:19 -0500 Subject: [PATCH 0337/1544] [game_skyrimse] Do not update status of primary plugins --- .../skyrimse/src/skyrimsegameplugins.cpp | 45 +++++++++++-------- 1 file changed, 26 insertions(+), 19 deletions(-) diff --git a/src/games/skyrimse/src/skyrimsegameplugins.cpp b/src/games/skyrimse/src/skyrimsegameplugins.cpp index de70d3df..a3829866 100644 --- a/src/games/skyrimse/src/skyrimsegameplugins.cpp +++ b/src/games/skyrimse/src/skyrimsegameplugins.cpp @@ -96,7 +96,8 @@ bool SkyrimSEGamePlugins::readPluginList(MOBase::IPluginList *pluginList, bool useLoadOrder) { QStringList plugins = pluginList->pluginNames(); - QStringList loadOrder = organizer()->managedGame()->primaryPlugins(); + QStringList primaryPlugins = organizer()->managedGame()->primaryPlugins(); + QStringList loadOrder(primaryPlugins); for (const QString &pluginName : loadOrder) { if (pluginList->state(pluginName) != IPluginList::STATE_MISSING) { @@ -124,27 +125,33 @@ bool SkyrimSEGamePlugins::readPluginList(MOBase::IPluginList *pluginList, if ((line.size() > 0) && (line.at(0) != '#')) { pluginName = localCodec()->toUnicode(line.trimmed().constData()); } - if (pluginName.startsWith('*')) { - pluginName.remove(0, 1); - if (pluginName.size() > 0) { - pluginList->setState(pluginName, IPluginList::STATE_ACTIVE); - plugins.removeAll(pluginName); - if (!loadOrder.contains(pluginName, Qt::CaseInsensitive)) { - loadOrder.append(pluginName); - } - } - } - else - { - if (pluginName.size() > 0) { - pluginList->setState(pluginName, IPluginList::STATE_INACTIVE); - plugins.removeAll(pluginName); - if (!loadOrder.contains(pluginName, Qt::CaseInsensitive)) { - loadOrder.append(pluginName); + if (!primaryPlugins.contains(pluginName, Qt::CaseInsensitive)) { + if (pluginName.startsWith('*')) { + pluginName.remove(0, 1); + if (pluginName.size() > 0) { + pluginList->setState(pluginName, IPluginList::STATE_ACTIVE); + plugins.removeAll(pluginName); + if (!loadOrder.contains(pluginName, Qt::CaseInsensitive)) { + loadOrder.append(pluginName); + } + } + } + else + { + if (pluginName.size() > 0) { + pluginList->setState(pluginName, IPluginList::STATE_INACTIVE); + plugins.removeAll(pluginName); + if (!loadOrder.contains(pluginName, Qt::CaseInsensitive)) { + loadOrder.append(pluginName); + } } } } - + else + { + pluginName.remove(0, 1); + plugins.removeAll(pluginName); + } } file.close(); From 578e4c254dd9deda3809ddca5a93a3daa1208225 Mon Sep 17 00:00:00 2001 From: LePresidente Date: Sun, 29 Oct 2017 11:21:02 +0200 Subject: [PATCH 0338/1544] use the new BinaryName variable. --- src/gamebryoscriptextender.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/gamebryoscriptextender.cpp b/src/gamebryoscriptextender.cpp index a1bc4ed6..3c3405ca 100644 --- a/src/gamebryoscriptextender.cpp +++ b/src/gamebryoscriptextender.cpp @@ -16,7 +16,7 @@ GamebryoScriptExtender::~GamebryoScriptExtender() QString GamebryoScriptExtender::loaderName() const { - return name() + "_loader.exe"; + return BinaryName(); } QString GamebryoScriptExtender::loaderPath() const From 8c0da26ed774e78acd2ffe62ec7cde8d656de09e Mon Sep 17 00:00:00 2001 From: LePresidente Date: Sun, 29 Oct 2017 11:45:10 +0200 Subject: [PATCH 0339/1544] [game_falloutnv] Updated to changes in modorganizer-game_features --- src/games/falloutnv/src/falloutnvscriptextender.cpp | 9 +++++++-- src/games/falloutnv/src/falloutnvscriptextender.h | 3 ++- 2 files changed, 9 insertions(+), 3 deletions(-) diff --git a/src/games/falloutnv/src/falloutnvscriptextender.cpp b/src/games/falloutnv/src/falloutnvscriptextender.cpp index d57a19b1..72f11d82 100644 --- a/src/games/falloutnv/src/falloutnvscriptextender.cpp +++ b/src/games/falloutnv/src/falloutnvscriptextender.cpp @@ -8,9 +8,14 @@ FalloutNVScriptExtender::FalloutNVScriptExtender(GameGamebryo const *game) : { } -QString FalloutNVScriptExtender::name() const +QString FalloutNVScriptExtender::BinaryName() const { - return "nvse"; + return "nvse_loader.exe"; +} + +QString FalloutNVScriptExtender::PluginPath() const +{ + return "nvse/plugins"; } QStringList FalloutNVScriptExtender::saveGameAttachmentExtensions() const diff --git a/src/games/falloutnv/src/falloutnvscriptextender.h b/src/games/falloutnv/src/falloutnvscriptextender.h index eba6e287..41a095b7 100644 --- a/src/games/falloutnv/src/falloutnvscriptextender.h +++ b/src/games/falloutnv/src/falloutnvscriptextender.h @@ -10,7 +10,8 @@ class FalloutNVScriptExtender : public GamebryoScriptExtender public: FalloutNVScriptExtender(const GameGamebryo *game); - virtual QString name() const override; + virtual QString BinaryName() const override; + virtual QString PluginPath() const override; virtual QStringList saveGameAttachmentExtensions() const override; From e3cfc102f4c134c2081a51d1f0a114a5363a03a9 Mon Sep 17 00:00:00 2001 From: LePresidente Date: Sun, 29 Oct 2017 11:47:15 +0200 Subject: [PATCH 0340/1544] [game_fallout3] Updated to changes in modorganizer-game_features --- src/games/fallout3/src/fallout3scriptextender.cpp | 9 +++++++-- src/games/fallout3/src/fallout3scriptextender.h | 3 ++- 2 files changed, 9 insertions(+), 3 deletions(-) diff --git a/src/games/fallout3/src/fallout3scriptextender.cpp b/src/games/fallout3/src/fallout3scriptextender.cpp index 085bddd9..c0f17fbb 100644 --- a/src/games/fallout3/src/fallout3scriptextender.cpp +++ b/src/games/fallout3/src/fallout3scriptextender.cpp @@ -8,9 +8,14 @@ Fallout3ScriptExtender::Fallout3ScriptExtender(GameGamebryo const *game) : { } -QString Fallout3ScriptExtender::name() const +QString Fallout3ScriptExtender::BinaryName() const { - return "fose"; + return "fose_loader.exe"; +} + +QString Fallout3ScriptExtender::PluginPath() const +{ + return "fose/plugins"; } QStringList Fallout3ScriptExtender::saveGameAttachmentExtensions() const diff --git a/src/games/fallout3/src/fallout3scriptextender.h b/src/games/fallout3/src/fallout3scriptextender.h index fe648395..828f5b77 100644 --- a/src/games/fallout3/src/fallout3scriptextender.h +++ b/src/games/fallout3/src/fallout3scriptextender.h @@ -11,7 +11,8 @@ class Fallout3ScriptExtender : public GamebryoScriptExtender public: Fallout3ScriptExtender(GameGamebryo const *game); - virtual QString name() const override; + virtual QString BinaryName() const override; + virtual QString PluginPath() const override; virtual QStringList saveGameAttachmentExtensions() const override; From d88a7473ab47ca833b9d22fb78e1acdb8dedef42 Mon Sep 17 00:00:00 2001 From: LePresidente Date: Sun, 29 Oct 2017 11:50:06 +0200 Subject: [PATCH 0341/1544] [game_skyrim] Updated to changes in modorganizer-game_features --- src/games/skyrim/src/skyrimscriptextender.cpp | 9 +++++++-- src/games/skyrim/src/skyrimscriptextender.h | 3 ++- 2 files changed, 9 insertions(+), 3 deletions(-) diff --git a/src/games/skyrim/src/skyrimscriptextender.cpp b/src/games/skyrim/src/skyrimscriptextender.cpp index f9a9317b..cea586e7 100644 --- a/src/games/skyrim/src/skyrimscriptextender.cpp +++ b/src/games/skyrim/src/skyrimscriptextender.cpp @@ -8,12 +8,17 @@ SkyrimScriptExtender::SkyrimScriptExtender(GameGamebryo const *game) : { } -QString SkyrimScriptExtender::name() const +QString SkyrimScriptExtender::BinaryName() const { return "skse"; } +QString SkyrimScriptExtender::PluginPath() const +{ + return "skse/plugins"; +} + QStringList SkyrimScriptExtender::saveGameAttachmentExtensions() const { - return { name() }; + return { "skse" }; } diff --git a/src/games/skyrim/src/skyrimscriptextender.h b/src/games/skyrim/src/skyrimscriptextender.h index 7f1e14b4..43242413 100644 --- a/src/games/skyrim/src/skyrimscriptextender.h +++ b/src/games/skyrim/src/skyrimscriptextender.h @@ -10,7 +10,8 @@ class SkyrimScriptExtender : public GamebryoScriptExtender public: SkyrimScriptExtender(const GameGamebryo *game); - virtual QString name() const override; + virtual QString BinaryName() const override; + virtual QString PluginPath() const override; virtual QStringList saveGameAttachmentExtensions() const override; From 9e27334a1e79176a2390a9e54e16d0e2d0173d9f Mon Sep 17 00:00:00 2001 From: LePresidente Date: Sun, 29 Oct 2017 11:51:45 +0200 Subject: [PATCH 0342/1544] [game_oblivion] Updated to changes in modorganizer-game_features --- src/games/oblivion/src/oblivionscriptextender.cpp | 11 ++++++++--- src/games/oblivion/src/oblivionscriptextender.h | 3 ++- 2 files changed, 10 insertions(+), 4 deletions(-) diff --git a/src/games/oblivion/src/oblivionscriptextender.cpp b/src/games/oblivion/src/oblivionscriptextender.cpp index 7db7d466..6c6ef557 100644 --- a/src/games/oblivion/src/oblivionscriptextender.cpp +++ b/src/games/oblivion/src/oblivionscriptextender.cpp @@ -12,12 +12,17 @@ OblivionScriptExtender::~OblivionScriptExtender() { } -QString OblivionScriptExtender::name() const +QString OblivionScriptExtender::BinaryName() const { - return "obse"; + return "obse_loader.exe"; +} + +QString OblivionScriptExtender::PluginPath() const +{ + return "obse/plugins"; } QStringList OblivionScriptExtender::saveGameAttachmentExtensions() const { - return { name() }; + return { "obse" }; } diff --git a/src/games/oblivion/src/oblivionscriptextender.h b/src/games/oblivion/src/oblivionscriptextender.h index d1010e56..310573e6 100644 --- a/src/games/oblivion/src/oblivionscriptextender.h +++ b/src/games/oblivion/src/oblivionscriptextender.h @@ -11,7 +11,8 @@ public: OblivionScriptExtender(const GameGamebryo *game); ~OblivionScriptExtender(); - virtual QString name() const override; + virtual QString BinaryName() const override; + virtual QString PluginPath() const override; virtual QStringList saveGameAttachmentExtensions() const override; From c97b2a17e0534fa99cb299c95df780abe5661d8c Mon Sep 17 00:00:00 2001 From: LePresidente Date: Sun, 29 Oct 2017 11:52:17 +0200 Subject: [PATCH 0343/1544] [game_skyrim] Forgot to append "_loader.exe" to the BinaryName --- src/games/skyrim/src/skyrimscriptextender.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/games/skyrim/src/skyrimscriptextender.cpp b/src/games/skyrim/src/skyrimscriptextender.cpp index cea586e7..6c56dbe1 100644 --- a/src/games/skyrim/src/skyrimscriptextender.cpp +++ b/src/games/skyrim/src/skyrimscriptextender.cpp @@ -10,7 +10,7 @@ SkyrimScriptExtender::SkyrimScriptExtender(GameGamebryo const *game) : QString SkyrimScriptExtender::BinaryName() const { - return "skse"; + return "skse_loader.exe"; } QString SkyrimScriptExtender::PluginPath() const From a6e357cec7c20a89397faaf153c1dd71475c73f6 Mon Sep 17 00:00:00 2001 From: LePresidente Date: Sun, 29 Oct 2017 11:54:33 +0200 Subject: [PATCH 0344/1544] [game_skyrimse] Updated to changes in modorganizer-game_features --- src/games/skyrimse/src/skyrimsescriptextender.cpp | 9 +++++++-- src/games/skyrimse/src/skyrimsescriptextender.h | 3 ++- 2 files changed, 9 insertions(+), 3 deletions(-) diff --git a/src/games/skyrimse/src/skyrimsescriptextender.cpp b/src/games/skyrimse/src/skyrimsescriptextender.cpp index 0cbb1213..5e09f3c3 100644 --- a/src/games/skyrimse/src/skyrimsescriptextender.cpp +++ b/src/games/skyrimse/src/skyrimsescriptextender.cpp @@ -8,9 +8,14 @@ SkyrimSEScriptExtender::SkyrimSEScriptExtender(GameGamebryo const *game) : { } -QString SkyrimSEScriptExtender::name() const +QString SkyrimSEScriptExtender::BinaryName() const { - return "skse64"; + return "skse64_loader.exe"; +} + +QString SkyrimSEScriptExtender::PluginPath() const +{ + return "skse/plugins"; } QStringList SkyrimSEScriptExtender::saveGameAttachmentExtensions() const diff --git a/src/games/skyrimse/src/skyrimsescriptextender.h b/src/games/skyrimse/src/skyrimsescriptextender.h index 5a338184..df1337a5 100644 --- a/src/games/skyrimse/src/skyrimsescriptextender.h +++ b/src/games/skyrimse/src/skyrimsescriptextender.h @@ -10,7 +10,8 @@ class SkyrimSEScriptExtender : public GamebryoScriptExtender public: SkyrimSEScriptExtender(GameGamebryo const *game); - virtual QString name() const override; + virtual QString BinaryName() const override; + virtual QString PluginPath() const override; virtual QStringList saveGameAttachmentExtensions() const override; From 37209e0b14646842a14d2f438a395208e2e8eeba Mon Sep 17 00:00:00 2001 From: LePresidente Date: Sun, 29 Oct 2017 11:58:02 +0200 Subject: [PATCH 0345/1544] [game_fallout4vr] Updated to changes in modorganizer-game_features --- src/games/fallout4vr/src/fallout4scriptextender.cpp | 9 +++++++-- src/games/fallout4vr/src/fallout4scriptextender.h | 3 ++- 2 files changed, 9 insertions(+), 3 deletions(-) diff --git a/src/games/fallout4vr/src/fallout4scriptextender.cpp b/src/games/fallout4vr/src/fallout4scriptextender.cpp index 7eb54a90..21c930c9 100644 --- a/src/games/fallout4vr/src/fallout4scriptextender.cpp +++ b/src/games/fallout4vr/src/fallout4scriptextender.cpp @@ -8,9 +8,14 @@ Fallout4ScriptExtender::Fallout4ScriptExtender(GameGamebryo const *game) : { } -QString Fallout4ScriptExtender::name() const +QString Fallout4ScriptExtender::BinaryName() const { - return "f4se"; + return "f4se_loader.exe"; +} + +QString Fallout4ScriptExtender::PluginPath() const +{ + return "f4se/plugins"; } QStringList Fallout4ScriptExtender::saveGameAttachmentExtensions() const diff --git a/src/games/fallout4vr/src/fallout4scriptextender.h b/src/games/fallout4vr/src/fallout4scriptextender.h index 6f9b17e6..4c134276 100644 --- a/src/games/fallout4vr/src/fallout4scriptextender.h +++ b/src/games/fallout4vr/src/fallout4scriptextender.h @@ -10,7 +10,8 @@ class Fallout4ScriptExtender : public GamebryoScriptExtender public: Fallout4ScriptExtender(GameGamebryo const *game); - virtual QString name() const override; + virtual QString BinaryName() const override; + virtual QString PluginPath() const override; virtual QStringList saveGameAttachmentExtensions() const override; From 6f3dcf1ba38f20d34080f4d83b2a8fbe7c11133e Mon Sep 17 00:00:00 2001 From: LePresidente Date: Sun, 29 Oct 2017 11:58:02 +0200 Subject: [PATCH 0346/1544] [game_fallout76] Updated to changes in modorganizer-game_features --- src/games/fallout76/src/fallout4scriptextender.cpp | 9 +++++++-- src/games/fallout76/src/fallout4scriptextender.h | 3 ++- 2 files changed, 9 insertions(+), 3 deletions(-) diff --git a/src/games/fallout76/src/fallout4scriptextender.cpp b/src/games/fallout76/src/fallout4scriptextender.cpp index 7eb54a90..21c930c9 100644 --- a/src/games/fallout76/src/fallout4scriptextender.cpp +++ b/src/games/fallout76/src/fallout4scriptextender.cpp @@ -8,9 +8,14 @@ Fallout4ScriptExtender::Fallout4ScriptExtender(GameGamebryo const *game) : { } -QString Fallout4ScriptExtender::name() const +QString Fallout4ScriptExtender::BinaryName() const { - return "f4se"; + return "f4se_loader.exe"; +} + +QString Fallout4ScriptExtender::PluginPath() const +{ + return "f4se/plugins"; } QStringList Fallout4ScriptExtender::saveGameAttachmentExtensions() const diff --git a/src/games/fallout76/src/fallout4scriptextender.h b/src/games/fallout76/src/fallout4scriptextender.h index 6f9b17e6..4c134276 100644 --- a/src/games/fallout76/src/fallout4scriptextender.h +++ b/src/games/fallout76/src/fallout4scriptextender.h @@ -10,7 +10,8 @@ class Fallout4ScriptExtender : public GamebryoScriptExtender public: Fallout4ScriptExtender(GameGamebryo const *game); - virtual QString name() const override; + virtual QString BinaryName() const override; + virtual QString PluginPath() const override; virtual QStringList saveGameAttachmentExtensions() const override; From 93c80f0adbc274c1da6849ef153e0879cacefb21 Mon Sep 17 00:00:00 2001 From: LePresidente Date: Sun, 29 Oct 2017 11:58:02 +0200 Subject: [PATCH 0347/1544] [game_fallout4] Updated to changes in modorganizer-game_features --- src/games/fallout4/src/fallout4scriptextender.cpp | 9 +++++++-- src/games/fallout4/src/fallout4scriptextender.h | 3 ++- 2 files changed, 9 insertions(+), 3 deletions(-) diff --git a/src/games/fallout4/src/fallout4scriptextender.cpp b/src/games/fallout4/src/fallout4scriptextender.cpp index 7eb54a90..21c930c9 100644 --- a/src/games/fallout4/src/fallout4scriptextender.cpp +++ b/src/games/fallout4/src/fallout4scriptextender.cpp @@ -8,9 +8,14 @@ Fallout4ScriptExtender::Fallout4ScriptExtender(GameGamebryo const *game) : { } -QString Fallout4ScriptExtender::name() const +QString Fallout4ScriptExtender::BinaryName() const { - return "f4se"; + return "f4se_loader.exe"; +} + +QString Fallout4ScriptExtender::PluginPath() const +{ + return "f4se/plugins"; } QStringList Fallout4ScriptExtender::saveGameAttachmentExtensions() const diff --git a/src/games/fallout4/src/fallout4scriptextender.h b/src/games/fallout4/src/fallout4scriptextender.h index 6f9b17e6..4c134276 100644 --- a/src/games/fallout4/src/fallout4scriptextender.h +++ b/src/games/fallout4/src/fallout4scriptextender.h @@ -10,7 +10,8 @@ class Fallout4ScriptExtender : public GamebryoScriptExtender public: Fallout4ScriptExtender(GameGamebryo const *game); - virtual QString name() const override; + virtual QString BinaryName() const override; + virtual QString PluginPath() const override; virtual QStringList saveGameAttachmentExtensions() const override; From 6fb89a66a2efe2e1ab50d80ba200e28a0478108a Mon Sep 17 00:00:00 2001 From: Jeremy Rimpo Date: Sun, 29 Oct 2017 19:29:06 -0500 Subject: [PATCH 0348/1544] Add file architecture getter --- src/gamebryoscriptextender.cpp | 5 +++++ src/gamebryoscriptextender.h | 2 ++ src/gamegamebryo.cpp | 36 ++++++++++++++++++++++++++++++++++ src/gamegamebryo.h | 3 ++- 4 files changed, 45 insertions(+), 1 deletion(-) diff --git a/src/gamebryoscriptextender.cpp b/src/gamebryoscriptextender.cpp index a1bc4ed6..f5b7938b 100644 --- a/src/gamebryoscriptextender.cpp +++ b/src/gamebryoscriptextender.cpp @@ -38,3 +38,8 @@ QString GamebryoScriptExtender::getExtenderVersion() const return m_Game->getVersion(loaderName()); } +WORD GamebryoScriptExtender::getArch() const +{ + return m_Game->getArch(loaderName()); +} + diff --git a/src/gamebryoscriptextender.h b/src/gamebryoscriptextender.h index 6386e952..807e7cf5 100644 --- a/src/gamebryoscriptextender.h +++ b/src/gamebryoscriptextender.h @@ -20,6 +20,8 @@ public: virtual QString getExtenderVersion() const override; + virtual WORD getArch() const override; + protected: GameGamebryo const * const m_Game; }; diff --git a/src/gamegamebryo.cpp b/src/gamegamebryo.cpp index 1102201f..fc291b86 100644 --- a/src/gamegamebryo.cpp +++ b/src/gamegamebryo.cpp @@ -224,6 +224,42 @@ QString GameGamebryo::getVersion(QString const &program) const .arg(LOWORD(pFileInfo->dwFileVersionLS)); } +WORD GameGamebryo::getArch(QString const &program) const +{ + WORD arch = 0; + //This *really* needs to be factored out + LPCSTR app_name = ("\\\\?\\" + + QDir::toNativeSeparators(this->gameDirectory().absoluteFilePath(program)).toStdString()).c_str(); + + WIN32_FIND_DATA FindFileData; + HANDLE hFind = ::FindFirstFile(app_name, &FindFileData); + + //exit if the binary was not found + if (hFind == INVALID_HANDLE_VALUE) return arch; + + HANDLE hFile = CreateFile(app_name, GENERIC_READ, FILE_SHARE_READ, NULL, OPEN_EXISTING, FILE_ATTRIBUTE_READONLY, NULL); + if (hFile == INVALID_HANDLE_VALUE) goto cleanup; + + HANDLE hMapping = CreateFileMapping(hFile, NULL, PAGE_READONLY | SEC_IMAGE, 0, 0, program.toStdString().c_str()); + if (hMapping == INVALID_HANDLE_VALUE) goto cleanup; + + LPVOID addrHeader = MapViewOfFile(hMapping, FILE_MAP_READ, 0, 0, 0); + if (addrHeader == NULL) goto cleanup; //couldn't memory map the file + + PIMAGE_NT_HEADERS peHdr = ImageNtHeader(addrHeader); + if (peHdr == NULL) goto cleanup; //couldn't read the header + + arch = peHdr->FileHeader.Machine; + +cleanup: //release all of our handles + FindClose(hFind); + if (hFile != INVALID_HANDLE_VALUE) + CloseHandle(hFile); + if (hMapping != INVALID_HANDLE_VALUE) + CloseHandle(hMapping); + return arch; +} + QFileInfo GameGamebryo::findInGameFolder(const QString &relativePath) const { return QFileInfo(m_GamePath + "/" + relativePath); diff --git a/src/gamegamebryo.h b/src/gamegamebryo.h index 76bc398f..5aacd74e 100644 --- a/src/gamegamebryo.h +++ b/src/gamegamebryo.h @@ -19,7 +19,7 @@ class UnmanagedMods; #include #include #include - +#include class GameGamebryo : public MOBase::IPluginGame, public MOBase::IPluginFileMapper @@ -76,6 +76,7 @@ protected: QString myGamesPath() const; QString selectedVariant() const; QString getVersion(QString const &program) const; + WORD getArch(QString const &program) const; static QString localAppFolder(); //Arguably this shouldn't really be here but every gamebryo program seems to From 4f3ba7005aaf69ffa5882b0b5a26f0a55e297701 Mon Sep 17 00:00:00 2001 From: Jeremy Rimpo Date: Sun, 29 Oct 2017 19:31:50 -0500 Subject: [PATCH 0349/1544] [game_falloutnv] Add DbgHelp library to CMakeLists --- src/games/falloutnv/src/CMakeLists.txt | 1 + 1 file changed, 1 insertion(+) diff --git a/src/games/falloutnv/src/CMakeLists.txt b/src/games/falloutnv/src/CMakeLists.txt index 3cd43312..13759b52 100644 --- a/src/games/falloutnv/src/CMakeLists.txt +++ b/src/games/falloutnv/src/CMakeLists.txt @@ -42,6 +42,7 @@ ADD_LIBRARY(${PROJ_NAME} SHARED ${${PROJ_NAME}_HDRS} ${${PROJ_NAME}_SRCS} ${${PR TARGET_LINK_LIBRARIES(${PROJ_NAME} Qt5::Widgets ${Boost_LIBRARIES} + DbgHelp uibase game_gamebryo liblz4 From 7878ed393d7667c3836c3cbce4380198afebc5a7 Mon Sep 17 00:00:00 2001 From: Jeremy Rimpo Date: Sun, 29 Oct 2017 19:31:51 -0500 Subject: [PATCH 0350/1544] [game_skyrimse] Add DbgHelp library to CMakeLists --- src/games/skyrimse/src/CMakeLists.txt | 1 + 1 file changed, 1 insertion(+) diff --git a/src/games/skyrimse/src/CMakeLists.txt b/src/games/skyrimse/src/CMakeLists.txt index b2e39a9f..eb222bd0 100644 --- a/src/games/skyrimse/src/CMakeLists.txt +++ b/src/games/skyrimse/src/CMakeLists.txt @@ -43,6 +43,7 @@ ADD_LIBRARY(${PROJ_NAME} SHARED ${${PROJ_NAME}_HDRS} ${${PROJ_NAME}_SRCS} ${${PR TARGET_LINK_LIBRARIES(${PROJ_NAME} Qt5::Widgets ${Boost_LIBRARIES} + DbgHelp uibase game_gamebryo liblz4 From ef56052ad7f522e3b4041c9fe24c0c5bfdcbe6bd Mon Sep 17 00:00:00 2001 From: Jeremy Rimpo Date: Sun, 29 Oct 2017 19:31:51 -0500 Subject: [PATCH 0351/1544] [game_oblivion] Add DbgHelp library to CMakeLists --- src/games/oblivion/src/CMakeLists.txt | 1 + 1 file changed, 1 insertion(+) diff --git a/src/games/oblivion/src/CMakeLists.txt b/src/games/oblivion/src/CMakeLists.txt index 2aac741b..fd93f6f7 100644 --- a/src/games/oblivion/src/CMakeLists.txt +++ b/src/games/oblivion/src/CMakeLists.txt @@ -42,6 +42,7 @@ ADD_LIBRARY(${PROJ_NAME} SHARED ${${PROJ_NAME}_HDRS} ${${PROJ_NAME}_SRCS} ${${PR TARGET_LINK_LIBRARIES(${PROJ_NAME} Qt5::Widgets ${Boost_LIBRARIES} + DbgHelp uibase game_gamebryo liblz4 From 942476618875b7076fe6a664b3c5761f8ff835c1 Mon Sep 17 00:00:00 2001 From: Jeremy Rimpo Date: Sun, 29 Oct 2017 19:31:52 -0500 Subject: [PATCH 0352/1544] [game_fallout4vr] Add DbgHelp library to CMakeLists --- src/games/fallout4vr/src/CMakeLists.txt | 1 + 1 file changed, 1 insertion(+) diff --git a/src/games/fallout4vr/src/CMakeLists.txt b/src/games/fallout4vr/src/CMakeLists.txt index 9d978382..c52541f2 100644 --- a/src/games/fallout4vr/src/CMakeLists.txt +++ b/src/games/fallout4vr/src/CMakeLists.txt @@ -46,6 +46,7 @@ ADD_LIBRARY(${PROJ_NAME} SHARED ${${PROJ_NAME}_HDRS} ${${PROJ_NAME}_SRCS} ${${PR TARGET_LINK_LIBRARIES(${PROJ_NAME} Qt5::Widgets ${Boost_LIBRARIES} + DbgHelp uibase Version liblz4 From 165f97aefa655922d8c7da69b5b69a22b31adef0 Mon Sep 17 00:00:00 2001 From: Jeremy Rimpo Date: Sun, 29 Oct 2017 19:31:52 -0500 Subject: [PATCH 0353/1544] [game_fallout76] Add DbgHelp library to CMakeLists --- src/games/fallout76/src/CMakeLists.txt | 1 + 1 file changed, 1 insertion(+) diff --git a/src/games/fallout76/src/CMakeLists.txt b/src/games/fallout76/src/CMakeLists.txt index 9d978382..c52541f2 100644 --- a/src/games/fallout76/src/CMakeLists.txt +++ b/src/games/fallout76/src/CMakeLists.txt @@ -46,6 +46,7 @@ ADD_LIBRARY(${PROJ_NAME} SHARED ${${PROJ_NAME}_HDRS} ${${PROJ_NAME}_SRCS} ${${PR TARGET_LINK_LIBRARIES(${PROJ_NAME} Qt5::Widgets ${Boost_LIBRARIES} + DbgHelp uibase Version liblz4 From 7c052825e2595bb0cfbca2d26a1c8efb06cdb7ff Mon Sep 17 00:00:00 2001 From: Jeremy Rimpo Date: Sun, 29 Oct 2017 19:31:52 -0500 Subject: [PATCH 0354/1544] [game_fallout4] Add DbgHelp library to CMakeLists --- src/games/fallout4/src/CMakeLists.txt | 1 + 1 file changed, 1 insertion(+) diff --git a/src/games/fallout4/src/CMakeLists.txt b/src/games/fallout4/src/CMakeLists.txt index 9d978382..c52541f2 100644 --- a/src/games/fallout4/src/CMakeLists.txt +++ b/src/games/fallout4/src/CMakeLists.txt @@ -46,6 +46,7 @@ ADD_LIBRARY(${PROJ_NAME} SHARED ${${PROJ_NAME}_HDRS} ${${PROJ_NAME}_SRCS} ${${PR TARGET_LINK_LIBRARIES(${PROJ_NAME} Qt5::Widgets ${Boost_LIBRARIES} + DbgHelp uibase Version liblz4 From 965ce120df42e4f5aa3401ba625c2dcc482be138 Mon Sep 17 00:00:00 2001 From: Jeremy Rimpo Date: Sun, 29 Oct 2017 19:31:52 -0500 Subject: [PATCH 0355/1544] [game_fallout3] Add DbgHelp library to CMakeLists --- src/games/fallout3/src/CMakeLists.txt | 1 + 1 file changed, 1 insertion(+) diff --git a/src/games/fallout3/src/CMakeLists.txt b/src/games/fallout3/src/CMakeLists.txt index 3cd43312..13759b52 100644 --- a/src/games/fallout3/src/CMakeLists.txt +++ b/src/games/fallout3/src/CMakeLists.txt @@ -42,6 +42,7 @@ ADD_LIBRARY(${PROJ_NAME} SHARED ${${PROJ_NAME}_HDRS} ${${PROJ_NAME}_SRCS} ${${PR TARGET_LINK_LIBRARIES(${PROJ_NAME} Qt5::Widgets ${Boost_LIBRARIES} + DbgHelp uibase game_gamebryo liblz4 From 31a7e172d8c5529661e6637516549d2e5610a2ea Mon Sep 17 00:00:00 2001 From: Jeremy Rimpo Date: Sun, 29 Oct 2017 19:31:53 -0500 Subject: [PATCH 0356/1544] [game_skyrim] Add DbgHelp library to CMakeLists --- src/games/skyrim/src/CMakeLists.txt | 1 + 1 file changed, 1 insertion(+) diff --git a/src/games/skyrim/src/CMakeLists.txt b/src/games/skyrim/src/CMakeLists.txt index cc3b3dfe..6f9c4c67 100644 --- a/src/games/skyrim/src/CMakeLists.txt +++ b/src/games/skyrim/src/CMakeLists.txt @@ -43,6 +43,7 @@ ADD_LIBRARY(${PROJ_NAME} SHARED ${${PROJ_NAME}_HDRS} ${${PROJ_NAME}_SRCS} ${${PR TARGET_LINK_LIBRARIES(${PROJ_NAME} Qt5::Widgets ${Boost_LIBRARIES} + DbgHelp uibase game_gamebryo liblz4 From dfda4b591cddd46ad95e74407a54cc67c5ee2e4b Mon Sep 17 00:00:00 2001 From: Jeremy Rimpo Date: Sun, 29 Oct 2017 23:15:04 -0500 Subject: [PATCH 0357/1544] Fixes ever-growing save game info box --- src/gamebryosavegameinfowidget.cpp | 3 +++ 1 file changed, 3 insertions(+) diff --git a/src/gamebryosavegameinfowidget.cpp b/src/gamebryosavegameinfowidget.cpp index 9b4b2a70..a05e4659 100644 --- a/src/gamebryosavegameinfowidget.cpp +++ b/src/gamebryosavegameinfowidget.cpp @@ -64,6 +64,9 @@ void GamebryoSaveGameInfoWidget::setSave(QString const &file) { } ui->gameFrame->layout()->setSizeConstraint(QLayout::SetFixedSize); } + + // Resize box to new content + this->resize(0, 0); QLayout *layout = ui->gameFrame->layout(); QLabel *header = new QLabel(tr("Missing ESPs")); From 6bab4f84fe7c263bbc7ae88da78043834e4f5907 Mon Sep 17 00:00:00 2001 From: Jeremy Rimpo Date: Mon, 30 Oct 2017 01:13:14 -0500 Subject: [PATCH 0358/1544] [game_fallout4vr] Fix the save reader ESL determination --- src/games/fallout4vr/src/fallout4savegame.cpp | 10 ++++------ 1 file changed, 4 insertions(+), 6 deletions(-) diff --git a/src/games/fallout4vr/src/fallout4savegame.cpp b/src/games/fallout4vr/src/fallout4savegame.cpp index ddd3f8d2..3c0e926d 100644 --- a/src/games/fallout4vr/src/fallout4savegame.cpp +++ b/src/games/fallout4vr/src/fallout4savegame.cpp @@ -7,8 +7,7 @@ Fallout4SaveGame::Fallout4SaveGame(QString const &fileName, MOBase::IPluginGame { FileWrapper file(this, "FO4_SAVEGAME"); file.skip(); // header size - uint32_t headerVersion; - file.read(headerVersion); // header version + file.skip(); // header version file.read(m_SaveNumber); file.read(m_PCName); @@ -37,12 +36,11 @@ Fallout4SaveGame::Fallout4SaveGame(QString const &fileName, MOBase::IPluginGame file.readImage(384, true); - file.skip(); // form version - QString gameVersion; - file.read(gameVersion); // game version + uint8_t saveGameVersion = file.readSaveGameVersion(); + file.read(ignore); // game version file.skip(); // plugin info size file.readPlugins(); - if (headerVersion > 15) + if (saveGameVersion >= 68) file.readLightPlugins(); } From b4741d0d84886cfbd17298d1d4a6cfd07f69251c Mon Sep 17 00:00:00 2001 From: Jeremy Rimpo Date: Mon, 30 Oct 2017 01:13:14 -0500 Subject: [PATCH 0359/1544] [game_fallout76] Fix the save reader ESL determination --- src/games/fallout76/src/fallout4savegame.cpp | 10 ++++------ 1 file changed, 4 insertions(+), 6 deletions(-) diff --git a/src/games/fallout76/src/fallout4savegame.cpp b/src/games/fallout76/src/fallout4savegame.cpp index ddd3f8d2..3c0e926d 100644 --- a/src/games/fallout76/src/fallout4savegame.cpp +++ b/src/games/fallout76/src/fallout4savegame.cpp @@ -7,8 +7,7 @@ Fallout4SaveGame::Fallout4SaveGame(QString const &fileName, MOBase::IPluginGame { FileWrapper file(this, "FO4_SAVEGAME"); file.skip(); // header size - uint32_t headerVersion; - file.read(headerVersion); // header version + file.skip(); // header version file.read(m_SaveNumber); file.read(m_PCName); @@ -37,12 +36,11 @@ Fallout4SaveGame::Fallout4SaveGame(QString const &fileName, MOBase::IPluginGame file.readImage(384, true); - file.skip(); // form version - QString gameVersion; - file.read(gameVersion); // game version + uint8_t saveGameVersion = file.readSaveGameVersion(); + file.read(ignore); // game version file.skip(); // plugin info size file.readPlugins(); - if (headerVersion > 15) + if (saveGameVersion >= 68) file.readLightPlugins(); } From 8ea2bb32fdca7b473228edbb9b9803782c4e5bde Mon Sep 17 00:00:00 2001 From: Jeremy Rimpo Date: Mon, 30 Oct 2017 01:13:14 -0500 Subject: [PATCH 0360/1544] [game_fallout4] Fix the save reader ESL determination --- src/games/fallout4/src/fallout4savegame.cpp | 10 ++++------ 1 file changed, 4 insertions(+), 6 deletions(-) diff --git a/src/games/fallout4/src/fallout4savegame.cpp b/src/games/fallout4/src/fallout4savegame.cpp index ddd3f8d2..3c0e926d 100644 --- a/src/games/fallout4/src/fallout4savegame.cpp +++ b/src/games/fallout4/src/fallout4savegame.cpp @@ -7,8 +7,7 @@ Fallout4SaveGame::Fallout4SaveGame(QString const &fileName, MOBase::IPluginGame { FileWrapper file(this, "FO4_SAVEGAME"); file.skip(); // header size - uint32_t headerVersion; - file.read(headerVersion); // header version + file.skip(); // header version file.read(m_SaveNumber); file.read(m_PCName); @@ -37,12 +36,11 @@ Fallout4SaveGame::Fallout4SaveGame(QString const &fileName, MOBase::IPluginGame file.readImage(384, true); - file.skip(); // form version - QString gameVersion; - file.read(gameVersion); // game version + uint8_t saveGameVersion = file.readSaveGameVersion(); + file.read(ignore); // game version file.skip(); // plugin info size file.readPlugins(); - if (headerVersion > 15) + if (saveGameVersion >= 68) file.readLightPlugins(); } From 7ec1aee367fde762b54368571059f8af695585a0 Mon Sep 17 00:00:00 2001 From: Jeremy Rimpo Date: Mon, 30 Oct 2017 01:14:51 -0500 Subject: [PATCH 0361/1544] Corrections for unencrypted save data --- src/gamebryosavegame.cpp | 16 ++++++++-------- src/gamebryosavegame.h | 2 +- 2 files changed, 9 insertions(+), 9 deletions(-) diff --git a/src/gamebryosavegame.cpp b/src/gamebryosavegame.cpp index 4692f179..0400f8f4 100644 --- a/src/gamebryosavegame.cpp +++ b/src/gamebryosavegame.cpp @@ -268,14 +268,14 @@ void GamebryoSaveGame::FileWrapper::readPlugins(int bytesToIgnore) if(m_Game->compressionType==0){ if(bytesToIgnore>0)//Just to make certain skip(bytesToIgnore); - unsigned char count; - read(count); - m_Game->m_Plugins.reserve(count); - for (std::size_t i = 0; i < count; ++i) { - QString name; - read(name); - m_Game->m_Plugins.push_back(name); - } + uint8_t count; + read(count); + m_Game->m_Plugins.reserve(count); + for (std::size_t i = 0; i < count; ++i) { + QString name; + read(name); + m_Game->m_Plugins.push_back(name); + } }else if(m_Game->compressionType==1){ m_Game->m_Plugins.push_back("Please create an issue on the MO github labeled \"Found zlib Compressed\" with your savefile attached"); }else if(m_Game->compressionType==2){ diff --git a/src/gamebryosavegame.h b/src/gamebryosavegame.h index b8ff2a09..b3041859 100644 --- a/src/gamebryosavegame.h +++ b/src/gamebryosavegame.h @@ -128,7 +128,7 @@ protected: QStringList m_LightPlugins; QImage m_Screenshot; MOBase::IPluginGame const *m_Game; - unsigned short compressionType; + unsigned short compressionType = 0; bool m_LightEnabled; }; From 8c6df79ac40fff2a4e32188248a8a089dc7a419e Mon Sep 17 00:00:00 2001 From: Jeremy Rimpo Date: Mon, 30 Oct 2017 03:20:09 -0500 Subject: [PATCH 0362/1544] [game_skyrimse] Refine save reading --- src/games/skyrimse/src/skyrimsesavegame.cpp | 11 +++++++---- 1 file changed, 7 insertions(+), 4 deletions(-) diff --git a/src/games/skyrimse/src/skyrimsesavegame.cpp b/src/games/skyrimse/src/skyrimsesavegame.cpp index 571dfdbf..61cd5a7c 100644 --- a/src/games/skyrimse/src/skyrimsesavegame.cpp +++ b/src/games/skyrimse/src/skyrimsesavegame.cpp @@ -59,12 +59,15 @@ SkyrimSESaveGame::SkyrimSESaveGame(QString const &fileName, MOBase::IPluginGame file.openCompressedData(); - uint16_t saveGameVersion = file.readSaveGameVersion(); + uint8_t saveGameVersion = file.readChar(); + uint8_t pluginInfoSize = file.readChar(); + uint16_t other = file.readShort(); //Unknown - file.readPlugins(4); + file.readPlugins(1); // Just empty data - if (saveGameVersion >= 78) - file.readLightPlugins(); + if (saveGameVersion >= 78) { + file.readLightPlugins(); + } file.closeCompressedData(); } From b44cf95c2004139b486ad526a496f71bb430caf2 Mon Sep 17 00:00:00 2001 From: Jeremy Rimpo Date: Mon, 30 Oct 2017 03:20:09 -0500 Subject: [PATCH 0363/1544] Refine save reading --- src/gamebryosavegame.cpp | 60 ++++++++++++++++++++++++++++++++++++++-- src/gamebryosavegame.h | 6 +++- 2 files changed, 62 insertions(+), 4 deletions(-) diff --git a/src/gamebryosavegame.cpp b/src/gamebryosavegame.cpp index 0400f8f4..2cb43a07 100644 --- a/src/gamebryosavegame.cpp +++ b/src/gamebryosavegame.cpp @@ -235,12 +235,12 @@ bool GamebryoSaveGame::FileWrapper::openCompressedData(int bytesToIgnore) } } -unsigned char GamebryoSaveGame::FileWrapper::readSaveGameVersion(int bytesToIgnore) +uint8_t GamebryoSaveGame::FileWrapper::readChar(int bytesToIgnore) { if (m_Game->compressionType == 0) { if (bytesToIgnore>0)//Just to make certain skip(bytesToIgnore); - unsigned char version; + uint8_t version; read(version); return version; } @@ -252,7 +252,7 @@ unsigned char GamebryoSaveGame::FileWrapper::readSaveGameVersion(int bytesToIgno // decompression already done by readSaveGameVersion m_Data->skipRawData(bytesToIgnore); - unsigned char version; + uint8_t version; readQDataStream(*m_Data, version); return version; @@ -263,6 +263,60 @@ unsigned char GamebryoSaveGame::FileWrapper::readSaveGameVersion(int bytesToIgno } } +uint16_t GamebryoSaveGame::FileWrapper::readShort(int bytesToIgnore) +{ + if (m_Game->compressionType == 0) { + if (bytesToIgnore>0)//Just to make certain + skip(bytesToIgnore); + uint16_t size; + read(size); + return size; + } + else if (m_Game->compressionType == 1) { + m_Game->m_Plugins.push_back("Please create an issue on the MO github labeled \"Found zlib Compressed\" with your savefile attached"); + return 0; + } + else if (m_Game->compressionType == 2) { + // decompression already done by readSaveGameVersion + m_Data->skipRawData(bytesToIgnore); + + uint16_t size; + readQDataStream(*m_Data, size); + return size; + } + else { + m_Game->m_Plugins.push_back("Please create an issue on the MO github labeled \"Found unknown Compressed\" with your savefile attached"); + return 0; + } +} + +uint32_t GamebryoSaveGame::FileWrapper::readInt(int bytesToIgnore) +{ + if (m_Game->compressionType == 0) { + if (bytesToIgnore>0)//Just to make certain + skip(bytesToIgnore); + uint32_t size; + read(size); + return size; + } + else if (m_Game->compressionType == 1) { + m_Game->m_Plugins.push_back("Please create an issue on the MO github labeled \"Found zlib Compressed\" with your savefile attached"); + return 0; + } + else if (m_Game->compressionType == 2) { + // decompression already done by readSaveGameVersion + m_Data->skipRawData(bytesToIgnore); + + uint32_t size; + readQDataStream(*m_Data, size); + return size; + } + else { + m_Game->m_Plugins.push_back("Please create an issue on the MO github labeled \"Found unknown Compressed\" with your savefile attached"); + return 0; + } +} + void GamebryoSaveGame::FileWrapper::readPlugins(int bytesToIgnore) { if(m_Game->compressionType==0){ diff --git a/src/gamebryosavegame.h b/src/gamebryosavegame.h index b3041859..ddfc065c 100644 --- a/src/gamebryosavegame.h +++ b/src/gamebryosavegame.h @@ -97,7 +97,11 @@ protected: void closeCompressedData(); /* Read the save game version in the compressed block */ - unsigned char readSaveGameVersion(int bytesToIgnore=0); + uint8_t readChar(int bytesToIgnore=0); + + uint16_t readShort(int bytesToIgnore = 0); + + uint32_t readInt(int bytesToIgnore = 0); /* Read the plugin list */ void readPlugins(int bytesToIgnore=0); From ec63a4e954502aa1757d21011b49f2bbb0e0eeb2 Mon Sep 17 00:00:00 2001 From: Jeremy Rimpo Date: Mon, 30 Oct 2017 03:20:10 -0500 Subject: [PATCH 0364/1544] [game_fallout4vr] Refine save reading --- src/games/fallout4vr/src/fallout4savegame.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/games/fallout4vr/src/fallout4savegame.cpp b/src/games/fallout4vr/src/fallout4savegame.cpp index 3c0e926d..429cf1cc 100644 --- a/src/games/fallout4vr/src/fallout4savegame.cpp +++ b/src/games/fallout4vr/src/fallout4savegame.cpp @@ -36,7 +36,7 @@ Fallout4SaveGame::Fallout4SaveGame(QString const &fileName, MOBase::IPluginGame file.readImage(384, true); - uint8_t saveGameVersion = file.readSaveGameVersion(); + uint8_t saveGameVersion = file.readChar(); file.read(ignore); // game version file.skip(); // plugin info size From efe1ef175396109f3eb22844c5a88b28e8d3a61c Mon Sep 17 00:00:00 2001 From: Jeremy Rimpo Date: Mon, 30 Oct 2017 03:20:10 -0500 Subject: [PATCH 0365/1544] [game_fallout76] Refine save reading --- src/games/fallout76/src/fallout4savegame.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/games/fallout76/src/fallout4savegame.cpp b/src/games/fallout76/src/fallout4savegame.cpp index 3c0e926d..429cf1cc 100644 --- a/src/games/fallout76/src/fallout4savegame.cpp +++ b/src/games/fallout76/src/fallout4savegame.cpp @@ -36,7 +36,7 @@ Fallout4SaveGame::Fallout4SaveGame(QString const &fileName, MOBase::IPluginGame file.readImage(384, true); - uint8_t saveGameVersion = file.readSaveGameVersion(); + uint8_t saveGameVersion = file.readChar(); file.read(ignore); // game version file.skip(); // plugin info size From 9f0c5cee8dc1fae302023ccbe7f85b7786c902b9 Mon Sep 17 00:00:00 2001 From: Jeremy Rimpo Date: Mon, 30 Oct 2017 03:20:10 -0500 Subject: [PATCH 0366/1544] [game_fallout4] Refine save reading --- src/games/fallout4/src/fallout4savegame.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/games/fallout4/src/fallout4savegame.cpp b/src/games/fallout4/src/fallout4savegame.cpp index 3c0e926d..429cf1cc 100644 --- a/src/games/fallout4/src/fallout4savegame.cpp +++ b/src/games/fallout4/src/fallout4savegame.cpp @@ -36,7 +36,7 @@ Fallout4SaveGame::Fallout4SaveGame(QString const &fileName, MOBase::IPluginGame file.readImage(384, true); - uint8_t saveGameVersion = file.readSaveGameVersion(); + uint8_t saveGameVersion = file.readChar(); file.read(ignore); // game version file.skip(); // plugin info size From 468f70bae1489335143f15234312acf8146edb8a Mon Sep 17 00:00:00 2001 From: Jeremy Rimpo Date: Wed, 1 Nov 2017 21:54:21 -0500 Subject: [PATCH 0367/1544] Fixes rare crash with calculated data size - just use value in save --- src/gamebryosavegame.cpp | 12 ++++-------- src/gamebryosavegame.h | 2 +- 2 files changed, 5 insertions(+), 9 deletions(-) diff --git a/src/gamebryosavegame.cpp b/src/gamebryosavegame.cpp index 2cb43a07..05ddf6eb 100644 --- a/src/gamebryosavegame.cpp +++ b/src/gamebryosavegame.cpp @@ -210,24 +210,20 @@ bool GamebryoSaveGame::FileWrapper::openCompressedData(int bytesToIgnore) return false; } else if (m_Game->compressionType == 2) { - unsigned long maxUncompressedSize; - read(maxUncompressedSize); - unsigned long compressedSize; + uint32_t uncompressedSize; + read(uncompressedSize); + uint32_t compressedSize; read(compressedSize); char* compressed = new char[compressedSize]; read(compressed, compressedSize); - - //unsigned long uncompressedSize=(65537)*255+bytesToIgnore‬; - unsigned long uncompressedSize = 16711935 + bytesToIgnore; char * decompressed = new char[uncompressedSize]; - LZ4_decompress_safe_partial(compressed, decompressed, compressedSize, uncompressedSize, maxUncompressedSize); + LZ4_decompress_safe_partial(compressed, decompressed, compressedSize, uncompressedSize, uncompressedSize); delete[] compressed; m_Data = new QDataStream(QByteArray(decompressed, uncompressedSize)); m_Data->skipRawData(bytesToIgnore); return true; - } else { m_Game->m_Plugins.push_back("Please create an issue on the MO github labeled \"Found unknown Compressed\" with your savefile attached"); diff --git a/src/gamebryosavegame.h b/src/gamebryosavegame.h index ddfc065c..72814b43 100644 --- a/src/gamebryosavegame.h +++ b/src/gamebryosavegame.h @@ -132,7 +132,7 @@ protected: QStringList m_LightPlugins; QImage m_Screenshot; MOBase::IPluginGame const *m_Game; - unsigned short compressionType = 0; + uint16_t compressionType = 0; bool m_LightEnabled; }; From 473626c1b9cdf3bc566c40ab4efad96a80d51f54 Mon Sep 17 00:00:00 2001 From: Jeremy Rimpo Date: Wed, 8 Nov 2017 19:28:17 -0600 Subject: [PATCH 0368/1544] [game_fallout4vr] Add 'UltraHighResolution' DLC --- src/games/fallout4vr/src/gamefallout4.cpp | 9 +++++---- 1 file changed, 5 insertions(+), 4 deletions(-) diff --git a/src/games/fallout4vr/src/gamefallout4.cpp b/src/games/fallout4vr/src/gamefallout4.cpp index f90ebffb..30191ccd 100644 --- a/src/games/fallout4vr/src/gamefallout4.cpp +++ b/src/games/fallout4vr/src/gamefallout4.cpp @@ -123,7 +123,8 @@ QString GameFallout4::steamAPPId() const } QStringList GameFallout4::primaryPlugins() const { - return {"fallout4.esm", "dlcrobot.esm", "dlcworkshop01.esm", "dlccoast.esm", "dlcworkshop02.esm", "dlcworkshop03.esm", "dlcnukaworld.esm", + return {"fallout4.esm", "dlcrobot.esm", "dlcworkshop01.esm", "dlccoast.esm", "dlcworkshop02.esm", + "dlcworkshop03.esm", "dlcnukaworld.esm", "dlcultrahighresolution.esm", "ccbgsfo4001-pipboy(black).esl", "ccbgsfo4002-pipboy(blue).esl", "ccbgsfo4003-pipboy(camo01).esl", "ccbgsfo4004-pipboy(camo02).esl", "ccbgsfo4006-pipboy(chrome).esl", "ccbgsfo4012-pipboy(red).esl", "ccbgsfo4014-pipboy(white).esl", "ccbgsfo4016-prey.esl", "ccbgsfo4017-mauler.esl", "ccbgsfo4018-gaussrifleprototype.esl", @@ -156,9 +157,9 @@ QStringList GameFallout4::iniFiles() const QStringList GameFallout4::DLCPlugins() const { - return {"dlcrobot.esm", "dlcworkshop01.esm", "dlccoast.esm", "dlcworkshop02.esm", "dlcworkshop03.esm", "dlcnukaworld.esm", - "ccbgsfo4001-pipboy(black).esl", "ccbgsfo4002-pipboy(blue).esl", "ccbgsfo4003-pipboy(camo01).esl", - "ccbgsfo4004-pipboy(camo02).esl", "ccbgsfo4006-pipboy(chrome).esl", "ccbgsfo4012-pipboy(red).esl", + return {"dlcrobot.esm", "dlcworkshop01.esm", "dlccoast.esm", "dlcworkshop02.esm", "dlcworkshop03.esm", + "dlcnukaworld.esm", "dlcultrahighresolution.esm", "ccbgsfo4001-pipboy(black).esl", "ccbgsfo4002-pipboy(blue).esl", + "ccbgsfo4003-pipboy(camo01).esl", "ccbgsfo4004-pipboy(camo02).esl", "ccbgsfo4006-pipboy(chrome).esl", "ccbgsfo4012-pipboy(red).esl", "ccbgsfo4014-pipboy(white).esl", "ccbgsfo4016-prey.esl", "ccbgsfo4017-mauler.esl", "ccbgsfo4018-gaussrifleprototype.esl", "ccbgsfo4019-chinesestealtharmor.esl", "ccbgsfo4020-powerarmorskin(black).esl", "ccbgsfo4022-powerarmorskin(camo01).esl", "ccbgsfo4023-powerarmorskin(camo02).esl", "ccbgsfo4025-powerarmorskin(chrome).esl", "ccbgsfo4038-horsearmor.esl", From 0e9184aa07088649c60cac19ea783ff5c60f8c26 Mon Sep 17 00:00:00 2001 From: Jeremy Rimpo Date: Wed, 8 Nov 2017 19:28:17 -0600 Subject: [PATCH 0369/1544] [game_fallout76] Add 'UltraHighResolution' DLC --- src/games/fallout76/src/gamefallout4.cpp | 9 +++++---- 1 file changed, 5 insertions(+), 4 deletions(-) diff --git a/src/games/fallout76/src/gamefallout4.cpp b/src/games/fallout76/src/gamefallout4.cpp index f90ebffb..30191ccd 100644 --- a/src/games/fallout76/src/gamefallout4.cpp +++ b/src/games/fallout76/src/gamefallout4.cpp @@ -123,7 +123,8 @@ QString GameFallout4::steamAPPId() const } QStringList GameFallout4::primaryPlugins() const { - return {"fallout4.esm", "dlcrobot.esm", "dlcworkshop01.esm", "dlccoast.esm", "dlcworkshop02.esm", "dlcworkshop03.esm", "dlcnukaworld.esm", + return {"fallout4.esm", "dlcrobot.esm", "dlcworkshop01.esm", "dlccoast.esm", "dlcworkshop02.esm", + "dlcworkshop03.esm", "dlcnukaworld.esm", "dlcultrahighresolution.esm", "ccbgsfo4001-pipboy(black).esl", "ccbgsfo4002-pipboy(blue).esl", "ccbgsfo4003-pipboy(camo01).esl", "ccbgsfo4004-pipboy(camo02).esl", "ccbgsfo4006-pipboy(chrome).esl", "ccbgsfo4012-pipboy(red).esl", "ccbgsfo4014-pipboy(white).esl", "ccbgsfo4016-prey.esl", "ccbgsfo4017-mauler.esl", "ccbgsfo4018-gaussrifleprototype.esl", @@ -156,9 +157,9 @@ QStringList GameFallout4::iniFiles() const QStringList GameFallout4::DLCPlugins() const { - return {"dlcrobot.esm", "dlcworkshop01.esm", "dlccoast.esm", "dlcworkshop02.esm", "dlcworkshop03.esm", "dlcnukaworld.esm", - "ccbgsfo4001-pipboy(black).esl", "ccbgsfo4002-pipboy(blue).esl", "ccbgsfo4003-pipboy(camo01).esl", - "ccbgsfo4004-pipboy(camo02).esl", "ccbgsfo4006-pipboy(chrome).esl", "ccbgsfo4012-pipboy(red).esl", + return {"dlcrobot.esm", "dlcworkshop01.esm", "dlccoast.esm", "dlcworkshop02.esm", "dlcworkshop03.esm", + "dlcnukaworld.esm", "dlcultrahighresolution.esm", "ccbgsfo4001-pipboy(black).esl", "ccbgsfo4002-pipboy(blue).esl", + "ccbgsfo4003-pipboy(camo01).esl", "ccbgsfo4004-pipboy(camo02).esl", "ccbgsfo4006-pipboy(chrome).esl", "ccbgsfo4012-pipboy(red).esl", "ccbgsfo4014-pipboy(white).esl", "ccbgsfo4016-prey.esl", "ccbgsfo4017-mauler.esl", "ccbgsfo4018-gaussrifleprototype.esl", "ccbgsfo4019-chinesestealtharmor.esl", "ccbgsfo4020-powerarmorskin(black).esl", "ccbgsfo4022-powerarmorskin(camo01).esl", "ccbgsfo4023-powerarmorskin(camo02).esl", "ccbgsfo4025-powerarmorskin(chrome).esl", "ccbgsfo4038-horsearmor.esl", From af953b0a3739cfb6bdf9a96340e91724f1805ef4 Mon Sep 17 00:00:00 2001 From: Jeremy Rimpo Date: Wed, 8 Nov 2017 19:28:17 -0600 Subject: [PATCH 0370/1544] [game_fallout4] Add 'UltraHighResolution' DLC --- src/games/fallout4/src/gamefallout4.cpp | 9 +++++---- 1 file changed, 5 insertions(+), 4 deletions(-) diff --git a/src/games/fallout4/src/gamefallout4.cpp b/src/games/fallout4/src/gamefallout4.cpp index f90ebffb..30191ccd 100644 --- a/src/games/fallout4/src/gamefallout4.cpp +++ b/src/games/fallout4/src/gamefallout4.cpp @@ -123,7 +123,8 @@ QString GameFallout4::steamAPPId() const } QStringList GameFallout4::primaryPlugins() const { - return {"fallout4.esm", "dlcrobot.esm", "dlcworkshop01.esm", "dlccoast.esm", "dlcworkshop02.esm", "dlcworkshop03.esm", "dlcnukaworld.esm", + return {"fallout4.esm", "dlcrobot.esm", "dlcworkshop01.esm", "dlccoast.esm", "dlcworkshop02.esm", + "dlcworkshop03.esm", "dlcnukaworld.esm", "dlcultrahighresolution.esm", "ccbgsfo4001-pipboy(black).esl", "ccbgsfo4002-pipboy(blue).esl", "ccbgsfo4003-pipboy(camo01).esl", "ccbgsfo4004-pipboy(camo02).esl", "ccbgsfo4006-pipboy(chrome).esl", "ccbgsfo4012-pipboy(red).esl", "ccbgsfo4014-pipboy(white).esl", "ccbgsfo4016-prey.esl", "ccbgsfo4017-mauler.esl", "ccbgsfo4018-gaussrifleprototype.esl", @@ -156,9 +157,9 @@ QStringList GameFallout4::iniFiles() const QStringList GameFallout4::DLCPlugins() const { - return {"dlcrobot.esm", "dlcworkshop01.esm", "dlccoast.esm", "dlcworkshop02.esm", "dlcworkshop03.esm", "dlcnukaworld.esm", - "ccbgsfo4001-pipboy(black).esl", "ccbgsfo4002-pipboy(blue).esl", "ccbgsfo4003-pipboy(camo01).esl", - "ccbgsfo4004-pipboy(camo02).esl", "ccbgsfo4006-pipboy(chrome).esl", "ccbgsfo4012-pipboy(red).esl", + return {"dlcrobot.esm", "dlcworkshop01.esm", "dlccoast.esm", "dlcworkshop02.esm", "dlcworkshop03.esm", + "dlcnukaworld.esm", "dlcultrahighresolution.esm", "ccbgsfo4001-pipboy(black).esl", "ccbgsfo4002-pipboy(blue).esl", + "ccbgsfo4003-pipboy(camo01).esl", "ccbgsfo4004-pipboy(camo02).esl", "ccbgsfo4006-pipboy(chrome).esl", "ccbgsfo4012-pipboy(red).esl", "ccbgsfo4014-pipboy(white).esl", "ccbgsfo4016-prey.esl", "ccbgsfo4017-mauler.esl", "ccbgsfo4018-gaussrifleprototype.esl", "ccbgsfo4019-chinesestealtharmor.esl", "ccbgsfo4020-powerarmorskin(black).esl", "ccbgsfo4022-powerarmorskin(camo01).esl", "ccbgsfo4023-powerarmorskin(camo02).esl", "ccbgsfo4025-powerarmorskin(chrome).esl", "ccbgsfo4038-horsearmor.esl", From cf4ad27de376fd9748dd0a428bc3a6546c7dd446 Mon Sep 17 00:00:00 2001 From: Jeremy Rimpo Date: Fri, 17 Nov 2017 16:08:53 -0600 Subject: [PATCH 0371/1544] Update to parse CC plugins from game.ccc file --- src/gamegamebryo.cpp | 5 +++++ src/gamegamebryo.h | 1 + 2 files changed, 6 insertions(+) diff --git a/src/gamegamebryo.cpp b/src/gamegamebryo.cpp index fc291b86..be5a69d3 100644 --- a/src/gamegamebryo.cpp +++ b/src/gamegamebryo.cpp @@ -173,6 +173,11 @@ QString GameGamebryo::binaryName() const return gameShortName() + ".exe"; } +QStringList GameGamebryo::CCPlugins() const +{ + return {}; +} + MOBase::IPluginGame::LoadOrderMechanism GameGamebryo::loadOrderMechanism() const { return LoadOrderMechanism::FileTime; diff --git a/src/gamegamebryo.h b/src/gamegamebryo.h index 5aacd74e..23b35da8 100644 --- a/src/gamegamebryo.h +++ b/src/gamegamebryo.h @@ -58,6 +58,7 @@ public: // IPluginGame interface //gameShortName //iniFiles //DLCPlugins + virtual QStringList CCPlugins() const override; virtual LoadOrderMechanism loadOrderMechanism() const override; //nexusModOrganizerID //nexusGameID From 0f8f69fd16e33cecfc9c02949b1d72db35ae5f4b Mon Sep 17 00:00:00 2001 From: Jeremy Rimpo Date: Fri, 17 Nov 2017 16:08:53 -0600 Subject: [PATCH 0372/1544] [game_fallout4vr] Update to parse CC plugins from game.ccc file --- src/games/fallout4vr/src/gamefallout4.cpp | 57 ++++++++++++++++------- src/games/fallout4vr/src/gamefallout4.h | 1 + 2 files changed, 40 insertions(+), 18 deletions(-) diff --git a/src/games/fallout4vr/src/gamefallout4.cpp b/src/games/fallout4vr/src/gamefallout4.cpp index 30191ccd..a1dd3874 100644 --- a/src/games/fallout4vr/src/gamefallout4.cpp +++ b/src/games/fallout4vr/src/gamefallout4.cpp @@ -23,6 +23,11 @@ #include +#include "utility.h" +#include +#include +#include "scopeguard.h" + using namespace MOBase; GameFallout4::GameFallout4() @@ -123,16 +128,12 @@ QString GameFallout4::steamAPPId() const } QStringList GameFallout4::primaryPlugins() const { - return {"fallout4.esm", "dlcrobot.esm", "dlcworkshop01.esm", "dlccoast.esm", "dlcworkshop02.esm", - "dlcworkshop03.esm", "dlcnukaworld.esm", "dlcultrahighresolution.esm", - "ccbgsfo4001-pipboy(black).esl", "ccbgsfo4002-pipboy(blue).esl", "ccbgsfo4003-pipboy(camo01).esl", - "ccbgsfo4004-pipboy(camo02).esl", "ccbgsfo4006-pipboy(chrome).esl", "ccbgsfo4012-pipboy(red).esl", - "ccbgsfo4014-pipboy(white).esl", "ccbgsfo4016-prey.esl", "ccbgsfo4017-mauler.esl", "ccbgsfo4018-gaussrifleprototype.esl", - "ccbgsfo4019-chinesestealtharmor.esl", "ccbgsfo4020-powerarmorskin(black).esl", "ccbgsfo4022-powerarmorskin(camo01).esl", - "ccbgsfo4023-powerarmorskin(camo02).esl", "ccbgsfo4025-powerarmorskin(chrome).esl", "ccbgsfo4038-horsearmor.esl", - "ccbgsfo4039-tunnelsnakes.esl", "ccbgsfo4041-doommarinearmor.esl", "ccbgsfo4042-bfg.esl", - "ccbgsfo4043-doomchainsaw.esl", "ccbgsfo4044-hellfirepowerarmor.esl", "ccfsvfo4001-modularmilitarybackpack.esl", - "ccfsvfo4002-midcenturymodern.esl", "ccfrsfo4001-handmadeshotgun.esl", "cceejfo4001-decorationpack.esl"}; + QStringList plugins = {"fallout4.esm", "dlcrobot.esm", "dlcworkshop01.esm", "dlccoast.esm", "dlcworkshop02.esm", + "dlcworkshop03.esm", "dlcnukaworld.esm", "dlcultrahighresolution.esm"}; + + plugins.append(CCPlugins()); + + return plugins; } QStringList GameFallout4::gameVariants() const @@ -158,14 +159,34 @@ QStringList GameFallout4::iniFiles() const QStringList GameFallout4::DLCPlugins() const { return {"dlcrobot.esm", "dlcworkshop01.esm", "dlccoast.esm", "dlcworkshop02.esm", "dlcworkshop03.esm", - "dlcnukaworld.esm", "dlcultrahighresolution.esm", "ccbgsfo4001-pipboy(black).esl", "ccbgsfo4002-pipboy(blue).esl", - "ccbgsfo4003-pipboy(camo01).esl", "ccbgsfo4004-pipboy(camo02).esl", "ccbgsfo4006-pipboy(chrome).esl", "ccbgsfo4012-pipboy(red).esl", - "ccbgsfo4014-pipboy(white).esl", "ccbgsfo4016-prey.esl", "ccbgsfo4017-mauler.esl", "ccbgsfo4018-gaussrifleprototype.esl", - "ccbgsfo4019-chinesestealtharmor.esl", "ccbgsfo4020-powerarmorskin(black).esl", "ccbgsfo4022-powerarmorskin(camo01).esl", - "ccbgsfo4023-powerarmorskin(camo02).esl", "ccbgsfo4025-powerarmorskin(chrome).esl", "ccbgsfo4038-horsearmor.esl", - "ccbgsfo4039-tunnelsnakes.esl", "ccbgsfo4041-doommarinearmor.esl", "ccbgsfo4042-bfg.esl", - "ccbgsfo4043-doomchainsaw.esl", "ccbgsfo4044-hellfirepowerarmor.esl", "ccfsvfo4001-modularmilitarybackpack.esl", - "ccfsvfo4002-midcenturymodern.esl", "ccfrsfo4001-handmadeshotgun.esl", "cceejfo4001-decorationpack.esl"}; + "dlcnukaworld.esm", "dlcultrahighresolution.esm"}; +} + +QStringList GameFallout4::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::LoadOrderMechanism GameFallout4::loadOrderMechanism() const diff --git a/src/games/fallout4vr/src/gamefallout4.h b/src/games/fallout4vr/src/gamefallout4.h index 655bc197..ad06bf54 100644 --- a/src/games/fallout4vr/src/gamefallout4.h +++ b/src/games/fallout4vr/src/gamefallout4.h @@ -32,6 +32,7 @@ public: // IPluginGame interface virtual QString gameNexusName() const override; virtual QStringList iniFiles() const override; virtual QStringList DLCPlugins() const override; + virtual QStringList CCPlugins() const override; virtual LoadOrderMechanism loadOrderMechanism() const override; virtual int nexusModOrganizerID() const override; virtual int nexusGameID() const override; From 12b34c24a5b70975bc829e23ba1c78f0bb4d5daf Mon Sep 17 00:00:00 2001 From: Jeremy Rimpo Date: Fri, 17 Nov 2017 16:08:53 -0600 Subject: [PATCH 0373/1544] [game_fallout76] Update to parse CC plugins from game.ccc file --- src/games/fallout76/src/gamefallout4.cpp | 57 ++++++++++++++++-------- src/games/fallout76/src/gamefallout4.h | 1 + 2 files changed, 40 insertions(+), 18 deletions(-) diff --git a/src/games/fallout76/src/gamefallout4.cpp b/src/games/fallout76/src/gamefallout4.cpp index 30191ccd..a1dd3874 100644 --- a/src/games/fallout76/src/gamefallout4.cpp +++ b/src/games/fallout76/src/gamefallout4.cpp @@ -23,6 +23,11 @@ #include +#include "utility.h" +#include +#include +#include "scopeguard.h" + using namespace MOBase; GameFallout4::GameFallout4() @@ -123,16 +128,12 @@ QString GameFallout4::steamAPPId() const } QStringList GameFallout4::primaryPlugins() const { - return {"fallout4.esm", "dlcrobot.esm", "dlcworkshop01.esm", "dlccoast.esm", "dlcworkshop02.esm", - "dlcworkshop03.esm", "dlcnukaworld.esm", "dlcultrahighresolution.esm", - "ccbgsfo4001-pipboy(black).esl", "ccbgsfo4002-pipboy(blue).esl", "ccbgsfo4003-pipboy(camo01).esl", - "ccbgsfo4004-pipboy(camo02).esl", "ccbgsfo4006-pipboy(chrome).esl", "ccbgsfo4012-pipboy(red).esl", - "ccbgsfo4014-pipboy(white).esl", "ccbgsfo4016-prey.esl", "ccbgsfo4017-mauler.esl", "ccbgsfo4018-gaussrifleprototype.esl", - "ccbgsfo4019-chinesestealtharmor.esl", "ccbgsfo4020-powerarmorskin(black).esl", "ccbgsfo4022-powerarmorskin(camo01).esl", - "ccbgsfo4023-powerarmorskin(camo02).esl", "ccbgsfo4025-powerarmorskin(chrome).esl", "ccbgsfo4038-horsearmor.esl", - "ccbgsfo4039-tunnelsnakes.esl", "ccbgsfo4041-doommarinearmor.esl", "ccbgsfo4042-bfg.esl", - "ccbgsfo4043-doomchainsaw.esl", "ccbgsfo4044-hellfirepowerarmor.esl", "ccfsvfo4001-modularmilitarybackpack.esl", - "ccfsvfo4002-midcenturymodern.esl", "ccfrsfo4001-handmadeshotgun.esl", "cceejfo4001-decorationpack.esl"}; + QStringList plugins = {"fallout4.esm", "dlcrobot.esm", "dlcworkshop01.esm", "dlccoast.esm", "dlcworkshop02.esm", + "dlcworkshop03.esm", "dlcnukaworld.esm", "dlcultrahighresolution.esm"}; + + plugins.append(CCPlugins()); + + return plugins; } QStringList GameFallout4::gameVariants() const @@ -158,14 +159,34 @@ QStringList GameFallout4::iniFiles() const QStringList GameFallout4::DLCPlugins() const { return {"dlcrobot.esm", "dlcworkshop01.esm", "dlccoast.esm", "dlcworkshop02.esm", "dlcworkshop03.esm", - "dlcnukaworld.esm", "dlcultrahighresolution.esm", "ccbgsfo4001-pipboy(black).esl", "ccbgsfo4002-pipboy(blue).esl", - "ccbgsfo4003-pipboy(camo01).esl", "ccbgsfo4004-pipboy(camo02).esl", "ccbgsfo4006-pipboy(chrome).esl", "ccbgsfo4012-pipboy(red).esl", - "ccbgsfo4014-pipboy(white).esl", "ccbgsfo4016-prey.esl", "ccbgsfo4017-mauler.esl", "ccbgsfo4018-gaussrifleprototype.esl", - "ccbgsfo4019-chinesestealtharmor.esl", "ccbgsfo4020-powerarmorskin(black).esl", "ccbgsfo4022-powerarmorskin(camo01).esl", - "ccbgsfo4023-powerarmorskin(camo02).esl", "ccbgsfo4025-powerarmorskin(chrome).esl", "ccbgsfo4038-horsearmor.esl", - "ccbgsfo4039-tunnelsnakes.esl", "ccbgsfo4041-doommarinearmor.esl", "ccbgsfo4042-bfg.esl", - "ccbgsfo4043-doomchainsaw.esl", "ccbgsfo4044-hellfirepowerarmor.esl", "ccfsvfo4001-modularmilitarybackpack.esl", - "ccfsvfo4002-midcenturymodern.esl", "ccfrsfo4001-handmadeshotgun.esl", "cceejfo4001-decorationpack.esl"}; + "dlcnukaworld.esm", "dlcultrahighresolution.esm"}; +} + +QStringList GameFallout4::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::LoadOrderMechanism GameFallout4::loadOrderMechanism() const diff --git a/src/games/fallout76/src/gamefallout4.h b/src/games/fallout76/src/gamefallout4.h index 655bc197..ad06bf54 100644 --- a/src/games/fallout76/src/gamefallout4.h +++ b/src/games/fallout76/src/gamefallout4.h @@ -32,6 +32,7 @@ public: // IPluginGame interface virtual QString gameNexusName() const override; virtual QStringList iniFiles() const override; virtual QStringList DLCPlugins() const override; + virtual QStringList CCPlugins() const override; virtual LoadOrderMechanism loadOrderMechanism() const override; virtual int nexusModOrganizerID() const override; virtual int nexusGameID() const override; From ba0ecab189d1bfa8a063dc7dcd17aa0dfb65253e Mon Sep 17 00:00:00 2001 From: Jeremy Rimpo Date: Fri, 17 Nov 2017 16:08:53 -0600 Subject: [PATCH 0374/1544] [game_fallout4] Update to parse CC plugins from game.ccc file --- src/games/fallout4/src/gamefallout4.cpp | 57 +++++++++++++++++-------- src/games/fallout4/src/gamefallout4.h | 1 + 2 files changed, 40 insertions(+), 18 deletions(-) diff --git a/src/games/fallout4/src/gamefallout4.cpp b/src/games/fallout4/src/gamefallout4.cpp index 30191ccd..a1dd3874 100644 --- a/src/games/fallout4/src/gamefallout4.cpp +++ b/src/games/fallout4/src/gamefallout4.cpp @@ -23,6 +23,11 @@ #include +#include "utility.h" +#include +#include +#include "scopeguard.h" + using namespace MOBase; GameFallout4::GameFallout4() @@ -123,16 +128,12 @@ QString GameFallout4::steamAPPId() const } QStringList GameFallout4::primaryPlugins() const { - return {"fallout4.esm", "dlcrobot.esm", "dlcworkshop01.esm", "dlccoast.esm", "dlcworkshop02.esm", - "dlcworkshop03.esm", "dlcnukaworld.esm", "dlcultrahighresolution.esm", - "ccbgsfo4001-pipboy(black).esl", "ccbgsfo4002-pipboy(blue).esl", "ccbgsfo4003-pipboy(camo01).esl", - "ccbgsfo4004-pipboy(camo02).esl", "ccbgsfo4006-pipboy(chrome).esl", "ccbgsfo4012-pipboy(red).esl", - "ccbgsfo4014-pipboy(white).esl", "ccbgsfo4016-prey.esl", "ccbgsfo4017-mauler.esl", "ccbgsfo4018-gaussrifleprototype.esl", - "ccbgsfo4019-chinesestealtharmor.esl", "ccbgsfo4020-powerarmorskin(black).esl", "ccbgsfo4022-powerarmorskin(camo01).esl", - "ccbgsfo4023-powerarmorskin(camo02).esl", "ccbgsfo4025-powerarmorskin(chrome).esl", "ccbgsfo4038-horsearmor.esl", - "ccbgsfo4039-tunnelsnakes.esl", "ccbgsfo4041-doommarinearmor.esl", "ccbgsfo4042-bfg.esl", - "ccbgsfo4043-doomchainsaw.esl", "ccbgsfo4044-hellfirepowerarmor.esl", "ccfsvfo4001-modularmilitarybackpack.esl", - "ccfsvfo4002-midcenturymodern.esl", "ccfrsfo4001-handmadeshotgun.esl", "cceejfo4001-decorationpack.esl"}; + QStringList plugins = {"fallout4.esm", "dlcrobot.esm", "dlcworkshop01.esm", "dlccoast.esm", "dlcworkshop02.esm", + "dlcworkshop03.esm", "dlcnukaworld.esm", "dlcultrahighresolution.esm"}; + + plugins.append(CCPlugins()); + + return plugins; } QStringList GameFallout4::gameVariants() const @@ -158,14 +159,34 @@ QStringList GameFallout4::iniFiles() const QStringList GameFallout4::DLCPlugins() const { return {"dlcrobot.esm", "dlcworkshop01.esm", "dlccoast.esm", "dlcworkshop02.esm", "dlcworkshop03.esm", - "dlcnukaworld.esm", "dlcultrahighresolution.esm", "ccbgsfo4001-pipboy(black).esl", "ccbgsfo4002-pipboy(blue).esl", - "ccbgsfo4003-pipboy(camo01).esl", "ccbgsfo4004-pipboy(camo02).esl", "ccbgsfo4006-pipboy(chrome).esl", "ccbgsfo4012-pipboy(red).esl", - "ccbgsfo4014-pipboy(white).esl", "ccbgsfo4016-prey.esl", "ccbgsfo4017-mauler.esl", "ccbgsfo4018-gaussrifleprototype.esl", - "ccbgsfo4019-chinesestealtharmor.esl", "ccbgsfo4020-powerarmorskin(black).esl", "ccbgsfo4022-powerarmorskin(camo01).esl", - "ccbgsfo4023-powerarmorskin(camo02).esl", "ccbgsfo4025-powerarmorskin(chrome).esl", "ccbgsfo4038-horsearmor.esl", - "ccbgsfo4039-tunnelsnakes.esl", "ccbgsfo4041-doommarinearmor.esl", "ccbgsfo4042-bfg.esl", - "ccbgsfo4043-doomchainsaw.esl", "ccbgsfo4044-hellfirepowerarmor.esl", "ccfsvfo4001-modularmilitarybackpack.esl", - "ccfsvfo4002-midcenturymodern.esl", "ccfrsfo4001-handmadeshotgun.esl", "cceejfo4001-decorationpack.esl"}; + "dlcnukaworld.esm", "dlcultrahighresolution.esm"}; +} + +QStringList GameFallout4::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::LoadOrderMechanism GameFallout4::loadOrderMechanism() const diff --git a/src/games/fallout4/src/gamefallout4.h b/src/games/fallout4/src/gamefallout4.h index 655bc197..ad06bf54 100644 --- a/src/games/fallout4/src/gamefallout4.h +++ b/src/games/fallout4/src/gamefallout4.h @@ -32,6 +32,7 @@ public: // IPluginGame interface virtual QString gameNexusName() const override; virtual QStringList iniFiles() const override; virtual QStringList DLCPlugins() const override; + virtual QStringList CCPlugins() const override; virtual LoadOrderMechanism loadOrderMechanism() const override; virtual int nexusModOrganizerID() const override; virtual int nexusGameID() const override; From 91270d7e6a25d6e6a16353ad9ab53722584c2c77 Mon Sep 17 00:00:00 2001 From: Jeremy Rimpo Date: Fri, 17 Nov 2017 16:08:54 -0600 Subject: [PATCH 0375/1544] [game_skyrimse] Update to parse CC plugins from game.ccc file --- src/games/skyrimse/src/gameskyrimse.cpp | 45 +++++++++++++++++++------ src/games/skyrimse/src/gameskyrimse.h | 3 +- 2 files changed, 36 insertions(+), 12 deletions(-) diff --git a/src/games/skyrimse/src/gameskyrimse.cpp b/src/games/skyrimse/src/gameskyrimse.cpp index 3af9764c..51e481e8 100644 --- a/src/games/skyrimse/src/gameskyrimse.cpp +++ b/src/games/skyrimse/src/gameskyrimse.cpp @@ -23,11 +23,11 @@ #include - #include "utility.h" #include #include #include "scopeguard.h" + namespace { std::unique_ptr getRegValue(HKEY key, LPCWSTR path, LPCWSTR value, @@ -261,11 +261,11 @@ QString GameSkyrimSE::steamAPPId() const } QStringList GameSkyrimSE::primaryPlugins() const { - return{ "skyrim.esm", "update.esm", "dawnguard.esm", "hearthfires.esm", "dragonborn.esm", - "ccbgssse002-exoticarrows.esl", "ccbgssse003-zombies.esl", "ccbgssse004-ruinsedge.esl", - "ccbgssse006-stendarshammer.esl", "ccbgssse007-chrysamere.esl", "ccbgssse010-petdwarvenarmoredmudcrab.esl", - "ccbgssse014-spellpack01.esl", "ccbgssse019-staffofsheogorath.esl", "ccmtysse001-knightsofthenine.esl", - "ccqdrsse001-survivalmode.esl" };// }; + QStringList plugins = { "skyrim.esm", "update.esm", "dawnguard.esm", "hearthfires.esm", "dragonborn.esm" }; + + plugins.append(CCPlugins()); + + return plugins; } QStringList GameSkyrimSE::gameVariants() const @@ -291,11 +291,34 @@ QStringList GameSkyrimSE::iniFiles() const QStringList GameSkyrimSE::DLCPlugins() const { - return{ "dawnguard.esm", "hearthfires.esm", "dragonborn.esm", - "ccbgssse002-exoticarrows.esl", "ccbgssse003-zombies.esl", "ccbgssse004-ruinsedge.esl", - "ccbgssse006-stendarshammer.esl", "ccbgssse007-chrysamere.esl", "ccbgssse010-petdwarvenarmoredmudcrab.esl", - "ccbgssse014-spellpack01.esl", "ccbgssse019-staffofsheogorath.esl", "ccmtysse001-knightsofthenine.esl", - "ccqdrsse001-survivalmode.esl" }; + return{ "dawnguard.esm", "hearthfires.esm", "dragonborn.esm" }; +} + +QStringList GameSkyrimSE::CCPlugins() const +{ + QStringList plugins = {}; + QFile file(gameDirectory().filePath("Skyrim.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::LoadOrderMechanism GameSkyrimSE::loadOrderMechanism() const diff --git a/src/games/skyrimse/src/gameskyrimse.h b/src/games/skyrimse/src/gameskyrimse.h index fd9b1afe..d1c68be5 100644 --- a/src/games/skyrimse/src/gameskyrimse.h +++ b/src/games/skyrimse/src/gameskyrimse.h @@ -30,9 +30,10 @@ public: // IPluginGame interface virtual QStringList primaryPlugins() const override; virtual QStringList gameVariants() const override; virtual QString gameShortName() const override; - virtual QString gameNexusName() const override; + virtual QString gameNexusName() const override; virtual QStringList iniFiles() const override; virtual QStringList DLCPlugins() const override; + virtual QStringList CCPlugins() const override; virtual LoadOrderMechanism loadOrderMechanism() const override; virtual int nexusModOrganizerID() const override; virtual int nexusGameID() const override; From ab3138b589fb7cfdfcf0fbabc32bf3e634abe051 Mon Sep 17 00:00:00 2001 From: Jeremy Rimpo Date: Wed, 6 Dec 2017 20:39:54 -0600 Subject: [PATCH 0376/1544] Split the ini destination based on the localSettingsEnabled status (Local settings are enabled by the ini being created in the profile.) --- src/gamebryolocalsavegames.cpp | 7 ++++++- src/gamebryolocalsavegames.h | 1 + 2 files changed, 7 insertions(+), 1 deletion(-) diff --git a/src/gamebryolocalsavegames.cpp b/src/gamebryolocalsavegames.cpp index 782d945c..f696bc76 100644 --- a/src/gamebryolocalsavegames.cpp +++ b/src/gamebryolocalsavegames.cpp @@ -31,6 +31,7 @@ static const QString LocalSavesDummy = "__MO_Saves"; GamebryoLocalSavegames::GamebryoLocalSavegames(const QDir &myGamesDir, const QString &iniFileName) : m_LocalSavesDir(myGamesDir.absoluteFilePath(LocalSavesDummy)) + , m_LocalGameDir(myGamesDir.absolutePath()) , m_IniFileName(iniFileName) {} @@ -39,7 +40,11 @@ void GamebryoLocalSavegames::prepareProfile(MOBase::IProfile *profile) { bool enable = profile->localSavesEnabled(); qDebug("enable local saves: %d", enable); - QString iniFilePath = profile->absolutePath() + "/" + m_IniFileName; + QString basePath + = profile->localSettingsEnabled() + ? profile->absolutePath() + : m_LocalGameDir.absolutePath(); + QString iniFilePath = basePath + "/" + m_IniFileName; WritePrivateProfileStringW(L"General", L"bUseMyGamesDirectory", enable ? L"0" : L"1", iniFilePath.toStdWString().c_str()); diff --git a/src/gamebryolocalsavegames.h b/src/gamebryolocalsavegames.h index 692e5144..eef7b9f3 100644 --- a/src/gamebryolocalsavegames.h +++ b/src/gamebryolocalsavegames.h @@ -38,6 +38,7 @@ public: private: QDir m_LocalSavesDir; + QDir m_LocalGameDir; QString m_IniFileName; }; From ca771fd18d9ab6e472ac3bb6d2c32a32c6991204 Mon Sep 17 00:00:00 2001 From: Jeremy Rimpo Date: Thu, 7 Dec 2017 21:52:25 -0600 Subject: [PATCH 0377/1544] bUseMyGamesDirectory should be false when using local and try to save original settings --- src/gamebryolocalsavegames.cpp | 40 ++++++++++++++++++++++++++++++---- 1 file changed, 36 insertions(+), 4 deletions(-) diff --git a/src/gamebryolocalsavegames.cpp b/src/gamebryolocalsavegames.cpp index f696bc76..1808c2b0 100644 --- a/src/gamebryolocalsavegames.cpp +++ b/src/gamebryolocalsavegames.cpp @@ -45,13 +45,45 @@ void GamebryoLocalSavegames::prepareProfile(MOBase::IProfile *profile) ? profile->absolutePath() : m_LocalGameDir.absolutePath(); QString iniFilePath = basePath + "/" + m_IniFileName; - WritePrivateProfileStringW(L"General", L"bUseMyGamesDirectory", - enable ? L"0" : L"1", - iniFilePath.toStdWString().c_str()); + + WCHAR oldPath[MAX_PATH]; + WCHAR oldMyGames[1]; + GetPrivateProfileStringW(L"General", L"SLocalSavePath", NULL, oldPath, MAX_PATH, iniFilePath.toStdWString().c_str()); + GetPrivateProfileStringW(L"General", L"bUseMyGamesDirectory", NULL, oldMyGames, 1, iniFilePath.toStdWString().c_str()); + if (enable && wcscmp(oldPath, L"") != 0 && wcscmp(oldPath, (LocalSavesDummy + "\\").toStdWString().c_str()) == 0) { + WritePrivateProfileStringW(L"General", L"SLocalSavePath", oldPath, QString(profile->absolutePath() + "/" + "savepath.ini").toStdWString().c_str()); + if (wcscmp(oldMyGames, L"") != 0) { + WritePrivateProfileStringW(L"General", L"bUseMyGamesDirectory", oldMyGames, QString(profile->absolutePath() + "/" + "savepath.ini").toStdWString().c_str()); + } + } + bool saved = false; + bool savedDir = false; + WCHAR savedPath[MAX_PATH]; + WCHAR savedMyGames[1]; + if (!enable) { + if (QFile::exists(QString(profile->absolutePath() + "/" + "savepath.ini"))) { + saved = true; + GetPrivateProfileStringW(L"General", L"SLocalSavePath", NULL, savedPath, MAX_PATH, iniFilePath.toStdWString().c_str()); + GetPrivateProfileStringW(L"General", L"bUseMyGamesDirectory", NULL, savedMyGames, 1, iniFilePath.toStdWString().c_str()); + if (wcscmp(oldMyGames, L"") != 0) { + savedDir = true; + } + QFile::remove(QString(profile->absolutePath() + "/" + "savepath.ini")); + } + } else { + QDir saves = QDir(m_LocalGameDir.absolutePath() + "/" + LocalSavesDummy); + if (!saves.exists()) { + saves.mkdir("."); + } + } WritePrivateProfileStringW(L"General", L"SLocalSavePath", enable ? (LocalSavesDummy + "\\").toStdWString().c_str() - : NULL, + : (saved ? savedPath : NULL), + iniFilePath.toStdWString().c_str()); + + WritePrivateProfileStringW(L"General", L"bUseMyGamesDirectory", + enable ? NULL : (savedDir ? savedMyGames : NULL), iniFilePath.toStdWString().c_str()); } From c230911ba492b3690889137ac04701e12883a252 Mon Sep 17 00:00:00 2001 From: Jeremy Rimpo Date: Fri, 8 Dec 2017 02:39:25 -0600 Subject: [PATCH 0378/1544] [game_falloutnv] Add function to return the script extender save extension --- src/games/falloutnv/src/gamefalloutnv.cpp | 5 +++++ src/games/falloutnv/src/gamefalloutnv.h | 1 + 2 files changed, 6 insertions(+) diff --git a/src/games/falloutnv/src/gamefalloutnv.cpp b/src/games/falloutnv/src/gamefalloutnv.cpp index 8f10abcd..00155013 100644 --- a/src/games/falloutnv/src/gamefalloutnv.cpp +++ b/src/games/falloutnv/src/gamefalloutnv.cpp @@ -115,6 +115,11 @@ QString GameFalloutNV::savegameExtension() const return "fos"; } +QString GameFalloutNV::savegameSEExtension() const +{ + return "nvse"; +} + QString GameFalloutNV::steamAPPId() const { return "22380"; diff --git a/src/games/falloutnv/src/gamefalloutnv.h b/src/games/falloutnv/src/gamefalloutnv.h index e53bfd51..e4609629 100644 --- a/src/games/falloutnv/src/gamefalloutnv.h +++ b/src/games/falloutnv/src/gamefalloutnv.h @@ -25,6 +25,7 @@ public: // IPluginGame interface virtual QList executables() const override; virtual void initializeProfile(const QDir &path, ProfileSettings settings) const override; virtual QString savegameExtension() const override; + virtual QString savegameSEExtension() const override; virtual QString steamAPPId() const override; virtual QStringList primaryPlugins() const override; virtual QString gameShortName() const override; From 66692fe87c71b56f1285f1ad5832434d9d4ea467 Mon Sep 17 00:00:00 2001 From: Jeremy Rimpo Date: Fri, 8 Dec 2017 02:39:26 -0600 Subject: [PATCH 0379/1544] [game_oblivion] Add function to return the script extender save extension --- src/games/oblivion/src/gameoblivion.cpp | 5 +++++ src/games/oblivion/src/gameoblivion.h | 1 + 2 files changed, 6 insertions(+) diff --git a/src/games/oblivion/src/gameoblivion.cpp b/src/games/oblivion/src/gameoblivion.cpp index fc9cb354..578abf51 100644 --- a/src/games/oblivion/src/gameoblivion.cpp +++ b/src/games/oblivion/src/gameoblivion.cpp @@ -110,6 +110,11 @@ QString GameOblivion::savegameExtension() const return "ess"; } +QString GameOblivion::savegameSEExtension() const +{ + return "obse"; +} + QString GameOblivion::steamAPPId() const { return "22330"; diff --git a/src/games/oblivion/src/gameoblivion.h b/src/games/oblivion/src/gameoblivion.h index 91b08be5..bea187a3 100644 --- a/src/games/oblivion/src/gameoblivion.h +++ b/src/games/oblivion/src/gameoblivion.h @@ -23,6 +23,7 @@ public: // IPluginGame interface virtual QList executables() const override; virtual void initializeProfile(const QDir &path, ProfileSettings settings) const override; virtual QString savegameExtension() const override; + virtual QString savegameSEExtension() const override; virtual QString steamAPPId() const override; virtual QStringList primaryPlugins() const override; virtual QString gameShortName() const override; From 88cbd78e29a3a2be38030f66d27ba4da80074380 Mon Sep 17 00:00:00 2001 From: Jeremy Rimpo Date: Fri, 8 Dec 2017 02:39:31 -0600 Subject: [PATCH 0380/1544] Add function to return the script extender save extension --- src/gamegamebryo.h | 1 + 1 file changed, 1 insertion(+) diff --git a/src/gamegamebryo.h b/src/gamegamebryo.h index 23b35da8..7f073107 100644 --- a/src/gamegamebryo.h +++ b/src/gamegamebryo.h @@ -42,6 +42,7 @@ public: // IPluginGame interface //getName //initializeProfile //savegameExtension + //savegameSEExtension virtual bool isInstalled() const override; virtual QIcon gameIcon() const override; virtual QDir gameDirectory() const override; From 354bf8160a4fec9a63f966dab8345cd0ec60f9c6 Mon Sep 17 00:00:00 2001 From: Jeremy Rimpo Date: Fri, 8 Dec 2017 02:39:33 -0600 Subject: [PATCH 0381/1544] [game_fallout3] Add function to return the script extender save extension --- src/games/fallout3/src/gamefallout3.cpp | 5 +++++ src/games/fallout3/src/gamefallout3.h | 1 + 2 files changed, 6 insertions(+) diff --git a/src/games/fallout3/src/gamefallout3.cpp b/src/games/fallout3/src/gamefallout3.cpp index d4900d50..c31214ee 100644 --- a/src/games/fallout3/src/gamefallout3.cpp +++ b/src/games/fallout3/src/gamefallout3.cpp @@ -115,6 +115,11 @@ QString GameFallout3::savegameExtension() const return "fos"; } +QString GameFallout3::savegameSEExtension() const +{ + return ""; +} + QString GameFallout3::steamAPPId() const { if (selectedVariant() == "Game Of The Year") { diff --git a/src/games/fallout3/src/gamefallout3.h b/src/games/fallout3/src/gamefallout3.h index d5401582..2cc6ce80 100644 --- a/src/games/fallout3/src/gamefallout3.h +++ b/src/games/fallout3/src/gamefallout3.h @@ -23,6 +23,7 @@ public: // IPluginGame interface virtual QList executables() const override; virtual void initializeProfile(const QDir &path, ProfileSettings settings) const override; virtual QString savegameExtension() const override; + virtual QString savegameSEExtension() const override; virtual QString steamAPPId() const override; virtual QStringList primaryPlugins() const override; virtual QStringList gameVariants() const; From ec17217d01ee1fc8aadf53e41482c2f55c4b3ba9 Mon Sep 17 00:00:00 2001 From: Jeremy Rimpo Date: Fri, 8 Dec 2017 02:39:34 -0600 Subject: [PATCH 0382/1544] [game_fallout4vr] Add function to return the script extender save extension --- src/games/fallout4vr/src/gamefallout4.cpp | 5 +++++ src/games/fallout4vr/src/gamefallout4.h | 1 + 2 files changed, 6 insertions(+) diff --git a/src/games/fallout4vr/src/gamefallout4.cpp b/src/games/fallout4vr/src/gamefallout4.cpp index a1dd3874..b92ad9dc 100644 --- a/src/games/fallout4vr/src/gamefallout4.cpp +++ b/src/games/fallout4vr/src/gamefallout4.cpp @@ -122,6 +122,11 @@ QString GameFallout4::savegameExtension() const return "fos"; } +QString GameFallout4::savegameSEExtension() const +{ + return "f4se"; +} + QString GameFallout4::steamAPPId() const { return "377160"; diff --git a/src/games/fallout4vr/src/gamefallout4.h b/src/games/fallout4vr/src/gamefallout4.h index ad06bf54..60cbf083 100644 --- a/src/games/fallout4vr/src/gamefallout4.h +++ b/src/games/fallout4vr/src/gamefallout4.h @@ -25,6 +25,7 @@ public: // IPluginGame interface virtual QList executables() const override; virtual void initializeProfile(const QDir &path, ProfileSettings settings) const override; virtual QString savegameExtension() const override; + virtual QString savegameSEExtension() const override; virtual QString steamAPPId() const override; virtual QStringList primaryPlugins() const override; virtual QStringList gameVariants() const override; From 0f064de60aa1e3e31f267f5ba9b7a6e1dfe1e6e8 Mon Sep 17 00:00:00 2001 From: Jeremy Rimpo Date: Fri, 8 Dec 2017 02:39:34 -0600 Subject: [PATCH 0383/1544] [game_fallout76] Add function to return the script extender save extension --- src/games/fallout76/src/gamefallout4.cpp | 5 +++++ src/games/fallout76/src/gamefallout4.h | 1 + 2 files changed, 6 insertions(+) diff --git a/src/games/fallout76/src/gamefallout4.cpp b/src/games/fallout76/src/gamefallout4.cpp index a1dd3874..b92ad9dc 100644 --- a/src/games/fallout76/src/gamefallout4.cpp +++ b/src/games/fallout76/src/gamefallout4.cpp @@ -122,6 +122,11 @@ QString GameFallout4::savegameExtension() const return "fos"; } +QString GameFallout4::savegameSEExtension() const +{ + return "f4se"; +} + QString GameFallout4::steamAPPId() const { return "377160"; diff --git a/src/games/fallout76/src/gamefallout4.h b/src/games/fallout76/src/gamefallout4.h index ad06bf54..60cbf083 100644 --- a/src/games/fallout76/src/gamefallout4.h +++ b/src/games/fallout76/src/gamefallout4.h @@ -25,6 +25,7 @@ public: // IPluginGame interface virtual QList executables() const override; virtual void initializeProfile(const QDir &path, ProfileSettings settings) const override; virtual QString savegameExtension() const override; + virtual QString savegameSEExtension() const override; virtual QString steamAPPId() const override; virtual QStringList primaryPlugins() const override; virtual QStringList gameVariants() const override; From 9be272819c17fb6b8b43bee74e587c1e2c7320df Mon Sep 17 00:00:00 2001 From: Jeremy Rimpo Date: Fri, 8 Dec 2017 02:39:34 -0600 Subject: [PATCH 0384/1544] [game_fallout4] Add function to return the script extender save extension --- src/games/fallout4/src/gamefallout4.cpp | 5 +++++ src/games/fallout4/src/gamefallout4.h | 1 + 2 files changed, 6 insertions(+) diff --git a/src/games/fallout4/src/gamefallout4.cpp b/src/games/fallout4/src/gamefallout4.cpp index a1dd3874..b92ad9dc 100644 --- a/src/games/fallout4/src/gamefallout4.cpp +++ b/src/games/fallout4/src/gamefallout4.cpp @@ -122,6 +122,11 @@ QString GameFallout4::savegameExtension() const return "fos"; } +QString GameFallout4::savegameSEExtension() const +{ + return "f4se"; +} + QString GameFallout4::steamAPPId() const { return "377160"; diff --git a/src/games/fallout4/src/gamefallout4.h b/src/games/fallout4/src/gamefallout4.h index ad06bf54..60cbf083 100644 --- a/src/games/fallout4/src/gamefallout4.h +++ b/src/games/fallout4/src/gamefallout4.h @@ -25,6 +25,7 @@ public: // IPluginGame interface virtual QList executables() const override; virtual void initializeProfile(const QDir &path, ProfileSettings settings) const override; virtual QString savegameExtension() const override; + virtual QString savegameSEExtension() const override; virtual QString steamAPPId() const override; virtual QStringList primaryPlugins() const override; virtual QStringList gameVariants() const override; From e3a2270d496ec771d60cfb7af276de46dff75330 Mon Sep 17 00:00:00 2001 From: Jeremy Rimpo Date: Fri, 8 Dec 2017 02:39:35 -0600 Subject: [PATCH 0385/1544] [game_skyrimse] Add function to return the script extender save extension --- src/games/skyrimse/src/gameskyrimse.cpp | 5 +++++ src/games/skyrimse/src/gameskyrimse.h | 1 + 2 files changed, 6 insertions(+) diff --git a/src/games/skyrimse/src/gameskyrimse.cpp b/src/games/skyrimse/src/gameskyrimse.cpp index 51e481e8..65274d97 100644 --- a/src/games/skyrimse/src/gameskyrimse.cpp +++ b/src/games/skyrimse/src/gameskyrimse.cpp @@ -255,6 +255,11 @@ QString GameSkyrimSE::savegameExtension() const return "ess"; } +QString GameSkyrimSE::savegameSEExtension() const +{ + return "skse"; +} + QString GameSkyrimSE::steamAPPId() const { return "489830"; diff --git a/src/games/skyrimse/src/gameskyrimse.h b/src/games/skyrimse/src/gameskyrimse.h index d1c68be5..14811d04 100644 --- a/src/games/skyrimse/src/gameskyrimse.h +++ b/src/games/skyrimse/src/gameskyrimse.h @@ -26,6 +26,7 @@ public: // IPluginGame interface virtual QList executables() const override; virtual void initializeProfile(const QDir &path, ProfileSettings settings) const override; virtual QString savegameExtension() const override; + virtual QString savegameSEExtension() const override; virtual QString steamAPPId() const override; virtual QStringList primaryPlugins() const override; virtual QStringList gameVariants() const override; From 2074c7703e6b37cb8ee8af9b102b14e7e90237d1 Mon Sep 17 00:00:00 2001 From: Jeremy Rimpo Date: Fri, 8 Dec 2017 02:39:36 -0600 Subject: [PATCH 0386/1544] [game_skyrim] Add function to return the script extender save extension --- src/games/skyrim/src/gameskyrim.cpp | 5 +++++ src/games/skyrim/src/gameskyrim.h | 1 + 2 files changed, 6 insertions(+) diff --git a/src/games/skyrim/src/gameskyrim.cpp b/src/games/skyrim/src/gameskyrim.cpp index 6b1c59f8..a3ba96af 100644 --- a/src/games/skyrim/src/gameskyrim.cpp +++ b/src/games/skyrim/src/gameskyrim.cpp @@ -120,6 +120,11 @@ QString GameSkyrim::savegameExtension() const return "ess"; } +QString GameSkyrim::savegameSEExtension() const +{ + return "skse"; +} + QString GameSkyrim::steamAPPId() const { return "72850"; diff --git a/src/games/skyrim/src/gameskyrim.h b/src/games/skyrim/src/gameskyrim.h index fd299550..fcc90193 100644 --- a/src/games/skyrim/src/gameskyrim.h +++ b/src/games/skyrim/src/gameskyrim.h @@ -25,6 +25,7 @@ public: // IPluginGame interface virtual QList executables() const override; virtual void initializeProfile(const QDir &path, ProfileSettings settings) const override; virtual QString savegameExtension() const override; + virtual QString savegameSEExtension() const override; virtual QString steamAPPId() const override; virtual QStringList primaryPlugins() const override; virtual QString binaryName() const override; From e87b1028d8d11537542e4e045dc5f5a408c26ce5 Mon Sep 17 00:00:00 2001 From: Jeremy Rimpo Date: Sat, 9 Dec 2017 19:04:17 -0600 Subject: [PATCH 0387/1544] [game_falloutnv] Add the launch argument to tell LOOT which game to start --- src/games/falloutnv/src/gamefalloutnv.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/games/falloutnv/src/gamefalloutnv.cpp b/src/games/falloutnv/src/gamefalloutnv.cpp index 00155013..7deca029 100644 --- a/src/games/falloutnv/src/gamefalloutnv.cpp +++ b/src/games/falloutnv/src/gamefalloutnv.cpp @@ -57,7 +57,7 @@ QList GameFalloutNV::executables() const << ExecutableInfo("Construction Kit", findInGameFolder("geck.exe")) << ExecutableInfo("Fallout Launcher", findInGameFolder(getLauncherName())) << ExecutableInfo("BOSS", findInGameFolder("BOSS/BOSS.exe")) - << ExecutableInfo("LOOT", getLootPath()) + << ExecutableInfo("LOOT", getLootPath()).withArgument("--game=\"FalloutNV\"") ; } From dc7f3aeb605c6544f4e5873ae253ccef2563e967 Mon Sep 17 00:00:00 2001 From: Jeremy Rimpo Date: Sat, 9 Dec 2017 19:04:18 -0600 Subject: [PATCH 0388/1544] [game_fallout3] Add the launch argument to tell LOOT which game to start --- src/games/fallout3/src/gamefallout3.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/games/fallout3/src/gamefallout3.cpp b/src/games/fallout3/src/gamefallout3.cpp index c31214ee..9193e99f 100644 --- a/src/games/fallout3/src/gamefallout3.cpp +++ b/src/games/fallout3/src/gamefallout3.cpp @@ -57,7 +57,7 @@ QList GameFallout3::executables() const << ExecutableInfo("Construction Kit", findInGameFolder("geck.exe")) << ExecutableInfo("Fallout Launcher", findInGameFolder(getLauncherName())) << ExecutableInfo("BOSS", findInGameFolder("BOSS/BOSS.exe")) - << ExecutableInfo("LOOT", getLootPath()) + << ExecutableInfo("LOOT", getLootPath()).withArgument("--game=\"Fallout3\"") ; } From d23f17758533802cfe79888f4d5f5858c8d77bbf Mon Sep 17 00:00:00 2001 From: Jeremy Rimpo Date: Sat, 9 Dec 2017 19:04:18 -0600 Subject: [PATCH 0389/1544] [game_oblivion] Add the launch argument to tell LOOT which game to start --- src/games/oblivion/src/gameoblivion.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/games/oblivion/src/gameoblivion.cpp b/src/games/oblivion/src/gameoblivion.cpp index 578abf51..cf4c1763 100644 --- a/src/games/oblivion/src/gameoblivion.cpp +++ b/src/games/oblivion/src/gameoblivion.cpp @@ -51,7 +51,7 @@ QList GameOblivion::executables() const << ExecutableInfo("Oblivion Launcher", findInGameFolder(getLauncherName())) << ExecutableInfo("Oblivion Mod Manager", findInGameFolder("OblivionModManager.exe")) << ExecutableInfo("BOSS", findInGameFolder("BOSS/BOSS.exe")) - << ExecutableInfo("LOOT", getLootPath()) + << ExecutableInfo("LOOT", getLootPath()).withArgument("--game=\"Oblivion\"") << ExecutableInfo("Construction Set", findInGameFolder("TESConstructionSet.exe")) ; } From 1ea27bf74fd411a7122dd85d8583975af2f45540 Mon Sep 17 00:00:00 2001 From: Jeremy Rimpo Date: Sat, 9 Dec 2017 19:04:19 -0600 Subject: [PATCH 0390/1544] [game_fallout4vr] Add the launch argument to tell LOOT which game to start --- src/games/fallout4vr/src/gamefallout4.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/games/fallout4vr/src/gamefallout4.cpp b/src/games/fallout4vr/src/gamefallout4.cpp index b92ad9dc..6257fbf8 100644 --- a/src/games/fallout4vr/src/gamefallout4.cpp +++ b/src/games/fallout4vr/src/gamefallout4.cpp @@ -62,7 +62,7 @@ QList GameFallout4::executables() const << ExecutableInfo("Fallout 4", findInGameFolder(binaryName())) << ExecutableInfo("Fallout Launcher", findInGameFolder(getLauncherName())) << ExecutableInfo("Creation Kit", findInGameFolder("CreationKit.exe")) - << ExecutableInfo("LOOT", getLootPath()) + << ExecutableInfo("LOOT", getLootPath()).withArgument("--game=\"Fallout4\"") ; } From 2a94d8f5b719defd3142e56de587dc6078faca95 Mon Sep 17 00:00:00 2001 From: Jeremy Rimpo Date: Sat, 9 Dec 2017 19:04:19 -0600 Subject: [PATCH 0391/1544] [game_fallout76] Add the launch argument to tell LOOT which game to start --- src/games/fallout76/src/gamefallout4.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/games/fallout76/src/gamefallout4.cpp b/src/games/fallout76/src/gamefallout4.cpp index b92ad9dc..6257fbf8 100644 --- a/src/games/fallout76/src/gamefallout4.cpp +++ b/src/games/fallout76/src/gamefallout4.cpp @@ -62,7 +62,7 @@ QList GameFallout4::executables() const << ExecutableInfo("Fallout 4", findInGameFolder(binaryName())) << ExecutableInfo("Fallout Launcher", findInGameFolder(getLauncherName())) << ExecutableInfo("Creation Kit", findInGameFolder("CreationKit.exe")) - << ExecutableInfo("LOOT", getLootPath()) + << ExecutableInfo("LOOT", getLootPath()).withArgument("--game=\"Fallout4\"") ; } From 98b771dd21b7bbc8b41d24574832ecafbbe28aa2 Mon Sep 17 00:00:00 2001 From: Jeremy Rimpo Date: Sat, 9 Dec 2017 19:04:19 -0600 Subject: [PATCH 0392/1544] [game_fallout4] Add the launch argument to tell LOOT which game to start --- src/games/fallout4/src/gamefallout4.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/games/fallout4/src/gamefallout4.cpp b/src/games/fallout4/src/gamefallout4.cpp index b92ad9dc..6257fbf8 100644 --- a/src/games/fallout4/src/gamefallout4.cpp +++ b/src/games/fallout4/src/gamefallout4.cpp @@ -62,7 +62,7 @@ QList GameFallout4::executables() const << ExecutableInfo("Fallout 4", findInGameFolder(binaryName())) << ExecutableInfo("Fallout Launcher", findInGameFolder(getLauncherName())) << ExecutableInfo("Creation Kit", findInGameFolder("CreationKit.exe")) - << ExecutableInfo("LOOT", getLootPath()) + << ExecutableInfo("LOOT", getLootPath()).withArgument("--game=\"Fallout4\"") ; } From bff2874fed07fe39c20ffc5e81760528455c837c Mon Sep 17 00:00:00 2001 From: Jeremy Rimpo Date: Sat, 9 Dec 2017 19:04:20 -0600 Subject: [PATCH 0393/1544] [game_skyrimse] Add the launch argument to tell LOOT which game to start --- src/games/skyrimse/src/gameskyrimse.cpp | 14 +++++++------- 1 file changed, 7 insertions(+), 7 deletions(-) diff --git a/src/games/skyrimse/src/gameskyrimse.cpp b/src/games/skyrimse/src/gameskyrimse.cpp index 65274d97..2b139675 100644 --- a/src/games/skyrimse/src/gameskyrimse.cpp +++ b/src/games/skyrimse/src/gameskyrimse.cpp @@ -186,13 +186,13 @@ QString GameSkyrimSE::gameName() const QList GameSkyrimSE::executables() const { - return QList() - << ExecutableInfo("SKSE", findInGameFolder(feature()->loaderName())) - << ExecutableInfo("Skyrim Special Edition", findInGameFolder(binaryName())) - << ExecutableInfo("Skyrim Special Edition Launcher", findInGameFolder(getLauncherName())) - << ExecutableInfo("Creation Kit", findInGameFolder("CreationKit.exe")) - << ExecutableInfo("LOOT", getLootPath()) - ; + return QList() + << ExecutableInfo("SKSE", findInGameFolder(feature()->loaderName())) + << ExecutableInfo("Skyrim Special Edition", findInGameFolder(binaryName())) + << ExecutableInfo("Skyrim Special Edition Launcher", findInGameFolder(getLauncherName())) + << ExecutableInfo("Creation Kit", findInGameFolder("CreationKit.exe")) + << ExecutableInfo("LOOT", getLootPath()).withArgument("--game=\"Skyrim Special Edition\"") + ; } QFileInfo GameSkyrimSE::findInGameFolder(const QString &relativePath) const From 04e462d4e8304a28b5e7dbb3c47ff48dd52755b3 Mon Sep 17 00:00:00 2001 From: Jeremy Rimpo Date: Sat, 9 Dec 2017 19:04:20 -0600 Subject: [PATCH 0394/1544] [game_skyrim] Add the launch argument to tell LOOT which game to start --- src/games/skyrim/src/gameskyrim.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/games/skyrim/src/gameskyrim.cpp b/src/games/skyrim/src/gameskyrim.cpp index a3ba96af..fc1c091e 100644 --- a/src/games/skyrim/src/gameskyrim.cpp +++ b/src/games/skyrim/src/gameskyrim.cpp @@ -61,7 +61,7 @@ QList GameSkyrim::executables() const << ExecutableInfo("Skyrim", findInGameFolder(binaryName())) << ExecutableInfo("Skyrim Launcher", findInGameFolder(getLauncherName())) << ExecutableInfo("BOSS", findInGameFolder("BOSS/BOSS.exe")) - << ExecutableInfo("LOOT", getLootPath()) + << ExecutableInfo("LOOT", getLootPath()).withArgument("--game=\"Skyrim\"") << ExecutableInfo("Creation Kit", findInGameFolder("CreationKit.exe")).withSteamAppId("202480") ; } From 7f807764b32764f5676f56fa06d58c0431e2ac2e Mon Sep 17 00:00:00 2001 From: Jeremy Rimpo Date: Sat, 9 Dec 2017 23:20:33 -0600 Subject: [PATCH 0395/1544] Use localSettingsEnabled to determine the correct settings path --- src/gamebryobsainvalidation.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/gamebryobsainvalidation.cpp b/src/gamebryobsainvalidation.cpp index aa4bfa06..000ca369 100644 --- a/src/gamebryobsainvalidation.cpp +++ b/src/gamebryobsainvalidation.cpp @@ -48,7 +48,7 @@ void GamebryoBSAInvalidation::deactivate(MOBase::IProfile *profile) MOBase::shellDeleteQuiet(bsaFile); } - QString iniFile = QDir(profile->absolutePath()).absoluteFilePath(m_IniFileName); + QString iniFile = profile->localSettingsEnabled() ? QDir(profile->absolutePath()).absoluteFilePath(m_IniFileName) : m_Game->documentsDirectory().absoluteFilePath(m_IniFileName); ::SetFileAttributesW(iniFile.toStdWString().c_str(), FILE_ATTRIBUTE_NORMAL); From 0943605a0e0e45e24f3dad5680a8c3defad5137f Mon Sep 17 00:00:00 2001 From: Jeremy Rimpo Date: Sun, 10 Dec 2017 06:29:29 -0600 Subject: [PATCH 0396/1544] Multiple fixes for filetime load order parsing * Check for nonexistant loadorder.txt as well as filetime * Ensure we're loading plugin files from the correct location * QFileInfo has unexpected results getting filetime on invalid files --- src/gamebryogameplugins.cpp | 24 +++++++++++++++++------- 1 file changed, 17 insertions(+), 7 deletions(-) diff --git a/src/gamebryogameplugins.cpp b/src/gamebryogameplugins.cpp index 10f39688..fcb9de8f 100644 --- a/src/gamebryogameplugins.cpp +++ b/src/gamebryogameplugins.cpp @@ -3,6 +3,7 @@ #include #include #include +#include #include #include @@ -42,6 +43,7 @@ void GamebryoGamePlugins::readPluginLists(MOBase::IPluginList *pluginList) { QString pluginsPath = organizer()->profile()->absolutePath() + "/plugins.txt"; bool loadOrderIsNew = !m_LastRead.isValid() || + !QFileInfo(loadOrderPath).exists() || QFileInfo(loadOrderPath).lastModified() > m_LastRead; bool pluginsIsNew = !m_LastRead.isValid() || QFileInfo(pluginsPath).lastModified() > m_LastRead; @@ -128,13 +130,21 @@ bool GamebryoGamePlugins::readLoadOrderList(MOBase::IPluginList *pluginList, if (!file.open(QIODevice::ReadOnly)) { // no load order stored, determine by date pluginNames = pluginList->pluginNames(); - QDir dataDirectory = organizer()->managedGame()->dataDirectory(); - std::sort( - pluginNames.begin(), pluginNames.end(), - [&dataDirectory](const QString &lhs, const QString &rhs) { - return QFileInfo(dataDirectory.absoluteFilePath(lhs)).lastModified() > - QFileInfo(dataDirectory.absoluteFilePath(rhs)).lastModified(); - }); + + std::sort(pluginNames.begin(), pluginNames.end(), [&](const QString &lhs, const QString &rhs) { + MOBase::IModInterface *lhm = organizer()->getMod(pluginList->origin(lhs)); + MOBase::IModInterface *rhm = organizer()->getMod(pluginList->origin(rhs)); + QDir lhd = organizer()->managedGame()->dataDirectory(); + QDir rhd = organizer()->managedGame()->dataDirectory(); + if (lhm != nullptr) + lhd = lhm->absolutePath(); + if (rhm != nullptr) + rhd = rhm->absolutePath(); + QString lhp = lhd.absoluteFilePath(lhs); + QString rhp = rhd.absoluteFilePath(rhs); + return QFileInfo(lhp).lastModified() < + QFileInfo(rhp).lastModified(); + }); } else { ON_BLOCK_EXIT([&file]() { file.close(); }); From cb2bfaa6ce9d9360bf7ebf4aaaf5fa61dbf9b689 Mon Sep 17 00:00:00 2001 From: Jeremy Rimpo Date: Tue, 12 Dec 2017 00:46:16 -0600 Subject: [PATCH 0397/1544] Use short name as it seems to be accurate for the actual appdata directories --- src/gamegamebryo.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/gamegamebryo.cpp b/src/gamegamebryo.cpp index be5a69d3..c2683f8f 100644 --- a/src/gamegamebryo.cpp +++ b/src/gamegamebryo.cpp @@ -332,7 +332,7 @@ MappingType GameGamebryo::mappings() const for (const QString &profileFile : { "plugins.txt", "loadorder.txt" }) { result.push_back({ m_Organizer->profilePath() + "/" + profileFile, - localAppFolder() + "/" + gameName().replace(" ", "") + "/" + profileFile, + localAppFolder() + "/" + gameShortName() + "/" + profileFile, false }); } From a476c58e7010cdd1f296c135c648fc4faf0ddc96 Mon Sep 17 00:00:00 2001 From: Jeremy Rimpo Date: Tue, 12 Dec 2017 12:41:27 -0600 Subject: [PATCH 0398/1544] Allow getLauncherName to be overridden --- src/gamegamebryo.h | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/src/gamegamebryo.h b/src/gamegamebryo.h index 7f073107..282b7b5e 100644 --- a/src/gamegamebryo.h +++ b/src/gamegamebryo.h @@ -65,6 +65,7 @@ public: // IPluginGame interface //nexusGameID virtual bool looksValid(QDir const &) const override; virtual QString gameVersion() const override; + virtual QString getLauncherName() const override; public: // IPluginFileMapper interface @@ -72,8 +73,6 @@ public: // IPluginFileMapper interface protected: - QString getLauncherName() const; - QFileInfo findInGameFolder(const QString &relativePath) const; QString myGamesPath() const; QString selectedVariant() const; From d9c567506ba7834b47835139d6ec6c8fffb0b18d Mon Sep 17 00:00:00 2001 From: Jeremy Rimpo Date: Tue, 12 Dec 2017 12:42:10 -0600 Subject: [PATCH 0399/1544] [game_fallout3] Correct the launcher name --- src/games/fallout3/src/gamefallout3.cpp | 5 +++++ src/games/fallout3/src/gamefallout3.h | 3 +++ 2 files changed, 8 insertions(+) diff --git a/src/games/fallout3/src/gamefallout3.cpp b/src/games/fallout3/src/gamefallout3.cpp index 9193e99f..8beb700e 100644 --- a/src/games/fallout3/src/gamefallout3.cpp +++ b/src/games/fallout3/src/gamefallout3.cpp @@ -170,3 +170,8 @@ int GameFallout3::nexusGameID() const { return 120; } + +QString GameFallout3::getLauncherName() const +{ + return "FalloutLauncher.exe"; +} \ No newline at end of file diff --git a/src/games/fallout3/src/gamefallout3.h b/src/games/fallout3/src/gamefallout3.h index 2cc6ce80..8283d159 100644 --- a/src/games/fallout3/src/gamefallout3.h +++ b/src/games/fallout3/src/gamefallout3.h @@ -29,6 +29,7 @@ public: // IPluginGame interface virtual QStringList gameVariants() const; virtual QString gameShortName() const override; virtual QString gameNexusName() const override; + virtual QString getLauncherName() const override; virtual QStringList iniFiles() const override; virtual QStringList DLCPlugins() const override; virtual int nexusModOrganizerID() const override; @@ -43,6 +44,8 @@ public: // IPlugin interface virtual bool isActive() const; virtual QList settings() const; +protected: + }; #endif // GAMEFALLOUT3_H From ee2cab9df4a574ccdfd2f81c60b009346e642788 Mon Sep 17 00:00:00 2001 From: Jeremy Rimpo Date: Wed, 13 Dec 2017 03:07:07 -0600 Subject: [PATCH 0400/1544] [game_fallout4vr] Simplify DLC ordering and allow displaying DLC in mod list --- .../fallout4vr/src/fallout4gameplugins.cpp | 91 +++++++++---------- .../fallout4vr/src/fallout4unmanagedmods.cpp | 24 +++++ .../fallout4vr/src/fallout4unmanagedmods.h | 1 + 3 files changed, 67 insertions(+), 49 deletions(-) diff --git a/src/games/fallout4vr/src/fallout4gameplugins.cpp b/src/games/fallout4vr/src/fallout4gameplugins.cpp index e68b7b18..588bbb89 100644 --- a/src/games/fallout4vr/src/fallout4gameplugins.cpp +++ b/src/games/fallout4vr/src/fallout4gameplugins.cpp @@ -8,6 +8,7 @@ #include #include #include +#include using MOBase::IPluginGame; @@ -16,10 +17,6 @@ using MOBase::IOrganizer; using MOBase::SafeWriteFile; using MOBase::reportError; -static const std::set OFFICIAL_FILES{ - "Fallout4.esm", "DLCRobot.esm", "DLCworkshop01.esm", "DLCCoast.esm", - "DLCworkshop02.esm", "DLCworkshop03.esm", "DLCNukaWorld.esm"}; - Fallout4GamePlugins::Fallout4GamePlugins(IOrganizer *organizer) : GamebryoGamePlugins(organizer) { @@ -46,30 +43,26 @@ void Fallout4GamePlugins::writePluginList(const IPluginList *pluginList, }); QStringList PrimaryPlugins = organizer()->managedGame()->primaryPlugins(); - - for (auto f : OFFICIAL_FILES) { - if (!PrimaryPlugins.contains(f, Qt::CaseInsensitive)) { - PrimaryPlugins.append(f); - } - } + QSet ManagedMods = PrimaryPlugins.toSet().subtract(organizer()->managedGame()->DLCPlugins().toSet()); + PrimaryPlugins.append(ManagedMods.toList()); //TODO: do not write plugins in OFFICIAL_FILES container for (const QString &pluginName : plugins) { if (!PrimaryPlugins.contains(pluginName,Qt::CaseInsensitive)) { - if (pluginList->state(pluginName) == IPluginList::STATE_ACTIVE) { - if (!textCodec->canEncode(pluginName)) { - invalidFileNames = true; - qCritical("invalid plugin name %s", qPrintable(pluginName)); - } - else - { - file->write("*"); - file->write(textCodec->fromUnicode(pluginName)); - - } - file->write("\r\n"); - ++writtenCount; + if (pluginList->state(pluginName) == IPluginList::STATE_ACTIVE) { + if (!textCodec->canEncode(pluginName)) { + invalidFileNames = true; + qCritical("invalid plugin name %s", qPrintable(pluginName)); } + else + { + file->write("*"); + file->write(textCodec->fromUnicode(pluginName)); + + } + file->write("\r\n"); + ++writtenCount; + } else { if (!textCodec->canEncode(pluginName)) { @@ -103,18 +96,12 @@ bool Fallout4GamePlugins::readPluginList(MOBase::IPluginList *pluginList, bool useLoadOrder) { QStringList plugins = pluginList->pluginNames(); - QStringList loadOrder = organizer()->managedGame()->primaryPlugins(); - - for (auto f : OFFICIAL_FILES) { - if (!loadOrder.contains(f, Qt::CaseInsensitive)) { - loadOrder.append(f); - } - } + QStringList primaryPlugins = organizer()->managedGame()->primaryPlugins(); + QStringList loadOrder(primaryPlugins); for (const QString &pluginName : loadOrder) { if (pluginList->state(pluginName) != IPluginList::STATE_MISSING) { pluginList->setState(pluginName, IPluginList::STATE_ACTIVE); - plugins.removeAll(pluginName); } } @@ -138,27 +125,33 @@ bool Fallout4GamePlugins::readPluginList(MOBase::IPluginList *pluginList, if ((line.size() > 0) && (line.at(0) != '#')) { pluginName = localCodec()->toUnicode(line.trimmed().constData()); } - if (pluginName.startsWith('*')) { - pluginName.remove(0, 1); - if (pluginName.size() > 0) { - pluginList->setState(pluginName, IPluginList::STATE_ACTIVE); - plugins.removeAll(pluginName); - if (!loadOrder.contains(pluginName, Qt::CaseInsensitive)) { - loadOrder.append(pluginName); - } - } - } - else - { - if (pluginName.size() > 0) { - pluginList->setState(pluginName, IPluginList::STATE_INACTIVE); - plugins.removeAll(pluginName); - if (!loadOrder.contains(pluginName, Qt::CaseInsensitive)) { - loadOrder.append(pluginName); + if (!primaryPlugins.contains(pluginName, Qt::CaseInsensitive)) { + if (pluginName.startsWith('*')) { + pluginName.remove(0, 1); + if (pluginName.size() > 0) { + pluginList->setState(pluginName, IPluginList::STATE_ACTIVE); + plugins.removeAll(pluginName); + if (!loadOrder.contains(pluginName, Qt::CaseInsensitive)) { + loadOrder.append(pluginName); + } + } + } + else + { + if (pluginName.size() > 0) { + pluginList->setState(pluginName, IPluginList::STATE_INACTIVE); + plugins.removeAll(pluginName); + if (!loadOrder.contains(pluginName, Qt::CaseInsensitive)) { + loadOrder.append(pluginName); + } } } } - + else + { + pluginName.remove(0, 1); + plugins.removeAll(pluginName); + } } file.close(); diff --git a/src/games/fallout4vr/src/fallout4unmanagedmods.cpp b/src/games/fallout4vr/src/fallout4unmanagedmods.cpp index 3bb279fe..5007c4f7 100644 --- a/src/games/fallout4vr/src/fallout4unmanagedmods.cpp +++ b/src/games/fallout4vr/src/fallout4unmanagedmods.cpp @@ -8,6 +8,28 @@ Fallout4UnmangedMods::Fallout4UnmangedMods(const GameGamebryo *game) Fallout4UnmangedMods::~Fallout4UnmangedMods() {} +QStringList Fallout4UnmangedMods::mods(bool onlyOfficial) const { + QStringList result; + + QStringList pluginList = game()->primaryPlugins(); + QStringList otherPlugins = game()->DLCPlugins(); + otherPlugins.append(game()->CCPlugins()); + for (QString plugin : otherPlugins) { + pluginList.removeAll(plugin); + } + QDir dataDir(game()->dataDirectory()); + for (const QString &fileName : dataDir.entryList({ "*.esp", "*.esl", "*.esm" })) { + if (!pluginList.contains(fileName, Qt::CaseInsensitive)) { + if (!onlyOfficial || pluginList.contains(fileName, Qt::CaseInsensitive)) { + QFileInfo file(fileName); + result.append(file.baseName()); + } + } + } + + return result; +} + QStringList Fallout4UnmangedMods::secondaryFiles(const QString &modName) const { // file extension in FO4 is .ba2 instead of bsa QStringList archives; @@ -34,6 +56,8 @@ QString Fallout4UnmangedMods::displayName(const QString &modName) const return "Vault-Tec Workshop"; } else if (modName.compare("dlcnukaworld", Qt::CaseInsensitive) == 0) { return "Nuka-World"; + } else if (modName.compare("dlcultrahighresolution", Qt::CaseInsensitive) == 0) { + return "Ultra High Resolution Texture Pack"; } else { return modName; } diff --git a/src/games/fallout4vr/src/fallout4unmanagedmods.h b/src/games/fallout4vr/src/fallout4unmanagedmods.h index 92149c73..aaa97e56 100644 --- a/src/games/fallout4vr/src/fallout4unmanagedmods.h +++ b/src/games/fallout4vr/src/fallout4unmanagedmods.h @@ -11,6 +11,7 @@ public: Fallout4UnmangedMods(const GameGamebryo *game); ~Fallout4UnmangedMods(); + virtual QStringList mods(bool onlyOfficial) const override; virtual QStringList secondaryFiles(const QString &modName) const override; virtual QString displayName(const QString &modName) const override; }; From 27359edb09ba7266f54dbef86d9946694f2a06bb Mon Sep 17 00:00:00 2001 From: Jeremy Rimpo Date: Wed, 13 Dec 2017 03:07:07 -0600 Subject: [PATCH 0401/1544] [game_fallout76] Simplify DLC ordering and allow displaying DLC in mod list --- .../fallout76/src/fallout4gameplugins.cpp | 91 +++++++++---------- .../fallout76/src/fallout4unmanagedmods.cpp | 24 +++++ .../fallout76/src/fallout4unmanagedmods.h | 1 + 3 files changed, 67 insertions(+), 49 deletions(-) diff --git a/src/games/fallout76/src/fallout4gameplugins.cpp b/src/games/fallout76/src/fallout4gameplugins.cpp index e68b7b18..588bbb89 100644 --- a/src/games/fallout76/src/fallout4gameplugins.cpp +++ b/src/games/fallout76/src/fallout4gameplugins.cpp @@ -8,6 +8,7 @@ #include #include #include +#include using MOBase::IPluginGame; @@ -16,10 +17,6 @@ using MOBase::IOrganizer; using MOBase::SafeWriteFile; using MOBase::reportError; -static const std::set OFFICIAL_FILES{ - "Fallout4.esm", "DLCRobot.esm", "DLCworkshop01.esm", "DLCCoast.esm", - "DLCworkshop02.esm", "DLCworkshop03.esm", "DLCNukaWorld.esm"}; - Fallout4GamePlugins::Fallout4GamePlugins(IOrganizer *organizer) : GamebryoGamePlugins(organizer) { @@ -46,30 +43,26 @@ void Fallout4GamePlugins::writePluginList(const IPluginList *pluginList, }); QStringList PrimaryPlugins = organizer()->managedGame()->primaryPlugins(); - - for (auto f : OFFICIAL_FILES) { - if (!PrimaryPlugins.contains(f, Qt::CaseInsensitive)) { - PrimaryPlugins.append(f); - } - } + QSet ManagedMods = PrimaryPlugins.toSet().subtract(organizer()->managedGame()->DLCPlugins().toSet()); + PrimaryPlugins.append(ManagedMods.toList()); //TODO: do not write plugins in OFFICIAL_FILES container for (const QString &pluginName : plugins) { if (!PrimaryPlugins.contains(pluginName,Qt::CaseInsensitive)) { - if (pluginList->state(pluginName) == IPluginList::STATE_ACTIVE) { - if (!textCodec->canEncode(pluginName)) { - invalidFileNames = true; - qCritical("invalid plugin name %s", qPrintable(pluginName)); - } - else - { - file->write("*"); - file->write(textCodec->fromUnicode(pluginName)); - - } - file->write("\r\n"); - ++writtenCount; + if (pluginList->state(pluginName) == IPluginList::STATE_ACTIVE) { + if (!textCodec->canEncode(pluginName)) { + invalidFileNames = true; + qCritical("invalid plugin name %s", qPrintable(pluginName)); } + else + { + file->write("*"); + file->write(textCodec->fromUnicode(pluginName)); + + } + file->write("\r\n"); + ++writtenCount; + } else { if (!textCodec->canEncode(pluginName)) { @@ -103,18 +96,12 @@ bool Fallout4GamePlugins::readPluginList(MOBase::IPluginList *pluginList, bool useLoadOrder) { QStringList plugins = pluginList->pluginNames(); - QStringList loadOrder = organizer()->managedGame()->primaryPlugins(); - - for (auto f : OFFICIAL_FILES) { - if (!loadOrder.contains(f, Qt::CaseInsensitive)) { - loadOrder.append(f); - } - } + QStringList primaryPlugins = organizer()->managedGame()->primaryPlugins(); + QStringList loadOrder(primaryPlugins); for (const QString &pluginName : loadOrder) { if (pluginList->state(pluginName) != IPluginList::STATE_MISSING) { pluginList->setState(pluginName, IPluginList::STATE_ACTIVE); - plugins.removeAll(pluginName); } } @@ -138,27 +125,33 @@ bool Fallout4GamePlugins::readPluginList(MOBase::IPluginList *pluginList, if ((line.size() > 0) && (line.at(0) != '#')) { pluginName = localCodec()->toUnicode(line.trimmed().constData()); } - if (pluginName.startsWith('*')) { - pluginName.remove(0, 1); - if (pluginName.size() > 0) { - pluginList->setState(pluginName, IPluginList::STATE_ACTIVE); - plugins.removeAll(pluginName); - if (!loadOrder.contains(pluginName, Qt::CaseInsensitive)) { - loadOrder.append(pluginName); - } - } - } - else - { - if (pluginName.size() > 0) { - pluginList->setState(pluginName, IPluginList::STATE_INACTIVE); - plugins.removeAll(pluginName); - if (!loadOrder.contains(pluginName, Qt::CaseInsensitive)) { - loadOrder.append(pluginName); + if (!primaryPlugins.contains(pluginName, Qt::CaseInsensitive)) { + if (pluginName.startsWith('*')) { + pluginName.remove(0, 1); + if (pluginName.size() > 0) { + pluginList->setState(pluginName, IPluginList::STATE_ACTIVE); + plugins.removeAll(pluginName); + if (!loadOrder.contains(pluginName, Qt::CaseInsensitive)) { + loadOrder.append(pluginName); + } + } + } + else + { + if (pluginName.size() > 0) { + pluginList->setState(pluginName, IPluginList::STATE_INACTIVE); + plugins.removeAll(pluginName); + if (!loadOrder.contains(pluginName, Qt::CaseInsensitive)) { + loadOrder.append(pluginName); + } } } } - + else + { + pluginName.remove(0, 1); + plugins.removeAll(pluginName); + } } file.close(); diff --git a/src/games/fallout76/src/fallout4unmanagedmods.cpp b/src/games/fallout76/src/fallout4unmanagedmods.cpp index 3bb279fe..5007c4f7 100644 --- a/src/games/fallout76/src/fallout4unmanagedmods.cpp +++ b/src/games/fallout76/src/fallout4unmanagedmods.cpp @@ -8,6 +8,28 @@ Fallout4UnmangedMods::Fallout4UnmangedMods(const GameGamebryo *game) Fallout4UnmangedMods::~Fallout4UnmangedMods() {} +QStringList Fallout4UnmangedMods::mods(bool onlyOfficial) const { + QStringList result; + + QStringList pluginList = game()->primaryPlugins(); + QStringList otherPlugins = game()->DLCPlugins(); + otherPlugins.append(game()->CCPlugins()); + for (QString plugin : otherPlugins) { + pluginList.removeAll(plugin); + } + QDir dataDir(game()->dataDirectory()); + for (const QString &fileName : dataDir.entryList({ "*.esp", "*.esl", "*.esm" })) { + if (!pluginList.contains(fileName, Qt::CaseInsensitive)) { + if (!onlyOfficial || pluginList.contains(fileName, Qt::CaseInsensitive)) { + QFileInfo file(fileName); + result.append(file.baseName()); + } + } + } + + return result; +} + QStringList Fallout4UnmangedMods::secondaryFiles(const QString &modName) const { // file extension in FO4 is .ba2 instead of bsa QStringList archives; @@ -34,6 +56,8 @@ QString Fallout4UnmangedMods::displayName(const QString &modName) const return "Vault-Tec Workshop"; } else if (modName.compare("dlcnukaworld", Qt::CaseInsensitive) == 0) { return "Nuka-World"; + } else if (modName.compare("dlcultrahighresolution", Qt::CaseInsensitive) == 0) { + return "Ultra High Resolution Texture Pack"; } else { return modName; } diff --git a/src/games/fallout76/src/fallout4unmanagedmods.h b/src/games/fallout76/src/fallout4unmanagedmods.h index 92149c73..aaa97e56 100644 --- a/src/games/fallout76/src/fallout4unmanagedmods.h +++ b/src/games/fallout76/src/fallout4unmanagedmods.h @@ -11,6 +11,7 @@ public: Fallout4UnmangedMods(const GameGamebryo *game); ~Fallout4UnmangedMods(); + virtual QStringList mods(bool onlyOfficial) const override; virtual QStringList secondaryFiles(const QString &modName) const override; virtual QString displayName(const QString &modName) const override; }; From 6a4a56d9738262d0b287a60354042789e7b9e5c8 Mon Sep 17 00:00:00 2001 From: Jeremy Rimpo Date: Wed, 13 Dec 2017 03:07:07 -0600 Subject: [PATCH 0402/1544] [game_fallout4] Simplify DLC ordering and allow displaying DLC in mod list --- .../fallout4/src/fallout4gameplugins.cpp | 91 +++++++++---------- .../fallout4/src/fallout4unmanagedmods.cpp | 24 +++++ .../fallout4/src/fallout4unmanagedmods.h | 1 + 3 files changed, 67 insertions(+), 49 deletions(-) diff --git a/src/games/fallout4/src/fallout4gameplugins.cpp b/src/games/fallout4/src/fallout4gameplugins.cpp index e68b7b18..588bbb89 100644 --- a/src/games/fallout4/src/fallout4gameplugins.cpp +++ b/src/games/fallout4/src/fallout4gameplugins.cpp @@ -8,6 +8,7 @@ #include #include #include +#include using MOBase::IPluginGame; @@ -16,10 +17,6 @@ using MOBase::IOrganizer; using MOBase::SafeWriteFile; using MOBase::reportError; -static const std::set OFFICIAL_FILES{ - "Fallout4.esm", "DLCRobot.esm", "DLCworkshop01.esm", "DLCCoast.esm", - "DLCworkshop02.esm", "DLCworkshop03.esm", "DLCNukaWorld.esm"}; - Fallout4GamePlugins::Fallout4GamePlugins(IOrganizer *organizer) : GamebryoGamePlugins(organizer) { @@ -46,30 +43,26 @@ void Fallout4GamePlugins::writePluginList(const IPluginList *pluginList, }); QStringList PrimaryPlugins = organizer()->managedGame()->primaryPlugins(); - - for (auto f : OFFICIAL_FILES) { - if (!PrimaryPlugins.contains(f, Qt::CaseInsensitive)) { - PrimaryPlugins.append(f); - } - } + QSet ManagedMods = PrimaryPlugins.toSet().subtract(organizer()->managedGame()->DLCPlugins().toSet()); + PrimaryPlugins.append(ManagedMods.toList()); //TODO: do not write plugins in OFFICIAL_FILES container for (const QString &pluginName : plugins) { if (!PrimaryPlugins.contains(pluginName,Qt::CaseInsensitive)) { - if (pluginList->state(pluginName) == IPluginList::STATE_ACTIVE) { - if (!textCodec->canEncode(pluginName)) { - invalidFileNames = true; - qCritical("invalid plugin name %s", qPrintable(pluginName)); - } - else - { - file->write("*"); - file->write(textCodec->fromUnicode(pluginName)); - - } - file->write("\r\n"); - ++writtenCount; + if (pluginList->state(pluginName) == IPluginList::STATE_ACTIVE) { + if (!textCodec->canEncode(pluginName)) { + invalidFileNames = true; + qCritical("invalid plugin name %s", qPrintable(pluginName)); } + else + { + file->write("*"); + file->write(textCodec->fromUnicode(pluginName)); + + } + file->write("\r\n"); + ++writtenCount; + } else { if (!textCodec->canEncode(pluginName)) { @@ -103,18 +96,12 @@ bool Fallout4GamePlugins::readPluginList(MOBase::IPluginList *pluginList, bool useLoadOrder) { QStringList plugins = pluginList->pluginNames(); - QStringList loadOrder = organizer()->managedGame()->primaryPlugins(); - - for (auto f : OFFICIAL_FILES) { - if (!loadOrder.contains(f, Qt::CaseInsensitive)) { - loadOrder.append(f); - } - } + QStringList primaryPlugins = organizer()->managedGame()->primaryPlugins(); + QStringList loadOrder(primaryPlugins); for (const QString &pluginName : loadOrder) { if (pluginList->state(pluginName) != IPluginList::STATE_MISSING) { pluginList->setState(pluginName, IPluginList::STATE_ACTIVE); - plugins.removeAll(pluginName); } } @@ -138,27 +125,33 @@ bool Fallout4GamePlugins::readPluginList(MOBase::IPluginList *pluginList, if ((line.size() > 0) && (line.at(0) != '#')) { pluginName = localCodec()->toUnicode(line.trimmed().constData()); } - if (pluginName.startsWith('*')) { - pluginName.remove(0, 1); - if (pluginName.size() > 0) { - pluginList->setState(pluginName, IPluginList::STATE_ACTIVE); - plugins.removeAll(pluginName); - if (!loadOrder.contains(pluginName, Qt::CaseInsensitive)) { - loadOrder.append(pluginName); - } - } - } - else - { - if (pluginName.size() > 0) { - pluginList->setState(pluginName, IPluginList::STATE_INACTIVE); - plugins.removeAll(pluginName); - if (!loadOrder.contains(pluginName, Qt::CaseInsensitive)) { - loadOrder.append(pluginName); + if (!primaryPlugins.contains(pluginName, Qt::CaseInsensitive)) { + if (pluginName.startsWith('*')) { + pluginName.remove(0, 1); + if (pluginName.size() > 0) { + pluginList->setState(pluginName, IPluginList::STATE_ACTIVE); + plugins.removeAll(pluginName); + if (!loadOrder.contains(pluginName, Qt::CaseInsensitive)) { + loadOrder.append(pluginName); + } + } + } + else + { + if (pluginName.size() > 0) { + pluginList->setState(pluginName, IPluginList::STATE_INACTIVE); + plugins.removeAll(pluginName); + if (!loadOrder.contains(pluginName, Qt::CaseInsensitive)) { + loadOrder.append(pluginName); + } } } } - + else + { + pluginName.remove(0, 1); + plugins.removeAll(pluginName); + } } file.close(); diff --git a/src/games/fallout4/src/fallout4unmanagedmods.cpp b/src/games/fallout4/src/fallout4unmanagedmods.cpp index 3bb279fe..5007c4f7 100644 --- a/src/games/fallout4/src/fallout4unmanagedmods.cpp +++ b/src/games/fallout4/src/fallout4unmanagedmods.cpp @@ -8,6 +8,28 @@ Fallout4UnmangedMods::Fallout4UnmangedMods(const GameGamebryo *game) Fallout4UnmangedMods::~Fallout4UnmangedMods() {} +QStringList Fallout4UnmangedMods::mods(bool onlyOfficial) const { + QStringList result; + + QStringList pluginList = game()->primaryPlugins(); + QStringList otherPlugins = game()->DLCPlugins(); + otherPlugins.append(game()->CCPlugins()); + for (QString plugin : otherPlugins) { + pluginList.removeAll(plugin); + } + QDir dataDir(game()->dataDirectory()); + for (const QString &fileName : dataDir.entryList({ "*.esp", "*.esl", "*.esm" })) { + if (!pluginList.contains(fileName, Qt::CaseInsensitive)) { + if (!onlyOfficial || pluginList.contains(fileName, Qt::CaseInsensitive)) { + QFileInfo file(fileName); + result.append(file.baseName()); + } + } + } + + return result; +} + QStringList Fallout4UnmangedMods::secondaryFiles(const QString &modName) const { // file extension in FO4 is .ba2 instead of bsa QStringList archives; @@ -34,6 +56,8 @@ QString Fallout4UnmangedMods::displayName(const QString &modName) const return "Vault-Tec Workshop"; } else if (modName.compare("dlcnukaworld", Qt::CaseInsensitive) == 0) { return "Nuka-World"; + } else if (modName.compare("dlcultrahighresolution", Qt::CaseInsensitive) == 0) { + return "Ultra High Resolution Texture Pack"; } else { return modName; } diff --git a/src/games/fallout4/src/fallout4unmanagedmods.h b/src/games/fallout4/src/fallout4unmanagedmods.h index 92149c73..aaa97e56 100644 --- a/src/games/fallout4/src/fallout4unmanagedmods.h +++ b/src/games/fallout4/src/fallout4unmanagedmods.h @@ -11,6 +11,7 @@ public: Fallout4UnmangedMods(const GameGamebryo *game); ~Fallout4UnmangedMods(); + virtual QStringList mods(bool onlyOfficial) const override; virtual QStringList secondaryFiles(const QString &modName) const override; virtual QString displayName(const QString &modName) const override; }; From 25b0cecd3ef6d79bd3857a435cd94e4b6328a09f Mon Sep 17 00:00:00 2001 From: Jeremy Rimpo Date: Wed, 13 Dec 2017 03:07:08 -0600 Subject: [PATCH 0403/1544] [game_skyrimse] Simplify DLC ordering and allow displaying DLC in mod list --- .../skyrimse/src/skyrimsegameplugins.cpp | 11 +++--- .../skyrimse/src/skyrimseunmanagedmods.cpp | 36 +++++++++---------- .../skyrimse/src/skyrimseunmanagedmods.h | 3 +- 3 files changed, 22 insertions(+), 28 deletions(-) diff --git a/src/games/skyrimse/src/skyrimsegameplugins.cpp b/src/games/skyrimse/src/skyrimsegameplugins.cpp index a3829866..ec77487a 100644 --- a/src/games/skyrimse/src/skyrimsegameplugins.cpp +++ b/src/games/skyrimse/src/skyrimsegameplugins.cpp @@ -16,9 +16,6 @@ using MOBase::IOrganizer; using MOBase::SafeWriteFile; using MOBase::reportError; -//static const std::set OFFICIAL_FILES{ -// "skyrim.esm", "update.esm", "Dawnguard.esm", "HearthFires.esm", "Dragonborn.esm"}; - SkyrimSEGamePlugins::SkyrimSEGamePlugins(IOrganizer *organizer) : GamebryoGamePlugins(organizer) { @@ -156,10 +153,10 @@ bool SkyrimSEGamePlugins::readPluginList(MOBase::IPluginList *pluginList, file.close(); - // we removed each plugin found in the file, so what's left are inactive mods - //for (const QString &pluginName : plugins) { - // pluginList->setState(pluginName, IPluginList::STATE_INACTIVE); - //} + // we removed each plugin found in the file, so what's left are inactive mods + for (const QString &pluginName : plugins) { + pluginList->setState(pluginName, IPluginList::STATE_INACTIVE); + } if (useLoadOrder) { pluginList->setLoadOrder(loadOrder); diff --git a/src/games/skyrimse/src/skyrimseunmanagedmods.cpp b/src/games/skyrimse/src/skyrimseunmanagedmods.cpp index be6d4b72..14fd3e43 100644 --- a/src/games/skyrimse/src/skyrimseunmanagedmods.cpp +++ b/src/games/skyrimse/src/skyrimseunmanagedmods.cpp @@ -8,27 +8,25 @@ SkyrimSEUnmangedMods::SkyrimSEUnmangedMods(const GameGamebryo *game) SkyrimSEUnmangedMods::~SkyrimSEUnmangedMods() {} +QStringList SkyrimSEUnmangedMods::mods(bool onlyOfficial) const { + QStringList result; -//not necessary TODO: Remove -QStringList SkyrimSEUnmangedMods::secondaryFiles(const QString &modName) const { - QStringList archives; - QDir dataDir = game()->dataDirectory(); - for (const QString &archiveName : dataDir.entryList({modName + "*.bsa"})) { - archives.append(dataDir.absoluteFilePath(archiveName)); + QStringList pluginList = game()->primaryPlugins(); + QStringList otherPlugins = game()->DLCPlugins(); + otherPlugins.append(game()->CCPlugins()); + for (QString plugin : otherPlugins) { + pluginList.removeAll(plugin); } - return archives; -} -// not necessary TOOD: remove -QString SkyrimSEUnmangedMods::displayName(const QString &modName) const -{ - if (modName.compare("hearthfires", Qt::CaseInsensitive) == 0) - { - return "Hearthfire"; - } - else - { - return modName; + QDir dataDir(game()->dataDirectory()); + for (const QString &fileName : dataDir.entryList({ "*.esp", "*.esl", "*.esm" })) { + if (!pluginList.contains(fileName, Qt::CaseInsensitive)) { + if (!onlyOfficial || pluginList.contains(fileName, Qt::CaseInsensitive)) { + QFileInfo file(fileName); + result.append(file.baseName()); + } + } } - + + return result; } diff --git a/src/games/skyrimse/src/skyrimseunmanagedmods.h b/src/games/skyrimse/src/skyrimseunmanagedmods.h index a39f6c87..c9be0379 100644 --- a/src/games/skyrimse/src/skyrimseunmanagedmods.h +++ b/src/games/skyrimse/src/skyrimseunmanagedmods.h @@ -11,8 +11,7 @@ public: SkyrimSEUnmangedMods(const GameGamebryo *game); ~SkyrimSEUnmangedMods(); - virtual QStringList secondaryFiles(const QString &modName) const override; - virtual QString displayName(const QString &modName) const override; + virtual QStringList mods(bool onlyOfficial) const override; }; From ca7fab73141615237c154bb45e557b025f8a9c6f Mon Sep 17 00:00:00 2001 From: Jeremy Rimpo Date: Wed, 13 Dec 2017 03:07:54 -0600 Subject: [PATCH 0404/1544] [game_fallout4vr] Ultra High Resolution can be disabled --- src/games/fallout4vr/src/gamefallout4.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/games/fallout4vr/src/gamefallout4.cpp b/src/games/fallout4vr/src/gamefallout4.cpp index 6257fbf8..c0ec9a73 100644 --- a/src/games/fallout4vr/src/gamefallout4.cpp +++ b/src/games/fallout4vr/src/gamefallout4.cpp @@ -134,7 +134,7 @@ QString GameFallout4::steamAPPId() const QStringList GameFallout4::primaryPlugins() const { QStringList plugins = {"fallout4.esm", "dlcrobot.esm", "dlcworkshop01.esm", "dlccoast.esm", "dlcworkshop02.esm", - "dlcworkshop03.esm", "dlcnukaworld.esm", "dlcultrahighresolution.esm"}; + "dlcworkshop03.esm", "dlcnukaworld.esm"}; plugins.append(CCPlugins()); From 8d66552fb08ed3ef551c0ddbec17e745e8547731 Mon Sep 17 00:00:00 2001 From: Jeremy Rimpo Date: Wed, 13 Dec 2017 03:07:54 -0600 Subject: [PATCH 0405/1544] [game_fallout76] Ultra High Resolution can be disabled --- src/games/fallout76/src/gamefallout4.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/games/fallout76/src/gamefallout4.cpp b/src/games/fallout76/src/gamefallout4.cpp index 6257fbf8..c0ec9a73 100644 --- a/src/games/fallout76/src/gamefallout4.cpp +++ b/src/games/fallout76/src/gamefallout4.cpp @@ -134,7 +134,7 @@ QString GameFallout4::steamAPPId() const QStringList GameFallout4::primaryPlugins() const { QStringList plugins = {"fallout4.esm", "dlcrobot.esm", "dlcworkshop01.esm", "dlccoast.esm", "dlcworkshop02.esm", - "dlcworkshop03.esm", "dlcnukaworld.esm", "dlcultrahighresolution.esm"}; + "dlcworkshop03.esm", "dlcnukaworld.esm"}; plugins.append(CCPlugins()); From 3403034646d0d6985c611035976bfbf1633d8f2f Mon Sep 17 00:00:00 2001 From: Jeremy Rimpo Date: Wed, 13 Dec 2017 03:07:54 -0600 Subject: [PATCH 0406/1544] [game_fallout4] Ultra High Resolution can be disabled --- src/games/fallout4/src/gamefallout4.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/games/fallout4/src/gamefallout4.cpp b/src/games/fallout4/src/gamefallout4.cpp index 6257fbf8..c0ec9a73 100644 --- a/src/games/fallout4/src/gamefallout4.cpp +++ b/src/games/fallout4/src/gamefallout4.cpp @@ -134,7 +134,7 @@ QString GameFallout4::steamAPPId() const QStringList GameFallout4::primaryPlugins() const { QStringList plugins = {"fallout4.esm", "dlcrobot.esm", "dlcworkshop01.esm", "dlccoast.esm", "dlcworkshop02.esm", - "dlcworkshop03.esm", "dlcnukaworld.esm", "dlcultrahighresolution.esm"}; + "dlcworkshop03.esm", "dlcnukaworld.esm"}; plugins.append(CCPlugins()); From 9cdc15a9c68c6582b74af62a6281eb4e6ef668ab Mon Sep 17 00:00:00 2001 From: Jeremy Rimpo Date: Wed, 13 Dec 2017 12:30:28 -0600 Subject: [PATCH 0407/1544] [game_falloutnv] Fix profile problems with archive invalidation --- src/games/falloutnv/src/falloutnvdataarchives.cpp | 10 ++++++---- src/games/falloutnv/src/falloutnvdataarchives.h | 5 +++-- src/games/falloutnv/src/gamefalloutnv.cpp | 2 +- 3 files changed, 10 insertions(+), 7 deletions(-) diff --git a/src/games/falloutnv/src/falloutnvdataarchives.cpp b/src/games/falloutnv/src/falloutnvdataarchives.cpp index 237a15f6..8179b505 100644 --- a/src/games/falloutnv/src/falloutnvdataarchives.cpp +++ b/src/games/falloutnv/src/falloutnvdataarchives.cpp @@ -1,7 +1,10 @@ #include "falloutnvdataarchives.h" #include -#include +FalloutNVDataArchives::FalloutNVDataArchives(const QDir &myGamesDir) : + GamebryoDataArchives(myGamesDir) +{ +} QStringList FalloutNVDataArchives::vanillaArchives() const { @@ -13,12 +16,11 @@ QStringList FalloutNVDataArchives::vanillaArchives() const , "Fallout - Misc.bsa" }; } - QStringList FalloutNVDataArchives::archives(const MOBase::IProfile *profile) const { QStringList result; - QString iniFile = QDir(profile->absolutePath()).absoluteFilePath("falloutnv.ini"); + QString iniFile = profile->localSettingsEnabled() ? QDir(profile->absolutePath()).absoluteFilePath("fallout.ini") : m_LocalGameDir.absoluteFilePath("fallout.ini"); result.append(getArchivesFromKey(iniFile, "SArchiveList")); return result; @@ -28,6 +30,6 @@ void FalloutNVDataArchives::writeArchiveList(MOBase::IProfile *profile, const QS { QString list = before.join(", "); - QString iniFile = QDir(profile->absolutePath()).absoluteFilePath("falloutnv.ini"); + QString iniFile = profile->localSettingsEnabled() ? QDir(profile->absolutePath()).absoluteFilePath("fallout.ini") : m_LocalGameDir.absoluteFilePath("fallout.ini"); setArchivesToKey(iniFile, "SArchiveList", list); } diff --git a/src/games/falloutnv/src/falloutnvdataarchives.h b/src/games/falloutnv/src/falloutnvdataarchives.h index 931d3120..995e7275 100644 --- a/src/games/falloutnv/src/falloutnvdataarchives.h +++ b/src/games/falloutnv/src/falloutnvdataarchives.h @@ -6,17 +6,18 @@ #include #include #include +#include class FalloutNVDataArchives : public GamebryoDataArchives { +public: + FalloutNVDataArchives(const QDir &myGamesDir); public: - 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; }; diff --git a/src/games/falloutnv/src/gamefalloutnv.cpp b/src/games/falloutnv/src/gamefalloutnv.cpp index 7deca029..277b13dc 100644 --- a/src/games/falloutnv/src/gamefalloutnv.cpp +++ b/src/games/falloutnv/src/gamefalloutnv.cpp @@ -34,7 +34,7 @@ bool GameFalloutNV::init(IOrganizer *moInfo) return false; } registerFeature(new FalloutNVScriptExtender(this)); - registerFeature(new FalloutNVDataArchives()); + registerFeature(new FalloutNVDataArchives(myGamesPath())); registerFeature(new FalloutNVBSAInvalidation(feature(), this)); registerFeature(new FalloutNVSaveGameInfo(this)); registerFeature(new GamebryoLocalSavegames(myGamesPath(), "fallout.ini")); From 619e68bc52d70cfc22b5e1bb470dc185467dc304 Mon Sep 17 00:00:00 2001 From: Jeremy Rimpo Date: Wed, 13 Dec 2017 12:30:28 -0600 Subject: [PATCH 0408/1544] [game_oblivion] Fix profile problems with archive invalidation --- src/games/oblivion/src/gameoblivion.cpp | 2 +- src/games/oblivion/src/obliviondataarchives.cpp | 10 ++++++---- src/games/oblivion/src/obliviondataarchives.h | 4 ++++ 3 files changed, 11 insertions(+), 5 deletions(-) diff --git a/src/games/oblivion/src/gameoblivion.cpp b/src/games/oblivion/src/gameoblivion.cpp index cf4c1763..017f813f 100644 --- a/src/games/oblivion/src/gameoblivion.cpp +++ b/src/games/oblivion/src/gameoblivion.cpp @@ -29,7 +29,7 @@ bool GameOblivion::init(IOrganizer *moInfo) return false; } registerFeature(new OblivionScriptExtender(this)); - registerFeature(new OblivionDataArchives()); + registerFeature(new OblivionDataArchives(myGamesPath())); registerFeature(new OblivionBSAInvalidation(feature(), this)); registerFeature(new OblivionSaveGameInfo(this)); registerFeature(new GamebryoLocalSavegames(myGamesPath(), "oblivion.ini")); diff --git a/src/games/oblivion/src/obliviondataarchives.cpp b/src/games/oblivion/src/obliviondataarchives.cpp index db55642b..e94dbdc5 100644 --- a/src/games/oblivion/src/obliviondataarchives.cpp +++ b/src/games/oblivion/src/obliviondataarchives.cpp @@ -1,7 +1,10 @@ #include "obliviondataarchives.h" #include -#include +OblivionDataArchives::OblivionDataArchives(const QDir &myGamesDir) : + GamebryoDataArchives(myGamesDir) +{ +} QStringList OblivionDataArchives::vanillaArchives() const { @@ -14,12 +17,11 @@ QStringList OblivionDataArchives::vanillaArchives() const }; } - QStringList OblivionDataArchives::archives(const MOBase::IProfile *profile) const { QStringList result; - QString iniFile = QDir(profile->absolutePath()).absoluteFilePath("oblivion.ini"); + QString iniFile = profile->localSettingsEnabled() ? QDir(profile->absolutePath()).absoluteFilePath("oblivion.ini") : m_LocalGameDir.absoluteFilePath("oblivion.ini"); result.append(getArchivesFromKey(iniFile, "SResourceArchiveList")); result.append(getArchivesFromKey(iniFile, "SResourceArchiveList2")); @@ -30,7 +32,7 @@ void OblivionDataArchives::writeArchiveList(MOBase::IProfile *profile, const QSt { QString list = before.join(", "); - QString iniFile = QDir(profile->absolutePath()).absoluteFilePath("oblivion.ini"); + QString iniFile = profile->localSettingsEnabled() ? QDir(profile->absolutePath()).absoluteFilePath("oblivion.ini") : m_LocalGameDir.absoluteFilePath("oblivion.ini"); if (list.length() > 255) { int splitIdx = list.lastIndexOf(",", 256); setArchivesToKey(iniFile, "SResourceArchiveList", list.mid(0, splitIdx)); diff --git a/src/games/oblivion/src/obliviondataarchives.h b/src/games/oblivion/src/obliviondataarchives.h index c2703f8c..c266831f 100644 --- a/src/games/oblivion/src/obliviondataarchives.h +++ b/src/games/oblivion/src/obliviondataarchives.h @@ -6,10 +6,14 @@ #include #include #include +#include class OblivionDataArchives : public GamebryoDataArchives { +public: + OblivionDataArchives(const QDir &myGamesDir); + public: virtual QStringList vanillaArchives() const override; From 525ea276e007444f942be6543e5ec4b906e009e5 Mon Sep 17 00:00:00 2001 From: Jeremy Rimpo Date: Wed, 13 Dec 2017 12:30:29 -0600 Subject: [PATCH 0409/1544] Fix profile problems with archive invalidation --- src/gamebryobsainvalidation.cpp | 2 +- src/gamebryodataarchives.cpp | 5 ++++- src/gamebryodataarchives.h | 3 +++ 3 files changed, 8 insertions(+), 2 deletions(-) diff --git a/src/gamebryobsainvalidation.cpp b/src/gamebryobsainvalidation.cpp index 000ca369..7d5774a8 100644 --- a/src/gamebryobsainvalidation.cpp +++ b/src/gamebryobsainvalidation.cpp @@ -81,7 +81,7 @@ void GamebryoBSAInvalidation::activate(MOBase::IProfile *profile) } // set the remaining ini settings required - QString iniFile = QDir(profile->absolutePath()).absoluteFilePath(m_IniFileName); + QString iniFile = profile->localSettingsEnabled() ? QDir(profile->absolutePath()).absoluteFilePath(m_IniFileName) : m_Game->documentsDirectory().absoluteFilePath(m_IniFileName); ::SetFileAttributesW(iniFile.toStdWString().c_str(), FILE_ATTRIBUTE_NORMAL); diff --git a/src/gamebryodataarchives.cpp b/src/gamebryodataarchives.cpp index 912d7df7..fd585d3b 100644 --- a/src/gamebryodataarchives.cpp +++ b/src/gamebryodataarchives.cpp @@ -1,9 +1,12 @@ #include "gamebryodataarchives.h" -#include #include #include +GamebryoDataArchives::GamebryoDataArchives(const QDir &myGamesDir): + m_LocalGameDir(myGamesDir.absolutePath()) +{} + QStringList GamebryoDataArchives::getArchivesFromKey(const QString &iniFile, const QString &key) const { wchar_t buffer[256]; diff --git a/src/gamebryodataarchives.h b/src/gamebryodataarchives.h index 66390880..055cc3c9 100644 --- a/src/gamebryodataarchives.h +++ b/src/gamebryodataarchives.h @@ -3,17 +3,20 @@ #include "dataarchives.h" +#include class GamebryoDataArchives : public DataArchives { public: + GamebryoDataArchives(const QDir &myGamesDir); virtual void addArchive(MOBase::IProfile *profile, int index, const QString &archiveName) override; virtual void removeArchive(MOBase::IProfile *profile, const QString &archiveName) override; protected: + QDir m_LocalGameDir; QStringList getArchivesFromKey(const QString &iniFile, const QString &key) const; void setArchivesToKey(const QString &iniFile, const QString &key, const QString &value); From 0a63e1eea3af8ddf985cb12028c862ef2f3f6457 Mon Sep 17 00:00:00 2001 From: Jeremy Rimpo Date: Wed, 13 Dec 2017 12:30:30 -0600 Subject: [PATCH 0410/1544] [game_fallout3] Fix profile problems with archive invalidation --- src/games/fallout3/src/fallout3dataarchives.cpp | 10 ++++++---- src/games/fallout3/src/fallout3dataarchives.h | 4 ++++ src/games/fallout3/src/gamefallout3.cpp | 2 +- 3 files changed, 11 insertions(+), 5 deletions(-) diff --git a/src/games/fallout3/src/fallout3dataarchives.cpp b/src/games/fallout3/src/fallout3dataarchives.cpp index b2d42bc0..c308dda7 100644 --- a/src/games/fallout3/src/fallout3dataarchives.cpp +++ b/src/games/fallout3/src/fallout3dataarchives.cpp @@ -3,8 +3,10 @@ #include "iprofile.h" #include -#include - +Fallout3DataArchives::Fallout3DataArchives(const QDir &myGamesDir) : + GamebryoDataArchives(myGamesDir) +{ +} QStringList Fallout3DataArchives::vanillaArchives() const { @@ -21,7 +23,7 @@ QStringList Fallout3DataArchives::archives(const MOBase::IProfile *profile) cons { QStringList result; - QString iniFile = QDir(profile->absolutePath()).absoluteFilePath("fallout3.ini"); + QString iniFile = profile->localSettingsEnabled() ? QDir(profile->absolutePath()).absoluteFilePath("fallout.ini") : m_LocalGameDir.absoluteFilePath("fallout.ini"); result.append(getArchivesFromKey(iniFile, "SArchiveList")); return result; @@ -31,6 +33,6 @@ void Fallout3DataArchives::writeArchiveList(MOBase::IProfile *profile, const QSt { QString list = before.join(", "); - QString iniFile = QDir(profile->absolutePath()).absoluteFilePath("fallout3.ini"); + QString iniFile = profile->localSettingsEnabled() ? QDir(profile->absolutePath()).absoluteFilePath("fallout.ini") : m_LocalGameDir.absoluteFilePath("fallout.ini"); setArchivesToKey(iniFile, "SArchiveList", list); } diff --git a/src/games/fallout3/src/fallout3dataarchives.h b/src/games/fallout3/src/fallout3dataarchives.h index 7b2a5345..7caf47f7 100644 --- a/src/games/fallout3/src/fallout3dataarchives.h +++ b/src/games/fallout3/src/fallout3dataarchives.h @@ -3,10 +3,14 @@ #include "gamebryodataarchives.h" +#include class Fallout3DataArchives : public GamebryoDataArchives { +public: + Fallout3DataArchives(const QDir &myGamesDir); + public: virtual QStringList vanillaArchives() const override; diff --git a/src/games/fallout3/src/gamefallout3.cpp b/src/games/fallout3/src/gamefallout3.cpp index 8beb700e..a685920f 100644 --- a/src/games/fallout3/src/gamefallout3.cpp +++ b/src/games/fallout3/src/gamefallout3.cpp @@ -34,7 +34,7 @@ bool GameFallout3::init(IOrganizer *moInfo) return false; } registerFeature(new Fallout3ScriptExtender(this)); - registerFeature(new Fallout3DataArchives()); + registerFeature(new Fallout3DataArchives(myGamesPath())); registerFeature(new Fallout3BSAInvalidation(feature(), this)); registerFeature(new Fallout3SaveGameInfo(this)); registerFeature(new GamebryoLocalSavegames(myGamesPath(), "fallout.ini")); From 5223834dc0f986efbe51517b48ccd2589f3b2511 Mon Sep 17 00:00:00 2001 From: Jeremy Rimpo Date: Wed, 13 Dec 2017 12:30:30 -0600 Subject: [PATCH 0411/1544] [game_fallout4vr] Fix profile problems with archive invalidation --- src/games/fallout4vr/src/fallout4dataarchives.cpp | 9 +++++---- src/games/fallout4vr/src/fallout4dataarchives.h | 5 +++++ src/games/fallout4vr/src/gamefallout4.cpp | 2 +- 3 files changed, 11 insertions(+), 5 deletions(-) diff --git a/src/games/fallout4vr/src/fallout4dataarchives.cpp b/src/games/fallout4vr/src/fallout4dataarchives.cpp index e5908ac4..3cad8c96 100644 --- a/src/games/fallout4vr/src/fallout4dataarchives.cpp +++ b/src/games/fallout4vr/src/fallout4dataarchives.cpp @@ -3,8 +3,9 @@ #include "iprofile.h" #include -#include - +Fallout4DataArchives::Fallout4DataArchives(const QDir &myGamesDir) : + GamebryoDataArchives(myGamesDir) +{} QStringList Fallout4DataArchives::vanillaArchives() const { @@ -34,7 +35,7 @@ QStringList Fallout4DataArchives::archives(const MOBase::IProfile *profile) cons { QStringList result; - QString iniFile = QDir(profile->absolutePath()).absoluteFilePath("fallout4.ini"); + QString iniFile = profile->localSettingsEnabled() ? QDir(profile->absolutePath()).absoluteFilePath("fallout4.ini") : m_LocalGameDir.absoluteFilePath("fallout4.ini"); result.append(getArchivesFromKey(iniFile, "SResourceArchiveList")); result.append(getArchivesFromKey(iniFile, "SResourceArchiveList2")); @@ -45,7 +46,7 @@ void Fallout4DataArchives::writeArchiveList(MOBase::IProfile *profile, const QSt { QString list = before.join(", "); - QString iniFile = QDir(profile->absolutePath()).absoluteFilePath("fallout4.ini"); + QString iniFile = profile->localSettingsEnabled() ? QDir(profile->absolutePath()).absoluteFilePath("fallout4.ini") : m_LocalGameDir.absoluteFilePath("fallout4.ini"); if (list.length() > 255) { int splitIdx = list.lastIndexOf(",", 256); setArchivesToKey(iniFile, "SResourceArchiveList", list.mid(0, splitIdx)); diff --git a/src/games/fallout4vr/src/fallout4dataarchives.h b/src/games/fallout4vr/src/fallout4dataarchives.h index a23eb10f..b6abd173 100644 --- a/src/games/fallout4vr/src/fallout4dataarchives.h +++ b/src/games/fallout4vr/src/fallout4dataarchives.h @@ -6,10 +6,15 @@ namespace MOBase { class IProfile; } #include +#include class Fallout4DataArchives : public GamebryoDataArchives { +public: + + Fallout4DataArchives(const QDir &myGamesDir); + public: virtual QStringList vanillaArchives() const override; diff --git a/src/games/fallout4vr/src/gamefallout4.cpp b/src/games/fallout4vr/src/gamefallout4.cpp index c0ec9a73..85b69b53 100644 --- a/src/games/fallout4vr/src/gamefallout4.cpp +++ b/src/games/fallout4vr/src/gamefallout4.cpp @@ -41,7 +41,7 @@ bool GameFallout4::init(IOrganizer *moInfo) } registerFeature(new Fallout4ScriptExtender(this)); - registerFeature(new Fallout4DataArchives()); + registerFeature(new Fallout4DataArchives(myGamesPath())); registerFeature(new GamebryoLocalSavegames(myGamesPath(), "Fallout4.ini")); registerFeature(new Fallout4SaveGameInfo(this)); registerFeature(new Fallout4GamePlugins(moInfo)); From c8c0f2fdbe4033d9d5f68b4977a28d4dceefdf15 Mon Sep 17 00:00:00 2001 From: Jeremy Rimpo Date: Wed, 13 Dec 2017 12:30:30 -0600 Subject: [PATCH 0412/1544] [game_fallout76] Fix profile problems with archive invalidation --- src/games/fallout76/src/fallout4dataarchives.cpp | 9 +++++---- src/games/fallout76/src/fallout4dataarchives.h | 5 +++++ src/games/fallout76/src/gamefallout4.cpp | 2 +- 3 files changed, 11 insertions(+), 5 deletions(-) diff --git a/src/games/fallout76/src/fallout4dataarchives.cpp b/src/games/fallout76/src/fallout4dataarchives.cpp index e5908ac4..3cad8c96 100644 --- a/src/games/fallout76/src/fallout4dataarchives.cpp +++ b/src/games/fallout76/src/fallout4dataarchives.cpp @@ -3,8 +3,9 @@ #include "iprofile.h" #include -#include - +Fallout4DataArchives::Fallout4DataArchives(const QDir &myGamesDir) : + GamebryoDataArchives(myGamesDir) +{} QStringList Fallout4DataArchives::vanillaArchives() const { @@ -34,7 +35,7 @@ QStringList Fallout4DataArchives::archives(const MOBase::IProfile *profile) cons { QStringList result; - QString iniFile = QDir(profile->absolutePath()).absoluteFilePath("fallout4.ini"); + QString iniFile = profile->localSettingsEnabled() ? QDir(profile->absolutePath()).absoluteFilePath("fallout4.ini") : m_LocalGameDir.absoluteFilePath("fallout4.ini"); result.append(getArchivesFromKey(iniFile, "SResourceArchiveList")); result.append(getArchivesFromKey(iniFile, "SResourceArchiveList2")); @@ -45,7 +46,7 @@ void Fallout4DataArchives::writeArchiveList(MOBase::IProfile *profile, const QSt { QString list = before.join(", "); - QString iniFile = QDir(profile->absolutePath()).absoluteFilePath("fallout4.ini"); + QString iniFile = profile->localSettingsEnabled() ? QDir(profile->absolutePath()).absoluteFilePath("fallout4.ini") : m_LocalGameDir.absoluteFilePath("fallout4.ini"); if (list.length() > 255) { int splitIdx = list.lastIndexOf(",", 256); setArchivesToKey(iniFile, "SResourceArchiveList", list.mid(0, splitIdx)); diff --git a/src/games/fallout76/src/fallout4dataarchives.h b/src/games/fallout76/src/fallout4dataarchives.h index a23eb10f..b6abd173 100644 --- a/src/games/fallout76/src/fallout4dataarchives.h +++ b/src/games/fallout76/src/fallout4dataarchives.h @@ -6,10 +6,15 @@ namespace MOBase { class IProfile; } #include +#include class Fallout4DataArchives : public GamebryoDataArchives { +public: + + Fallout4DataArchives(const QDir &myGamesDir); + public: virtual QStringList vanillaArchives() const override; diff --git a/src/games/fallout76/src/gamefallout4.cpp b/src/games/fallout76/src/gamefallout4.cpp index c0ec9a73..85b69b53 100644 --- a/src/games/fallout76/src/gamefallout4.cpp +++ b/src/games/fallout76/src/gamefallout4.cpp @@ -41,7 +41,7 @@ bool GameFallout4::init(IOrganizer *moInfo) } registerFeature(new Fallout4ScriptExtender(this)); - registerFeature(new Fallout4DataArchives()); + registerFeature(new Fallout4DataArchives(myGamesPath())); registerFeature(new GamebryoLocalSavegames(myGamesPath(), "Fallout4.ini")); registerFeature(new Fallout4SaveGameInfo(this)); registerFeature(new Fallout4GamePlugins(moInfo)); From f3f176013ef31757cd385e4cda999733853af4e1 Mon Sep 17 00:00:00 2001 From: Jeremy Rimpo Date: Wed, 13 Dec 2017 12:30:30 -0600 Subject: [PATCH 0413/1544] [game_fallout4] Fix profile problems with archive invalidation --- src/games/fallout4/src/fallout4dataarchives.cpp | 9 +++++---- src/games/fallout4/src/fallout4dataarchives.h | 5 +++++ src/games/fallout4/src/gamefallout4.cpp | 2 +- 3 files changed, 11 insertions(+), 5 deletions(-) diff --git a/src/games/fallout4/src/fallout4dataarchives.cpp b/src/games/fallout4/src/fallout4dataarchives.cpp index e5908ac4..3cad8c96 100644 --- a/src/games/fallout4/src/fallout4dataarchives.cpp +++ b/src/games/fallout4/src/fallout4dataarchives.cpp @@ -3,8 +3,9 @@ #include "iprofile.h" #include -#include - +Fallout4DataArchives::Fallout4DataArchives(const QDir &myGamesDir) : + GamebryoDataArchives(myGamesDir) +{} QStringList Fallout4DataArchives::vanillaArchives() const { @@ -34,7 +35,7 @@ QStringList Fallout4DataArchives::archives(const MOBase::IProfile *profile) cons { QStringList result; - QString iniFile = QDir(profile->absolutePath()).absoluteFilePath("fallout4.ini"); + QString iniFile = profile->localSettingsEnabled() ? QDir(profile->absolutePath()).absoluteFilePath("fallout4.ini") : m_LocalGameDir.absoluteFilePath("fallout4.ini"); result.append(getArchivesFromKey(iniFile, "SResourceArchiveList")); result.append(getArchivesFromKey(iniFile, "SResourceArchiveList2")); @@ -45,7 +46,7 @@ void Fallout4DataArchives::writeArchiveList(MOBase::IProfile *profile, const QSt { QString list = before.join(", "); - QString iniFile = QDir(profile->absolutePath()).absoluteFilePath("fallout4.ini"); + QString iniFile = profile->localSettingsEnabled() ? QDir(profile->absolutePath()).absoluteFilePath("fallout4.ini") : m_LocalGameDir.absoluteFilePath("fallout4.ini"); if (list.length() > 255) { int splitIdx = list.lastIndexOf(",", 256); setArchivesToKey(iniFile, "SResourceArchiveList", list.mid(0, splitIdx)); diff --git a/src/games/fallout4/src/fallout4dataarchives.h b/src/games/fallout4/src/fallout4dataarchives.h index a23eb10f..b6abd173 100644 --- a/src/games/fallout4/src/fallout4dataarchives.h +++ b/src/games/fallout4/src/fallout4dataarchives.h @@ -6,10 +6,15 @@ namespace MOBase { class IProfile; } #include +#include class Fallout4DataArchives : public GamebryoDataArchives { +public: + + Fallout4DataArchives(const QDir &myGamesDir); + public: virtual QStringList vanillaArchives() const override; diff --git a/src/games/fallout4/src/gamefallout4.cpp b/src/games/fallout4/src/gamefallout4.cpp index c0ec9a73..85b69b53 100644 --- a/src/games/fallout4/src/gamefallout4.cpp +++ b/src/games/fallout4/src/gamefallout4.cpp @@ -41,7 +41,7 @@ bool GameFallout4::init(IOrganizer *moInfo) } registerFeature(new Fallout4ScriptExtender(this)); - registerFeature(new Fallout4DataArchives()); + registerFeature(new Fallout4DataArchives(myGamesPath())); registerFeature(new GamebryoLocalSavegames(myGamesPath(), "Fallout4.ini")); registerFeature(new Fallout4SaveGameInfo(this)); registerFeature(new Fallout4GamePlugins(moInfo)); From 2c094c95fcdbfe80bb516032028bc829995e54e5 Mon Sep 17 00:00:00 2001 From: Jeremy Rimpo Date: Wed, 13 Dec 2017 12:30:31 -0600 Subject: [PATCH 0414/1544] [game_skyrimse] Fix profile problems with archive invalidation --- src/games/skyrimse/src/gameskyrimse.cpp | 2 +- src/games/skyrimse/src/skyrimsedataarchives.cpp | 9 +++++---- src/games/skyrimse/src/skyrimsedataarchives.h | 7 ++++++- 3 files changed, 12 insertions(+), 6 deletions(-) diff --git a/src/games/skyrimse/src/gameskyrimse.cpp b/src/games/skyrimse/src/gameskyrimse.cpp index 2b139675..b8528369 100644 --- a/src/games/skyrimse/src/gameskyrimse.cpp +++ b/src/games/skyrimse/src/gameskyrimse.cpp @@ -168,7 +168,7 @@ bool GameSkyrimSE::init(IOrganizer *moInfo) registerFeature(new SkyrimSEScriptExtender(this)); - registerFeature(new SkyrimSEDataArchives()); + registerFeature(new SkyrimSEDataArchives(myGamesPath())); registerFeature(new GamebryoLocalSavegames(myGamesPath(), "Skyrim.ini")); registerFeature(new SkyrimSESaveGameInfo(this)); registerFeature(new SkyrimSEGamePlugins(moInfo)); diff --git a/src/games/skyrimse/src/skyrimsedataarchives.cpp b/src/games/skyrimse/src/skyrimsedataarchives.cpp index 455d46a3..91921ea4 100644 --- a/src/games/skyrimse/src/skyrimsedataarchives.cpp +++ b/src/games/skyrimse/src/skyrimsedataarchives.cpp @@ -3,8 +3,9 @@ #include "iprofile.h" #include -#include - +SkyrimSEDataArchives::SkyrimSEDataArchives(const QDir &myGamesDir) : + GamebryoDataArchives(myGamesDir) +{} QStringList SkyrimSEDataArchives::vanillaArchives() const { @@ -32,7 +33,7 @@ QStringList SkyrimSEDataArchives::archives(const MOBase::IProfile *profile) cons { QStringList result; - QString iniFile = QDir(profile->absolutePath()).absoluteFilePath("skyrim.ini"); + QString iniFile = profile->localSettingsEnabled() ? QDir(profile->absolutePath()).absoluteFilePath("skyrim.ini") : m_LocalGameDir.absoluteFilePath("skyrim.ini"); result.append(getArchivesFromKey(iniFile, "SResourceArchiveList")); result.append(getArchivesFromKey(iniFile, "SResourceArchiveList2")); @@ -43,7 +44,7 @@ void SkyrimSEDataArchives::writeArchiveList(MOBase::IProfile *profile, const QSt { QString list = before.join(", "); - QString iniFile = QDir(profile->absolutePath()).absoluteFilePath("skyrim.ini"); + QString iniFile = profile->localSettingsEnabled() ? QDir(profile->absolutePath()).absoluteFilePath("skyrim.ini") : m_LocalGameDir.absoluteFilePath("skyrim.ini"); if (list.length() > 255) { int splitIdx = list.lastIndexOf(",", 256); setArchivesToKey(iniFile, "SResourceArchiveList", list.mid(0, splitIdx)); diff --git a/src/games/skyrimse/src/skyrimsedataarchives.h b/src/games/skyrimse/src/skyrimsedataarchives.h index 6ba4fb6d..5f4fbef7 100644 --- a/src/games/skyrimse/src/skyrimsedataarchives.h +++ b/src/games/skyrimse/src/skyrimsedataarchives.h @@ -2,14 +2,19 @@ #define _SKYRIMSEDATAARCHIVES_H #include "gamebryodataarchives.h" +#include +#include namespace MOBase { class IProfile; } -#include class SkyrimSEDataArchives : public GamebryoDataArchives { +public: + + SkyrimSEDataArchives(const QDir &myGamesDir); + public: virtual QStringList vanillaArchives() const override; From 14568d355f01413947bd636e4c4148a86162d2be Mon Sep 17 00:00:00 2001 From: Jeremy Rimpo Date: Wed, 13 Dec 2017 12:30:32 -0600 Subject: [PATCH 0415/1544] [game_skyrim] Fix profile problems with archive invalidation --- src/games/skyrim/src/gameskyrim.cpp | 2 +- src/games/skyrim/src/skyrimdataarchives.cpp | 9 ++++++--- src/games/skyrim/src/skyrimdataarchives.h | 4 ++++ 3 files changed, 11 insertions(+), 4 deletions(-) diff --git a/src/games/skyrim/src/gameskyrim.cpp b/src/games/skyrim/src/gameskyrim.cpp index fc1c091e..0c07aced 100644 --- a/src/games/skyrim/src/gameskyrim.cpp +++ b/src/games/skyrim/src/gameskyrim.cpp @@ -39,7 +39,7 @@ bool GameSkyrim::init(IOrganizer *moInfo) return false; } registerFeature(new SkyrimScriptExtender(this)); - registerFeature(new SkyrimDataArchives()); + registerFeature(new SkyrimDataArchives(myGamesPath())); registerFeature(new SkyrimBSAInvalidation(feature(), this)); registerFeature(new SkyrimSaveGameInfo(this)); registerFeature(new GamebryoLocalSavegames(myGamesPath(), "skyrim.ini")); diff --git a/src/games/skyrim/src/skyrimdataarchives.cpp b/src/games/skyrim/src/skyrimdataarchives.cpp index e4c39c2e..1952809e 100644 --- a/src/games/skyrim/src/skyrimdataarchives.cpp +++ b/src/games/skyrim/src/skyrimdataarchives.cpp @@ -1,7 +1,10 @@ #include "skyrimdataarchives.h" #include -#include +SkyrimDataArchives::SkyrimDataArchives(const QDir &myGamesDir) : + GamebryoDataArchives(myGamesDir) +{ +} QStringList SkyrimDataArchives::vanillaArchives() const { @@ -24,7 +27,7 @@ QStringList SkyrimDataArchives::archives(const MOBase::IProfile *profile) const { QStringList result; - QString iniFile = QDir(profile->absolutePath()).absoluteFilePath("skyrim.ini"); + QString iniFile = profile->localSettingsEnabled() ? QDir(profile->absolutePath()).absoluteFilePath("skyrim.ini") : m_LocalGameDir.absoluteFilePath("skyrim.ini"); result.append(getArchivesFromKey(iniFile, "SResourceArchiveList")); result.append(getArchivesFromKey(iniFile, "SResourceArchiveList2")); @@ -35,7 +38,7 @@ void SkyrimDataArchives::writeArchiveList(MOBase::IProfile *profile, const QStri { QString list = before.join(", "); - QString iniFile = QDir(profile->absolutePath()).absoluteFilePath("skyrim.ini"); + QString iniFile = profile->localSettingsEnabled() ? QDir(profile->absolutePath()).absoluteFilePath("skyrim.ini") : m_LocalGameDir.absoluteFilePath("skyrim.ini"); if (list.length() > 255) { int splitIdx = list.lastIndexOf(",", 256); setArchivesToKey(iniFile, "SResourceArchiveList", list.mid(0, splitIdx)); diff --git a/src/games/skyrim/src/skyrimdataarchives.h b/src/games/skyrim/src/skyrimdataarchives.h index 8c532a4c..35f5fb44 100644 --- a/src/games/skyrim/src/skyrimdataarchives.h +++ b/src/games/skyrim/src/skyrimdataarchives.h @@ -6,10 +6,14 @@ #include #include #include +#include class SkyrimDataArchives : public GamebryoDataArchives { +public: + SkyrimDataArchives(const QDir &myGamesDir); + public: virtual QStringList vanillaArchives() const override; From b00ee9b5e9c85bce56eb68dc1a2ae5d93ebec5ef Mon Sep 17 00:00:00 2001 From: matzman666 Date: Fri, 5 Jan 2018 17:23:58 +0100 Subject: [PATCH 0416/1544] [game_fallout4vr] Rewrote code to support Fallout 4 VR. --- src/games/fallout4vr/CMakeLists.txt | 2 +- src/games/fallout4vr/Readme.md | 3 + src/games/fallout4vr/src/CMakeLists.txt | 2 +- src/games/fallout4vr/src/SConscript | 4 +- src/games/fallout4vr/src/fallout4savegame.h | 14 -- .../fallout4vr/src/fallout4savegameinfo.cpp | 19 -- .../fallout4vr/src/fallout4scriptextender.cpp | 24 -- .../src/{fallout4.qrc => fallout4vr.qrc} | 2 +- ...rchives.cpp => fallout4vrdataarchives.cpp} | 15 +- ...ataarchives.h => fallout4vrdataarchives.h} | 10 +- ...eplugins.cpp => fallout4vrgameplugins.cpp} | 8 +- ...4gameplugins.h => fallout4vrgameplugins.h} | 10 +- ...ut4savegame.cpp => fallout4vrsavegame.cpp} | 4 +- src/games/fallout4vr/src/fallout4vrsavegame.h | 14 ++ .../fallout4vr/src/fallout4vrsavegameinfo.cpp | 19 ++ ...avegameinfo.h => fallout4vrsavegameinfo.h} | 6 +- .../src/fallout4vrscriptextender.cpp | 24 ++ ...textender.h => fallout4vrscriptextender.h} | 8 +- ...edmods.cpp => fallout4vrunmanagedmods.cpp} | 12 +- ...anagedmods.h => fallout4vrunmanagedmods.h} | 10 +- .../{gameFallout4.pro => gameFallout4vr.pro} | 0 ...e_fallout4_en.ts => game_fallout4vr_en.ts} | 8 +- src/games/fallout4vr/src/gamefallout4.cpp | 210 ----------------- src/games/fallout4vr/src/gamefallout4vr.cpp | 218 ++++++++++++++++++ .../src/{gamefallout4.h => gamefallout4vr.h} | 12 +- ...{gamefallout4.json => gamefallout4vr.json} | 0 26 files changed, 336 insertions(+), 322 deletions(-) create mode 100644 src/games/fallout4vr/Readme.md delete mode 100644 src/games/fallout4vr/src/fallout4savegame.h delete mode 100644 src/games/fallout4vr/src/fallout4savegameinfo.cpp delete mode 100644 src/games/fallout4vr/src/fallout4scriptextender.cpp rename src/games/fallout4vr/src/{fallout4.qrc => fallout4vr.qrc} (67%) rename src/games/fallout4vr/src/{fallout4dataarchives.cpp => fallout4vrdataarchives.cpp} (76%) rename src/games/fallout4vr/src/{fallout4dataarchives.h => fallout4vrdataarchives.h} (64%) rename src/games/fallout4vr/src/{fallout4gameplugins.cpp => fallout4vrgameplugins.cpp} (94%) rename src/games/fallout4vr/src/{fallout4gameplugins.h => fallout4vrgameplugins.h} (70%) rename src/games/fallout4vr/src/{fallout4savegame.cpp => fallout4vrsavegame.cpp} (88%) create mode 100644 src/games/fallout4vr/src/fallout4vrsavegame.h create mode 100644 src/games/fallout4vr/src/fallout4vrsavegameinfo.cpp rename src/games/fallout4vr/src/{fallout4savegameinfo.h => fallout4vrsavegameinfo.h} (64%) create mode 100644 src/games/fallout4vr/src/fallout4vrscriptextender.cpp rename src/games/fallout4vr/src/{fallout4scriptextender.h => fallout4vrscriptextender.h} (59%) rename src/games/fallout4vr/src/{fallout4unmanagedmods.cpp => fallout4vrunmanagedmods.cpp} (82%) rename src/games/fallout4vr/src/{fallout4unmanagedmods.h => fallout4vrunmanagedmods.h} (60%) rename src/games/fallout4vr/src/{gameFallout4.pro => gameFallout4vr.pro} (100%) rename src/games/fallout4vr/src/{game_fallout4_en.ts => game_fallout4vr_en.ts} (71%) delete mode 100644 src/games/fallout4vr/src/gamefallout4.cpp create mode 100644 src/games/fallout4vr/src/gamefallout4vr.cpp rename src/games/fallout4vr/src/{gamefallout4.h => gamefallout4vr.h} (86%) rename src/games/fallout4vr/src/{gamefallout4.json => gamefallout4vr.json} (100%) diff --git a/src/games/fallout4vr/CMakeLists.txt b/src/games/fallout4vr/CMakeLists.txt index 950d7a0c..deefeff3 100644 --- a/src/games/fallout4vr/CMakeLists.txt +++ b/src/games/fallout4vr/CMakeLists.txt @@ -1,6 +1,6 @@ CMAKE_MINIMUM_REQUIRED(VERSION 2.8) -SET(PROJ_NAME game_fallout4) +SET(PROJ_NAME game_fallout4vr) PROJECT(${PROJ_NAME}) diff --git a/src/games/fallout4vr/Readme.md b/src/games/fallout4vr/Readme.md new file mode 100644 index 00000000..e47da4f0 --- /dev/null +++ b/src/games/fallout4vr/Readme.md @@ -0,0 +1,3 @@ +# Fallout 4 VR plugin for [Mod Organizer 2](https://github.com/LePresidente/modorganizer). + +Go to [release section](releases) for download and instructions. diff --git a/src/games/fallout4vr/src/CMakeLists.txt b/src/games/fallout4vr/src/CMakeLists.txt index c52541f2..c45fea37 100644 --- a/src/games/fallout4vr/src/CMakeLists.txt +++ b/src/games/fallout4vr/src/CMakeLists.txt @@ -7,7 +7,7 @@ FILE(GLOB ${PROJ_NAME}_HDRS *.h) FILE(GLOB ${PROJ_NAME}_FORMS *.ui) SET(${PROJ_NAME}_QRCS - fallout4.qrc + fallout4vr.qrc ) SET(CMAKE_INCLUDE_CURRENT_DIR ON) diff --git a/src/games/fallout4vr/src/SConscript b/src/games/fallout4vr/src/SConscript index ebd2e920..e04e8a8f 100644 --- a/src/games/fallout4vr/src/SConscript +++ b/src/games/fallout4vr/src/SConscript @@ -3,11 +3,11 @@ Import('qt_env') env = qt_env.Clone() # Shouldn't this be GAMEFALLOUT3_LIBRARY -env.AppendUnique(CPPDEFINES = [ 'GAMEFALLOUT4_LIBRARY' ]) +env.AppendUnique(CPPDEFINES = [ 'GAMEFALLOUT4VR_LIBRARY' ]) env.RequiresGamebryo() -lib = env.SharedLibrary('gameFallout4', env.Glob('*.cpp')) +lib = env.SharedLibrary('gameFallout4vr', env.Glob('*.cpp')) env.InstallModule(lib) res = env['QT_USED_MODULES'] diff --git a/src/games/fallout4vr/src/fallout4savegame.h b/src/games/fallout4vr/src/fallout4savegame.h deleted file mode 100644 index 98dffc9f..00000000 --- a/src/games/fallout4vr/src/fallout4savegame.h +++ /dev/null @@ -1,14 +0,0 @@ -#ifndef FALLOUT4SAVEGAME_H -#define FALLOUT4SAVEGAME_H - -#include "gamebryosavegame.h" - -namespace MOBase { class IPluginGame; } - -class Fallout4SaveGame : public GamebryoSaveGame -{ -public: - Fallout4SaveGame(QString const &fileName, MOBase::IPluginGame const *game, bool const lightEnabled = true); -}; - -#endif // FALLOUT4SAVEGAME_H diff --git a/src/games/fallout4vr/src/fallout4savegameinfo.cpp b/src/games/fallout4vr/src/fallout4savegameinfo.cpp deleted file mode 100644 index 22856d86..00000000 --- a/src/games/fallout4vr/src/fallout4savegameinfo.cpp +++ /dev/null @@ -1,19 +0,0 @@ -#include "fallout4savegameinfo.h" - -#include "fallout4savegame.h" -#include "gamegamebryo.h" - -Fallout4SaveGameInfo::Fallout4SaveGameInfo(GameGamebryo const *game) : - GamebryoSaveGameInfo(game) -{ -} - -Fallout4SaveGameInfo::~Fallout4SaveGameInfo() -{ -} - -const MOBase::ISaveGame *Fallout4SaveGameInfo::getSaveGameInfo(const QString &file) const -{ - return new Fallout4SaveGame(file, m_Game); -} - diff --git a/src/games/fallout4vr/src/fallout4scriptextender.cpp b/src/games/fallout4vr/src/fallout4scriptextender.cpp deleted file mode 100644 index 21c930c9..00000000 --- a/src/games/fallout4vr/src/fallout4scriptextender.cpp +++ /dev/null @@ -1,24 +0,0 @@ -#include "fallout4scriptextender.h" - -#include -#include - -Fallout4ScriptExtender::Fallout4ScriptExtender(GameGamebryo const *game) : - GamebryoScriptExtender(game) -{ -} - -QString Fallout4ScriptExtender::BinaryName() const -{ - return "f4se_loader.exe"; -} - -QString Fallout4ScriptExtender::PluginPath() const -{ - return "f4se/plugins"; -} - -QStringList Fallout4ScriptExtender::saveGameAttachmentExtensions() const -{ - return { }; -} diff --git a/src/games/fallout4vr/src/fallout4.qrc b/src/games/fallout4vr/src/fallout4vr.qrc similarity index 67% rename from src/games/fallout4vr/src/fallout4.qrc rename to src/games/fallout4vr/src/fallout4vr.qrc index c8e52145..75ba0553 100644 --- a/src/games/fallout4vr/src/fallout4.qrc +++ b/src/games/fallout4vr/src/fallout4vr.qrc @@ -1,5 +1,5 @@ - + splash.png diff --git a/src/games/fallout4vr/src/fallout4dataarchives.cpp b/src/games/fallout4vr/src/fallout4vrdataarchives.cpp similarity index 76% rename from src/games/fallout4vr/src/fallout4dataarchives.cpp rename to src/games/fallout4vr/src/fallout4vrdataarchives.cpp index 3cad8c96..c43d86b8 100644 --- a/src/games/fallout4vr/src/fallout4dataarchives.cpp +++ b/src/games/fallout4vr/src/fallout4vrdataarchives.cpp @@ -1,13 +1,13 @@ -#include "fallout4dataarchives.h" +#include "fallout4vrdataarchives.h" #include "iprofile.h" #include -Fallout4DataArchives::Fallout4DataArchives(const QDir &myGamesDir) : +Fallout4VRDataArchives::Fallout4VRDataArchives(const QDir &myGamesDir) : GamebryoDataArchives(myGamesDir) {} -QStringList Fallout4DataArchives::vanillaArchives() const +QStringList Fallout4VRDataArchives::vanillaArchives() const { return { "Fallout4 - Textures1.ba2" , "Fallout4 - Textures2.ba2" @@ -27,11 +27,14 @@ QStringList Fallout4DataArchives::vanillaArchives() const , "Fallout4 - Materials.ba2" , "Fallout4 - Shaders.ba2" , "Fallout4 - Startup.ba2" - , "Fallout4 - Misc.ba2" }; + , "Fallout4 - Misc.ba2" + , "Fallout4_VR - Main.ba2" + , "Fallout4_VR - Shaders.ba2" + , "Fallout4_VR - Textures.ba2" }; } -QStringList Fallout4DataArchives::archives(const MOBase::IProfile *profile) const +QStringList Fallout4VRDataArchives::archives(const MOBase::IProfile *profile) const { QStringList result; @@ -42,7 +45,7 @@ QStringList Fallout4DataArchives::archives(const MOBase::IProfile *profile) cons return result; } -void Fallout4DataArchives::writeArchiveList(MOBase::IProfile *profile, const QStringList &before) +void Fallout4VRDataArchives::writeArchiveList(MOBase::IProfile *profile, const QStringList &before) { QString list = before.join(", "); diff --git a/src/games/fallout4vr/src/fallout4dataarchives.h b/src/games/fallout4vr/src/fallout4vrdataarchives.h similarity index 64% rename from src/games/fallout4vr/src/fallout4dataarchives.h rename to src/games/fallout4vr/src/fallout4vrdataarchives.h index b6abd173..4f76a003 100644 --- a/src/games/fallout4vr/src/fallout4dataarchives.h +++ b/src/games/fallout4vr/src/fallout4vrdataarchives.h @@ -1,5 +1,5 @@ -#ifndef FALLOUT4DATAARCHIVES_H -#define FALLOUT4DATAARCHIVES_H +#ifndef FALLOUT4VRDATAARCHIVES_H +#define FALLOUT4VRDATAARCHIVES_H #include "gamebryodataarchives.h" @@ -8,12 +8,12 @@ namespace MOBase { class IProfile; } #include #include -class Fallout4DataArchives : public GamebryoDataArchives +class Fallout4VRDataArchives : public GamebryoDataArchives { public: - Fallout4DataArchives(const QDir &myGamesDir); + Fallout4VRDataArchives(const QDir &myGamesDir); public: @@ -26,4 +26,4 @@ private: }; -#endif // FALLOUT4DATAARCHIVES_H +#endif // Fallout4VRDataArchives_H diff --git a/src/games/fallout4vr/src/fallout4gameplugins.cpp b/src/games/fallout4vr/src/fallout4vrgameplugins.cpp similarity index 94% rename from src/games/fallout4vr/src/fallout4gameplugins.cpp rename to src/games/fallout4vr/src/fallout4vrgameplugins.cpp index 588bbb89..1e8c46c8 100644 --- a/src/games/fallout4vr/src/fallout4gameplugins.cpp +++ b/src/games/fallout4vr/src/fallout4vrgameplugins.cpp @@ -1,4 +1,4 @@ -#include "fallout4gameplugins.h" +#include "fallout4vrgameplugins.h" #include #include #include @@ -17,12 +17,12 @@ using MOBase::IOrganizer; using MOBase::SafeWriteFile; using MOBase::reportError; -Fallout4GamePlugins::Fallout4GamePlugins(IOrganizer *organizer) +Fallout4VRGamePlugins::Fallout4VRGamePlugins(IOrganizer *organizer) : GamebryoGamePlugins(organizer) { } -void Fallout4GamePlugins::writePluginList(const IPluginList *pluginList, +void Fallout4VRGamePlugins::writePluginList(const IPluginList *pluginList, const QString &filePath) { SafeWriteFile file(filePath); @@ -91,7 +91,7 @@ void Fallout4GamePlugins::writePluginList(const IPluginList *pluginList, } } -bool Fallout4GamePlugins::readPluginList(MOBase::IPluginList *pluginList, +bool Fallout4VRGamePlugins::readPluginList(MOBase::IPluginList *pluginList, const QString &filePath, bool useLoadOrder) { diff --git a/src/games/fallout4vr/src/fallout4gameplugins.h b/src/games/fallout4vr/src/fallout4vrgameplugins.h similarity index 70% rename from src/games/fallout4vr/src/fallout4gameplugins.h rename to src/games/fallout4vr/src/fallout4vrgameplugins.h index 1e3aef1f..407f4e89 100644 --- a/src/games/fallout4vr/src/fallout4gameplugins.h +++ b/src/games/fallout4vr/src/fallout4vrgameplugins.h @@ -1,5 +1,5 @@ -#ifndef FALLOUT4GAMEPLUGINS_H -#define FALLOUT4GAMEPLUGINS_H +#ifndef FALLOUT4VRGAMEPLUGINS_H +#define FALLOUT4VRGAMEPLUGINS_H #include @@ -8,10 +8,10 @@ #include -class Fallout4GamePlugins : public GamebryoGamePlugins +class Fallout4VRGamePlugins : public GamebryoGamePlugins { public: - Fallout4GamePlugins(MOBase::IOrganizer *organizer); + Fallout4VRGamePlugins(MOBase::IOrganizer *organizer); protected: virtual void writePluginList(const MOBase::IPluginList *pluginList, @@ -24,4 +24,4 @@ private: std::map m_LastSaveHash; }; -#endif // FALLOUT4GAMEPLUGINS_H +#endif // FALLOUT4VRGAMEPLUGINS_H diff --git a/src/games/fallout4vr/src/fallout4savegame.cpp b/src/games/fallout4vr/src/fallout4vrsavegame.cpp similarity index 88% rename from src/games/fallout4vr/src/fallout4savegame.cpp rename to src/games/fallout4vr/src/fallout4vrsavegame.cpp index 429cf1cc..e47a330f 100644 --- a/src/games/fallout4vr/src/fallout4savegame.cpp +++ b/src/games/fallout4vr/src/fallout4vrsavegame.cpp @@ -1,8 +1,8 @@ -#include "fallout4savegame.h" +#include "fallout4vrsavegame.h" #include -Fallout4SaveGame::Fallout4SaveGame(QString const &fileName, MOBase::IPluginGame const *game, bool const lightEnabled) : +Fallout4VRSaveGame::Fallout4VRSaveGame(QString const &fileName, MOBase::IPluginGame const *game, bool const lightEnabled) : GamebryoSaveGame(fileName, game, lightEnabled) { FileWrapper file(this, "FO4_SAVEGAME"); diff --git a/src/games/fallout4vr/src/fallout4vrsavegame.h b/src/games/fallout4vr/src/fallout4vrsavegame.h new file mode 100644 index 00000000..316c7cb8 --- /dev/null +++ b/src/games/fallout4vr/src/fallout4vrsavegame.h @@ -0,0 +1,14 @@ +#ifndef FALLOUT4VRSAVEGAME_H +#define FALLOUT4VRSAVEGAME_H + +#include "gamebryosavegame.h" + +namespace MOBase { class IPluginGame; } + +class Fallout4VRSaveGame : public GamebryoSaveGame +{ +public: + Fallout4VRSaveGame(QString const &fileName, MOBase::IPluginGame const *game, bool const lightEnabled = true); +}; + +#endif // FALLOUT4VRSAVEGAME_H diff --git a/src/games/fallout4vr/src/fallout4vrsavegameinfo.cpp b/src/games/fallout4vr/src/fallout4vrsavegameinfo.cpp new file mode 100644 index 00000000..efb407c3 --- /dev/null +++ b/src/games/fallout4vr/src/fallout4vrsavegameinfo.cpp @@ -0,0 +1,19 @@ +#include "fallout4vrsavegameinfo.h" + +#include "fallout4vrsavegame.h" +#include "gamegamebryo.h" + +Fallout4VRSaveGameInfo::Fallout4VRSaveGameInfo(GameGamebryo const *game) : + GamebryoSaveGameInfo(game) +{ +} + +Fallout4VRSaveGameInfo::~Fallout4VRSaveGameInfo() +{ +} + +const MOBase::ISaveGame *Fallout4VRSaveGameInfo::getSaveGameInfo(const QString &file) const +{ + return new Fallout4VRSaveGame(file, m_Game); +} + diff --git a/src/games/fallout4vr/src/fallout4savegameinfo.h b/src/games/fallout4vr/src/fallout4vrsavegameinfo.h similarity index 64% rename from src/games/fallout4vr/src/fallout4savegameinfo.h rename to src/games/fallout4vr/src/fallout4vrsavegameinfo.h index c36ec6f4..1ea49f51 100644 --- a/src/games/fallout4vr/src/fallout4savegameinfo.h +++ b/src/games/fallout4vr/src/fallout4vrsavegameinfo.h @@ -5,11 +5,11 @@ class GameGamebryo; -class Fallout4SaveGameInfo : public GamebryoSaveGameInfo +class Fallout4VRSaveGameInfo : public GamebryoSaveGameInfo { public: - Fallout4SaveGameInfo(GameGamebryo const *game); - ~Fallout4SaveGameInfo(); + Fallout4VRSaveGameInfo(GameGamebryo const *game); + ~Fallout4VRSaveGameInfo(); virtual MOBase::ISaveGame const *getSaveGameInfo(QString const &file) const override; }; diff --git a/src/games/fallout4vr/src/fallout4vrscriptextender.cpp b/src/games/fallout4vr/src/fallout4vrscriptextender.cpp new file mode 100644 index 00000000..3266c5b4 --- /dev/null +++ b/src/games/fallout4vr/src/fallout4vrscriptextender.cpp @@ -0,0 +1,24 @@ +#include "fallout4vrscriptextender.h" + +#include +#include + +Fallout4VRScriptExtender::Fallout4VRScriptExtender(GameGamebryo const *game) : + GamebryoScriptExtender(game) +{ +} + +QString Fallout4VRScriptExtender::BinaryName() const +{ + return "f4se_loader.exe"; +} + +QString Fallout4VRScriptExtender::PluginPath() const +{ + return "f4se/plugins"; +} + +QStringList Fallout4VRScriptExtender::saveGameAttachmentExtensions() const +{ + return { }; +} diff --git a/src/games/fallout4vr/src/fallout4scriptextender.h b/src/games/fallout4vr/src/fallout4vrscriptextender.h similarity index 59% rename from src/games/fallout4vr/src/fallout4scriptextender.h rename to src/games/fallout4vr/src/fallout4vrscriptextender.h index 4c134276..e13bbf16 100644 --- a/src/games/fallout4vr/src/fallout4scriptextender.h +++ b/src/games/fallout4vr/src/fallout4vrscriptextender.h @@ -1,14 +1,14 @@ -#ifndef FALLOUT4SCRIPTEXTENDER_H -#define FALLOUT4SCRIPTEXTENDER_H +#ifndef FALLOUT4VRSCRIPTEXTENDER_H +#define FALLOUT4VRSCRIPTEXTENDER_H #include "gamebryoscriptextender.h" class GameGamebryo; -class Fallout4ScriptExtender : public GamebryoScriptExtender +class Fallout4VRScriptExtender : public GamebryoScriptExtender { public: - Fallout4ScriptExtender(GameGamebryo const *game); + Fallout4VRScriptExtender(GameGamebryo const *game); virtual QString BinaryName() const override; virtual QString PluginPath() const override; diff --git a/src/games/fallout4vr/src/fallout4unmanagedmods.cpp b/src/games/fallout4vr/src/fallout4vrunmanagedmods.cpp similarity index 82% rename from src/games/fallout4vr/src/fallout4unmanagedmods.cpp rename to src/games/fallout4vr/src/fallout4vrunmanagedmods.cpp index 5007c4f7..9c7a420c 100644 --- a/src/games/fallout4vr/src/fallout4unmanagedmods.cpp +++ b/src/games/fallout4vr/src/fallout4vrunmanagedmods.cpp @@ -1,14 +1,14 @@ -#include "fallout4unmanagedmods.h" +#include "fallout4vrunmanagedmods.h" -Fallout4UnmangedMods::Fallout4UnmangedMods(const GameGamebryo *game) +Fallout4VRUnmangedMods::Fallout4VRUnmangedMods(const GameGamebryo *game) : GamebryoUnmangedMods(game) {} -Fallout4UnmangedMods::~Fallout4UnmangedMods() +Fallout4VRUnmangedMods::~Fallout4VRUnmangedMods() {} -QStringList Fallout4UnmangedMods::mods(bool onlyOfficial) const { +QStringList Fallout4VRUnmangedMods::mods(bool onlyOfficial) const { QStringList result; QStringList pluginList = game()->primaryPlugins(); @@ -30,7 +30,7 @@ QStringList Fallout4UnmangedMods::mods(bool onlyOfficial) const { return result; } -QStringList Fallout4UnmangedMods::secondaryFiles(const QString &modName) const { +QStringList Fallout4VRUnmangedMods::secondaryFiles(const QString &modName) const { // file extension in FO4 is .ba2 instead of bsa QStringList archives; QDir dataDir = game()->dataDirectory(); @@ -40,7 +40,7 @@ QStringList Fallout4UnmangedMods::secondaryFiles(const QString &modName) const { return archives; } -QString Fallout4UnmangedMods::displayName(const QString &modName) const +QString Fallout4VRUnmangedMods::displayName(const QString &modName) const { // unlike in earlier games, in fallout 4 the file name doesn't correspond to // the public name diff --git a/src/games/fallout4vr/src/fallout4unmanagedmods.h b/src/games/fallout4vr/src/fallout4vrunmanagedmods.h similarity index 60% rename from src/games/fallout4vr/src/fallout4unmanagedmods.h rename to src/games/fallout4vr/src/fallout4vrunmanagedmods.h index aaa97e56..65719490 100644 --- a/src/games/fallout4vr/src/fallout4unmanagedmods.h +++ b/src/games/fallout4vr/src/fallout4vrunmanagedmods.h @@ -1,15 +1,15 @@ -#ifndef FALLOUT4UNMANAGEDMODS_H -#define FALLOUT4UNMANAGEDMODS_H +#ifndef FALLOUT4VRUNMANAGEDMODS_H +#define FALLOUT4VRUNMANAGEDMODS_H #include "gamebryounmanagedmods.h" #include -class Fallout4UnmangedMods : public GamebryoUnmangedMods { +class Fallout4VRUnmangedMods : public GamebryoUnmangedMods { public: - Fallout4UnmangedMods(const GameGamebryo *game); - ~Fallout4UnmangedMods(); + Fallout4VRUnmangedMods(const GameGamebryo *game); + ~Fallout4VRUnmangedMods(); virtual QStringList mods(bool onlyOfficial) const override; virtual QStringList secondaryFiles(const QString &modName) const override; diff --git a/src/games/fallout4vr/src/gameFallout4.pro b/src/games/fallout4vr/src/gameFallout4vr.pro similarity index 100% rename from src/games/fallout4vr/src/gameFallout4.pro rename to src/games/fallout4vr/src/gameFallout4vr.pro diff --git a/src/games/fallout4vr/src/game_fallout4_en.ts b/src/games/fallout4vr/src/game_fallout4vr_en.ts similarity index 71% rename from src/games/fallout4vr/src/game_fallout4_en.ts rename to src/games/fallout4vr/src/game_fallout4vr_en.ts index 7fd0409f..01e5ca6c 100644 --- a/src/games/fallout4vr/src/game_fallout4_en.ts +++ b/src/games/fallout4vr/src/game_fallout4vr_en.ts @@ -2,10 +2,10 @@ - GameFallout4 + GameFallout4VR - - Adds support for the game Fallout 4. + + Adds support for the game Fallout 4 VR. Splash by %1 @@ -13,7 +13,7 @@ Splash by %1 QObject - + Some of your plugins have invalid names! These plugins can not be loaded by the game. Please see mo_interface.log for a list of affected plugins and rename them. diff --git a/src/games/fallout4vr/src/gamefallout4.cpp b/src/games/fallout4vr/src/gamefallout4.cpp deleted file mode 100644 index 85b69b53..00000000 --- a/src/games/fallout4vr/src/gamefallout4.cpp +++ /dev/null @@ -1,210 +0,0 @@ -#include "gameFallout4.h" - -#include "fallout4dataarchives.h" -#include "fallout4scriptextender.h" -#include "fallout4savegameinfo.h" -#include "fallout4gameplugins.h" -#include "fallout4unmanagedmods.h" - -#include -#include "iplugingame.h" -#include -#include -#include -#include "versioninfo.h" - -#include -#include -#include -#include -#include -#include -#include - -#include - -#include "utility.h" -#include -#include -#include "scopeguard.h" - -using namespace MOBase; - -GameFallout4::GameFallout4() -{ -} - -bool GameFallout4::init(IOrganizer *moInfo) -{ - if (!GameGamebryo::init(moInfo)) { - return false; - } - - registerFeature(new Fallout4ScriptExtender(this)); - registerFeature(new Fallout4DataArchives(myGamesPath())); - registerFeature(new GamebryoLocalSavegames(myGamesPath(), "Fallout4.ini")); - registerFeature(new Fallout4SaveGameInfo(this)); - registerFeature(new Fallout4GamePlugins(moInfo)); - registerFeature(new Fallout4UnmangedMods(this)); - - return true; -} - -QString GameFallout4::gameName() const -{ - return "Fallout 4"; -} - -QList GameFallout4::executables() const -{ - return QList() - << ExecutableInfo("F4SE", findInGameFolder(feature()->loaderName())) - << ExecutableInfo("Fallout 4", findInGameFolder(binaryName())) - << ExecutableInfo("Fallout Launcher", findInGameFolder(getLauncherName())) - << ExecutableInfo("Creation Kit", findInGameFolder("CreationKit.exe")) - << ExecutableInfo("LOOT", getLootPath()).withArgument("--game=\"Fallout4\"") - ; -} - -QString GameFallout4::name() const -{ - return "Fallout4 Support Plugin"; -} - -QString GameFallout4::author() const -{ - return "Tannin"; -} - -QString GameFallout4::description() const -{ - return tr("Adds support for the game Fallout 4.\n" - "Splash by %1").arg("nekoyoubi"); -} - -MOBase::VersionInfo GameFallout4::version() const -{ - return VersionInfo(0, 3, 0, VersionInfo::RELEASE_BETA); -} - -bool GameFallout4::isActive() const -{ - return qApp->property("managed_game").value() == this; -} - -QList GameFallout4::settings() const -{ - return QList(); -} - -void GameFallout4::initializeProfile(const QDir &path, ProfileSettings settings) const -{ - if (settings.testFlag(IPluginGame::MODS)) { - copyToProfile(localAppFolder() + "/Fallout4", path, "plugins.txt"); - copyToProfile(localAppFolder() + "/Fallout4", path, "loadorder.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 GameFallout4::savegameExtension() const -{ - return "fos"; -} - -QString GameFallout4::savegameSEExtension() const -{ - return "f4se"; -} - -QString GameFallout4::steamAPPId() const -{ - return "377160"; -} - -QStringList GameFallout4::primaryPlugins() const { - QStringList plugins = {"fallout4.esm", "dlcrobot.esm", "dlcworkshop01.esm", "dlccoast.esm", "dlcworkshop02.esm", - "dlcworkshop03.esm", "dlcnukaworld.esm"}; - - plugins.append(CCPlugins()); - - return plugins; -} - -QStringList GameFallout4::gameVariants() const -{ - return { "Regular" }; -} - -QString GameFallout4::gameShortName() const -{ - return "Fallout4"; -} - -QString GameFallout4::gameNexusName() const -{ - return "Fallout4"; -} - -QStringList GameFallout4::iniFiles() const -{ - return { "fallout4.ini", "fallout4prefs.ini", "fallout4custom.ini" }; -} - -QStringList GameFallout4::DLCPlugins() const -{ - return {"dlcrobot.esm", "dlcworkshop01.esm", "dlccoast.esm", "dlcworkshop02.esm", "dlcworkshop03.esm", - "dlcnukaworld.esm", "dlcultrahighresolution.esm"}; -} - -QStringList GameFallout4::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::LoadOrderMechanism GameFallout4::loadOrderMechanism() const -{ - return IPluginGame::LoadOrderMechanism::PluginsTxt; -} - -int GameFallout4::nexusModOrganizerID() const -{ - return 0; //... -} - -int GameFallout4::nexusGameID() const -{ - return 1151; -} diff --git a/src/games/fallout4vr/src/gamefallout4vr.cpp b/src/games/fallout4vr/src/gamefallout4vr.cpp new file mode 100644 index 00000000..256cb6fb --- /dev/null +++ b/src/games/fallout4vr/src/gamefallout4vr.cpp @@ -0,0 +1,218 @@ +#include "gameFallout4vr.h" + +#include "fallout4vrdataarchives.h" +#include "fallout4vrscriptextender.h" +#include "fallout4vrsavegameinfo.h" +#include "fallout4vrgameplugins.h" +#include "fallout4vrunmanagedmods.h" + +#include +#include "iplugingame.h" +#include +#include +#include +#include "versioninfo.h" + +#include +#include +#include +#include +#include +#include +#include + +#include + +#include "utility.h" +#include +#include +#include "scopeguard.h" + +using namespace MOBase; + +GameFallout4VR::GameFallout4VR() +{ +} + +bool GameFallout4VR::init(IOrganizer *moInfo) +{ + if (!GameGamebryo::init(moInfo)) { + return false; + } + + registerFeature(new Fallout4VRScriptExtender(this)); + registerFeature(new Fallout4VRDataArchives(myGamesPath())); + registerFeature(new GamebryoLocalSavegames(myGamesPath(), "fallout4custom.ini")); + registerFeature(new Fallout4VRSaveGameInfo(this)); + registerFeature(new Fallout4VRGamePlugins(moInfo)); + registerFeature(new Fallout4VRUnmangedMods(this)); + + return true; +} + +QString GameFallout4VR::gameName() const +{ + return "Fallout 4 VR"; +} + +QList GameFallout4VR::executables() const +{ + return QList() + << ExecutableInfo("F4SE", findInGameFolder(feature()->loaderName())) + << ExecutableInfo("Fallout 4 VR", findInGameFolder(binaryName())) + //<< ExecutableInfo("Fallout Launcher", findInGameFolder(getLauncherName())) // Fallout 4 VR does not have a launcher + << ExecutableInfo("Creation Kit", findInGameFolder("CreationKit.exe")) + << ExecutableInfo("LOOT", getLootPath()).withArgument("--game=\"Fallout4\"") + ; +} + +QString GameFallout4VR::name() const +{ + return "Fallout4VR Support Plugin"; +} + +QString GameFallout4VR::author() const +{ + return "Tannin"; +} + +QString GameFallout4VR::description() const +{ + return tr("Adds support for the game Fallout 4 VR.\n" + "Splash by %1").arg("nekoyoubi"); +} + +MOBase::VersionInfo GameFallout4VR::version() const +{ + return VersionInfo(0, 3, 0, VersionInfo::RELEASE_BETA); +} + +bool GameFallout4VR::isActive() const +{ + return qApp->property("managed_game").value() == this; +} + +QList GameFallout4VR::settings() const +{ + return QList(); +} + +void GameFallout4VR::initializeProfile(const QDir &path, ProfileSettings settings) const +{ + if (settings.testFlag(IPluginGame::MODS)) { + copyToProfile(localAppFolder() + "/Fallout4VR", path, "plugins.txt"); + copyToProfile(localAppFolder() + "/Fallout4VR", path, "loadorder.txt"); + } + + if (settings.testFlag(IPluginGame::CONFIGURATION)) { + /* + There is a fallout4.ini in the game installation directory, but it never get copied to "My Games/Fallout4VR". + The only files in the MyGames directory are fallout4custom.ini, fallout4prefs.ini and fallout4vrcustom.ini. + All settings you would expect in the fallout4.ini can be put into the fallout4custom.ini. + */ + /*if (settings.testFlag(IPluginGame::PREFER_DEFAULTS) + || !QFileInfo(myGamesPath() + "/fallout4.ini").exists()) { + copyToProfile(gameDirectory().absolutePath(), path, "fallout4.ini"); + } else { + copyToProfile(myGamesPath(), path, "fallout4.ini"); + }*/ + + copyToProfile(myGamesPath(), path, "fallout4custom.ini"); + copyToProfile(myGamesPath(), path, "fallout4prefs.ini"); + copyToProfile(myGamesPath(), path, "fallout4vrcustom.ini"); + } +} + +QString GameFallout4VR::savegameExtension() const +{ + return "fos"; +} + +QString GameFallout4VR::savegameSEExtension() const +{ + return "f4se"; +} + +QString GameFallout4VR::steamAPPId() const +{ + return "611660"; +} + +QStringList GameFallout4VR::primaryPlugins() const { + /*QStringList plugins = {"fallout4.esm", "fallout4_vr.esm", "dlcrobot.esm", "dlcworkshop01.esm", "dlccoast.esm", "dlcworkshop02.esm", + "dlcworkshop03.esm", "dlcnukaworld.esm"};*/ + // Fallout 4 VR does not support the DLCs, so we need to tread them as unmanaged plugins. + QStringList plugins = {"fallout4.esm", "fallout4_vr.esm"}; + + plugins.append(CCPlugins()); + + return plugins; +} + +QStringList GameFallout4VR::gameVariants() const +{ + return { "Regular" }; +} + +QString GameFallout4VR::gameShortName() const +{ + return "Fallout4VR"; +} + +QString GameFallout4VR::gameNexusName() const +{ + return "Fallout4"; +} + +QStringList GameFallout4VR::iniFiles() const +{ + return { "fallout4prefs.ini", "fallout4custom.ini", "fallout4vrcustom.ini" }; +} + +QStringList GameFallout4VR::DLCPlugins() const +{ + return {"dlcrobot.esm", "dlcworkshop01.esm", "dlccoast.esm", "dlcworkshop02.esm", "dlcworkshop03.esm", + "dlcnukaworld.esm", "dlcultrahighresolution.esm"}; +} + +QStringList GameFallout4VR::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::LoadOrderMechanism GameFallout4VR::loadOrderMechanism() const +{ + return IPluginGame::LoadOrderMechanism::PluginsTxt; +} + +int GameFallout4VR::nexusModOrganizerID() const +{ + return 0; //... +} + +int GameFallout4VR::nexusGameID() const +{ + return 1151; +} diff --git a/src/games/fallout4vr/src/gamefallout4.h b/src/games/fallout4vr/src/gamefallout4vr.h similarity index 86% rename from src/games/fallout4vr/src/gamefallout4.h rename to src/games/fallout4vr/src/gamefallout4vr.h index 60cbf083..60383c4a 100644 --- a/src/games/fallout4vr/src/gamefallout4.h +++ b/src/games/fallout4vr/src/gamefallout4vr.h @@ -1,5 +1,5 @@ -#ifndef GAMEFALLOUT4_H -#define GAMEFALLOUT4_H +#ifndef GAMEFALLOUT4VR_H +#define GAMEFALLOUT4VR_H #include "gamegamebryo.h" @@ -7,15 +7,15 @@ #include #include -class GameFallout4 : public GameGamebryo +class GameFallout4VR : public GameGamebryo { Q_OBJECT - Q_PLUGIN_METADATA(IID "org.tannin.GameFallout4" FILE "gamefallout4.json") + Q_PLUGIN_METADATA(IID "org.tannin.GameFallout4VR" FILE "gamefallout4vr.json") public: - GameFallout4(); + GameFallout4VR(); virtual bool init(MOBase::IOrganizer *moInfo) override; @@ -49,4 +49,4 @@ public: // IPlugin interface }; -#endif // GAMEFallout4_H +#endif // GAMEFallout4VR_H diff --git a/src/games/fallout4vr/src/gamefallout4.json b/src/games/fallout4vr/src/gamefallout4vr.json similarity index 100% rename from src/games/fallout4vr/src/gamefallout4.json rename to src/games/fallout4vr/src/gamefallout4vr.json From 52c06920822be1b3155b751a2abaf02803c3802d Mon Sep 17 00:00:00 2001 From: matzman666 Date: Sat, 6 Jan 2018 18:42:27 +0100 Subject: [PATCH 0417/1544] [game_fallout4vr] Overwrote getLauncherName() to return the binary name to fix the absent launcher problem. --- src/games/fallout4vr/src/gamefallout4vr.cpp | 5 +++++ src/games/fallout4vr/src/gamefallout4vr.h | 1 + 2 files changed, 6 insertions(+) diff --git a/src/games/fallout4vr/src/gamefallout4vr.cpp b/src/games/fallout4vr/src/gamefallout4vr.cpp index 256cb6fb..557bcfe8 100644 --- a/src/games/fallout4vr/src/gamefallout4vr.cpp +++ b/src/games/fallout4vr/src/gamefallout4vr.cpp @@ -216,3 +216,8 @@ int GameFallout4VR::nexusGameID() const { return 1151; } + +QString GameFallout4VR::getLauncherName() const +{ + return binaryName(); // Fallout 4 VR has no Launcher, so we just return the name of the game binary +} diff --git a/src/games/fallout4vr/src/gamefallout4vr.h b/src/games/fallout4vr/src/gamefallout4vr.h index 60383c4a..fd1b61fc 100644 --- a/src/games/fallout4vr/src/gamefallout4vr.h +++ b/src/games/fallout4vr/src/gamefallout4vr.h @@ -37,6 +37,7 @@ public: // IPluginGame interface virtual LoadOrderMechanism loadOrderMechanism() const override; virtual int nexusModOrganizerID() const override; virtual int nexusGameID() const override; + virtual QString getLauncherName() const override; public: // IPlugin interface From fa14efc5314025ca0ef052ece45eb658426c26ca Mon Sep 17 00:00:00 2001 From: matzman666 Date: Sat, 6 Jan 2018 19:10:35 +0100 Subject: [PATCH 0418/1544] [game_fallout4vr] Got auto-detection of existing Fallout 4 VR installation working. --- .../fallout4vr/src/game_fallout4vr_en.ts | 12 ++++- src/games/fallout4vr/src/gamefallout4vr.cpp | 53 +++++++++++++++++++ src/games/fallout4vr/src/gamefallout4vr.h | 4 ++ 3 files changed, 68 insertions(+), 1 deletion(-) diff --git a/src/games/fallout4vr/src/game_fallout4vr_en.ts b/src/games/fallout4vr/src/game_fallout4vr_en.ts index 01e5ca6c..326872d3 100644 --- a/src/games/fallout4vr/src/game_fallout4vr_en.ts +++ b/src/games/fallout4vr/src/game_fallout4vr_en.ts @@ -4,7 +4,7 @@ GameFallout4VR - + Adds support for the game Fallout 4 VR. Splash by %1 @@ -17,5 +17,15 @@ Splash by %1 Some of your plugins have invalid names! These plugins can not be loaded by the game. Please see mo_interface.log for a list of affected plugins and rename them. + + + failed to query registry path (preflight): %1 + + + + + failed to query registry path (read): %1 + + diff --git a/src/games/fallout4vr/src/gamefallout4vr.cpp b/src/games/fallout4vr/src/gamefallout4vr.cpp index 557bcfe8..c7a93bc1 100644 --- a/src/games/fallout4vr/src/gamefallout4vr.cpp +++ b/src/games/fallout4vr/src/gamefallout4vr.cpp @@ -30,6 +30,47 @@ using namespace MOBase; + +// Need to duplicate code from gamegamebryo.cpp here since it's otherwise unaccessible. +namespace { + +std::unique_ptr getRegValue(HKEY key, LPCWSTR path, LPCWSTR value, + DWORD flags, LPDWORD type = nullptr) +{ + DWORD size = 0; + HKEY subKey; + LONG res = ::RegOpenKeyExW(key, path, 0, + KEY_QUERY_VALUE | KEY_WOW64_32KEY, &subKey); + if (res != ERROR_SUCCESS) { + return std::unique_ptr(); + } + res = ::RegGetValueW(subKey, L"", value, flags, type, nullptr, &size); + if (res == ERROR_FILE_NOT_FOUND || res == ERROR_UNSUPPORTED_TYPE) { + return std::unique_ptr(); + } + if (res != ERROR_SUCCESS && res != ERROR_MORE_DATA) { + throw MOBase::MyException(QObject::tr("failed to query registry path (preflight): %1").arg(res, 0, 16)); + } + + std::unique_ptr result(new BYTE[size]); + res = ::RegGetValueW(subKey, L"", value, flags, type, result.get(), &size); + + if (res != ERROR_SUCCESS) { + throw MOBase::MyException(QObject::tr("failed to query registry path (read): %1").arg(res, 0, 16)); + } + + return result; +} + +QString findInRegistry(HKEY baseKey, LPCWSTR path, LPCWSTR value) +{ + std::unique_ptr buffer = getRegValue(baseKey, path, value, RRF_RT_REG_SZ | RRF_NOEXPAND); + + return QString::fromUtf16(reinterpret_cast(buffer.get())); +} + +} + GameFallout4VR::GameFallout4VR() { } @@ -40,6 +81,11 @@ bool GameFallout4VR::init(IOrganizer *moInfo) return false; } + // GameGamebryo::init() searches for the wrong registry key when setting the game path, + // and we cannot just override it because the corresponding code is in a private non-virtual function. + // So we need to set the correct path AFTER we have called GameGamebryo::init(). + setGamePath(identifyGamePathVR()); + registerFeature(new Fallout4VRScriptExtender(this)); registerFeature(new Fallout4VRDataArchives(myGamesPath())); registerFeature(new GamebryoLocalSavegames(myGamesPath(), "fallout4custom.ini")); @@ -221,3 +267,10 @@ QString GameFallout4VR::getLauncherName() const { return binaryName(); // Fallout 4 VR has no Launcher, so we just return the name of the game binary } + +QString GameFallout4VR::identifyGamePathVR() const +{ + // In every other Bethesda game they use gameShortName() as registry key, but for Fallout 4 VR they use gameName() + QString path = "Software\\Bethesda Softworks\\" + gameName(); + return findInRegistry(HKEY_LOCAL_MACHINE, path.toStdWString().c_str(), L"Installed Path"); +} diff --git a/src/games/fallout4vr/src/gamefallout4vr.h b/src/games/fallout4vr/src/gamefallout4vr.h index fd1b61fc..12a6056d 100644 --- a/src/games/fallout4vr/src/gamefallout4vr.h +++ b/src/games/fallout4vr/src/gamefallout4vr.h @@ -48,6 +48,10 @@ public: // IPlugin interface virtual bool isActive() const override; virtual QList settings() const override; +private: + + QString identifyGamePathVR() const; + }; #endif // GAMEFallout4VR_H From 93fb1cccd1094e09ee6963af71ec222147fa2bb1 Mon Sep 17 00:00:00 2001 From: Al12rs Date: Thu, 1 Feb 2018 13:23:59 +0100 Subject: [PATCH 0419/1544] [game_falloutnv] Added support for the INI files custom.ini and falloutcustom.ini. --- src/games/falloutnv/src/gamefalloutnv.cpp | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/src/games/falloutnv/src/gamefalloutnv.cpp b/src/games/falloutnv/src/gamefalloutnv.cpp index 277b13dc..af841dac 100644 --- a/src/games/falloutnv/src/gamefalloutnv.cpp +++ b/src/games/falloutnv/src/gamefalloutnv.cpp @@ -107,6 +107,8 @@ void GameFalloutNV::initializeProfile(const QDir &path, ProfileSettings settings } copyToProfile(myGamesPath(), path, "falloutprefs.ini"); + copyToProfile(myGamesPath(), path, "falloutcustom.ini"); + copyToProfile(myGamesPath(), path, "custom.ini"); } } @@ -142,7 +144,7 @@ QString GameFalloutNV::gameNexusName() const QStringList GameFalloutNV::iniFiles() const { - return { "fallout.ini", "falloutprefs.ini" }; + return { "fallout.ini", "falloutprefs.ini", "falloutcustom.ini", "custom.ini"}; } QStringList GameFalloutNV::DLCPlugins() const From 08ba70ed835a49bb674fb113e5667a8842c7c97a Mon Sep 17 00:00:00 2001 From: Al12rs Date: Thu, 1 Feb 2018 13:24:52 +0100 Subject: [PATCH 0420/1544] [game_fallout3] Added support for the INI file custom.ini --- src/games/fallout3/src/gamefallout3.cpp | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/src/games/fallout3/src/gamefallout3.cpp b/src/games/fallout3/src/gamefallout3.cpp index a685920f..47d8b7cc 100644 --- a/src/games/fallout3/src/gamefallout3.cpp +++ b/src/games/fallout3/src/gamefallout3.cpp @@ -107,6 +107,7 @@ void GameFallout3::initializeProfile(const QDir &path, ProfileSettings settings) } copyToProfile(myGamesPath(), path, "falloutprefs.ini"); + copyToProfile(myGamesPath(), path, "custom.ini"); } } @@ -153,7 +154,7 @@ QString GameFallout3::gameNexusName() const QStringList GameFallout3::iniFiles() const { - return { "fallout.ini", "falloutprefs.ini" }; + return { "fallout.ini", "falloutprefs.ini", "custom.ini" }; } QStringList GameFallout3::DLCPlugins() const From 52a9387b20313018092406a45f422008b50da2a3 Mon Sep 17 00:00:00 2001 From: Schilduin Date: Thu, 22 Feb 2018 00:00:48 +0100 Subject: [PATCH 0421/1544] [game_morrowind] First commit --- src/games/morrowind/src/SConscript | 15 ++ src/games/morrowind/src/gamemorrowind.cpp | 221 ++++++++++++++++++++++ src/games/morrowind/src/gamemorrowind.h | 51 +++++ 3 files changed, 287 insertions(+) create mode 100644 src/games/morrowind/src/SConscript create mode 100644 src/games/morrowind/src/gamemorrowind.cpp create mode 100644 src/games/morrowind/src/gamemorrowind.h diff --git a/src/games/morrowind/src/SConscript b/src/games/morrowind/src/SConscript new file mode 100644 index 00000000..a4136841 --- /dev/null +++ b/src/games/morrowind/src/SConscript @@ -0,0 +1,15 @@ +Import('qt_env') + +env = qt_env.Clone() + +env.AppendUnique(CPPDEFINES = [ 'GAMEMORROWIND_LIBRARY' ]) + +env.RequiresGamebryo() + +env.AppendUnique(LIBS = [ 'Version' ]) + +lib = env.SharedLibrary('gameMorrowind', env.Glob('*.cpp')) +env.InstallModule(lib) + +res = env['QT_USED_MODULES'] +Return('res') diff --git a/src/games/morrowind/src/gamemorrowind.cpp b/src/games/morrowind/src/gamemorrowind.cpp new file mode 100644 index 00000000..c1f58c87 --- /dev/null +++ b/src/games/morrowind/src/gamemorrowind.cpp @@ -0,0 +1,221 @@ +#include "gamemorrowind.h" + +//#include "skyrimbsainvalidation.h" +//#include "skyrimscriptextender.h" +//#include "skyrimdataarchives.h" +//#include "skyrimsavegameinfo.h" + +#include "executableinfo.h" +#include "pluginsetting.h" + +#include +#include +#include + +#include +#include +#include + +#include + +#include +#include + +#include +#include +#include +#include +#include + +using namespace MOBase; + +GameMorrowind::GameMorrowind() +{ +} + +bool GameMorrowind::init(IOrganizer *moInfo) +{ + if (!GameGamebryo::init(moInfo)) { + return false; + } + //registerFeature(new SkyrimScriptExtender(this)); + //registerFeature(new SkyrimDataArchives(myGamesPath())); + //registerFeature(new SkyrimBSAInvalidation(feature(), this)); + //registerFeature(new SkyrimSaveGameInfo(this)); + //registerFeature(new GamebryoLocalSavegames(myGamesPath(), "skyrim.ini")); + //registerFeature(new GamebryoGamePlugins(moInfo)); + //registerFeature(new GamebryoUnmangedMods(this)); + return true; +} + +QString GameMorrowind::gameName() const +{ + return "Morrowind"; +} + +QDir GameMorrowind::dataDirectory() const +{ + return gameDirectory().absoluteFilePath("Data Files"); +} + +QDir GameMorrowind::documentsDirectory() const +{ + return gameDirectory(); +} + +QList GameMorrowind::executables() const +{ + return QList() + // << ExecutableInfo("SKSE", findInGameFolder(feature()->loaderName())) + // << ExecutableInfo("SBW", findInGameFolder("SBW.exe")) + << ExecutableInfo("Morrowind", findInGameFolder(binaryName())) + << ExecutableInfo("Morrowind Launcher", findInGameFolder(getLauncherName())) + // << ExecutableInfo("BOSS", findInGameFolder("BOSS/BOSS.exe")) + // << ExecutableInfo("LOOT", getLootPath()).withArgument("--game=\"Skyrim\"") + // << ExecutableInfo("Creation Kit", findInGameFolder("CreationKit.exe")).withSteamAppId("202480") + ; +} + +QString GameMorrowind::name() const +{ + return "Morrowind Support Plugin"; +} + +QString GameMorrowind::author() const +{ + return "Schilduin"; +} + +QString GameMorrowind::description() const +{ + return tr("Adds support for the game Morrowind"); +} + +MOBase::VersionInfo GameMorrowind::version() const +{ + return VersionInfo(1, 0, 0, VersionInfo::RELEASE_FINAL); +} + +bool GameMorrowind::isActive() const +{ + return qApp->property("managed_game").value() == this; +} + +QList GameMorrowind::settings() const +{ + return QList(); +} + +void GameMorrowind::initializeProfile(const QDir &path, ProfileSettings settings) const +{ + if (settings.testFlag(IPluginGame::MODS)) { + copyToProfile(localAppFolder() + "/Morrowind", path, "plugins.txt"); + copyToProfile(localAppFolder() + "/Morrowind", path, "loadorder.txt"); + } + + if (settings.testFlag(IPluginGame::CONFIGURATION)) { + if (settings.testFlag(IPluginGame::PREFER_DEFAULTS) + || !QFileInfo(myGamesPath() + "/Morrowind.ini").exists()) { + copyToProfile(gameDirectory().absolutePath(), path, "Morrowind.ini"); + } else { + copyToProfile(myGamesPath(), path, "Morrowind.ini"); + } + } +} + +QString GameMorrowind::savegameExtension() const +{ + return "ess"; +} + +QString GameMorrowind::steamAPPId() const +{ + return "22320"; +} + +QStringList GameMorrowind::primaryPlugins() const +{ + return { "Morrowind.esm" }; +} + +QString GameMorrowind::gameShortName() const +{ + return "Morrowind"; +} + +QString GameMorrowind::getLauncherName() const +{ + return "Morrowind Launcher.exe"; +} + +QString GameMorrowind::gameNexusName() const +{ + return "Morrowind"; +} + + +QStringList GameMorrowind::iniFiles() const +{ + return { "Morrowind.ini" }; +} + +QStringList GameMorrowind::DLCPlugins() const +{ + return { "Tribunal.esm", "Bloodmoon.esm" }; +} + +namespace { +//Note: This is ripped off from shared/util. And in an upcoming move, the fomod +//installer requires something similar. I suspect I should abstract this out +//into gamebryo (or lower level) + +VS_FIXEDFILEINFO GetFileVersion(const std::wstring &fileName) +{ + DWORD handle = 0UL; + DWORD size = ::GetFileVersionInfoSizeW(fileName.c_str(), &handle); + if (size == 0) { + throw std::runtime_error("failed to determine file version info size"); + } + + std::vector buffer(size); + handle = 0UL; + if (!::GetFileVersionInfoW(fileName.c_str(), handle, size, buffer.data())) { + throw std::runtime_error("failed to determine file version info"); + } + + void *versionInfoPtr = nullptr; + UINT versionInfoLength = 0; + if (!::VerQueryValue(buffer.data(), L"\\", &versionInfoPtr, &versionInfoLength)) { + throw std::runtime_error("failed to determine file version"); + } + + return *static_cast(versionInfoPtr); +} + +} + +IPluginGame::LoadOrderMechanism GameMorrowind::loadOrderMechanism() const +{ + try { + std::wstring fileName = gameDirectory().absoluteFilePath(binaryName()).toStdWString().c_str(); + VS_FIXEDFILEINFO versionInfo = ::GetFileVersion(fileName); + if ((versionInfo.dwFileVersionMS > 0x10004) || // version >= 1.5.x? + ((versionInfo.dwFileVersionMS == 0x10004) && (versionInfo.dwFileVersionLS >= 0x1A0000))) { // version >= ?.4.26 + return LoadOrderMechanism::PluginsTxt; + } + } catch (const std::exception &e) { + qCritical() << "Morrowind.exe is invalid: " << e.what(); + } + return LoadOrderMechanism::FileTime; +} + + +int GameMorrowind::nexusModOrganizerID() const +{ + return 1334; +} + +int GameMorrowind::nexusGameID() const +{ + return 100; +} diff --git a/src/games/morrowind/src/gamemorrowind.h b/src/games/morrowind/src/gamemorrowind.h new file mode 100644 index 00000000..792b9004 --- /dev/null +++ b/src/games/morrowind/src/gamemorrowind.h @@ -0,0 +1,51 @@ +#ifndef GAMEMORROWIND_H +#define GAMEMORROWIND_H + +#include "gamegamebryo.h" + +#include +#include + +class GameMorrowind : public GameGamebryo +{ + Q_OBJECT +#if QT_VERSION >= QT_VERSION_CHECK(5,0,0) + Q_PLUGIN_METADATA(IID "org.schilduin.GameMorrowind" FILE "gamemorrowind.json") +#endif + +public: + + GameMorrowind(); + + virtual bool init(MOBase::IOrganizer *moInfo) override; + +public: // IPluginGame interface + + virtual QString gameName() const override; + virtual QDir dataDirectory() const override; + virtual QDir documentsDirectory() const override; + virtual QList executables() const override; + virtual void initializeProfile(const QDir &path, ProfileSettings settings) const override; + virtual QString savegameExtension() const override; + virtual QString steamAPPId() const override; + virtual QStringList primaryPlugins() const override; + virtual QString gameShortName() const override; + virtual QString getLauncherName() const override; + virtual QString gameNexusName() const override; + virtual QStringList iniFiles() const override; + virtual QStringList DLCPlugins() const override; + virtual LoadOrderMechanism loadOrderMechanism() const override; + virtual int nexusModOrganizerID() const override; + virtual int nexusGameID() const override; + +public: // IPlugin interface + + virtual QString name() const; + virtual QString author() const; + virtual QString description() const; + virtual MOBase::VersionInfo version() const; + virtual bool isActive() const; + virtual QList settings() const; +}; + +#endif // GAMEMORROWIND_H From cdab0399a2633464d70332bb22cecdec17c6703b Mon Sep 17 00:00:00 2001 From: Schilduin Date: Thu, 22 Feb 2018 00:37:41 +0100 Subject: [PATCH 0422/1544] [game_morrowind] Added core files --- src/games/morrowind/src/CMakeLists.txt | 66 ++++++++++++++++++++++ src/games/morrowind/src/gameMorrowind.pro | 39 +++++++++++++ src/games/morrowind/src/gamemorrowind.cpp | 7 ++- src/games/morrowind/src/gamemorrowind.h | 1 + src/games/morrowind/src/gamemorrowind.json | 1 + 5 files changed, 113 insertions(+), 1 deletion(-) create mode 100644 src/games/morrowind/src/CMakeLists.txt create mode 100644 src/games/morrowind/src/gameMorrowind.pro create mode 100644 src/games/morrowind/src/gamemorrowind.json diff --git a/src/games/morrowind/src/CMakeLists.txt b/src/games/morrowind/src/CMakeLists.txt new file mode 100644 index 00000000..0d84ace7 --- /dev/null +++ b/src/games/morrowind/src/CMakeLists.txt @@ -0,0 +1,66 @@ +CMAKE_MINIMUM_REQUIRED (VERSION 2.8) + +CMAKE_POLICY(SET CMP0020 NEW) + +FILE(GLOB ${PROJ_NAME}_SRCS *.cpp) +FILE(GLOB ${PROJ_NAME}_HDRS *.h) +FILE(GLOB ${PROJ_NAME}_FORMS *.ui) + + +SET(CMAKE_INCLUDE_CURRENT_DIR ON) +SET(CMAKE_AUTOMOC ON) +SET(CMAKE_AUTOUIC ON) +FIND_PACKAGE(Qt5Widgets REQUIRED) +QT5_WRAP_UI(${PROJ_NAME}_UIHDRS ${${PROJ_NAME}_FORMS}) + +SET(Boost_USE_STATIC_LIBS ON) +SET(Boost_USE_MULTITHREADED ON) +SET(Boost_USE_STATIC_RUNTIME OFF) +FIND_PACKAGE(Boost) + +IF (Boost_FOUND) + INCLUDE_DIRECTORIES(${Boost_INCLUDE_DIRS}) +ENDIF (Boost_FOUND) + +SET(default_project_path "${CMAKE_SOURCE_DIR}/..") +GET_FILENAME_COMPONENT(${default_project_path} ${default_project_path} REALPATH) + +SET(project_path "${default_project_path}" CACHE PATH "path to the other mo projects") +SET(lib_path "${project_path}/../../install/libs") +SET(plugin_path "${project_path}") + + +INCLUDE_DIRECTORIES(${project_path}/uibase/src + ${project_path}/game_features/src + ${project_path}/../lz4/include) +LINK_DIRECTORIES(${lib_path} + ${project_path}/../lz4/dll) + +ADD_LIBRARY(${PROJ_NAME} STATIC ${${PROJ_NAME}_HDRS} ${${PROJ_NAME}_SRCS} ${${PROJ_NAME}_UIHDRS}) +TARGET_LINK_LIBRARIES(${PROJ_NAME} + Qt5::Widgets + ${Boost_LIBRARIES} + uibase + liblz4 + Version) + +IF(MSVC) + SET_TARGET_PROPERTIES(${PROJ_NAME} PROPERTIES LINK_FLAGS "/LARGEADDRESSAWARE") +ELSE(MSVC) + SET_TARGET_PROPERTIES(${PROJ_NAME} PROPERTIES LINK_FLAGS "-std=c++11") +ENDIF(MSVC) + +IF (NOT "${OPTIMIZE_COMPILE_FLAGS}" STREQUAL "") + SET_TARGET_PROPERTIES(${PROJ_NAME} PROPERTIES COMPILE_FLAGS_RELWITHDEBINFO ${OPTIMIZE_COMPILE_FLAGS}) +ENDIF() +IF (NOT "${OPTIMIZE_LINK_FLAGS}" STREQUAL "") + SET_TARGET_PROPERTIES(${PROJ_NAME} PROPERTIES LINK_FLAGS_RELWITHDEBINFO ${OPTIMIZE_LINK_FLAGS}) +ENDIF() + +QT5_USE_MODULES(${PROJ_NAME} Widgets) + +############### +## Installation + +INSTALL(TARGETS ${PROJ_NAME} + ARCHIVE DESTINATION libs) diff --git a/src/games/morrowind/src/gameMorrowind.pro b/src/games/morrowind/src/gameMorrowind.pro new file mode 100644 index 00000000..4c5c5973 --- /dev/null +++ b/src/games/morrowind/src/gameMorrowind.pro @@ -0,0 +1,39 @@ +#------------------------------------------------- +# +# Project created by QtCreator 2014-11-15T15:36:33 +# +#------------------------------------------------- + + +TARGET = gameMorrowind +TEMPLATE = lib + +CONFIG += plugins +CONFIG += dll +DEFINES += GAMESKYRIM_LIBRARY + +SOURCES += gamemorrowind.cpp \ + +HEADERS += gamemorrowind.h \ + +CONFIG(debug, debug|release) { + LIBS += -L"$${OUT_PWD}/../gameGamebryo/debug" + PRE_TARGETDEPS += \ + $$OUT_PWD/../gameGamebryo/debug/gameGamebryo.lib +} else { + LIBS += -L"$${OUT_PWD}/../gameGamebryo/release" + PRE_TARGETDEPS += \ + $$OUT_PWD/../gameGamebryo/release/gameGamebryo.lib +} + +include(../plugin_template.pri) + +INCLUDEPATH += "$${BOOSTPATH}" "$${PWD}/../gamefeatures" "$${PWD}/../gamegamebryo" + +LIBS += -ladvapi32 -lole32 -lgameGamebryo + +OTHER_FILES += \ + gamemorrowind.json\ + SConscript \ + CMakeLists.txt + diff --git a/src/games/morrowind/src/gamemorrowind.cpp b/src/games/morrowind/src/gamemorrowind.cpp index c1f58c87..42a629c0 100644 --- a/src/games/morrowind/src/gamemorrowind.cpp +++ b/src/games/morrowind/src/gamemorrowind.cpp @@ -60,7 +60,12 @@ QDir GameMorrowind::dataDirectory() const QDir GameMorrowind::documentsDirectory() const { - return gameDirectory(); + return gameDirectory().absolutePath(); +} + +QDir GameMorrowind::savesDirectory() const +{ + return gameDirectory().absoluteFilePath("Saves"); } QList GameMorrowind::executables() const diff --git a/src/games/morrowind/src/gamemorrowind.h b/src/games/morrowind/src/gamemorrowind.h index 792b9004..4a817a15 100644 --- a/src/games/morrowind/src/gamemorrowind.h +++ b/src/games/morrowind/src/gamemorrowind.h @@ -24,6 +24,7 @@ public: // IPluginGame interface virtual QString gameName() const override; virtual QDir dataDirectory() const override; virtual QDir documentsDirectory() const override; + virtual QDir savesDirectory() const override; virtual QList executables() const override; virtual void initializeProfile(const QDir &path, ProfileSettings settings) const override; virtual QString savegameExtension() const override; diff --git a/src/games/morrowind/src/gamemorrowind.json b/src/games/morrowind/src/gamemorrowind.json new file mode 100644 index 00000000..0967ef42 --- /dev/null +++ b/src/games/morrowind/src/gamemorrowind.json @@ -0,0 +1 @@ +{} From ba0511fee0f412f7cbc825d23f36710dfb4ae92c Mon Sep 17 00:00:00 2001 From: Schilduin Date: Thu, 22 Feb 2018 00:42:26 +0100 Subject: [PATCH 0423/1544] [game_morrowind] added CMakeList --- src/games/morrowind/CMakeLists.txt | 16 ++++++++++++++++ 1 file changed, 16 insertions(+) create mode 100644 src/games/morrowind/CMakeLists.txt diff --git a/src/games/morrowind/CMakeLists.txt b/src/games/morrowind/CMakeLists.txt new file mode 100644 index 00000000..5f62ad07 --- /dev/null +++ b/src/games/morrowind/CMakeLists.txt @@ -0,0 +1,16 @@ +CMAKE_MINIMUM_REQUIRED(VERSION 2.8) + +SET(PROJ_NAME game_morrowind) + +PROJECT(${PROJ_NAME}) + +SET(DEPENDENCIES_DIR CACHE PATH "") + +# hint to find qt in dependencies path +LIST(APPEND CMAKE_PREFIX_PATH ${QT_ROOT}/lib/cmake) +LIST(APPEND CMAKE_PREFIX_PATH ${DEPENDENCIES_DIR}/lz4/dll) + +FILE(GLOB_RECURSE BOOST_ROOT ${DEPENDENCIES_DIR}/boost*/project-config.jam) +GET_FILENAME_COMPONENT(BOOST_ROOT ${BOOST_ROOT} DIRECTORY) + +ADD_SUBDIRECTORY(src) From 0f327e234272116b27ead18730ae3ea4813d5832 Mon Sep 17 00:00:00 2001 From: Schilduin Date: Thu, 22 Feb 2018 00:42:26 +0100 Subject: [PATCH 0424/1544] [game_morrowind] updated CMakeLists --- src/games/morrowind/CMakeLists.txt | 16 ++++++++++++++ src/games/morrowind/src/CMakeLists.txt | 26 ++++++++++++++--------- src/games/morrowind/src/gameMorrowind.pro | 6 +++--- 3 files changed, 35 insertions(+), 13 deletions(-) create mode 100644 src/games/morrowind/CMakeLists.txt diff --git a/src/games/morrowind/CMakeLists.txt b/src/games/morrowind/CMakeLists.txt new file mode 100644 index 00000000..5f62ad07 --- /dev/null +++ b/src/games/morrowind/CMakeLists.txt @@ -0,0 +1,16 @@ +CMAKE_MINIMUM_REQUIRED(VERSION 2.8) + +SET(PROJ_NAME game_morrowind) + +PROJECT(${PROJ_NAME}) + +SET(DEPENDENCIES_DIR CACHE PATH "") + +# hint to find qt in dependencies path +LIST(APPEND CMAKE_PREFIX_PATH ${QT_ROOT}/lib/cmake) +LIST(APPEND CMAKE_PREFIX_PATH ${DEPENDENCIES_DIR}/lz4/dll) + +FILE(GLOB_RECURSE BOOST_ROOT ${DEPENDENCIES_DIR}/boost*/project-config.jam) +GET_FILENAME_COMPONENT(BOOST_ROOT ${BOOST_ROOT} DIRECTORY) + +ADD_SUBDIRECTORY(src) diff --git a/src/games/morrowind/src/CMakeLists.txt b/src/games/morrowind/src/CMakeLists.txt index 0d84ace7..6f9c4c67 100644 --- a/src/games/morrowind/src/CMakeLists.txt +++ b/src/games/morrowind/src/CMakeLists.txt @@ -1,4 +1,4 @@ -CMAKE_MINIMUM_REQUIRED (VERSION 2.8) +CMAKE_MINIMUM_REQUIRED (VERSION 1.8) CMAKE_POLICY(SET CMP0020 NEW) @@ -12,6 +12,8 @@ SET(CMAKE_AUTOMOC ON) SET(CMAKE_AUTOUIC ON) FIND_PACKAGE(Qt5Widgets REQUIRED) QT5_WRAP_UI(${PROJ_NAME}_UIHDRS ${${PROJ_NAME}_FORMS}) +FIND_PACKAGE(Qt5LinguistTools) +QT5_CREATE_TRANSLATION(${PROJ_NAME}_translations_qm ${CMAKE_SOURCE_DIR}/src ${CMAKE_SOURCE_DIR}/src/${PROJ_NAME}_en.ts) SET(Boost_USE_STATIC_LIBS ON) SET(Boost_USE_MULTITHREADED ON) @@ -20,29 +22,32 @@ FIND_PACKAGE(Boost) IF (Boost_FOUND) INCLUDE_DIRECTORIES(${Boost_INCLUDE_DIRS}) -ENDIF (Boost_FOUND) +ENDIF () SET(default_project_path "${CMAKE_SOURCE_DIR}/..") GET_FILENAME_COMPONENT(${default_project_path} ${default_project_path} REALPATH) SET(project_path "${default_project_path}" CACHE PATH "path to the other mo projects") SET(lib_path "${project_path}/../../install/libs") -SET(plugin_path "${project_path}") - INCLUDE_DIRECTORIES(${project_path}/uibase/src ${project_path}/game_features/src - ${project_path}/../lz4/include) -LINK_DIRECTORIES(${lib_path} - ${project_path}/../lz4/dll) + ${project_path}/game_gamebryo/src) +LINK_DIRECTORIES(${project_path}/uibase/build/src + ${lib_path} + ${project_path}/../lz4/dll) -ADD_LIBRARY(${PROJ_NAME} STATIC ${${PROJ_NAME}_HDRS} ${${PROJ_NAME}_SRCS} ${${PROJ_NAME}_UIHDRS}) +ADD_DEFINITIONS(-DUNICODE -D_UNICODE) + +ADD_LIBRARY(${PROJ_NAME} SHARED ${${PROJ_NAME}_HDRS} ${${PROJ_NAME}_SRCS} ${${PROJ_NAME}_UIHDRS} ${${PROJ_NAME}_translations_qm}) TARGET_LINK_LIBRARIES(${PROJ_NAME} Qt5::Widgets ${Boost_LIBRARIES} + DbgHelp uibase + game_gamebryo liblz4 - Version) + version) IF(MSVC) SET_TARGET_PROPERTIES(${PROJ_NAME} PROPERTIES LINK_FLAGS "/LARGEADDRESSAWARE") @@ -63,4 +68,5 @@ QT5_USE_MODULES(${PROJ_NAME} Widgets) ## Installation INSTALL(TARGETS ${PROJ_NAME} - ARCHIVE DESTINATION libs) + RUNTIME DESTINATION bin/plugins) +INSTALL(FILES ${CMAKE_CURRENT_BINARY_DIR}/${PROJ_NAME}.pdb DESTINATION pdb) diff --git a/src/games/morrowind/src/gameMorrowind.pro b/src/games/morrowind/src/gameMorrowind.pro index 4c5c5973..305149b3 100644 --- a/src/games/morrowind/src/gameMorrowind.pro +++ b/src/games/morrowind/src/gameMorrowind.pro @@ -10,11 +10,11 @@ TEMPLATE = lib CONFIG += plugins CONFIG += dll -DEFINES += GAMESKYRIM_LIBRARY +DEFINES += GAMEMORROWIND_LIBRARY -SOURCES += gamemorrowind.cpp \ +SOURCES += gamemorrowind.cpp -HEADERS += gamemorrowind.h \ +HEADERS += gamemorrowind.h CONFIG(debug, debug|release) { LIBS += -L"$${OUT_PWD}/../gameGamebryo/debug" From 090394c944c99172bcb93323c4c0f33a9cd98304 Mon Sep 17 00:00:00 2001 From: Schilduin <36682523+Schilduin@users.noreply.github.com> Date: Thu, 22 Feb 2018 01:00:05 +0100 Subject: [PATCH 0425/1544] [game_morrowind] Update CMakeLists --- src/games/morrowind/src/CMakeLists.txt | 26 ++++++++++++++++---------- 1 file changed, 16 insertions(+), 10 deletions(-) diff --git a/src/games/morrowind/src/CMakeLists.txt b/src/games/morrowind/src/CMakeLists.txt index 0d84ace7..6f9c4c67 100644 --- a/src/games/morrowind/src/CMakeLists.txt +++ b/src/games/morrowind/src/CMakeLists.txt @@ -1,4 +1,4 @@ -CMAKE_MINIMUM_REQUIRED (VERSION 2.8) +CMAKE_MINIMUM_REQUIRED (VERSION 1.8) CMAKE_POLICY(SET CMP0020 NEW) @@ -12,6 +12,8 @@ SET(CMAKE_AUTOMOC ON) SET(CMAKE_AUTOUIC ON) FIND_PACKAGE(Qt5Widgets REQUIRED) QT5_WRAP_UI(${PROJ_NAME}_UIHDRS ${${PROJ_NAME}_FORMS}) +FIND_PACKAGE(Qt5LinguistTools) +QT5_CREATE_TRANSLATION(${PROJ_NAME}_translations_qm ${CMAKE_SOURCE_DIR}/src ${CMAKE_SOURCE_DIR}/src/${PROJ_NAME}_en.ts) SET(Boost_USE_STATIC_LIBS ON) SET(Boost_USE_MULTITHREADED ON) @@ -20,29 +22,32 @@ FIND_PACKAGE(Boost) IF (Boost_FOUND) INCLUDE_DIRECTORIES(${Boost_INCLUDE_DIRS}) -ENDIF (Boost_FOUND) +ENDIF () SET(default_project_path "${CMAKE_SOURCE_DIR}/..") GET_FILENAME_COMPONENT(${default_project_path} ${default_project_path} REALPATH) SET(project_path "${default_project_path}" CACHE PATH "path to the other mo projects") SET(lib_path "${project_path}/../../install/libs") -SET(plugin_path "${project_path}") - INCLUDE_DIRECTORIES(${project_path}/uibase/src ${project_path}/game_features/src - ${project_path}/../lz4/include) -LINK_DIRECTORIES(${lib_path} - ${project_path}/../lz4/dll) + ${project_path}/game_gamebryo/src) +LINK_DIRECTORIES(${project_path}/uibase/build/src + ${lib_path} + ${project_path}/../lz4/dll) -ADD_LIBRARY(${PROJ_NAME} STATIC ${${PROJ_NAME}_HDRS} ${${PROJ_NAME}_SRCS} ${${PROJ_NAME}_UIHDRS}) +ADD_DEFINITIONS(-DUNICODE -D_UNICODE) + +ADD_LIBRARY(${PROJ_NAME} SHARED ${${PROJ_NAME}_HDRS} ${${PROJ_NAME}_SRCS} ${${PROJ_NAME}_UIHDRS} ${${PROJ_NAME}_translations_qm}) TARGET_LINK_LIBRARIES(${PROJ_NAME} Qt5::Widgets ${Boost_LIBRARIES} + DbgHelp uibase + game_gamebryo liblz4 - Version) + version) IF(MSVC) SET_TARGET_PROPERTIES(${PROJ_NAME} PROPERTIES LINK_FLAGS "/LARGEADDRESSAWARE") @@ -63,4 +68,5 @@ QT5_USE_MODULES(${PROJ_NAME} Widgets) ## Installation INSTALL(TARGETS ${PROJ_NAME} - ARCHIVE DESTINATION libs) + RUNTIME DESTINATION bin/plugins) +INSTALL(FILES ${CMAKE_CURRENT_BINARY_DIR}/${PROJ_NAME}.pdb DESTINATION pdb) From dc19589d7c40f461dd7025de94608a3b191ed846 Mon Sep 17 00:00:00 2001 From: Schilduin Date: Thu, 22 Feb 2018 01:08:05 +0100 Subject: [PATCH 0426/1544] [game_morrowind] added missing SEExtension --- src/games/morrowind/src/gamemorrowind.cpp | 5 +++++ src/games/morrowind/src/gamemorrowind.h | 1 + 2 files changed, 6 insertions(+) diff --git a/src/games/morrowind/src/gamemorrowind.cpp b/src/games/morrowind/src/gamemorrowind.cpp index 42a629c0..90172c04 100644 --- a/src/games/morrowind/src/gamemorrowind.cpp +++ b/src/games/morrowind/src/gamemorrowind.cpp @@ -133,6 +133,11 @@ QString GameMorrowind::savegameExtension() const return "ess"; } +QString GameMorrowind::savegameSEExtension() const +{ + return "mwse"; +} + QString GameMorrowind::steamAPPId() const { return "22320"; diff --git a/src/games/morrowind/src/gamemorrowind.h b/src/games/morrowind/src/gamemorrowind.h index 4a817a15..a2a89ce1 100644 --- a/src/games/morrowind/src/gamemorrowind.h +++ b/src/games/morrowind/src/gamemorrowind.h @@ -28,6 +28,7 @@ public: // IPluginGame interface virtual QList executables() const override; virtual void initializeProfile(const QDir &path, ProfileSettings settings) const override; virtual QString savegameExtension() const override; + virtual QString savegameSEExtension() const override; virtual QString steamAPPId() const override; virtual QStringList primaryPlugins() const override; virtual QString gameShortName() const override; From 1d3885738170ba8ffb1a55ca827dc78ac5be8f67 Mon Sep 17 00:00:00 2001 From: Schilduin Date: Fri, 23 Feb 2018 23:05:43 +0100 Subject: [PATCH 0427/1544] [game_morrowind] First full version --- src/games/morrowind/.gitignore | 4 + src/games/morrowind/src/gameMorrowind.pro | 14 +- src/games/morrowind/src/game_morrowind_en.ts | 26 ++++ src/games/morrowind/src/gamemorrowind.cpp | 79 +++++----- src/games/morrowind/src/gamemorrowind.h | 8 +- .../morrowind/src/morrosindgameplugins.h | 29 ++++ .../src/morrowindbsainvalidation.cpp | 16 ++ .../morrowind/src/morrowindbsainvalidation.h | 23 +++ .../morrowind/src/morrowinddataarchives.cpp | 38 +++++ .../morrowind/src/morrowinddataarchives.h | 28 ++++ .../morrowind/src/morrowindgameplugins.cpp | 139 ++++++++++++++++++ src/games/morrowind/src/morrowindsavegame.cpp | 83 +++++++++++ src/games/morrowind/src/morrowindsavegame.h | 14 ++ .../morrowind/src/morrowindsavegameinfo.cpp | 19 +++ .../morrowind/src/morrowindsavegameinfo.h | 17 +++ .../morrowind/src/morrowindscriptextender.cpp | 24 +++ .../morrowind/src/morrowindscriptextender.h | 20 +++ 17 files changed, 529 insertions(+), 52 deletions(-) create mode 100644 src/games/morrowind/.gitignore create mode 100644 src/games/morrowind/src/game_morrowind_en.ts create mode 100644 src/games/morrowind/src/morrosindgameplugins.h create mode 100644 src/games/morrowind/src/morrowindbsainvalidation.cpp create mode 100644 src/games/morrowind/src/morrowindbsainvalidation.h create mode 100644 src/games/morrowind/src/morrowinddataarchives.cpp create mode 100644 src/games/morrowind/src/morrowinddataarchives.h create mode 100644 src/games/morrowind/src/morrowindgameplugins.cpp create mode 100644 src/games/morrowind/src/morrowindsavegame.cpp create mode 100644 src/games/morrowind/src/morrowindsavegame.h create mode 100644 src/games/morrowind/src/morrowindsavegameinfo.cpp create mode 100644 src/games/morrowind/src/morrowindsavegameinfo.h create mode 100644 src/games/morrowind/src/morrowindscriptextender.cpp create mode 100644 src/games/morrowind/src/morrowindscriptextender.h diff --git a/src/games/morrowind/.gitignore b/src/games/morrowind/.gitignore new file mode 100644 index 00000000..5ff13f91 --- /dev/null +++ b/src/games/morrowind/.gitignore @@ -0,0 +1,4 @@ +build +CMakeLists.txt.user +edit +std*.log diff --git a/src/games/morrowind/src/gameMorrowind.pro b/src/games/morrowind/src/gameMorrowind.pro index 305149b3..10d7e641 100644 --- a/src/games/morrowind/src/gameMorrowind.pro +++ b/src/games/morrowind/src/gameMorrowind.pro @@ -12,9 +12,19 @@ CONFIG += plugins CONFIG += dll DEFINES += GAMEMORROWIND_LIBRARY -SOURCES += gamemorrowind.cpp +SOURCES += gamemorrowind.cpp \ + morrowindbsainvalidation.cpp \ + morrowindscriptextender.cpp \ + morrowinddataarchives.cpp \ + morrowindsavegame.cpp \ + morrowindsavegameinfo.cpp -HEADERS += gamemorrowind.h +HEADERS += gamemorrowind.h \ + morrowindbsainvalidation.h \ + morrowindscriptextender.h \ + morrowinddataarchives.h \ + morrowindsavegame.h \ + morrowindsavegameinfo.h CONFIG(debug, debug|release) { LIBS += -L"$${OUT_PWD}/../gameGamebryo/debug" diff --git a/src/games/morrowind/src/game_morrowind_en.ts b/src/games/morrowind/src/game_morrowind_en.ts new file mode 100644 index 00000000..2c4358ec --- /dev/null +++ b/src/games/morrowind/src/game_morrowind_en.ts @@ -0,0 +1,26 @@ + + + + + GameMorrowind + + + Adds support for the game Morrowind + Adds support for the game Morrowind + + + + + QObject + + + failed to set game file key (errorcode %1) + + + + + Some of your plugins have invalid names! These plugins can not be loaded by the game. Please see mo_interface.log for a list of affected plugins and rename them. + + + + diff --git a/src/games/morrowind/src/gamemorrowind.cpp b/src/games/morrowind/src/gamemorrowind.cpp index 90172c04..ec1a440d 100644 --- a/src/games/morrowind/src/gamemorrowind.cpp +++ b/src/games/morrowind/src/gamemorrowind.cpp @@ -1,15 +1,15 @@ #include "gamemorrowind.h" -//#include "skyrimbsainvalidation.h" -//#include "skyrimscriptextender.h" -//#include "skyrimdataarchives.h" -//#include "skyrimsavegameinfo.h" +#include "morrowindbsainvalidation.h" +#include "morrowindscriptextender.h" +#include "morrowinddataarchives.h" +#include "morrowindsavegameinfo.h" +#include "morrowindgameplugins.h" #include "executableinfo.h" #include "pluginsetting.h" #include -#include #include #include @@ -38,13 +38,13 @@ bool GameMorrowind::init(IOrganizer *moInfo) if (!GameGamebryo::init(moInfo)) { return false; } - //registerFeature(new SkyrimScriptExtender(this)); - //registerFeature(new SkyrimDataArchives(myGamesPath())); - //registerFeature(new SkyrimBSAInvalidation(feature(), this)); - //registerFeature(new SkyrimSaveGameInfo(this)); - //registerFeature(new GamebryoLocalSavegames(myGamesPath(), "skyrim.ini")); - //registerFeature(new GamebryoGamePlugins(moInfo)); - //registerFeature(new GamebryoUnmangedMods(this)); + registerFeature(new MorrowindScriptExtender(this)); + registerFeature(new MorrowindDataArchives(myGamesPath())); + registerFeature(new MorrowindBSAInvalidation(feature(), this)); + registerFeature(new MorrowindSaveGameInfo(this)); + registerFeature(new GamebryoLocalSavegames(gameDirectory().absolutePath(), "morrowind.ini")); + registerFeature(new MorrowindGamePlugins(moInfo)); + registerFeature(new GamebryoUnmangedMods(this)); return true; } @@ -53,31 +53,33 @@ QString GameMorrowind::gameName() const return "Morrowind"; } +QString GameMorrowind::getLauncherName() const +{ + return "Morrowind Launcher.exe"; +} + QDir GameMorrowind::dataDirectory() const { return gameDirectory().absoluteFilePath("Data Files"); } -QDir GameMorrowind::documentsDirectory() const -{ - return gameDirectory().absolutePath(); -} - QDir GameMorrowind::savesDirectory() const { - return gameDirectory().absoluteFilePath("Saves"); + return QDir(gameDirectory().absoluteFilePath("Saves")); +} + +QDir GameMorrowind::documentsDirectory() const +{ + return gameDirectory(); } QList GameMorrowind::executables() const { return QList() - // << ExecutableInfo("SKSE", findInGameFolder(feature()->loaderName())) - // << ExecutableInfo("SBW", findInGameFolder("SBW.exe")) + // << ExecutableInfo("MWSE", findInGameFolder(feature()->loaderName())) << ExecutableInfo("Morrowind", findInGameFolder(binaryName())) << ExecutableInfo("Morrowind Launcher", findInGameFolder(getLauncherName())) - // << ExecutableInfo("BOSS", findInGameFolder("BOSS/BOSS.exe")) - // << ExecutableInfo("LOOT", getLootPath()).withArgument("--game=\"Skyrim\"") - // << ExecutableInfo("Creation Kit", findInGameFolder("CreationKit.exe")).withSteamAppId("202480") + << ExecutableInfo("MGE XE", findInGameFolder("MGEXEgui.exe")) ; } @@ -98,7 +100,7 @@ QString GameMorrowind::description() const MOBase::VersionInfo GameMorrowind::version() const { - return VersionInfo(1, 0, 0, VersionInfo::RELEASE_FINAL); + return VersionInfo(0, 1, 0, VersionInfo::RELEASE_FINAL); } bool GameMorrowind::isActive() const @@ -120,7 +122,7 @@ void GameMorrowind::initializeProfile(const QDir &path, ProfileSettings settings if (settings.testFlag(IPluginGame::CONFIGURATION)) { if (settings.testFlag(IPluginGame::PREFER_DEFAULTS) - || !QFileInfo(myGamesPath() + "/Morrowind.ini").exists()) { + || !QFileInfo(myGamesPath() + "/morrowind.ini").exists()) { copyToProfile(gameDirectory().absolutePath(), path, "Morrowind.ini"); } else { copyToProfile(myGamesPath(), path, "Morrowind.ini"); @@ -148,16 +150,16 @@ QStringList GameMorrowind::primaryPlugins() const return { "Morrowind.esm" }; } +QString GameMorrowind::binaryName() const +{ + return "Morrowind.exe"; +} + QString GameMorrowind::gameShortName() const { return "Morrowind"; } -QString GameMorrowind::getLauncherName() const -{ - return "Morrowind Launcher.exe"; -} - QString GameMorrowind::gameNexusName() const { return "Morrowind"; @@ -166,7 +168,7 @@ QString GameMorrowind::gameNexusName() const QStringList GameMorrowind::iniFiles() const { - return { "Morrowind.ini" }; + return { "morrowind.ini" }; } QStringList GameMorrowind::DLCPlugins() const @@ -204,21 +206,6 @@ VS_FIXEDFILEINFO GetFileVersion(const std::wstring &fileName) } -IPluginGame::LoadOrderMechanism GameMorrowind::loadOrderMechanism() const -{ - try { - std::wstring fileName = gameDirectory().absoluteFilePath(binaryName()).toStdWString().c_str(); - VS_FIXEDFILEINFO versionInfo = ::GetFileVersion(fileName); - if ((versionInfo.dwFileVersionMS > 0x10004) || // version >= 1.5.x? - ((versionInfo.dwFileVersionMS == 0x10004) && (versionInfo.dwFileVersionLS >= 0x1A0000))) { // version >= ?.4.26 - return LoadOrderMechanism::PluginsTxt; - } - } catch (const std::exception &e) { - qCritical() << "Morrowind.exe is invalid: " << e.what(); - } - return LoadOrderMechanism::FileTime; -} - int GameMorrowind::nexusModOrganizerID() const { diff --git a/src/games/morrowind/src/gamemorrowind.h b/src/games/morrowind/src/gamemorrowind.h index a2a89ce1..0f82ccda 100644 --- a/src/games/morrowind/src/gamemorrowind.h +++ b/src/games/morrowind/src/gamemorrowind.h @@ -10,7 +10,7 @@ class GameMorrowind : public GameGamebryo { Q_OBJECT #if QT_VERSION >= QT_VERSION_CHECK(5,0,0) - Q_PLUGIN_METADATA(IID "org.schilduin.GameMorrowind" FILE "gamemorrowind.json") + Q_PLUGIN_METADATA(IID "com.schilduin.GameMorrowind" FILE "gamemorrowind.json") #endif public: @@ -22,21 +22,21 @@ public: public: // IPluginGame interface virtual QString gameName() const override; + virtual QString getLauncherName() const override; virtual QDir dataDirectory() const override; - virtual QDir documentsDirectory() const override; virtual QDir savesDirectory() const override; + virtual QDir documentsDirectory() const override; virtual QList executables() const override; virtual void initializeProfile(const QDir &path, ProfileSettings settings) const override; virtual QString savegameExtension() const override; virtual QString savegameSEExtension() const override; virtual QString steamAPPId() const override; virtual QStringList primaryPlugins() const override; + virtual QString binaryName() const override; virtual QString gameShortName() const override; - virtual QString getLauncherName() const override; virtual QString gameNexusName() const override; virtual QStringList iniFiles() const override; virtual QStringList DLCPlugins() const override; - virtual LoadOrderMechanism loadOrderMechanism() const override; virtual int nexusModOrganizerID() const override; virtual int nexusGameID() const override; diff --git a/src/games/morrowind/src/morrosindgameplugins.h b/src/games/morrowind/src/morrosindgameplugins.h new file mode 100644 index 00000000..4cafdbef --- /dev/null +++ b/src/games/morrowind/src/morrosindgameplugins.h @@ -0,0 +1,29 @@ +#ifndef MORROWINDGAMEPLUGINS_H +#define MORROWINDGAMEPLUGINS_H + +#include + +class MorrowindGamePlugins : public GamebryoGamePlugins +{ + +public: + MorrowindGamePlugins(MOBase::IOrganizer *organizer); + + virtual void writePluginLists(const MOBase::IPluginList *pluginList) override; + virtual void readPluginLists(MOBase::IPluginList *pluginList) override; + +protected: + virtual void writePluginList(const MOBase::IPluginList *pluginList, + const QString &filePath); + virtual bool readPluginList(MOBase::IPluginList *pluginList, const QString &filePath, bool useLoadOrder); + +private: + virtual void writeList(const MOBase::IPluginList *pluginList, const QString &filePath, + bool loadOrder); + +private: + QDateTime m_LastRead; + +}; + +#endif // MORROWINDGAMEPLUGINS_H \ No newline at end of file diff --git a/src/games/morrowind/src/morrowindbsainvalidation.cpp b/src/games/morrowind/src/morrowindbsainvalidation.cpp new file mode 100644 index 00000000..bf4c3542 --- /dev/null +++ b/src/games/morrowind/src/morrowindbsainvalidation.cpp @@ -0,0 +1,16 @@ +#include "morrowindbsainvalidation.h" + +MorrowindBSAInvalidation::MorrowindBSAInvalidation(DataArchives *dataArchives, MOBase::IPluginGame const *game) + : GamebryoBSAInvalidation(dataArchives, "morrowind.ini", game) +{ +} + +QString MorrowindBSAInvalidation::invalidationBSAName() const +{ + return "Morrowind - Invalidation.bsa"; +} + +unsigned long MorrowindBSAInvalidation::bsaVersion() const +{ + return 0x68; +} diff --git a/src/games/morrowind/src/morrowindbsainvalidation.h b/src/games/morrowind/src/morrowindbsainvalidation.h new file mode 100644 index 00000000..d551c1d5 --- /dev/null +++ b/src/games/morrowind/src/morrowindbsainvalidation.h @@ -0,0 +1,23 @@ +#ifndef MORROWINDBSAINVALIDATION_H +#define MORROWINDBSAINVALIDATION_H + + +#include "gamebryobsainvalidation.h" +#include "morrowinddataarchives.h" + +#include + +class MorrowindBSAInvalidation : public GamebryoBSAInvalidation +{ +public: + + MorrowindBSAInvalidation(DataArchives *dataArchives, MOBase::IPluginGame const *game); + +private: + + virtual QString invalidationBSAName() const override; + virtual unsigned long bsaVersion() const override; + +}; + +#endif // MORROWINDBSAINVALIDATION_H diff --git a/src/games/morrowind/src/morrowinddataarchives.cpp b/src/games/morrowind/src/morrowinddataarchives.cpp new file mode 100644 index 00000000..4eb15782 --- /dev/null +++ b/src/games/morrowind/src/morrowinddataarchives.cpp @@ -0,0 +1,38 @@ +#include "morrowinddataarchives.h" +#include + +MorrowindDataArchives::MorrowindDataArchives(const QDir &myGamesDir) : + GamebryoDataArchives(myGamesDir) +{ +} + +QStringList MorrowindDataArchives::vanillaArchives() const +{ + return { "Morrowind.bsa" }; +} + + +QStringList MorrowindDataArchives::archives(const MOBase::IProfile *profile) const +{ + QStringList result; + + QString iniFile = profile->localSettingsEnabled() ? QDir(profile->absolutePath()).absoluteFilePath("morrowind.ini") : m_LocalGameDir.absoluteFilePath("morrowind.ini"); + result.append(getArchivesFromKey(iniFile, "SResourceArchiveList")); + result.append(getArchivesFromKey(iniFile, "SResourceArchiveList2")); + + return result; +} + +void MorrowindDataArchives::writeArchiveList(MOBase::IProfile *profile, const QStringList &before) +{ + QString list = before.join(", "); + + QString iniFile = profile->localSettingsEnabled() ? QDir(profile->absolutePath()).absoluteFilePath("morrowind.ini") : m_LocalGameDir.absoluteFilePath("morrowind.ini"); + if (list.length() > 255) { + int splitIdx = list.lastIndexOf(",", 256); + setArchivesToKey(iniFile, "SResourceArchiveList", list.mid(0, splitIdx)); + setArchivesToKey(iniFile, "SResourceArchiveList2", list.mid(splitIdx + 2)); + } else { + setArchivesToKey(iniFile, "SResourceArchiveList", list); + } +} diff --git a/src/games/morrowind/src/morrowinddataarchives.h b/src/games/morrowind/src/morrowinddataarchives.h new file mode 100644 index 00000000..ae2cae52 --- /dev/null +++ b/src/games/morrowind/src/morrowinddataarchives.h @@ -0,0 +1,28 @@ +#ifndef MORROWINDDATAARCHIVES_H +#define MORROWINDDATAARCHIVES_H + + +#include +#include +#include +#include +#include + +class MorrowindDataArchives : public GamebryoDataArchives +{ + +public: + MorrowindDataArchives(const QDir &myGamesDir); + +public: + + 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 // MORROWINDDATAARCHIVES_H diff --git a/src/games/morrowind/src/morrowindgameplugins.cpp b/src/games/morrowind/src/morrowindgameplugins.cpp new file mode 100644 index 00000000..fa88211d --- /dev/null +++ b/src/games/morrowind/src/morrowindgameplugins.cpp @@ -0,0 +1,139 @@ +#include "morrowindgameplugins.h" +#include +#include +#include +#include +#include +#include +#include + +#include +#include +#include +#include +#include + +using MOBase::IOrganizer; +using MOBase::IPluginList; +using MOBase::reportError; + +MorrowindGamePlugins::MorrowindGamePlugins(IOrganizer *organizer) : + GamebryoGamePlugins(organizer) +{ +} + +void MorrowindGamePlugins::writePluginLists(const IPluginList *pluginList) { + if (!m_LastRead.isValid()) { + // attempt to write uninitialized plugin lists + return; + } + + writePluginList(pluginList, + organizer()->profile()->absolutePath() + "/Morrowind.ini"); + writeLoadOrderList(pluginList, + organizer()->profile()->absolutePath() + "/loadorder.txt"); + + m_LastRead = QDateTime::currentDateTime(); +} + +void MorrowindGamePlugins::readPluginLists(MOBase::IPluginList *pluginList) { + QString loadOrderPath = + organizer()->profile()->absolutePath() + "/loadorder.txt"; + QString pluginsPath = organizer()->profile()->absolutePath() + "/Morrowind.ini"; + + bool loadOrderIsNew = !m_LastRead.isValid() || + !QFileInfo(loadOrderPath).exists() || + QFileInfo(loadOrderPath).lastModified() > m_LastRead; + bool pluginsIsNew = !m_LastRead.isValid() || + QFileInfo(pluginsPath).lastModified() > m_LastRead; + + if (loadOrderIsNew || !pluginsIsNew) { + // read both files if they are both new or both older than the last read + readLoadOrderList(pluginList, loadOrderPath); + readPluginList(pluginList, pluginsPath, false); + } else { + // if the plugin list is new but the load order isn't, this probably means + // an external tool that handles only the plugins.txt has been run in the + // meantime. We have to use plugins.txt for the load order as well. + readPluginList(pluginList, pluginsPath, true); + } + + m_LastRead = QDateTime::currentDateTime(); +} + +void MorrowindGamePlugins::writePluginList(const MOBase::IPluginList *pluginList, + const QString &filePath) { + return writeList(pluginList, filePath, false); +} + +void MorrowindGamePlugins::writeList(const IPluginList *pluginList, + const QString &filePath, bool loadOrder) { + QTextCodec *textCodec = loadOrder ? utf8Codec() : localCodec(); + bool invalidFileNames = false; + int writtenCount = 0; + + QStringList plugins = pluginList->pluginNames(); + std::sort(plugins.begin(), plugins.end(), + [pluginList](const QString &lhs, const QString &rhs) { + return pluginList->priority(lhs) < pluginList->priority(rhs); + }); + QString key = "GameFile"; + for (const QString &pluginName : plugins) { + if (loadOrder || + (pluginList->state(pluginName) == IPluginList::STATE_ACTIVE)) { + if (!textCodec->canEncode(pluginName)) { + invalidFileNames = true; + qCritical("invalid plugin name %s", qPrintable(pluginName)); + } else { + if (!::WritePrivateProfileStringW(L"Game Files", (key+QString::number(writtenCount)).toStdWString().c_str(), pluginName.toStdWString().c_str(), filePath.toStdWString().c_str())) { + throw MOBase::MyException(QObject::tr("failed to set game file key (errorcode %1)").arg(errno)); + } + } + ++writtenCount; + } + } + + if (invalidFileNames) { + reportError(QObject::tr("Some of your plugins have invalid names! These " + "plugins can not be loaded by the game. Please see " + "mo_interface.log for a list of affected plugins " + "and rename them.")); + } + + if (writtenCount == 0) { + qWarning("plugin list would be empty, this is almost certainly wrong. Not " + "saving."); + } +} + +bool MorrowindGamePlugins::readPluginList(MOBase::IPluginList *pluginList, const QString &filePath, bool useLoadOrder) { + QStringList plugins = pluginList->pluginNames(); + wchar_t buffer[256]; + QStringList result; + std::wstring iniFileW = QDir::toNativeSeparators(filePath).toStdWString(); + + errno = 0; + + QStringList loadOrder; + QString key = "GameFile"; + int i=0; + while (::GetPrivateProfileStringW(L"Game Files", (key+QString::number(i)).toStdWString().c_str(), + L"", buffer, 256, iniFileW.c_str()) != 0) { + QString pluginName; + pluginName=QString::fromStdWString(buffer).trimmed(); + pluginList->setState(pluginName, IPluginList::STATE_ACTIVE); + plugins.removeAll(pluginName); + loadOrder.append(pluginName); + i++; + } + + for (const QString &pluginName : plugins) { + pluginList->setState(pluginName, IPluginList::STATE_INACTIVE); + } + + if (useLoadOrder) { + pluginList->setLoadOrder(loadOrder); + } + + return true; +} \ No newline at end of file diff --git a/src/games/morrowind/src/morrowindsavegame.cpp b/src/games/morrowind/src/morrowindsavegame.cpp new file mode 100644 index 00000000..e72274cc --- /dev/null +++ b/src/games/morrowind/src/morrowindsavegame.cpp @@ -0,0 +1,83 @@ +#include "morrowindsavegame.h" + +#include + +MorrowindSaveGame::MorrowindSaveGame(QString const &fileName, MOBase::IPluginGame const *game) : + GamebryoSaveGame(fileName, game) +{ + FileWrapper file(this, "TES3"); + //file.skip(); // header size + //file.skip(); // header version + file.skip(79); //Mostly empty header Data + //file.readPlugins(); normal readPlugins function does not work + file.skip(); + uint8_t count; + file.read(count); + this->m_Plugins.reserve(count); + file.skip(); + for (std::size_t i = 0; i < count; ++i) { + file.skip(); + QString name; + file.read(name); + uint8_t tmp; + file.read(tmp); + name+=tmp; + file.skip(); + file.skip(4); + this->m_Plugins.push_back(name); + } + + file.skip(31); + file.setBZString(true); + file.read(m_PCLocation); + + file.skip(); + std::vector buffer(32); + file.read(buffer.data(), 32); + + m_PCName=QString::fromLatin1(buffer.data(), 32); + + //file.read(m_PCName); + //m_PCName="Placeholder"; + + // Placeholder values + m_PCLevel=0; + m_SaveNumber=0; + + /*file.skip() + file.read(m_SaveNumber); + + file.read(m_PCName); + + unsigned long temp; + file.read(temp); + m_PCLevel = static_cast(temp); + + file.read(m_PCLocation); + + QString timeOfDay; + file.read(timeOfDay); + + QString race; + file.read(race); // race name (i.e. BretonRace) + + file.skip(); // Player gender (0 = male) + file.skip(2); // experience gathered, experience required + + FILETIME ftime; + file.read(ftime); + //A file time is a 64-bit value that represents the number of 100-nanosecond + //intervals that have elapsed since 12:00 A.M. January 1, 1601 Coordinated Universal Time (UTC). + //So we need to convert that to something useful + SYSTEMTIME ctime; + ::FileTimeToSystemTime(&ftime, &ctime); + + setCreationTime(ctime); + + file.readImage(); + + file.skip(); // form version + file.skip(); // plugin info size + + file.readPlugins(); */ +} diff --git a/src/games/morrowind/src/morrowindsavegame.h b/src/games/morrowind/src/morrowindsavegame.h new file mode 100644 index 00000000..a4a63761 --- /dev/null +++ b/src/games/morrowind/src/morrowindsavegame.h @@ -0,0 +1,14 @@ +#ifndef MORROWINDSAVEGAME_H +#define MORROWINDSAVEGAME_H + +#include "gamebryosavegame.h" + +namespace MOBase { class IPluginGame; } + +class MorrowindSaveGame : public GamebryoSaveGame +{ +public: + MorrowindSaveGame(QString const &fileName, MOBase::IPluginGame const *game); +}; + +#endif // MORROWINDSAVEGAME_H diff --git a/src/games/morrowind/src/morrowindsavegameinfo.cpp b/src/games/morrowind/src/morrowindsavegameinfo.cpp new file mode 100644 index 00000000..82c1d321 --- /dev/null +++ b/src/games/morrowind/src/morrowindsavegameinfo.cpp @@ -0,0 +1,19 @@ +#include "morrowindsavegameinfo.h" + +#include "morrowindsavegame.h" +#include "gamegamebryo.h" + +MorrowindSaveGameInfo::MorrowindSaveGameInfo(GameGamebryo const *game) : + GamebryoSaveGameInfo(game) +{ +} + +MorrowindSaveGameInfo::~MorrowindSaveGameInfo() +{ +} + + +MOBase::ISaveGame const *MorrowindSaveGameInfo::getSaveGameInfo(QString const &file) const +{ + return new MorrowindSaveGame(file, m_Game); +} diff --git a/src/games/morrowind/src/morrowindsavegameinfo.h b/src/games/morrowind/src/morrowindsavegameinfo.h new file mode 100644 index 00000000..aac29fdd --- /dev/null +++ b/src/games/morrowind/src/morrowindsavegameinfo.h @@ -0,0 +1,17 @@ +#ifndef MORROWINDSAVEGAMEINFO_H +#define MORROWINDSAVEGAMEINFO_H + +#include "gamebryosavegameinfo.h" + +class GameGamebryo; + +class MorrowindSaveGameInfo : public GamebryoSaveGameInfo +{ +public: + MorrowindSaveGameInfo(GameGamebryo const *game); + ~MorrowindSaveGameInfo(); + + virtual MOBase::ISaveGame const *getSaveGameInfo(QString const &file) const override; +}; + +#endif // MORROWINDSAVEGAMEINFO_H diff --git a/src/games/morrowind/src/morrowindscriptextender.cpp b/src/games/morrowind/src/morrowindscriptextender.cpp new file mode 100644 index 00000000..91240340 --- /dev/null +++ b/src/games/morrowind/src/morrowindscriptextender.cpp @@ -0,0 +1,24 @@ +#include "morrowindscriptextender.h" + +#include +#include + +MorrowindScriptExtender::MorrowindScriptExtender(GameGamebryo const *game) : + GamebryoScriptExtender(game) +{ +} + +QString MorrowindScriptExtender::BinaryName() const +{ + return "skse_loader.exe"; +} + +QString MorrowindScriptExtender::PluginPath() const +{ + return "skse/plugins"; +} + +QStringList MorrowindScriptExtender::saveGameAttachmentExtensions() const +{ + return { "skse" }; +} diff --git a/src/games/morrowind/src/morrowindscriptextender.h b/src/games/morrowind/src/morrowindscriptextender.h new file mode 100644 index 00000000..5809a496 --- /dev/null +++ b/src/games/morrowind/src/morrowindscriptextender.h @@ -0,0 +1,20 @@ +#ifndef MORROWINDSCRIPTEXTENDER_H +#define MORROWINDSCRIPTEXTENDER_H + +#include "gamebryoscriptextender.h" + +class GameGamebryo; + +class MorrowindScriptExtender : public GamebryoScriptExtender +{ +public: + MorrowindScriptExtender(const GameGamebryo *game); + + virtual QString BinaryName() const override; + virtual QString PluginPath() const override; + + virtual QStringList saveGameAttachmentExtensions() const override; + +}; + +#endif // MORROWINDSCRIPTEXTENDER_H From defb2c9755b8d62d05b9e3e0e958c6b3c5d01809 Mon Sep 17 00:00:00 2001 From: Schilduin Date: Fri, 23 Feb 2018 23:22:28 +0100 Subject: [PATCH 0428/1544] [game_morrowind] Fixed misspell --- .../src/{morrosindgameplugins.h => morrowindgameplugins.h} | 0 1 file changed, 0 insertions(+), 0 deletions(-) rename src/games/morrowind/src/{morrosindgameplugins.h => morrowindgameplugins.h} (100%) diff --git a/src/games/morrowind/src/morrosindgameplugins.h b/src/games/morrowind/src/morrowindgameplugins.h similarity index 100% rename from src/games/morrowind/src/morrosindgameplugins.h rename to src/games/morrowind/src/morrowindgameplugins.h From a32b1ec8afb1118c6b45817d7a6e6d927e90b02a Mon Sep 17 00:00:00 2001 From: Schilduin Date: Sat, 24 Feb 2018 00:33:21 +0100 Subject: [PATCH 0429/1544] [game_morrowind] Fixed Plugin behaviour --- src/games/morrowind/src/morrowindgameplugins.cpp | 3 +++ 1 file changed, 3 insertions(+) diff --git a/src/games/morrowind/src/morrowindgameplugins.cpp b/src/games/morrowind/src/morrowindgameplugins.cpp index fa88211d..77085bdb 100644 --- a/src/games/morrowind/src/morrowindgameplugins.cpp +++ b/src/games/morrowind/src/morrowindgameplugins.cpp @@ -69,6 +69,9 @@ void MorrowindGamePlugins::writePluginList(const MOBase::IPluginList *pluginList void MorrowindGamePlugins::writeList(const IPluginList *pluginList, const QString &filePath, bool loadOrder) { QTextCodec *textCodec = loadOrder ? utf8Codec() : localCodec(); + + ::WritePrivateProfileSectionW(L"Game Files", NULL, filePath.toStdWString().c_str()); + bool invalidFileNames = false; int writtenCount = 0; From bdcd4ad16a59161305f5076e46dacb59151bc7f2 Mon Sep 17 00:00:00 2001 From: Schilduin Date: Sat, 24 Feb 2018 01:19:53 +0100 Subject: [PATCH 0430/1544] [game_morrowind] Edited Archive Handling --- .../morrowind/src/morrowinddataarchives.cpp | 45 ++++++++++++++----- .../morrowind/src/morrowinddataarchives.h | 5 +++ 2 files changed, 39 insertions(+), 11 deletions(-) diff --git a/src/games/morrowind/src/morrowinddataarchives.cpp b/src/games/morrowind/src/morrowinddataarchives.cpp index 4eb15782..79516263 100644 --- a/src/games/morrowind/src/morrowinddataarchives.cpp +++ b/src/games/morrowind/src/morrowinddataarchives.cpp @@ -11,28 +11,51 @@ QStringList MorrowindDataArchives::vanillaArchives() const return { "Morrowind.bsa" }; } +QStringList MorrowindDataArchives::getArchives(const QString &iniFile) const +{ + wchar_t buffer[256]; + QStringList result; + std::wstring iniFileW = QDir::toNativeSeparators(iniFile).toStdWString(); + + errno = 0; + + QString key = "Archive "; + int i=0; + if (::GetPrivateProfileStringW(L"Archives", key.toStdWString().c_str(), + L"", buffer, 256, iniFileW.c_str()) != 0) { + result.append(QString::fromStdWString(buffer).trimmed()); + i++; + } + + return result; +} + +void MorrowindDataArchives::setArchives(const QString &iniFile, const QStringList &list) +{ + ::WritePrivateProfileSectionW(L"Archives", NULL, filePath.toStdWString().c_str()); + + QString key = "Archive "; + int writtenCount = 0; + foreach(const QString &value, list) { + if (!::WritePrivateProfileStringW(L"Archive", (key+QString::number(writtenCount)).toStdWString().c_str(), value.toStdWString().c_str(), iniFile.toStdWString().c_str())) { + throw MOBase::MyException(QObject::tr("failed to set archive key (errorcode %1)").arg(errno)); + } + ++writtenCount; + } +} QStringList MorrowindDataArchives::archives(const MOBase::IProfile *profile) const { QStringList result; QString iniFile = profile->localSettingsEnabled() ? QDir(profile->absolutePath()).absoluteFilePath("morrowind.ini") : m_LocalGameDir.absoluteFilePath("morrowind.ini"); - result.append(getArchivesFromKey(iniFile, "SResourceArchiveList")); - result.append(getArchivesFromKey(iniFile, "SResourceArchiveList2")); + result.append(getArchives(iniFile)); return result; } void MorrowindDataArchives::writeArchiveList(MOBase::IProfile *profile, const QStringList &before) { - QString list = before.join(", "); - QString iniFile = profile->localSettingsEnabled() ? QDir(profile->absolutePath()).absoluteFilePath("morrowind.ini") : m_LocalGameDir.absoluteFilePath("morrowind.ini"); - if (list.length() > 255) { - int splitIdx = list.lastIndexOf(",", 256); - setArchivesToKey(iniFile, "SResourceArchiveList", list.mid(0, splitIdx)); - setArchivesToKey(iniFile, "SResourceArchiveList2", list.mid(splitIdx + 2)); - } else { - setArchivesToKey(iniFile, "SResourceArchiveList", list); - } + setArchives(iniFile, before); } diff --git a/src/games/morrowind/src/morrowinddataarchives.h b/src/games/morrowind/src/morrowinddataarchives.h index ae2cae52..83074631 100644 --- a/src/games/morrowind/src/morrowinddataarchives.h +++ b/src/games/morrowind/src/morrowinddataarchives.h @@ -19,6 +19,11 @@ public: virtual QStringList vanillaArchives() const override; virtual QStringList archives(const MOBase::IProfile *profile) const override; +protected: + + QStringList getArchives(const QString &iniFile) const + void setArchives(const QString &iniFile, const QStringList &list) + private: virtual void writeArchiveList(MOBase::IProfile *profile, const QStringList &before) override; From ac1c01c66d9d2ea4bf48b4f62807a7492cba2272 Mon Sep 17 00:00:00 2001 From: Schilduin Date: Sat, 24 Feb 2018 01:23:47 +0100 Subject: [PATCH 0431/1544] [game_morrowind] Edited Archive Handling --- src/games/morrowind/src/morrowinddataarchives.h | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/games/morrowind/src/morrowinddataarchives.h b/src/games/morrowind/src/morrowinddataarchives.h index 83074631..8264c676 100644 --- a/src/games/morrowind/src/morrowinddataarchives.h +++ b/src/games/morrowind/src/morrowinddataarchives.h @@ -21,8 +21,8 @@ public: protected: - QStringList getArchives(const QString &iniFile) const - void setArchives(const QString &iniFile, const QStringList &list) + QStringList getArchives(const QString &iniFile) const; + void setArchives(const QString &iniFile, const QStringList &list); private: From da2495a1443654380cb352df95c81e8276547eae Mon Sep 17 00:00:00 2001 From: Schilduin Date: Sat, 24 Feb 2018 01:28:45 +0100 Subject: [PATCH 0432/1544] [game_morrowind] Edited Archive Handling --- src/games/morrowind/src/morrowinddataarchives.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/games/morrowind/src/morrowinddataarchives.cpp b/src/games/morrowind/src/morrowinddataarchives.cpp index 79516263..3e04b3c2 100644 --- a/src/games/morrowind/src/morrowinddataarchives.cpp +++ b/src/games/morrowind/src/morrowinddataarchives.cpp @@ -32,7 +32,7 @@ QStringList MorrowindDataArchives::getArchives(const QString &iniFile) const void MorrowindDataArchives::setArchives(const QString &iniFile, const QStringList &list) { - ::WritePrivateProfileSectionW(L"Archives", NULL, filePath.toStdWString().c_str()); + ::WritePrivateProfileSectionW(L"Archives", NULL, iniFile.toStdWString().c_str()); QString key = "Archive "; int writtenCount = 0; From 244ea2448e9db71a9e7fed86acf362ced4db937c Mon Sep 17 00:00:00 2001 From: Schilduin Date: Sat, 24 Feb 2018 02:16:07 +0100 Subject: [PATCH 0433/1544] [game_morrowind] Edited Archive Handling --- src/games/morrowind/src/gameMorrowind.pro | 6 ++++-- src/games/morrowind/src/gamemorrowind.cpp | 2 +- src/games/morrowind/src/morrowinddataarchives.cpp | 2 +- 3 files changed, 6 insertions(+), 4 deletions(-) diff --git a/src/games/morrowind/src/gameMorrowind.pro b/src/games/morrowind/src/gameMorrowind.pro index 10d7e641..96916e2c 100644 --- a/src/games/morrowind/src/gameMorrowind.pro +++ b/src/games/morrowind/src/gameMorrowind.pro @@ -17,14 +17,16 @@ SOURCES += gamemorrowind.cpp \ morrowindscriptextender.cpp \ morrowinddataarchives.cpp \ morrowindsavegame.cpp \ - morrowindsavegameinfo.cpp + morrowindsavegameinfo.cpp \ + morrowindgameplugins.cpp HEADERS += gamemorrowind.h \ morrowindbsainvalidation.h \ morrowindscriptextender.h \ morrowinddataarchives.h \ morrowindsavegame.h \ - morrowindsavegameinfo.h + morrowindsavegameinfo.h \ + morrowindgameplugins.h CONFIG(debug, debug|release) { LIBS += -L"$${OUT_PWD}/../gameGamebryo/debug" diff --git a/src/games/morrowind/src/gamemorrowind.cpp b/src/games/morrowind/src/gamemorrowind.cpp index ec1a440d..f5f88d08 100644 --- a/src/games/morrowind/src/gamemorrowind.cpp +++ b/src/games/morrowind/src/gamemorrowind.cpp @@ -39,7 +39,7 @@ bool GameMorrowind::init(IOrganizer *moInfo) return false; } registerFeature(new MorrowindScriptExtender(this)); - registerFeature(new MorrowindDataArchives(myGamesPath())); + registerFeature(new MorrowindDataArchives(gameDirectory().absolutePath())); registerFeature(new MorrowindBSAInvalidation(feature(), this)); registerFeature(new MorrowindSaveGameInfo(this)); registerFeature(new GamebryoLocalSavegames(gameDirectory().absolutePath(), "morrowind.ini")); diff --git a/src/games/morrowind/src/morrowinddataarchives.cpp b/src/games/morrowind/src/morrowinddataarchives.cpp index 3e04b3c2..1c4b9726 100644 --- a/src/games/morrowind/src/morrowinddataarchives.cpp +++ b/src/games/morrowind/src/morrowinddataarchives.cpp @@ -37,7 +37,7 @@ void MorrowindDataArchives::setArchives(const QString &iniFile, const QStringLis QString key = "Archive "; int writtenCount = 0; foreach(const QString &value, list) { - if (!::WritePrivateProfileStringW(L"Archive", (key+QString::number(writtenCount)).toStdWString().c_str(), value.toStdWString().c_str(), iniFile.toStdWString().c_str())) { + if (!::WritePrivateProfileStringW(L"Archives", (key+QString::number(writtenCount)).toStdWString().c_str(), value.toStdWString().c_str(), iniFile.toStdWString().c_str())) { throw MOBase::MyException(QObject::tr("failed to set archive key (errorcode %1)").arg(errno)); } ++writtenCount; From 13e5eab3019432aca8d686cf44c4855cfed9ed7e Mon Sep 17 00:00:00 2001 From: Schilduin Date: Sat, 24 Feb 2018 03:23:35 +0100 Subject: [PATCH 0434/1544] [game_morrowind] Edited Savegame Handling --- src/games/morrowind/src/morrowindsavegame.cpp | 73 +++++++++---------- 1 file changed, 33 insertions(+), 40 deletions(-) diff --git a/src/games/morrowind/src/morrowindsavegame.cpp b/src/games/morrowind/src/morrowindsavegame.cpp index e72274cc..c008bdb1 100644 --- a/src/games/morrowind/src/morrowindsavegame.cpp +++ b/src/games/morrowind/src/morrowindsavegame.cpp @@ -37,47 +37,40 @@ MorrowindSaveGame::MorrowindSaveGame(QString const &fileName, MOBase::IPluginGam m_PCName=QString::fromLatin1(buffer.data(), 32); + file.skip(8); //Record SCRD + file.skip(16385); //Record SCRS + //file.skip(8445); //Globals + + //Globals, Scripts, Regions + std::vector buffer(4); + file.read(buffer.data(), 4); + while(QString::fromLatin1(buffer.data(), 4)=="GLOB"||QString::fromLatin1(buffer.data(), 4)=="SCPT"||QString::fromLatin1(buffer.data(), 4)=="REGN") + { + uint8_t len; + file.read(len); + file.skip(11+len); + std::vector buffer(4); + file.read(buffer.data(), 4); + } + + file.skip(4); + + std::vector buffer(4); + file.read(buffer.data(), 4); + while(QString::fromLatin1(buffer.data(), 4)=="NAME"||QString::fromLatin1(buffer.data(), 4)=="FNAME"||QString::fromLatin1(buffer.data(), 4)=="RNAM"||QString::fromLatin1(buffer.data(), 4)=="CNAM"||QString::fromLatin1(buffer.data(), 4)=="ANAM"||QString::fromLatin1(buffer.data(), 4)=="BNAM"||QString::fromLatin1(buffer.data(), 4)=="KNAM") + { + uint8_t len; + file.read(len); + file.skip(11+len); + std::vector buffer(4); + file.read(buffer.data(), 4); + } + + file.skip(7); + file.read(m_PCLevel); + //file.read(m_PCName); //m_PCName="Placeholder"; - // Placeholder values - m_PCLevel=0; - m_SaveNumber=0; - - /*file.skip() - file.read(m_SaveNumber); - - file.read(m_PCName); - - unsigned long temp; - file.read(temp); - m_PCLevel = static_cast(temp); - - file.read(m_PCLocation); - - QString timeOfDay; - file.read(timeOfDay); - - QString race; - file.read(race); // race name (i.e. BretonRace) - - file.skip(); // Player gender (0 = male) - file.skip(2); // experience gathered, experience required - - FILETIME ftime; - file.read(ftime); - //A file time is a 64-bit value that represents the number of 100-nanosecond - //intervals that have elapsed since 12:00 A.M. January 1, 1601 Coordinated Universal Time (UTC). - //So we need to convert that to something useful - SYSTEMTIME ctime; - ::FileTimeToSystemTime(&ftime, &ctime); - - setCreationTime(ctime); - - file.readImage(); - - file.skip(); // form version - file.skip(); // plugin info size - - file.readPlugins(); */ + m_SaveNumber=fileName.chop(4).right(4).toInt(); } From 1427820c088f3f3beeb76a2abe4400f839554748 Mon Sep 17 00:00:00 2001 From: Schilduin Date: Sat, 24 Feb 2018 03:30:35 +0100 Subject: [PATCH 0435/1544] [game_morrowind] Edited Savegame Handling, fixed errors --- src/games/morrowind/src/morrowindsavegame.cpp | 19 ++++++++----------- 1 file changed, 8 insertions(+), 11 deletions(-) diff --git a/src/games/morrowind/src/morrowindsavegame.cpp b/src/games/morrowind/src/morrowindsavegame.cpp index c008bdb1..4601957b 100644 --- a/src/games/morrowind/src/morrowindsavegame.cpp +++ b/src/games/morrowind/src/morrowindsavegame.cpp @@ -42,28 +42,25 @@ MorrowindSaveGame::MorrowindSaveGame(QString const &fileName, MOBase::IPluginGam //file.skip(8445); //Globals //Globals, Scripts, Regions - std::vector buffer(4); - file.read(buffer.data(), 4); - while(QString::fromLatin1(buffer.data(), 4)=="GLOB"||QString::fromLatin1(buffer.data(), 4)=="SCPT"||QString::fromLatin1(buffer.data(), 4)=="REGN") + std::vector buff(4); + file.read(buff.data(), 4); + while(QString::fromLatin1(buff.data(), 4)=="GLOB"||QString::fromLatin1(buff.data(), 4)=="SCPT"||QString::fromLatin1(buff.data(), 4)=="REGN") { uint8_t len; file.read(len); file.skip(11+len); - std::vector buffer(4); - file.read(buffer.data(), 4); + file.read(buff.data(), 4); } file.skip(4); - std::vector buffer(4); - file.read(buffer.data(), 4); - while(QString::fromLatin1(buffer.data(), 4)=="NAME"||QString::fromLatin1(buffer.data(), 4)=="FNAME"||QString::fromLatin1(buffer.data(), 4)=="RNAM"||QString::fromLatin1(buffer.data(), 4)=="CNAM"||QString::fromLatin1(buffer.data(), 4)=="ANAM"||QString::fromLatin1(buffer.data(), 4)=="BNAM"||QString::fromLatin1(buffer.data(), 4)=="KNAM") + file.read(buff.data(), 4); + while(QString::fromLatin1(buff.data(), 4)=="NAME"||QString::fromLatin1(buff.data(), 4)=="FNAME"||QString::fromLatin1(buff.data(), 4)=="RNAM"||QString::fromLatin1(buff.data(), 4)=="CNAM"||QString::fromLatin1(buff.data(), 4)=="ANAM"||QString::fromLatin1(buff.data(), 4)=="BNAM"||QString::fromLatin1(buff.data(), 4)=="KNAM") { uint8_t len; file.read(len); file.skip(11+len); - std::vector buffer(4); - file.read(buffer.data(), 4); + file.read(buff.data(), 4); } file.skip(7); @@ -72,5 +69,5 @@ MorrowindSaveGame::MorrowindSaveGame(QString const &fileName, MOBase::IPluginGam //file.read(m_PCName); //m_PCName="Placeholder"; - m_SaveNumber=fileName.chop(4).right(4).toInt(); + m_SaveNumber=fileName.chopped(4).right(4).toInt(); } From cd127b8913ac45bd20804b4466b04db1cdacfa94 Mon Sep 17 00:00:00 2001 From: Schilduin Date: Sat, 24 Feb 2018 03:59:29 +0100 Subject: [PATCH 0436/1544] [game_morrowind] Edited Savegame Handling --- src/games/morrowind/src/morrowindsavegame.cpp | 12 +++++++----- 1 file changed, 7 insertions(+), 5 deletions(-) diff --git a/src/games/morrowind/src/morrowindsavegame.cpp b/src/games/morrowind/src/morrowindsavegame.cpp index 4601957b..36be25af 100644 --- a/src/games/morrowind/src/morrowindsavegame.cpp +++ b/src/games/morrowind/src/morrowindsavegame.cpp @@ -37,7 +37,12 @@ MorrowindSaveGame::MorrowindSaveGame(QString const &fileName, MOBase::IPluginGam m_PCName=QString::fromLatin1(buffer.data(), 32); - file.skip(8); //Record SCRD + //definitively have to use another method to access the player level + //it is stored in the fifth byte of the NPDT subrecord of the first NPC_ record + + m_PCLevel=1; //Placeholder + + /*file.skip(8); //Record SCRD file.skip(16385); //Record SCRS //file.skip(8445); //Globals @@ -64,10 +69,7 @@ MorrowindSaveGame::MorrowindSaveGame(QString const &fileName, MOBase::IPluginGam } file.skip(7); - file.read(m_PCLevel); - - //file.read(m_PCName); - //m_PCName="Placeholder"; + file.read(m_PCLevel); */ m_SaveNumber=fileName.chopped(4).right(4).toInt(); } From b07d4c9c07fc0dd3191a97d1b985c3497affef76 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Sandro=20J=C3=A4ckel?= Date: Sun, 4 Mar 2018 11:47:23 +0100 Subject: [PATCH 0437/1544] [game_ttw] Initial upload --- src/games/ttw/.gitignore | 4 + src/games/ttw/CMakeLists.txt | 17 ++ src/games/ttw/src/CMakeLists.txt | 71 +++++++ src/games/ttw/src/SConscript | 13 ++ .../ttw/src/falloutttwbsainvalidation.cpp | 16 ++ src/games/ttw/src/falloutttwbsainvalidation.h | 23 +++ src/games/ttw/src/falloutttwdataarchives.cpp | 35 ++++ src/games/ttw/src/falloutttwdataarchives.h | 25 +++ src/games/ttw/src/falloutttwsavegame.cpp | 50 +++++ src/games/ttw/src/falloutttwsavegame.h | 14 ++ src/games/ttw/src/falloutttwsavegameinfo.cpp | 18 ++ src/games/ttw/src/falloutttwsavegameinfo.h | 17 ++ .../ttw/src/falloutttwscriptextender.cpp | 24 +++ src/games/ttw/src/falloutttwscriptextender.h | 20 ++ src/games/ttw/src/gameFalloutTTW.pro | 50 +++++ src/games/ttw/src/game_falloutTTW_en.ts | 12 ++ src/games/ttw/src/gamefalloutttw.cpp | 173 ++++++++++++++++++ src/games/ttw/src/gamefalloutttw.h | 49 +++++ src/games/ttw/src/gamefalloutttw.json | 1 + 19 files changed, 632 insertions(+) create mode 100644 src/games/ttw/.gitignore create mode 100644 src/games/ttw/CMakeLists.txt create mode 100644 src/games/ttw/src/CMakeLists.txt create mode 100644 src/games/ttw/src/SConscript create mode 100644 src/games/ttw/src/falloutttwbsainvalidation.cpp create mode 100644 src/games/ttw/src/falloutttwbsainvalidation.h create mode 100644 src/games/ttw/src/falloutttwdataarchives.cpp create mode 100644 src/games/ttw/src/falloutttwdataarchives.h create mode 100644 src/games/ttw/src/falloutttwsavegame.cpp create mode 100644 src/games/ttw/src/falloutttwsavegame.h create mode 100644 src/games/ttw/src/falloutttwsavegameinfo.cpp create mode 100644 src/games/ttw/src/falloutttwsavegameinfo.h create mode 100644 src/games/ttw/src/falloutttwscriptextender.cpp create mode 100644 src/games/ttw/src/falloutttwscriptextender.h create mode 100644 src/games/ttw/src/gameFalloutTTW.pro create mode 100644 src/games/ttw/src/game_falloutTTW_en.ts create mode 100644 src/games/ttw/src/gamefalloutttw.cpp create mode 100644 src/games/ttw/src/gamefalloutttw.h create mode 100644 src/games/ttw/src/gamefalloutttw.json diff --git a/src/games/ttw/.gitignore b/src/games/ttw/.gitignore new file mode 100644 index 00000000..5477e9c4 --- /dev/null +++ b/src/games/ttw/.gitignore @@ -0,0 +1,4 @@ +std*.log +build +CMakeLists.txt.user +edit diff --git a/src/games/ttw/CMakeLists.txt b/src/games/ttw/CMakeLists.txt new file mode 100644 index 00000000..6250189b --- /dev/null +++ b/src/games/ttw/CMakeLists.txt @@ -0,0 +1,17 @@ +CMAKE_MINIMUM_REQUIRED(VERSION 2.8) + +SET(PROJ_NAME game_ttw) + +PROJECT(${PROJ_NAME}) + +SET(DEPENDENCIES_DIR CACHE PATH "") + +# hint to find qt in dependencies path +LIST(APPEND CMAKE_PREFIX_PATH ${QT_ROOT}/lib/cmake) + +LIST(APPEND CMAKE_PREFIX_PATH ${DEPENDENCIES_DIR}/lz4/dll) + +FILE(GLOB_RECURSE BOOST_ROOT ${DEPENDENCIES_DIR}/boost*/project-config.jam) +GET_FILENAME_COMPONENT(BOOST_ROOT ${BOOST_ROOT} DIRECTORY) + +ADD_SUBDIRECTORY(src) diff --git a/src/games/ttw/src/CMakeLists.txt b/src/games/ttw/src/CMakeLists.txt new file mode 100644 index 00000000..13759b52 --- /dev/null +++ b/src/games/ttw/src/CMakeLists.txt @@ -0,0 +1,71 @@ +CMAKE_MINIMUM_REQUIRED (VERSION 2.8) + +CMAKE_POLICY(SET CMP0020 NEW) + +FILE(GLOB ${PROJ_NAME}_SRCS *.cpp) +FILE(GLOB ${PROJ_NAME}_HDRS *.h) +FILE(GLOB ${PROJ_NAME}_FORMS *.ui) + + +SET(CMAKE_INCLUDE_CURRENT_DIR ON) +SET(CMAKE_AUTOMOC ON) +SET(CMAKE_AUTOUIC ON) +FIND_PACKAGE(Qt5Widgets REQUIRED) +QT5_WRAP_UI(${PROJ_NAME}_UIHDRS ${${PROJ_NAME}_FORMS}) +FIND_PACKAGE(Qt5LinguistTools) +QT5_CREATE_TRANSLATION(${PROJ_NAME}_translations_qm ${CMAKE_SOURCE_DIR}/src ${CMAKE_SOURCE_DIR}/src/${PROJ_NAME}_en.ts) + +SET(Boost_USE_STATIC_LIBS ON) +SET(Boost_USE_MULTITHREADED ON) +SET(Boost_USE_STATIC_RUNTIME OFF) +FIND_PACKAGE(Boost) + +IF (Boost_FOUND) + INCLUDE_DIRECTORIES(${Boost_INCLUDE_DIRS}) +ENDIF () + +SET(default_project_path "${CMAKE_SOURCE_DIR}/..") +GET_FILENAME_COMPONENT(${default_project_path} ${default_project_path} REALPATH) + +SET(project_path "${default_project_path}" CACHE PATH "path to the other mo projects") +SET(lib_path "${project_path}/../../install/libs") + +INCLUDE_DIRECTORIES(${project_path}/uibase/src + ${project_path}/game_features/src + ${project_path}/game_gamebryo/src) +LINK_DIRECTORIES(${project_path}/uibase/build/src + ${lib_path} + ${project_path}/../lz4/dll) + + +ADD_LIBRARY(${PROJ_NAME} SHARED ${${PROJ_NAME}_HDRS} ${${PROJ_NAME}_SRCS} ${${PROJ_NAME}_UIHDRS} ${${PROJ_NAME}_translations_qm}) +TARGET_LINK_LIBRARIES(${PROJ_NAME} + Qt5::Widgets + ${Boost_LIBRARIES} + DbgHelp + uibase + game_gamebryo + liblz4 + Version) + +IF(MSVC) + SET_TARGET_PROPERTIES(${PROJ_NAME} PROPERTIES LINK_FLAGS "/LARGEADDRESSAWARE") +ELSE(MSVC) + SET_TARGET_PROPERTIES(${PROJ_NAME} PROPERTIES LINK_FLAGS "-std=c++11") +ENDIF(MSVC) + +IF (NOT "${OPTIMIZE_COMPILE_FLAGS}" STREQUAL "") + SET_TARGET_PROPERTIES(${PROJ_NAME} PROPERTIES COMPILE_FLAGS_RELWITHDEBINFO ${OPTIMIZE_COMPILE_FLAGS}) +ENDIF() +IF (NOT "${OPTIMIZE_LINK_FLAGS}" STREQUAL "") + SET_TARGET_PROPERTIES(${PROJ_NAME} PROPERTIES LINK_FLAGS_RELWITHDEBINFO ${OPTIMIZE_LINK_FLAGS}) +ENDIF() + +QT5_USE_MODULES(${PROJ_NAME} Widgets) + +############### +## Installation + +INSTALL(TARGETS ${PROJ_NAME} + RUNTIME DESTINATION bin/plugins) +INSTALL(FILES ${CMAKE_CURRENT_BINARY_DIR}/${PROJ_NAME}.pdb DESTINATION pdb) diff --git a/src/games/ttw/src/SConscript b/src/games/ttw/src/SConscript new file mode 100644 index 00000000..d6c52cc5 --- /dev/null +++ b/src/games/ttw/src/SConscript @@ -0,0 +1,13 @@ +Import('qt_env') + +env = qt_env.Clone() + +env.AppendUnique(CPPDEFINES = [ 'GAMEFALLOUTTTW_LIBRARY' ]) + +env.RequiresGamebryo() + +lib = env.SharedLibrary('gameFalloutTTW', env.Glob('*.cpp')) +env.InstallModule(lib) + +res = env['QT_USED_MODULES'] +Return('res') diff --git a/src/games/ttw/src/falloutttwbsainvalidation.cpp b/src/games/ttw/src/falloutttwbsainvalidation.cpp new file mode 100644 index 00000000..d1359487 --- /dev/null +++ b/src/games/ttw/src/falloutttwbsainvalidation.cpp @@ -0,0 +1,16 @@ +#include "falloutnvbsainvalidation.h" + +FalloutTTWBSAInvalidation::FalloutNVBSAInvalidation(DataArchives *dataArchives, MOBase::IPluginGame const *game) + : GamebryoBSAInvalidation(dataArchives, "fallout.ini", game) +{ +} + +QString FalloutNVBSAInvalidation::invalidationBSAName() const +{ + return "Fallout - Invalidation.bsa"; +} + +unsigned long FalloutTTWBSAInvalidation::bsaVersion() const +{ + return 0x68; +} diff --git a/src/games/ttw/src/falloutttwbsainvalidation.h b/src/games/ttw/src/falloutttwbsainvalidation.h new file mode 100644 index 00000000..57b01506 --- /dev/null +++ b/src/games/ttw/src/falloutttwbsainvalidation.h @@ -0,0 +1,23 @@ +#ifndef FALLOUTTTWBSAINVALIDATION_H +#define FALLOUTTTWBSAINVALIDATION_H + + +#include "gamebryobsainvalidation.h" +#include "falloutttwdataarchives.h" + +#include + +class FalloutTTWBSAInvalidation : public GamebryoBSAInvalidation +{ +public: + + FalloutTTWBSAInvalidation(DataArchives *dataArchives, MOBase::IPluginGame const *game); + +private: + + virtual QString invalidationBSAName() const override; + virtual unsigned long bsaVersion() const override; + +}; + +#endif // FALLOUTTTWBSAINVALIDATION_H diff --git a/src/games/ttw/src/falloutttwdataarchives.cpp b/src/games/ttw/src/falloutttwdataarchives.cpp new file mode 100644 index 00000000..15a8a5ae --- /dev/null +++ b/src/games/ttw/src/falloutttwdataarchives.cpp @@ -0,0 +1,35 @@ +#include "falloutttwdataarchives.h" +#include + +FalloutTTWDataArchives::FalloutTTWDataArchives(const QDir &myGamesDir) : + GamebryoDataArchives(myGamesDir) +{ +} + +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") : m_LocalGameDir.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") : m_LocalGameDir.absoluteFilePath("fallout.ini"); + setArchivesToKey(iniFile, "SArchiveList", list); +} diff --git a/src/games/ttw/src/falloutttwdataarchives.h b/src/games/ttw/src/falloutttwdataarchives.h new file mode 100644 index 00000000..83e011f9 --- /dev/null +++ b/src/games/ttw/src/falloutttwdataarchives.h @@ -0,0 +1,25 @@ +#ifndef FALLOUTTTWDATAARCHIVES_H +#define FALLOUTTTWDATAARCHIVES_H + + +#include +#include +#include +#include +#include + +class FalloutTTWDataArchives : public GamebryoDataArchives +{ +public: + FalloutTTWDataArchives(const QDir &myGamesDir); + +public: + 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/src/games/ttw/src/falloutttwsavegame.cpp b/src/games/ttw/src/falloutttwsavegame.cpp new file mode 100644 index 00000000..af206733 --- /dev/null +++ b/src/games/ttw/src/falloutttwsavegame.cpp @@ -0,0 +1,50 @@ +#include "falloutttwsavegame.h" + +FalloutTTWSaveGame::FalloutTTWSaveGame(QString const &fileName, MOBase::IPluginGame const *game) : + GamebryoSaveGame(fileName, game) +{ + FileWrapper file(this, "FO3SAVEGAME"); + + file.skip(); //Save header size + + file.skip(); //File version? + file.skip(); //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); + + unsigned long width; + file.read(width); + + unsigned long height; + file.read(height); + + file.read(m_SaveNumber); + + file.read(m_PCName); + + QString whatthis; + file.read(whatthis); + + long level; + file.read(level); + m_PCLevel = level; + + file.read(m_PCLocation); + + QString playtime; + file.read(playtime); + + file.readImage(width, height, 256); + + file.skip(5); // unknown byte, size of plugin data + + //Abstract this + file.readPlugins(); +} diff --git a/src/games/ttw/src/falloutttwsavegame.h b/src/games/ttw/src/falloutttwsavegame.h new file mode 100644 index 00000000..995c7477 --- /dev/null +++ b/src/games/ttw/src/falloutttwsavegame.h @@ -0,0 +1,14 @@ +#ifndef FALLOUTTTWSAVEGAME_H +#define FALLOUTTTWSAVEGAME_H + +#include "gamebryosavegame.h" + +namespace MOBase { class IPluginGame; } + +class FalloutTTWSaveGame : public GamebryoSaveGame +{ +public: + FalloutTTWSaveGame(QString const &fileName, MOBase::IPluginGame const *game); +}; + +#endif // FALLOUTTTWSAVEGAME_H diff --git a/src/games/ttw/src/falloutttwsavegameinfo.cpp b/src/games/ttw/src/falloutttwsavegameinfo.cpp new file mode 100644 index 00000000..3535f637 --- /dev/null +++ b/src/games/ttw/src/falloutttwsavegameinfo.cpp @@ -0,0 +1,18 @@ +#include "falloutttwsavegameinfo.h" + +#include "falloutttwsavegame.h" +#include "gamegamebryo.h" + +FalloutTTWSaveGameInfo::FalloutTTWSaveGameInfo(GameGamebryo const *game) : + GamebryoSaveGameInfo(game) +{ +} + +FalloutTTWSaveGameInfo::~FalloutTTWSaveGameInfo() +{ +} + +MOBase::ISaveGame const *FalloutTTWSaveGameInfo::getSaveGameInfo(QString const &file) const +{ + return new FalloutTTWSaveGame(file, m_Game); +} diff --git a/src/games/ttw/src/falloutttwsavegameinfo.h b/src/games/ttw/src/falloutttwsavegameinfo.h new file mode 100644 index 00000000..46df7a83 --- /dev/null +++ b/src/games/ttw/src/falloutttwsavegameinfo.h @@ -0,0 +1,17 @@ +#ifndef FALLOUTTTWSAVEGAMEINFO_H +#define FALLOUTTTWSAVEGAMEINFO_H + +#include "gamebryosavegameinfo.h" + +class GameGamebryo; + +class FalloutTTWSaveGameInfo : public GamebryoSaveGameInfo +{ +public: + FalloutTTWSaveGameInfo(GameGamebryo const *game); + ~FalloutTTWSaveGameInfo(); + + virtual MOBase::ISaveGame const *getSaveGameInfo(QString const &file) const override; + +}; +#endif // FALLOUTTTWSAVEGAMEINFO_H diff --git a/src/games/ttw/src/falloutttwscriptextender.cpp b/src/games/ttw/src/falloutttwscriptextender.cpp new file mode 100644 index 00000000..33ef7360 --- /dev/null +++ b/src/games/ttw/src/falloutttwscriptextender.cpp @@ -0,0 +1,24 @@ +#include "falloutttwscriptextender.h" + +#include +#include + +FalloutTTWScriptExtender::FalloutTTWScriptExtender(GameGamebryo const *game) : + GamebryoScriptExtender(game) +{ +} + +QString FalloutTTWScriptExtender::BinaryName() const +{ + return "nvse_loader.exe"; +} + +QString FalloutTTWScriptExtender::PluginPath() const +{ + return "nvse/plugins"; +} + +QStringList FalloutTTWScriptExtender::saveGameAttachmentExtensions() const +{ + return { }; +} diff --git a/src/games/ttw/src/falloutttwscriptextender.h b/src/games/ttw/src/falloutttwscriptextender.h new file mode 100644 index 00000000..d45c82a7 --- /dev/null +++ b/src/games/ttw/src/falloutttwscriptextender.h @@ -0,0 +1,20 @@ +#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; + + virtual QStringList saveGameAttachmentExtensions() const override; + +}; + +#endif // FALLOUTTTWSCRIPTEXTENDER_H diff --git a/src/games/ttw/src/gameFalloutTTW.pro b/src/games/ttw/src/gameFalloutTTW.pro new file mode 100644 index 00000000..bd08c6dc --- /dev/null +++ b/src/games/ttw/src/gameFalloutTTW.pro @@ -0,0 +1,50 @@ +#------------------------------------------------- +# +# Project created by QtCreator 2014-11-15T15:36:33 +# +#------------------------------------------------- + + +TARGET = gameFalloutTTW +TEMPLATE = lib + +CONFIG += plugins +CONFIG += dll + +DEFINES += GAMEFALLOUTTTW_LIBRARY + +SOURCES += gamefalloutTTW.cpp \ + falloutttwbsaittwalidation.cpp \ + falloutttwscriptextender.cpp \ + falloutttwdataarchives.cpp \ + falloutttwsavegame.cpp \ + falloutttwsavegameinfo.cpp + +HEADERS += gamefalloutttw.h \ + falloutttwbsaittwalidation.h \ + falloutttwscriptextender.h \ + falloutttwdataarchives.h \ + falloutttwsavegame.h \ + falloutttwsavegameinfo.h + +CONFIG(debug, debug|release) { + LIBS += -L"$${OUT_PWD}/../gameGamebryo/debug" + PRE_TARGETDEPS += \ + $$OUT_PWD/../gameGamebryo/debug/gameGamebryo.lib +} else { + LIBS += -L"$${OUT_PWD}/../gameGamebryo/release" + PRE_TARGETDEPS += \ + $$OUT_PWD/../gameGamebryo/release/gameGamebryo.lib +} + +include(../plugin_template.pri) + +INCLUDEPATH += "$${BOOSTPATH}" "$${PWD}/../gamefeatures" "$${PWD}/../gamegamebryo" + +LIBS += -ladvapi32 -lole32 -lgameGamebryo + +OTHER_FILES += \ + gamefalloutttw.json\ + SConscript \ + CMakeLists.txt + diff --git a/src/games/ttw/src/game_falloutTTW_en.ts b/src/games/ttw/src/game_falloutTTW_en.ts new file mode 100644 index 00000000..8da7a685 --- /dev/null +++ b/src/games/ttw/src/game_falloutTTW_en.ts @@ -0,0 +1,12 @@ + + + + + GameFalloutTTW + + + Adds support for the game Fallout TTW + + + + diff --git a/src/games/ttw/src/gamefalloutttw.cpp b/src/games/ttw/src/gamefalloutttw.cpp new file mode 100644 index 00000000..966cb9c6 --- /dev/null +++ b/src/games/ttw/src/gamefalloutttw.cpp @@ -0,0 +1,173 @@ +#include "gamefalloutttw.h" + +#include "falloutttwbsaittwalidation.h" +#include "falloutttwdataarchives.h" +#include "falloutttwsavegameinfo.h" +#include "falloutttwscriptextender.h" + +#include "executableinfo.h" +#include "pluginsetting.h" +#include "versioninfo.h" +#include +#include +#include + +#include +#include +#include +#include +#include +#include +#include + +#include + +using namespace MOBase; + +GameFalloutTTW::GameFalloutTTW() +{ +} + +bool GameFalloutTTW::init(IOrganizer *moInfo) +{ + if (!GameGamebryo::init(moInfo)) { + return false; + } + registerFeature(new FalloutTTWScriptExtender(this)); + registerFeature(new FalloutTTWDataArchives(myGamesPath())); + registerFeature(new FalloutTTWBSAIttwalidation(feature(), this)); + registerFeature(new FalloutTTWSaveGameInfo(this)); + registerFeature(new GamebryoLocalSavegames(myGamesPath(), "fallout.ini")); + registerFeature(new GamebryoGamePlugins(moInfo)); + registerFeature(new GamebryoUnmangedMods(this)); + return true; +} + +QString GameFalloutTTW::gameName() const +{ + return "New Vegas"; +} + +QList GameFalloutTTW::executables() const +{ + return QList() + << ExecutableInfo("NVSE", findInGameFolder(feature()->loaderName())) + << ExecutableInfo("New Vegas", findInGameFolder(binaryName())) + << ExecutableInfo("Fallout Mod Manager", findInGameFolder("fomm/fomm.exe")) + << ExecutableInfo("Construction Kit", findInGameFolder("geck.exe")) + << ExecutableInfo("Fallout Launcher", findInGameFolder(getLauncherName())) + << ExecutableInfo("BOSS", findInGameFolder("BOSS/BOSS.exe")) + << ExecutableInfo("LOOT", getLootPath()).withArgument("--game=\"FalloutNV\"") + ; +} + +QString GameFalloutTTW::name() const +{ + return "FalloutTTW Support Plugin"; +} + +QString GameFalloutTTW::author() const +{ + return "Tannin"; +} + +QString GameFalloutTTW::description() const +{ + return tr("Adds support for the game Fallout TTW"); +} + +MOBase::VersionInfo GameFalloutTTW::version() const +{ + return VersionInfo(1, 0, 0, VersionInfo::RELEASE_FINAL); +} + +bool GameFalloutTTW::isActive() const +{ + return qApp->property("managed_game").value() == this; +} + +QList GameFalloutTTW::settings() const +{ + return QList(); +} + +void GameFalloutTTW::initializeProfile(const QDir &path, ProfileSettings settings) const +{ + if (settings.testFlag(IPluginGame::MODS)) { + copyToProfile(localAppFolder() + "/FalloutNV", path, "plugins.txt"); + copyToProfile(localAppFolder() + "/FalloutNV", path, "loadorder.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, "custom.ini"); + } +} + +QString GameFalloutTTW::savegameExtension() const +{ + return "fos"; +} + +QString GameFalloutTTW::savegameSEExtension() const +{ + return "ttwse"; +} + +QString GameFalloutTTW::steamAPPId() const +{ + return "22380"; +} + +QStringList GameFalloutTTW::primaryPlugins() const +{ + return { "falloutnv.esm", "deadmoney.esm", "honesthearts.esm", + "oldworldblues.esm", "lonesomeroad.esm", "gunrunnersarsenal.esm", + "caravanpack.esm", "classicpack.esm", "mercenarypack.esm", + "tribalpack.esm", "fallout3.esm", "anchorage.esm", "thepitt.esm", + "brokensteel.esm", "pointlookout.esm", "zeta.esm", + "taleoftwowastelands.esm" }; +} + +QString GameFalloutTTW::gameShortName() const +{ + return "FalloutTTW"; +} + +QString GameFalloutTTW::gameNexusName() const +{ + return "newvegas"; +} + +QStringList GameFalloutTTW::iniFiles() const +{ + return { "fallout.ini", "falloutprefs.ini", "falloutcustom.ini", "custom.ini"}; +} + +QStringList GameFalloutTTW::DLCPlugins() const +{ + return { "DeadMoney.esm", "HonestHearts.esm", "OldWorldBlues.esm", + "LonesomeRoad.esm", "GunRunnersArsenal.esm", "CaravanPack.esm", + "ClassicPack.esm", "MercenaryPack.esm", "TribalPack.esm", + "Fallout3.esm", "Anchorage.esm", "ThePitt.esm", + "BrokenSteel.esm", "PointLookout.esm", "Zeta.esm", + "TaleOfTwoWastelands.esm"}; +} + +int GameFalloutTTW::nexusModOrganizerID() const +{ + return 42572; +} + +int GameFalloutTTW::nexusGameID() const +{ + return 130; +} diff --git a/src/games/ttw/src/gamefalloutttw.h b/src/games/ttw/src/gamefalloutttw.h new file mode 100644 index 00000000..dc89840b --- /dev/null +++ b/src/games/ttw/src/gamefalloutttw.h @@ -0,0 +1,49 @@ +#ifndef GAMEFALLOUTTTW_H +#define GAMEFALLOUTTTW_H + +#include "gamegamebryo.h" + +#include +#include + +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(); + + virtual bool init(MOBase::IOrganizer *moInfo) override; + +public: // IPluginGame interface + + virtual QString gameName() const override; + virtual QList executables() const override; + virtual void initializeProfile(const QDir &path, ProfileSettings settings) const override; + virtual QString savegameExtension() const override; + virtual QString savegameSEExtension() const override; + virtual QString steamAPPId() const override; + virtual QStringList primaryPlugins() const override; + virtual QString gameShortName() 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; + +public: // IPlugin interface + + virtual QString name() const; + virtual QString author() const; + virtual QString description() const; + virtual MOBase::VersionInfo version() const; + virtual bool isActive() const; + virtual QList settings() const; + +}; + +#endif // GAMEFALLOUTTTW_H diff --git a/src/games/ttw/src/gamefalloutttw.json b/src/games/ttw/src/gamefalloutttw.json new file mode 100644 index 00000000..0967ef42 --- /dev/null +++ b/src/games/ttw/src/gamefalloutttw.json @@ -0,0 +1 @@ +{} From d8cb09df4a6fd217c7ee531047426c952328bc77 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Sandro=20J=C3=A4ckel?= Date: Sun, 4 Mar 2018 11:50:41 +0100 Subject: [PATCH 0438/1544] [game_ttw] Fixed horrible formating --- src/games/ttw/src/gamefalloutttw.cpp | 18 +++++++++--------- 1 file changed, 9 insertions(+), 9 deletions(-) diff --git a/src/games/ttw/src/gamefalloutttw.cpp b/src/games/ttw/src/gamefalloutttw.cpp index 966cb9c6..be7015f5 100644 --- a/src/games/ttw/src/gamefalloutttw.cpp +++ b/src/games/ttw/src/gamefalloutttw.cpp @@ -107,8 +107,8 @@ void GameFalloutTTW::initializeProfile(const QDir &path, ProfileSettings setting } copyToProfile(myGamesPath(), path, "falloutprefs.ini"); - copyToProfile(myGamesPath(), path, "falloutcustom.ini"); - copyToProfile(myGamesPath(), path, "custom.ini"); + copyToProfile(myGamesPath(), path, "falloutcustom.ini"); + copyToProfile(myGamesPath(), path, "custom.ini"); } } @@ -130,11 +130,11 @@ QString GameFalloutTTW::steamAPPId() const QStringList GameFalloutTTW::primaryPlugins() const { return { "falloutnv.esm", "deadmoney.esm", "honesthearts.esm", - "oldworldblues.esm", "lonesomeroad.esm", "gunrunnersarsenal.esm", + "oldworldblues.esm", "lonesomeroad.esm", "gunrunnersarsenal.esm", "caravanpack.esm", "classicpack.esm", "mercenarypack.esm", - "tribalpack.esm", "fallout3.esm", "anchorage.esm", "thepitt.esm", - "brokensteel.esm", "pointlookout.esm", "zeta.esm", - "taleoftwowastelands.esm" }; + "tribalpack.esm", "fallout3.esm", "anchorage.esm", "thepitt.esm", + "brokensteel.esm", "pointlookout.esm", "zeta.esm", + "taleoftwowastelands.esm" }; } QString GameFalloutTTW::gameShortName() const @@ -157,9 +157,9 @@ QStringList GameFalloutTTW::DLCPlugins() const return { "DeadMoney.esm", "HonestHearts.esm", "OldWorldBlues.esm", "LonesomeRoad.esm", "GunRunnersArsenal.esm", "CaravanPack.esm", "ClassicPack.esm", "MercenaryPack.esm", "TribalPack.esm", - "Fallout3.esm", "Anchorage.esm", "ThePitt.esm", - "BrokenSteel.esm", "PointLookout.esm", "Zeta.esm", - "TaleOfTwoWastelands.esm"}; + "Fallout3.esm", "Anchorage.esm", "ThePitt.esm", + "BrokenSteel.esm", "PointLookout.esm", "Zeta.esm", + "TaleOfTwoWastelands.esm"}; } int GameFalloutTTW::nexusModOrganizerID() const From 99e2b84fd813095d77f074e728f7121223e912dc Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Sandro=20J=C3=A4ckel?= Date: Tue, 6 Mar 2018 23:23:18 +0100 Subject: [PATCH 0439/1544] [game_skyrimse] Changed lz4 path to var --- src/games/skyrimse/.gitignore | 4 ++++ src/games/skyrimse/CMakeLists.txt | 2 +- src/games/skyrimse/src/CMakeLists.txt | 2 +- 3 files changed, 6 insertions(+), 2 deletions(-) diff --git a/src/games/skyrimse/.gitignore b/src/games/skyrimse/.gitignore index bcc50d34..4c4fa01e 100644 --- a/src/games/skyrimse/.gitignore +++ b/src/games/skyrimse/.gitignore @@ -2,3 +2,7 @@ CMakeLists.txt.user edit build std*.log +build +vsbuild +vs_stderr.log +vs_stdout.log diff --git a/src/games/skyrimse/CMakeLists.txt b/src/games/skyrimse/CMakeLists.txt index d10ab54f..ba8e4e09 100644 --- a/src/games/skyrimse/CMakeLists.txt +++ b/src/games/skyrimse/CMakeLists.txt @@ -8,7 +8,7 @@ SET(DEPENDENCIES_DIR CACHE PATH "") # hint to find qt in dependencies path LIST(APPEND CMAKE_PREFIX_PATH ${QT_ROOT}/lib/cmake) -LIST(APPEND CMAKE_PREFIX_PATH ${DEPENDENCIES_DIR}/lz4/dll) +LIST(APPEND CMAKE_PREFIX_PATH ${LZ4_ROOT}/dll) FILE(GLOB_RECURSE BOOST_ROOT ${DEPENDENCIES_DIR}/boost*/project-config.jam) GET_FILENAME_COMPONENT(BOOST_ROOT ${BOOST_ROOT} DIRECTORY) diff --git a/src/games/skyrimse/src/CMakeLists.txt b/src/games/skyrimse/src/CMakeLists.txt index eb222bd0..838e9a41 100644 --- a/src/games/skyrimse/src/CMakeLists.txt +++ b/src/games/skyrimse/src/CMakeLists.txt @@ -35,7 +35,7 @@ INCLUDE_DIRECTORIES(${project_path}/uibase/src ${project_path}/game_gamebryo/src) LINK_DIRECTORIES(${project_path}/uibase/build/src ${lib_path} - ${project_path}/../lz4/dll) + ${LZ4_ROOT}/dll) ADD_DEFINITIONS(-DUNICODE -D_UNICODE) From 72930a1b5820addae13dd2c755de3291748869a3 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Sandro=20J=C3=A4ckel?= Date: Tue, 6 Mar 2018 23:35:48 +0100 Subject: [PATCH 0440/1544] [game_skyrim] Changed lz4 path to var --- src/games/skyrim/.gitignore | 6 +++++- src/games/skyrim/CMakeLists.txt | 2 +- src/games/skyrim/src/CMakeLists.txt | 2 +- 3 files changed, 7 insertions(+), 3 deletions(-) diff --git a/src/games/skyrim/.gitignore b/src/games/skyrim/.gitignore index 5ff13f91..4c4fa01e 100644 --- a/src/games/skyrim/.gitignore +++ b/src/games/skyrim/.gitignore @@ -1,4 +1,8 @@ -build CMakeLists.txt.user edit +build std*.log +build +vsbuild +vs_stderr.log +vs_stdout.log diff --git a/src/games/skyrim/CMakeLists.txt b/src/games/skyrim/CMakeLists.txt index 31d9b748..93c5aab6 100644 --- a/src/games/skyrim/CMakeLists.txt +++ b/src/games/skyrim/CMakeLists.txt @@ -8,7 +8,7 @@ SET(DEPENDENCIES_DIR CACHE PATH "") # hint to find qt in dependencies path LIST(APPEND CMAKE_PREFIX_PATH ${QT_ROOT}/lib/cmake) -LIST(APPEND CMAKE_PREFIX_PATH ${DEPENDENCIES_DIR}/lz4/dll) +LIST(APPEND CMAKE_PREFIX_PATH ${LZ4_ROOT}/dll) FILE(GLOB_RECURSE BOOST_ROOT ${DEPENDENCIES_DIR}/boost*/project-config.jam) GET_FILENAME_COMPONENT(BOOST_ROOT ${BOOST_ROOT} DIRECTORY) diff --git a/src/games/skyrim/src/CMakeLists.txt b/src/games/skyrim/src/CMakeLists.txt index 6f9c4c67..b9895cea 100644 --- a/src/games/skyrim/src/CMakeLists.txt +++ b/src/games/skyrim/src/CMakeLists.txt @@ -35,7 +35,7 @@ INCLUDE_DIRECTORIES(${project_path}/uibase/src ${project_path}/game_gamebryo/src) LINK_DIRECTORIES(${project_path}/uibase/build/src ${lib_path} - ${project_path}/../lz4/dll) + ${LZ4_ROOT}/dll) ADD_DEFINITIONS(-DUNICODE -D_UNICODE) From 62394ef9a5a68da31b16a9ea61bab7deea762a42 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Sandro=20J=C3=A4ckel?= Date: Tue, 6 Mar 2018 23:37:15 +0100 Subject: [PATCH 0441/1544] [game_oblivion] Changed lz4 path to var --- src/games/oblivion/.gitignore | 4 ++++ src/games/oblivion/CMakeLists.txt | 2 +- src/games/oblivion/src/CMakeLists.txt | 2 +- 3 files changed, 6 insertions(+), 2 deletions(-) diff --git a/src/games/oblivion/.gitignore b/src/games/oblivion/.gitignore index c5a72415..4c4fa01e 100644 --- a/src/games/oblivion/.gitignore +++ b/src/games/oblivion/.gitignore @@ -1,4 +1,8 @@ CMakeLists.txt.user edit +build std*.log build +vsbuild +vs_stderr.log +vs_stdout.log diff --git a/src/games/oblivion/CMakeLists.txt b/src/games/oblivion/CMakeLists.txt index 914f15e9..29c3d048 100644 --- a/src/games/oblivion/CMakeLists.txt +++ b/src/games/oblivion/CMakeLists.txt @@ -8,7 +8,7 @@ SET(DEPENDENCIES_DIR CACHE PATH "") # hint to find qt in dependencies path LIST(APPEND CMAKE_PREFIX_PATH ${QT_ROOT}/lib/cmake) -LIST(APPEND CMAKE_PREFIX_PATH ${DEPENDENCIES_DIR}/lz4/dll) +LIST(APPEND CMAKE_PREFIX_PATH ${LZ4_ROOT}/dll) FILE(GLOB_RECURSE BOOST_ROOT ${DEPENDENCIES_DIR}/boost*/project-config.jam) GET_FILENAME_COMPONENT(BOOST_ROOT ${BOOST_ROOT} DIRECTORY) diff --git a/src/games/oblivion/src/CMakeLists.txt b/src/games/oblivion/src/CMakeLists.txt index fd93f6f7..0bc4f5fe 100644 --- a/src/games/oblivion/src/CMakeLists.txt +++ b/src/games/oblivion/src/CMakeLists.txt @@ -35,7 +35,7 @@ INCLUDE_DIRECTORIES(${project_path}/uibase/src ${project_path}/game_gamebryo/src) LINK_DIRECTORIES(${project_path}/uibase/build/src ${lib_path} - ${project_path}/../lz4/dll) + ${LZ4_ROOT}/dll) ADD_LIBRARY(${PROJ_NAME} SHARED ${${PROJ_NAME}_HDRS} ${${PROJ_NAME}_SRCS} ${${PROJ_NAME}_UIHDRS} ${${PROJ_NAME}_translations_qm}) From 199bf8cdb51cbebf0290a8dca4b598a2c2f4014e Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Sandro=20J=C3=A4ckel?= Date: Tue, 6 Mar 2018 23:39:03 +0100 Subject: [PATCH 0442/1544] [game_morrowind] Changed lz4 path to var --- src/games/morrowind/.gitignore | 6 +++++- src/games/morrowind/CMakeLists.txt | 2 +- src/games/morrowind/src/CMakeLists.txt | 2 +- 3 files changed, 7 insertions(+), 3 deletions(-) diff --git a/src/games/morrowind/.gitignore b/src/games/morrowind/.gitignore index 5ff13f91..4c4fa01e 100644 --- a/src/games/morrowind/.gitignore +++ b/src/games/morrowind/.gitignore @@ -1,4 +1,8 @@ -build CMakeLists.txt.user edit +build std*.log +build +vsbuild +vs_stderr.log +vs_stdout.log diff --git a/src/games/morrowind/CMakeLists.txt b/src/games/morrowind/CMakeLists.txt index 5f62ad07..f960b421 100644 --- a/src/games/morrowind/CMakeLists.txt +++ b/src/games/morrowind/CMakeLists.txt @@ -8,7 +8,7 @@ SET(DEPENDENCIES_DIR CACHE PATH "") # hint to find qt in dependencies path LIST(APPEND CMAKE_PREFIX_PATH ${QT_ROOT}/lib/cmake) -LIST(APPEND CMAKE_PREFIX_PATH ${DEPENDENCIES_DIR}/lz4/dll) +LIST(APPEND CMAKE_PREFIX_PATH ${LZ4_ROOT}/dll) FILE(GLOB_RECURSE BOOST_ROOT ${DEPENDENCIES_DIR}/boost*/project-config.jam) GET_FILENAME_COMPONENT(BOOST_ROOT ${BOOST_ROOT} DIRECTORY) diff --git a/src/games/morrowind/src/CMakeLists.txt b/src/games/morrowind/src/CMakeLists.txt index 6f9c4c67..b9895cea 100644 --- a/src/games/morrowind/src/CMakeLists.txt +++ b/src/games/morrowind/src/CMakeLists.txt @@ -35,7 +35,7 @@ INCLUDE_DIRECTORIES(${project_path}/uibase/src ${project_path}/game_gamebryo/src) LINK_DIRECTORIES(${project_path}/uibase/build/src ${lib_path} - ${project_path}/../lz4/dll) + ${LZ4_ROOT}/dll) ADD_DEFINITIONS(-DUNICODE -D_UNICODE) From 3a0d4d02237c9603d25f29b0254ddadae374854a Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Sandro=20J=C3=A4ckel?= Date: Tue, 6 Mar 2018 18:27:53 +0100 Subject: [PATCH 0443/1544] Changed lz4 path to var --- .gitignore | 8 ++++++-- CMakeLists.txt | 3 ++- src/CMakeLists.txt | 4 ++-- 3 files changed, 10 insertions(+), 5 deletions(-) diff --git a/.gitignore b/.gitignore index 5477e9c4..4c4fa01e 100644 --- a/.gitignore +++ b/.gitignore @@ -1,4 +1,8 @@ -std*.log -build CMakeLists.txt.user edit +build +std*.log +build +vsbuild +vs_stderr.log +vs_stdout.log diff --git a/CMakeLists.txt b/CMakeLists.txt index 584c342b..0939b7ec 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -8,7 +8,8 @@ SET(DEPENDENCIES_DIR CACHE PATH "") # hint to find qt in dependencies path LIST(APPEND CMAKE_PREFIX_PATH ${QT_ROOT}/lib/cmake) -LIST(APPEND CMAKE_PREFIX_PATH ${DEPENDENCIES_DIR}/lz4/dll) +LIST(APPEND CMAKE_PREFIX_PATH ${LZ4_ROOT}/dll) +message(${LZ4_ROOT}) FILE(GLOB_RECURSE BOOST_ROOT ${DEPENDENCIES_DIR}/boost*/project-config.jam) GET_FILENAME_COMPONENT(BOOST_ROOT ${BOOST_ROOT} DIRECTORY) diff --git a/src/CMakeLists.txt b/src/CMakeLists.txt index 0d84ace7..ce0a5f0c 100644 --- a/src/CMakeLists.txt +++ b/src/CMakeLists.txt @@ -32,9 +32,9 @@ SET(plugin_path "${project_path}") INCLUDE_DIRECTORIES(${project_path}/uibase/src ${project_path}/game_features/src - ${project_path}/../lz4/include) + ${LZ4_ROOT}/include) LINK_DIRECTORIES(${lib_path} - ${project_path}/../lz4/dll) + ${LZ4_ROOT}/dll) ADD_LIBRARY(${PROJ_NAME} STATIC ${${PROJ_NAME}_HDRS} ${${PROJ_NAME}_SRCS} ${${PROJ_NAME}_UIHDRS}) TARGET_LINK_LIBRARIES(${PROJ_NAME} From 0724b5e0736c0c1de114d53c9dcd94172ddb2ac8 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Sandro=20J=C3=A4ckel?= Date: Tue, 6 Mar 2018 23:40:08 +0100 Subject: [PATCH 0444/1544] [game_falloutnv] Changed lz4 path to var --- src/games/falloutnv/.gitignore | 8 ++++++-- src/games/falloutnv/CMakeLists.txt | 2 +- src/games/falloutnv/src/CMakeLists.txt | 2 +- 3 files changed, 8 insertions(+), 4 deletions(-) diff --git a/src/games/falloutnv/.gitignore b/src/games/falloutnv/.gitignore index 5477e9c4..4c4fa01e 100644 --- a/src/games/falloutnv/.gitignore +++ b/src/games/falloutnv/.gitignore @@ -1,4 +1,8 @@ -std*.log -build CMakeLists.txt.user edit +build +std*.log +build +vsbuild +vs_stderr.log +vs_stdout.log diff --git a/src/games/falloutnv/CMakeLists.txt b/src/games/falloutnv/CMakeLists.txt index fc30c94e..3bd2ca8d 100644 --- a/src/games/falloutnv/CMakeLists.txt +++ b/src/games/falloutnv/CMakeLists.txt @@ -9,7 +9,7 @@ SET(DEPENDENCIES_DIR CACHE PATH "") # hint to find qt in dependencies path LIST(APPEND CMAKE_PREFIX_PATH ${QT_ROOT}/lib/cmake) -LIST(APPEND CMAKE_PREFIX_PATH ${DEPENDENCIES_DIR}/lz4/dll) +LIST(APPEND CMAKE_PREFIX_PATH ${LZ4_ROOT}/dll) FILE(GLOB_RECURSE BOOST_ROOT ${DEPENDENCIES_DIR}/boost*/project-config.jam) GET_FILENAME_COMPONENT(BOOST_ROOT ${BOOST_ROOT} DIRECTORY) diff --git a/src/games/falloutnv/src/CMakeLists.txt b/src/games/falloutnv/src/CMakeLists.txt index 13759b52..6b2a0f5d 100644 --- a/src/games/falloutnv/src/CMakeLists.txt +++ b/src/games/falloutnv/src/CMakeLists.txt @@ -35,7 +35,7 @@ INCLUDE_DIRECTORIES(${project_path}/uibase/src ${project_path}/game_gamebryo/src) LINK_DIRECTORIES(${project_path}/uibase/build/src ${lib_path} - ${project_path}/../lz4/dll) + ${LZ4_ROOT}/dll) ADD_LIBRARY(${PROJ_NAME} SHARED ${${PROJ_NAME}_HDRS} ${${PROJ_NAME}_SRCS} ${${PROJ_NAME}_UIHDRS} ${${PROJ_NAME}_translations_qm}) From 165d6036c2a4916fcd2cb41c23773971486955cf Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Sandro=20J=C3=A4ckel?= Date: Tue, 6 Mar 2018 23:41:13 +0100 Subject: [PATCH 0445/1544] [game_fallout4vr] Changed lz4 path to var --- src/games/fallout4vr/.gitignore | 4 ++++ src/games/fallout4vr/CMakeLists.txt | 2 +- src/games/fallout4vr/src/CMakeLists.txt | 2 +- 3 files changed, 6 insertions(+), 2 deletions(-) diff --git a/src/games/fallout4vr/.gitignore b/src/games/fallout4vr/.gitignore index bcc50d34..4c4fa01e 100644 --- a/src/games/fallout4vr/.gitignore +++ b/src/games/fallout4vr/.gitignore @@ -2,3 +2,7 @@ CMakeLists.txt.user edit build std*.log +build +vsbuild +vs_stderr.log +vs_stdout.log diff --git a/src/games/fallout4vr/CMakeLists.txt b/src/games/fallout4vr/CMakeLists.txt index deefeff3..7f463b5a 100644 --- a/src/games/fallout4vr/CMakeLists.txt +++ b/src/games/fallout4vr/CMakeLists.txt @@ -8,7 +8,7 @@ SET(DEPENDENCIES_DIR CACHE PATH "") # hint to find qt in dependencies path LIST(APPEND CMAKE_PREFIX_PATH ${QT_ROOT}/lib/cmake) -LIST(APPEND CMAKE_PREFIX_PATH ${DEPENDENCIES_DIR}/lz4/dll) +LIST(APPEND CMAKE_PREFIX_PATH ${LZ4_ROOT}/dll) FILE(GLOB_RECURSE BOOST_ROOT ${DEPENDENCIES_DIR}/boost*/project-config.jam) GET_FILENAME_COMPONENT(BOOST_ROOT ${BOOST_ROOT} DIRECTORY) diff --git a/src/games/fallout4vr/src/CMakeLists.txt b/src/games/fallout4vr/src/CMakeLists.txt index c45fea37..c96b6133 100644 --- a/src/games/fallout4vr/src/CMakeLists.txt +++ b/src/games/fallout4vr/src/CMakeLists.txt @@ -39,7 +39,7 @@ INCLUDE_DIRECTORIES(${project_path}/uibase/src ${project_path}/game_gamebryo/src) LINK_DIRECTORIES(${project_path}/uibase/build/src ${lib_path} - ${project_path}/../lz4/dll) + ${LZ4_ROOT}/dll) ADD_LIBRARY(${PROJ_NAME} SHARED ${${PROJ_NAME}_HDRS} ${${PROJ_NAME}_SRCS} ${${PROJ_NAME}_UIHDRS} ${${PROJ_NAME}_RCCPPS} ${${PROJ_NAME}_translations_qm}) From 20b851ceefa3a3e3e314b36077aae1f1e8e4a214 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Sandro=20J=C3=A4ckel?= Date: Tue, 6 Mar 2018 23:42:36 +0100 Subject: [PATCH 0446/1544] [game_fallout76] Changed lz4 path to var --- src/games/fallout76/.gitignore | 4 ++++ src/games/fallout76/CMakeLists.txt | 2 +- src/games/fallout76/src/CMakeLists.txt | 2 +- 3 files changed, 6 insertions(+), 2 deletions(-) diff --git a/src/games/fallout76/.gitignore b/src/games/fallout76/.gitignore index bcc50d34..4c4fa01e 100644 --- a/src/games/fallout76/.gitignore +++ b/src/games/fallout76/.gitignore @@ -2,3 +2,7 @@ CMakeLists.txt.user edit build std*.log +build +vsbuild +vs_stderr.log +vs_stdout.log diff --git a/src/games/fallout76/CMakeLists.txt b/src/games/fallout76/CMakeLists.txt index 950d7a0c..53ea565d 100644 --- a/src/games/fallout76/CMakeLists.txt +++ b/src/games/fallout76/CMakeLists.txt @@ -8,7 +8,7 @@ SET(DEPENDENCIES_DIR CACHE PATH "") # hint to find qt in dependencies path LIST(APPEND CMAKE_PREFIX_PATH ${QT_ROOT}/lib/cmake) -LIST(APPEND CMAKE_PREFIX_PATH ${DEPENDENCIES_DIR}/lz4/dll) +LIST(APPEND CMAKE_PREFIX_PATH ${LZ4_ROOT}/dll) FILE(GLOB_RECURSE BOOST_ROOT ${DEPENDENCIES_DIR}/boost*/project-config.jam) GET_FILENAME_COMPONENT(BOOST_ROOT ${BOOST_ROOT} DIRECTORY) diff --git a/src/games/fallout76/src/CMakeLists.txt b/src/games/fallout76/src/CMakeLists.txt index c52541f2..73c9c557 100644 --- a/src/games/fallout76/src/CMakeLists.txt +++ b/src/games/fallout76/src/CMakeLists.txt @@ -39,7 +39,7 @@ INCLUDE_DIRECTORIES(${project_path}/uibase/src ${project_path}/game_gamebryo/src) LINK_DIRECTORIES(${project_path}/uibase/build/src ${lib_path} - ${project_path}/../lz4/dll) + ${LZ4_ROOT}/dll) ADD_LIBRARY(${PROJ_NAME} SHARED ${${PROJ_NAME}_HDRS} ${${PROJ_NAME}_SRCS} ${${PROJ_NAME}_UIHDRS} ${${PROJ_NAME}_RCCPPS} ${${PROJ_NAME}_translations_qm}) From bd9ea31897bc95bb3f6f43ac2d1d9c8d991a2487 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Sandro=20J=C3=A4ckel?= Date: Tue, 6 Mar 2018 23:42:36 +0100 Subject: [PATCH 0447/1544] [game_fallout4] Changed lz4 path to var --- src/games/fallout4/.gitignore | 4 ++++ src/games/fallout4/CMakeLists.txt | 2 +- src/games/fallout4/src/CMakeLists.txt | 2 +- 3 files changed, 6 insertions(+), 2 deletions(-) diff --git a/src/games/fallout4/.gitignore b/src/games/fallout4/.gitignore index bcc50d34..4c4fa01e 100644 --- a/src/games/fallout4/.gitignore +++ b/src/games/fallout4/.gitignore @@ -2,3 +2,7 @@ CMakeLists.txt.user edit build std*.log +build +vsbuild +vs_stderr.log +vs_stdout.log diff --git a/src/games/fallout4/CMakeLists.txt b/src/games/fallout4/CMakeLists.txt index 950d7a0c..53ea565d 100644 --- a/src/games/fallout4/CMakeLists.txt +++ b/src/games/fallout4/CMakeLists.txt @@ -8,7 +8,7 @@ SET(DEPENDENCIES_DIR CACHE PATH "") # hint to find qt in dependencies path LIST(APPEND CMAKE_PREFIX_PATH ${QT_ROOT}/lib/cmake) -LIST(APPEND CMAKE_PREFIX_PATH ${DEPENDENCIES_DIR}/lz4/dll) +LIST(APPEND CMAKE_PREFIX_PATH ${LZ4_ROOT}/dll) FILE(GLOB_RECURSE BOOST_ROOT ${DEPENDENCIES_DIR}/boost*/project-config.jam) GET_FILENAME_COMPONENT(BOOST_ROOT ${BOOST_ROOT} DIRECTORY) diff --git a/src/games/fallout4/src/CMakeLists.txt b/src/games/fallout4/src/CMakeLists.txt index c52541f2..73c9c557 100644 --- a/src/games/fallout4/src/CMakeLists.txt +++ b/src/games/fallout4/src/CMakeLists.txt @@ -39,7 +39,7 @@ INCLUDE_DIRECTORIES(${project_path}/uibase/src ${project_path}/game_gamebryo/src) LINK_DIRECTORIES(${project_path}/uibase/build/src ${lib_path} - ${project_path}/../lz4/dll) + ${LZ4_ROOT}/dll) ADD_LIBRARY(${PROJ_NAME} SHARED ${${PROJ_NAME}_HDRS} ${${PROJ_NAME}_SRCS} ${${PROJ_NAME}_UIHDRS} ${${PROJ_NAME}_RCCPPS} ${${PROJ_NAME}_translations_qm}) From b2d9e54888f3208321d442be59ed857926bc92bb Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Sandro=20J=C3=A4ckel?= Date: Tue, 6 Mar 2018 23:43:32 +0100 Subject: [PATCH 0448/1544] [game_fallout3] Changed lz4 path to var --- src/games/fallout3/.gitignore | 4 ++++ src/games/fallout3/CMakeLists.txt | 2 +- src/games/fallout3/src/CMakeLists.txt | 2 +- 3 files changed, 6 insertions(+), 2 deletions(-) diff --git a/src/games/fallout3/.gitignore b/src/games/fallout3/.gitignore index bcc50d34..4c4fa01e 100644 --- a/src/games/fallout3/.gitignore +++ b/src/games/fallout3/.gitignore @@ -2,3 +2,7 @@ CMakeLists.txt.user edit build std*.log +build +vsbuild +vs_stderr.log +vs_stdout.log diff --git a/src/games/fallout3/CMakeLists.txt b/src/games/fallout3/CMakeLists.txt index da91acdd..ebc30185 100644 --- a/src/games/fallout3/CMakeLists.txt +++ b/src/games/fallout3/CMakeLists.txt @@ -8,7 +8,7 @@ SET(DEPENDENCIES_DIR CACHE PATH "") # hint to find qt in dependencies path LIST(APPEND CMAKE_PREFIX_PATH ${QT_ROOT}/lib/cmake) -LIST(APPEND CMAKE_PREFIX_PATH ${DEPENDENCIES_DIR}/lz4/dll) +LIST(APPEND CMAKE_PREFIX_PATH ${LZ4_ROOT}/dll) FILE(GLOB_RECURSE BOOST_ROOT ${DEPENDENCIES_DIR}/boost*/project-config.jam) GET_FILENAME_COMPONENT(BOOST_ROOT ${BOOST_ROOT} DIRECTORY) diff --git a/src/games/fallout3/src/CMakeLists.txt b/src/games/fallout3/src/CMakeLists.txt index 13759b52..6b2a0f5d 100644 --- a/src/games/fallout3/src/CMakeLists.txt +++ b/src/games/fallout3/src/CMakeLists.txt @@ -35,7 +35,7 @@ INCLUDE_DIRECTORIES(${project_path}/uibase/src ${project_path}/game_gamebryo/src) LINK_DIRECTORIES(${project_path}/uibase/build/src ${lib_path} - ${project_path}/../lz4/dll) + ${LZ4_ROOT}/dll) ADD_LIBRARY(${PROJ_NAME} SHARED ${${PROJ_NAME}_HDRS} ${${PROJ_NAME}_SRCS} ${${PROJ_NAME}_UIHDRS} ${${PROJ_NAME}_translations_qm}) From 5f1d268af4d98f9282ddb588d819969ee2b64466 Mon Sep 17 00:00:00 2001 From: Al12rs Date: Wed, 14 Mar 2018 20:32:51 +0100 Subject: [PATCH 0449/1544] [game_oblivion] Added missing DLC, DLCBattlehornCastle.esp to the DLC list as it was currently displayed as unmanaged instead. --- src/games/oblivion/src/gameoblivion.cpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/games/oblivion/src/gameoblivion.cpp b/src/games/oblivion/src/gameoblivion.cpp index 017f813f..091c5bc2 100644 --- a/src/games/oblivion/src/gameoblivion.cpp +++ b/src/games/oblivion/src/gameoblivion.cpp @@ -143,9 +143,9 @@ QStringList GameOblivion::iniFiles() const QStringList GameOblivion::DLCPlugins() const { - return { "DLCShiveringIsles.esp", "Knights.esp", "DLCFrostcrag.esp", + return { "DLCBattlehornCastle.esp", "DLCShiveringIsles.esp", "Knights.esp", "DLCFrostcrag.esp", "DLCSpellTomes.esp", "DLCMehrunesRazor.esp", "DLCOrrery.esp", - "DLCThievesDen.esp", "DLCVileLair.esp", "DLCHorseArmor.esp" }; + "DLCThievesDen.esp", "DLCVileLair.esp", "DLCHorseArmor.esp" }; } From 7ff4f165ba3fe0aa55ee6a5d65df8eddddb7393d Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Sandro=20J=C3=A4ckel?= Date: Fri, 16 Mar 2018 19:31:05 +0100 Subject: [PATCH 0450/1544] [game_ttw] Fixed wrong DLC order. Fixed renaming of plugin. Upstream changes. --- src/games/ttw/.gitignore | 2 ++ src/games/ttw/src/CMakeLists.txt | 2 +- .../ttw/src/falloutttwbsainvalidation.cpp | 6 ++-- src/games/ttw/src/gamefalloutttw.cpp | 35 +++++++++---------- 4 files changed, 23 insertions(+), 22 deletions(-) diff --git a/src/games/ttw/.gitignore b/src/games/ttw/.gitignore index 5477e9c4..08f775e4 100644 --- a/src/games/ttw/.gitignore +++ b/src/games/ttw/.gitignore @@ -2,3 +2,5 @@ std*.log build CMakeLists.txt.user edit +build +vsbuild diff --git a/src/games/ttw/src/CMakeLists.txt b/src/games/ttw/src/CMakeLists.txt index 13759b52..6b2a0f5d 100644 --- a/src/games/ttw/src/CMakeLists.txt +++ b/src/games/ttw/src/CMakeLists.txt @@ -35,7 +35,7 @@ INCLUDE_DIRECTORIES(${project_path}/uibase/src ${project_path}/game_gamebryo/src) LINK_DIRECTORIES(${project_path}/uibase/build/src ${lib_path} - ${project_path}/../lz4/dll) + ${LZ4_ROOT}/dll) ADD_LIBRARY(${PROJ_NAME} SHARED ${${PROJ_NAME}_HDRS} ${${PROJ_NAME}_SRCS} ${${PROJ_NAME}_UIHDRS} ${${PROJ_NAME}_translations_qm}) diff --git a/src/games/ttw/src/falloutttwbsainvalidation.cpp b/src/games/ttw/src/falloutttwbsainvalidation.cpp index d1359487..1b2b0e60 100644 --- a/src/games/ttw/src/falloutttwbsainvalidation.cpp +++ b/src/games/ttw/src/falloutttwbsainvalidation.cpp @@ -1,11 +1,11 @@ -#include "falloutnvbsainvalidation.h" +#include "falloutttwbsainvalidation.h" -FalloutTTWBSAInvalidation::FalloutNVBSAInvalidation(DataArchives *dataArchives, MOBase::IPluginGame const *game) +FalloutTTWBSAInvalidation::FalloutTTWBSAInvalidation(DataArchives *dataArchives, MOBase::IPluginGame const *game) : GamebryoBSAInvalidation(dataArchives, "fallout.ini", game) { } -QString FalloutNVBSAInvalidation::invalidationBSAName() const +QString FalloutTTWBSAInvalidation::invalidationBSAName() const { return "Fallout - Invalidation.bsa"; } diff --git a/src/games/ttw/src/gamefalloutttw.cpp b/src/games/ttw/src/gamefalloutttw.cpp index be7015f5..8c8053e1 100644 --- a/src/games/ttw/src/gamefalloutttw.cpp +++ b/src/games/ttw/src/gamefalloutttw.cpp @@ -1,6 +1,6 @@ #include "gamefalloutttw.h" -#include "falloutttwbsaittwalidation.h" +#include "falloutttwbsainvalidation.h" #include "falloutttwdataarchives.h" #include "falloutttwsavegameinfo.h" #include "falloutttwscriptextender.h" @@ -35,7 +35,7 @@ bool GameFalloutTTW::init(IOrganizer *moInfo) } registerFeature(new FalloutTTWScriptExtender(this)); registerFeature(new FalloutTTWDataArchives(myGamesPath())); - registerFeature(new FalloutTTWBSAIttwalidation(feature(), this)); + registerFeature(new FalloutTTWBSAInvalidation(feature(), this)); registerFeature(new FalloutTTWSaveGameInfo(this)); registerFeature(new GamebryoLocalSavegames(myGamesPath(), "fallout.ini")); registerFeature(new GamebryoGamePlugins(moInfo)); @@ -45,14 +45,14 @@ bool GameFalloutTTW::init(IOrganizer *moInfo) QString GameFalloutTTW::gameName() const { - return "New Vegas"; + return "TTW"; } QList GameFalloutTTW::executables() const { return QList() << ExecutableInfo("NVSE", findInGameFolder(feature()->loaderName())) - << ExecutableInfo("New Vegas", findInGameFolder(binaryName())) + << ExecutableInfo("Tale of Two Wastelands", findInGameFolder(binaryName())) << ExecutableInfo("Fallout Mod Manager", findInGameFolder("fomm/fomm.exe")) << ExecutableInfo("Construction Kit", findInGameFolder("geck.exe")) << ExecutableInfo("Fallout Launcher", findInGameFolder(getLauncherName())) @@ -68,7 +68,7 @@ QString GameFalloutTTW::name() const QString GameFalloutTTW::author() const { - return "Tannin"; + return "SuperSandro2000"; } QString GameFalloutTTW::description() const @@ -119,7 +119,7 @@ QString GameFalloutTTW::savegameExtension() const QString GameFalloutTTW::savegameSEExtension() const { - return "ttwse"; + return "nvse"; } QString GameFalloutTTW::steamAPPId() const @@ -129,17 +129,16 @@ QString GameFalloutTTW::steamAPPId() const QStringList GameFalloutTTW::primaryPlugins() const { - return { "falloutnv.esm", "deadmoney.esm", "honesthearts.esm", + return { "falloutnv.esm", "deadmoney.esm", "honesthearts.esm", "oldworldblues.esm", "lonesomeroad.esm", "gunrunnersarsenal.esm", - "caravanpack.esm", "classicpack.esm", "mercenarypack.esm", - "tribalpack.esm", "fallout3.esm", "anchorage.esm", "thepitt.esm", - "brokensteel.esm", "pointlookout.esm", "zeta.esm", - "taleoftwowastelands.esm" }; + "fallout3.esm", "anchorage.esm", "thepitt.esm", "brokensteel.esm", + "pointlookout.esm", "zeta.esm", "caravanpack.esm", "classicpack.esm", + "mercenarypack.esm", "tribalpack.esm", "taleoftwowastelands.esm" }; } QString GameFalloutTTW::gameShortName() const { - return "FalloutTTW"; + return "FalloutNV"; } QString GameFalloutTTW::gameNexusName() const @@ -154,12 +153,12 @@ QStringList GameFalloutTTW::iniFiles() const QStringList GameFalloutTTW::DLCPlugins() const { - return { "DeadMoney.esm", "HonestHearts.esm", "OldWorldBlues.esm", - "LonesomeRoad.esm", "GunRunnersArsenal.esm", "CaravanPack.esm", - "ClassicPack.esm", "MercenaryPack.esm", "TribalPack.esm", - "Fallout3.esm", "Anchorage.esm", "ThePitt.esm", - "BrokenSteel.esm", "PointLookout.esm", "Zeta.esm", - "TaleOfTwoWastelands.esm"}; + return { "FalloutNV.esm", "DeadMoney.esm", "HonestHearts.esm", + "OldWorldBlues.esm", "LonesomeRoad.esm", "GunRunnersArsenal.esm", + "CaravanPack.esm", "ClassicPack.esm", "MercenaryPack.esm", + "TribalPack.esm", "Fallout3.esm", "Anchorage.esm", + "ThePitt.esm", "BrokenSteel.esm", "PointLookout.esm", + "Zeta.esm", "TaleOfTwoWastelands.esm"}; } int GameFalloutTTW::nexusModOrganizerID() const From 52319e3f9dce6ece1a31abcd7987955f4027dfb0 Mon Sep 17 00:00:00 2001 From: Jeremy Rimpo Date: Tue, 20 Mar 2018 01:26:32 -0500 Subject: [PATCH 0451/1544] Rework plugin loadorder parsing --- src/gamebryogameplugins.cpp | 184 ++++++++++++++++++++---------------- src/gamebryogameplugins.h | 3 +- 2 files changed, 102 insertions(+), 85 deletions(-) diff --git a/src/gamebryogameplugins.cpp b/src/gamebryogameplugins.cpp index fcb9de8f..db24b580 100644 --- a/src/gamebryogameplugins.cpp +++ b/src/gamebryogameplugins.cpp @@ -51,12 +51,10 @@ void GamebryoGamePlugins::readPluginLists(MOBase::IPluginList *pluginList) { if (loadOrderIsNew || !pluginsIsNew) { // read both files if they are both new or both older than the last read readLoadOrderList(pluginList, loadOrderPath); - readPluginList(pluginList, pluginsPath, false); + readPluginList(pluginList, false); } else { - // if the plugin list is new but the load order isn't, this probably means - // an external tool that handles only the plugins.txt has been run in the - // meantime. We have to use plugins.txt for the load order as well. - readPluginList(pluginList, pluginsPath, true); + // If the plugins is new but not loadorder, we must reparse the load order from the plugin files + readPluginList(pluginList, true); } m_LastRead = QDateTime::currentDateTime(); @@ -125,96 +123,116 @@ void GamebryoGamePlugins::writeList(const IPluginList *pluginList, bool GamebryoGamePlugins::readLoadOrderList(MOBase::IPluginList *pluginList, const QString &filePath) { - QStringList pluginNames = organizer()->managedGame()->primaryPlugins(); - QFile file(filePath); - if (!file.open(QIODevice::ReadOnly)) { - // no load order stored, determine by date - pluginNames = pluginList->pluginNames(); + QFile file(filePath); + if (!file.open(QIODevice::ReadOnly)) { + readPluginList(pluginList, true); + } else { + QStringList plugins = organizer()->managedGame()->primaryPlugins(); - std::sort(pluginNames.begin(), pluginNames.end(), [&](const QString &lhs, const QString &rhs) { - MOBase::IModInterface *lhm = organizer()->getMod(pluginList->origin(lhs)); - MOBase::IModInterface *rhm = organizer()->getMod(pluginList->origin(rhs)); - QDir lhd = organizer()->managedGame()->dataDirectory(); - QDir rhd = organizer()->managedGame()->dataDirectory(); - if (lhm != nullptr) - lhd = lhm->absolutePath(); - if (rhm != nullptr) - rhd = rhm->absolutePath(); - QString lhp = lhd.absoluteFilePath(lhs); - QString rhp = rhd.absoluteFilePath(rhs); - return QFileInfo(lhp).lastModified() < - QFileInfo(rhp).lastModified(); - }); - } else { - ON_BLOCK_EXIT([&file]() { file.close(); }); + ON_BLOCK_EXIT([&file]() { file.close(); }); - if (file.size() == 0) { - // MO stores at least a header in the file. if it's completely empty the - // file is broken - return false; - } - 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 (!pluginNames.contains(modName, Qt::CaseInsensitive)) { - pluginNames.append(modName); + if (file.size() == 0) { + // MO stores at least a header in the file. if it's completely empty the + // file is broken + return false; } - } - } - } - pluginList->setLoadOrder(pluginNames); + while (!file.atEnd()) { + QByteArray line = file.readLine().trimmed(); + QString modName; + if ((line.size() > 0) && (line.at(0) != '#')) { + modName = QString::fromUtf8(line.constData()).toLower(); + } - return true; + if (modName.size() > 0) { + if (!plugins.contains(modName, Qt::CaseInsensitive)) { + plugins.append(modName); + } + } + } + + pluginList->setLoadOrder(plugins); + } + + return true; } bool GamebryoGamePlugins::readPluginList(MOBase::IPluginList *pluginList, - const QString &filePath, bool useLoadOrder) { + QStringList primary = organizer()->managedGame()->primaryPlugins(); + for (const QString &pluginName : primary) { + if (pluginList->state(pluginName) != IPluginList::STATE_MISSING) { + pluginList->setState(pluginName, IPluginList::STATE_ACTIVE); + } + } QStringList plugins = pluginList->pluginNames(); - - QFile file(filePath); - if (!file.open(QIODevice::ReadOnly)) { - return false; - } - ON_BLOCK_EXIT([&]() { - qDebug("close %s", qPrintable(filePath)); - file.close(); - }); - - if (file.size() == 0) { - // MO stores at least a header in the file. if it's completely empty the - // file is broken - return false; - } - - QStringList loadOrder; - while (!file.atEnd()) { - QByteArray line = file.readLine(); - QString pluginName; - if ((line.size() > 0) && (line.at(0) != '#')) { - pluginName = m_LocalCodec->toUnicode(line.trimmed().constData()); - } - if (pluginName.size() > 0) { - pluginList->setState(pluginName, IPluginList::STATE_ACTIVE); - plugins.removeAll(pluginName); - loadOrder.append(pluginName); - } - } - - file.close(); - - // we removed each plugin found in the file, so what's left are inactive mods - for (const QString &pluginName : plugins) { - pluginList->setState(pluginName, IPluginList::STATE_INACTIVE); + // Do not sort the primary plugins. Their load order should be locked as defined in "primaryPlugins". + for (QString plugin : plugins) { + if (primary.contains(plugin, Qt::CaseInsensitive)) + plugins.removeAll(plugin); } if (useLoadOrder) { - pluginList->setLoadOrder(loadOrder); + // Always use filetime loadorder to get the actual load order + std::sort(plugins.begin(), plugins.end(), [&](const QString &lhs, const QString &rhs) { + MOBase::IModInterface *lhm = organizer()->getMod(pluginList->origin(lhs)); + MOBase::IModInterface *rhm = organizer()->getMod(pluginList->origin(rhs)); + QDir lhd = organizer()->managedGame()->dataDirectory(); + QDir rhd = organizer()->managedGame()->dataDirectory(); + if (lhm != nullptr) + lhd = lhm->absolutePath(); + if (rhm != nullptr) + rhd = rhm->absolutePath(); + QString lhp = lhd.absoluteFilePath(lhs); + QString rhp = rhd.absoluteFilePath(rhs); + return QFileInfo(lhp).lastModified() < + QFileInfo(rhp).lastModified(); + }); + + // Add the primary plugins to the beginning of the load order + pluginList->setLoadOrder(primary + plugins); + } + + // Determine plugin active state by the plugins.txt file. + bool pluginsTxtExists = true; + QString filePath = organizer()->profile()->absolutePath() + "/plugins.txt"; + QFile file(filePath); + if (!file.open(QIODevice::ReadOnly)) { + pluginsTxtExists = false; + } + ON_BLOCK_EXIT([&]() { + qDebug("close %s", qPrintable(filePath)); + file.close(); + }); + + if (file.size() == 0) { + // MO stores at least a header in the file. if it's completely empty the + // file is broken + pluginsTxtExists = false; + } + + if (pluginsTxtExists) { + while (!file.atEnd()) { + QByteArray line = file.readLine(); + QString pluginName; + if ((line.size() > 0) && (line.at(0) != '#')) { + pluginName = m_LocalCodec->toUnicode(line.trimmed().constData()); + } + if (pluginName.size() > 0) { + pluginList->setState(pluginName, IPluginList::STATE_ACTIVE); + plugins.removeAll(pluginName); + } + } + + file.close(); + + // we removed each plugin found in the file, so what's left are inactive mods + for (const QString &pluginName : plugins) { + pluginList->setState(pluginName, IPluginList::STATE_INACTIVE); + } + } else { + for (const QString &pluginName : plugins) { + pluginList->setState(pluginName, IPluginList::STATE_INACTIVE); + } } return true; diff --git a/src/gamebryogameplugins.h b/src/gamebryogameplugins.h index 5676ed15..b41c5395 100644 --- a/src/gamebryogameplugins.h +++ b/src/gamebryogameplugins.h @@ -26,8 +26,7 @@ protected: const QString &filePath); virtual bool readLoadOrderList(MOBase::IPluginList *pluginList, const QString &filePath); - virtual bool readPluginList(MOBase::IPluginList *pluginList, - const QString &filePath, bool useLoadOrder); + virtual bool readPluginList(MOBase::IPluginList *pluginList, bool useLoadOrder); private: void writeList(const MOBase::IPluginList *pluginList, const QString &filePath, From 2985f3b802f64e465d0a8470b8881fe9b929ea69 Mon Sep 17 00:00:00 2001 From: Jeremy Rimpo Date: Tue, 20 Mar 2018 01:26:32 -0500 Subject: [PATCH 0452/1544] [game_fallout4vr] Rework plugin loadorder parsing --- src/games/fallout4vr/src/fallout4vrgameplugins.cpp | 3 ++- src/games/fallout4vr/src/fallout4vrgameplugins.h | 1 - 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/src/games/fallout4vr/src/fallout4vrgameplugins.cpp b/src/games/fallout4vr/src/fallout4vrgameplugins.cpp index 1e8c46c8..daf5ed90 100644 --- a/src/games/fallout4vr/src/fallout4vrgameplugins.cpp +++ b/src/games/fallout4vr/src/fallout4vrgameplugins.cpp @@ -92,7 +92,6 @@ void Fallout4VRGamePlugins::writePluginList(const IPluginList *pluginList, } bool Fallout4VRGamePlugins::readPluginList(MOBase::IPluginList *pluginList, - const QString &filePath, bool useLoadOrder) { QStringList plugins = pluginList->pluginNames(); @@ -105,6 +104,8 @@ bool Fallout4VRGamePlugins::readPluginList(MOBase::IPluginList *pluginList, } } + + QString filePath = organizer()->profile()->absolutePath() + "/plugins.txt"; QFile file(filePath); if (!file.open(QIODevice::ReadOnly)) { qWarning("%s not found", qPrintable(filePath)); diff --git a/src/games/fallout4vr/src/fallout4vrgameplugins.h b/src/games/fallout4vr/src/fallout4vrgameplugins.h index 407f4e89..8eb21375 100644 --- a/src/games/fallout4vr/src/fallout4vrgameplugins.h +++ b/src/games/fallout4vr/src/fallout4vrgameplugins.h @@ -17,7 +17,6 @@ protected: virtual void writePluginList(const MOBase::IPluginList *pluginList, const QString &filePath) override; virtual bool readPluginList(MOBase::IPluginList *pluginList, - const QString &filePath, bool useLoadOrder) override; private: From 90f1c43226ba8f5706521411f010061345ac1a34 Mon Sep 17 00:00:00 2001 From: Jeremy Rimpo Date: Tue, 20 Mar 2018 01:26:32 -0500 Subject: [PATCH 0453/1544] [game_fallout76] Rework plugin loadorder parsing --- src/games/fallout76/src/fallout4gameplugins.cpp | 2 +- src/games/fallout76/src/fallout4gameplugins.h | 1 - 2 files changed, 1 insertion(+), 2 deletions(-) diff --git a/src/games/fallout76/src/fallout4gameplugins.cpp b/src/games/fallout76/src/fallout4gameplugins.cpp index 588bbb89..678d63e0 100644 --- a/src/games/fallout76/src/fallout4gameplugins.cpp +++ b/src/games/fallout76/src/fallout4gameplugins.cpp @@ -92,7 +92,6 @@ void Fallout4GamePlugins::writePluginList(const IPluginList *pluginList, } bool Fallout4GamePlugins::readPluginList(MOBase::IPluginList *pluginList, - const QString &filePath, bool useLoadOrder) { QStringList plugins = pluginList->pluginNames(); @@ -105,6 +104,7 @@ bool Fallout4GamePlugins::readPluginList(MOBase::IPluginList *pluginList, } } + QString filePath = organizer()->profile()->absolutePath() + "/plugins.txt"; QFile file(filePath); if (!file.open(QIODevice::ReadOnly)) { qWarning("%s not found", qPrintable(filePath)); diff --git a/src/games/fallout76/src/fallout4gameplugins.h b/src/games/fallout76/src/fallout4gameplugins.h index 1e3aef1f..091c5ce5 100644 --- a/src/games/fallout76/src/fallout4gameplugins.h +++ b/src/games/fallout76/src/fallout4gameplugins.h @@ -17,7 +17,6 @@ protected: virtual void writePluginList(const MOBase::IPluginList *pluginList, const QString &filePath) override; virtual bool readPluginList(MOBase::IPluginList *pluginList, - const QString &filePath, bool useLoadOrder) override; private: From 1f9b606a5aec01ef056801cab72474f7a68e168b Mon Sep 17 00:00:00 2001 From: Jeremy Rimpo Date: Tue, 20 Mar 2018 01:26:32 -0500 Subject: [PATCH 0454/1544] [game_fallout4] Rework plugin loadorder parsing --- src/games/fallout4/src/fallout4gameplugins.cpp | 2 +- src/games/fallout4/src/fallout4gameplugins.h | 1 - 2 files changed, 1 insertion(+), 2 deletions(-) diff --git a/src/games/fallout4/src/fallout4gameplugins.cpp b/src/games/fallout4/src/fallout4gameplugins.cpp index 588bbb89..678d63e0 100644 --- a/src/games/fallout4/src/fallout4gameplugins.cpp +++ b/src/games/fallout4/src/fallout4gameplugins.cpp @@ -92,7 +92,6 @@ void Fallout4GamePlugins::writePluginList(const IPluginList *pluginList, } bool Fallout4GamePlugins::readPluginList(MOBase::IPluginList *pluginList, - const QString &filePath, bool useLoadOrder) { QStringList plugins = pluginList->pluginNames(); @@ -105,6 +104,7 @@ bool Fallout4GamePlugins::readPluginList(MOBase::IPluginList *pluginList, } } + QString filePath = organizer()->profile()->absolutePath() + "/plugins.txt"; QFile file(filePath); if (!file.open(QIODevice::ReadOnly)) { qWarning("%s not found", qPrintable(filePath)); diff --git a/src/games/fallout4/src/fallout4gameplugins.h b/src/games/fallout4/src/fallout4gameplugins.h index 1e3aef1f..091c5ce5 100644 --- a/src/games/fallout4/src/fallout4gameplugins.h +++ b/src/games/fallout4/src/fallout4gameplugins.h @@ -17,7 +17,6 @@ protected: virtual void writePluginList(const MOBase::IPluginList *pluginList, const QString &filePath) override; virtual bool readPluginList(MOBase::IPluginList *pluginList, - const QString &filePath, bool useLoadOrder) override; private: From 86451919aac9da160858e10aafa86b05c8c9b37d Mon Sep 17 00:00:00 2001 From: Jeremy Rimpo Date: Tue, 20 Mar 2018 01:26:33 -0500 Subject: [PATCH 0455/1544] [game_skyrimse] Rework plugin loadorder parsing --- src/games/skyrimse/src/skyrimsegameplugins.cpp | 2 +- src/games/skyrimse/src/skyrimsegameplugins.h | 1 - 2 files changed, 1 insertion(+), 2 deletions(-) diff --git a/src/games/skyrimse/src/skyrimsegameplugins.cpp b/src/games/skyrimse/src/skyrimsegameplugins.cpp index ec77487a..7657ab9b 100644 --- a/src/games/skyrimse/src/skyrimsegameplugins.cpp +++ b/src/games/skyrimse/src/skyrimsegameplugins.cpp @@ -89,7 +89,6 @@ void SkyrimSEGamePlugins::writePluginList(const IPluginList *pluginList, } bool SkyrimSEGamePlugins::readPluginList(MOBase::IPluginList *pluginList, - const QString &filePath, bool useLoadOrder) { QStringList plugins = pluginList->pluginNames(); @@ -102,6 +101,7 @@ bool SkyrimSEGamePlugins::readPluginList(MOBase::IPluginList *pluginList, } } + QString filePath = organizer()->profile()->absolutePath() + "/plugins.txt"; QFile file(filePath); if (!file.open(QIODevice::ReadOnly)) { qWarning("%s not found", qPrintable(filePath)); diff --git a/src/games/skyrimse/src/skyrimsegameplugins.h b/src/games/skyrimse/src/skyrimsegameplugins.h index ecf733d2..3ef14f71 100644 --- a/src/games/skyrimse/src/skyrimsegameplugins.h +++ b/src/games/skyrimse/src/skyrimsegameplugins.h @@ -17,7 +17,6 @@ protected: virtual void writePluginList(const MOBase::IPluginList *pluginList, const QString &filePath) override; virtual bool readPluginList(MOBase::IPluginList *pluginList, - const QString &filePath, bool useLoadOrder) override; private: From f5cdc7a143319abfb328640f2b3037f0758f6939 Mon Sep 17 00:00:00 2001 From: Jeremy Rimpo Date: Tue, 20 Mar 2018 01:26:33 -0500 Subject: [PATCH 0456/1544] [game_skyrim] Rework plugin loadorder parsing --- src/games/skyrim/src/gameskyrim.cpp | 3 +- src/games/skyrim/src/skyrimgameplugins.cpp | 93 ++++++++++++++++++++++ src/games/skyrim/src/skyrimgameplugins.h | 27 +++++++ 3 files changed, 122 insertions(+), 1 deletion(-) create mode 100644 src/games/skyrim/src/skyrimgameplugins.cpp create mode 100644 src/games/skyrim/src/skyrimgameplugins.h diff --git a/src/games/skyrim/src/gameskyrim.cpp b/src/games/skyrim/src/gameskyrim.cpp index 0c07aced..f1b06e1a 100644 --- a/src/games/skyrim/src/gameskyrim.cpp +++ b/src/games/skyrim/src/gameskyrim.cpp @@ -4,6 +4,7 @@ #include "skyrimscriptextender.h" #include "skyrimdataarchives.h" #include "skyrimsavegameinfo.h" +#include "skyrimgameplugins.h" #include "executableinfo.h" #include "pluginsetting.h" @@ -43,7 +44,7 @@ bool GameSkyrim::init(IOrganizer *moInfo) registerFeature(new SkyrimBSAInvalidation(feature(), this)); registerFeature(new SkyrimSaveGameInfo(this)); registerFeature(new GamebryoLocalSavegames(myGamesPath(), "skyrim.ini")); - registerFeature(new GamebryoGamePlugins(moInfo)); + registerFeature(new SkyrimGamePlugins(moInfo)); registerFeature(new GamebryoUnmangedMods(this)); return true; } diff --git a/src/games/skyrim/src/skyrimgameplugins.cpp b/src/games/skyrim/src/skyrimgameplugins.cpp new file mode 100644 index 00000000..94fad0f4 --- /dev/null +++ b/src/games/skyrim/src/skyrimgameplugins.cpp @@ -0,0 +1,93 @@ +#include "skyrimgameplugins.h" +#include +#include +#include +#include +#include + +#include +#include +#include + + +using MOBase::IPluginGame; +using MOBase::IPluginList; +using MOBase::IOrganizer; +using MOBase::SafeWriteFile; +using MOBase::reportError; + +SkyrimGamePlugins::SkyrimGamePlugins(IOrganizer *organizer) + : GamebryoGamePlugins(organizer) +{ + m_LocalCodec = QTextCodec::codecForName("Windows-1252"); +} + +bool SkyrimGamePlugins::readPluginList(MOBase::IPluginList *pluginList, + bool useLoadOrder) +{ + QStringList plugins = pluginList->pluginNames(); + QStringList primaryPlugins = organizer()->managedGame()->primaryPlugins(); + QStringList loadOrder(primaryPlugins); + + for (const QString &pluginName : loadOrder) { + if (pluginList->state(pluginName) != IPluginList::STATE_MISSING) { + pluginList->setState(pluginName, IPluginList::STATE_ACTIVE); + } + } + + // Do not sort the primary plugins. Their load order should be locked as defined in "primaryPlugins". + for (QString plugin : plugins) { + if (primaryPlugins.contains(plugin, Qt::CaseInsensitive)) + plugins.removeAll(plugin); + } + + // Determine plugin active state by the plugins.txt file. + bool pluginsTxtExists = true; + QString filePath = organizer()->profile()->absolutePath() + "/plugins.txt"; + QFile file(filePath); + if (!file.open(QIODevice::ReadOnly)) { + pluginsTxtExists = false; + } + ON_BLOCK_EXIT([&]() { + qDebug("close %s", qPrintable(filePath)); + file.close(); + }); + + if (file.size() == 0) { + // MO stores at least a header in the file. if it's completely empty the + // file is broken + pluginsTxtExists = false; + } + + if (pluginsTxtExists) { + while (!file.atEnd()) { + QByteArray line = file.readLine(); + QString pluginName; + if ((line.size() > 0) && (line.at(0) != '#')) { + pluginName = m_LocalCodec->toUnicode(line.trimmed().constData()); + } + if (pluginName.size() > 0) { + pluginList->setState(pluginName, IPluginList::STATE_ACTIVE); + plugins.removeAll(pluginName); + loadOrder.append(pluginName); + } + } + + file.close(); + + // we removed each plugin found in the file, so what's left are inactive mods + for (const QString &pluginName : plugins) { + pluginList->setState(pluginName, IPluginList::STATE_INACTIVE); + } + } else { + for (const QString &pluginName : plugins) { + pluginList->setState(pluginName, IPluginList::STATE_INACTIVE); + } + } + + if (useLoadOrder) { + pluginList->setLoadOrder(loadOrder); + } + + return true; +} diff --git a/src/games/skyrim/src/skyrimgameplugins.h b/src/games/skyrim/src/skyrimgameplugins.h new file mode 100644 index 00000000..13839af4 --- /dev/null +++ b/src/games/skyrim/src/skyrimgameplugins.h @@ -0,0 +1,27 @@ +#ifndef _SKYRIMGAMEPLUGINS_H +#define _SKYRIMGAMEPLUGINS_H + + +#include +#include +#include +#include + + +class SkyrimGamePlugins : public GamebryoGamePlugins +{ +public: + SkyrimGamePlugins(MOBase::IOrganizer *organizer); + +protected: + virtual bool readPluginList(MOBase::IPluginList *pluginList, + bool useLoadOrder) override; + +private: + std::map m_LastSaveHash; + +private: + QTextCodec *m_LocalCodec; +}; + +#endif // _SKYRIMSEGAMEPLUGINS_H From 3bdea54cbafbcc5446dcee68622f1180165da817 Mon Sep 17 00:00:00 2001 From: Jeremy Rimpo Date: Tue, 20 Mar 2018 01:29:31 -0500 Subject: [PATCH 0457/1544] Various save game improvements related to script extender files * Improve handling of SE save transfers and deletes with main save * Add indicator in save popup dialog if SE save file is present --- src/gamebryosavegame.cpp | 12 ++++++++++++ src/gamebryosavegame.h | 2 ++ src/gamebryosavegameinfo.cpp | 6 ++++++ src/gamebryosavegameinfo.h | 2 ++ src/gamebryosavegameinfowidget.cpp | 6 ++++++ 5 files changed, 28 insertions(+) diff --git a/src/gamebryosavegame.cpp b/src/gamebryosavegame.cpp index 05ddf6eb..fae0a24f 100644 --- a/src/gamebryosavegame.cpp +++ b/src/gamebryosavegame.cpp @@ -55,10 +55,22 @@ QStringList GamebryoSaveGame::allFiles() const res.push_back(name.absoluteFilePath()); } } + + QFileInfo SEfile(file.absolutePath() + "/" + file.completeBaseName() + "." + m_Game->savegameSEExtension()); + if (SEfile.exists()) { + res.push_back(SEfile.absoluteFilePath()); + } } return res; } +bool GamebryoSaveGame::hasScriptExtenderFile() const +{ + QFileInfo file(m_FileName); + QFileInfo SEfile(file.absolutePath() + "/" + file.completeBaseName() + "." + m_Game->savegameSEExtension()); + return SEfile.exists(); +} + void GamebryoSaveGame::setCreationTime(_SYSTEMTIME const &ctime) { QDate date; diff --git a/src/gamebryosavegame.h b/src/gamebryosavegame.h index 72814b43..b956fda9 100644 --- a/src/gamebryosavegame.h +++ b/src/gamebryosavegame.h @@ -31,6 +31,8 @@ public: virtual QStringList allFiles() const override; + virtual bool hasScriptExtenderFile() const override; + //Simple getters QString getPCName() const { return m_PCName; } unsigned short getPCLevel() const { return m_PCLevel; } diff --git a/src/gamebryosavegameinfo.cpp b/src/gamebryosavegameinfo.cpp index 946947bb..12f723fa 100644 --- a/src/gamebryosavegameinfo.cpp +++ b/src/gamebryosavegameinfo.cpp @@ -99,3 +99,9 @@ MOBase::ISaveGameInfoWidget *GamebryoSaveGameInfo::getSaveGameWidget(QWidget *pa { return new GamebryoSaveGameInfoWidget(this, parent); } + +bool GamebryoSaveGameInfo::hasScriptExtenderSave(QString const &file) const +{ + GamebryoSaveGame const *save = dynamic_cast(getSaveGameInfo(file)); + return save->hasScriptExtenderFile(); +} diff --git a/src/gamebryosavegameinfo.h b/src/gamebryosavegameinfo.h index 89c88e58..60df58e6 100644 --- a/src/gamebryosavegameinfo.h +++ b/src/gamebryosavegameinfo.h @@ -15,6 +15,8 @@ public: virtual MOBase::ISaveGameInfoWidget *getSaveGameWidget(QWidget *) const override; + virtual bool hasScriptExtenderSave(QString const &file) const override; + protected: friend class GamebryoSaveGameInfoWidget; GameGamebryo const *m_Game; diff --git a/src/gamebryosavegameinfowidget.cpp b/src/gamebryosavegameinfowidget.cpp index a05e4659..d003c5b2 100644 --- a/src/gamebryosavegameinfowidget.cpp +++ b/src/gamebryosavegameinfowidget.cpp @@ -69,6 +69,12 @@ void GamebryoSaveGameInfoWidget::setSave(QString const &file) { this->resize(0, 0); QLayout *layout = ui->gameFrame->layout(); + if (m_Info->hasScriptExtenderSave(file)) { + QLabel *scriptExtender = new QLabel(tr("Has Script Extender Data")); + QFont headerFont = scriptExtender->font(); + headerFont.setBold(true); + layout->addWidget(scriptExtender); + } QLabel *header = new QLabel(tr("Missing ESPs")); QFont headerFont = header->font(); QFont contentFont = headerFont; From 2f43c2a20b9efb98efce8a5829a310e08e7d6a68 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Sandro=20J=C3=A4ckel?= Date: Wed, 21 Mar 2018 18:36:24 +0100 Subject: [PATCH 0458/1544] [game_morrowind] Added custom splash --- src/games/morrowind/src/CMakeLists.txt | 11 ++++++++--- src/games/morrowind/src/gamemorrowind.cpp | 5 +++-- src/games/morrowind/src/morrowind.qrc | 5 +++++ src/games/morrowind/src/splash.png | Bin 0 -> 83336 bytes 4 files changed, 16 insertions(+), 5 deletions(-) create mode 100644 src/games/morrowind/src/morrowind.qrc create mode 100644 src/games/morrowind/src/splash.png diff --git a/src/games/morrowind/src/CMakeLists.txt b/src/games/morrowind/src/CMakeLists.txt index b9895cea..f9e8de37 100644 --- a/src/games/morrowind/src/CMakeLists.txt +++ b/src/games/morrowind/src/CMakeLists.txt @@ -6,12 +6,16 @@ FILE(GLOB ${PROJ_NAME}_SRCS *.cpp) FILE(GLOB ${PROJ_NAME}_HDRS *.h) FILE(GLOB ${PROJ_NAME}_FORMS *.ui) +SET(${PROJ_NAME}_QRCS + morrowind.qrc + ) SET(CMAKE_INCLUDE_CURRENT_DIR ON) SET(CMAKE_AUTOMOC ON) SET(CMAKE_AUTOUIC ON) FIND_PACKAGE(Qt5Widgets REQUIRED) QT5_WRAP_UI(${PROJ_NAME}_UIHDRS ${${PROJ_NAME}_FORMS}) +QT5_ADD_RESOURCES(${PROJ_NAME}_RCCPPS ${${PROJ_NAME}_QRCS}) FIND_PACKAGE(Qt5LinguistTools) QT5_CREATE_TRANSLATION(${PROJ_NAME}_translations_qm ${CMAKE_SOURCE_DIR}/src ${CMAKE_SOURCE_DIR}/src/${PROJ_NAME}_en.ts) @@ -39,14 +43,14 @@ LINK_DIRECTORIES(${project_path}/uibase/build/src ADD_DEFINITIONS(-DUNICODE -D_UNICODE) -ADD_LIBRARY(${PROJ_NAME} SHARED ${${PROJ_NAME}_HDRS} ${${PROJ_NAME}_SRCS} ${${PROJ_NAME}_UIHDRS} ${${PROJ_NAME}_translations_qm}) +ADD_LIBRARY(${PROJ_NAME} SHARED ${${PROJ_NAME}_HDRS} ${${PROJ_NAME}_SRCS} ${${PROJ_NAME}_UIHDRS} ${${PROJ_NAME}_RCCPPS} ${${PROJ_NAME}_translations_qm}) TARGET_LINK_LIBRARIES(${PROJ_NAME} Qt5::Widgets ${Boost_LIBRARIES} - DbgHelp + DbgHelp uibase game_gamebryo - liblz4 + liblz4 version) IF(MSVC) @@ -64,6 +68,7 @@ ENDIF() QT5_USE_MODULES(${PROJ_NAME} Widgets) + ############### ## Installation diff --git a/src/games/morrowind/src/gamemorrowind.cpp b/src/games/morrowind/src/gamemorrowind.cpp index f5f88d08..76935d29 100644 --- a/src/games/morrowind/src/gamemorrowind.cpp +++ b/src/games/morrowind/src/gamemorrowind.cpp @@ -95,12 +95,13 @@ QString GameMorrowind::author() const QString GameMorrowind::description() const { - return tr("Adds support for the game Morrowind"); + return tr("Adds support for the game Morrowind.\n" + "Splash by %1").arg("AnyOldName"); } MOBase::VersionInfo GameMorrowind::version() const { - return VersionInfo(0, 1, 0, VersionInfo::RELEASE_FINAL); + return VersionInfo(0, 2, 0, VersionInfo::RELEASE_FINAL); } bool GameMorrowind::isActive() const diff --git a/src/games/morrowind/src/morrowind.qrc b/src/games/morrowind/src/morrowind.qrc new file mode 100644 index 00000000..b3802a08 --- /dev/null +++ b/src/games/morrowind/src/morrowind.qrc @@ -0,0 +1,5 @@ + + + splash.png + + \ No newline at end of file diff --git a/src/games/morrowind/src/splash.png b/src/games/morrowind/src/splash.png new file mode 100644 index 0000000000000000000000000000000000000000..7914180d382c89df4c3c1d1c092cee04957849dc GIT binary patch literal 83336 zcmeAS@N?(olHy`uVBq!ia0y~yVEoR&z);G;#=yW3T(!c1fq{XsILO_JVcj{ImkbOH zEa{HEjtmSN`?>!lvNA9*a29w(7BevL9R^{>8UgaP#eG7*YS5kR-xwe*& zSy|JKwH>k@67yHAkkH`bVl(^jFIg`^e%tZA+uvFI-}&9Bf-SqY`0Tvm-j98et3$cB z29S^bnhGh0U;Bm3NCTU%TEr6nb83knNYe);g>hlH?j^F-x#B{eOMFMEQUx7Sa(CBPmm zIc?>N6*1*SMOE7B>gDt9)OpYN$6@Gr&p$Ty@4X3%%oAqX@k?LVJ9zKTRg0&RY z4mao%$Q zZ8~v*l(3{+$3y2`k3YREU7=;&p}l;%@{Rj)Tt$=CpX`omK40JG;czbNzMf3F|I-I| zPjhS3Z{TPCU6yd*(9VO${UPoZOsp?{QNR%(b9zx z;^I#mW2My=EGiM#n{&2p=1fo4*3#ULMXmqDh2}3t+xwrJB($i1u~Tfp-zz~P@eyqL{JZ&|=-v77 zWBG|wckZlNwd9Ayy7^~azMo?h5E9zs@lK4lzg|&P>v0Hg=udu4|9V@ zUg3ZK-+JvI0fB)RH;352EYZLD;LHBD8z#Ndh4PzDoL_eSb@Od;Bg5PnA?Ab6SDyJk ze|pYxJLQt@KO0`IRZDXI%=x7zaKd`siuB8czYf%BXr9=kw7q$=y4phj^AgK$BwOCs zz2c;M#pyporJu}Hhb|-0^LcCC-^XpN&tU!h`SW|-o!e#xzdQf#nZd(jQ-0S^YT05U z5;sL`-J!pSt`?M*uE;9+FFEPTwQG8{CGRbkuSxfR!xWgPxa`J$>#U0&VMUuJou9t^ z%kjNUq7@%A^nHAJwNCEcneczVOWV75dGh!6=^S|V)c8ipxgBob|My<8%+1Tcvv&*6 z=4Ibf-+ORqzOwB-_1FCO{@t5jUS|&vTlD0W8(UNH3C%?_i_9O`KuV9l%vWr+lP%84 zMm1#rT)881gWQrmo2BR1_AjZay=yNTA9GOi`=&={FI>OA`}U7F_HMUkb*0w3?wq_} z?q=g^NxAs*hfdmVPDow%d*+<4QuF@lS4s~147PxJ< zqfhSdvywH~Yp#P_QXjap`^L@4{p;%Xveqqk1&Ha_q2H8R7M_P72IyTc}j^(}{ z&P7jqf*1ol^PBN`{E;Z$Mtx(Lxi+8+!{(n*PIzHrGZo04hfyjF~b|n%2zv=ux z$lG7nF(p^`>pqcZy3g94pMS2K{&niLA8-D1Z50#~(g~O{y~;h+f8l*6-gE!6U+zBj z_vBh#`z3eYn+3nSe7r0V>YVeFIy=uj4hkxY6>3sYQ~Q&1ei>&)Wxe#Cy>o9UnYOaU z@1Kz4(C~fw#>2t}#WhM^db-E=p4K+l5U;Mb;)dP*`^wAyOr9Z>;?!3WJ=-i-ZKCvT z_dnG~w(Tg*`(oX>uJ*+%k5hkN&JTSz<=d9U)z69^v^36~p^-nW{$|^9dpDM@zGrV| zojm&S(LKJ5>}<37vl7H~w8f)$3pmNRo)J^l3cl6d5q`Or{ZYO++@$T-v0g8|NQe0pNqq)?azI^E~28US{ml&)~0KB+o`Z$ z&3qff$7pW*jvw2Xx!jm`_?}1|qj&ea+k*eaCL}yJ-%$6$QO5C%*kQw>MH_OYZ!_)s zznNP>dg|{__RH^ZM^C8+Rib~Ndn}8cBAyo?!^duYdHa{$$b!%e zKY3e}Bq%d6|FsX^lPvwW)>}3wXHES2n4J>s{CUT|>7L%06v@@bC(9C_ul|Si>AsiO ze){OWFJJNIUR)o~i9b5NQQH>Ci@U$PdX*#h_35@}tt)gM-@SX+?%SK2%))9t$M)_k&mP$wbzc?oKKB(yuMb-rx&0!&g=+A2@!!%KG;6{gs!C_SBTg<;Oi){OoGws_$DT zOrET}q`;@pEU-E__;T0D$;Th+JT?9=VLt!N0heN<&!0a1`SR+gtJia(d3H9F4DQd1r;z?bnGgkY({Y z^WliuASr37@KsftEP+)Ap$MdmlPmd|FXS>BzPNA5Wh0xMMxbST?l3?9iDr z6Xx#w+Fh!ts92bFzRxw|@~%?F+39^Z#!;&?cu+v_Dk=4x8FJM=+nQ9nrZ(2>B|`ErzNTJyg$Gwb1ZiEmgLd} zj)mv>K9nA5oD*45Rjur`ZjICXd2=UBGm~HLx90FR)8qqfpY>&Y8@DcHyzQm#lPI=M z&9%m$T=7cC)B9YUoMN+PXI#yXFq2t7fBu2p;o*U?fd@Wb<+fH-(y8c4ZD{q5v|yf^ zs=lG{sYXfGd)|C=?hS9leH!oBOmEySdi=ubbeYr9m$x);p0nmlbv(be%*mO@t{z-{ z>8*$V?7pkoVhy>5Jp4sR{;a%P@bpNM&C|7q`_>jm{63SzbN*87n`cSgz1nU?mxbKR z_5YYZ_1k~FSN7`k*{?ibJ?Pe4EHq(nna;ZT@om%n`4<2ADEa10Wbc$#9m z%wHSza!bB^-2L6z62e|@ZDY>tU`_S0d~-JL#Gj3cpYuJB-Mjbg?d3_f9r@4C{^?OM zH`BT0>lnAoC^;_v&b}F*4od8k)rzkD*LU7+WMm{h-_GL9+6V9NSx$J`zm_qf{fWdR z&+WBe9(-GJBm7V1({s8-i}o0=zJ30D^V%u@Ba0+&825B9p7Cm7_H>PD^}LU+tvR>I z({q#Hgx}ZA9$wm+Q}R-R!Bq67RFIRuP|_ZQ4e1uz!kZObZEfe+@2lFuJyX*;LZ-Px z^5^R;&FeC^E$1@x2OlqY-!NZx&YPYY^6yj}L{%&AT@9XTQCwl@{ zfComm?;U5jaqg^f(rfm zRzW{+F4}bGtFS>~iu;DcNf82KeS%LHe%?`dIN)P~x|q-FgOAb<^gpdk`^{l4@>Kuf zHpOSMx4T;S4z9_``PJxaniFZWnLRwd|NWce=hku`bl_R~J0vvno9t`jd+(;5*)RX` ze30?ebCLfOr`((O=yY~nz|QsQPjC482`0B6*{1Ow)MEejyrbppt3#J1XIO5O7B-nH z9TVM|xmr7H<6GbJ@1Ji_yqSGwBFnocrrK!^?%u7DpZ~P|%6jT!Xz;YmvfflU=6-a; z^-|YkEI|iWKY0KAS8Lto%DZZtu3QbPtGB4u5bZLTWZeQEOlOP z4nMEy(ex+RYUYJC>HH`!=aBg0`E=jUEBh>CcKLizE9**mn%?y@{lu>N?-$sf`g!fC zwXPR)zx>CnzF|8r`-FAR^jn+P7RoL?c}{4$(lec}X1NxQ=j&dVy%sqktF$HMpMjXW zjG=qT^T%raJcNa*J*u!^ylHvkmK5dx9wVN^Y>+3 zT9KY4F#Ub<{lIr$ek;W8iw!<->;A-fYd3A#a->i9<(m{|HmNB)mh)bTij95yZS|(b zJF1E}m2U6aRC2b%S2HH7Ab??8s_#=b<}0C3?aijG=9Jhn+uCyG>h*JYCu`(sma#E1 zJH0uPWcz9N>VKh$4{KegNJx^sH~_tp#b#wSmCiQDYl+8FKQZh!OQOqq!Sv#hh7 zl;+(zap=QB&o?u-x3#&wY`c1SM#CeWn!vz?n|%xo9DnVwXy5rh`Q6#hJD2q5$DE2h zp6gtbb@FAn`~!ujCTq&4Cv1|tyz}R0*3FiuO($8{C0|tVv)r^cOyoS5o`dnFkYJ5u zF)3!g`ZUM8tBx}7+++N@{@cLG{40Yr?dC$p2ZdzEjtcL$h%mFvMx~*)BCeC=2e9bI+ z!SyXa&PBPnJn=Z!_jHbEwL&`M>cja{tF=>IUrO^VFb#fpjn`kQ6P0XuVzm$g9UCLk1_B{T?g7E&bnESgc&6wG$Ud?xLb?q;I zb!DTSZmHR??|u!NCVi3i%GdiDn#b{pd+TibrP|lm{VpqLcy?av)BB6-r&#|@Kz5dLbXC^E&ps2T-9OtlX_8QM$yaS9`AqgiM1HLOe0sssl|{QR&b@eE<9k@pq(#@i<V zy3%J~B|0ts{k>zYmb{LtYU#r4BJsSB51*~k+~HqZpCP`y=D+VwZZ57l319z3pPJjK zzb#{e?fc7D9^G7&az1e_nrL{#x;b1uySi z<&D^@#d|Y)y0W64z$POheGUINB75%ND*HJ<@ZDs~r*h|Sy;7h0+i=s5zfsWE=;V}3 z>&r!Mcor)uIW3pETc=p}&#ZdeTDjJ)NxB^!90&H@DJgsR=jpNIJ|Fy3x*yF@s4XgH zUb9yB-`m$=DrYv`yr3m~rS4U^w*GqwBGdcyzLGg0LomG@T)TQCSX74pYVx0}-a z`@%X`9}U0!4}bM9T?^4lcKYnERi2pZdo(zsZJNkjwzo0MguXkz|ZrkD0ux{_O^OB9iyVHt_k3TtP zxAwQLXTYtQ2M;>Nhp&z4c{}^EpzJ$N*UFXaA0Pj6U~zVKLCW`}Y5VJg-#yvZ&b#yf zv?BFa^9=XvUpL!ZU2y8f{i)Vd|5q2kyRWFY>45*68~datF1#atWtqvYdT+*@b@OvK zr*vP~rMj)PXUmV^qV#ORe=mMBo}FU7onr$uasJm;QWV}@a**N8-BY|@$@y3GB>sgbO)s!I)8qB*@XlDzF7B0d$^zfpPSX>(WCS55c6;I$Iqtfz7TnR zShq|0d)||JuXoofWj0uCn$7HSKlB~{%C~j?JJ-k9Oo%R-K1br*yv_WJOad1d#eYr_D{Pz@6=rlpEc3ZWrMQ0@4-H{K929HFaN!``S%r}iUB(SBonuPoK9$CLiDZ1|A2_}*FC{APHT(gqKPI`9tPa-f!r)S1QcZ+*qAi z{JS7}$*KJOBiD2_eF8SS`qzJHwf5a+|Nm*Tti>GL-m~2G(dKuWcFhlb=fWi}fyDQ%~F~_MYuuR7i?7E^i_92B(c z>#L8Bei#3)D_U;#NA{^*!sRZ(9d%Z`b#~u!9G93EUY^xZulap%%paef#t*K^Fci3) zH=3?9uh}zs(#ks48`Dn5uig8jElT@@_w-E{x!87HTleJK>i+ziYjYNT{qp5Tla<-` zdoKS4pYE%;cR}sxzL)M(e=nXL9cg((%-Tq@U%%M2vOGyJH@{vk z{%P}xS8=B_zu&oY_Qs}6Nt-*e5puKifBjN63J;pHGDUmM&3m7_e%~&5@xW@u>ecs` zr{^@@`o5-u)6j6^pF`fe3m$%8QaM&Q?dkS-=ijb7r~jK#G(9XVY~RHB)0;OaOjlDl z%$J$?TKdMxviqu)l`osZms;N0@Uy`##@b3~vu^TbF#(SRb^cA;c9z+3A3AjCjf&N> zn)<*sPx^!3wN`oyNWMCD=>I9FWzUWKCQZ_{*vRtflhGBnSiuMH5B}L$V;cPK&W8Wa z@$&t<+!`*W1Yx_HaKPr>~P^R8)^%og{zl|DjIVlllDG+NVz?Ht*WBD{G(qzxhG$nnbQonY!}u zjvbeS+BTQCPq@A9(do$jOYcZZ7=QSR>Encup=lC{VQ~P&ej&4zZ zP9DmnzF%?W zzOr(l;KSKD@xPWmRX$)nzq4!k&nf#?ZrHdn@&5gLo;KZoHtxN}T~bmqPsVnW?9boN z7klr~zrFbH-i3eSw;hVL+14U5>yrH0o&6`H47sO%-r>&62Ws1<@7ralv46sZ1iRb41^+J8gxK3Qc#D5iP)#*c z^O0!&vW3+n+D1}HNXh(!zVylrCBL1UGh0k07ysjXD(Aak^@;1(w@;f}^?lPD7Iri5 z{M2NTtA!;cCiCvxV${|3HQRNFLGt#bPBfO@m}e?h*>1cs>84Xq z%Ca|8%yzQH?+=i!v|L#fl;AF1U+mKL?8b+O&J*f$WS0wEU&eoQqOInMsJ$$Q+xeSj z%y_ZRZN2Xi|E8Q}+m>AtUsf>f+}q|iUxhbVW-I+F;cxDm#B=-pxwe}9s>y|h6DO4= zuJf3APd0lR-!r}~fm5chTlAxh_4iGuXy=c{cQ@O9t3S$>l#n`Q%94nks~2+=c&XUb*^P@vvO1td0YS9`+ooD-@R)l+O6l8 z$>EtX_4v7v|F&J6A2%O9m>V2WR;?W;v_qr5gv;OS^T#g_Gxt>0G0MlqA6+Zm{_s)K z`F#hD_ihRJl{q)Lc7p5IP3fmoWNz%8GUc9&#qHTfM>o!?Xk0bvP4%;OU;C2RA`DDM zZ)7U^Ui_3ZTl?T$&ang1)|>x^FIl$ii1*y<;`8#tbnf_Su?OGrJ#e<8arPP3zXD=U zSONnR<#w9ReR@vA$l${N*L`QX4YuTqSZ(|4O=g-$qkiBJ`|7d z&I@F|?da?~@9XpTeI9=mG$W&ukCi>8K5huKsU zJ{~&h@#03`*3Sv2ip!2&vW(c9W2M&nw(DHsz7C$kXMVgqAIlw_Vg!DD?>c&BrL#fu zEr}DSPv6b)Sq~b^h|$%}jm4cmOiiY|o_Rs_^vB6dcASt+Og!icAxsk1G=$Tn}`hy#IQf@@NICRcyez01xTIoYK1G(u>90CL9MXt%Y5#Dm>tV;GT zsi$98uIRW>`fKmJS6hGXeC-u7?c|fXDKpOQ{=dnrq3*fH32)ow&wZCaGF5l9+h?}) zNxN=c@_pVPW#{7EqrCP^yObtoe>?qt&6g(Gkk5{hp8IA!vUB{Nb5PBCWnW|Sx+6Ir z)pj4#ydG~^(&F*+1Eb-ED*;*mKF(E3dV8?p)JC^B@4TFQ|EoWL6TC7%`-bJulKdMF zzAQgE;Zo9Nw%?tbJ8t&%?mLpRTFu%+W7>?V)jYPz^3J#1Q)NA`iym3CZaZjX{Na=K z+8OF?Gg^~N4W`UHt9s9Cj{E-T6`*+hXS8vBzNXooe@>*t*%Jq}VpZT5P ztMn8QdbEF6h8w@lzHMyIY=zzT|8<4laswTKd3a9APkWO1;sDFCE&FX>EbmlW*5i5PX|m=Ek>j$Z*_R*u z+22-|&sqx_UH*hi?+j*oB`GGq1B=dkLidzkA2o)=r_*0-JYU`QLr!)VXc08*{C5 z1O<2hlT1sL+}!LNG54SBnZAoD(G@oWp2Vkao3Jv|@5gzg+4AWhYxMs;JM-yGSo>zz zyfuCiwwsR@h> z=K5EwJ_SsgUZ<|5RMI?eqwuSy)|MlGOs-zNIsM#?d0+0&`us0n?OLC2?l1e+=w~0J zU+iy+^7iyRsiA$!|HAc)J60`S6|-dh%Al0YCE+RASs^K@YtC=%?X=tZQf#KwE73>^ zX|c$e(&9IxW{5=2k`kXO@wzA{Gtna_BqcL5CM7*JFeN?H@w=Lb7ec_sZBBCKK&YY11w{>nz+_tmRuslCIcVcd8qSN=bn_)-ZoZ8swX!g|d z_O&|}w@-!CcW>MmwrXDAv5-}lUmk0_WxVEWZ@NX)Y~k7GHkg{vNz7YgeK;h3a8&uCrho<(l(6t469kZWd?_Tq}!i$+q&MQ>ZabjtMw^prk0UV@Kuo|X&R?J z&Q1{(pR1s!awXQsL7~rL-o_;j4oy2YY?$4$V1eN2`3i<#Be%8Bdt3NlY{AwK>t|jS z+#bB(Vz*F;$~Q^ zl2_}0)qOIV-Q>fJe={sL@w@SQ9h;$e*B~=QzDM?2^POKwLXRJQsSYUjk+>ur?Dp;0 zlZkr`nh%|wXCQGo^2f!!hN(IEKJxeFjn%#!KjX=4Q2whxC(=Mp(tBA#vGoq0`1 zi;pKC>@l2SpKKy_POAIL&&eB)hvB|O=n%S_w_HTmtO@v>s#*~ZLl;i_1BzTrP^ZGQgvs?Znvtf zx+|4b7CYB)abD=FExSU!mtS9dc24Ymv*fV1r>?A=Z}i;1X8Oj0ptGyCtTde+es1;2 zn;Vv>S!V~H-8Qv2+br$Oipb3+TpzE@y1H_5c9{O$n9X|0Mz-^#C-2To^nLfN)pYje zv@1E$_Rs$wjGcLvz37rwdA{GuGv{W-?lj9yO1<`|aH_P?vXFO5+nX)DwfWzlTVqp} z;hXwzV(HZM{x$1uYBg3H)&F00YIFN$E&X{n0xF+g*>NJC|k_ADgZ>!(@+1?YovsyqU$`*Y)QH?y7n?+I*Rv|8-rf|XReVi%&7Hl8iBI>P?bcl1 zt-blW{+c`UO#gqKCR%(iKic+v_PbxMH}J@2*#~PQOy+Jcf9-Ye@Y zp0j%%ZMNJ~J-z(%yZF0@s|#xF-^<0m7kMJ|{@LA~d)kj%Pd~i7CQ13d&CmTcHMV#2 zpT#aK`1yNtMYWmkliX7?jzv#5>)ftcE0uqFQ|6wnnZgyXJNe(vIKF$<_P+3%I_sm8 z5AQBZGd{X;QhC+=qPTnWO5)=3q>eBDzU;G}T-wjbbJpbsz2#}~Qcp_-^PkUpxkpxe z*{7l~-^XubEPJ;CcUoP(1s_ER({%KRV?}NEFW}n(UW&5=9pI@xv?3T{0 zuVB@G|DfpJM_ccgvksoVJ^!5b7US0KrrApQmaWk?i|zGuuNgcN+%qNfZ^dV|uTRcO z+-)___A$yA{OdRKUcY&@Q~A9uf^#b;x0O8cmAy36JiSK$UX$kElm7nqwoJTRQGD#{ z1KoM|rg!J(9<#W&%ye?a>oA`OXXjpMHecj!k)JYOjG~ZR$Rixd^ zU8?t1;#t%!%UgT5RL3;WpC@~J+P9Y?QMdNiGW`7h_)tmqd*?UNx2C?^9UQaQYOC(s znF2w#7AJdTE-%}+^k1IX(sO3VmX=LxTe>Z+YH8V#bJyCI>TOF~%6IM9(r?qMmg<>R zEuE)#Y^mTsy`{0qx2LHIA8-3P<(T`AX=+>fHB}`eX9+wFmlA(hTJLh+;@*b1k9+Jo zAMROFR=4Lzfq$IS6!G=mYvk9vA7_aBUQr)c#9kja-J*UM|HH5TJx_Q&x*mOfA#mum z%sbaNC%u*acOH3TXLqGl{9W>K?vkw!TB~k;QhIss_{ka1Qx+aB-gxopPQmS8H$6P+ zKIy-NeVo$L%Zhh;uj`%Yyly$`(L$RetyLd|lxkl@GT458QkqbAoAraxqQ4b^j^}Lh z)s5$EUMhF~T*U0>3F{7THoo}mrbOmEBjbSEOIK=b_KuCr+P-PejXX)uhj(Ya>QX<^ zurnoPMP(n)WM;OgQ@cw|M2dK~gobBoob(N!B>GlQUDYfmE+}JO)07J)qLmvRxi%>= zi!OC(JLSpIH$_lfMpgHeeOQ!F!Gx9-3DJRpjM+?|ryUVXN@9BU=uwl}p+k4Jg|Zpk z@Q5!qxF{21@;rb3=7RmleG5(4b9|jC{|5P;zbgeM%gdWv{|K_E zFDu=sx@}?gt{|IxPu{&u;mudq{;~7cq2o8X=Jh?hGj*f*M)r-nxp(fq^{4yp+Xrs% z*1fSjdi>L~=WluHPi^L3`r7ql^^SGy|#rkd>KG<|= z%ac>je19g(ym{R8V%xqBK1IH-?l~0#x7yhhlumFjWR&CJ{o)WYL0ze7?*+Xp{mIYl z)pQs>zP+Wi(phC!S&v&$jmTa11;xJuO0vY8Ty~ZDcet%T^6kaNm9o1^dz{RF&Go6< zRl?z1Q^N3Q5tE?&WwE&@*Jda22wA%+bv}A|+9C9R9?P;xhCAYo+P=L%cbEUw?4CxR zjIXb|9RKc4GWfW`ktgHp!54zHhK&cVp3yvPSpQ67$(flR3o^7WiJfzJ_9*g%&)nWE zt}GQ|K8Gi@vQ)jO`*>*O5tb?rmW|Hlm!|t1pY@b`!qy^1#+5fuc+Blgomo6#o|*7V z@ASm0U9AyYYvhbh#{atXQei^N8dJ?Xn$fq-QWJhJ^LZCM=eD`-V~gt3MLD-8^sSY? zyz}?mBi3eV3D>thy|Fo2v@AEiF=p3&-|%nM{$?M)O}()@TlSm$jYA*j*-CHBzFzg_ z&Q7V_#n%(ApEDH+XWO>U`)J!5k({XQ647SMisJ2VZ?kOvdaYke>q>e;(re@KiTMR<4Wm*Uq9I9JgTtun}4I@^YU$v-kkKk z^Y`W--7nSLdQb9Q4$jowQIjRCH~&sUQ?PX5(=TbejPA8G{qf!5QW&eIw_ro~rx!mt zcL{AykFhxSJ}qY9hUxz6jxGIj^~tuj-C}c29{TzCbYanbp*eO_+PII0Ke*H>x}(B` z`Fa16hkq7^^qrTDY3gT{h)IAKvOr-7#@HleyozCEA9umCLU`em0YL zM_rcf(cNM{tEW9m_?GnM_CAT~?YhSr-+C96q)YX^jp<6Z^e&w9?sJiGLDhRMt;=gmG*nfbS-HVWSkE-X2%^yFoA`KZK{VisMd;@E#p&{Yx~;menofgt<8BCkE|=* z>|U~FwyDj&yu+6svRp}j@Zg)|jqRCUvFBDz+Nou6aw=~wcvb69$Z*sJD* z_b*)cOwm^N>teQBuhM->w{V~R`ZX^?^7VbQYZrHAFIZXU9v{5-MnH6P`jXY9mm}OC zZ`-x#5o2WJP0=GWd!9ad5_aOG=9&ppC;CpGHZ4v=Th}(y&n?ZuR$5D2)ilJ*E30G6 zl9c*gWlQgGbaGmBaLJ^b+d|pQ{!M#(kVkbxhl)vP=x_GlziJ9MZ*LaYylo(#zJ>pz zn@@E9yL(*1=okC{ws)y=)S5&P17)ZTAZ6UfjILes_`W#jSJgZ~e49c>0!r z-8QuXql>NkX4!l(ow8v4N*3GF${DX#9XuE!-*;?Rfzh?L^>aC!=ICCSHl>24vDJWy zDNc;7!01YoacjB3rN*`U#B#oxB>I2XOJgfA%ui4cw!I;haVRK!>Yo*d?>h0@l^y$_ zzVw|x*S-EnNe2$zKFOB1O{`$ES+o9K_FdLW2hK9)?u`+6_`EYfzWj&f?Sm)pa7?R` zGPruNp>-eMnUbvuOIEt=-})dUktbZ**dj7$=Zkw2*L_QCQ`o{^U0i!Z;`M>1Pf4ju zxV@QUXJo8C=;GaaXw!#R2Fw3M2UwmdF-=Hb6rAaHdp|5N=Fr#Tn?%VW`~5pex_ zZ`!-syKf&l=041D&7AQnAgZchK{Z>Hg@H@M(dnmNJWb*BPv3PZKfJp5Mx?}{S+9OzSB+)qo-K0STw2t(PkV;fA3n|fC&mT%p@peUg7&Ds}Pp8GpjF1~E6CB8ad zYr5&t#}26_OVjm4_8V_hwk=*@^5*P{-ZL-f&AVOvaE0EA-kcSAYi>@xb@I}TPtLh{ znP=v0{399kkLSdG&8v$gujU@Udh-^OU)Zylc`|FxXy`9{a(~9@&E0ENr=FL}+eGO8Lrs>&Q%ukQsYg)RLJ39DP`jmL*hdOTmvQjoW!25Q^e^~^IJ20Irrr@^TWn>9GoT21r6GaxojWa3i>42A2~nu_3c2#xDJJS!6*7A7epQF z`b4hHn`f=4b7Sg_UWU!qO3pR{vVJeygMTf&H$`6mRKN8`_FG%OE_(isgMZ-Qbtj3%%6sqNf%cL)57__I#rn&{g@wgQsxI?Dp@uRGYYFZ3$Zwnr0xnwF(DB^yc zZ{e3cx>j5G)e_|Tp7^oc>YU6m=lFJh$KM`CLK=H3KHZ<#`2B`~$|S)FE)4SxnLl@a zOyLN);a50C%+|jnJLOzHOJfb&my-n^8OIsx*#1?k9bZ_!y`tp3(D9=eHT9-^^8R>X zYp{&5iH6S7`_-f0_tZ(r=Kh4n?&U;Mb-zxy?&)UZst_|TuN zUB0T6%WZw1pjFIHz~@xQ!}5nNqzQM znHnLnB7dvlC7Xm*i>n;mL+!3R#HOzA>w4tbW$f=5_H0Mjo;#JIl|Q9do#HazY8sON zV%6$NiVUG#fS_Ynj2b<;wY4FEZwuE?eE$b}CX?)^y&| z#&h1>%5S-(gYR;&8!zUv4nE8klq9;O$8wvo=?aC$=!b7pq6HtljuI4n5iR)ceYD_% zw_y+8z6p5vG$mN@$?G6N!AHS@f=^-v#U&#yYO1YSI3>~8$5NETyYs%H z-n17kPV4=v^ZTlgS1b(QVlDJim8aOat$!-ppWIS`=lShV0;&R;-%gN7>DN2>?Zu1i zPK|P96_(oz>fPhNbSWQwkjmt*og4IT$pwy{o06G_&jm=ITXN^FXJB>I#2}^AH*Wg9 z{cA02W-Kzg*tmG2*v{9%^IlkLmbx=JY-_XHV0dBWCc_Ig4>MN8zROMhGPTi7Uz@3X z$&9(a98&`Bg@m6S#D=5PC9kXvgefS)0TA?&&jB} z-BLC@CC9w$N8+0U89lG0`x5uwN=n#dUv;!v!SYz=p+CxgbL3QYZP?ln8`F>mo>*%hP18MDh`L2`+N zW^=?5_ie5VmUAr;Qrx-wZ@ z+TU0^=gotxT)uFoa=nl|@mI_|Q{06XbaZp5EO_XC;DE3o4@`=NN?TVUp zAuPDPZxQ*w!8pSHpQ{$HA+OJxtQ8tlily zZr(a@Wx~VD;+*K z=hch@(|c8?-j)0J?i|Org`0w+6!*PYQhCk#IxqT?qTSDf^_CzJHkEUFy7` zL8)WKVQj|vysJ#ns!jN5x6 zp{P8eFj{Cv>Veq@R?XF&I+aJzYx>>YH*N^r*t(=@gTmv(9m&tGAG|Z?RXbxv_9y4B zhZ)Qmf3RK1_Wr59toqrx9>z3=8-;F+lI$Vtdt^@}Bp#cg|MckmQ;(k~o&S2-!D!8) z+8Dv7?++HbB+u_r5s-3LFjKqHz1uCgKHHs5{5VV5;}!g>F02cM3)7i0WtEr&ydIcc zn9Hz~{bY20xJ$quoqZaw=5J*25L(RnL6E_-BjsV!M4yD-LVu=GTZw`t&nLU_9ay!6 zb;C9TO~u+jZ^MoM8*OamIW%eiyx9rPEWX7oIp-SA${IX-CX$j;H*T zS#x67lXY`uZ<7+=r#WxgkDIpD$Nv0L+`Q$)db8>M^@iN%cf6dp^mWGF19^REVU2cu zNAh~Z-L>V-v(L@7-EMaI*^SjdF?wQTA7jN9Wym@2y{N=vPyKn8Nu$r-Z z$E_DTZ_LQvIpg)pT@u-vyI!n3WwJ@>`|XI;Cu1jmcAmDKoAayNwa15y&5Lb6c|Yvg zni7-Kvo$8> z4gJgZLfMDhOA>qdNL;Owe-|;ZMe<@<}?pcyq1>x4k zcWd0E7uTpKm2KU8>AZTk{ry`$?K2*!Y%{&O&>}=SQu%&_yK;QEbMvF?4<20)3_W#y z@s=+y=56d-mBqYTqwqYB>D5nXzi#=&dE}XOq*QR!vfiItmQ)*`YF1pjcz%B7in-}| zDr;JDTt-B`kdq>37-#c$kWB<8h3VX$k>D3mI(}I5#c{A@V zGG>-d+FPW|e7A^sSJVuNY0)#Kr$=ABdg;c3J56^q-#<;;b<4l=zQtsQTyHNeEfogF zdF$pRlq;z|b!Re}!V=9qd8^B*IlhlKzO*T45;*syKi2lm+8u!c@l1MlDg}EzDh*h( zT(3=xeY`>_SzMaQ+)j_pt$FlYVoGFL zhtg_Wk&6rKIFuf~_pB`6oPMfHWYJtnb5oBtcFpKj(m@IPzSy+%t}f z+U?so>8a$QM+I9NdpF9NOPz2NjogzXW!T2x+kPTp(>2e7+xeAQ&$|iTQl7=ox4D@$ zMx!ooO8cu`&7`pV+tS)(IudhFOj&NPskO`|vf7X#DL?O!X8f`ZwVnqzZ{Y2kb8GG& z6OFLspk+QQH(k^yt_YU=vtsTF{X^$M#HYFK+Mr~R=gKhumw4o%92bB2G`3v^m(|To z7*3|WSh>3S9{-E%%mWP$(>M0%^^|T+T(bD!)zvE-`C6|oHd|!T!*kMCdY4qzh3nUH z5}3l+Zi!4YY&BFdQ&(>66^WX3@PHfdTFuxnvv4NaHT{;89Ur0 zZr7HZJwsRMhjLmlv+wu&-HTiIpFjKhgZ6RvPMx~{{H$J|x*742 zeMk52tULWgPcP4_G;NuNZtluOO8M>zNAG!rU!NB{_30CfYYHEZ*8T6knV)(t)_Lbe z{@D75@$)o`&p&yhQs24yq`r86o^uTENAqKzi5Ac5Ht#X{pr2{}FRk*)9qIX|ORrCn zpSEntll?z#+Z5cH5kKvn{!5di*CnRACEqF1@#}J*`6zLJZ%@hFvuAtXoPBvKB%Zf2 zV-2%jj~fBJN~_*)P6_xC^Z-z{IcPU?@@(Tf4{zW;VuJ=(EwUu3Q6)!XZDJ*vJV@+`j4 z!lR?Bt&@whRQa9joyp0Jjq{v(b+nE|teCxK&64EcUA{k`eDcZLf2ulo_P?V0CwfzV zE&W#)x=-zY@1O4d%gQcqxPJM{mSnbNZEcexg5d@BpZFrj|}-< z?KQJ-@`IE^zoQw?&HJxAGh?CHFX@$>Isf9HK_n9w(#zwQ;X4ZG#eDy`` z?$`S#-pKxo?(kn2s$Hn5shG>@=;-X|=%~!d$Y^XfMNj35m%oRH$NUNXQ#TmwpFKe! zo?&DC;R}`8)=Ak1+x*ivEvz-qU}{uMUeFW-f-f2%z_{>yptg5>Y@Pi0dRqke^gcDqP&PWW_9Oeo`WZ~y+URf>%N zVmt*Klf5P-Ef-Bu>C-&zDIYXp(k&%jwVB$wnzfF8QSYWLS#m_zkaMC_VBkb!rA1E5 zTU%Jaaen%|Uf{vw=v%u?Jl?%e6+bU${#FUzF-|L#-gSTwsQYvyfRALQ)eVdCN9v1fb7 zgc~7&iXUB*4kcMG`om<+^7BU+=QcqZf18ee|Bl-KF|%jrUYekgR`_S8%|-(q9qs?y zzkb?Vl@-T+_I2CQ&${NCUC-+Nrj6^PLfYqxF}I#NN+;TU}YzySlsl#Kgs4YAb0-xaPe%T`P5DO}#o^3SKBM=L)SU3$JmRrQ{xhv&7-6Q{4f);xJ# zdbQ@&+b>sNzb&18&3g9htGA_AUA-;2^4jegSyv@9wCg5_2=3E6p+3X2l2=qvFi}0z z(D7W$8~Lr=)#qBaDW_2;-FI7ra#SzCC1=S%u}_?4$)K){75 zzg`)58eY81HOVNoD~KyzR3-JbNNUP!k(AU|qA5#WJylhG^;A{m)l%2i*GFAlUbp;Y z%{toZlGn}2wN6k};Dux12I1=wk~2R2*!J$WhDL{0_UaQ~RQ^Z)Y06bQ?d7eKsd3`V z)JXzw)l~KF^;x*ZxGb4#U|kpxP%vS|f)^^QrtdqH#8jA*7ZT*5eYzq6G8FQCkqEoojf@>_1&aNlXA99)I9cV!J0~G!*WSA;Rt($ zey>MskId#XoVfUY*P6eP)|*Y9ytwtFXRkkxjd5D;c@e{G;j*a<`i?pTOqMU3`ZGLo z)}!2`N45PwdV3WuUZk@|$Fyl#M@NEnVB$efAtj~DE6*+S?&$CpfAswQ`Fo~Zm-{yE z*sw$WXSzc#qjgx{{@GF~f!dQ?*G6TU?i1#DV0x8bTUy&VSu#v)mAkH))R|ks0Re|P z?%eqOZExLG7vHxBBO0`NnI|5(a^=w#_9LPzHcq{=@?B_Xs>zM1e@ypgAG#twB_*ZB z^k$T3mJ9DS^AmHonomyDiG3D6Yv*Q*NV(3dk=2{`2xWJ4{86f&bwH0fV9lHRul4_j z9$Bxc{!Cjtg}UqHe2;c%ZoFZ!-FQ>lk%WI6wn8R_>y|_KwWS5HTg5u`_ zDylAvypLY`8yfOPjwu<;17`oe|8PLAERsuUF)MF59%K^F#T{e%|lvUf(iYV`sK1w>BiB zAT}l>BR40-BR8ogeT2S9(Kz zx!I?__s7mkt8Xm4yGe@McyZwrzSkl4-ZgI~C|-LQ@+8IWb*4t#R-^0d(|^x${ws4) z@k;aUYbK=`>TBW*II^F8bvgEB-HlB-LVoX~+b{nPf0%L3Cnf#c@olYtUs&A!XR#lBBPSN^_vnepS~Nw5El z*Ur3`o*Vj9f77E&^HWux*mrb$?4LS)QdRP@)qk#?KKHq9?fBR?6DyG=p z_?9Zmke?PauCrJ~?|&^Q|26H-gE;x1G+&pfQzlE!NVV@Yc1!%TVqXXU_kS-^mQ=cX z2WIV6(PTNrEUZxP7O_!x-m4^~re@L9qu*a=YTPN>c&+|H&eHPxG44MbH?29M$*TGB ztkI-L*(dL7875Ag8nh^Bw`uCq`B9Q94qrVcaj!3JgYmVNzD;+$QzKu-R7Q68UR%ay zF1+~AK0c4G;}hP=8f>d~=Xo#Kd&Hn$d>@}0KhKqv^Cvnv&ng%^)6+j6x!q^SAJK;I z(MMW(H8_<`6B8TtxGo8~f4v%FXE9@D!RiIJZ_Yk^oz%GP-nJJK4-bExS&*N7q}@Wv z@Qx(2P>rFQC5N*W>mu(KX{FlSots{*URf79X^MrKn!femi1%Zzfv%f4{JN@!=hV<3H4EU{GDy^@x zTi&dB`Qmx>?SsdKZ5RJBSQxML^zxI9Q(8{=s%Kv|(r52}9@WJqD&}@9zr^IK+-XnG zx#82oZ4{LiD`TR4-*zlqcTCYa_h_wHRa7`zOGiHo~; zAjIGQ{)Gzx%L6$(ygWT$zR1qhohTrxt>97+>+kw<&%8~)3`--g*6v#M>bJ>M5x-fP zE2sUqJ?rj!dEqdzw@(9?EnT)H+Q%uSZ$`_JoWjJ5B9)#mcXnO6)ckab>Thii&)y4R zL7s*o;jzmU^=;!r{j!$rYC4k?E4ouQ?N-ISds4S! z_ElZu+^NiulpbBYr6qMUtZG;M+AmuZl2^2P*q66d?LK(biT$G8HIJ?@Zaxjxcg~z$ zxONqrWoD<8ujx_KEAwYw`n@}K-HOh(Qx@vNe~qoOyuzQREY0`u_MAI)!UQ`#{ngvN zgM7;7O_@^RU#R)jHuUV#2?d2X@xq9NZES953?{%uB zp8O^DGAb~Y$>)`i=H{d8avm=0n^iPz_EgWE)2E*N>JYx#+3+8qd)2Y3yE3=+|D5ZY zC~L>-!}IS=N~VoZY~(pdXIIq&$B+IBoH3vK)~}t4CvJc3-oE*1=qvMD>AvG(J{PWs z%t~Cdbk3{P^dsB_oAy1*Syg;LDt_&p+{2}Ymz#SxK69@PZQZT4Nhn;?c=J_}l-nz{ zPL^BA!mWh-{wZ%Q~JzCz6>Atx3RqWIyLzS%a7BGZtZ&T?Q7}|=bE2SWMWRu zZrjb8xuaN___~Ns?w(!8Zu9cRFaAiy*ld&t_tSU$cvZLJlLEh}zy8Cs zr*HrGvrp*i`FD>BKT6u@S~jPD_j~ZHRrki;GBvd?{q3vgo>ccVocJ|`*CKcp&)a%` z#*;0qKV$4BZ|A+PpMUh}<(C%aHHLm~{EtpE-E3HW$$;n8?2do698XH$w*)rtR!%>h z6JxzqO#J)uhrdpSYG|HtySP$zN8LY$JkdE0FV_}V_mZvQrE<^v-yLXtQ?lfY%%6)lPZjK&Jh_)MGX72LuRztCQOl$Pu|Y#w9R%`Dh`Y9k-a1Nchb#=iU<zPT;`<~YN2kGPqhO!r*L#RXNzeMDpz z7s=dgdc6DE;}h%7S`=1@>&>z2Xy1Nr!J~_*A$I#ZR;5q>xatklsrT~^Y&DMF*x7Jp zN8Ln;DKDBe;#Z%p%KEg|M09D1rvDkC-_|XRua%q598yS}_aY;?ZgTGLPsQ6EeO6d6 z>wn$8R{Qy*6X$qVeb&`@`u1@1qrW?R|2CIrDqsCCXQOG?puU~|@yTB19kq$ppNgg@ z9ACxBBEp_<@rFvzTgl#S^Y{WL1?q?iPn7jySg-kCNlvWIw&#jS#i>u5)?b?5hYkQr4JijT-w$Oi# z{xMay1^yknR=*<_q<8STsj(&}1W8Of9AjwJ*fU2U{mV;%o*OF|R#oel@DwKH_BoUn zvs6bYpE=AnxB0H2mZHSvU2REa?=#N4zc0tlw#EI|i@qB+yTz~hzwcXf^5l)J85+;{ zJr8Wzw^8DvX_us*{O&E>>)s2!YkfB*E=Zu!gehINM#f;)fhW6;F5Xafkz>hOnHFBj z%@a0Pnr_R9IJ)iR)!Q?qpLud|Zq#&3EBz;X#9eKT-^``EbMzE>^O zP<(jEO~!_oz5};Zl{eI?9^IZJv+4S|uG z$4yJNl`T15bD{O#YLBe*1?I2U_Z^E8pZZkwxb`V8i_L;enwoh>`WaWMZTR%Rmqn)6 zBw4kEHNJ&?=apFN{SvL|;t##F4E3-rRqDdO5$!9Q#Gv0#66gOO|~8 z@Zz7KO>K$L)Bf|5FFhAru~Oma&o+_&-dC=KJi6@8WGx@}i1}{#-kPRAd+vT!W-G5x z&RkaS5a!i$HuGP`&Yv?`7cNqemXH=K+Ew45lCs2SSy^P$B4_Wws#N8?dGW1Vy?-yP z-!5=u%h!h0YZ>S0Y!Q@w(#H7Z(AoK>a_;Saq3Umd6@>HM_tL)&`Qqes;@1u~stmTt>>wcyRF`}^J7-TmLiJG`80 z!_?&d@x#B=J!>=$PS?+uSmk*4`t^{1MZ5MLz3#t0AT*5Q-p{W)N>b#wK23Yfv^R$} zz5mghleHFex65De@_YR8@$HJZe-iJr;)3S?Y|`I4Kj8C2-Fx**EVAqa_E#O&{4*=O zJfQNwPT%|3zb9^APMi>OI3VG(%|EfNYWuBDd0nzzAA7g=Radq~eTAs%_3sP6{F2*K zQ6hI$pDW;_g?#GwzDJpva&b16z2WEe7XFEods;8rrN92z+(WiI>fQ--ai4z>c+&UI zL(v6a91XR!HS^!c1<$lE{`=QESNH01cBTWSEDSGYE58bemY-Wx@INRg?#BFh8yjeB<`-T81ZVqb+B*SRMT?p=*p_1)ECt}Wm5 z@8^!+)8#fSeWRdK-sMo#WWUV!Rkt#G`Gb>>f3H|q*V{keZt=c-eLtA9;-)YDbWwND zj{2z#zIt*oJOsIB2D&lQn1XG%pjhomgcdUjT-?euZujYVnZ zF*e)yZ6oWK9l?(Z!rXSI#A z``?|I(^q-eI{EjX#v4YK zV#kAo3X&3q`qoPHPpo}(!S)(|vQ<^GqrLr{^D~<#dEaD7GJo`|({e|lnrQj@{Nr<1 zTka^UV&>{wd*th7OO2gXV&A*{9y(quwAoYG=5W1|=}tI@%)KMKwTvdbi**T_A$~~a zOJUjns#nv)4GJUpbrd#~zI`Ax=dOiR^m2FQ>O7lu^3iS6{q+~T`YBqqyt3l+E3uRJ zxoZCY;@la%N#J36_d3}_+&6ZQS#@)#}9O#T>g78^lxENXuQbVISta)>5ndK z`WIoUD75-mYx47^lsBF)8+#`|-caFTQRQZ#a3xYctm>3&RM)2Bt525Hgx;{!;eBsD z+5Zg3&wlNyI%iYMctOU6w3}g7yCzqH30%`zCSO?OXHO zZCq_79~|e*e<~Bo$!VtlSziA`xyOX8eS4=ay!M&b`}l)*S98v-+UcnO{PLy8F~=)E zf6|Ma5_@p-@#P=>yv&?3d4rbrS@i|QqVGL9>i+(i$MV}f=*9XE5A68WJu}zFPCj+6 z{C`e*ZqzZcZJu3SY=KcZKVI^S3U1u6W59D~`|KUEV+GdvSlUvCtysiz{Opj`6?lJz9KX)6Hpp zyN`;0co=J{d2xHi_kC?5FRE+Su0Ouqe|_P<4`DfRMsmt0xGr3s(B84&K%yCoe`RJA z%gIkmuUT7eOL@P|r$^3d!6N^B9?1*rpVNGuzxA#Cs;X+Ur#js6Rp;SWEj zGbx(Nb2v;YQeS%bz@z8p*f*E=Ly>DrhQgu4OcSO^^iMq8rlf2ty4-KhfyM0KKYr6~v|V-EJmkFm z3YqvYs-G| zRnpFQQ=l`;ST@=$=;wOT!mt0ge&gOJ6!F{V)V^u&^2O)6AM1Je;_^Lqw^^SA#6?%B zKHcZ$<8xq=$imj1B|jGVaXt(+K32N^>(;P!(KcJ_|IVHs{&CK|sqE!^0vt9zrNt8( zZi>j9@HsM1a$>|KdyYoFwt$JjKde$+_J<2L%CWCFU%6UKTd(tzdA+RsL*JjKjngKH z{8HJG^nckwm2RPp=Gu(k^K+IJ#U0-p&9aR%!@jOY_Hf&mhkTc38rS}~?wg&y-+#9C zlj44f<-h)YoELBXW9PN%pqtglcRalG@$3p!$*=2n@uc^?Ke9uxcK@%68~X!;C$0Wa zV6b1{-QzRM>P3`nVz2dias7Rjoy()kDY@y&nTfM+iHl$VcI230Vn?a*L%x*A%_(eV ze(zgvrab)m`a%1>x6B61{8iNW`43*Z%6w2eqWySz*`s@Bc`ITzH3#p@nX-P{JKL|X zz4%zd!owf`Yi8Hj6XX!~Jnqa~+s@ww;Vsj7tIE38$zR)FzIJM(T})4}p^c{0OXb_i zcQxWudP|OdJgfX+$rFyoi_%M;$W00?l+V9sv*`PC)yCDwXBaOOXDj1#SkZphc4k|1 z;Efg6<0VanL&VO@k_|{6d3eP_F@YqF>Ik(INZ;PoamwTE&(eXL*Zi>pBsGIWc)4v_) zv-FIx*X1l`-|qaKBmKv%SDS;?w9jk}-5i>dB6LGi=*{ZYA^ABk{@E}4d}{+M=cA@3 z;heWVr_=oB|49AwLh)h0$bZ0)`s`0^i4Eo$k3ZenFq}pC>|^#ZFBv zZ1V$;SH=`coR^z-FniOf2wR)VKP<1WrzslQ@VwGG6|Z{4HU7i)%(=?Cnm0XteS337 z{|ItV?l)Q4v!}%+BWTO_x30l$iK)MwK6LRtPJF1QBX>`1@1Zpp?Cp328S4r*nL1CO zq2METNwRx6?}0~>&IWZJ+kahT-hK7_Oe3aD&C3%vR>+B+o9T0?n#FAGoQ6Y}XMgzg z)3)ZN$ z@r%AKJ;iCtm(DY~{dy&F#aOQHp4?VjtK*?OFQ(S4cAwsNy;@a$O2saVy~fwf*UUF7 zRPpLM|KRa%@gKh)YVWH_VVKmQ!aVWH^tiye_jgQaJ}jNS(0PIP%pDySJWt>DHwf=< zX;~1sJmUXsPs4lX*ZORY@8bNlS43Q_Znc8u-_Elu^J5G}m#VTC{5~Zn@@7__@$27- z;ZaIO(^M2vD=cizeBH6wjJdKf&oq z?Al+gir!K3QQ=ts%jUV##@Wn!=Hz>McIiLNSDvD)sTjFTX??(}w>kfl4nEO~_j@rU(dcC zu0HzkHi{^jt4xX!Phf%oL+p5@K*DY^3c?b$D{d$*dt`f_zj z*4#5D8w+ZTB42wKJiOvE=ltv*_wC<>GuA2`^{Z_<@NMUx8m8IG7k5|d+}f)8SlvcI z`B&+&Gbf#2#lAUv?{fF|ps=7f>vr$0T)BO2?96$)zD;+qPEP6VI=YWFw&39bCmZe5 zO)unD#Z7;tyVrcaef^ULGvgzt0#G@aq@0H+QFW)oq;E z!CP>A1LNG+(^Jo_dw0!L&)?7Ql)qz`Ql{0@+>=xEPTbux!-0!m{{EB&yZ*>XvTGM4 zyiR!XUY_yZ)1N!)<~@0MG;~M3F?;#?=MU;W+SzDXwp@y~)KH%J=b7r%{l5fH$A@v(2PN*^lrOX^`+j!o)wBr77aK}_bIzWMXAHAg;nbmy~HSMKHbP*P{VDF1r@b-gDSxqr`UdFy_q z?r)QRJjcW9wW_S){kv|R|M6qrB&jXg7^ABrp zYKxm1|FrF~_ex>gJ=HB!ezOV*^%wqolj+jd>bS!XGf#5#C&nR6|n@j~35cxBO*QtB|hX6Y(_x)57bnZ*=x~yJ+X*4b``0=Gbp! zQoYXqu=Hv0mAb@J&z0>aZTj!@_P9>hD{<9`eF-vu-u5ok)Q;6xQ!$+VC|fFNl7ecc zLs;MX#&vnt$+>?WVneU4%l&)ze(cVgX}^xBue-ZC?v5JkoYp^clM8cxX9T_bEGYh{ zbAm(prWuRvJUTj`y?&KdelalA^vdPSm&*$ZHk6fZk@ougVM@!21H0oqAMThjz1KfK zK1gom{92{ee_yB9tX!>}{e%1KMsEl9I317Zesoc%8C2d;fm8+Ga zT>cAJE$TT?#>u%M(nDUfuT}WhutwcS{sY=39p4j#+wG=+t0)o-!x+HZ0#JUQDo;-|#M@2+#!i_V|FW5a=i zj(Z>3@x2h__s!(=dGV%o&sOFQIc_{*=X;J%wywNlzpCK99RKOd&k_$_nYdNt8;@c1 zj@4(cZ`i9J)X<-Q@`vKw_x46kkjf z=sRe8d!hUDZEuu~*4M_w$a!>f#%7(pZsi-|WYzihjl#Ai;sN1)eudrp+CHuR_wby> zmKu?HcbAp_e5xA~diVJ1RnfVwq zy8`$9?_xcFt84A<2W3+QHedbAr_|Ks9CF0v{rVV_&HGkuk~m(bbMR!Y@y3!c`w|ZB zmiEnut4&jPUaqOB;h9i;eAa61(|+^J&H6;XTfK_k{_)8_L7CHX{jsMf73O5eKUw#_ zuQrvYvvE-NZ*MFCHsvco6m)6>@ z`0m8@RbPcP4Np#UKLHxZ@vhKUqf9l&Z|7dW2 z*eb-s|IM^!R(XZy)31_|-TIpMr=}dWJG%Q-(4JL0TxDNaasHK_(^T&_jY&GKrpR9Y z{rxGA-mTUCP*%?PwdBSu>AfF|O6MqRpI+;i`t|2x-V^=~4u^fBQxpHUY>VgifA9MC zxzwtM+bh0&PWTuLXC-S5H~EXSu(sY0__27&k@ibdBkgm( zs#Rz1uswU|(4x+@(I3w)xL?is!&Tm`{pVFZb%o-L(<*m%%y7>5Z)k4+XQIfT+vWM5 z1_8IP)i2w0@9??MV#A&FGBtB`6qQtrx*sJ>s9xiez7Vd{~HtEUe>IlA?9I>!S; z)c{xho0T!A{Eu!m*4z=jfi1mkslt)FTw%v%Z7{#M$2IXrI`8bTzRf>wOw~+hl`Q;d z_^L?gyc(~k!oym=()cV6g-NXb4j+ZT8g46lpe((u{MV=PL#We!SDX zx2LYDoF&X|lIfp~&sZCeX=~VQ6BDj#b@mC-Xg{?1`}^&`cuueHnlRzOmm2}!cO_e9 zh8(}XGjQ{*_4){z3^_e7RY!~WH|TOG0+Yp;at^>B;` zw(;3vaPZs=&a`XgMJt22*7WeKW>eXI^h~1Tjh#sbd2zSSM$U}q45j8_a}2%f^;0Ubm8B_bW_HSRi^5Mzc z)5jLItl8(i{Ce`iH;FSmt}R{OeK(j@Qu3Pke)csH(I+~%xc#NBAKm<{@+9YzxA!@{ zWp#UA&hF?FWQ>3LlU1-#v#gIjxJXAgO>lFyuy^d#$=d3w3Fn(!p5)4TKA2d0tBl9* zt$Zu{_DzAowR1mhVm=*wEa}#ZeQ&apO>?8RYA)R{x$|cAnMaAWJtrqE``)s*{7PN! zuGyW z|1!~2|ElOyAq~B0&+oq~ws-b@KV?<_=A);#o_;QLp~A-~#p;@W_wkEwxf8RN9B;Uw zl=SVL$w_xlTivOd-OInaJUl78qx>_|G+nvo9R{cSWu1NRe|h^N%yw1$o9BXit*`UH zyY?~rzTd&E#mCDT-(TX(^ZTpW_{6=Ouh{wh_xzki|8@!azn`yg)3-FBu>Ib~+8rfX zf_K)GDqistc=f5v;PUmA8x1b$8eIrDYj!0l-rXv1^{Pdu_)JxwPJQL&b^7Ym5dPPh zEAARz3afsYkoD={{d?=|j-3{aRkjg$l)=QGtjuyNIyvHcz?(RKE<1bP?RslmJReHM zSkLX+6Fa%E>c7mCdrNHWtWWEnySKH_Zj%_F`>!_(=f7RkQx&}P|Ent}{DXs;IXBui zF|B1;!*@X~5&JHE<&J!pviEx3Qt{q^ zN2jYRJj3!!pUV0f)TnIlSNR}0*Sb{V*{@f3o+s|j^;tGCC|RG``}=?P&XZo=ese4h zKc3ypzMQjVk3#DAmNkcr@;ZL~on6GYV9#157N69WRfWt`pNfBc^D!{QW^a!a6SMTS z6epL4`L#P1ox6JPnZVJXo2zgBydkEnt^D@OPvNSo(?sM{kN%sudbK!RG>V_{)kSX~{SvR&!6|bedKU&`uX=C7rjxc2)}m8dwRE#*_566hDl5^5A*VSJnENAi?qqE z_-vbS{L!?9J^EitOxD`&Nw?HIRP-u;Ys%jJ$Df~n@3C?7SGg#aEv`yy+#xwna(37H~LX`GyspSS(!ZFByQO~3q(er6Kd zV*cUbVeeIs%URU4Pd4rEJM*$u@X?yzt}!kuU5DzW^_BJFDkEQ3{;g_T{NapM&B}fK z>*wD%5y|WIe%`T7t&2BWq>4>TU3>h<#M%vYiSat~Zb=`jdeyI?v)O0nri@q0zGpt2 znbE7~$yxOIe~x>*!^ZyAzJK?0$`%xy_PDcqU;FFV?_b*f`|wgWvQ_`3Z2IEjqZWJh znR7f$SJpC!q&_*_!qT#9@>XlNxTrN1DewK>`^n#FQt#*b_~W0a$Y$5H<(C43w(vgf zKeuR}gXgnHo)J4UxSamn4Z0Cmdg}Q0T=yA{2deILtTX?%Ccfd^Jhcd0Q?CB}_s1We z)wI}}Z5S7Lw@&40so8slXMQprp2=)ixi~(|Ur>;;;=}E3&hEFbW?xzN@4&5v7TeQR zt}W$N=dR~z`}+Q8WMEvH=F)=>ueaCk>O5jP^-0h+J&BJiU;PZ#nPtkESl0GJTAU}B zb!)OyO-)Wp!`1B1A97owIA2Pv(tbblrno ze|=DNp8K^&A76-wGS<~SjNv-HO?uP!uiHNz?$|olnVG~@2LK)?q{B+KTqUASRmg#d+T=p`SXH*hbq7SAe9q&hkbIps_pcN6I0rI3|aq| zpG^2UV;kT0{x?yFbocBltz-AgmG(DEG20S4CGKKzY0|X+YC;zSrb=!r2olgRZ# z@9n*p8rou zd&+M^8)eI~pGRWm*jX_4=gBMl^mTYH`t{R z0}>}ve_x+H<0M~M=%eS)%M}i5boTpaEOe0mCwyy_*Lf@V-?b9c?rhsv-ebOtW%q); zt1YYAZYgK`@qhSqeZiIlZZEEDkDk5s5t+aIzIplM%$J#2(}gC*`*SwPA3V5rAiDj%2_{nYrpQn>=mAt1a$Br9xIf&LyJJ4h>I|>br~Dm1zp}mlD{Of8dfl@- zap8B5cc+Vc2*y2aTYG>1dKK09-l|`#6Bc=%rsy91|Nn4R`qWi< z*=uK(Ta*X>{k^Ka<%`_Iz?Zpu*6J;gL_TwEI~*ZbXL! zMwtCM)#6{AxZp){_K!bb7V0j!^V*|w@4?UR={qdff4U^RqNYsHTrbCYxkvqs*DDWQ zzqzU7&<0`ddhPo@2TLF4Uw-xRh~Zw&R(pn-?`1qvxJ_@K>nUG9Z&JYXhi_MBN7&?x zFmVKye<9{!uz z>dJSH&#bk5)zs3mfxGp0-2A7nA|fL0%w0GAaP!^$clH%Z=xeWgaPY429g}n2pEj#B zykGR{X>gVKsTW7}k2lI@8|v6?I2Y#sxB7m5TIxhWaZx$@X$^5V=l=ciF{j+A8&=gnkAe*|`j^mYJKFZkH_l;M1{T*T2P8iFGP2EUqVn zo@#$6-1e)g;Btt~vs`!ApQ?M->~Wu_*m&QZ|HGS?m78XLDtv#;G05-m#H}SvR!6qD zz7EUn@-*O6y(fD8+V{7|zPya@UN57v;QZm_SKQ_&Htj03n;U)o!>&g{eDC7=JP%hV z9cyXqU%JHQt<>iWb0X$;y~xtsetVYT&a{UQSk}zF-+$nkt<0IT4yS%p*zDLi-{GdS zjmFNl$j59+uU5=6xDr}_>UvbdEQjocM_+ky<){0+h^_zmBWaHHCWcJz_Jlhd-fhkE z`?gyn?^=AF_rDEWMEB^H_=&u`AMyRkN6{~@Z!tc8^yh-*g_VCes$zJzdF@Ko>W%f@@oyr;oS(+KKHcB3I^8_k_f)}`4*vEvEmz#Q zPER@AFK~ME(%#Nil^fvM;7AI4s_WlB)le`4*LClY#3mp<@#C$h`l z>-{5Do7zeJdu+QW&Nda?E95+X(`8Q0b@}&S+Iw$0Y4}cj{qwadGkk=Wdsp%1 z+$^48Sza@(gHQa6A5EV;=@W0k<{i(IG7ktpeLi1DN$HTALZq$1g(EXghFto}^en1t z)ADEjFM7pudJksH<=wYxd9?cGmw9;y7Rnwj%(<>%q`@~SX}>eW7qPwS{3omSbsw~S zoS3_WJF~FUTST0B*M4>5NZSq1*W}*(sWj_NfF7gW#iN%VJ!0p*^5p%|A2+Wr>+w3a z=wYG63GOxb>d z-->I}n*j5$bMq&L*IR!K_WvX#^k}!$3U{7))8md!zg52E$Gk~SH6C7ng(E}qKQ3&` zWvo7`xNTK<%M6c$;Wqk5Zg21RP}uWmjnkF=$KP}=PF%md?cv>;#AVA3r#?z&{bOx) z?Yux^-o6=)cW>M74KHaZdF3qiTyNZ%%gdo4EOC>C~sK z8r2n(bS5U>`6DL1F=Bt3rHRN>gFV&l{As(gxHaR{JnE;os2pt(o^)t#+#I_NGN$^c z1HNzVlXi-pWW_r%(N1Ge1` zxV!3WP-*B_f9=cZf(4p~j+cv8oOaXp(5U(QX<~rg?E3#r-OIl#C?1kL{fzHmkD;xC zvR;_O!<*A)J!1;Ic>3If%72ZeG6#~iOW)tU(e{~r*`gnpq=d5C3tnIHE8+RxzHXDs zoinA}p3Cd}CzuP$Z@%_o*7ddCI-EW=G7K6Bt^YCJ2#5{y06u;?BD6W;%kfLGu@)H^7-ERsIUI2;gu)9G~3R6QQ+TA zGo}azPg-(k^(oE`bKQ%6C;Ye_X>_`6?d6QBn~`&TUL3Q&IeXupsyuDG(9a%$LJ9wV zbT%9m&WW?`*7%O*~fuid}H#Pui3;g;JR z^Z37PS#LYTTKv4c{PEA~(*r+l>DX%P``hD}hmB9%-NJDBc!~S7NuD3R6|lM% z_B`^~Xk_?g?F{QjXQ%Gj`t`h=_=GhN9^QEWdG;>nQgdkxjElDx!&n4YVmt^H1|wd`QpB% zM4)5dd<`D|DgG-C#P~lweQD?2*YoTwI#xd~Q?7ky@#UpZsEW4s!DX!V>(_tyIQi-P z7n%RQcwRJ&*;B$WG49-qX(9)=^(?#e`F_>)+Z!%g#G1DH&J3=8`0Ap_o&EEAf4fF+ zNKaKVJM-Q3-@1hZ>YKF zpyJAIGi9PcuJ=bn*I$eOKH2VJWq9rXhn>#eui~bPKKwE<^v3=&hOo0QgV(QJa$xcE zoRVdhg@1jWoDKzqgmmrwyyoxC-Cy_CobdRt{hn2Egm{Rpu8S$-p6cy4wmpsAQCiCE z_ilb$_VZ~EEx(?8p31tUy30fS?!j($af8wfqdU623l&r==RHbXtZX0b7j}Kk{0)M9 zS@QcZm986mpL=9Il494^O>xwKq>3g9Ni<{S>56N zAD`t)#$EpV`<2if%PpcOH#W{M4S5FY_ z`QPpR`(@{d;D0%kH zwK{Q+9+S#m&U*Adp3-9w6Y>O{keQopR@J0UTS>~L&?Oj^MAGpx5pxoqe z(WX9;r%PUGd@5G4nep{Udb#umb2;r@*U#PB@b1C8l0B-g{}%g-+FcEK^!Rvq$Udn( z^}(I~OB}wX={uJ+7>DUewSI8m57;-`jc3-Wl`rzv{`_;GFC_2oq0{27J4%xDHeI%Q zbZKGagV=iw$<|`ZM{WzQ3#;NN+q%auvS4w+eXSE}Ngs_4?!0pQ^vZWp2MbrdF0VNM zt*3s?v$l@aarYEbYDAWn7jYhyKXU1(vcS7{48^uJI)lFfknRDj0pVS?}{=7HJ zPvg9r9t!!rpV@F&`d2|^edx4y-qXjGZye^_ckbKvCredtY~0~ndj8X`KSy)Uew(*F z^J?0RDH{Sp(@uHhc|ScoNw~s`>qTm%;JtlX3wPCeo%*YJ^?Gqt8S~xAw-irY{Iu5R z@U)Z5suIJcMO|+mI^&wGA=7_v@$wa`YCOVj=Ds-}+stb0{x~qxFp};3Mb(|M$9ms& zDb@wL?l{x8R$9r@GE^@($ntH1dprMrcH?`YZVEuV0zs8i&3q+h1Z z&iU>RFGSvnzCV0OvUx+oFNHOyB$z{0XPS$+PFu0!$GpJ3xAvYqKlA^~Tdi|be5XG6 zbaHFNeuZgkreD<1i|H<3-?d||jCA-J*Xb=AX6IDPFa2rjsJ=i$`?XD>!=2R|?=GHD zpCHNDdpTnJ0{OIWUk|qt6A>2D!EGwa7Y^6y9XiN z_w)6y|7QC}1;s{(W;(x{Rax3b*PCH7oPWbWxhZC3(c z$ceLM8g@<<`R3l!yv!~=ZOP(ew@**`{o0*HrrWSQ$K1%|(1zr*J~s6wd{gzgc9dyZ z>=T+9Jb6P|n)sZv^Ew`VUS06bgY<{^Te`>Yx#!m+S_HH@4^{J}SwR6(0f1l~y+o$b% zba8jZ&mTPR;_ml8-ubz3cLMv#OWIfb&p-ZnxO>GKjRTw6k8ezR#?WFh+tJTyNk=VD z@1tLvQ&S%9$X&s-Hd@~>VCveG-M-h(zGw|yth}K%kY6M|Ihf5=Mqr)F;SZ%(ZTGCN zbo^P{6t4gNQRq|Intva7%(?uNLhkF8nz7vyo^fVD#sA4xAH1FkI2L1Z;?>&09HQ8eFe!-`y*LOI_+HIV=J;$}| zuX~T&9sVe;q6ni}hLWvQ>&q;DuNM-o$X(nND=$9LHL`vEl<(JHI9;3E*mmr9_4jwz zu3X!v{`8-K=+kh{R$2FxTVtGVsekM;6)RoyT|TZj)vmI}{))%W_7L-` zzH`F+XfOBcjheYSp8n&Ue{-S1{CmOn zRi64DhNtA_A6Wdm+Vf?s%eiePF4fitz2YBF@H(v5D!*2mF+96@+u~na4o|+V{^4h` zWt{E)KJVi}g?aC7@)(~^|6abK?rF%8mLG~{78`urf+p#@BsrJ)2y7CcwDhZYRg2D& zAGfziDqPqV8hUDuqDFmD+wH?2h)VoKITx=G2ni;!z zrOx%4i!y>vd~&L(*}VG*+vAUKldrhPFKm13vSLrG_ws9r_qHVNDEY>7-M=g+x>4@# zEydJt1~;N+8m_L@n-|9suG zTcdh{e~rX-y*Gz0*v&Oa%TQvR>cPR;8NYCq@7EH8=dyQAmT!AdAtq#VIF}e`M?D*BkN==kTZ+=xgeo z6Px{ag-puZd|_PVdtUq894ND98#RrdPT z!ub6AH@w~AH2vPq>HjPJ{7_8%Ytj9XqeyZz1Ptjxg*USBu2h##I393M&%%-Esqwq`^M|L@aJolRNyuGGz!3p}1s^7M`3j8`kKzRb>i7?t>N`mS5+ zzg}H0H>tFuZ}#Qgg=xC)Vyzpx)N?96n%%oL;i(_1-PG;!QLDH(3by=t^*Ckgbl&5p z%RW{g(bv+-vdt^G|2ilB@AdOJPZo>K_bBX@yvOY=e$M6S=G`I3 za3ktfov7%a@5W9pNib8cvzJ>P!s z<7eVGAF4j}|8#=unWA~R>8;;Zhr{B(E?afS|Lkt=A3G*J_49i9bn@vdY)kHFzkBd( zr|gbWMfQA-((Cn=O}^RB7S!HmIMT|tcbbTJ;_BGe)YNFtNmG89J9=F5j%kU{SfCL9 zdeu>Gw?%UpoJ4Qu2G%jJj~9EK`?WUc1OJZ1pIT*AcR&C3@SW-Y;K--7%Qoq3o))>+ z;Niop6|29MT%L7v#Y(MX?q+Yl?qllr$jFVcoOW;R*A+{@zf{${<(d4e`RvJlsVl6L zCM`Nz!z+I`vGTX}p{C#hCMKrp-=+QQ(htv{n#vM1Z*y~-oZy7r?d>`JAMZA=s45e! z-nQ<*hPu55Wfk%fGbJ}Cek_TMTzN*-n7w{Si2<{@eu}Vw_OYj%S-u4c7bd+{SoK)7 z;{PU&V7Ko_yRH}(ly9GTo-jJ6V z{^3*jqCW?3{*sjztDkGO?R$HvU*2{{*A>;^iPJ9epOkGn*I_zG z_e1sj2^&`Kdw5~vU#t2Zp(Qfu{cE;5UoFZFM8D_fsHD~~g!|{JJhkIiW>;y@NjF=2{N71<#V~s@x2ji1 z+sl?-+rPB#*NcCmBH}VfF5X>jxH4blSULBhXFZ)7yUUsM<>sq2?2xXsewN_1U4Vzv z^yoCri95>cRMQ{Mv)sdZI<3@w$^NgLhK7b_Z@*Q)fA)T2MaYKlzxGC_UAy~qu0m`; zW48Lr9%=CdM;uQV?YU<{&$)}@^E=!e*SDqWpbML2Yg^$9cQzuO$_7@m1 zcDl+mJc^C!Ez1MU0=D|w;VtDrm`ZSXx6>Y?I{{}l(P5EV7SKoC}>Y@^f6!UYa3*FS^BbH*zPL( zC*W4r-#&5HA(5{4_I57kg^~{ous6-oEi|>C-tsnF=+<;YgLBf3er$6lC4YJM)jMQ= zm7CWiQ@efjoqL?63%?xj+EY_F`}V)X-%ee-dNuHee@ACegQVuVL&en>6s;!Y#{Rt6 z_cy#_zV3||mu+W-*W~JRo>pJ+_mkY@w(rfW7WuR;+x6=CVs`#OvDZ7?D!#p7@>-WR zS>V*6y|39hc;~qty}UZ*uAQsw)q_vD)f2K7FguGbT|e#DtKHJ9m*q>v1jF4=zfAYb z`SB$c7UGD4&b2v3mcxEx&nN z-MN4X6YI3p6t1Z#h$b`T%#*)qBRO@6!fLH`iuM0}*31!YY*OCrx#Eq>!A{-|o=-{9 z*B)f%mduai*jD@E`!nmAA7q{-B!7DNXQj-#{Tng`wq5`G`FQ!Acid)oj)pC$ud0`~ zyt(?K<{9R5VpZo&rlj1M{;ci`t6;$CRr7-1b+)-(!7X8zl zXZNdI@w;|rw>kgEK8E+l`KMOI)yZ=|Kj*lh`JHs6=R0OQ9X~@w#f6NvC%N>rPN*h2 zG`x-#y%&5VIE8h6q*>>q>Jz;S?(V2!`MbN!<$hn{hvKbkmv4}~!hbXC!G33t4x#em zl1(+9e?|2@62feD_syD>F0-QI&jSswytnR=o^q?^$2z>5w)BOJw6DTBA*CiIbq(&h zva&w@c~Mp}u9ey=^+gx``l>5)$AZs#`jLl^7M=`I7oWJ>lvmiT%zb}c;nt9M4ql(D zuPIlrUoz+HSM~F<0v&sFlV9Gw)3*A#dBVLD9B(||cik2bd-&#Luj$^&w?cg-@3l?| zyQLm?@Z2q9^=}E0zf^SM3|=js*?6v^t9|P0@ArZ^nM-@WHt%w&ul)1DDD2$a#)l^v zJ>H2$_?^G;;?Dc4y4~TP!LEjX9p0I}yPIZhbHnDtPvz4EInQHa_V1aLayszN&MF4> zZD$sK>u%byLgRMQ&)`$B{=qM=t;_xVI)4A2UiJR`2W1Zvede2Nxpw~SrWCLLWu=R) zsuPZWi3{=H{b50Yu$Q0y;j7LsPt2LnpgC7|V_uX^#dNdDKFX~7?U^IH+m!5XnY%kZ zYCjkILymLi>(?c-4cCS9uGi@2+4X%#bOD3&?zZczHBWBZDsf*=;%{JP$IMVW$jPRzNF>7L-*SGc^l@+JyppsTb#b6e(u6)MVEI?-al#i{6%Ih4|-Xn zKFfdFZ0_hN#~FQPp}~I!r&yiDb!v^hr_&d`)3$DW&6^&&cct3X@aX18*~>T7-j%tt zvrtGr%cHQS!kINMAT4tx_l0Gl**dW%tk3&%t5h^k@+`dXdbysxbCzU=|BbzMw`MWXzL*&Dx^UVUsFwCr2P>&GnV*~T4Q-EWs|IFt3?x}{9G^OTn-?_9fm z(N`}&YQFMw-h`s{4|INZEBmg&Gn@aP z?L$R3QPbo1FE9M}%9W{a$(`5xt`#eDy}7b>`x1%OtK}Z19@TvnUOr)_m1yICq@9MSVS+3>sEAi9f)w8#^#J#DO$yiZQ$ew@C z?)c^9{)U_4%ULX>438cR`?P6K_No)7-$oc^bG*A}b#AR`LU8Q)`7y5Nrv0?oRL^X; zui7o|eBmn>y-By*74=R?TdnHK35+X$w4axOi(`vXc+fQK-KN=s73td+todT|b>i`g z(8^xxX+Iy%Rlak)JI>DDx6-yjv362o`VwYc(W_coUinN?&1@yStInOC+2pRe{Kej% zP1(!Ml24!6cH+Kelg_!j72kds?JDncT`p07!n-qnQOV5@Z@<5q79SRLX`}Oox0mrTX*`d7E5&KFZ=p# zUD@p$P3~RKzdzye4)=2oGt0lY=HplXcX3BL{@tBmw3*$<_v-eI>2ucKR}+hibM(vm zI7>8h&YI-tCixG1lcw4U-pp2C@W98)>-{^o%#Vdn-bXgw>kJeS6NvJ8SeF)Y&&xe{ zXT|Shm0#E2oVI>>`3k!-WlOUswzkq4nJc!|1g$^OUwbHLV^Wm9&Av^N*ZcGiEk2~X zqsW3exSDlA{S3phC0`DmEtdZ9;aJ_AGrk9>UAg#`Gw`3a)bi50u!EaxPQK38cxS&W zzxeKTeffZ@-3%Awp2dr#sN4*@WpDlWl)BED_pjD0uBm%EMRAG5`$eB_h6XKKed0q@ zdvj#+hO~19A~Lso_S|9B(7V&vu5#XM{o8{VdpB<|-)jAgzqhTchbLP1e8cKR;u`lpQ~w?wiXLSWselFYJRy-=uTOt>@0kR5(wwv3}6I_i+EaImb3%DrWhU zU&KA({@z`^Hj^A>oorT3l@eq9AN&5jywLn9D^{3pjjo%}Et(f=<#TtdTsnX1;mbkt z@6@tVmhv9xcE27N|G$;xL-D42ULGrK)k>;(Uw%HGeEr+gl(jZbw|VYWW;pOH;QZXX z{Gq9?HzFkxUw2tF%rSc2vtwb}Kn}^02grN8F*^uV$xgoZGaM z@#^|sL!PZ6_TAlGn=kh6x4QmMcjMK&b&d1Ft`~**D?hE7D{@CWZ?~kiXy4iV&ANp- zv!1@5UOvMhO-0j^{fIlOLy$|6Zfkmio2KTOuRpg=&SaT#Zo#9Il}?w0Czxq6JTLb> za5k8`u;#YRmak>a?TbYZ?Txvy>gN4h&(C#ioviftw%~)TM(^d{1^Sd2zC1O)QF-%D zUe7A_mOJ?Y);0&`MlZj(y_)^Uu1JSyXT!B0C(pHya%Xy_)phas_w|Yf-#czQg@pcO z`1#wYAnQI8-cUN&1BJwJ51@S6Mk z(!?0Ie@}Ti?cvYM-Yay{t@Uplx0Rb5o#M z*)z8DVaxlDH9zA1@$026Vw}0PZ-^3|*?LED+_%&Y$-x0g9 zg>|yvgCw@#THg(|heX;Nw{Jdqv$wnYao$6_E7zF)<;9X7H&x{Lzvj3%mG{S|bt1;c z_?z12a^A`Hz1Pw4Ve{Ha_qCm~zs>X&&ON&H_4J-2f3=sa_!OQH{VT!e{lkvr?B9=W zzMZ?HsLHwazh2|l?lgY)lW)Bx?r3vfQ@fQO67uBcwcGcl4U<$nGPm?{^Vfdc@I;ME zf9`<~jTS@IrToEzVI*Q+d!m_H#nFd$+_%}b@K-LF^r-#s?>(ApERmQ1(9dLC|D zes}jy-tYNx2PWzoU$ot)+tS)HJz$4?XdTa-8?Rrj6wkkJvVUIg@2XE9*tq)FxE1+4 zu(q??mr=FuNmAw{qmAWHmUG57Z%B*se-m#hGrcJN;hSqGZ&)o?cPlSAd?BOy%sY7p zuL2vrchNm-e*QJ6EMVFbD{Jm)I%na>&9$CR9u5fypM5>OukPn3L4WW31^HX5Wq)tc zwf(($n)Q4Gd(HCLtK8XXeM`Q-u=^)pT+evz>ZexT!_P0=%iO5|_r^yLa!-ZR$!WKmGUYpK~88Yin)gzW(^LK0o&Qd!_GhZf?H5 zruwdN_O&XTi2i4v6iTkUEBt$vS7C9}Fzim(B-@KY!hUnkmE6hmb#q)I9aLlXsO4`_ z2N%bb$=mkzbuaq%Y(H0S^SWocl8Ra(@5>Twt)z@NH+(m2N_&6*b%Mo@lG~s1$_4XG z(--Ym=Kh{H)j+}~_H9kYdM@$1-;;Z`L~LH5kR19Ye7jqn*9=z{mJHSHuTr_w7R=sI zAmDMzoA2-)O|A`BX18)z>r9ZX=9RY-QvULfGx=rS1cM#h*S}NxvrIp6>FrKIy`#Us zpa1yCGI6y($7IP>&4!Ged0}B^W*JSBuy`9?|3316-@$*=HW>atxaUmL(z^P>G=;?+ z2fNkF6Zh2^rW|EGudUg0>*(>5e;+KGu6}Rt?*{XhgO~nZns zolAIE$XH#N_g~2*Wu8;=x6C^>yPGBQQdjhZOUzqswQ)j>bMLY3_l*C_8qUi(7IUWl z&Zf;VZW4aHc9#}UJ92YTwC(x%cMe`ike0K}IW&9v_JSu9l+#xF9TA%Qb9?L0A1@?t z&X-g+;|xsfKC+_w$B&14mGAo{gbnRpXgpf?-YGm*V&1)zN4IkCmNdO6ekQ0|UrnW8 zR?PRGHLs?hKd|De!lC1(Z8!STy|-Km3>P@ep|Ak<5-9>z}@Oh;#w;W4M)gHx_ zD@A1`CuU_ZeEnDyVN|YV>*vb*V*2ryb?pVlhK9Lvy2_v49m(@fnxNIO_^ZVE&d+{x z7qXYHF4(QzYEkyH!Y0IXPOAKx=#{K%CA}Uz7xq%Qe%iB(`@Qv+(vRJ<&YbS4J-%ID zezC$+A*Q=$0%ulAHOoqBc|Jq;Yh4? z!->^?8a}q2*KP@vm@j#7Yo+c5#Xe1T?bYTx-=!a@ZEI@E$xivO@*#V9)`jb#-Jgzl zM`W+~+BCVh*G@aNzDeq`+D^-Lh83H_ie`tEp`)qMBZ=EU6z zHs^9Kx_;}m)$l4hKJ&2j#;ne7zYUe$e*D{e^mG3CKTA0_ZQkG#`}N}wkN&Io-mYp| ze>zHM&Ptcfng7nLx;6b!!n@7KPEC!q-YEY4ec8i=@!6wC-`PGX}Hft+>F6FE7m#+)Skp8lBN5ssCvo1d@ zZ_8|3cl7SQs0)`~_{)EtSQ*nPcT6ly?cFxvf_z_>;7kt1enXZI+#HkjU1~jfba+e^ z6;DL$UDS8s{fpb>t*%iq5tHvMJ?D`vbxUh<$Dw^rF&p@o^-4ERy|sB`7ilnDvK%mt3s+JiOwjJVFIW^{uOn;x8 zolC_q_p7;mx?@-!W4Bqf_HE`1Wxpev+eIzPPf0FbvSgvH zyJ(S+lWfYQza5D`MIS!@H~HzTISSV6;tE)G@BaRHS)J*{`+uuGxcATBTXirZ_vOoX zjr+EV#gs)S-aHhU-*MPcxY9#He~wkejoHSYjFBc8Z{Bi0%CR{#c{z*E zJiZ5-iPxrV-LL+}P}`KpI8;61U61ArgR(byMR(6X^GTRKNg#Ii%$jDK`@(x_zxRCE z&u!Saj$?mP`?R8Xo>I4i(=F7s9=khxCO&azjC;5GNLCQD<8Pn$Un`S7pWyhkUfupn zC)dXZmu@y!{F~r*|G44C$Ae^i1o0`WI3Xz@aGlZqmcPZZU?4sNT{FkB&PA2kLa11O8rYe zUp;X6l;ii@`X?4w&vR%OKAI-D`s;;+cOqM^q)*)Wx$8{-?<0}*j?ap@-+fymym)Gx z^$|ne^Ss9v&duI6{I%Oa1oOYJQaMEnZ&ID=m8YpYz3; zz?-{s-W~aEwriC|#!i8S>bVnN?BtxNe*M9uX2G)AXAZl?rpA=S^sqhZF`vfv=*`8s z7iQUhH9dR5{nn3}bEF>Kk zvs)GQ4qSITaprx;wExpCeD^!vabtl!|7nj7+is41UibbBCp~_@Xsuq~1ocN(LR$r6 z`<Z`e_O zgd_f=U9<4H-52l9I(y=>-3|Yqn0m>1cUB)bwKS@w@Po5^DCe_Vo2^g&{ihlAZ9j)> zNvmeEd&rU2IF$n*W?0DaZ_J#lIps;Jai*JQA!FmwJ#*&xm)*>ltNZlh-3Q}CZ+`DG z>X_7Gd|>asPh5o|Ngp#-i2BQI6~0y~9{cv`4D({GB`qxTvwec^`M>*^?_E~&E9x@S z>h47!9-ie+Qn6pOd8fd<Lgwb$-&b~SdUW_-oSuv1e=mD)?O%HKEB;(VQQ{bz_ zazl2zE_<)ovShc*+b;R^^0QkTlx&}7v14ve$-;>b8GF{`J@YOx^op9btYhh}!!A)% z!~`F5-`RPT<7Q#_g`iqtUD0_S{C8Uw*7Iuk+IKdkh%?3gJK<&1YT z)!Ezmw%F#tdl4}?zP_C{GCH~4Y1#`n8HjCp_WSquFBz|^-Q>7uP28|skxw^N{9>SV zFLxe$LiW0LO)swRC$$$w^0F>v`PpwBb*}zqgg~3)p>Oi{PP_NKcifR1-Snb6`$Ale zq~dgbhsZ!FwHAXD9o)AkzTWp$CuDl7n-_=0{JZHLd5>P0h{QO?J<^ORGID+q85^?1 z@cV`Mg|4lYJ8W{!hzr)fQtf-}eQf9Rnn!D%s{IlSo9T4ISGVf6)`LyS zq9Jal8@ihxryq>1J;HHvns>TvJG&Lvg^M8_9Qy1tvR2zEpZA)4spg$_t=_)EA|dPN zt9$CVlw1?JvGzj4_c&!1IRlpijL9*j+m2jIU3FuLt=z)n*B9*nr?#>9Xh-Khj@q-C z`o~Ur&0Bn1amifynejrxB1fW~neVn|u6p!)`|E&t6)dMq)h^#?dG|CScx^#=FZt zFI=v~?O8W3I_LlWtIhSr*XrCdc9*Q4yi7IEFlGZF>*t|LWpXY(v zk4&Xk#EuC&|BzC=zSqFfkL%UrCx+#dY($Q>?%IBH&5q*bi|0r@cDwUZ|IpigNl7Pm zUAPp%6P?X{C}6uVvxCj5Zz3gI)dceG8BYej3z%=kr|jxlnAOiJl5*5u-~XTA!-W6M znYXQi_p1Mm4dn^Y)$d@Nd18i%TORjMYx}dCb#zp|+_;r=b@{=@YY!LRUiu=V$2Hv9 zg7Jq!i5c7ElM<&HYIeEQuQ!+NohryvApY=SwVi*d60gM1xc&c^FqXI7G7ir6zT_d_ zCaDnR*7J1fWa+?JrJT%rcOD54dvx}3n44E%sjBOmOY;~D6%YQ|Km9=cSJ!&~#+@7n za@RtGtK@5+S{Pn4iTGff`2M}*@pJd~?Cam2FE7;muW@49jiWyW&V1eap!f`^TdzDZEJfQLPoSHg5c@!vNE348gDo$yS)dB<{wb>z#x^XvcI zJbdf7_>TXpK>Na8!5%l^ z8yA*-Uh}15hLmK&&PKCDabqn|hiTQZ{co4ndEapFnGg{@<@@!_e*eSsPZ*adojA_v zC|)k8Hmg^>KfCbR5k8$b3;EMu#rLYX&DfVN^}%#j#r1B>$Qe16H)rU3dVlz;cWEBm z{cgV(?{$=p?GY^ht@ZJPqjAQqr|Cx=D?ev7Y`NcNoY$VPBZ6D{+AM*;fu|L6Yv&#D z*etVhG2_Ll>-*UrpPBu=K1{aGMI(5g(y7DKc31wCF%dZ`aJS-bxY^O~>m?cc{Ml|7 z?pBswdsY0xWf{i$_m2&(&27I}bZPyK$cPsg9rMD%^isE8ymZxZ-tUXo=k@OX`|-%M z9|yDNn=kE+}=h(s<_e56nira|&(_Zkpx{rUig8cne%6!khzb_SC z_`XcPPv%zV;&ZbVH8qp`|M`VKtxGwR(Pm|7X}EAha&@?IpABRF#}|&~UYnFB&X;TX z&D`3<5?VXA^hxE~g;seYx=f`rV}1)iIA`P=<+J5xYWvLsXHOo<^K3_AZ*f1~DLl`> z*tmYKdsCm{{2dD($eAuR^yhuP@_mV>Gu9%!ZTr-PUiUoPqj&bhvB}3}choPJ64lhZFw?rR z>9@Be6tj;6>}f*zj@&G53wglsuX{oN)u^) z?;3bTj%miZ6(>J6tiK!;@zO`-%-rv08yDNpUi2%yb*6>WmSY{V{QTwq6%ia8wdFrP z@Z;_ZKDW^5Ee}`n-3hX#0;!VEF9u09{Q9$cg@=86mx_7Fv3U+he(G+BF?l_AP6x-? z;~(lxcl15`zf{xwwOF>Fv#+3Oi@c!BgWiooN)Z;hN<7c~n>F~;H{5bL`s34{h&^>T zT_dVR-+c*v@NKQlp4y8%zje(5B(+;Nyf%B0#pPBVEYfAPW^r|Xzc*VC z%=0~c>*U^yfGh8-7)zYEI=Bmt#@Q852xOXgs&e~Y7901ktNlZlc)Qv#F)>;1*jXVz zV_n3z#0O=MKRCqeMZG?B;jTp6yk!A*vU*k6bogS=Ud+(_?3le$d{wueWAQX2mYqA| z&dj$uH*?Ep+s6l0PMozWe0k`l>Q&eO{5zhfwmtY0=q<8b_}RVbo(%J@<@Yz%+b$=1s`Yls9X7*z>olBz}m~d-o;f!22z>+h(10?$~X4 zY0ve;SI;qU86CQya$R?(Dd*y&KMf~Kn1r%=YV?a7GfK+od$Y+gtcU+yS-N0bTn~Hm z*CWo$IfGYmXndQrk7v@pJI)ywc+Z4|AJwep}S=t^P z)~zd-#Lo&=Pkh$0vDwF`{=(Jf_j*sy&NlBqn$pHo>Qo;xea4M{3DUYpj*4wOUBXzE zZQQZ3s+&LG?!njD=?OCPYl@`#*;ieNt7hdD4S!Hu#h>OY*)RBLkvuEQj`9g+FaB2S zh@9!a#yIN7p0!33E&fODaA){;$dP+Ter(^0&0!hmt-X6b6=rDlw=et_Q?SXf&!_Hn zWyDjJqtkxNn;o9IIBLa7i|$Q3ns*c?GJjhe-|?dOm4Oh2L>m1l^is3x5# z{a@lT;h$g9E0@+48UOdn$Jynz-w&;qkUrOVHtMgPnVB2kFZo!}Br$QJp!vq3E7ff; z@t*gLet#mS>dyvo(Vv_r&T|}`8y#8U_2rSDzpS3j!jBqWEO&0!N!?L(b)8kd=AyLT zSw6MC0(ql9u^Wr-9a-LDSvT|Lhs_t#pG==DWWA%{*_G+sQ>G@E)avNHi)*tm`c}D* zkE6(}_3@@ci|pl{i#9O7SkLKD?<}x~f9>%(A3yc~tgL(~`Tu<*@7(5~-{ul~GBkF$ z%-hN6{5O^5%r_@*=gtP}*YynL(`N2Em3(TEP3*@Par}Aa=?WiSXtBte9#(Z{o>R2R z(W}GS>CTys;^!UPYWz#C$2tanN)&06IpDhd>I4y?9o}zV*rz)FiFG>O@QUl~l*+{4 z+t%jKv#&q7VScY_qef4$TkJORtWD<^D*QCjGSXYPRE1&gRr7#pMO>NJ%O>vJAg1^F zYg@Wj@3NQs_D?r>Y0uqlV7^^VviFv2vD)HQ3KM4>NOWQQnXstGBJ9HXCguLpPbT@$g9I^|yVDD=$yg-ylB*ItM!6|~hAT%r5HDfeAq z(vmV~zcd!HGqXAZ^x02%b6i%vb^qwS$dew~de`S)y&2>Eox73${rtqMMY%Kd=9UM> z%n^(|tF5C`)6?JnzVGKL)%Wkdg&Ut+xb5m)m-M^5B@@@nnmWG7?o)J-@BAbZE~5TU zwXaWnnqZplk&_>z(vLl<=k7?HDDZIR?ppz?H?CBgZSc^)XJ3jc`=d*m*;AhGcw83F zBRTu^iGCZOe%FLwF040ZzHo5zFql2}uYB``ebeTLviQmAt^50_DJTD~Y>vT&`1bAj zY#hqFPbYl*^5pPjciD>L1zmOrPoHjn)_%O|aO8u>PnN9K*%YnA%T_)6F-Nt>@wx9p z=9EYF%RY-bv16aGtD@hIXZwVwwQ+Aee~m|cj`@REoo73~mP++~ES2lq`^+e2N=f04 z^{Tw*+oV4Hh*NHRcSWcz`t*s|y4f36tXd`W<44uQhR0=V3?dkqV|8EXM+KPI_1vk~ ztvYBosi8VEQ0sAQ&95(l&E?htZ=Uz;cpzNicjMY@@$!O~cj6)hu2p^hQ>GGo_pjaO zw$rbFG(471%BvD$*Ju4+mG$viB!6@7-iosJ!ed*vYflt(F~4xX<<%!07S@U5;o5urrc0kcC@kWBwxXxKXU7QxeRFeN zP4D>=n|gmunYbzRW#YUif5QYC`dw~RM!(q{!F1nQJ5b+oBNfFPjTi|pYe?Lo={rL`>M!aN$r3npY(Jm zSI>>@Q>Rvo?)(;gj_K@;jFdEk#rnM#;{0q;1qs`gWB4PJKe<%STKqqK(Vm&9s;=qM z8LRlOid?XmqIT?*xUNfR^puWGe>{?+H+}r$$y{~I>%q3`Tv?CZFE#9%-#aZ_^~~O* zg?A@CyfrDpM&^~vvj2f=t_8~es@~o6@BDSAx9tyB2u@me>+;n58Gdq{x0ePNKJKvG zRBNXEdXsLROdMbT+06oFCj^fE<6F^Vd4gfiSMPMErhfgtEr0heNdNVl^IY__y=zX` zG%q~J#q)Klf_<9#mS;VG{m;yu-kLh?;~CG?mv!$dD%Nw?_O9GfcSJ-{{rZDX_m*0e z-w?CB7{_6g)@AZPH{;Y&)-EQ_hFy#7PI5NpnN1LRBL73a;dlDNA6qNW>1=g>t9zE` zcTl`k)0G8pSDd$Lzr}Ot%4J)Q3-M0Q_e4vkuqzp#k#t;sUFpo@5z4^Q2dr?b;(e1#Ad&IXr zvwDz{e%N!-o89KKw@v!}?}X5WevbYf3jOXA_W%Cf&vGSm+vW$-OWt!$%Gc@H`m#=8 z?wdU}Ha2>nHeLE_ZMLrR{@p2k^Nt0WOs!hH_*%bU?d@3c#^~OQ89Mt~o-jnGwA@&@ z?}^ZwGh)s2n;-v;5v@A+clYrP5$>nEq;s|#zI&Cco8F^1b<2*`JF40w-Y)sea-;S_ zKn>&3!gU50XY%c}Tvc!@gDcQ+U(O{@se-Td&YC+bc3Sdlb8Xsdzx8z22ChR>;xFHM z{d>z7jdc?oG1I`;|^VZE#mVf?ctk!rUIf57Dr1do2`klxDh4U^6r@jlUtp| zrn4N|j(rXgC}qj5oE|vuUGo(V|0C{k4p~<$pQz4L_fsmIHES~GW9`GQ)k|AcgWFee zZSnhgxH`9G>373-Z!5F-r|He&pZt`~z}Vz~m-AfptW}fqI5;>05|#+R2ydLrHG9pP z7FXAo@n`=2{r&yPyt^HIR_#9m_-*!h&-+`(`6}J&}QL&_eIv~LuuN<5)=Qek6GpYYrlYZscD|(DX;me zZf>1-=D)f({cpOMpx}(IuaBZgd<4C(tMMXi+{@rX86nXq) zUtvM_%l326Snj;)a4J5RYH?ey`TfLF4$IWWMICo{)Kmzk^@JZNdFuH-B0{2+V_#WB zM)ad@ldJk^_iwb{*--mp<^INVzYLDBTRq;>tjAcc9r9e(-MiFePUmGUedT}Cnw!6C z#Tuz!ue0ob@%_;urkID%W7pjKzICaxwyMN)|2IwVTmSmIxU%jq{r{eGb5F~OJE~S$ z&S#G#*vn)byM4X?!w*MxE$&4D)5QJeT;s8kTjiAR&A4vnFI_sT|LrE3yp=v`Rku4AT?l4rdCpVtS5*FkZozV=di_OKjt`$qGp%|bmhFF7 zjoI{vY(&qV23-~oe#MiQg_i3qdpPH-kIGy#_sSc5B1dJ8J~Q>6U$mjtBQG4{6&POSIeO9$-&b$|STn^bMT_a|{a0<>g?o)8+P_C6pL>&OU>MUf z)m!X9+lKJtZ?g*zrCJ9qs^y$;%`m9sQt0G%{#g={yqS$NE;J-Z?98w-o29RO@Bfw{ zsk?sfJe#Xm9Q>>9@GCG;+VjBPT{g`NrRDAF6x=qkKWtnsDE`RvS4h9QbE?LvU0rX@ zv^QqFGkFzrppD_%x3kx7Y)_WmbC)w)$5-WVuF9L9bwwAhY+_DXGw;#Axls`_vl6eR zxaLG9|0sOpF>|t4vdD`%jk#;?GbM@@7AE?ZPW3FfwM}Z`^fwpd$^>~`#RbZ)v3(SO zGvVQ8MpeV=i{5iqtbTXfuxtuXNt(}5m7^0~mmG}T(z}1wFU!KhpYD4Tg;a8U8z#S9 zby3GP#bxf%)7NV&z9tFucPM}U;mIv`N6WR`StII{ZRh28Jo($dZirjQzLoRwJ?e@A0IsUvi+};F*se4{n z!>__pVP|CgH}L4mV{XCn^(XIj?oE#~EB-WNU&a2r6<>Df*3x^1(auck^9K6Ir~9n=V|GaF#h-^5{;QqU{@z#aarC z3viw?*%K zu=uJ|>WvKF15ca11H`iXSIuztu*qlNzIF4%L}PAEx$KLf1$_}Imx&VpzQ~_Ii#7pnYGP&$9}!Ks5!chpsg z8vXsI{PdI@i)?gj#wW{diJAZJujaj9J%7JWPe!HLGW*xtB6W`ajo!*K-A>`kdG13p zIT88WIF6S`H_vZZpYUhB!dV5=x3!{V`P7LE+2_xD{A1(e8~YLs z7wNBe340MHvfN^!)=LI1C9}gxKXW)fepbA2JoCpD#@B3@?$xKhpYvzWop0ebbK@@N z#D(z5++hDy9kIsfmU&pjjH(48ijgz_CtRCr;PvaFrTSxj-`0DF&x*!rcv?2R5r|G< zed|!GclR)-Tez=5)ams?$!;@h(xv#`++&dQTbH;uGPqm4XWHV(x&Kz~&rx2&;+v~0 zcK7Y7(`q~Xx?k*ZO?y-tW4~F<)BKunfy&$Kf)jN1x5&=E=8(IH>En^-&QshsG|ip+ zx4o}m#-F7u_Q^dJER~gedrglky!jJ$=)kKF4-Xf+mF@b??7QP`bkn?TJdc)`PAI?8 z|5)#L!cM1diT$+#LPAL_S8}&qkjYuk=alctAr*YLFsohBOzNC#)(OW$Hu{To&Wd-N zEOV^=l=31wGjZN5t~EY98xEdfnC888L*-OEqsMuQ%(>s$abR=B z#~t$T<4YC39MjCWnDJB7>%zRXOwrlGZ_00UJ!Y5PSp3&(j_syqiPuGYs_Ldo++^HS z|DEmpd>)}|K^?D>>Me3i8mCTtr>+^uxa-o#y^pJO4*faAt=1#iYx{b-vSEV!#mxy< zL@FO2i{y5h8}H9hXPUUm`hsuCglBy7O`^mmi!RB~YcV=h^!$?9zpPi!j~qGjWPT63 zu)XzfjX=3|6Jpbf17|(zeSUuT$3L#}$`1u~zt(Km<`#`?pCGk|?WSOK!O2|XGve9K zm1`b(Cy8I1Y-ZQ2Y0M~B%B{RrZhbA=3LmTfKCbvF>cZ`XOU3f4ZYY22kqpwyZ@A3H z>=PPr&zkH^yJkOTLZ)ZQR__9EFt?9`XdR(eY6lPgmy!j%} z&-u+)XM>B^8LW+82Nu2UZ?Z1UDHVO1`mXJ_#pAqm$$9p#+&0bUUL)pPt8wD=3aOv@ z2@dyLr!>u(v3zc)TA4&vWOBZ_V+9JB{*(!_VwVh|UqXT5Ub4qU+ z&bgKRGp6*-k0?>qrI(lRN*(`DncCdNvwa#})?Rbg8kLwXQ+RyLN+Q#E(bNCJ zJM=@Q>3_C==8+R9U$|#=;OwW4zbb`qK2#TYv6cU-<@A8~0><24!5-a>>HSt0ZqIC; zlp%hkYF+Cij*E4Ry#K2j{7i3o)w}Um#>(oA;oly!7XGr|Tisdl|1ism>56yL*)Qqm zyIx|AZjmuRzEif!Vt=vby4_L9|8H6Dc$L#O>Gf`bk{h4y@+=K}?ip>rEA?~mA%=3k zvS+)Tt#v+3+8|t0<;t_pdPytmgDscY?DDoO5?-95Xd3fJSk#S8{$5(otx3`;6Sxca zub)s(hirUA5e_ z`cu8NLR8Ysm7=T7*Z z)#nN%*PXHHIFn$V61&~ebBgk+O?NNGymog`Z)%8D`E@(EaJRbnId-!~1CAHxLe|c) zNE6ZB^})aEu$tb9#9e7e-|T)nwe!I5?LBs)DJ+6V@ATX`Qu`vm*THp}^sM4@$^Xl; z&jinJ*()9HwiD|>%B*v ztyAsiPWuZUJR!C}Lmq^ct8Kd-m2@?TcaH5gIh_{EiLX`9PG7|nmR7mQ^tyPjjT*jI&F^MOdvFvjPBoJ}{pzxswyns+=WBzcG=G;|dNHx5_>c89eaU^#o;K|3 z3v%PS(bykHrCy;naJ#rG@RSFZS(!XSVDzT1NLg=-WNmRgrT^R_fx*q;34XQpbXPh`mV^7sjhV}RNGT7e#{pek;RU`-i%xfB*2$w2(>ut1!C?SL#eX zmK)}aZH`KYpSy9mW~H85PoTt;gw$BiTR(Uvgxq&ATXSvIN2?Y5{k3io< zv#QrViFt*x#^QBGPlFn6i^bg7#1I#~rGxo-TjRe76VXb=rk=%n&spR|TS$g~({l^l zA$uzM`{OhFOpiRgR=LF4eEyutOz%HAD2?u&fW4i%`%vVFC+Lh+{=^a^kAn zdvEqg?9r>K_$;xU|2?BTyS9v(;QGTizZvfcRy(72=y+n<=A2`DH~Gllk=JsxXFPas znaiWZv`2P^W!C1i4i>KEYq}Grc(~rys3u(b*ABhMJx@biHQkbCKl0h1c>nY6Ot*#S z&U@QRkIB~<1RoxJ@aRF)&XwoRR(`(nqOkS++ew`V78%C*y(wGq z{FV99i_z_$7w1eA-og3Qll?+mG3VRT@QXp!!h7F-eDU7vSgw)d`!CNP&p2K7p{U3y zxYTLssqY8pPMzPLyL08iE&HA=DyXUWdcCqJ%0gZ3gMb#d-@?W3i~@Gv^I43eo9oMlP5&a6XtI`ZeW?HcBmdA5=P7NSFZ;j5N|#&+6>M;K=B@bpO77mC zB`3|_J^uMP&Zhc?_nxOpCFMtwdN<0M&C+i={ch{}<-T&~J(4z;9ql>zX-lw%e}QxI zGtC`0r4w&!*pBVPiT98FQUA>P=%=}~?qwIB z4cb!LN*uxO(_|`l-;O_EQTAhw+}Yn>WW>+OwK1q$r>*X-SG5o7(mVUVuff}llauM) zM)8j?A3N9l_|Wts%d+O&Eu}ZN5xqkoN!Cr0k1jjktXDwf;>iGEVKC$7Vg5h%e z|0!kii#2A8J$w9R(ds{JhHA1uJ`~Qd(9q{B-rv4^uj&icgdfi;jr-o+ZmG z;j^j}D?Yz6ENl|;_@5#BR%uD=+v7K7HwOsplZ`FCF7T*WMsD5h!iw!b*$V?1XNgVU z$86W+X6LX2elg_w{{DjUp}j3PuPGe3EGV_=vE4?)jTd6r?H64Zad>IHZH`IW zmE!pCXEWAz9S+DhJoWgT!0ufy6cwfaiv)bvRkX8ee-kBqc6DZ4nZ<@8wm<&)N@jh} z_Vv3I->dxb&ivRX&r22w%eppwxSMgV#L4kVp2cn5<7KO-vY0>Uk+Ir@l;Tcm3r{ z(|3M6E~#C>|7-O`*=@3`zl6q5j;__~`Lfw*=5L?uxsppO8Ph+eOtAQKr0_(yN?+m` z#v`$}+Gfj@beGF_O^&^Id0r3u_f;QDR?PepFSl;jngb_!vn1@jHuX0A{-1SzuHADP zNyT~5&-o=5_up!~&irESc}KlMw{?Qw{Jvie-jg%2DAD-fzN;O!yBRg7mn+O-sJ%5+ zb_GxIvEIY0H-{{CMgv^q%h{kB%gB1nyeNMEuti7LqsQKXjPYW*RRGpVMTfBZb6B~EB z!1FT`Hhf^6D}4M!V1Ce{b57M8%q}xu)m(lds)+Gkd+vjbtuuV~OkQ#Jo5P;{+S7C{ z9EvJF{P5x@<)D+MR|GCRQ1txdaeC>JBSC&U^D3@K)bwur?su>@V?pD_^uKc&Y-l^e_SIc87oI!1jv4nS`(%em_G|>73N#xM+??&VGlAe#W?!9o<>HENzn6iujW)w|7fM zzJ4cE(7(G-g$J~3ueQs$w4bt8z2$~;ymx1V_2PF2 z*Y{{P?|g4`S#xdoN40a&(zjj`&jj`SZt*Gv}+{?Ee0*RG!(z`*gRWq8_)f^V(y*W^M8B zJukkWnyTt@s_%WwpJfK8B%gj{7py%c(3w6>>2sH=p@Uw=st?NNC-yAdt=jVN+Qjvt zA1q24Y+~jd?tZ>f6-2w4YjtUee-z=Rh}^`o4<%Cz3!g}F^@O~L5R5)z zlx?^EH&ss}kJHN1?1rBbG z-}Y-*&)(AVVb+-nd8T*$5-%IrI}Y-GFLx_xFg8?hd@^t22itmv)jYf#3jXO-DLp#P zp#5vAZ_E7nt2Z1>|3BJjdf3)?WzP|NfBEkZFESK%SZ%r(;281uaFq*doSNTT5uHej z@5O?>>wo)w4e0HjTbr?To0Xn0TV%XoPj&1`kKJ2X?WC^=ZjKlJ8Gdc?qz%(J`gtz| z$#(Z@f7zJ2^`L>Z_GihWzx{48^}7E}`fPma4Q^`oOsJ5r{;Dv~euZj7X#ccV4u`Jk zPu}^a`19TH1_AG^Im;n5klDa+?O z=k|#gG4UUYs+T%<>$QS@hI-OE3&CUN!pFa_KUgxg)AWf|7W)gCfcZ92irSx=WN&#n z8&v$)>)6=%{ohgzZ;S5d=kp%gCFX6cE8FpCiTjNpj-p`y#r@IE%Y1vP zj9unDbu$TZUD)+y`m(Kcz6a)7ot}B|d53Z0k7>=lhbPATUi`rC_<@|ROD~Ssshcm_ zXTafH+v>5ej^Wtnsq-gry82K0qtmgetNU~RrrRks#`afO74x>8=-THqC+E?d`{$g4 z|FOF4Tz^<`@yY_Dc`YpGx3(Od?{Md7Zo$@QrsJijtDmN>IDFRX;e@##Pixq--^tQH zD$I05Q2e@Mdf%gLqx1EWcUUVc({Ii^qwT$S(|n65I~RCv7Fu^h$-YQGX#G34FGp=X zc5ahA**KeHB9Bt?oWm=Q2gH`}&a8X#Jx(lOiqIORI6>ReFWT?Frnly$_dZKX%`CmQ zsQb$U*^ITjJMYbkh$%B^n}0Z{W%sPZm;Knqx9K11byn-J-YRDJZuLX|h`+Axwo76* zIg3die|+2be*eVj-Aa7V>rV##^8J~8es1&LbEW^o4*C50`0uQE*GNm=`Pls}k>W^<;@jvElIimMEb;0q(Nq@@^yuKi%6EMFc_O-74 zx%q|@nQl+Nc>YV}jh9E{RaIv^e_SXaf8X}!?;iqdZ{Bl|=`FI6$vM_;Ufa?8q3ztB zmnK=Y4j~~EjHbxPF8wiWL+>QP=(*D6sXy+{uG>@nxuL&YF5L-(I@;1=({y-?w3^M)r9OwZZ{Uu|IcH~WfU z`5hKk^KA;#4W_?6(z(gt%CTvt-3n)pdp=iSJ#c@ia{Z;}e?OnMuif%&#UiWw^8M`E z7cS3gc-EDjvHFvH^;~_{^%-I?uEwXVmmA?GZ|;(>*ikm$EkO9 z-n?hqif9M?x%JcSL@z0Fg9MVaQ$TA zrs8>VOBerIrFgnMuuxa&jQqLk>xy67n4Qku6j;8hv!~v^E7*VH&aHx_meVf=mhvWE zFFW-2f?JhSaz)FOl)gDF5nDfp-SwXt`251fFiv@Y@th4&H?%c0Jm&t_-!4?=mZ4WC zY+So_du`~EmDP8e($DXfRJa)-+t;OJ|K-vz!Twnn?@sAoGNE|GHiMe8KmW@}{xM&e z?EZV3M_}B$#`m4N8JgV365{oWlKT?(f88{_M0)C~x|7YUf*G*C~@yam{!g1{_vs9HfgVU^3roGyLA4qesE6d#9`y~_il?nZCY~qMNWrP@WW7-d4}$% zQnguj-aPR8fftLssmmc%Zl^=*9_9I)wdFlsxbcV8roV3|JjiV|4CtgLK`Lml(pF4GG%dMlScMseS zZ`sPf-#I#(H{|M+g^Mj;-<+4bdOy#HpE_IaUTpef^U?a+`ikHQC7gfPeryr_p`_d3 zX8cOwWVNc)=R2K-pIwuWs+x#YFJAo5XkF|*X2rUD-#=efcU_@*@?!0u_nLg`duAjo z=_G1s)c3ojmu?A3kRve*7~@|Cm8Q(ZGxUSa?K>SM+PwQVQc z9*1#D=wCa$XXfQU8AtSYehWX|;ycaY`;rBl53fIAysx&HzdSEg`9ih6(t0c5xxNYx z6C0#k9B1h&exGgkHu`~IYv*Tvzf8HZbp^9StKR1cyM24)D*w(tC&eP)GXWfusL~sx#K^Tp0XAJ@$esKR!%Owb8*%gR`)H_;+%q?X)c*#+J635 zCdY>BF27ifMFgikdYRH1%JzA~*&z3`5?-G9bZ#nav?NSGGHi|9tm8+f~v%jt8U*^_M=NONSyLzuh z{gu|qxJ0gzPSpJ7p>*u+jJb@724WdL_Ib~W-%x$|nVS>%pwvjEFyA=-qf6;zZYx0W6e^=i&ZaLW9e`nLdFKKh`%gwpDRU~ja z|AVq%qrwM&0z|51ZZiHZ$lPwn#3#Av!7f`aX4whiJA~ECbnErco!?!3Z;K)CJ$Ey{ z`+3?&_wFlN5?_9R&-?8EO*-cf`5JV*aEQ(CwU6Sc2wy(eZOLrGO*Pk)-W^h7ddJqG zW-s3U)}`E;gYlb^&5r03C;pY)z1p&Im2p(mk{MfE!=?X+KREaQxqSVx_nRWEWC{*( zbeeBpuwGkE^rU#ljMctfg;7kz(_=dP9L$eOX1-?=Hyu=N4P!rN7c7Oif4in@Hl@ElXZm z$9%QqHVkB3V;DOnZAZqz?MzxP&KEJ&)J%Le`M53LS6efm)m))z^6sv$>QdNmDSW-8 zW%5KueZO_nofC6coVDz{_UiKo%l)EEHFwruRoA?vY&L(p>OapLl@T|#dvI;Ezq!F{ zcA?I*r<09D)P6q_NmMt#Gfl}l$M}@-9LZ=&v1Q%~3#^%!-<5gs!%nTitH1H@y6LA~ zG^VPYp06W#?DVrm8n^o;I&u!3s0j?Nm?p?*dnMkdC*3Y?{~MRWI<03u^Vy!)Zkw@W ziNoBr=O1gB)vr2~aELd3iqQEjCLa~n&5vsSyR9u_^&Y<)`6^jm&WV|8+K+xt-#^>3 zbdCJZXVH&cZVLrX5U{I1mZ+L%y7ckc+rKORZE2S{o)b4flU5Sy#57^Zk9^hhgEIdb@8wTJ}Bf&Rf6Zo7s1E z@Y*t8KFYn&C^6>9{mRArQ)N1QpPO9|2z}$rW7G8eyVl1SuIh3;A;QPzwOh+dzR2l0 z&iskz_uK1E_49tYuNL)wVfXs_nQ7iL`j3ZsIB;~Q`5m%s7hQ4wt3&KP&nIo~4)y-+ zp73H9OQd+u#Ij6PCeG|zP9>SUdj*&I1n8(-zg%)^f0Dy~)t*I$Yu21$Hp?#QY!>P~ zw@bh+?#-knhc)`j-5l2lp9=O{WKqfQ)VXl0;k9F{Qg2D9YEN@t_kZ4E$9ny>E0B{uLxh^t)RLoiC-)x#JT{@vSSvafcZs%qL=~t7F9S%r8C#~oA?a);2Q2QmU zyN#2KlbVt?`uGXU%mZt;3Q#&<+5fM0)i_KpFHW-Y*JqmIj?W-8xGG-tLJaS z4u3t$>2iLRKv|)*-n;mJg?*naqUwHmNB`M;NJ~LMVYzj2(S+rXy>>*LPi0wCD)@J; z{#SR=%KMygVIMZk?rr$Xc4BW*yU6*{6MOcF&-NAP>zyp*RlLFM*M;k0O}Fp5c6_?S z@LbpX|LILO-1g?*4;dfdZqBoXO<2A8)v3TEJ9OPQY&LW9pY`w(WA350(h23s+RE#X zz1^mBC(GLsapi zA1?2=OMGjl!E4>JCqey5yQT8ce08Hg+Y}#OQd<&pxA7H=dB|}~W51I+vusy3w@;pY z%=FKTYj5~DR|}Z$Hk0Nqer)%<_lHY_wWH4t*?+J1{3weyW_lOB(8B3Z_n$vYoh~wp z%von+W@dRrvU#rNj=M8E*G;qdQkwSQ>gK#DV#gB?X?Q;RI8#}_gnyM#|6+q@0$m); z9$)XX@`|#4DEQ>)T>I*ShGpif(!bKx&l6IUVzYDe3f6D^rN+24`iNv@&su36MP*Gg;$KHsPuj9R>Cc}(^PFsI_?c_&NIZy|__}A6k9tb{cBf00$xnXWUZjv=JgFv3 zaM{C#Uyl}lu*zd)lsh+_>(Zl=n}6=BiM-vd!f)>WDCzA@kKQi|lkIyY&M?d=iD+A3 zoIOD

tNxV-^9S!gn|Pm^8RPSZ(L-QdYG$GTeBf_E~+gLS4v>77NSi#Tz$$ja+lZ zDVUdWUL)6()ZL4%-kbc25;Al+@bBK+oIUlo*}o^Z8@SgB&H0|+xIjUkH}98CU(#l^ z6MSlSOB^#dX$RhM=J&9D6<&=0M$G{1uLi%|J z%8Yg2MC5ZZzr7iobLNbR=jr!G3_U+xzI?rEC@y{HwVzY&z0f5rZ`0Noq_(|tSYgh1 z?n`opo?ZWE_ce+8Y8ZW{ontpw|6N%0cmLb}#hx6W=0z;Fej1w9Ae?w-df@y*#-9__ z3n~`t3F${K)_JJV_h$RS8G)M=5{%bq=>15$-1YOYY^dgocNvXSXL9QJn#A``5Ghmb zo4)Diqn9_Im+QI5hB3t1<~w^X(_goHrjqs*#?Q z$ZtOU?5fG#;*Kd(9(=#F`d`O};=+Q6S+7>^UEfjWn(r-?F}KU?kVUaDzk>QT*51_V z7w=2@ef|UEijq&r*Ko# zlk*`neyb>e*FLe0cX#jPH{x8pXOp{hy4kt5>(f{{iVa;~ zxkks7#c`IhUbMdE{jB~~uKv-x`;1!VY-{1;S%lI z|JnuW{bv>`D(l_alz+M?MSaI(zkDvO;PVe|HM)8z@dZ|X32d2rzhzFx;fzxsT_T?- zK4E+BTzDnXB&|{?tX{_4Z_TkYoXWRv&bawv+m-y(cR5NmcTAop>{m^kbYAXWBFlcWf_9UnFy>F&JKy{KZ=q;Cu#BlsTd*sFM?#nr&6ibdq`_^#7np}LH{F@D)_A$!HKqUG{j0^A_WZeX{ANUie4I`7 z9ErzHheDVFratTX(!F|u-vQfiM~qx#uBvjSv^?UlzVcM&(ALjo6U0RSD5xq)9RB!~tGJRYaj7!xT{||&wx4Lp zTKP@=`tt>wP5G})bGtBO)t9K;u0NSYXYD0xZ|N_5T0B+1eePXfo@6dLn+1}ur8qZC zH~Lkve!tZATgnsXmT=874lyXaGo!!jlk&?t)vJ5w&)t%fwC7Itx;b}j|NQb)kK6mg zF~6Fvsb-tfqg!>4?mT&Pw!11t<;Q_jA@ki{vVZ#YDTw{^{Fdmbj`HP~)&5$ab#1Ju zSHFe!8%!?$*>J5$(DtZ9ui5)47lU@o`j`m5*e2^-&Rwuu znOX86`^2hZ@mr_XJ@$*%S+ss`OXIJI2ua-|d#(4LIPcriI?*h#%xTN2d+YVm>&43W z!os+jdkf!pHI*;ktH$!SH!wqQf6ts3cRN1cZ+dm-@{<3aEO+t~{(9B+Or0$CEam@3 z6|;JE=|#VP9TRd=`Yx8aLebikDL>BE;Ye!uj{IxCEs8%$#DB8i-^{Y1ps487neaf4 zds~a1eV7+&T+n)rp~I@_Q-%4VNplNs9u$~2dn?BdefJ|DpL*;`X`Q_LOxszpRSQ(q zn;NP$*X@!xn0tQJ^)qMAm~20>{*B~ju8$vI#(cSP{Yt>2)w@^yT? z(CLEt15-1F57b4nD6dAQGZn?;}Qv`Pm*#g)c3DHZ`J?j z!QKxA5k@w-XF5LZ56`Pl{qrwy$B6|OL?-o5f0-#L_Emhxe9JY z)UfD2Q+d{!qg$8xYkn--<`y+W+v?S!!tLhsZBj%TCrG5Y${arQa`J|wDSDg!ybYLK z*)?&_f|d>656!4GxH_NPuS~8-O4C+HQ7y{h)^GK1=M)bd-C8!Y@7Ue$=Vgmm+O-;- zbDUFZ&1P8`*drjm@ZOv6OqW%3$(W2InPi{?$` z)8(>8>mn5X9;-T()Ti|Bm}Aex$uiRf1oYG%e^HKn^5Q=0%>OChWZh>x4?W*}gds-d z-U{J4W;zF!I(rK|-N{rrkuO8zYtvb+Scw;B+wLAaT9WxsP+fZQnOF5@4vYTST;YB* z-^x+&q~Y_A1rrzo{Kc$hDRHiND%jpU@1oyvXQoxRw?`yRyCrgCt#R{?4GO6e@oqxh zzF|{jdiaZ6!-E-iz4|**vWz2c-LVzg`yvG{^kUCr{}(yVq)bzD!E%^4yYUa37v2@vlU@^`_yC9ce!|?Aml` zf9SiUg_V1kYjr%Yw2H2MlY3sdc73vihplemj=M8m<|#J!WXjI7dF34NK-6cx(XZB9 zPdH07e|RsS+S%M7CoW#ULB!tNY?huw?8Q=^lA{Y&9uZ&3XkB=@RPhmKcAn<0o=GPD zH`W>+*tB!i;UkJ23BQ|r)4cwOwtZP@@Oi_>p7hkGCu25N=)LN4{!p=jac$_s486TA zvug6Ugt7|X{pwuRVywfNY#zHyAp5N3%8-@J-NMK=s7V3k>ENKGTjH^?p3z&F2;v$i^psr;Q>0xud72qUWE!lmJ};GG&-XpV)&a!x4Cg6MIr~Qsn z;gT!Iw|jFLP1^q_{PD?iN6+PLE|_$tox?o1B>czXc8kSpw_XpJ_M|Igf3L;~tDg4n zMuGFhnLaQ5tf;BR!pHYbUQ6b4xgFD^-y7EpKYLuiBjp{B$aA%aCl7}mVU=-v@Gx|K zNqX;c$JJM^{pC|+_}~5|XzfeI=Woxp#c~{ApBvZyXp69hr&ar>56LIK7`bnltXCr= zru1!%s?oZ)E+1z0w!D0=#&^{>#y+dF_FDJ-4I2$FTYcVdv`?q0X-~I}-`kA0D?Tb( ziF?^4YWQ2V+)@#DsmyVDplRK*YrWf!+g?qw>sI)wt}*{@!=?P~@tnPOk44%n_7~V? zzOLteS0dLZ@Z`yv5Bp2LDECUfTG#I=b#T(17tJP-(z~>qIXBFAtok4)qB_SRd!zi} zgSx%8jmNGOTkO64WpUG#f>Ys3UTx>tu3*k?EA{D6KzzG~pzmX=p3UlW4xIIw@mtM! zj_oGlRbE_jU+N{p|Lkvd4w_K^x2U(1pZ|uQTWBCh^Ugajb(1A_#W8(bKF7=wX6eMP6K<)TsbriY8+FS6;Q7mZlSP(3%t&v_JeAx&b4EnbjT`?K zoW8Jsm(Afb$Iq=har~6j;lt-__FTL)W5dZDo-d+{HtTZQu08qU{h4EP-^uWNOMUdk zklkm#6=zk{W(9rSKnIaGuRrhSDd^`_d2sJd|1+<0~KR4D&-?y*7&~jbB`r_@0T|XAYp76A3c5g0q z>3^qauiYlrP-z`pddc3kzFy2~CTnFx#GJ5~ezL31@gDlS(CE(Ixt;f>u^ierx!`>m z-#mc{HEsv~-gDrW*|tvl+6=RaZXfGv?@aD(ZcgXpXLp~yYm!V^?gh81E!w}L7Y9hy zOEv0w7yR8IcIxt-g6-CldF^X9mfe(jk$vvP)90d_)UF4!e+ciD*xT3M*?F>PO4A)# z|L?Ug)~HrpoY?p3(B~B=ES+W6uo(SI)KJd3ef8jshAC!+|9m<>ANM~$;j$FBeOAkg zjp4U5wtc9pTw`rmV&0+ru>G1>y-Lj8#x2sjFT_0bl<9J~A)&9}H_eVM&s1pdo&Lw| zZx<}L{r$O2_U-5SC8?RRM~>%-vEQOAY4coI6Q{oY z%2@Gj15awDOFi#%XGbp{nVdBx^Z(4h@ojqTqWi^{Zv9O z(VaI?aIgGN$G#K1H~XKw-W?$HzU##2=nctVA6=J`k=gR?;Q9t(-PSc#XKwCV)VkrL zToN-Ihv3T7HjTGj!hgtbJm4xW{V3#yu+X-~z@DX(&fL#>r0|SY{>ao??Tu$M*pB@8 z@o)Nre?R5cv=nCd3p~o_{#L45W+uJ;_N5CE1(LE`8+W*dmv$VEoBh7E%cn`7b>9o+ z{jb+?x=H_>f9uKSf(=*xDI7X0=RKz^iu-B$o7?-j^yS&5O;5<5nWld%m~991zBqM7 zeKm&3u2KfEHvGyiEdN%n5`5d!@axA!b#Wi*&qkN-Gk^b`#c^P|anZE$F!sfrK55Fm zk`e3eIj3IqTj6KZ*t5Fq#NNE-HM65Po=VXBaf4MNHPN+|rP!nTzr6E_!zXt-IeBcj zd&h%6_HAgzw-g5La2>YG^Xr`||Gd}|xOmCF=`%a_aVQ#T-;J0V@jhx+Chuj{E6Wyb zUU9Nib%PQBOYu^BK*)Ei+~Bq;hd4Hg4Y| z^Jbz;V#bp{=b3CC#};hfw7Y1das7qMGVQa&V>u>-8&B(Re|Poa$G>_uJMZ`T=eKca z@8WT_l$jbQk7sR4MQ?qZ-p72^Q!h?0PWtM{P$!ig##j+iWpB#M;vK~7X^k8Xi#C9+K*=wc=#ZG+v z&zkk!_c<@tw|?u-KPGZ?!;8(g?M2$;U9B0vl^v>3-pi?6Z0;7giMg;u|G@Rba?|zS zIr~Lf^u6EQxbR?4`kXm)qECK}-zWU7b8$-e`z=>$gOyU^0Z39K8e4u#cz?- zUFNl};Q^6P`j@P5sF1zad)WF++-e^Q*YHhs?rWIL&DEFx&58|8i7|6e++w`3RJG^9 znNuR+AhW+lPl-FY^*x;VEgRX`-C4o+2wiQZ~45I#3e@_K7O9E++8~%$>YG^i?wXU-#=S5 zc5V{7Fw>5+c#6AoP{;dfRqmDBkLe#cwkdgY>&eIGj>Wh=TfD1_BP6YAk>PU@Kg)IM zZ(_MR#oq)>uMo)$zoz`|OOXiM`u67suLcNAK6GQ^VuRXKE$lTl|L5;Ib4O{RS-6JtcK&|Mmac*JW}F z=4T3C?7yZhzF6hANtM+4gzvvxZ{!+sC#Hulu*u}t+j%Qt->Hm4cl-|jzM>bU`I?!V zJN(7{-|y`=opGJtKb5Un(4bi1zP*%fkPtiP<5fBzloNt`4_foOeB5PNv7Yt)y*o~2 zRZPpY{SU9xb&K$~ahKC8i(1;>_wc%~b54)S|AdzN3-=dEny@ZZ`pdDX_PW6G7c$B- z)-2vCusZxjQs1ms!AlE`;=?$9&-<{VPqOgV_Ze>sjCJqd5Ng|YOrYfI{e%WD&u@uW zrp-B+kgsL*xOU^!GYn}}pRJc1J(BTkqkQbI#SivnO@F)Udq3Ok56`aV8htDZnESqW z*{J}VJ@-#|)XttK<2w1qo!K^ZXZq*e5Dx>xHIJ>>g=K1p;ooud~W4(```-=JV>vAS0u0NTq#;fgd>QK_pk|%EY z&Yn-Kepu@(G30l6B*kbKcv_`(nif?kM+)O^gCdyonjr7e`}(p zP?xy>tAKC`w)4!_B9@s7r|1Pg`&aq&fxpwm7uAdZ{=61Z^#7;&XU$B*m)oa#e+if) z*H~R^c|`ISeFqd?)trl+3dhOKe&bqQ7(6q)qXHX?$YSW*(~wUZs8M+{2%X z%Xq$uE>`=il6hY+{q1yNr3nR_u#sNvhA*%|tuoR59I`=Ky~Z@Fo)qVkD& z&s)FZ$X z$6oQzt;!XrPCL~v<4QhXGiAw%{a2Njb*ULt_WWt>vDm-8yfbha+ZLshysQUj3%=UO zdinT?hfkiVYH;3ceW1Ln!)~L9rQPbnp9>ft=NBn0YFYX+@gC1qo=ex#zx`9cE*~Sb z$mWk@)aGT1swd^=-?Km1DSZ6Ep)*XqFN1G=HA%l{yR$xdr_-A=Z}Pmj7Qbuxkt@4S zcNyDLqrCEE58th|`6BfA&b=4y%ZlWuESGZ){FApRrae&LabICk(hS4WoYt>dljp~p zEu8Ec5*DQt>m6JAW6EU7sMYHhP1q3lym!}!QX_|D|JB;Q=dWAN7@f3Za+7~T^V6UY zpFZqKO?|e*hu1K(+3xmr{ki{qejoBX|F(;>@SMPtho6+(9xj~0VQ&_t?^txjby0w4 zkIhdL?mG`0j2FMFbNANNIpe$WR*1Aa|E;~!n#!K%A6(k}@_v=s#*derT6W62(>lj7Xtz9imx z)u(tsqI=t?(<~`5fx#7h1{LvN%8xwu3)i#xw)Xh3)X#>Qd;YZU{~YuGgi6BWgjCb} znc4sT{d*gAY~F8%%Il>|OK#e;`O9w?4z2H;(o&#vab9`$oINtOW#5(G^!0XkdtXo5 zSXG|);^4z~yA(>UwJ%<5C}6sDI>&|O#zo)kYpeLr&;PdA#$GUcdiK7n^Xw+(<<{TD4$;TLgB?8S*1UHiF-Gy@#V#} ztj#WwJJrz1bz$pb{-#I1Ne#;-9CCdHl=@Qo$U02SpG5a&w zKyZTG!8507QV(nCh8%z6>UAKF=dP|&)vSg)9Mwzi-RRghYjwr11w3C_5B6An>lXK8 zuk_E1seijN==c}!yMKRG|9Y65mi$%l+4I`;MV9POEem^gw5;g1E<6$>t-a;SZ_jFz zqlUHO^Vk23J;YG4)l+%>`e?JyzHSqwcX=}hPA`;ly||krdArlE(r6L)H;#S}^ro~< zw#&WvPeWbLVea(xpQHb*5GZ&)W2aNKSE=*C&^?tm`y1!gOi>k*YB_{Zy+OWwtNF*&+m?=AV34#ZZFS!-V@w6dcUfD ze*gJz>9N1%FJAmt{*!X(Q*qHeg~g3qm!1BQ(J?Krw(-b@?h9e_nQTo{GgkVkJka}@ z|G=+RtL@4`+3elcuaqy`mgxF*CRl^(RtrEXFq9hTc9Jm1}V zqUgJ^_GwN>L6KwrGOfNhn|9bcc^#Ru#Z`WqYfwnZHxbsKZOPR+23O{{Z~LWl=K2iI zL^-}0FEV4)|9@7l&a6pMlZi1%zIAuioXv+rTaO3Md*1l(n-9-jtz&DqiQG}+S+m_# z?(Nni+G{>Jr}yf6ZLTpWZDI;J-oGYhqswHYrSnbm*06AdsGaCvWp;U<*_+Z6vnmP$ zU##JCdC~gyL|=hh-5J3nKi(bPB$>P+E`Dy!{`nH2xg6Y_`xDcieffX8A$WZs6SL`) zJx`^2rG+NZOi^=BB@*6W}NLTEzxTh&xaARAc>ZD{nq2o(AYGqq{4(xPqzS`q? zIbe2wX?FPGjFV0|TOz*&g?PNEKHzseq-M^R0}p%`bx1O<7JR?3{fYK64`rRFVu>sJ z+q5o5%s<|-ZMyK}8XZlgO%r3Be|wfTZu|N3^VSR7Sba*=+SGo(m&w!H-Lh&;@rv^n zhff$@2zu4K@0rGzt;>bmH?w^`I`PK-MAm0MK@}>e4r|PDoSya4cHj4VH-GN143oc` z{Pp3*xmvQbGdu#RNj_9JQ$!XcW?FaUheh&(KNn3`xH|(jXSq8_Z3)teD){{Q^(|3Lu9bbhqn6?(?{q;>xgu|tn~ak7myp(ld-YiTcCVS|-OYK~ z#rl5K#9xvNuLlK)CH-!$Y+ay`Klk&&QWtgo#Y*p`=Izf=e>|;o(h=tqop)M)O**~f z^5jObLwbMv*B?G)Ir+euQ&va5v3DCEm+!f1@oV0S+{Jy|xzqO;J0ByLom6$^JC2`JtYucHZFcguR)e{bGp~ZJd*GcYj-aE$~x1(aLH%NUFIyCpm!~fx}$ty1KEV$kC%(rrmd?8Eo z_D`HU><A-Nl`kqqy{y?awq$tljitnerzmzJoO{bAH*? z*PB`|5_H=0W{&#K8#6Z69?m-S=GTXBR~c$-`5av1m}X5ro^WtWr-ZKVL%)A>wa)M7 zoIh()PDWYN^>#a^cd4B16Xg@S*Q{Q)qv#4()~6y1*NE&jtNDcbUMjv^!uP2*?9s8p zs&$cFa_I_ZjxtTt-lAE(JiX6S{q%`7o8wk}wo^YRyng<)1E&v5CLQ`?5NGiBsavou zmzw>fj{ycZOnf~HH(2}>Vcb)&SLY z%?lUjSguh}4OwAUd1t)_pDB;blc&0K?J{e=muWvreHYQXqocTGWtzaWDNU!&bZhwA zG_5&s*J4kY{5S7q509O^dSm}xfyrvUe-9izec2^qk2yE@Zdq&X-Msqj$Mxj+`1Jk4 zmc@jLExY|^&z<~GwSH#X^L6)Xg^h&%1Vl@Ds&O!W-95F!=t{%8KBX4+N{8@lvuEc+ zf2ZW^_#kF)Z-2LaN!zo}#uwLrapvW-p1CsVi8Sw7&q@Bt=hwTOYIXJaWaJR{!fJ|& ztW$olM&Lc4l%;X)ZNF4BJUsV=N|`F9{qcC1%Dqf;m5;Q#ap9bvA1;xGb(Mh^|6i}Q z<34V)_2X>)-D@giWar+PO^A$73j@2ii)W{xFs+v*v(tBf10qAfA5R?xpkUr z{@l6q`Fm7m`O>)CCNXng_OxVQ^Vpf$y2>Z~(b0B6ccsYnZgm$!v>$xnJz@ z^AA%5pI#1?)HR&f^FRH-lG^8qsn2g|s4D&Ns{ankKVOD#xP6XG zY#CebllshrEB2PcUt~Y8?w!1|=;;dHQ!te93m$BLl7TbwEPFdP<&+EH4H%I*Q=Z|hW+&h`{Y2TF{J9nyc6%_g= zK2MwP&v4GsCql#3rQvve&z2v$vR_vo*0VNSw9bU>XlDAv!d`&}%gKg?S30VdRgRYR z2#DJ&>#7wMw#?|b?!hUT?kV`Mw5cX$3gf>Qo^9_rWvdmFvh}ikCRVIcRGXlc4>3Q@>%ZxJ~o%_skqbXy}Uem z)gl%#KiTHitjCJ#dVidsn{*axM`b7OnfWWP>aXD@xs zSWV&HS&@zI;tG%F2yWUNu3(*@YbKH1Ft<}Q$~g4FyDg<2aX~$Lle<=*^1NrU=P1YD z+>I@ztxo9^*=)=GXUr+w_w7ukebn8~xdzj>YCU%2o0=++R=S?Y`R~&mcLN&^?qj<1 z`mEX++g6{5L#t*dJ8HLGw7Gq^<*#0((R*dXQ=XqbO}g^>-&Apj^$*p)Z=Y#eT(!Tk zO)JeONX4OMhJ|S54*P)4cgrje{aL4={>0#$^y=jQT%k+iZ?|OZ&%LqJkN?+Z^`y2- zC-}3Hm)_4_<^N|xfOBcZ!8e)_J1f|}y^mzz$X8~Gz?A3l$G#SSvv{7+lU+Ss;lxpi z=WluA-^VSs+z=N3^x`B-;p{0QshOXquAgg==45>=LN84F+}@WB-xhUy@ZNM|xFoi9 zXI{qooqlR=I)y<-5{#~YZC`${+|L{Bd*xxy(oR|Jt$Dih*2<{pEANbni%Kzhx&OhT zo2xe6+PqA|oBN~m%X1-oy9<)e7q|!W#o4_*^!T@IPs5?>`tlF{{@z~k`Ia|$J7XRE+F4leJou8EM?%(+e|32LfW>zvQzjdToQEqnJ z)s%S-H(0Y%THmPhJZ7n!es6`&o~CcdIPSdkQ>~iT_9sRDMs!B<@2;5}u7*p_F!VbX znb`7!r73BCIQI_@;Q|R&)vuGLU0C|{!&UX3w$FOSDaR}qTYcxyx-@5^P(nZR>#qy# zb7f@Ch#B;8?z}OZH+!X)?OYw@yVhPVJ2Kbwc&vV9vGVpU<0tdqM{Iv__~+!=69md+ zDmB9c=ZQCO>#CS?MAr2euhqTi2k$exo%^oMSZF2aRCDLOd+!8IMLreX0H@#IcK4{} zx_kMBy!e-BUF#+g>wUGvw$i&tY&+g>tXaI+aIRSYPr=z={SSFDlwaFYxM^iJ&$EQHr7E~LH1WlHZpXYMo^LirFt8W<%51uL_?K(& z#)#ODb60-*qRwVzoX^eu!A-MY>gnct8G+aS%oMKL`pmz6t5ZGSnXgyw=WoC8|H+oq zY?+=9D+~gL{wBcb{O|{{)=ZV|6^a);2-9s^yWbutGu@HxkoP-m+h(l%d-7e zaA#kI!1JG0ue|jZZoI+0_Gz4kcd={iLUt={<_iG@f^SprdF*=VvcaKI%=g#Zz<>2Y z&-`p^Kqo)Extn)Xqv8Lrqq;HQ?OHMyFHP8*BDbbT%)v40i~GU3p@l6!CfQEg-Y|vdlO#9Q=ypth-SC9LT_+&Ci9=ug znqEA|;-9Y!H#O~Hn;o9PGi@?w&3<#f>9(>8ih4}lsoZw6bZ2>Q=h9IABe?LurnGgp zrYwB6X*SD_)rJ54SU(DIt`KgkUOhMMhIgvY`mg271=Hrc)cHBPds|J@zg(w(=Cq)u zw)Us^IEGM*sy`=uyquO)FPWim%%k%_O)KNNUvr!b1DV*~g)G{yJ$J*kge7t1&TFo- zO>tS{>^Q+RZ=S({nR7oE)SY)?sg6{dQgP99i(8eah1F}JfOxr{=-ihTRuQfTY$YN$ z9xpg}mND&gsex;zNzZi218HARsV`1Zx#MB~V&2#3zkh7WfAsjtQsFhz&Q+I{OjfMn zk5u|~N$$#XwnuV|SNE;UFcDZkS&VJh_4pG%crIyt&#T&I&DGCl{P9Jen4Exsw9;eC z3)32|3F%*1^3K)sMqEzh%DLX}KCa!o(daLEazwaxM}a) z_fJ$RgpMol=EvVVxZ9ln;~P(V<+(3shx32@byay!?PsR<_InN==g*h){wz_~+yDOk z!>^b9_AFRxVEy?*xK!7>J*zGD-rwb!fA32E(%Mv(F3H!cuBozHDcM)a7pBDqPOKC2 zRSmyzTgd;{TwfXCR|iBNUfdgWVbh_~o6je{-Oqh6Pt0OxvFqtcm8({#q(~g?d(p)y zFU@^hFHdh>`X^=gq$N|7o~XDTaH!_ICDKsXvoGgs~+aSACMLS(vstaAqZ&5?NaDhp0A{6Fhp92~aJx;W^U@1uxmYI7X#^)j#Mv1y5zpF97Hsaovg zhYx>RZU29sqc(5i$F57^{&~@zYc3RLX!IPryUvD(Z_0zG-M1?~Etr00YsnSySm(q~ zhR2qxofqc)`6Rf2@9NB!-1Z#`C-coG?J<9RYTi+c-KBzhaxvW2#jz(kKGa{CZ}{-; z#?q?8)BE4Mq(({!DeV<_RxL5{y1#Y7_>dCmYv-a3w zSyA(j+Ly<>)5|#>dz_s+*=Igq9yqm*M|ETM1o3^6Gab!VoUrM6cZ=be;hRrak}Wpf zeermQ;G>O8baz>Oi*D6w5U|!>y}M-vgN@&tqqoD$CD<-Lf8*HmAiaHUr(RjU$-xEf3q>vt)_oPW#YB>m9pVr+4R0d^+hS zzxJit3!&nz%elS5&+ueDkIG#F>JPOLio`-`&Y{`oGr7&Gz-Ku8cXQ8ynB9(M&y5KR5V)RK(96J4$48OLiOoSsOTQ zhrH;@woxiQ`@H2s$olod``sHgp6&UX1Fd{FH*B#WEJ-uradv){%_3c zuZ5IMeDS;Tkink`5;ZcGoOT-L_?+@)*?%%(3Jmm-S+dK;i5xq3)Z7uwyFJZl+VaoN-zNMlX}R-Q?cGH^$`KZAm-d(%5JA%x6B6^VydMm#-hVclKCI!&|il z?|bI#=sw}kd7$sBoBz_*AK(7F9C+E!b=9*ju3 zT%@f{`6Z92+yAG}v_5+_abtw(@|6cBZ)ClGSD^pPfwLN18(RCD?fl+ubctjt%vyJQ zu||nJBtrE2|Rb#I;GspFex zZuz?UtMR|ce@XA=s2^?pQE(}f{oY==q$|bt^^X{SSVn9}ohrwdXVyID3BPfh=wQC?MaSMujdZef{?$HT-wt7$wwv~TH&{X3;@hIcOdvBt&sSKbt% z!|M!7d5*BK6dcJD^?MuDbR+w>!4*;Go+p+*!E((LlbkNhv()^RulnzzxaYyzyAhEa z7f#}_zq3EON$=3P*;=)M!A}}jHC@hF{V{RL#GI8M65lZY3q5Tmu{vC8&qRR-U;kET ze%sF#%GGCowDWeM`_Q{J6xZ=C*tT&i!*P|l*rGw-6AQS8+PDKg!pP+@d;+88@ePWpH1sd z^zZ3idoyUp>+FL8*qjpP0Uz19nzLvG`&HYwgvuO*w z&wNhzS^SfG-_biSD>%-C%1TQ=+$(EtyDf2fuVSH}$%c$?BFAidN}eCQ;m~b!J7&g< z^Q~)J70qtXNO;X=EVCuPeQH$}hfQw(25B`n6TgcGH9F-exD} zr*lRZowYhGdSgc!>$RDBZ7(0O8pJK(>=ym?Wsdc>{0)cRy)7%)a=&da-#3dL#~GKk zSs7fKZ*7v_Cw2GqAE`SlFMJd+xpuwhY~Q!G&)=?YQ0<%5c}_;+OnCFgdp4Jz|9m28 za$@hZWXZ~DqQ7R{NJ(tb&7PK|Tbb^+EzSS>Y~96;z4N#0X3VzP;w54&UA$7k{=M|k ziOLzgY!a{ak3?O%@4H$&x&3R>j(2x^P6)`Wxcyc<^Iqc8;eJ8($2wfW=Y@|S;$QkR z@q{0@W6Toyb35NQT=n{OX7h#!Z{E$J>PZuy$*eJq{Nz!&CyB?f$7I&*b07cDJ~nac z?76l3j%_L29(>4V;%u3gfdAba;uIofL{GAAuIja(N}r&1a1L+WBO)Rgc)2BU;SNCptUB zPkVDtTNh>Xed6C;q4F7;cR9N*%`kHm+&p#ag5?YO7Ksuo`qB|T96O-Sr zypg-K|LbYfglwDn7BZisPu~B}y+eD(Yprzi=ar8?I#^cCo-{!wp?!z3_JggZihJf< zTWD}gwsU%pshNG9qhx(IuR_e~!opJ2Ovr9KFS6E%? zxt=d4STv)(%_#p$nyhQz{iv4t7o5A63kIFncR#jts)p~4uBIco8r?U08kAQru*yr} z&ukA{^yhEwGWUl+cJA!&`c!=IXrZ#*zS^ei`tuGHzW%kp=ybGh>*Z;o5{i0W{fGW& z>?rQ~*lqb@RZp#O$t{`8#@7>Sifyg3)(LErZ0X4`*ErpqVDMu_@#+Z=mbIUFY;}Tb zqgu{SCO`SROon!GI&;_e{5Zh8aG{w z^*m2o{gi#cl&aE-4fB`z_Bxeblni+yhEKk zJ!eD&MV6E@uL%CMSClW!FeyUZXYQpHON|6CtM|6Q^9hwWH?PaIO6ta@BExO7^bcHkcM7yVIhuFRU>BX;gr$(6#x>e-8b&NsPwtS-vL{paMT zMQ{CYU!PrfYwOK7lMk1D_WxG4+AeZ!+@H*oi!A4FdG7n$Bs}-f@|DS{_L?WV`1<8F z?QC2Fe_j5%+BX%MM4ItvMBIQO;J{_b-!aQ{NPU znb}*5F5Xp*GPYmUC;8bk^~?+Z*KJw7=X-encXtBo|noSuw ziz5UCE~uWHG3(Nd?@Ro@i@14AyL4&I6T2%Pe_agS@L%c6&K*xwTBk+p#YgN3ieFrO zQ0D5bjf+$4=ZE}|3|RF4v}M|pj?~v@rcZyFeO6|I*t2(Y74+Rp|7~9UWwq07u}PCf z%C?$CeK>IO*pIiZ@s##D@jF`M2lhW_I^e zC*~xlrq0zkbbfQ=aa?U!a-PkgeSm;J0s!cs%NNli?$ zIXOB1S7%iEsi{qi6{`xCpRO|JXt(&^3g-=*7n=!Pja;{)<9_dtU~j>?5OK}tJpvC` zHSd_r=CLoQN#p&|6FV|mila;I{UmKCO)LEO*89`^*8c9^v#BjD0)O=9CcLq?tE-To zwmRHk)uFY~8z)G7b3Gj7RMURqygk>ul7gex^{&1uySXF5;?`}cr<&D)GfP_-_VAw) z=1;ubb#jJbnMhw=Ov{hQ-4kAHWXfa|TXD{|;Z&0Snb|9Sg54JFv*DY6Z_DDXio#K! z(;6BSzU6FQIm6WZZTjaAMH@D3$eAYeMEZp14wF9x3z{ZsZP@vX>s6O+z_ePPURAk_ z)qBqT*b*Lpc6{>nPD|M;i)gu96 zr~4wRMWx6XoTj;UCdpALHQg;D1d^E9)WGm*H{u3M3OB7Pw|^{IJnz(Zk6i z?k(rS=RY#7{S+ZJ_5a$p4dExbMKs{iAl%kq~jGnfZjGdpGTFsaH@>e|{ zD?MAGJvm$T#Uz_pv)}5?p7rN-51rrY=oO+7(X&O<>(=605wQoVe?_>&#f5l;o;|nM zI&uEJ*S=koHY&;IT^C$*Xq}MLpDpta*fUDY8XKA9Bv;OeJYQg7c>Po1hWir*g=@{c zg8oe2!C-%cmDRv2h(}oT>4Jq;jBVWMhibUH zd+HI_*R4Ny)Sle4-23_!h0E!`<0X!qcY5#oHK<|s?1ND&=Kaf(e=+0Yww4+H6Rs`2 z`25N5`lyA!A{Qp>A31$4@94o(Z%&>+UEef)`hN~<_1)6e*3SdY#HQ`l@u|;APEWjb z==|Y*aSh$cy87(xtqknnv+DHXq!sh(ss-aFzFoxRG;NX7A2p#xPHIX@P1>$3KhIQD zSWKV1?^615ZP6|NO%BbqikR~E->de0-crq9)`~8>uWE9IdLp7 zD5&z0Q_YqI7uVl%=X%HWns@orkfm}*@7@!+^J>A<^z(~$K41yrjOPD*qvg?#!zVs$ zS7q2K7dhR0fzcJgmDkG;+@2>8aM@Df^Y(rV@Bgb)EA0{kA7-n6pRq4roAcQ1?ff66 zJlo=7-`>)l=CN-BmpQ-Q0bljpCG(6`=Zp3{N=ej<>abkc`{eTJhY2Q+uWAHdl=uDh z)%%dQ$-@UKsy`nd>M?LD+vU#Bmbf`hmHCeEmgR@5Zr({exj*jSd4tq-FN4)&>^7c# z()`;mHe{)+Q{tPl6t^1+ckgp_hWBhNW&OBA%*XYQW$_f(Jon5d=AxwS3#K)!-Mm=! z+AQ5ryX(1;5|iJO-ut}o=C^7o z*B(4_Vxv&oi4@O$_Gb^Cns?yv!C18eXM_EE+=Rv1tF`U*!@D~s6zuKTkRZvpQYf)* zpG#iYwaIJh4KDsI*`?yj%koxz?gM*cyZO9&vf)`O|6V%ZUVf(G-~IlY7g_A43IEL= zzPSJLf8b-6+yDRk44eJ`H2+)vx7YXgK7Iai@&Es8%T|0`mh5={>~wjn<#zA4*86K* zxbR;*F*z;n$QSm@b<^x4n>b&HPxMz-S9jM|XRqdFoOAoh<)bGLUOaX1+&!-uVWRrt z@r>-;o9%Z_OVeNCn)9Me?5+CV_vc@n_;1f$%V*_QB2)j|xVCP6$(#Lk^o)a{ABA57NGQY)6DM`m~9cl|CE6YTk`gELUZ5K6amYGnOsco}ew@t$S zy0g=RjQRiadtayTUG(;}Z?Js4NbO&Ss@FmvpM4E>>be~`t$-uZU0mqcy8aW%-h!`o ziHL7M-#Gtq%#nEp4ksLWm+a6#+}o_ZV7*b*gzxL8w$&@y{*T<@>Hl5l+T7m@m+x#4 zH2w49VC;>k*~SOvKC|7v-9#d6g4p7f>h)}QGTYtfSSMVrfB0b2!xyJtPmtax>A2if z@a@9>riM_Cf~d|??&XRXa#c?Wl`rTr_?$6<$S>P` zPI<5;`|E>At;PF7W1ih_NwEH%=6LRZe04fg-_vXFKJK0D^HIv!txd(K^^EAE2`L&O zLP4Ibi^@9ECh@E^$00t&RW0R$g>?&&XMHSYzUn14j=!K4-hY*5_uh?((iaPxA7!uw*0!87M{A^E%aX4H?u3{`L2s!rKy}#uS%*u5^~2*zHQCo zI*;408n5_X?kIoL*!}xY!RG{pGM(~<9R~kj-#_xVz4K}Qg!z)kw=_6xZ~HREbVv1L z7OUI$7wmkfmp3o2>x)Ho%w0QfNzTm$YPVRW_qr)(uGI7sF0_|UZ5I~oi+GgqsdCAd zAE}eX|K|QPs9@)l5O`yId*k+>u8hB`qA%Y0!6WzXTux!U$!$47Z`)sPCp_!c?g;*I zOuDbjukX{3J<5mVESJ|#+;&*(`D57v!)t8miO1VEep|xM`wB~Lbl0&@7}&} zR{{4$9{n8N*yZ@6KaKEgvNv@+q_VHF=_+2amzQ znP>fWY`MxCK6%fE%1+xap>1Veom^kvANqAz;gMazQ5o~y`*yWQz7d$w`?cTT@YQ*` z?_N*)tx)!L(!Phz`)?I5FW`|f@lZ|JR(m-y=x3z*GzIgk+>)M?3zH_Zo>TR6_1a_n zEq`9$r8zg^^)p^FUJ=aySz2srWhLbiDRHeqS^%pJ?+4#0t!Mq6qVs8|4ZF-eID66%7vknVkj-CGF?3(lY zMfxZIzV;w7RPNq3Tc@LInRgUsNm^&!Yt8*!pqIyY?%1x$i>-~y&mMl;TzBHmW&y`{ zVYRD@Hi@dtUmyAQtM3QCKbZ&gr>R-hs_r~~;dW^It@Nie-sKz?`#zOBJ;`@M`1(r$ zg}ZKFzTRcs8t)osms!6gKE7y*`a5ye1wSt7@2I&Tyz}|A1zm0oyG6RYnv~!0ro`>l zNLXK+`~O16yK`bGakia`ixvfhO*wSu<~9EIlO7jhH}8A;sF3fGM2fmW$7aindEB>^ z^D}jvy`3fF%*XHR-Q*Z#|qKZDEqs_fasqDwn>Co>mnBr0yY z%)fB)-l-PNKQ&JJ9eG=Wy7*G_}=cWvJ#xXJNx5;PiktBQX8iq+UaA`w0v>p@;zq+tR$aD zAE{O7Z8N!l_SxBM2K;yQ?V6r{Kfhp80{d<6{JOx7@U2Hz)XwmB`75~V_U#LIKeFw$ zegE;Jv#?SayK{?b+fuu4CWnM$pE(}a*tc}|#L3Oc6SfMRU+~N!pWVb}e`{FToww;3 z_17EB&wjrc6z|~j*GMi@@crM1nvd?ryB|MZl@hy?!P2wyS7Oqkc%j<9Mo@sB{uvoC zA^Kch&!el}yPYot)Qb9R2i;&?a%#QXgAZ2WDs5+vZFN3fn6+8i&&~JPPTn$$4MjSA z>$W=mN-N)W*Yt^MTSNEc&+eUS?1J{0a&qgO_ibKdpUYQt=$SzN6}xpumY)j?5nsMY zL3xralSS?Opeb?pdM2F?Tydi3;Mc_mPxyR0d~@x*h`k5eGFD|uo_yb4{Z_>4V%pSY zi+GIsjy)>A9(-qSv1D5E)`PYU%w}#<8|2sD)l@fpl6`&Ze>uif)|-ntUGC`1^12?r z%%ij*v*OW%B3J$yKEmXVw4^`3Bi z`PD^a4*$V>p?w|PGkf=J`D(HItf=P2$%R#SRpvzHcW#leeiLgYn7vocA+%1Tf~`nb z;b-k?zrW=Lf3_vwViS(-<)7WDSg24WC>K6;@v_|bQNT38=1pfJ zLPXyk|GTHQqUyOo-rUIkuXWcxY>>XaSWDl#^a&_56(6y=&&udIFm-bD#joqQmLARA zU?R`_&v8zH+2!WunSRTsXuPgIGIz3H$&AeOPlk$Dc(;Bx4*33rO)4(NJ(&69g4tRZ z|83-qy(|0U%GK8Gx%wA=E)-Med&?xR+5C&6a97=TyDdu(%J95f0^f8=vX#?VV~RD%}*_M z$$W@D_8U}aO8lEKzp}DY^=*%dQQvW0wM8@gu00D1nJ(-6a%q7~&j$B5Mdc~;W173! zZ42wRTk9ROR5Cs(8R@yMV^%i9_m5r@i;Z~p%!w&fv46Fp&iD;y-2XSS%MR%sJA8C& zl#kPv+=C_FIbY^>bsfqHm^JUdbDEdRIvFmvdoN8ZChTSA&&zT54AXgc-?HiW_j8Xk zpR%suFH3(Pm1z_8+T!HoZ+8C+*3YeLRNOP?PV`%!l8F;HvA)gsE?jTITxRy{fs_G5 zT=22Pb19e4Ej+Zw;nTf*(ef&}gMyoc(wq0_1Xg`kxwm(nW>m7BD&jqIEwiq8iy{r1g zTg788<>Hp#7JLs@ub%VYH(NC-{;q1Awcz*b{wF`@u2`k>ZkENp7xNbXoFN<(bl)U+ zJ~*HEFZ`vjY`N0xZHfh2r@H$V{7lu$l9xNa_l?1upGTPj|E+UzI6Sd1g|RxR?3kJP zlH8e1-ks+x3iFGyuDoaNOpc&er3&E3E8RPj{|4!mKEJz_8{>gW7(hn-P_9_KV2*%b6=3L z+Bo+{WZ!OmRV63&)c+@Z+x{J75EH*{P|5jnN@bsL!NUtuTTD|P)%}TBZt>Q$^P6T}db~pOUUzhQ^Tf$E%pdE1x!jpMp}a`8s884RT48;R{RWQX zW;Ya7Z%L_6zpjuQ&LN}Y=Ij`?WODTbg-o_im%U`upZuTb7*y-`~$UczYYyo-B={?dJX;|K-X` z%@cq4vf0GsYOHHelE#mpJ03hYlavcylQ-$S*W@p@a>jz?`#$cGVV1h4`(1fjxbUuy z9p&Y?Sk&p99#bo!>$=MK^4QkNDL&eJjp^lVosGr^7-s)nJ7H_O;W~AF zH?_*Q?^-$TSV=W_|K1ZAyhFCXyFcmU8BU4iYgr--A0BtPe#diP$>oi8XMa@6Tx`f> zGqUMczxa3Fzknw%i%Slf+?6=vJLhP9aB+*zd68n%9~ON_e?D%%@OPzne)Rmu&syJl z+}+7>bNS(biIY33uWwiU|0-?DojYy2UTw};v9oE>m$e?A9}dlOExW5Mvh-z8kyXrx z{gUGKQgdQtV#J=^`sDw3`b{BiWw!5mYKwHtFdu&`zAL%F-Nl%HOkaJ(dl zaqWzJ+3#{Hx_VjFHPH%OMoAxDx#~qpdtbN~(KdbS_QLn?9BtP5xP`tnwD2=)UNy;v z@95e$R|2R0H*VU-qcYD9M>MKsa(|z%7nc?2*&K>0o{>CcrEchPif8_7S z=I#|M_xPL&Z)_9iw`0})w$k{r#Ko+<9G7y@MS{!!OUq6KViiU&Resy)PI~W zJg}8p{o=I(?&sgD6ituu&9t5~LGFFaPn-H#*o^ zs{_Lec`~b=9@^eycxH8~r0A}5A|s?=I@()BT<=duRTO_M5p^@cGil!-`=R`|7y*j-7FM z`Bk zC`g<-e_H;Cl4nSOf=^7xR=2c{j3Wh}A61NVw{|J`&wi(SdfB5#`vPpVcJ@5mrL`w} zrDNSQJDEEs!poDEE&T9C%0}0!sr_erVC8Rt>fE}QU*}rPmT59RQh8U@PWYW!)!j!* zYeb(||4Th|@BUYXBaa?(#u(HdIz8vGcHq>#qW$k=+<*4UuF&*!i~XAVrX$i#N1;%l zn0?ZpKNo^S-y2`MxH5doR4pl+iVrc9*mb{LulgACX;YG4`?eiQx%Y)0sXl-7^6}@2 zu(^HD#D8Y2+1+&HMykN0=SOYKxo`Ly?eMVsyfyoFrfZOP?==6O?m0nTQ=Tq0blP^I z=*^6K(bx4C{!LcCbxUqjf9zY`A3xT~y}vc@!PnL7D{3e8w%yX%v+Dfu)3=hgm|lBu z>t$`n40Fk9<+Q`ui_*?#RIaS%3JR)j`SG*&gyoALe2-5W8yFb;5x&KD`KRaKdxmdo z-+rHzIen+Z_lEgRXMK6+Etj$GDSvOjX#H#5b9wwnv&w~2WdE>+Mqb<@@VsfRH_wLL zdlD)?rIP#iYYP4OT4-{Ob*lNchlvO4LIlq5eDaFT=7hh4*~QHbFOSVwWzQuyO>Mro zk7<4KqGcCMg2FZh#yY;-y6aMhc~sZo=;IoiTYM#!ezHT3Q>BIbf$szVTB~~fh zRj768=N^8&Z1;=T)!oy-PWAAPYk%=m%|a@zZ_nc5iPe|nSzk`92rHY^@t=23_TKhA zr`spWxIR9kfBaD9v;L#5E*VF*|J(Rq-fRB~ZjY`_C1*;f1U<8wx#f;mw|nY8$0^U= z9XqU4bmmUa?@IOyUo?cTs{Y=nt;cXV_soK|3cN=Z4;jcViKwtKt!%6V7RPwQ`JEmk-s)f35gEI)Kg zTg_RW+NjPuj~+ex^k+{@Tyxz&OV1Y5AD>nTep)J*7aYHqlk?Ed;NzX!|B1FY^`zH%kAFIuNFdY zTc653n~}WwzPVrQzlBXR9^{GX-=4hO{LOa0NKhs9XSu`eM~YlVLGv!_9$&lV;&qvS&nf6_0UUx_-Ii+sDH5o*q5*(NTeY@9y!{d@*kXAe9*)D zi{p;#ELju%{gpL1d+S5Tyje=U`#gGQ%4@yJIjHRE5$jdav~bT0KXv7)?YEU{esLK;3iz(T zJN4-DfEjy*r&jI`s4QmJ%75!<`ti}~cPfuxHWxps5KQMkrjYZI=f}>d#F_27ch>kW zSf+4S@5I^I%q5malb-k=f4slsyP2GCX{%*=`LBf*x?JB+_b+(pDps{C>cbC5#xp!$ z6IQHc(GNeZrKhJSb@!Dw%Va5in`vsvbHuBC&qqEoUS61b;n2C*+lLE2-pR9BwXgen zuI`U3cYTlSoosvU-_K%w&-piBi)OC49WVUz_U&H(xw#qj;qH5Wx*wUn-pxChb=E8I zPV@MdUG3Kc9C;S)`J!tf_PTpPq}pC#_tV!TG&u7A>AD$T4n2S1z=!fQ1#$NFnfqoH z6+gL?`CjkIs4&@qT)ASF1z1hip}|S7%BrU(T1072tWIM66dbPf{!7pu z3$y-?UCe$ik&nDCl{|U#)#=o-%o~zv-NBs2g+*w78 z6KaK~vQF<1uWPl~>0YQ+Y5UEEJt6vqj!vmrQ};xpKg%Q(%T9*O>HBtMZt%kud&K(Z z7#rS@-Y+!USzI~cn2L{CsJ6V8+B0pHBfhe6w~{|Pn>KVUdhq1qE^g&N&r{yt*|6!| zm3cq>XQuZ*s4P{y6(_d%+rP>X@i(rSVKSC-E`R@a@0h;7S=QxgrLWbj_w#M!`)yw=%?OpEuUYdQ|($$sqxN8fG=vCXwhVS{( zo#Ao)^WIe{UCY0*=&$RSS~q`w!TA3vK$!`xl|Ni9vx%m5s+a#Et6kczC ze#Bu{PjtGuK>xkX#Yf+CruQCSkvZv;!QC&Qo_%=60=?yhi`^5RA6mI%Lnh-YZvKVK zbVNg2H8u8aVxIoJO~JHE&TmcW!HojZZ@!owdwBGig>Y7DkMHG)($Bljym)!y&bvIYk?>xG>D|W@|8~wX3rR>r0ay$Cd*P}naMS3@rXXP`6yp6Kg z&YQU}SuSaIZtKCCZ03rnm&r4`EwBBGP%hfY?DWj)(CL#>+md+=!@S>iHciRc(X)f0 z*Y=Zc@x^^|ii(QYLb%uFmgg3-Fk$>qWSmEz=|jdPpu+ZIZ@Sz&Zl+ntUhr_C!IYf z>J`KOnZkcmRaIY3|1I?6$&r>C;X}_CJuFnS`);yu&ljm%vC{{g zV4c~CO|5;&8*=(Am8L}`Up@4ZbFlCBDQ zx9D$kd~t{~LOh{&2Zy`M`WZf3PRd0ejw#egW9(DWQIo4N2-?Q}$YF_jU(N@YOGec$ zJ0z9T{;A}A+W-T`G30f4; zbChe6lv0YvK7H9qOZo1`UryFmR#ui3HvInd>+0nNdXJ_0=G!&Db(wRhV})+i3*P%b z^$N0jWmT`5V`W76^XELPrW)23ON9X=`MXEx1tTk=;sox=H7_S$8n&F}A)G->m8 zu3W)W654jyC)*K=R(?lHW{ok9}=ByYU_G9MhHM|9Ebn-@N>0(zMeeKC_Jk538ys=34!l zv0=l9?{AhJKXBl{hyODhA3aifoU8M7m)~2?BkNu`9C2fxxa}r`m6p+k@ZcB9oNl+Y z4CHKub}gQAYio$8on*%9q(u|;-uP^Jn6j!<)Hql0t-bKPZEXe$^MfZ&{n(s9P^9?_vr~ItXRj8 zY+E`*y8jr<-@pwQBptUna6X&Wwc(O1qqNe4ZOfjRGV@Ag_clzM#G^LhJA1|XBTbTg z8@3y~+C1A}TgsA2PCYF%HY{GCFrV$`ypou|>xIA8nY5qwNT1X9YlreJY3b=!N%wzQ zc6{1;kjY!OWkOd+_l(vZzLz)D&E&nNTj-!6SZ$tNdt>&?q+3f03%1F%-{gCCBxzRP z*~ZO+?+hg`a?5O}e(IAGZ7I8O-{eGRt%4;z3X{ywH_hMP+J5JHZpmSF9gPh)g5tT? znJt^~+DuY9{O6;fsGRd6w+l`3eoz0#6tKh9we|1fYb|vhJp7H{IF^1hTvasx%~_M( zz9vuadvbAa>Ehtn>e1b0cA8&s&GkvbwN_!i+ln@QJdu>`yfxjjmK~^!c=@zxYxiCO(I?$49SJ(0 z=P{l(l)4Z$>2>e~sUXXc7?aR2ucXCorwYPlw+f~yyJ@WW{P}bDg!k^%Q(g*u`G59~ z7Avb_*pE*$SMwdI4$qHzc}Hm9iCsr8yDdJNH6^Ee^2D^$O4~Wtp03S#m3HgZoh{db z&uzaDqAT z{yJ-({q>t$EJ_w;yZy;}9~!nSD}MKTEB2Ku1Q&};@meM!$lVzc^LzW+e-fJxWv^ed zWP(oZ-|O3J1!Zh(Y>aNbQa)_r-gie!M?>Q1@xxmk8_EMDcJJML;oR51|36pC-MK}hyL`){Ek7zu zT{Dd}4X24^&VJcuQj$NhUd2#s{WKFpz6!R_XXI^WnD?}IXDj|(V=OO!y`soOKtN!I z$F0h2N5)10%goLw)yT{jD|y>z?o&JVD(irYyX@m*8HWR+7hk>-@O|N~S0{`YEn4J# z^H`g}{9OX(+t(aeZ$0VK(yLo?w#5G5K11j1!sW}AjEZM7NDZv}SFfV^X-?Oa6`Q*DOxZNA zZO^98d0m@Y=dt~acfHx7B5mxvlhexT{-$Sh5BZ*7y;LLB#LxX|%B>J>*93jlJoEOy-(_>Ne$~8lr|*s(KhCHeZSnCi`u9~MO-WD3rfo{`lnDaX z1`+>%Sf2gef9`j_b3N;YFTYQ{TED?w`C@U6KkEgXy7*=9*Pi+JsV3j=Qhug}OYwRf(Tzz_cE{&>0kKU3K8^8Bi8b4?i-7#KWV{an^LB{Ts5R!->r literal 0 HcmV?d00001 From 95a7925177a67ae4990d11140579e89f0f66bf17 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Sandro=20J=C3=A4ckel?= Date: Wed, 21 Mar 2018 18:29:43 +0100 Subject: [PATCH 0459/1544] [game_morrowind] Merged changes from Schilduins WIP branch #1 --- src/games/morrowind/src/game_morrowind_en.ts | 9 +- .../morrowind/src/morrowinddataarchives.cpp | 2 +- src/games/morrowind/src/morrowindsavegame.cpp | 89 ++++++++++++------- 3 files changed, 65 insertions(+), 35 deletions(-) diff --git a/src/games/morrowind/src/game_morrowind_en.ts b/src/games/morrowind/src/game_morrowind_en.ts index 2c4358ec..e3f9d226 100644 --- a/src/games/morrowind/src/game_morrowind_en.ts +++ b/src/games/morrowind/src/game_morrowind_en.ts @@ -13,14 +13,19 @@ QObject - + failed to set game file key (errorcode %1) - + Some of your plugins have invalid names! These plugins can not be loaded by the game. Please see mo_interface.log for a list of affected plugins and rename them. + + + failed to set archive key (errorcode %1) + + diff --git a/src/games/morrowind/src/morrowinddataarchives.cpp b/src/games/morrowind/src/morrowinddataarchives.cpp index 1c4b9726..aafde61a 100644 --- a/src/games/morrowind/src/morrowinddataarchives.cpp +++ b/src/games/morrowind/src/morrowinddataarchives.cpp @@ -21,7 +21,7 @@ QStringList MorrowindDataArchives::getArchives(const QString &iniFile) const QString key = "Archive "; int i=0; - if (::GetPrivateProfileStringW(L"Archives", key.toStdWString().c_str(), + while (::GetPrivateProfileStringW(L"Archives", (key+QString::number(i)).toStdWString().c_str(), L"", buffer, 256, iniFileW.c_str()) != 0) { result.append(QString::fromStdWString(buffer).trimmed()); i++; diff --git a/src/games/morrowind/src/morrowindsavegame.cpp b/src/games/morrowind/src/morrowindsavegame.cpp index 36be25af..41bd55c6 100644 --- a/src/games/morrowind/src/morrowindsavegame.cpp +++ b/src/games/morrowind/src/morrowindsavegame.cpp @@ -1,6 +1,7 @@ #include "morrowindsavegame.h" #include +#include MorrowindSaveGame::MorrowindSaveGame(QString const &fileName, MOBase::IPluginGame const *game) : GamebryoSaveGame(fileName, game) @@ -14,62 +15,86 @@ MorrowindSaveGame::MorrowindSaveGame(QString const &fileName, MOBase::IPluginGam uint8_t count; file.read(count); this->m_Plugins.reserve(count); + std::vector buffer(255); file.skip(); - for (std::size_t i = 0; i < count; ++i) { - file.skip(); + file.read(buffer.data(), 4); + while(QString::fromLatin1(buffer.data(), 4)=="MAST"){ + uint32_t len; + file.read(len); QString name; - file.read(name); - uint8_t tmp; - file.read(tmp); - name+=tmp; + file.read(buffer.data(), len-1); + name=QString::fromLatin1(buffer.data(), len-1); file.skip(); file.skip(4); + file.read(buffer.data(), 4); this->m_Plugins.push_back(name); } - file.skip(31); - file.setBZString(true); - file.read(m_PCLocation); + file.skip(7); + file.read(buffer.data(), 64); + m_PCLocation=QString::fromLatin1(buffer.data(), 64).trimmed(); - file.skip(); - std::vector buffer(32); + file.skip(); file.read(buffer.data(), 32); - m_PCName=QString::fromLatin1(buffer.data(), 32); + m_PCName=QString::fromLatin1(buffer.data(), 32).trimmed(); + file.skip(36); + + file.readImage(128, 128, 0, 1); + + //Color correction, I am unable to get it to work in a more efficient way + this->m_Screenshot=this->m_Screenshot.rgbSwapped(); + unsigned int rgb; + + for(int y=0;ym_Screenshot.height();y++){ + for(int x=0;xm_Screenshot.width();x++){ + rgb=this->m_Screenshot.pixel(x,y); + this->m_Screenshot.setPixel(x,y,qRgba(qRed(rgb),qGreen(rgb),qBlue(rgb),255)); + } + } + this->m_Screenshot=this->m_Screenshot.scaled(252,192); //definitively have to use another method to access the player level //it is stored in the fifth byte of the NPDT subrecord of the first NPC_ record - m_PCLevel=1; //Placeholder - - /*file.skip(8); //Record SCRD - file.skip(16385); //Record SCRS + //file.skip(8); //Record SCRD + //file.skip(16385); //Record SCRS //file.skip(8445); //Globals //Globals, Scripts, Regions + //file.skip(); std::vector buff(4); file.read(buff.data(), 4); - while(QString::fromLatin1(buff.data(), 4)=="GLOB"||QString::fromLatin1(buff.data(), 4)=="SCPT"||QString::fromLatin1(buff.data(), 4)=="REGN") + while(QString::fromLatin1(buff.data(), 4)!="NPC_") { - uint8_t len; + uint32_t len; file.read(len); - file.skip(11+len); + file.skip(8+len); file.read(buff.data(), 4); } - - file.skip(4); - - file.read(buff.data(), 4); - while(QString::fromLatin1(buff.data(), 4)=="NAME"||QString::fromLatin1(buff.data(), 4)=="FNAME"||QString::fromLatin1(buff.data(), 4)=="RNAM"||QString::fromLatin1(buff.data(), 4)=="CNAM"||QString::fromLatin1(buff.data(), 4)=="ANAM"||QString::fromLatin1(buff.data(), 4)=="BNAM"||QString::fromLatin1(buff.data(), 4)=="KNAM") - { - uint8_t len; + while(QString::fromLatin1(buff.data(), 4)=="NPC_"){ + uint32_t size; + file.read(size); + file.skip(3); + uint32_t len; file.read(len); - file.skip(11+len); - file.read(buff.data(), 4); + file.read(buffer.data(), len); + if(QString::fromLatin1(buffer.data(), len-1)=="player"){ + file.read(buff.data(), 4); + while(QString::fromLatin1(buff.data(), 4)!="NPDT") + { + uint32_t len; + file.read(len); + file.skip(len); + file.read(buff.data(), 4); + } + file.skip(); + file.read(m_PCLevel); + } + else + { + file.skip(size-len-8); + } } - - file.skip(7); - file.read(m_PCLevel); */ - m_SaveNumber=fileName.chopped(4).right(4).toInt(); } From 1650eac953f663f9b1df1f93973c929e1b5b889c Mon Sep 17 00:00:00 2001 From: ImgBotApp Date: Fri, 23 Mar 2018 14:08:51 +0000 Subject: [PATCH 0460/1544] [game_fallout4vr] [ImgBot] optimizes images /src/splash.png -- 54.12kb -> 51.74kb (4.4%) --- src/games/fallout4vr/src/splash.png | Bin 55418 -> 52981 bytes 1 file changed, 0 insertions(+), 0 deletions(-) diff --git a/src/games/fallout4vr/src/splash.png b/src/games/fallout4vr/src/splash.png index 2522871afd12baaffc532b57a91d30d66f69eed5..b5908bc88ffed0126695a78e4e9e4b9f44942e69 100644 GIT binary patch literal 52981 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

eD(kHJ+eRlhXFjkK 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 Z`jYB*%T61HGB7YOc)I$ztaD0e0syF#mE!;a From be1daf62040b098688d90b05acea0a8172308bf7 Mon Sep 17 00:00:00 2001 From: ImgBotApp Date: Fri, 23 Mar 2018 14:08:51 +0000 Subject: [PATCH 0461/1544] [game_fallout76] [ImgBot] optimizes images /src/splash.png -- 54.12kb -> 51.74kb (4.4%) --- src/games/fallout76/src/splash.png | Bin 55418 -> 52981 bytes 1 file changed, 0 insertions(+), 0 deletions(-) diff --git a/src/games/fallout76/src/splash.png b/src/games/fallout76/src/splash.png index 2522871afd12baaffc532b57a91d30d66f69eed5..d612e7b86367b35b49a4d682bb8e7abd086f3f5e 100644 GIT binary patch literal 52981 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 Ad;kCd literal 55418 zcmeAS@N?(olHy`uVBq!ia0y~yU>0LwV3^Or#=yXk^3q?6fq{V~-O<;Pfnj4m_n$;o z1_lO&WRD&6 zg#iqHI`6J$U|`@Z@Q5sCVBi)4Va7{$>;5n>G%$F&IEGZ*dJ|h7A#(j*U3p?+4BO%~zu#BCs~@^AuXJsH(&Bp8HT$^*6dW2D z7@1f&1QZU~Xk2rT|DE{%UFQ#L?z=9H0?Zp&6PO(i{o2pV!*#6w@MkWB>I+j6w0T@+ zUSPZ+Ra^2vODgSSx$u@wb|;=@r9}1vbypu1-c3JSQ8lsJ{eNB1%Hrsi+3xHc=XRfP zOUi$1$DP5Fc77f&!;LMO!JD_lM?`Sw>+9>p?U8tWZSCf7kGTW_)W!7UcsgB}dfk|N z-I%vV^|Eq{C7hU`*qfDpc9!XhGiO?&*1CCka40D&Gcs&WJG<$d^1oaG0fB~Yas8;> z(jfm_ShL`ZRY>THFXnlop?15fzdrlw{qpv_*j>-W8A2IWF?8M<;4txq$3<_Vs>7-wf=cN zufM;4cDdt$dPy!Wt_N@5=DyA25IE52k<%=-w>LsX%-U|%Hcp+3nsz#SsvhoT|Eb>Z z-dmk2$Y7eGx|nSX`{5(iAIk%DI;J0D+fwet z6z!DRUH*PsS-3@jhDgBbtJmJOF);QXJ3HIF@XZaw3=^pyS?h0|*U!(hmF8+?;%a3Q z>SUQWZ{CEHDQEu3TbJo9TD;iu{>0PL+wZQtnl;&s#e^?wtCZ2qGq>($7|K|e@hH3X zY$!ATw>rV5or{Z0VWP*HySj`_1#fN`YKU+hTd_K9^}-OXiSy_8D>}DL*nDQ)=JEqK zq-Vw^^}o6M_26mwzhztwtQq`mo!=L2)fPMAt;m?b@9^#KE7n>ypBZ0VmtQcnU2}Km ze(kRAZpG=RrB(i1VeNH091$X|{pLz*Gdn+5m#eIYr>7vxk^PJv4rZB`RBFE6O#krx zyZO$vUteBMIGHlx^wT-~AFr$o(K<8B^z@r@>F#Awv;Uut*qU|q|CHlNXJ?rd@Sd-}BX-{0S}YnFQ-sdztK z>Dd39i+5kY_3(4pe_;p7jQ6cjLc#@~c*GG?%*2L`Gec*WR@?{7*dbwCF^Nk%kD@vvRGeT>t+4 z^EpuwD`ED1arpH;W?SVM)GxTzOK&LJ7M=ZR+r}Wp{d2bb^`AdurQz4wmzP>)YTtA& zUUg*2kx4yg_DniteX8qI*QsaRH^dPo#)J3#6KAi!v(J6I-lqi%7`7KCyI1`^;cIOKYSWC!bb__fM1xHIHcrf>TrWmAy0f7iYZzy3aTm9P2a%azgV$!hg%HIsuX zPvq;;OG%uFg6xAmPtuj`tPdEh&Ya|Rm_1MM;JwV5m3w>k7udf4()@0r^D%}1CJolP z`3tjiyI4K1Ok*tQzWeKGd-L-BrpNEJ-ZuXm^zq@W^G5nHT00n{qP5sQ2yAHzWOR1o z++DN)$s0@=0Lka7Jub*1yq}MVzNnToBe!o^cYHix-@c7!lsu__ntP6ITUOX$5 z-^$EzUD>+s*U>w!_5VKA_dnN(s1i63%dkCL{+V4yzN_VnN3uCfo#KCoI_^Y-nL-2i zq~wF&qCy&`EzM={IRAXvw4W?3rx+9d{rTC^)5GHMvnk9;qHM*rMG+Hj=v6bE`~T~~ z(dEp){l1y*%eWrDf7iWFL3o7cvK99$4$!7w3S zr{Y7!?>9G#oI9k9UiZlB0I8PDk4l1_!&MH!ZEt^nSg1oj=)8Tl6}ENYl44 zfu&7*ShhJSf|3t3bQ*p+ZnV3)Aoa7+1w}utxqi{UtBNNtTBoO{XLMm<@LI2p3b!WO zGAvJ@_fB5uLUxa5(~0u=>-S8aGH*8Xt>8e82Yd}e7raEXLaGH5BsDIuRq1B@ z+{M*!Yj5xFDIpW5pG=wHp;ECXD72}J$H4VdRCki&qn&fa^k-~7@}ueW^UWpe_x}FK zc%f3XoI#{9OzVcLB}=OltPXZ)V5n1QtFq0IjJ|GtTmoF_oYR*YPL5dki zn{?+#&&`|Gd7nw)wb+f@cYicpPJeu^v21fl)48<*hZeAK2qf^eNSzmJc>7!5Kg`9& zHNP_btNH7M6&zYEF3{xiwRz%s>#C}XA1udDi0Q>}bhM|9xV0iOI{;^0)bxH?EH0NDN?N;V@wP7<7Ya!WW*G5C7ch?halb zcjl*=qVDuRz8@l>Y2j=0}6d;e|6&-XIx|L&bp zx|RVF2?uO$bhSE1xSW@0bz=N9(L=?<&oi*md)1MN=hucFZ_*Ge`4g5fWBy0hnJZ70 zJ5+1m$O&jl0_8lWvLBOe8D2h=-JhF(-}FTFsU;t69jjeR*Syx`kn@KazCf?wk_eOY zA!||F3YMKQ=VB(zm{GyI?2~2jwkYq730ChEwibWtmC!QZ_u$IR%{w0)%jf(FN_Ywn zT7sDhemri^-~aiAlu5$p_4ajBCQOXyZC>8gv>*f)IE}^Ye*OAUVpa8J#$FetMz5tz z3?ky#QZ35y~Q6vHK4_ygOZeW{cxgG4a6qx3*JRqm+$q7cw%j{5gLp zVr9Xd4P|G!{NFFgewP)niFOi&Y8s+TQm ztJHa$&pqF6ZOv{qSUPj-s^d+8g;`y~t5eBmFKO7{CYBXr}Dh`U+AA9lMjBU=T>udUZFP`tcS<<<^F(=N9Vafab zM!H2WXJ^-y6lE%(^0NAsaI`%>XVu%YKSqh%y3Wsu9Wzf<43+@Y`VzrIYJx% z<#L?(rI6ms*Cr72?Z4*Y*U`c^GPy3jxVQIj+54NxtAkc92wVN}cK&`whHdX{r?6c9 zB`ULJOVYuYKVEaI^_%Tm@Zucr-;+Pic&})dzwWgnTghyzn^%jvk>O4I=*9ZS3|}=h zTr1dMuJ*Vvi{l38@s#AOwVo&5SZ3zD-N>p?`Sz&hy@Ll2Ud+9{?fdjwr*GZzmc4r< zN!ohi47JirfmQ(m&Z}24GTi8Lz0lY+x0l0AY3{aNt9CiXudR!T{rlt9*Vo&N_TS&} z`q78Pzt2~Ccdt_1B)EU?qrX?Te!t!nrWJMio}xp8=|z#}tp#EnKXxDf(W6wP@px)Q z_QM_LoY`Ey6_yurPuL!~W%9{6ce6~YR>tw)@NjAH=y}!U|8@v%*xtPN zjG&o_YiP(y`PW-^&ARmHQS|qB_fOkSoiOv$>u-y_E*#p<_T{F_IhAjf_hub<65bgbi9#Ft~uCxXG_)3!nG`J z39s(li`|v<@J3$N+O@u=zDs?3qjDFE-@YJiqRQl=#3163>DYNhLqF6xM}1+mAoH$Q zS+}mMOm=*v;940es&{|gBAGWwLmGDXp7UII;iQc0s`%)?hf5{Yl&gi)x%10D&#T=w z+i(5k7bQ{By?*J+%M_Y8E(9~Ma$N|#(Ad=5(KI)rUu&-Jk*&u&7yFaXCe@jIli{smq4@7dRUmx|9ed1?!&h(Yn z?4qs5+*U7lN!sXxL)8L=T>gE=<6@Z#M1P)TFig(mFYt z!kcZC!R=}6>|Z!K{LkvHe9L`uwZeNZfd-a8`pq}H_gHP2xNmnt$o5THr{>BbF*^=ln_qnJ0k@JM&+euyoMeAJ1Z~W#f6XeL-(}KgaYkJFb=9*0Y!G`MCLXL%rzzi*`FoU*;tq z{Mr1z_E-IXuamn%xSB7n-nv%tQ{Nkg6G}=-PJD7!J(ZuI8H%SYQL|+*|GzVIO5+CB z2W$uA54@26nHf4o@Y+CGk z?$6(kFXjLG_V%`y5x2#ywfm3WXEj?;%n-v^qM^Gh>}-1764{vl(l1IMGgRqqYun+w zZQ=pR2KV_M^Bat-|84#JZmUdb@OnX}wQkOTKQG>1$86xJw6XS?S6mXSYhcL5wb{4i z_tn(vH`p=k$-Y0`AfEM)esgtM?$3tnHpCy9^SflN>;pCOz1Yl zi?9hhRF`V1M`vbge!W|Mzp!rko_XIT8uH)np41p8v*Pb{#s;Q_a>u+op`YeZE2l5>IhM(^C)*TQr>nx^x7aeK1$`}Ol?tGe^pMDDh2I3eiI`~O1B z{kd~f{~uFhkImgzr0C9_z}ir_V5?gB1^v6THn6UJ zTgE2v^+8(RhKf31T)1$thUA~c_is=KB?v1F`D<0ivO}g-Tk8Hz%-2Xp+3C#bfxo>hj zbArGN=Gew-3o~vv-V?a(D=B&Teaxqg)xJB`ULE>=zpha9fIY(=vCGtDKiE@pZ$;ew|37Z8T<~J~Ewk^v|9^a4-tHY= z{XF39-=+WmyxBb6y+;N#S~NM^Ik|1?&3~6?`6qJR6nM6-;lHavdU%CLzuvpIRTdvJ zb-um1sdJ&LD*MAME`bETImWN%s$Q@YVk!5ukkOHV!5T^X@~{mwykjZ>F@G)M!os<$j#;@37mhE8pjCuuFDp-nQaI z!e8I$hK6Zu*8A>!ocdhNXWPcDH7moyrX;>?TYJ-Bjwch#7PEqLD>gb;|K9WUp1O6+ z?b7Yr%Z{H>T=0E`0e|^U_9*vttik&aUAuN{<@pDNdB?<$9GiEpbzvRr!kJ57Wvx*? zAXo76!oG*LR%QG~oQ1!#zb|w#mffy)BWg~vgGUI@`EL?BF*^jh#r2Q9xw+Z*U)gWJ zKuw=k#po+ytkM6^PxX$uy(Ry`4N);Mr=>wxf0lQ;Fts{0HZ?IFIey%D|Md(L51$VG zwSO<}=xbp3oN!t5blfcC%o%rl6E`}nzIr9$?t1IX+4Wo0?&<{Qc%E5x`?>u3f2)1n z|EJyGaDHCr)pPTV|8Iy}U(d1N%j?4P}CZ!@f z(x;g6B+M}qIDfXLYQoO$Z!%UhIiu|Am8MpE%Wd;HK7Xc7+MJK_=TlX$-_g|C7k~Ss z)z89ci6f_#SRdRts=mcJ*i>iYg{rAOYQ{fr_a2J=eo$2DWK$u7g1kY>lND|Ej-Ni= z9Vm0gQEz&4NSKa}PD|8U&`_kHv~>5ABS&5v6c}u8`(et`y=Aw} zF<7zS!wP}N+(pKdx*fGe*J|!>`nbtQ>gw_Piznw#KI-VHB2-ab?W{CWK~=T&^Y$}q zip>w+-E(y7`*WF3U!U)P^-5kd`_11yd-uNn662vFbmD0d!npQer>bytYl6po3wLtp6z?s`}+DyPJjE_PY)Mg zVq$P*2=R`uT6h1(^5s<~TY9tBx^X%8wQl_!%)*hOxnb@0OA9YL-nHG$`k5=zrtD9O z*^Y}WQ5@-w4cD08Ntza&ipeftp}1nr8bzP^*LYf!PU~)3@PH%#G4~{4q4x(u?A90m zjdtER;V0X76G1*9;Ya$1O!gnTB`v-<;!IuIsT<33BGe{3E)8;2nwaqS*Vi-eO--+Q zoVBVKkKt$ZWGkCzk@~8}`~AugE#EqKr-dp)oGC_+b99VQ}Dl5NO?Rw(b4C{|8%+Z7F{DskeQ>ap#0qp%44nf?jz2IyC2Fva8bR{$IzJ zs$MzAyu3Jpqgeoy8-y*=ue9agt39`Pvj67i|4doe#c1oW?hU)CVynv=bSC_jR(Vmc zq`{S&KbjV+`z>26xXHs?LrmuN$v2*dm2PeMY*hI3&%Vb6Mm~?Xui^9)b=u#s;li?< zn6+WfYr~A0Y(GX#xfA~C;MyH$MUGZix%@vcA#U34?_J&9zIE<4qFk*^^XAQ)aQf+l z(@#D8d^FguN8OXsTChE>;E_oDEaS|cxqF+B_D-E{duW-g`{fG&rXi zA1|NniHwYtOglSc-pr|!r?WobYe-_4YX9f=>{MB+(##F3e>`MX6`fx6PL5~x)&&t9 zKjInHwaA9Lxei4tEGTU%cKiC~?)H=CR?L{8=DpgqF)X@y?Qg%> zhJ&;7*8bsgvQUoQl<>^sG53^mu9e1|E5$Dy_`|gzwPJ;($>zsyyt0Wkj&6@muG&=e zRe6ivYm3D^j1x*fay~x#E}3U(5NE3sBSXN-kci!7x@NhzTHN`&JnWbQbvz`deBQKF zf1lFE%{JmE=Oj5!k#@3P9iX8w{q)9<+v7hc2IzDIXv?UTHs_iacDy>8?|#b5Gax+d z>WTwrEjN`(OzHN|_@CAteKo_RBJ z+EumfxwqS1US4kelUJ&jZL*s0p=|wgsp{(%Z{y!o#ue@wvR_bf+Wm=bQEQ*6^i)?> zIVnvvm?zBe;>JehZ*T1efv%R-}k(2>v$V<4Az9J+x0G8s&cRG>t}6?lP~i3 zn`G|ju0DL@gw8?f)6>NAZf?^Sb5MLCu)=8P=E-mFez&i1%(=W{&$caFrbHX~nuxY2 zGXCdI*i*9j7rVAr$Wc@NuI{5(uSym6hUs5>sTt7Fk*%=Qp-!x^DMDpYPOgKes?y(u zht(f3PC2vyJhT?YZIOOuw!XjgE0ypMR*P4y()xJlPkOgm{@qf^FOo5_ztw-+Z_6pa zv$@*;y70#I-8W1=`53vyg?(a{;1FDsy5s2+``_&DrH1N*doibTlrFQPzdG+bjr~C&?Ya?$rUzv4~ z^ZV=j)=PFzFBjOKa&oe|@dc|-+B5E~Xk=#Zd2lms?vD@6Q~CGB|Gyk~!Ru%&Lq9{p z;r;gYyLab5zW?-~^Ks*Z8N08kH3=vzP*r5w8~&p2$o$=xPi}v%#Bi6Pf~kPnH$QTI z$P#8<7aOLv5AHKKoNK;TV8<=saKJ3)bQ_PX#hm!>Q z+B^QoRi`agJzn1R(!67OTA`WVJ0_mC=xlctkKJW?_sukvj;YjD|6iD_xgb?=+r*oz zx>(yIGf#2{pZRn?|8BV!cW=l2EXIOE+pAcD$b6h- z!7ugGQMxab|>%@oCb z!(?;cT&v%|KW6HvD|>#wT5dmwt$_Q>9(_jJ_eU38_lst@%Ku(Gw3%=3CXT7EivIjL zelKOlyg=Q`W5rKCKYunuNF;Xuto5hQ?XHmR^$E`KJbFk`%OtDgBWrs9`}G$xw(veX zo~vjOHRsUTn`pjou!n8~N*0-i5G>(F;Cnty0-$w(0x5_^;bkIX~RYo1;_EV74G*8Tm@e1Yl4WUY(BOP2^aNM!@&`uWnAi{GT4T@}v2V3u=( zfni7Sb3ehJLko`e&p*>W`RDHU`+t@t{h|VL$rD{QR4pG$MTKW9Wnk3hToe(~80XLL!0maRF^08ZC*ypk3#aS^ z*LkejxnUa17O?{5q-Xw84v z!dDcBRh^2R@k|#qRyi@6$w|qF%Rzm)is*qYb!UZt-@GHoo%C@_`4r0?E?Md66NCJ5)cwb6)Whn+s# zvtB1O^bXrvmpjaBC#-f@FQ56gR%>~0^{ME0=lah)zcBIfwQ1Fsl?(SOGwu5Jf!j22 zTG?CM9Gz|x53wA-qfN>Mx^uqwcs_dGyeRt0#LFk2N66;${uGtbU6<{UB0le}sYKLT zw&(gWJA!}zDPzcqudV#2Z6@?@Yn%udtBDjZ7dQ9A_wV@|_?nd#1}G{j2CNM6@Y@;7 z@jCkSf4>Jgd5hclC1RlrIQO`?vJWpM92z>)s!$HG3z1eXhhc;{}Z0R|-e2 z{HSUW`eu!*u{NWEtf|E&_x3zTp?SGX406+K4t&X+ER=U=PbuG)phD>_sVk%!zWhFa zFIwzs{*Kv8-=;59*>dD}^(7njGw1Iwn|HW(=K5#9u1E!3udbOS;3N6>zSQql)$_N4 zKDYg~J^1*{(ffbrWUYF>X7&HIFC|}9o4JK?e|dRh-)8?QM=Mt_6nwgJGv|U_myv|d zmn9yC!nML8LI=B#sOTH7T=Pxt*qYh8oQ4q#&rJ*ze0WU!Ny@Sf-74l@cKP50)Y{@& zV!BVkT6^uqKRa|8o~7!~vCZ5Qai)Lu4#SF&qWK(-+ZbfxqV{}YP5)lz8)fgjGGx($ z1q}D@-P6#~Y4KXxw0*ld!-Del^L`!e7LRv4{7L(U^wb$&HyZxhsn^)ZTReM<99y}~ z@BdHo-@K1(I`(aT!(H)3ELIE!1!W}@ez&* z+eAg5&M^Nz^URYgZ+HqOZ`EeF!S_!1q3!RZsgo=A?mzOwdxdp+_j%_H&%1bEC+E$R zIG^~fM$z8<8-sf85NjT`SbeP<|seYWlE_Fvz6etqNqHt(Xy zZ`S*r@z*Oh&Y#M=ZF%EgnVRRm$pPWN*RHIpP411YUtav`{T~0VDl`6cg~!h^I(O_? z(e3MtC;h(iZLj*~1iPriY+E<2nLBrGa)8Qy<9Sn=Gv3O01u@(@sJ~;nr{LKmM_Rl$ z7%bVbQ?xs(F6R8U#>Bn8M)u|JY_oD?w{J^2=xNs9^G^8cB=h=+n)Om`OLBj&3|`KY z@v3@7h?d&&MLTv#96fsU!}ss)E=rC;NluzOxKBqor{?cV*?6-_E}fI%w)wO(+;7BX zuioBV8(nXm>l;0D@0F|fE=Foi-0l6P%63(DiBd<7L+6nNTdp>2<0|V5@>+lWQDLFy zP7jt`U)Rb?-=~kGT~FP9ZhY?P^7@aL|E=Cyn;5Q|etC0b(TNSe&)XdCI=Xo8?{8c$ zue)75*DqwbrMR%HptPW1Lf28VZ&AJTn%3=#Ss!}0He!uWed<;DXe0eQN?VHc^v}<= zaC-J8>*KRlQ3e-<=??{`_3o zw;*$A>*$qp*Sajb9DL#BS0(F=g&S74HHYv-TSt4vFLw1U4P|u=l$zM0wZ0;zZ26Wa z4|g8vDVCJ~SN%HGq;7wLcHURbEdN=?QvzqtdH%QV>y-s@4;7td=iJ%tDH~(e;ZhdV zc_mU!>~=@#tyf%L@xd#vhTEO6D%bvgGpJkxV zBOQHreuZD{&vTm__g1-on`X7^x3_G}Eh`JlolIsy(VcUTh$(d}37Q!8gh5udkvD6> z@*@{sYkIBLYu>eJk<5imO|SU4g;h1L6AK^yT(hO+OaJxvd2cMQh9n>RH+{GNS;?1{ z>91xK=H=Qp%glK?_o#q(?wb@NuBx?u!LduVwKdl-Ji;$`XJ3_`>G!Ndue0kmmdww} zoM3xYtU<+QO}f8b@6*&H)0_F~ld82(+&o?JKK<+*tDG}CJ}%m^!=n40bD+q!_jWg4 z>=HQp;hhBknU00EPF58^XGC1s{?6uzowu}Vx5@ORgD0=mSN?l)@tC+s-2OHG=Pdk< z&P96*n)$_4es5S&W^+4R#7j81b^?Gx2GdpC> zX1AEGQzCf%M&XA8^O$B_Uve`{V3Xr*#tG{pwq+EQ%%35?>+1`_OJ{HI@9kb)Jz37? zGQ*lbZ~ER%{Iuv(;Kiel^J{;64tIZC?D>Lc_R#N^I%jNbh z%(ZIOcq3~orFFy4L+bChSD!t9Z%Wszcz*Y^`4qm3wZC{CeO|Lu^5oT{{Gt2_e}9SI zu~GgX$F+}l-~LBi5B<-%BgTCz*ikEc`Zc@xm(At({i?a2C~Wm<=keA%TVDNEUCN(u z;<^yyhWO9FO!RyECWVAuyYa##%8+$$1i!Vzl6IFh&3joEe5uMXwem<6@>1EhH0OxY zsjwy2!&f-Y^*N>McTW4t8M*7L@4nhDw(jE#LE8g2jc*7pQuh~?Pl%d-^1$i*x^>kx z>hGWRu73W%W8RJ$<{cqBp7G^vOE_}odZzN?Tl+uIO$$>H3w)<1WSg+~YsT|M>jSRaRDGU*yZeA@Wde6aPU<1PhQDt-nQwiUv#DG; zfBpXed;9(8;$nAs9I<(|Z^OqcHV@YJUw`GD7rU$cyW78$@9Tbjo*(^ft}fGe0rTzg z1ydUOr`cckja|GwI6ON?V{cqcWTfi4Rjb-ObliH~n4>pxSgqv~=nPoQsJc}=@LQ1d zDMzhqr)5=tUGB6zdUEFVY^yEBg*QH2mG<8K+tv5go7uAk;-$6i@%0}* zeD+^GCH&H7p-F!Ae;%E>ACxt}`OVp5U5c0ge_g$-ygDQ(b2($qmRVATuC0DK?-Q6O zda&%3+ptx%`BJdJ&07vR$?lyl3sk=GRk6Ff&-Hn?z`jPsbLabrtkh_8_1mJwZPl5% zE|0Q$&$%&2OWP_m-4GMF%`}DYLS{f<6yL;Ni88*j4I3vf*tABx1v}l<3I>qIg z!^_pHzUr+zXO%uPWcJMBf8Vw-FF$?Y>#JF|%m4lO_4MFhHl7N{cNdk9Ts*wHcW?4+ zHQVKC_SBw}S9+BhRnUkX-Ep3>ZoxFPc#*ItA&G*pk^FM$6%)ATh z@4hOJk9>U5G^e3B+TPvd!0k88KCi7sBffk~w+g*@b+-As_&>^3N4R-!E?>jim%h0= zA%)$p_vzCm_ZfUw`moe(dvo~8idiPB-Zw0tf3xN5>+8uE7rFNCJO6dHc*)Gl>G=)W zHd~Harz#1x@ye!65}!4gkQ2He0ccQUOd3fVncE=XG1sx5Ay@w z1FT=enRD|x9JqttGPsdeSZ`m>)WLRv*&&_5?%=*yH@h9xv8TV=+1GtP$;;5~@Lsc#VUJx+>9c}; zZ`VcHWIo(@|60ykJ^hQHbGsL5tXlIT>F7oKYkSys32oZ*t#Evk~gi($d{#n~VGe{3n%Pxh8+Fk7&6F{^}k5AUAKzc|L))O z|I**4AJVh3Ot)rUR?|{eUhFwIpA7!F^MN4(Rt~c4QCudi> zCx6-h*Wq@TAN;%CdVhayvQ@*o>V1`8d)4Hps2$qAI$k<#x1C2W-#I(^N4Jlf|GaQM zx;y{rs_0$$p`xk3?)<1-ezwlKpeExoIV&bF5`P;6o2=(3UFB-qv zqUgi@uWy5|wfMfZC}+IDejtZob=LWrcNzQ`ESMkU$j-maz{h-p>47xEdL{{G1&I@~&Dsp{49fb?kAA+@Q2ysbn}l>K-xkNw#1>-w+v>9FW_ z^RVf5TP%K>DkyxT$Vutg4hWgBIBsXf zr^^dO71U>h>vc37`||(GG}HT2r^e(@Iy|p;Yy6)2ean{33YRuk@4LbNAQCi1%%B^w z?aM5IW;>R>3}5d5{~i9aX5P!~^Y_*BJg{fD$85m-Me)MoZ$Ec2ba+_(dcJg-MDt7k z{u}HGdJT*WO$? z3YYdu_B&_nW~^KLaOvh*N9*@hm5Sdl`@X)uR`j)G#{oYU8*zrW`>V>Y-C$=;e;+W# z@t$SD1BR~;4mPXRFWVIm6B4oa$I|EN&0#aV-=Xd;35vr$JXWae2hWXF4nxn}}*}m+& zqh9--|K!<^GBqC^Di=#_sc}3OeCpnF{`{Zcjvqg|-SpbK=ZAMszcPQ{_8WIBk4kR7 z{JZYCX<91()LTm)N6)I8e<^cC&y)RU-UeT5^L_jK4TplvmOGz>8m2PrW7@!Xp#N*l zHRd1U4gC(%JC-+?Rg|)>b@5E#Sp1bi;MU2_XN^s-{`q$LdVJkCo`%Y;&lA)m+}}-Y zF!N(!l!#xlXYuaJ&uYu(Z(i1K&y(Qy*7{|K+bN~93mXeIePutwQudXv!{DL!-F?3c zxYo#f=iSLyTX)A?!D7Wy>w>Shd_@`Bk9Nn+DR_NNS1n|vWk5hc!=Xb?M~)p^v|)pQ zr>EyJ9tIw3QHJI71QYN2&9#{F;^o!HM-RLA-KwgrbX1${sJ3~>DqH<6ujO8Sc-7^< ztzTN?CiAnk6I>2VWGaxdHrexf?&;%?+0NGd4^{uZ&i7Ekkz;2nyO~sMG8#ksy;jU+ z_fI|aD=}bB=>=tlOV=;8@x8ef_Vv%{^^;cJGC!cZjg^7#|DWTBH21cj-||C_Whq2U zO4Gdkw{E2uWWIlTd%pi}C28xAJ0iPh)#wY{_7E_9wY1W@KFXAx?Vv}{?R-s!>FdL6 zZomI=(OEJsF?msr${r5?Gf98eTvz{)xqX+D>)Gg!!CWtx@A1VP^sFot=5+ zjE{!MnheK{E;bc!v?reZC?jY4t6JvI=lJ~xt^}R`a(`i=2v@ZE=bpgWzlcJ3MdEuWY3A>+-`L?KdcHi09<*z#nK7T2V_;btp zwtA0bPK{sTvzXasb1Qpi%9%Zy@z8j7-F%_jN{g;vskHw8r|C`b+N0Ty9DJ)Bj4kgn z&)r=v=%Cl&!yxJZBZb+5{Q*~ol3m)ce&C}pFTCYElzxqxprv; zL&KuY`|m!N-~U7L+4ufGvHOSXw&$1E?RNj2X6@jb6wM=L{Mq(G znD@4ZC!e0)-pr<7_xtnPb8l;AZ@Xj3&2@g=o^SuNpHDh1w@Pb?!Pjjk7KbHTvN5gOn_m>uFvz0v#+mP`#JyM-{oIkO251<+V(+8h*^*M!Ly5|P1onx%T6y5 zZE%0im%F?CLwC`WzmH}!78Y_=E)b1!TUn9z>&S!ue|}ZZDK98d&;H)eyR&`z-C3dk z4eXX%oLUgxuMn5~?9s9H3DLCzow)*HhF@$iyl#7|y4kE`LGOa63#Kv!#s1@JsJYXH+&<~A&&rTT z&*#@4+q=km>eZ{JE@B&3@VFFL>dg2hdhp;wwP~~8d|4ti`#}cBi?!KI?zwh4bTY47+8IJWzr(gYdt@X>3CD9w|e8v3&Pj8=oMk-rBcTdd3 z>9g0)x2U{zkZaefZ@dy2sh*<2oD9=#qyPOa-L1#?XSF?(hqtFr%fcud)&qGT|8O=x z$+d|-%ow45tAwW@#wxwU{z9VjIff^f-M)Q`{qpR%wCtTV`GsrwBcB&>Cq@*jyb0iP zklX+NcE1ywt+`){+QHa`0W(6i7_R*My{y4U&AG6!@OWMA@3un^QWHP#wBBcseoMf0 z_pj$Y%a^M=*98Uy9C*{|+xbg`+j?eq#?9`_&zoMq+{FA~$D^m3&N8vLBW<2*diDSR z{d7GyLyY*jxn_sLE+wVTk>crH#`e1I)(ozwg;SXdc)omp`{k+l|2x+YuCCs!`KacB z_%-tj=a)GA8+V*G`L`39LCp$}wlT>f}=Y4Go+-Fa(XZcPZE9^PyhE!UvN zx|265vf|Qnv4-7S?`yBkZGY?fV8YLmuY4aLU4D3G%Mzt6ea7=TJvjJyzhBKTIdSHU zOJbrTgMy{zOFkdZnlr8;_gZ7xcVX=!RtiY%{WnNIOqdR3IWnmt{ow(gTffqBj`p)b$t_x)eo zo4!GK=e^69g%>Vd81{CvrHoCPlI$JR#Ipt()(o3g#MMg0CVu(0R{BZ{r*OZ$M&hch z`%JmKTC96LI~gtN{=92?`0%gV=S3VTj}JV2e5CaB21j0LqY2@nU#2G(S4$TjkvPOtu4J@wPywZEd!FZO=+NdXNr5iZue`}=wm z54ZWU>MGnk?BJTkf1vQd0msF!f7uy+5)l(q(%0uVn#mIv7w03pVA+wYtHWRa-JO11 z&&5(nPFa)TxT5pxclFKhX3t-~Hzpv0`GDar|NCK*Y^8SkyMH}fYaMFPvg=g+kNx@e zudi%%U;SkrL&MyVw(0ZdyPnh3%#yssV8JJMq5t}fts=j^y|!Pq?f+WE^GyMK*^cwI zMHfu%c3-eMUA#F=;?*ya>v7*X4kQ;iAGmpCuMoqfjtTE%txEVGFHM!VFVtecBjtT9 zsb&hpgj=_7Tk^{p1%Y;Lb_%N-#XY&a{QQ$cA$Iv8_Oov(9ozVaU;2XeisJD4Xa)~I zzhf5`Ix{jnFWRj8?0Bx)hOHJe%N;D%pX!?SVBV*`x@%W9HpbRAMduu>s;+*#`MllX z>GSI<#M?TTxV~-M`{n3Qhduzgv(CQ0KOC=gU z@6x|N=b5&0ob;0$S&1VkY`+IYz{`zOa>rc5o{K`~Y{zkHFoEySu^)lqwW&7#=AGoBBbeC;cEr^fwcxzYkO^D}RjbK)< z;O6K1ek@%(cjd#1tE)mI_Ev4Z`b%f}X~oGW0|Emtin2Mku&^zjq@!SP!+&j9@}(u7 z5nD0@_w3!f@M4C5q^I>gV`F2+22OU>{rP-3cXkMVescqe z36<5Q|DxXno0$n6ayxd;e^c5L&fUvAgPV0vTkY9YaLd9@ad&^$`@rb$a_1TP_q3|j zsl6;NUe3e(Vy}^Kb02Q!U7B`&-dxssn>>nl+?x4gZQa1ODngEnFD6`C z;yK}DidbdDwYAahjLd8f3j-3qzq{*u@Bf-B6{0-r+_RsC7kG%Xedm08Yh(1`!&9`h zP8sH(GoIvz4JA1-?Wr4~X_CIL$x5{?5_;A2;64+A5W`b=GVRZUsxr#y$3G zJ?BH;sk|4INDZv>@Lue+m_6&Wj+?FRXV&cR%M~r=PyQs)X1UsNtzpvT|9d~z{FbZr zc{KCW=g*Q$l~hz(I2D!donLn9s#Vz=2_s|Uhc91p`uqD=R971>oNY9dhn1Ce!`6+8 z)AF_@DNfyOv75Ek&FXZDkxu+R8FqfTBOQXu6Xwt7XXxndO`UY^c%SU;H}`IReSQ7< z%7_&q{iX}PTU%ez5|ewUmp8Xox#H~4V0HgE_65CMpTEDja`pVJu*}UCb&sxCUJ#2H zWVrd|X0ceOR6y{tTPxPANt+*>#Bj+huW0+b#y`i_Ed8)yhYP>+i`duo5C0s{6q1&@ z*B#HeZ_SjV3tXz4*Hf?m&D1P7w4mx+k0eLKX8UE!RYMkVrc7KGrgI|U24ew7cgF*d z1s5+~yz$|${rkq(d|A4Q0c8v__v%XR)}N{OUbx)lk)yNw_6nb`f2+M--8i}VrU3_s z5(A&Ujd59l`Tc~SJBy#sxMAJEr|RYD=~z-y(!GE2u7cO^_6BX}Qe>R4cWcG93FmB; zV!64w4XeN99E)0cF+)mM;LH2_@+$ux;03RY z{{H?ye*bn}7~rt@qCw|1p-z_X@9*n3E9OjU@$-6qcBbK_i=Fd~RrYjlcrLhJSNg1P zOkliHb>hRhLK4@sSsivIz1*z)R#s>J=g_HHIk!tcC^7uqQmCvv>+3@um&}*SS=Z{=uuGfjV%`K5y&^EW=3So`pqvxLz0wP(4m z-bv`mVUXF&{M%#|!~J=-)eqjkKmW#G-S7C_mape4`fB8ar0($=RKznXn5yoaaMizi zb(8tlYbWJ+B0XH*n;jEBa{TD#o9$}?&)t!bIjW?kwdrEvQ{P6%!)`aaa-;4!OqnDR z&Ue^FDKVfg`FKy&wZn&-H~wmEX)#D-Ttf&H`}dd0dbK%vY)+F9 ziDcij;6mH+iap=YNw@C*_fdTJs&BCpD}H-q%;IUd-L*ZuMt7>E`HO%g?yxs|dmA-nCz3cgG=9|G>TwE4jM;{&SHmv>L%h<;Lz#zq=KJDC^*xh2A)6RnCbk+Rk+{jUp z`nqtR%Qs`rO!0)0vaj#%c3+=kKYemoY}mSW3=3YHCpb(OtAD_zV6E)C_F{&X!~2Po zZeE^0PbbSEH8b0J{q^M6({i65OOl@oO@o%5Jr+?Dk5+%EIxyy?uH~qF%yj-p4c<|sJ|Ca3O=d#y}-wR!MEvWZa z*PML^C;A*;ym;}(s;^mXyRP5(6d^xpve1{?+jBLwHFhjprom+zb>RH@^O+YHx%#aR zUoTc!UHy3V`hA-$8b2rHwSD{a_4f9}+E=OPtUhqQdU|n!e(lej?)?9Lp8f8g_#tFM zlxXUL>*ktv&o({2FTd~Y_3RJAnR7Z7PJ}5qIXMXk2{Ab-IqVUAn!5DXq1)x}4^5C) zVM~ygkUH9Zu=znu9N*T;%k!W96xR>S*c!#9BxqIkLZQ0yV$$>t9UA{WfB$58_v~#i zUWVffKD`IR|@YZcBTWbmaK)#XEM)_$ZNOBBe3aE5k%;&#zaj=VV`B8_m9T7gK%i zuf5Nnth}-5)2HLRTDiq<=|^t5@$|&R#Y#(qI^Xa6eeQ|ey?gh1!i5Y}qMkp0?yNTX z;QjmZ7cXA4D1RsO_1WzFXNMoCrk~(yYC5!wVawLS6B86aeEYvR0?!YBD!^SGcIWw_IHHqv6&*`)@&SjVCOrj12$p5%*c$ z*7PG|7H{3cy}x#Uc$;3VV5<63EJAU&qhRf9m0~+3T0N zZPJTze!XDk(%0cW^HV-KZ0B14a`NR(pJp$b@4Gf)f^U>nfkXY|g7zyv9#5Sb%45II zbmy;|wPr`Ay0e#kd?R*8<;(PX@i+D-M6^^ARlY53wB1w1;`XVJ{r8{Crm64u{&&=K z4NQHYrMF2pdi!?E@_#WE?RCmzH{FA=Bze|^X^8W5YeT_Na|NQ;5+4QOQzmJZ5u7O7` z9XWH~w?4PnzW!ZIMf!TZKd+`QSw4kn!^=xMn-{J27g)b{`JOdA=g-crO+WtbugaFb zz0YLo{-iEGJ#TKktM3e(X7SgDcD@M_dKAXVY`RrP<2PM#4{Oq@sD@}w z?M!^~>ZYcC-Yr~#BHf=)FkH}4~nV|k~etb>PzjM2_&z_rU zZ=PSezu;d@#qx7;yt9l;D?N*hg-(Lfr|0{E`+c&z*gnnr?9L~@mtldDn$m%%*S2zt znod98z1p;Dwp6d*lB>ZOHTy z``*NZveu>Fp56VQzb_*A-?QEFR}7zT+Zk_BueT>Tz3%swlQ(uG6%;f7i=N7@bli*4 z!v6c6;$XKPiHE0_AN+jtWd8-LA`QuBmrty?SKCv3J81Ic8$0Lic~LOidE*9lh3*cM z)D%yDPn9>$VxJ$IG0#YPy$H zsQ50w`dpKki6@i3=f6qzTDqaK_GL%X@BI<42xK{S{OI$;6SioxCG0Oaw}rFx>;8pa zNBLjx)BgYDa{V#suk#l^to`ty@zsgOz4t!HRdj|gD2<7^;~Fu)YG!bC+LaRz7tj0B z>damiezx|XYFTJ*5JP`#N(blqs4Y*nZtcsoLtFVp8mbN%eTxosB{ar``+2#uUzu* zY67QWYz=Sg&3(V$S+9xQ+_pGCqFTM@qX&Ih$Qm>AS{&N?H!G^jIjbK1Mn>rFTIa!LNAQTO{P``6pr_tux6ld-Qm@_py?_?!!KR(fwd;o-fL^RSdKtC5j@@E= zc+4T?S$v@F^&5+}9Z1i}==i^Ub@;wB+nG5F)AgIbJ=pwNEb7>i0G)%YGhSFe#F$`EYdVp{Qa-ZQXq$ zF|#5K88TfeMD*EO7VR!yVSc~rxk&?)1lNTrjdI!U7urLoZd2|x%`-Hv?D$w3OIjMD9wAuf!wlYH#({ zu*Ykz2lH9Y?Yki6gS7aM*MW&r!ZRY6fEBf#A^SDXz zfx*ACPu|gVJ}fftuI2Mix5WoL1eK*^{C>XOeqUp~NX%*Gz0clVy?2;xOG0#DT->^_ z)mQaY%9B1nJL|(SC2DP(*HWj%#KgTRT);|L!bawrtg+gT>4AmZlxwcUW`5cbi2KH`v=hKi+%xtWVN)Mve8g`u*AU z?pbvvS6-bB)0*?f4e`6YM1BjF|qgcH8p!{ z;qc8ndun)s`?DMDKdQ@lID1pFiY93E)&Ax;kDTQctSKgQ?tbg$d1lcGdH*+Vwp?Id zs^k)Rd+xE5f8Ia4zj>|b?@Nz7JpFbt1)pB*yuE=V?xSt=_CNm?gnZq>uqC06`%7Cm zU)4N|#orP#uJ5y5?>c+>+_1k3o&*~1=xS~DS2+Lg|Igpe$5WqPkNB(J#k&0eyth9> zz0dmit_hkNDsWoowouB}U!u7&b7QMnT(3&T*M6*7SNCbkN_K6nE8&Sz4E-EARR!j` zf7kE-TPEb-&LHa`U!k|)`dr>K(G!lW2rXf-sQ>?WfAznAzu)&95SNtfyz*qps!gA| z+6`KsbTE1}AFlo=_5W=BpJVg(Z%?$?;JTo74Hv_U8;$Xy?>}3vH0}2~eTpGqq2S)w z*SpQMw78^tmz}H9I?n%oFMHI=9dWnQonH3dvRln~<4YIMQ&H=BL+hoxo=jXN5tDkZ z?#>HAwa(|gDx zO>Ee?olFIy+?))N<^NB70}a%#4Dr$PNZwF-S)bo4H1$~VvOV9JUzcTXn|Id#RGYvB*E5|{S<6ne8Z&%%-feCx zYn-s+=%!OXUu(W@S!!s$cG-(MPfnia zI<{$bj(d*f{C*ZMXQQQC{mAa>%EeEo-Y}Kooj2Qj`LFBo^{QQVff>==#}7qJOfcSi zlWD_To3aJZCpg+xm%V%Q^0i8F*6P4;>r*Lx=O)}*ylahH%IgH~i5@J1uANi*zZms@ zo4fb!ojW3T|NOZ8YW{h@m0|a^72ltmbu?e{XU(-UoXI!qKYaOeuaX3lzTeSE)b zx0s=Q_ExE!dxZv!Zqtqz`hVqqcjIXL^*uj|FHcLkARVj7$Y}+LG7Oj3%1Gb`uOU<{A{zy|L(8)J7vb}{oC^c7FRGOCnp=GbT~fu z^Y_$gI_R49_J%hnL;KV2^!`a!GwRnwx0z)*LQzUNlCd9ZCLmJ zpz_THx_`H4{q_^lD}1}(j3K7_+q=sPmi*Z@Vcwhq{x5T$Y7{pvoak6{%eMO0lgFRB zx(?m?C*CwKJk+3qzP|p7tFP2287*0^Hs#O* z*%X@?(7A>$@6G+T?Z@xmi#KeTpvaz~@$b%_wd*XCgRAYM8S?5H5Ax14ekRi0bH(Ko zPmf{7u@=R~F21{!XMeuk&A+5U?3R4vJnO3lbNYFgN~Au|vSiFC&iLK0&ns(t_3EX% zqjPN+SC*aI6T9{OHjXcLN>Y|36Ux=~>z;pIb~akN#P4J5bIFyR-xIg^pPgf*wqosa z@%_cy-dP^Mx%>~4l-={5jb(46cH9iV&t|Ld!RM9D(W>;E?PHg)RQ&J!@clNc($~*B zzhmoHzRzDil@Ew~k>RgW1|2pO*oefB@X5eFV zywkzg>(;zw%98esLnf`u!gSs+p7_(G?3<*y*=SP!!7X*Js~66cwXeG2G4JixtTnN_ zr!9_{bN=L&JGxZ`@@%J-8E*8-8&48{`gE$dc*)Di%IA*qOy3hyQkiW1wf@%ZdAs}j zho@6rs*Jvs@bx@;t?nyxK3ise+_~$iDaL>Gn-t5oO0_jbO}!U4?^~T?V(+W}vrMxE z-oqUhKvut3oTy&D++0cjT5> zy7hhQp66Qn=grLSHQLHb6|LV@@al@>r*o32aY@;aZ=BsfU3z|*{~U`#&M$S2_bLrv z>|D(J;L)o`EBO06CLQ}?d}EE0vhv2t&uI+2izoQ`dMe6AZ3{}Vulk~KZk~HqqKQbj z-m{mNHl3S2+xU&``c>}R^)9`$W8}SOye@8U)~DT3`o`tw>`mWvS_Xc7_^tQ!t|MFa ztX{yn;J87HNzj9~30K&+1t~Hs+}iuGJKW8`cH_Mbrw$!*dUJF0@tl8Wm;UMgFve4_ipd!Utj#{%grA)61_L4 zEIWDFwPC9ZuLc(|xFlIUo3hnfu;WFomyVF_ zv>Uf

sBa(=P%pQ4=I?znNUa2dlA<73}HNA1eEx4dp4GkaypmuwTxW6$T;^Yywh z`}_NYjvDp7baK@xuA2Xs->WAW$VKh0Yqe#F^zcZjE_<{sM$bJch^ab1$Fz&pIr-`_ z-*-~CsyjN{YJS`}$ur~Fr0D342`sA)Y=~ z-F`EMC5eK8dvy9MEhYOMqJMZNY$)3Bo{?dZs<#;b)5!_Zzg{SAP5*zixp3UjBE!AZ@zwQikJsaju3JSH;tLHg3)RQE6PHQrmar*s-Lir>1ID7W7*c zyeTnTvtP|(wx2_aPxxc*E25$^jH}(!f>zyJbt|V$>hZqUi60_fIOa$6CvGs>=%^F0 zM6C05LtSl6c1l2xpiX4&xePHC%*m`+qw1q z-^91ZAy>Xd^D~@|uPNIQlJ?4TwrRH5;+QM!z0265x4rdinD|tp!MP%WCHy9~U!8gI&%$lnroFF}^5y+^W0y6f+pz@~JnGWJp=# zt7pyBynp+@tM||U8nxGL)ru7w9x6hcEuCFY?Y{El{6nv9 zi{x>RU1St-UE|ERpc{+@8TZ5V{%0RnzyDq8(;1JMn|HfbUwC$Q_QC)SskcjOg!Ws>b|jlU7{I*rGDgpZ$QF(#EN!-}#?k z{eR?$%Hw~Nd#7Cf|H7_T`fmNsm~%OCk|#etwVE5pnpfAlb<(ak3?9|(Kg(afk&aSGb%k6_Q)i#teC$rtvV;Jg8(eIHC1;<83e2)UwS0GY`~12;5C8Vo z=ZT$6F{-GnH2liJ#l;m+@wm#8$7{Y^L+{$&UY$MZChI@iSAWZi{XBif_bprZ*K;_} zxLA9EX{zii@k1IH9-rZ8-L}mvk5O@Nh3LkevxMuJ*;)_%NJ!A~cK_D(^6YcF=S4v$ zXDKuFNHpACkl4)jG1FXKd-JXxPZT+e6RSl!p5D;g<$vF5b3vm?oRHXX!==uN$|2B^NHs-8wF>-(|Rv{(8TxPqdK#t zNr~(S6fLeCNcEdAd*TO)I}t_M>i-M2?AR`5Z|w8z&9z^r%Re1xvn@eedeMf)r~%io+7c)j#Zi+?pk+5Y@L z=gor8UGEAguw!E?pTF@KVBYtMC<$=Av(cQ=QFIy&6 z{axNjuD&c*u^)OkJc{J;JW=?)}N_d zZ=!Rf$fHf{4=$K)@K^VK&&;r~Q1VSd*rDV4Zv{mTce|OGnm*;rSlSd3d$Y&)8-vWB zLyKO2c{Slt^;b>tn>TMBaX$UAz<0J;?gkg7hkNQ5tuSFRHNARc*Yb0ghi@7)IUlNg zTlwuo<$FWWsjx$#KU$!`@_`ZfPb1vMaS`{1RGyZ-)K5uix#WpWj-x*R}Jd)>N*I8#i)rayGgxPIS_|`S4NAhF{I~ zPhxl0?PmBA`BQ@JnQyk6iiL~IH^Y-2{{G&oUdfYN92tEVM-==hWIhwJ$Jf(uA7k*k zy6kpG!&3qO8<{I2@BHISQ0Glws=9LZs%)=B5jT^R9};ozA3i$TZR)jj6Gx0!Vv&bo z)aM%;lmFUSmpw84&L?Y=vPQy_jaT~M>i?C`KV`kUyW5}dz145~yfYd1%VhURiI!J? zc@cQ-JUgGf@?Z7to3|1J_!jP6WO;4p`u{(V{?*_2Yuc4h8jTCxSP$ngy<>CvlF~qKSS{R@(>F6@ei5>-CBtHM^==8jl|KPyE znmD((JioKekA#XJpSRmkYQVAY)-5}a1dBEEOA?sB>{Dh}ko|YXBQCDxb@->!o6kSx zH%Q01KGS(TRaQXu=H9*2&DS&4RDXZ#-RijED$|DVuirhrbya^xxbF1B?R?7*3;a8> zEO08r1im-om$w#|-?#d`ujr{4XbzAeW12?ssiQBA3o9SAb=+i_@a^^W{D8tj!^IvM zCQ>V|zGBlBd%kIN);oKRx<~U2t9}I3uU~g>&$m4{ZbVFu_{-?r_VLzdz320<-`Tl( z5C7>!oEAI*d#k^{`E>Dk{6EF%yJzxlo@rZc7NR98!sR;G)YtCEgXY`P=Kl(%wkS5s z7OiBQE0AYi@LDR3yusMUf*7B zzuwS#`sB#qlJ}0q?}LBcGBerwR=|Jt)^nOgb{6}$ro39P-R?)x+{xXkYkIoH_1l&& zS5MARWi{BlXOC3O^Hp|#e!tf5`uFv(zq_OM5toe#(wfn~?iwyU_m6R*norh8&dw#% z!X`^v{?rnaNmJdQH}^Jsi|g!=Nq07WFEHBiG5T7Vj>V~f?Q)8L(l6iVkks^C5};_! z7cC_sceUAncVuK_%4XwlK7}?e&h0#s*45u~a&B!ox#;(uy~XbHC(NnhyrUHOZJ(Xp zo@0i(mJ?;np4nudX*A9~w#9JT-Ns{In@<0Fa%Ru!2T`-vY)us2l{z!Nz#@6Bb={YO ztJC&xi+d@3`S#75H&?E0U!<#AUN~ju@w+n{uuG(_hYe|q-{Nja2f+S78b180` z8nCHs-jpi`V1Cqca(+BpEt8w z^v*BsZ;A^O_Z+j=R^GesBRdbfUgbO~6Puk=53rfso@&dWrC_i@dcNKBXHO^Ch;Ngg z{bizpw9J7UlIPR&zh+yPRdRV&%%lIRA^LGgqqnrwB4k z^k|v%h<%r{d%v)ol3A?b=J+%9i3eNMzs|j~al+}RYG36~g=ppc%4QFA+4)oS;X~UK z<*7!JQ@m8Wy1S+4q)(hWG3NT5hi@u{)opCIIr3g>JiaO@=k8X0-k9VGwcq_@E6)DB zv!-O5`f|f-Uf(`jo?7y)>+Edv_usyJF`0d2bHPI=4;3K~6`>3hsbylk(y#x&|Ls1% z?$^si35|Bo9Q&2&LD9u34cCp+)6xXGijwn9Hg;Gu70k0JJY-?_eP{iDyHcHRZ!8PW zYwniYSNG@F{CU@eev2d+aJ)>+QpnQWaJW?Vw$`27dbN)a&({srx>xhr_gKWz01XKz zflimE%*)F@zS3|FjQD+aI)7Ys@lm}CJhlEx=9wqU)#qB3dM#PLT+{W}J6rY}U$tkc zsO;9X5$ic%n&0-)X-}P{|Mc>YQnTf^hhAO(;@ZyUMcw`xbH&VqY@Y1rboZNcszGqG zcl)=ucXt2$VcunTRbs1{Y4JSGZPk(2mgnD}u$q;%;`3Q^#fcsd-oKC6|G&rZ(xuBc zI9F9Mn91JSUjF&p)9e2?7jizIccH$TVbg&F33076H(k2yv1zVl;)bOM47twCG+Vgb z{dZr_(vK@AE?(;2D|7e!qic*YyGkb zn*vWBPWPXCs=dLI2}wzlMSqEim}(;oTXTDQapeRW`?%!Q zHWn&P-Tk!46141@i_1c8(=UPQUpdX+_FU-Th+FdGrsPXesou7^!D`=f?w`AAKI8rz zd(rByz0XarM4b%OV%V{Kj_s%E+qe7A4T(~@ud;*E8am@SLzSwB<`wa)4S*726u-kv*?Tu(@B9DDdi^^`F~b1RRVZ#x6S<&8p|HT&GV;Xe@^4j-m9)Hr`pWnr5Ti@G#Eb8!#b9&4V4XUna2;03o($cbO z(Md-3AFVsfBgC8N#9fbw^<&j%+{~X{ASTPw|1_$yiLUhzwK}D z3x0opZ&}~5W0Q~Ms`aEC{WSf!hsrc}FBLVlgv-l(-+YkURy{LW^8LNFvzsE;d*qlL zJlM=W^HDg1LGCRRVXc!#e*9pPIJ)-SZ1eIdbLT$&TfZhK@%Xt||5x_0GjHwAKD<-o ztb(rXUWRMSs+9pw5~G*S z!l$pVf8_Xa^A~e%!lowue#iXm8BgW^GxMIyOI&I@|J&c&b06>GKV9MCx-y~nZ+=w? znPPuz+5WPPYp3#_TyOBrXqW1dchS;!vJ2)uz54w8{PR7Xma7Yj{z$%EWBK{}p$98> zFjvV5x^|sOefhduyyxlW^UMc6pSPFaS8{R@!^$g;+EXoGt1zz=%cy2UBeyD z-ThyG8ZS` zyURDWrJbL5c8BoqBS%(jjnZ8hYOJ^DFh{Vkx}U^{m+A96O{92}j|ORofEHs1tpvq} z2zRH;p#V=lNh6lHxVQ_izuwrE8?D6CCFpzq`Sa`PA0HhJ(3<+;`}gBbtlUyhGrjzM zgRWuB7XE%0CnH^QT z|A!){s9{;MvEB#Q^L?*g-a7W_)$S>A{khR~{w(G4>StW|v*)jt+0vxYdhl2FAI0|$ z;kVr^Gai0ajJS9F)_ZHFg1Xd)Z~o=wTa553pt<^9xm za&N_DmE}o4KRxB$6<$`AU-JV@e(gy9qX4#`G1gEg=f{WZ?d;s+kPGW zkonmuttl!tGPJ8LTKlFK=z@^L^?zTVwQD}cyZXHycwMTLR4-fd@gn6z>z>TN>_6A= z@r0G-#|nh)LuPwMChh)bR} zcUHi{izdJAu0|dBn6ZCr$-UWq=RUcuS3ab{ap9+k%5tZrL5_H0yt z%l<6=m3X*bFJ^z?Z>twE3PB6L=#@jO0zdnTjGBF-9a_Zwe@f9oIYvK(y8lKx48CPu5O|1>s=cZD;a+N6p!}VxTEf^ zR8GZ*1i3m?$Rn z*h7SeDe38@43issDvd+5M3?!_T(dW@;gJF^p|4?ZSZYuj(7E4%(Y z(Jp)6H;Zl3l7OI&UJc=ITmP4{E|4%vDOlXKKhs32@AzlGhoygKs+p zpI7eS>DE-6EG+!`w($(x_4)T-EUdZr|L*PWU($twK4rgmjyU>;*=e!W=S*{B-H&`y z;=Ttsy>I?_|2>U&{+CNlyFSG)TC_-_G4J9c*BPeSV$a`yf3LYx^78U|`-;EE+41lM zd`~#B{bGZ(sN!e-z9(DLqPW7>$6R{)WbSUhcb2NWeBDn>(=s)6H~DWB6L>tGr@=;R z*?d_`6c7eT#nj& zssDEtDK6T+#(kF zwYBSU+n4X=?*rpEr}2hpi3&}gB;Oz{q`=9=^+rg<=llL0J0zrf+X4elEDMT=h*;15 z_{PV_FAe++4tzZIv+diu?UQn1CCu|=_+%^^mON3pRA2U&EBi^fgw87N<^2T(C7D9I zQo9yy$a=bJvB3qIO_TpIEKYfQcXs{HMejQ_c`_Mp{^%4sk@i~BD23yZzr6bUevM<3 z?mhe$yX$wG(dX$JD_Xn+DvCNT{&RMJCG~$<&GQ~3^Cj^q+rQ1Ntz5e^*}ebyff^6l z^mD&hzCL-{d+Mx56@#9sdf`mrqfHuIS66J+t1kUgQd#-$%!~sUCU}TnH=COhG;{Ud zy&-Ao`RUoo+8eiS-P(LaOu##5<*Y8R8`c&97p^x5c{{$`dg0ZUM_FH!3vc_`N`*d7 z{`%@_#pJE~QDS?%9hJ&Qqu5 z9`8&~Pf2+idx|Z5WrF(dSB~q&ITe1X z`Q!fDmwZVnejmJ+HRoW2nTFMs{oVEc-9_3@iY!%xIIm=x+SuA&+#Rl;b^P4i(E8k) zLB4@iwMln0yS7!lSQ!*L(@lj<&R*}bh`q*2y*9;!5&WH2+lMV_>G#^qv)T4jmv{znH z-5oWC&zsWE&IwWv=GwUAdb{`ZPl{sQ(J7Z!T+O<(v$$O)HL9g)b$F?zrKNd7$q762 z;wupoPZZr<@#0}sr_Wk{>ux+{L7upnX=T1C3Rd>#b>;FGDKR@O_`*3G3 z2PdavO^uC>t?k3NZ_jFoweT4z+V%AaC)duiDtseRcBs6j#%9st#WR1g9l07C6VvnO zPtCC+*Jp?4Mz{XD@ncJOMjbQ9p6s%cSobK~rYg&|$rsm4o-X}`7@CT)EBH~ikdmG)CFDE$t}W}I2vcUi4x zR>sR4r&Em7RJQ#%*u1LYz=1udPI(Ds9j|MD(^4K(-5Gm+vCx;@`pj=9R`57aJaqiQ zGcAG0>$BWS)UH@6s2pnfXl$I?n+sU0SH&&kxKG+r&+j#dk-{c=vZTr@zufHeApc}B_ zYL={`S6=^svt$+Tl{r9D* z`8RJAtvzZqlZRVOCt=d-8ymI?CV&5@{ANe0AVc+It#?H`Wi&N4dy14MpWIOQx9V8) z#F;ZYCrl7Xvr|z$CfQ$K-0Em3w&TD9gSc!xedCQz-r;%X%Oeb$-gYfDZugee)jt** zy7Jii`gcl}j&C-meEX+7dw-?krvEFh+gSbF-N?Q)H`sA$&_mG9*9DEtAFr?bt76`= zQHFT}8_UJ_`xSqhKbtU5DE|JO#81)psz3j{_$}!4>6#a%R)2P8W((~ozNe>QF-83J z^_^>u{Q8z-X0cUkS83k+on>#!Z$IhM6U*+MzozQ*IsMsX^O_u2D!7`TKG6I5*_xRX zHWb8VFI&3cYSzZu<9d?~xp}yrnWnw;{HVLpf2-Jr^BTtwT;S+FK2L&AX33>f&*#k`NLk_=tJ3sMFH1`wT>Gf-aQ@T<$G0-IEoywz^);$MR5ZI$v+vatmC5cdyk>@Z zG8QFD+-F1L&jlTAdVFoZZDBx$^!YqB*Fv*A+c`|1TW7Cf&5Q6ZSQ5Ey;#BSMq^qk! z1GJ`oH4~Gr_WJwHT6>l)ClAB5wekOd{OA6F)@7f0Cx6NjX83U0-`-}&g!-RMFD9^+B`T!&$#p- zY+xyUD|jgTZ0b_uskb{XwuRh#x@PALyV}ai#d=ScgxKn>u3%|a?OT<5JMZTq&Bpb6 zcI5<5f57->htzC|+uL#v|M~g3&`>|Pc+*F@DapJt7>vJCN z`M+YG?e9;O)BY6CoYgdY`?~`g%TK5qOnN?VZpig{XWKmOu6&fWf0K3lXc7Mz{nz`n z{yy0Jp6_q~L;sak3EHB^mPnddM+AthPtVhgv6#MkXYF%8!5ztJyxkA3|KD=u$+R2G zqquJ*zn2gZygbc6Sy;_y0TVN`KchnDwUl!cH@CztZm!U|af&t2pkq?t(O>)7*19ib z*pU;(cY2yl@}%VOPY?LE{;x37-0@STKXq~9O4d1#7s=Sxba*z!mYrI;>e6x17WwJ9 zf*Y4*cWhKSJJ)b!xitUhrw^Q+oHkT{&+9A5;+gB${#f15_RWQj$(v`tcyxZ=HEXL= zTh^_c_F7b`mu2TuD*g@uhZ~@bSKm7dLix^UmIOZHASf+GIr|BO#&ABP!S8)?ZJ4f3LPwwBSkA z)0$=-y|icV-}mp~S!S?stML07TYo>=JXu|$npfxG-bG5U7Mse;v#brVVaOF+)o}2T z@1)|p*K7BGThA9;BYk$~jCrS2W*c35zVdOK%eMC?=I%cd%qa1qJJkrZr*vV^$_*J8 zmE2Z>I>DRYGgSYXeR%V!z-MCT=H3auc<=NhQ+5XHZ!$)4#m^3%O}YD5sY3L@X&=uN zVcrQ{SN){z>T6HEs$XY+@75HqrbCCERMb_49yTUh&a=;U@-KI-e)iY=TJpl{uQ!$+ z-v^#QfALQE*3!UUX+?eYsV&0BDbnZ9ONl;wcd_&OyuG={5AOPw!}P6Ellj54!XL-) z@2U3RU{U$&!@adr_4j=`Cs&Y}>bYq3M%H4cZKP*Z+Cf zmG^$#8TWf9W7WKSOlQNj=dS>6vZust1pxT1h((Z#*hGbPN=rK(So(mp%s^~vMO zi3?`(_L^v_OrAUQ(6i%P!zQiTX?OXk)3Kg9rC_hxuiBe78+}cEnwrJWAJx$|sS{@-`k zdi&>3-?nO0_B?oUa`Md$`;K;QE<3EWXwj@i7whZ4pWQmCy+5xZ?Pvu@GwURkgi{PV zWbHTnoql3pv+g5ryCNGiX}2%Ei|0uNse6YP78)ukD=SVux!_{Pf&dL4t$%U5CM@1t z^;Qj(G#C!utZw`I@@V$iyE`jg>(w;dL-N*de&*FtFMhu7u5-oNn~#_Kr61n#%!MK4 z{=VG>KQ?=Z)#{gSvN^J9Cul>|pAUbxKTnLv?|J%TSe0)F8a;?d&h2XoIlrtjhU%u1B;4go^^|i$T+~&(QSSD95XY+ z$r%@wD|>HF<=%PAJ3QayJ7@&K(?-s=#y~%8x1w`f!pBEP)g84tTo&pwPT$IDu*ZAb z^Fup6S=`=yQEHFyvjc{CKYq?`vr2!Oa?izhnP$YQh=NSv=Bn8r9?!EXZHtw?6vgUv zM z+F};Ad{<4LLvwhuS|{_~umAdOgW=@r$fEw=uH`Eit3Te9I3-?CBI^4e)9L=nJ#W6K z1RYti^L4mHQ54hR%C$T9taTOP#2Y)mD{vl7<;r9#`0$mVm*K#No90s-niRCx-m^UXBtC!*mycBl1n9LW+zH)E!^#gW$UWp$$dUUg7@|nVyx0xq= z?RjTts}6 z9&TfQu<6g#>GS59{$Kj@*cmxq-#h;Pz54Be9vyr4&egGKy8p-5E9sej=i&6@73QKd zKB%nRJ9l%w3(tDHC;^v<3aVfE9#}BLLJnj;FT-^_!^6r^2 zHzG1F@F#~(e|K~9-Zi`H_2WLPE53W9D$%uMRFJe`x7?fqLPI-CU)S&X_GO0PyRx!r)mP+Kdu^;d%@v4k1JNJ_;y}G)I({8eZ8HSZd8iUGA0S98A8HB zc}>~1TdIGyMmo=psW8}Z&iyX~L--|67srr$A)$%e7p`Ofs5D^?L!b4==>7+N)9$vq zxkY{Qogw$^n$E1p28nk%F4jofls?M1`fRQB`35nu8y_#JoV;H7;{oHs)AuXi7tdU* zdA@P~e*2)HpamB*X4ps+d!=O+J>o48P2Me@<}dY1XM4@Ru<+1F{rkVEAN=#f{J8b> zegE!UdDwSu+WE-2Va@UX@5F{bEjz>#G+ROLjP`#;UDcOrJWgv`;FGx}@!vA>pA(m%mv(=Se^R`j+jPMHB3s z*1QP;EoFXj_o;Eax04vpR;{jt6Z==4&ORM!oUc32Hs)E%Pvc;bR?o@m@p@WXN?uXHn?GJ{ zxOcnTvHhk^gW~=(bw4LPZ?m+D)XNVE4^6zhZSUE={#(Tgj@5nSzT9T9d)vksw~JRE z9B5?jT<|teQ{maL4{kJ{qrAlpPPSL!_~NYzfPzQ&(V6PMLu2sQGNA`cbA3S4ZTyJKM?B4mh&-2imo5ocMg@uM!vP`?WyA`LOo;ZCv`vC{#$ne<=6Q<7& zj*SU&;%nUHB(+4j?aSA^`!{EYw|(9g%ibe=WbMO)kJsGIyUSG3dOg!rYR$h4(?G3v zhZPK7WW9g<;@z`b@4EH({W-jO@${2Fjvqg+Y-A)P)ysDA;>8IbDgjzk)10q;leL(` z)4Y|B;mxmaZx45W)G#+*y6a0}C1;eu{zdWk?e<)|GqwBXtl8V&&s=?nZv)>GMdqsC z)g^Bf85<@lyMtyT)RwUMA3C?U{Zc}J(9+ZKu^VoLDY<5U4`Vp+@UXklLEgVx7!`W^ z%=XkDVpE-bazo|kv^5bQQ(86EwYNs4)}3QmW1IZVc(K#1EpHF4W_WurdAV_7Nb!pL z|BZXjt@GZgdG&jjcXy&yy~UPIfeY*IPW$`#^!?-hGjk8C*+uNDsoYzw)#$hUu(Wsl zjxGOBWCpE%B=*8UWSjfub+!{Wr!A`f`l!8tLpu5||!)~cPq8*<^wK7Y{{wIAx< z8sB1=aOB9Bho)(jk(yVR_Me_r4QirF?04&vGMnL_{QT1;Q&m+}uM5eC>+1jazUMPA z>L~llX>QoDY}v9HSL4&qr{&c6{F%0SakF>E{N+AQU41gvQ+vZ=_8&TKzhm`BR?vxD z=8>~|TUuIz7(!*O%CfEntoZ+Xe`z>l$gwZ70s2dGQ&Lo_zPt#0-Z+2aEEf^mbBfXe z_jbp%KK1nQ^;6J`e;g6}?wLW-kr}^kC2syPqd9^l_TEnJ@Wdq&tu3x);VVNlj==anHwp_{H|nLc{_Skm#wv8&y?*6cZbJ<(;Sq~O)b*Z-V7lMr!i*5rgH??Tx_ z>(5(8u5`&*xjpU70ma3~`eZDHggTc5p2=ouW&OG9$(hgB4@mjnUvO`s??%@xL+ux*3Z_Jn$ z71bN6W0AKi{F%Q@UXA0)zt&g&J@!lq23-L0W_s@X$9J!8&gQS5oHDIf+FVIrpI_Q6 zry{A@y-#*O=Ymyx)7#TNM=V*UlKEJ8a(-3$>#X;$<^LSv`S@#1$8UalzxIoYub*E& zx;VMtBd*6V-EY3)<1_2bPA-dCa<_2e#DibAK7RQUG`h9{7Bb$oxn2G9^DAqHBgf}n)s5Wr zq$=;;PNf3f<2>nq-^E%xA3AhMXWO^*)Mb;Ml4RHn*Pokv>nAIlHN$}|nU^=z{jExy zAF;QpwE32usC4x8IS<9=e&Kxdl=qBhzxpA8$-z&a-@dsx`ME<}a)Ht`FwL&4c7mg-(`DS2sGmR`0MLC8|S)TmrLwBCT?`R0bhbB!70+aqGPcw?a~od1f6w3R*4)&@bmD2zX3_25-tvLgW$(<~4IF;u zuZS0vIM*F)VXFGmXwCkeh1c@#?=#$Uh`TQ0`}^JId17&lYa=FnV3U1OSpM(J;qv*j z&64w)RRlX-KqDV1X=$J>V@Ho3ol~%4bNXYw!x?{`pPgaic1ZdCiZ2(Pv#$S3j?B3C z!K6>L`r_x!$085uOq)3qbdJ)A6r(qHiW{!TuP8su`%eCEir1Q|2~%cx*tA$NY|}qG z-!3ZWaQ^OY>sl}KnjK8YJxN)Xpnm-D&KFCc zANPuQKffig?%U0D-mL9k0u8rT|1T^qZu|T1?OPSIb8)dvcciam#GaoZ;yA{8(WwyCE6e5{H$K>VRsEifB*XS2Z{yd0eQP^0(Wj@oJNt@lpWKbW ztqCV*S378nwA}j4c;@;l1NL*XDxbD`imjDoDs^Qodv|X#gVpxOd@l@CCq$PhGXvR3x| zwZ{%G&fP5XCQ$2r(EdN4viTZLH8Qh*TEu+zRKl9_H(6J|*&bH@u~8;<$tqJR-&oFH zXPz0VpXqs6)UG_U_h*YEo|EmxT@q|=3| z*R8ozSbb6b|9@v@WSUC-+4`8lGc4_xz16Pp_iW~QY?d=midxN`*JFP(VRluFMYaF= zdlz}*isS45n*RCwS5Qdk&>K(nKKbDA@bKx6IJ4hc& zazoZ<#2u=utdtbfsWDvXwsLh@7=pxoqhbE0ncJ_#VHEc z3OO0t zw17?s5?p`n)t5Jm;(Q_$8Ll(iudT37JC%J{C)ZwEH_p2B*`2*rd;hWR@M5*z|K4*` zL*S=Op7q6A#>#6~Epn=r|6&))kikqP!Wx3+L*Ut5!?cV|zf@slD;^_sHB$9gYh zm_%$yU}R9x)m^%36KKr-_tW~tL2mcto#ierjqc#AbSZiid8p}RSkUY{Co(&e6d4ol zuMLiFjd!URp11FBd!O*Ph1Y`0<^^|}X{fC6TQ+6N6p=SKH!qLdUXhe^Xz#7`%hg+Q zuj{z#Z2Px$X~g1-Qy5pgle~Mq(?5FU$-DJa(A4BVHN;7894GaGAVByIh?Cswl znbrqSp3IeKcWsa6LEj~xxhs?AFZZ9{H(`Q6MRoPz+qY*6OU;-x$tj}gRcvuHJHO1Y zCBLt20q5R zI^iF8p1U1<`sqrK%%o_yXIq>DG9=FbTfXfGXml|#l=~yU$;wZD9Aaj9cR032oz)O~ z62CL1FZp<%nTc~u#skM*WzJAWU zzOj1opUvFjdM(qZi|^U9#~}Zn&7ZBs@+WT_geh3EJ3Ayy@Q=-{`}_5Jnq&jV;^4$Y z#YsVvJU3|t_NdfWyMOuck$1v`maI;fCPn8qhowP|Yr~9xihX@}z)`K|^o_k|PV&FJ zw^MliBb%F&o-PeaVZzzDd1r3L+T_2g@aA5gnz|(O|JJg*ff9Q}Q@6f9$Jg+>ZT_|Y zS9i|#Uz|MUO4im+1zv`knVnDm8iwv^|H}LN;Z@}s;@;QqG5a(wcoy`{Li+ECg@0?U zs;-{bF{}QTbK+@{hl)^JOGB@+d;ikId(3Be`w5C1)UGkoH~(uFA$Q2|@bA+6>nDGA zrn}ZoS!@6Q(|i*Nt^4=bY|FK>e(N*aZu6TM7`TUJ$XTk~3ES+z1wlmZ2=rO!> z_ddp3_i$~${f4dOIVH0h0zN&ETjoEvBn|0=un95^*qduI3Zv$Mm~ovXjSY4lM${PMebrI2-8!F7YYwk&WW^v!x@#?1bu^&yvk)BI4YTvM)aWgIc)>G)e zYlj_o*uksXzdnoW-D3<86?pLcn#^3=qKx{Zy|c}yGH9v$&ie4=RN~hMr;dKURs56n z$fu(+o6h^pHrTdN$Nk>DdjT3E9esUniHQsC6ct}Gy;`NLgCKI3J?2I{gWYP8Z-R19IoS)OV zo8>aE^aC;D;!m7!-=0e6@tbdXdYwc5+OxgVaTly_Jvx+`eXV8+kMp5zTx|hj)8p&@ zy?lOhbNq&m-SsCXD5kYun!MakxQQX{Pr9F^@v@0$ivub?&$3groGall%Q$c5P5tG* zb8X&vX6N1ARXQhW;t_6khSt{BkeV8sNbVy{Ih&q|oW@nA(^eK~OG0&RX96&1w`)b$SQTSsD7ri zJ3;;N!&#P}CH?mK7ZnvPzO}dZbC;c-=J7jo68G2t_M4Y`tK^;F(bK18rWcsWAG1uo ze9Wl0?&qhcy?Mcr6`}P;dY^@Oirsk}%yNC+A2^y{|Fd~=bai)(Xz0|eJqG1zX;I&f z`k1T>bB#^7c4m!c^1K~subd}-;w$}e;$uv~_sV28)5zW1EoWZ}}K={y{Icv65XDp04f2>01MxIvtJ4QjZKRYxvPhL;h$F+Iu zfsHDxZ7wYzGIf-7dyg!?_T|I7hqq*8|9w0zzd0Z~wCmmN{^?)!taWD|nOyWqo9VEU zw6FBeq@!G*Gt2MYyLV%6ws@k>%IV9#ZVeajnPxTP6sZ1g^igYeQF1IS+!z^GvNNXd zc)$GP0|%Qm4Nk4+=}k)w_-E$fA0i3b^)X#% zt@|a~*`kd1J8?NYlNCq}e7J?Vx_o8%d)pZ-&aJtoFANL+{CjPhf42TzYh3zcp;>D# z_lGXMQT(7ns^^%!iA~pat8*uPG+PyQ7O7^W$u>1N&D-(pNs%S!l<;Tik1kC={q)4y zlQ|b=MeloY^WrzYX{Wco`gHupj?{dqh*pl~LrT&qXV-R{YM5JpHq3DS!kCe|Xv??A zEnEMxF?`&l+U@p9lO-xPv~{g@*`yk^W&asunw*_01D~cXJu-FCJIlj+{%^k@Wf7H> zZpj%?TB>T6XXo=td&Z$UM#VPE`!}jo7$!^>jOS{e;L5n+`|DfR{{DWy|Ng2ETpLb& zU3dNU#+sYn;osye=W;}?)NnbR9Xf+K{cOqCXXa^^kuOuuUJ3u~x-I45pO4>yP9OJK zs&(}J>}^jEo_HlED0p!7|C_p-K_j9<{j#@M+WcpkaPBUDziq|F;+ut{8PAjo*7C@F z>eI7(sMeX4{#ZzFQESf}-mO6eVm|jd3;!xS2h zv{VFjhF!k6d2e=bxtX=HYxR#8ou3)51g+d_XP~j>;=Y%R%sei!oF5C1RJrp-MlwijtcSGPBRb*rP1rqQ@|v*lYf}z=NyvElhs!N;mQkKZ z!S8dn^D+V=b`&TwMD3VsTWz*#^{Nm3^?T}>mMI2Yx;}l6LEgXa)6Y7OCiNwp5tm%q z`D)dxSwRxL`|~q+^p7o`BI4J$VA_fG1z&i%@=NBs_eeDE*<({tUH$me&X~t@6gFq; zsV$RV|Ks21oiAUldiBakBI$$by}HCb5`B7c7WL9wj1KxasczhR#`@Lu_4gC(zMnkh zvp#609B72$*x~~d4C0E_Y)x0LvpoFuiF@1kr^WN{^c-0=$vsu|fmHL7eT;j5p8J`d z5E{t-peW_Ke)R3K*Qpzq{_8ejhv%LJQ@N7PY&zm}Cerxd!#~$5cz_NBu!oV zx$xiZ`>oxs#cnFd>RG*eC4151Wwt6h`)=A=^cL0|9Xk2h*vDD$)A`g){W#4%yusg? zvY&^0FnEaXHCR4BTAIIm^4d}>-EHq~%mku`Sz-5SMP|9{uwy^|(Q^4O%s$+=;sMWK_AbgR>wr%#WHT$}8n0$S-M zeWko>5$L|p$1G}PYfKI=mlwKudbwlowZ=C*YB#UVlC$Z1U|e-&h5D}N_W%DBd#DKc z%(s(W9k%w+GT+%7K0cTCE;=7?!|!~yD~n;$#KUYq_kVr2%3pSFg{#mE*QzX`hqu#? z)xW$m(QsW?pV;~My>adPx4l(+y~r{%ZRXYuPkyE+-MO`8>x%O#EDGA{%NhJ5igRP; z-aVYu_Q9*p&);_!x0vtiML&b9cJA1|)kcoh!7WWpa6*sveWTAt8VB|#roOnt@a<-Mo}GCn%l>+nvCQL8^Yx?f>1H&LvhHeeL2``;uOX>nAUn)&GC`UvB^RhvMvs3#RVnZa#Q$QjF2L zS&=`^ypS;GKYiVjLB@XOha;w!uQ^{_R(_vx&ov)6H!H&}hHQIwZcca8w$X|H%wU^# zo9FrW`f3Rg_psT9WeG0s>)-8>F#j%VbMhSH-~9D|4;psx$=h8~DKWMEnvjP}-z@2KFfDlz%-bcrj$8awk%{Z~clIl4&E_so zua4Vz;F!kF^-K0ef6tc5T5IdiE1wp)gI)8(^vUyr{%-hUc>9woQ-XQUjezd^%$@VY z?(MDS|B{qCy*WKvW=?(N?}I@*CtlkFT9y~BIMKu6WW=+AS64iP(wokx?q2BJ#xvPN zMaI9?MXAwiY1WNuJGZcKfq8a4TbK%S_h6#42B^@W{ZLj>C#=>IKGyUPIpFU@=&h{!UW=qf% zWB$cbntA_XyZGYc7awm_c{t^yrj${I!FtR3pD}IQ9z47Id+Ynys)EPt`K|pGH*UmH6Z}Q%2*8y}I-#!+D#{G9nC*KC7!gBYFR>^@Wx_%DS2l^`bUR3v*^=;^U3@ zen3O`)xjrERLTT5q&+^K%d$g%w>y8FkLJslk}9+Ju{9hy8>^Um>fF2gU!U8SriOaH zwOtXwo%zaxx1;5VimK0KiKUDS1M8-3;cgIoVqNm$!K9f}U5`!MlOBCxYIN-U`G!_$ zH-1z$-@Jc!N1^iMIje(K`gGltSo~w(B&%YxcQQLpwv`D!Gx=YgO^Rs`Sa(Z>)q)PG0ZMwAv2HD|B*{^LD#K(W1 zF~e?#NhWAliHQ{Np1pe|^@Rd&g=mRx%e~FU@Z;O-`g?o+FZf}_Bj#z#aC4h({U13I zshcV5xPqp$Fm$~W2~zh{pWm#w--+kIy4~?A`%CA{@{uS9O|9(xe&P?4vu<25ORQCS zL8rgl-0XKZH5Vt%o42*VV1D(T@O#Vp=5$%}PuqIO-r~+||Je)=-ao#pW@veL$NMFh zHvhRgeZIVD*`q54cHb)^f}Gyo**srD$>OKz-(N1j8B2;PPr>gFQXV2Ecqd~^>;!J+YU?DZ~OiQ?s-;I=H}#?TfOam-G@I<0yp2=JmZgo zv2LJ!<*hXpd*jwK$=*7~7d)j=?snT6^`Na$?9CIDS#>|0W;$H;DbD!ro?E+Bmd}ng z_G5VRIn77T;PK6!dz`LM0o}QE{zz;?py9Cv4?sJMW>38a9_~)x&+}IFaQ8xOZRM4F zw)t9L(VDQ;{&Q`8$XoaD-xm)Qta}}CeT&Hq<9m)-??t3cPh9=cl&qdqd{9^9#u~SC zZ5m=S=2w?I-23Nt8K=R|d)H#wJq1^%Jw2YwBH=x0_v$;k3MxI*8A^VYcvqUV0HF?;t)```4OFmYnz@_AKV8w4jhU%Pkn4*>P={{X{)O z{r2D+{`?L)lTXe$tgI9R+O`*>B`7O935O5ky%;MVQH!2#@?q--CYx_TYURg*zR}d%T9Y0 z@6MbZ6}7U`^JA0v8G)VmLqps|rU*(*eQ0#}%;7Vie?OjS{P_&4L`8$-?ay_4=ZR~a zpJREx^4!mPpKYI4Pdu6OOr=S_<^!Wd+rb`5;|V#Zo|b((llgeR-LDjR9kqZe2D$rn zUvEa&??_*EbtpAA`6(q0oPbs;6T;^ftak-g$DsSua9lv8ASNX0{wLbRa zy8ig<%)AT^iDhaZ8xt5d{QXn=^l%$@_cUgP&(G~mpYFf^cMJ0zrHAa@O7H)l7hP}r z>CvO`>D3iwcQd6KK7IN$E1|H&^u5gQpTE9zN}4X?Kj7N0EcnFg@W=a?Zoe`Pn;7xP zU7f>AX~yKa7mxgwQ)cK~-@iTI96zl*OjM_U$^%> zZdb3Y@=&X)^yrZ@+8C%db)!&chp6ONgBKDKJ!-qv49gu;jCuvSccxA5NX#*HdZn1^ zs&wE+R)W9Wue^(2(yz~9d2spo_1*6$JUlc{lHu9;>ZDKn)_fn1_w2mC_uq7T+fT1% zYlr>duu;|4F<}oim_O;~uM>Zh9=UU``oHn<@oHzko!rm1&hk%QdJfG-=m#{Vd+|JzL-Y>4%cy^ZypRKDefo z!h3u1zIo^7Ma=N+lB;@2sUY9TF0@r{1-jwQK#$FE_cx6TKw9K5zZ3?zJR#yWYz6`wz<5R!!OenU!JF z^!O-?yV3W)b{MK~o(=x|jGv2#Cnh#3YSzlDS$b7fRVV-a`oh`U-RHHd_S2Qdq|T-9 zR)?*1a&c*~+};wkwoFSi)bHBK?hQ9U3 zv;5xI_7$&Qy{ZYBzmsQTg!bg$ydPu*gybhrkdYP8uvuJH7Usq(W8Lvx?b<)l@As`+ z{~Wxil>PP9RR)X6Tc12h$uN=n^ZD=hu4vx2)en3YY+*Q(uUGx^;&QP+C-wZw+`U*C zwB4(h266VfHJfH%b69+F#^M%MHnvA8$2z+=)cv1#diuHf?=;{4s#%+vcZ@%}T!7u| z_Jp-}?>;kPxYzyv$Cr})%Ilw)Kg|4i|bD(=s6b#?Ae1J@mo`M?X)(VLflCa+!V)9Ry@{q^%} zX(<^i9ZMrK&4@d^rRPssRdVtvJ=pu>P4M?qtUvx|n4Z1y;qkm}zj*G8oK>%JdBos& zzTgu}C7aR5>NAx!-%57+U;n))>~f2I*)lO^f&B*W_uYQ-@6exAw;mbSNvBGs*Zxxb z*8l%T5ZeNNhWkg)+uGdqK42{Tt}^4_fTorxpWfVOtO7GO)-zT2L)g>w_E_}TB z_fDv>nU}a^Wgfj&b||><>Fcl3n-3oC%w|ydc`Z7* zbxQbz>DO~iq@)uj?^ntTiJAUcoFQh46sY%8Uw^0geJ%65o!|GdGrZfPU~eyfyZr6Z zWxCNDGcGErsHi;XHNWRjP+)K+YpdlVkwCv&hcDdf$~Vii{8mP~PyLVfh@9&dA8Jw6=e{ zb?xPvRWEV>KEeFGH}c!}dYy@7MncndBO@a_IyxGh7BU<*`0)L^`D{l+p60XmZ*BNa zzq4dGaZL5Tn$9D?#60iKZr+bxe|~)HyGxP{KSNw+XXoSHs~>P)ekW~^C}sX^m-MvM zjk(|F=|srnFHLqk&V8%#xv`Di&H9R(Pqv4=i_Xm3`+HO3-eMir2d0IOTpTz34+-@1 z4&Hp&j`@Qh^Ze>Z{K>yrTRBTCY&|9|oG2{b@43BK{K|9h&&DNZrE<9$PHtHlylbs~ znR;mY=Bv|Jh1MR}x;nn*Pln@Xk@*)-mh(!?tqJe%nR)G6SkA3Khu3eI7%ZGOTj9lA z(I=_j+vXIBuQA)Nc27^oDLh@lZt)Qz=e1#v7x&vS9avlXZr|^`B}&DYQ|U>AR}^|F3?ncSK~l5YLm_^Zo}lpmYK?C;3hd~Rak#6%}9 z?K7u?4lOc~%#)t3qVb7+{-sAv*JO8pf8Mk?{3_#t4>Js7y^P!}3JkUii5V+>ei!>< z!3IaCQ>;3>&pi3QX_L|ByPsZNUA-~yuGQyrTYc0HKRVid(17PkmT8EV=#{L}_P%RB zZ|=`LKQ&%S@Yoq9YonTu2fx0vb!`%I{+Q`18e?x5ptp$}%xYi)DoIJNk4w1&vj zwl{Cy6y0c_`L(Z0Qg_YyC(pNCO_xQZ-v?c>u<=xgY<_nz_d@)8R9|K^Oa z>9S8tlph~2x8w@(4~m#j%;*qb&}}mR!a{TR{ii+b*X^xX`H5@I-vc&_A0OlBHkvy7 z_UgWEdTn!lRWg0(lbNV+WBF=j(9yOB4mf;%Y5CDq#fw$m$o=M`T~VojKCGVm^ud{x zOAF?H-d0(xoRSdW5R$X$uFU@QcrE)5pY<-{uRS(CXm9u&_2I~uLdS!NW%GaL{bnrp zvd$O1Y;LDlR&b?5!m;mKb?~>R&CjRU*=RWhM7Y>R*WW7QoAb8Hm?7;{ZfA27JHKFx z^oQFY<2{4S>T+`V?d$6u1N#_2(=Q7H7A#r9a`526j=sLU%Ue8`1~E2FRdVu)zm)%E}D{NAtlx8vvTWAXLYfed=hdE5*q zkLBGN14CE@?S#K6V7&xFb_`nw=#<$@3`>rl7Mx?`mUe?!~y%y{3hgxO8$ zj-QoYu2d5mnQAj>S|D5Z?55iqVri2X?S8+7pD}#K-__eZF9-2|KUI)%&$BA&++yR_ z8}iq$#-)Cjw~J%yPCCfOFDG(Ec52AgtDEMp`T58|CoSOEarv2+z8*8DPMvyea^%hD z34veEcvknYEq=fl5Ej<9X_L|NISQRl8!J90X-xH6aWyL>EG+5cqocWXYUaO})V;la zUzXYbrqN$dF2%%IRTIDT+}T`E`;Y6uq7-ii4@tN8Qw%b5a*jm5-&4#nC*IYVA?N0f zcYi&Dm*4(cy)RRGV{mT&nl(C`7ysRsds|`p>9c)*1qB5sboKnwwf|egGmY~$hr_Ss zuHESz8;^!xy}Ch@y-+QHUooSww$k3Q?=@UvPV8SoO@io0NSSyOXz0Y5o0u_hd=+ zFZXk9RPdM;z3M-&J412F`K#ArQop||zwx}TzpHhsc$dfd)Lz^aF;cDRJlT*=XHc$M% z?(J4z-?LjEoLTUNVZs!fgF7F*%AGKOdNBX*yG0BF@w>woi$4cTb1EwGOo;BRbNxH=fd%~CRKa+?*H9zHZVy! zT+t}@(X7?sU(VG$c&-0Gc=3*ck4!u2uKYSTyMFHPAHnCXc-T+ff62+iQ!+#T@V9>l z4mfB`_1c_pJ;P*%VKUpSSyCHIUIzX9t$xwW#;w1{OXL#A&z+GeGM^tG`rb0fXuCOs zr*m!XaX(kRwu`SfR=z&JdW$K+$;Z??BDuo_g{)SpWX(dOSB4UU5FUAp04L1%ZP7GS<5*9Y?>Ppu7=j}5N z30}H%>CD15Q7%>ny-6Vj1qMBC%G31XO0>2wn6an+QLzfs15=% zy{=0~wN9O1*&=><^AwS%uU~~+|5+Qxe;^>_#lOdILp&GmTefW*o0;cRh7;}X$GP4Z z&&>TQxtjH23+HyuA`4yJbC<7QiCx|LwX-|iXU~S6uU)FDOnth%Vh*)9D5icDsoW_k zp2*p}l6ir?)~UkVb?GKj8*^TsUcRZQNaoba6)!RxU-#yOpU@0XoVwLcD=gyLuf7Q< zQ=U!u{_o$v1c_s>t{jRy*eT_FuZk+CI9#N{V9i7 zUw{54!ma&#Eo-sdtVb`Ft=-Kpe(0;;D!$i$PW&zJm9o+Cny~-SwYR&C66b#LzoM_; zP;l+7^Y8jhJ=@xCGIyBPu{IR`Tl`(^i@d<4)MEL?7aQd3Z+VsN^Ke(1>-qoTt@Yop z#;<>UY4^>o+2U$`b8fsmzxU%Y>1X%Nb8bBNFz;FzTmGJJ*Sk!!?d>@hNIB^0JWEu$ zz2V>CtN(A7`#!Dt8(;tT>pHX4>6$0buW$U?IZ?ZOjz>-|Tf@8itL<*D&de*SQ1&$Y z@t!{{E+Zpj4eNs5-af8hKQ5bg*Veo_T)OIN){-SlZfNq?@WZG7)0{?s);aK`*-=IsAmf(-qU#_zgBU#;F&`uyIu zUp-f!h5ngQ*d*h(+1U7m@r28fFZY(;Gb{QKkXU^E{O<45nGAa5rHu_tYL?ud`DCL` zw{Gorz+#wU*%?JHqNSa>#~2B zqKi&l{UCm9-eck9!-tfTs;`9Qe|>fJ*@R6h9X$Wt} zUgi1N?_8R17A-mx5Ky#@N$lt$4u?D2;~O3@ZYaF`{pN$58`8e1-OK#DD?Be>iY9~phEp_22~;%(d7=31xwo!lQ@JBMij z*PH`t%+uf8dclw}B|JO(UVXajzRh3D%{J>jytLGNZk=0npNwr3OZH`la6cZmg5)6f z1v__qxzqZ;`u*Bq6-@#8wnT-g9lZ1Fe||M&I2#u??~$+c{#xaV4*|PbJtHF}FI~E{ zAZ+!*5Us$-$eRoESr4cl+1$$!7QHw{zWz(&q^sHcx7Gfa3f_HEZr;~|>Bg+g2V9Rv zI@eu%$@S%&rcmIsFAQ6%zb_Yif9qdz|J_uNRsRJ-O0a+;*pF(!EK+?;0xCZhNrO zoi%lBxmeOK7p2file><~Rr9#_%ayL`d3?OSm|fm$wZZ0OVWCMm`5Ibhb~B2*f*QmI z?@#r3dh~4BtEg^0`N;97@6YY35)e4<8F^+!h2umkKk>9!_U*-fIe()WC4RH>32f0W zT(x9H>Fe{m{ThOG&Io(O)HqFXaC`uwD+kkx6&5A zy`!k|t4TRZlI?!}oduG{X=e`R+P}A8TfpR?+OT?qS@WgOum8WirT=~Jw^yg1M@2>5 z`upz4kt2L>|NaaK4^KWj%hXEo{Otwn(zoaRw`9L&y<(kNbCOSKCQHHF`Tu`ad|%xy zKKHsw^#1=-rikqMdacW8@x>b)4LA2B-ksF)aeH*@I&Do&$E++ZFE6h%|Ca}?RG55n z!n}F!0y=$seO;rXW<|~rjt*-}{P5O1KJ(Gz$Nca9JUw6-vHyS7hc{2%kM#+e^nETi z`uTXr^0(6>3yPY)-2AokvsjKzjlt67v#Te^>?~rLN?0ltu6&wR=n13Tod@zb{|$vb8m}onKyTNd;GHqD0P*Z~JFmT1+8k>x9|{mIfU|#Y~_48coZUE7q(r(H1{>@}yt>oL5m>ZtQ%1fHT5R zC+4a1N&l4(WG$7>=>@$!Dg5&JLnYP~wnq=;1c^vIxL^KeZSdPe4NGM#T+~#`Ew??k z_Um#xqRLUU>D;+fHms+WwzD?aX=r#nd4AtN;7Zrq=z1IG1#DtRovt50&wlu^5bILu zzi)3$R4O>s_ddr@>>2NavWQjoKfd3ZqA9GtMAqx>Vq=M_Jf8_47S_DV%Kmutmg!l} zWcT#*)oBO)mVV0OZ1~Ke$FPIv^hYB}j+BXM>;A9ux4&I{{7L8W?@QlY-M)3Tt54n> z#m7fDA3r%cSzAe2nbq{z%SngQ_Rb5O`O529i?%x3rW042W^c%1jQN@JHoW?HzrWSC zx69?XJo#HueR7NDZ@wo?8CB&+rTOjt{IFR)M=>=uHDLAC01c59Yu30_Rqe9e85-PQ(X--MlpL>X9&A%^?pI!V|c=Np7|3l|yMNM7&{XWZSwN?$Aq#X+i z=S-em%k}N?B6E>$HilBGz5h;q`7L+j$F)!9daGY$?SATAcXRLR(mOi}!w(&9=hRxh zWQWJ%>&8dk1Z3};bx=BA+y0mTDOursU+6yz?r5t;~+E z{d)E2j2k!fPF`->^Cqp$u-|<1WlM$@_kOV}>7R=Iwp~v@Q+%f7$;YNi=R}{Sni%`6 z<`O%)NR+`^NiQ(qud%WJyyla0Ov*|&CCooCPr+P$vB;f2UNY09eM`d_SNtowTOT}a z-zJr{3ijdGZ`^osWo1TrV0d`<`Tv`@Rlb>Fc$0fxZC<*suWx&imX=l21#9gWv6fG> z)?CY)c=2OXQMu)5clp|s>6y20CYUe;M9sKb^tSC6*P7=)?!|qNn)&B`b$HPeUB$pM z>mAYCXPOl9nZNwz-P0O6_rEYd$#NbW2tD5hcM0 zF&!6$+Me{nLtRIb=0>PwefjWVN7>S-%C^KApC7Pe@ z!Gss-22!;LHch)MIBn~fxQQGMCo}}Rw+eMGiPI9i9v2v=d+qht=Lcl3PGa39I4A5j z`vC@qW=0-H0k(vIl8}lYe|{D(R`=U;IRDEHl}!2n`^tJ(UCdCJUjA>(|9`*VyXWNS zq@CMwJ|JSkV%wT08M&wSUHKH&{LpI0$;E69mrAZSoc`c*==;RGQk*;Xz2H~iaL`!) zPqENYSy{gR&qu+@?`J%kK4FH&$FHS&Jlo=yAKsXpd1hJf>?yPBe>{|7h;?vixN`aO zMdnriv*;kmii6X(y*f7(2G-n_mqUrO#2pSR7(2#_u+F52SWC$q|SM%9u# z7e4+@KOj5t``0fMc;!sB>{f1cv~{_CNhrr)6QkSWi|whAni0z8CtOncn9QfSDlPU< zx#qQ0XseIb+Py(*bqssEy&`1vIv3~rZ`~;qb7_6!gI})$7!vpGvr9a0XRBX$YRbyL z>VEScNtz@yTxN}5w^z-jt|Nr^u zwNbCzZI#KMz07PZmCdP3-ITRcd)+i$l(auv|MM1dTq4}<>Kn8&Wa-r`(b84fOBwW< zf@euG6zTi-PuTJBp{K9UYk^)j`5c2SY#ZDb_g_@`y|d`eB4;UAoz+uM9?9Zgxn_9)&~LiQ&TVm^me9xSV^^nW_m?DJ`?b8| ze###8&3mWbQ4wNXle&&IL8RLyYGufpX`U)ur%x?Cy3A}JPu?5jW!rc+y)A$E(E0Fl zJ45xVQ&U#fc|Jbo{nz^9`#B32E@WJ)dbF*nsU|loE9>pPTJ||Jm+KUrx?EgP6B84Z zoP1cow_EQXYG5HHb!Vq^|~r&JMOM5VbI-p#$8b8YWbVo{ryr=@ ztctL*$rP^-p3Ba}VHV5mbN?;7gPfJclKUMG5C3j$=l?wQ_m5Lgigq5k9j*86!-TDs zyHuGJ#F%?~d)MmfMjih8`ufaOr?1Z1oPPSXwqD$xyehXO=hbZGL5q!IOP86gY)@U@ zCZF1P!??ORxXn~+&`MTlFw2#iAr+jkN-Y)ptc_GupcCyf&B@0@%{_nAN@l<|q z&k-Xp>SdqO&vm`}^DT<8ID0?q%nbJK<+tX7l@6;m3*1&TPCNKfjkwNpZCkTG>9` zLuaC7@0t^PTpp~IJ#qEQjSH(TZgwY2iR5;rcY*q`X!_UqTzkCT7>`sKBE@7|+9D?_eaS!1|m%NB`M>qE9{ z=*0x2r#%gOE!lP?^!aS=S!ct2r!VO(f1R->bY|VP*{^ilQ<)d3|LT#L);sIpvhPw^ zS&JDiTj%FHUb$vGVMTyY@O=rL1^=!mT5>Y%aE-DL{yRr=^>T&JqLE8JKG)t9F#TZE zx$TzzM_t^%cK7sr`1<~`yV~?>?>&2Kj~LBtnZ5i-kaX`9;UJxcW50fdt#wP@QTW)Z z_@~#_Wp8pS|L!b0`hU@!B2}S?XG<72obhxqE8FtzrEZ61q417>1)^dzou5_6R+aau zdqoN~D603py;*Zx_ItFe^6gETdq16AF20Zd0Z)VXgJ0psRi2Dlr^64Ns?)a0TQj#e zjZu8plpo2*TV<*PjFCRfhh zw|sGx;j*HWEl!(^jrV+4czE^tZsD)F&#q2aF@5aLV9@aT53gD2N_O=lznX-f?F*g0 zdhaT|@ajh|42=#>_KdsY80%po^T@zwPFv}Q8@c8))>Yke&B^)sw?lqsLw;1!?P*^h zluh_G^VR#{z`%#Gfq@ShPcyaZ-|%c%A~yTi4XgS|t$kNI)76%_^*&HzepKO?v+r)A z&xCJ}K{yf|8I@W2fg$z2Uile#hKH1*= z`pbQHQ1S z$GJ=l>($fkbxtgcj;uX8W7@aZk`eB_ii{R>CW%iC4d0`+dR@h#sy!2r1iE~iQ11Ce zK2Yz+#5q5@YNENjwjGl;Y*qUG%=TuwhyC@L|J-D{r4HymIBAjD{cT>OM&uIPT~YOq z);k>AW4@zu;jxpOs=B`2njtSWcS~^l=PL&f@84B4Z`aMIQ?xh6uJ-gje9d+ZObE0FjVw%$eR=#S&?G>eoL

eD(kHJ+eRlhXFjkK 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 Z`jYB*%T61HGB7YOc)I$ztaD0e0syF#mE!;a From e72dbbf7e59a4a10ed014ff18b4e28bac54b03d5 Mon Sep 17 00:00:00 2001 From: ImgBotApp Date: Fri, 23 Mar 2018 14:08:51 +0000 Subject: [PATCH 0462/1544] [game_fallout4] [ImgBot] optimizes images /src/splash.png -- 54.12kb -> 51.74kb (4.4%) --- src/games/fallout4/src/splash.png | Bin 55418 -> 52981 bytes 1 file changed, 0 insertions(+), 0 deletions(-) diff --git a/src/games/fallout4/src/splash.png b/src/games/fallout4/src/splash.png index 2522871afd12baaffc532b57a91d30d66f69eed5..d612e7b86367b35b49a4d682bb8e7abd086f3f5e 100644 GIT binary patch literal 52981 zcmeAS@N?(olHy`uVBq!ia0y~yU>0LwV3^Or#=yXk^3q?6fq{V~-O<;Pfnj4m_n$;o z1_lO&WRD&6 zg#iqHI`6J$U|`@Z@Q5sCVBi)4Va7{$>;5n>G%$F&IEGZ*dJ|h35prAXf2`>4-Mgc6 zB$**#Z&Csh=xH=$>q<`OaqQJ#TOpCmqs1nqwe!Aw`uvAy44h>Pj{QFOYv13!<*es! zroZ2MJ?>}pf&2ddFHGcikYjLT_{4aEe*r^7(;xzGK`d?k% zxw7sr|3Cg0^1lwcl_+vCYcMY0Y52sT#khiLfmV8mFp930#w@9-qErS^#wpAJTn>f| ztt%Eze7-*;r9fHu=L*9>A%|Ag;9s*^?%k>VQG8?V^}zSdNsp85)YXsuS7Z7co06L9 zx@OIqqBlReTAKu%I@YdTyWs|tq{+=&w}h;%t&_5|y>oJMI;Kt){rK_Y$uGro=FI76 zZDlnyHdg-j?VF2^nDE939i0NT6?K1q9a7>@nc(oh(#y|F#eVTVHQU-xD$mYM-R#eo zUmWAr+k1(jE8wp6_xhtd5|l;OI0i~Nh~D2k`&wOX-RH>%`2O=26%;6Z`}XaS6UUe9 zfmc_BR{q^PcdqQl?c3G+`udKXJJ)yP=1sxu>}*qI3nL?=;PXBG{p$Pn?K|}BgGz94 zaH1f~sW2{XZecM;h2|wEPIw3j2|4ZAv!`SAYVAttZzg{4wqET{W1PB3kZ19J%c_HJ znmsR$Phkpp+E{XY-uw4WN~~fhez|5QCMFhqE-EZk^z-vO#K!q0d{T&(YFu2LgH*e0gu(C?)cAOCD?6TmBh_tl#nX_mAudj$$@aDOq z@8YK3dE6=!_MP7yqo*z?DCn{>WYUHW21=7pcI@6=t@Zf(*}uh!*38}Dk}x~`S~9` zd#08%iH$Sv`TlMl9UTu3kB)2eBcq~LDG7o??dsL36%`c%<>lp%-o5jiGiOf8zqJna z^WMCD+u7TD_W#-MT`o$Am;WtlupM*Z`=bh4G^ZAURbf-eg%IO=nY*7gd3tKgd)7sj4YU0Cp@BD0RY(nb zc=F_6t@WSlr=B@;rsc|d88vfrb44SS32`S+pYGNW;S!RTUTvgf^!PxGVettAu1O(N z(nS7#-Yy}^nyKr$_W5_eJKpb|o#)$l+L|@)su#o9GLyQn=o>^Gz z;Vq(Hwz#x=nPaj$Z*}pf7j<**O}S9LJf1PbCoqEh(wjy5kF8iC{Hol{K)3nPucx02 zlihe~7!PnC&}49DkYU&$-eBEum!XUkl6PU*I6!*$%6)s}4AQnPaO z^E{@2_H9)svR4FhZ(FvAAv?roSLK(oD7T}ZTsI$PoWocka3G9fHKPubf%E|rhHVUL zj59Rg345t}oD*k;* z6bctFFDOtbes)8i@q&!c@^^pQrtwXkeJykf^Mx-b=LVnOA}QMbE$6pmwnhxY85V;c zDUq`bSD2dDpWddZ?{wI>^~L5^MCl2#Y)Ow(!YqGr*5)Ho6Qv~XGTdN@(6)TG?v;K* zZmw@kY;5Q1*Uuan)EHJ>N|)gI^2UD4hs7)nw`NcCi&=Aag+*yeyos(>;j&Es+LfW9 z-BK#9E03nMOj#!TzjNDTCQg+J4p3rB^R5cLB@7xLS!A{2;FZV?7rVL`qU^rzUtl_Yb?xe9;VS|S8{0BwHDz83oFgSt`9a+D zm4JsrBa0A}U^X@=YVJ%3VGnLk+hPep}DZd+6E?>c*Heb6xAplg?Ljy!5U|XP_K`PrZhBnqapZe0i7VV7jyL0#M zNg?;+3=Dr)CI+4g;OV}T@M%*P(~CtlUmr|gmbkHO=3j4y(+3X3Z)FW&^;z<0eTK3g zJcv~$IMmNf43u;5W>DVesxjI0>u0;Y)$&Zi%@+mOgf=F0Z}Vo($WhBOa*UP=`Fras zUsL9ti?a2O)9n#K*~s$C`=z|WO_!+*TV`k7tzT^R*Cu{n4Ie`l;|lg=_bj(B^x31- zVD>1t``l8m=BgrlMxM5J23e+|3+k0cGPx1)trGApNN>y^&#= zv#hAs`(2fJ2AaO6j3qnkKYwWt5!lSWy^iJb`bFwnJ8rzIbJ~Iu1DoRQ_1Tu)+;a1A zL$>{nT|4K_m5tn2^Rw8%R?o%bW%9!EyEgnY=B#03II~|PUM)jPY_mG=e$Hi|Kf6gf^%X}7kUQ}XjFZf!dt*!m&#S4#JWu{+Q5?B|A&d5>PTYm2!yQb)K zUAHf$g%_sn4_#OCaVvw)!7V)c-v8Y?!ax!D@}&4#MOdgWt*?K^9=z>V$2c@%R1vSvwB|CK4LxSqG%;k9{p-@W{AzS({;={QPrqZ-f&Etl4n!;>0tv&EFdaT@QZ|Yj4hU*=Mm} zL*2yr_ti6{#3mo(*};)uGUJ};)B_6~IZrh@FmWz9yW#{dTbtGYM<<)LT7JcHnPlGG z!ZG8^NgI#O7*Lpj6a6hs{RSh3Sz)UJ(nO?J78DdH`1$!AIeN5JVtd9$`2z(88Ec;= zI(!v<%D82Y<-Y$}xnD(DKR=Jva}t+zennYOCOybJe%Lg!Li$dl!6E-Tr$pR=hg39jMiF>vuT*tw`u zafvguR12v3Rhek;lzlG0{0-@64<0zg#Kd&$-fdl2TB@3~@rU$`f1-B}PB9i~ZM+gL z!W{hJ;^UitvnS4KJNmBobR5GBmIcBym?j+(c%==B@6yFe=B8R*j2h2tFFn3?e7pW5 zpQvm3Obd)8mT+C$An>FeT8_S4W|Pn`=@s*f+W-6hm}iGTGRZ&Bn$yq4)H2 z9p=kdmTOHlZdEY3Dgr4`7kqhlbx%T+waNPE<>y$;{&vdp@$oH5J3H$(BM)l=kD9T= z`&@;Hnmb$!QPyW=w)tLO@k37V+@r@)2O2&UvI==9G@EE??aYsSSoQUkXwlCVk?fk+F zXV@=@J2+PzmvX6X<&yvY>7wt!S#3vk-%r-DTPMlGAs?>L$YR8Ca5{HS`x1$UQ|ng0 zk*)jRr8@txy^551t_6dS_=TzjrMa$(OB`Ww=Jw^Y56-k3b+4Ej*G`k({Yg9~(|nO7|< zO(?SX-0-m|rR2#&o@*;sY{~jJqkeIHji*}61k=;cHq4H%9 z9#7LYbc(KZHJ|vAQ9{Bl&+5#KxsUf7h&OJ^@Beo!Kc#iEpeYkqLuZiKQoq(o2@hU+ zr58+DR3AL2FNi@)cV6Dj_wFr9jRH>Z?(h8~$-X6|9S6O z|F%!-$j-%HDG&R!T>r1LkXT=@`0LJ|fcJ~P^fRvawlgpl*1feY)A;tyn=^0RzAYRb z9X+)!Zeh&JuMBMr8GOsc4lBIU=4$W^%y_&hQSU#l>1Cr13(u}fm3Lh8IX zQmiWlr}FRG&HDf3PLT!Y&6_4Ho+mml(N@0lWugL7dx2fEW=KAxwcNE^#e(|{ixevOe(GfP_4D29k}!2jP)JGfbX>CbK6Gi82vP3Vy4PD+SO`cw{-PcZ#DCW1`C%7gr8+~Fnk@jcvk-=sf$%d3{IChxA7QB zT2)NQcrn3okzzA@CmX+g zoPTeT-QMc%s_(Bb3;9aii8ZNBDWCZF#=Aw9kI%S# zR-4r=<}aVJsp#E>venNcx8B=SvE?Jv>$uRDbxvW^C+mgz`l?#bI1`g-c;<6EPRYCBFodg<)io!%#)JI5@-s?f$ z@sF2h|K6KF@3h^&Ump!8K4EZm+v8tR_AenyCs_Z7Pa;NRx^39{h8aE8TPJxhYuZ3oqEKH z!RxN|#!Gg)XRi00td{j(_Oq{~|JsbOh3AjX>=vBs{Zje%^j^i52`5gR(AgiYHd(N| zyd2aXe)Hx{$JD7)Z=GMPv|n|)e)KA#mMxRc$OVXPT#@wTcz9vW59J4k`1q^xxFjYR zBq2@zq=2U$0cz1ZG z^>tl4ZndPq?sd}-tY_lnXExCISxD-e+z4-p>>go_a$JY*rqI^yGU%z}StGth zLDVJm{JV0y506jpJ~Bt_-0LvCU5sou66gH>wzb@}{@;!3zl;AyO}*W;@~oChMHuTZ zd$p~*wcq@!jJHeo7nJ(ZT&yoD^p2^KXU_MXEDxO()r$c ze!YE&Eh%OLsL>@c`|FE+KDY05i|FkTI*`C{c7@-H?`s&g?OP<&P%ULsLF8#G#z45wzQ1=Eai7&HlWLmdcG)Voe?qWM~ z{O_Z`b@B1>kDfhqQxWo9HJ_E8U3h!%>h;Zy@7H*V-nMBv;}yO@bb-_2h0pi#ivN6b zemeicj|mg{UIjH@65x5eCq!YI^qtLfPbS|#J^x>e!@X^lxe^Vo3~Af4?Nz;2>}kGf zz3R=0#@Jih&Z!TNG`yJo>F0Ys-PcF{8%^B$8FBsxt$R@eqW7u#`vAtRTjm{mbrXc!OWD7 zqF}rAd<&ZIpY0Z``SyI<_l4UT&Kxx9(&7HAv}7aGZjJ`7%WJB?^41GWeOG7sc(8W& zKBgN?37QP-H?MlzU;0(MzByaf!?RQ9k{QdddX=kpukP`D>)6Tpr|(shAK7D^D(Zk0u|-RrtNo*m|1E#@<&>7~Pco?oqH$;xT1j3E*?R;NDKfA9RS**k^gK;^vl0zcZ>JeH8-wa$D)|)yx_n6qkFNs-}AQEpV79rQR@=X zno-Xt5ioUEQ=;O8#!q`*^%=dtwe0eAetn)xD->EL%)fYl(&;HWX-sNf0WRmCpX_)w ztM~JhlePi3YuLZPE)+YUVGww_%V5GUE>XL@>wIV5Zt>j{^z+hd#)v}&9|~`3c=IyM zWv=nl*wnoeH1NB2ZSJb1%w-p^&w0(j)^PA~I&b%%lE1TLOQLJF4p(mEV(skc@GurV zb@l4h9lLk04*h@p`0>ffkDB9GCSGLqIkKo@!GfiypZ`4gM0495v%C{-b~cj)Tm6m67!uf>GF#H_osY$|88QCvg6+K!QJV!dHxR-5uJz!A`NF5rd?STn45d#dH+kP z?2{)?E=gaWro2)pgz1<6N)Zo*y?0~xh4<}wRLsZxKJG84+Uy0=GdfxyqzIk3@GkDF z^{aoTs)hwodlUX}8JznTbRm8()9URZ3>UHvt!SLR^{i?6yBKdq9+nFs{kuF?b&9hH zw`RP5x9P*CXG`So?oaRdu_G&R+WGhMQlsUjtX-?SaqHI5!yIXupY|W_bKcv}&OJFy z)?xW|#ZNxrneDBunSZ}em>}@z(W6CP?OnaSs`KW}bJ3bQX=boGdz0e}qsByqlE1vu zD-{haPssMax%Z)gzu$&)SF%RBlDO$7Z>ANsHOKeZ);qmmv#*&DvdQIRF@ss-%Ut8z zuitc@m;C#C=3_RiV0Bh*CdCO3|Mi!&9r*F^sdHRqK=t;uRjdh04Sog-OgI`@E|s}g zzAG$KuV;LF_sIiJwM}u1zq%P#ywt6}6Vqh!{AKaa8lHwohAJi1q?P5znZ)I{zrMSA zc~GVG(RZ`$7-le)zTdGgF)cK3TI1eZ=g;}IZQ8t9Sx-;z$hB+Je*9WB-Fr*s#SGa{ zwbz%Mg9J=`o?5)Vf3-$n#TH31&_MXvv%aC}4`03VGRwc`lNGXh7w>@p2|lOk3xo5j z9=u{Q;QqGz;OYziFTDHuK0#u}#mW^*fszid{kz;P?zS#*58!DJMzp%g86KmX9d3{^&GBx$j*{a4l4%aU;xG`n$s_`oAFPO(- zWZ)cC>Rwy--R51sfzGzI^J=*oIDD)^6m92fuDf^X^S!m%fh(1?y~S-7_qFz2VKC$X z`~Us){;rS>Q-Y84?c+Lp=y>RBr;1Mvr?h?isIl$9XF>{`+z_RMNrvqZxbLi4yyL^`7SrFL8`$ z@I0xbdxw=tQeyw=cN*V&x$m5acQVdtd-K$S@9WYv&zGj}%KVtr+MYQ(J$?FAvzy6+edHneCrnv4SYZoSHDk(K}98FT1=+Uu$z5c|LDWJqZ_xARd z%atXq0r3+9?b5qdZ?BnQ?s%r%e$nE66PbQ~)?+u|_;ofj8YFA+LsEj9CljppFhYsfoE6kH|F`qmG9fa zc}mM>2BuFBh*zAj@Z;`ReO$Y0?QXwYu`T!Zvm3F~CkVKony#CFfV+aFOb*za$f1ailq16cGab?PyLKw*nIGb$tz)F zEB>HEOKj_Ec>PalI!epS`@8YTif|=Z&+uq9ZCGfwSoiKEA>-@S@7JCGnZfY*;1zaG zLGH$X^E-TVS1>O){@p*n!gSr8t%Vnb86I1tuM}wc#ns5ue&yYY7biIGm4_4+8GW?U z_mr@&`?GytZI!0(nQBe<{tZ1h_7vV-|Ki1poSpCEY^EM}w!OM@gWNlfu>6&L3qGH0 zz8$o5Ym7y;jnDy}B`FsrT9O-&9$(A5;P>C#&-Z8e)%@Rfb^XBw{E}RD>!fy_-;=3) z?P-frYG$VAnl)=eTi=%oC4?4M74ytCnwLXp(Yi^raQ zR^yGCJ^5l+<~CtbhO!3FgVMYQ7DY@v6sAAl_S~1KUF%~1h^!3OW)*tz-&5@BTh%O^ zM}I#bn16mg%fGsk|8aZn{P$b5|NUDR`}?;&>-LpfC_ml*w>Dp$_19g`8i5LR#V-%< z?qIaN^^U2T?ed&cOrQZYXT`17S?5x`)AxP9us+_t^Xdl2hYWd4I~X3A$ci)Ed2wmu z;n_!yxZL}GH}m5+ezpgHl6p5)F;v;^tJe?xx9#yCNq*C3nF4*R*FN9BaYAEz>o!(7 z(;H_ld??%*D0XqFvNTiiCGYIqTwhRaJ9Vn)&DZ;aJ+Cj)o$(>UltGs-x76zV_gJCM z7LBQ=LRJO{b+&-A+2oTQK5EL>*T?_oP2iis5mYPT#&YsP>+Dq#L06WYyz)e)&TsO( zWx0J0|1Ep(6kj;#y~j{v`MHCaRJ-k&Z}28Cnri)Gdhz<@MqTeftIg+f`4vq+G&nH* zwVxmuDwfsgSh$I81J40HhIt{5yQUo5!SH~^w*U0X#jA~jvi^ZnR_hJxRa^~x;x^ma zKJ4v&c4o#O!3LHF>xR-VJQj^F7jF?i@Uwb*{)cTkX?}8bteOoRzji&ox$8pO)zwqv z7w679JKN+2Z-RuxmsOt(7zE@^YwpaP+`cPg_Kt~x^HL3TYGStPwIm+gv|`SeE1Lqj zt*xy$9Xk0^v*F>D6RVtcPx|H0xBoF!wyibIpW95dOZVP150#X&t3>Z`OtS0l`loi- zDO6|Y>C}bh^J|0lRVQm$_GUeQ5P9M3i#ZSe%jVr)%>xaWLq+XgOC^c%YY3Si)4zY6ITv>Px$KD(&Tl z1j3bfE84%W`*7*19LqglmV%yn6K`J8kawCJ@_6Or({B&GOx{>?@3XPlED^ns1lBLn z&L^+6hA~|z`*~>PN-2l^Rf3Z|_TOCaF37azj&ol2(^&xY$-1oRgb6W#a7y$7G|pMEf$^`%Z=K?(S;^yEkkw0QE;e^Ek6- zOHVxgbcz4@cj*ZUvSR<49xiJN-luE(apL*9%DHwjoQF?jrd(8-6`~VfRAJ*kMLW0T z&y9`oJByxLF(h!#xUzH}gO&8tlXrh-Uf8R{nV;YJ!wjmg zySwB0l?~fiFMF?Ho+0A!ji;Aw!;$~rOygwtGQW%Y>B;*&?m|4T>h{jG>BZ_caoOiS zw^ZC0Ut)4>O{zw@X14D&)&#K%Yg4;-Vb5E0^eWXQ*zEMSd+qyL)&BAKKanpp)~?l+ zys-a2r@_V9+omkEw%t+qPWXPhwY9adzyJA=-cL`8EDMW^l|cif7cWk%>HINgj`j3a zhn2W>XM|6Pf5~MoI_J}K{``ukj=FPltK~I&IloT5yrQk>=_8B4Id}imJ^r<|rHPeW zhFLf*&33UYL&>KbyH2UEJ|AmV-*t!Kn!iHhmzNh#d%wSA^d)YszwKh(gG=JJcqVUQ zy3kamk==OGLc{N=qujxhDiazf%v$%%BH3j9v9%iwFD|Lr=v2KTc)h+Y^VI`OE`=@o z6_C$hthE0V^XHpycNy^E$6#0T=6w|`&R9T;?if+b0@9&{(1eU3NfvS zgpO^j@2)Pr8~94`V*0$9%L39?Ke7Hf=f=-B{*R>0vu+e9OYHf;$8d}P)vaS@hV$yz zPw(j9c=YJeq*c>fr%x9Ltzj@TGdpti>eM-t=k&2%PQ2J7)xxwT;nyKu`5AYd9~(CB z(tq6Tc5y>q@7pVzGkE?!HCeSVCf5Ea|5LBY^K9xSgse*GG-e2EetMtnwhw#%>r|D0YpIj= zTXnT{Tjs@tu5FdqR)kd=&oJ2_W-vkRWY)DOKDX=3v;BS*|A=-zay)ePr24Nn{(qlu zq$MQuh;zn=8w>^lDR=WLcG;d?_Z*ZyR));t5Vb_uDgt8coH_)gg1=MJSM z5B_sc_q=t;mvwo~k=&=YcGV)EemF8Qu)o-ExKQfU)!)q!M)bYFzuB$D!@JE|>n)X1F|YQd7*Feahw*n$FcRb1NHvy43ucz>{G3<#xfO zXz^S3j%J=~4LP^}!2uS74ey^ZNL|<+@?OC%>)Mlz%+|r0C&JIk|78S?f34kN#4u}X zPRL<3P0f$}uG)6(`+b=%cVs9u%uDs2Dk1pwYx1^l=RbV;qB3#f#8nz?vu8^e78NPI zd-v|h*|WV{GOm@_Hwd1Pk`k<*xlueyt}3C&V*2cL2mkrWol8v9-(3Ii!N32LkNxR2 zc{Z*4-}Y4%Ixo&G^|1S0oN|9#zelFeiuH5c%(#NZ96raz_AFOdPv@7e`}=9;mh8(h zY|A`KjAmRY@_rSOvGr`_Lr=T&_P^4v>D$^}Kc@cw#mso#P|GXdcq@$*j7!#jwKs@i zy%F%k&0yERchz1G%z0ziCeHOr78d^bbDs`-i8b%CbN#n>cgOC2lwf30b?@`T^5ef_ zY%)2j^s{xYvRt_OyvZU|_^h(r?Zb>djF;C$#`FHUv`uZk%?Iz$pF8hmmKpGH%TJG1 zy`T5|)y?$(DNiaYzR9F#P6#`q~ID|g1|sh>M{4zlXWC(fpR z8Vj56a{Ei}3>Ut1JYAd}K0~Yc=)_B=drU+bQdewRWqD)%)MfkQC;h7pJSEIJL8$Be zTwf=f&7afRt+y+Md=O!q9Cu-h$3iCOq{aI_Uplb-uk{}>36-vI7vhthO!M1r>=$-;{}wyEum10m)pn`7&VHC3bxnVIo6zj32cJ&; zGey7jW2YLw__94y#Wi25{7*^r|MyUXL-OhMpadoVH<72-ALX8V_2BW26VBHcGt3Pa z{Kczkq+on$l6dRp$hbd;i(lMYFH~}G>DCj|g`_s=TmMkA{`OU#S;|uNIq$=Hzh*z3 zVpp4o;&>vml4BWbN--LPG{{k z<}LrUz<+i|Df27eNxV!)+MD~M9kuQ9c2Dd5*3cMcDpGSNMn?PGmH)Rozt>;du%rC3 zlgQQ-cP5FiA09UEcvIItd9v`wj~^9_cFyrw8kCfuzdmb1`Gw^B;Zj^zT9+Lbjmi0! z7pS%16!Qw3>Q!5Bu56ALyT7;QO~Hes&C}<{eg0Da^0n+Avm^RX&Q7jYJl~YpZdYBP zZ}Mefd`8Egu#ArTPcKaG&u`ts@r`rh?>QVh>i-_GjbHyaJa2Bn-RC<~*Zuv|`PVA= zVc@j59jz-5oauUS+4TRU1*}ng!BypU+w1QgvVLwZv*Yd4GR+^)>h6pGJ1)0}$42ne zn|mLZpU;#3!oPFl*E4e`bBjxxuL+mp7_2 z-TNWC^WUFqap!k0zov6@OGb(Lsl%x+RO326#lPcuqkDSunneLK<~46(&^jxBd+*=5 z!P#QAd!Lp4m{{`s>htY0b|4rN7vGTirSS*L=>(!rv(;CTF)Z%g5W6ygzxiIsDK0 z{O>#7Y)m@0>E&Uc%^LduF3w2br}N2&vDZ}h(B1X9e$Hq9oYRdLezW=OkI&WYDf%`2 zYkNvJqtz}5vP5Y2KT??HEu}^A0 z$~qoZCcHQ;?(a0;zFzLvr=O26h@YR=X2)GA^vUI&v{1q8D2D@UPk;ZDAGfRM@0{oR zf`7-n5x>oM=9KN!*y?4`e!cH*9{Rp!_2bRe^N!!Mn|81A|Bo)4KR@RRJT1PtxZHmo z+n$fMb$@^E6`oh_XQ6-diN(DBIhWek9aHM-s?nFPIsE+H4ozFpqZey;1hV9vZn>6x zJR(=T(`8SVM(^w^cRBxlYkgoQnv-~K>)z&VJEv)e*6{MI@!T}abmy_cSAl0ewc~8P zn;t%VyeTY(nc-Rdl=VXYmLxtbO?vNc(0cjt^jrP5Ik~xWmETYFP;pV4yfR=>O-+r5 zhX=>TxjB#fuW&HzG}+Vh^JQuzmxF4%{IRW+WoWN{F>S9xpo!Df+t;()6P!6!JBDY?)1NG^YL#l4YG6eFZOKw>uP-LtLRzD z`_Wr6it;ZW>a=zJe5_Plcjm3zDKEd&$<9gplE1$y?f$lIwQsqX*Lhx@#jvX9&Fx)R zPtV@Hcd?yKkK)Oh(Uaou+pE-7)x2DKeMW5AjYJQV{Zz-R3XZ_c{rOMH}&TL)d z`8<7z^TEejN4z480%zG~TNYHCJ5b$!$C@0l-uKj>H0TRW3Q z^~;xi3G(re+mId0;BfKjx5u;2&dCuG#SxTXKp! z{#UyCq*N@kyK?ksYfZ4tzpqbLwf}!7n*2N1b%Dfl>wgzb|I2!}nMK=fjeq?#`1jW0 zIX5;Relzi|D|b#+mzduR)gp=e-dieyw4e9nY)^c7 z6R%XkUCJ zdDx|UIj_)JsZ_ODxp%#v80_4iG4XD~#W#huuExi{2%eR=9d42xQ-5*IM`oAJ|KDnF zl1|r~m3BAYB=-!%#V3Yhi#{Iy-J#aMQQ&5uw9YKU!WAd#J~>?cv$EN>J3XT7nZKmQ zEYr*x8NZGQF4DZ_?2~q*@0~&IoeO2%X}$S-(=J{SbN*eXx!ASxdX>NIErZG@+VvaH zU%y@_xIcN{lM}Y0(myQ?-*_I_9ertX^;sY5lqd6oZf`E_UT!kmEYaolOy%EOHp|~! zeVAvp+@hO{t2>|hzfq1d*tk98V@mPGN1A_KyO;AMe9LJ|WnX^t@U8XptT(-lVt;M6 zDD11GrRjksSH15i-wTv?PV!I-j;MF9_xtnZ(L3+`r>l*%mVa^0(ef{4khR}me@2@> z>-H|zg9!_!-449FTtMA+je%)`)jZoxx-$fv?%cVv>C3$7=jGL%{+l-BxH*Y3$X;6) zQxjV}&+(r*?`u=W4u&<))#dMAHoCeh zbmi{q-_suZ%iI5vl#%)4eqBTFTXj*#n-{&)dRJdxI&Y7Y%u+So{FPb%bfv;p7XQDs zZSj3OmZK@h=Nyu|->n(9jYMqzyQOEf+*x0o*M3tVV{P%~+{tv#{hM1;PkP6H3}(pP zw}02)x#x@RPWGQ#@hNP=;x}1RuBr?nHv7vzE;+BCzu&Xtx95>0!-=P#TI%c9xvIDS znE(B4`n83c?r~498Z`Y|Sgg;n;7QZU@(M&-(;$q zFyq7QJ)i8w0@g>(w6eMuZTerfPkGm;+WQC3Zf<8*ZcfsIEjKgM%z2%?eb1S% zj9$C${ZZTF`}c7F`?>u2H)}I1%OBr%N}rX!da2ZZ<=dODS|?Y&zd4KbvHG2_w`y(v zJ@0=rF*rW%Xxy$1rn;7?9Brj>dt!jJgZX>zbS0Cg*Wi(l`WEK{`i=knHxmk(tYF?2_p`Pw)^r1tpf)7>sEE`JOw zKR$hYdxz%af3lvu&y?ouEb4tJ#IVY<@9jB(^ByWfivlz{f>x^7*=gp6?{nYdyXW0j zRrfW^&g-YlKRsPDY`)fNR?B$>SN}Bc`SGzPC!~UD@ATX3^X|UP?r?K;`7zsKRs4qE zGv{kR-`k&ePxR~4+NOQafBOD>^ZZq7@Rqy5S=D8a?>NR)i~ZHL`FL;Y;+y)*Ckb`j z`98x8oFo#ZLNoooPV?O2cZjt?x*;~RN0z~?@uh*i?16+=A6EJGYACM|?=W8*v+zpC z4~x1_Mc1AL-pXS5|3x<6Wv*~9!`-sKzVA<_qDfkXy*$I}JLNm~8XFrci;0O@F56*kVIkn| z?haa!W@Br6a+>ZsuNBG+B9EUqPtU!&DAIfWYVrG(RaHXe<>jF5A~m(O|2wV+K7abj zOl4hudb02-`&N@n%n|*Wi43V{cbl32`|#(~>^ZYeKkt{XsO(hQU+ZaRbZWDY_s1D_ z=Nh@5YN;GhKb`yh{Cul(Z&&5AvK`vN7qsEa>-F&_iK%4@>udjiQ?)FA7jrtpWr=M= z8pAD{J&(UOo-f{C$LD`ebDpQ4m%{Qg{YVe}w@GvEd{bi3+F{YNspHoVo#T7f3ZA;Y zr)WamaTm4eI$ypu%iSMnQXJtQ0cfHeK7i;o< zrOh4N>L=xMuh0AY(-0-g(h6PeumSl=MG@q$+q^o@#0VQJQ64VbY}8M zuX+&O)M%aWT)EPuHZL#3q_Z^E^sRz^<DM_ADA>MMih8ZB#hkId_VAwKS=@h2BIYq9*zs`7ho>HWYI-VJ@bhEu zPxHkb&PrXk4P6#uxc$Wm{gVd|9z1gA&YT&uW<5Kxd(GOlosbD#)pO_0rJR_c7(S6{ z>oKkgN(`sU-{xHU>RE8Xe`ADCO>J%G?Ag+R8X_)w)0cZO{}u27 z0t4$VWo%w|-`=iMv1Q3Cn>>vt#eqW3ud}Nzz1Li~+<0MDR^&RLj|=zLr~0nnQT#c} zNpacgZ$+oV=e{VPy1Z#s)zKnV>)M*nCeaLB>nc}YJ3pr?GK%@dMA@&3majbP|C_XN zz3(bH-_5*YOWwSz9rN#hd0*(;J?~fCFUDoh{fcMl1nr}-?)d56 zEm7|C7o2Xpne2*6JrdBpPF_U6Ug}XzbM5+!d%-_<*nEHdI=y*XaH2m`(t$5A8vf@i z@|X>DcHDisIyf%FQ`TEaYUedmmoML=E^WD)C8e4D-(hd6Q~FKS{^vE44}4kn#Y1a}IA55(xP18i zucBJoc@yuR=&k?tKuzVyjk-;IDY;$?z*x%a-+5=kL$#y z^RXNbJE!?(Z~e8XM&#_jy1&1^@&*;Gk2cb0@!7ni4>V-6b=frOX}*>dmU@3l3<#PT zv})b0$1g0`_lvkJ>SCDn>vsq9rtH7hbY}maQnhGT@cYRpr)*>no3y`SS?{}C@9WFC z8nUL@-k#xBUniRX;uv7@$bv)}u9F?#mna_w0- zZ|aWtjZ5O@O5LemC2+cUbDB@#FX<;&=43jnUF_+5B=a@8_x*p{==f z4PqZkmkD;STh5om@k3fKXXEQd##gGZu{3Oa^s)DQ{oy_A-(HqXNR9|uC|+$Uete^_ z@S_szzUJoUuSpT0A;$Fd^i4-DUYxwnboRc`8Cp_ma_??4m1uA2S-U(yqa#F1RZmZ^ zs(8&EtM_s)yf3t5`qy?|DdyInSO4#eBNIb7!|J8!N9B1ZzHfR`x1aG08*^kX(}KHe zv&H92{;ItBWKYN5-S=hwwMCw1Kh^}7we!9xJjRfv5o&As>FH_f4r}{XC&wd6hA-1@{S?{j9eug- zRqgt#6Q=Ge%`x^5UTJJ-?*UQhzWgorDn($5Qi2W~r`CIIb<-%**X4qeB zKM=7y>!o+r!m@?g0g?`HGlh@q-Q8QgUF&P-(i=B!X+}new+Qj&9Xj7YZ9XlQ-b5uicqUrt^0RKuhdRj;D7kg;ls_KJy>UFoBuAJ6Xj~D zscHM?-JK55QlGT6G#90b6CONBnEFvbUVeSiii*n0RLLSE#b1Jsf{F0c*lVE5Y{l=!3C($_MgxBma-Cf6GW8&lEl_uZq zVm1(OYwcfsN_&0G!ZRIjzAQWd56%CP0j?zh4# zL$o@5)Rgn`@{U}-Jo!&%#Z4YpojK2|E{ZIgbtPae&w+@KHXp333qTPC*(ZE@OQPcB zlN}x^N}wj0(f`ltHv1YIcVE6bAjvYBjeKc?NQ-x?dIHK+!nW7 zrokjc-C~y$dVWD=l`jw`y=69&oDd6Z1wxZ6?@Fj6kTwA zwL^kq!TrbVj1%h*&%C*{(zM$D>av@HzTQ(c%)X?bi7$L|vd(-4aXk4&$wOx@6XI1KYj@C^Yc$l6ciM6tf}SYZY;R>#jyS01E=fD<1YUyULJ8% zU0q$c)ydICNzl;TTsFA4OB1N8k3{dh_($`E%#Wg4XW{bw24=ju4zw zW_x3s>F2zQ8sXft;x6YMo}^j*bI<$h=Ocoa6dYt`Fk2I8@_3=*r@PyNlu0y10z(-}5a$8!zj%=Uu>l{O8wrGo355j@14C zq!_Gd*y*xJZN7~7xk?tcPOl}$rB2yA`10h#?s8){%ujKZ=a@}OmTs% zwVC3z)RA-dk|i!di?fchhCDD`mT9wAf9@UWBfV2*&YUUe?R{EjsnbRgK|x2*>fY6> zwLueuWo2cc9q1C$(!%26({;|-cV1Z=Sg9>h;SMT*XTDze@>Tg?pSI7dpP!qz>}Kff zvpeM7A!MxNzfdC?5EeloXy zzRBOQX7c389$Qa|Zexrncz5I7^ZMg+CVO6P+j{54tnEvU7JGhnGi6gx*`(h#efsoU z^`ITM-rn9xSy`*BHcKjk;&-A)hl`S;ot<44>m#mKr_dQM9zAmM*ZJw4sMrnWY8o=xqNyrrTWH@r#TCG7M4UYLpK*^p;j?Wdgo&Ghc>4_>za z^>g1`@@(#5irKH#yHK+tnX$*BIOX``{SVKmsH#qs3f12HJ;Zoc+NG!0j!s@!-#uql zz`~}-|2q>8`buV*9z1qTS$E2|Ege(i*G8L^EdR7g)wlVw``xBh>h4Fmmbz!o&fk4a zm+w-Pf9<*8>{{1K2Hmx~)$1;qePsF>`eVo01c@Izvd;do+fyUq{;xmdG-o9#zZr(D`D))w$ z`!CLo+i;elq*hdFiCO)%9R|k6r>6)Oynpw0$xY+sZhSAUN8j9^ub;X;ZtoQ1v@;!C zyu7~KHf>V+_U+rAfJ8a=pT!HOOFPwHIGrUoD}TQ6vxSknt7fK!zcssZIdD#}N4S(j z^W^C1sVg``Qc{*^v9|UGxwyDYIB~)Qv?9<)O<7P-P(??l=g#!i*YX*9e{5mD@crcB zhMb4@-4F6l5A(#BE84yRxA1?;-Xtuh+_4SU>$z*`*&R7X1F?^RY+ou+pd3&r=L8 zoT`0MnazCQPwWlnIGg>4OTSt(NHeVY^YQCq$2P`m>!QS*WF@XK9NWiHIV1P`6{q&f zz-Bf+j`#P^$J|`Me&?mKPfJc5@8A4&%l+ zwOmpE9)51)z{9f z_rBdW`G1?zhBr&ndSCAh=H6=i^~d(CTN}RZc#{$JY|kmpSM%%t?c_Zm-N14{li@i- zjBenbiVN-he-7sR$=&=c$nz^8Tx-MaZCPRd&;J-Fv*<)we79zpIqhe>cJMNv56Al- z?s=|%Z?~$)!nOy5y_qBDb&EzCJ!r?lUF5&03yuYX5YTpW8hq9{PS? z>)wZbTWtB?|6@w<-l`>9{>irZVqjp(i34@-8Sk(ZG@kp;(qPQ6gyG#>%hDe6SBGvs zem8%`q>FQ3*YfU}IH^4cavn&?M3#*aKA;iE)vL2-r5l($@hm$0tJI0%$A#kOya$#C zEOc_zkKgB0R#ooT^XE9|Y-r2H__q4H} zpWmuOZ_Y4r8D}7E*&Ly?Cud%<}9({dvaCKZzP>|W3;M2u_ z=2?{|*?*sx#k#;*`tdR0P0D{O4@=!GT9p9`$Nf+BmzTXM;C9cl_)`C`xy@Cts(dQz zg`7J(3UB{dH}}bndmILL_wK&59#_U(GRKKxG!X|WBCy!3bFhHRz-DczrKIPa&wzqwbLtwFru z?-lN6ED4el5|?Bd{3_qvKP)YovFz;)X_Kw%jQ_Uz?T!(f|4`Rsdww5V!91;VdI?f{ zH-5g)`C!ZOd2{!yHdpW8`la#T!s%D%FfHfL{pz28PyF2cYj0NNGJVZEpu>_-$gou} ze&3Q4FJ^(xAd#0}zv^jcPfv)m>f=lM7wgn!M73y!Zt}UVGq-ly`+aYU?+c!Oc)wTX zU+JxjLc_j}IH{sUja3>WS^R?4vD{;s-%kxm_1>oRSf z#oykaY8EbYo>RTbv_Wro?A*%JE19deEk9k%erNlqS^GUylqRofk8l6CFlh6t#~U|n z*|}ogEcfIMd)I#|QhHN5+bq{e=g(d3d(-aES$VB|#h#q=D;NH`oV|S7OyNHUrT%@E zo0p&FU2rWpTgx?*q4)Fi)7AmEnWDeEE0W^*C2)GquXFc<*8kaGcW46_N6`#FnR{Pb zqb}K6WV+lm40ojpY} zG>Nx%TZh)PwC(HXJTm|Pf&Zjyw}>4(+rtdKP?sH_=QAgKKDYLD<=OwB_TL(hg;x`# zgw2}&EdV8=ex|%X9@+QG^Y8m;gsgZ_xT5^(I%ntQIp&XJOt^x$9QGC_AJ?02oA<&` zyW4L0@2_v_4zGz$uPndp=kIGh)5iF1%BMS9CZGI#PS)Dyea5ACJ6AaGe!htBZQPdp z``auD7A90UG`N|X;sSCJq1x`s{b1w*e_k4 zQ}}S}f6yWm)h=;MwuIM9H@h2s(TRO&=r3>Yv54zum4U?nYg5*<1<}pGiE)LVUV6X zO`l)9`zZJjBx`G7$f)Vno~|zkM50Wx_q4lRj|!fb%W&Y!saE0l5iB-lvD(I80)N`= ztk|gZ^3$1fZ>5dT81MRaYf0{B+bc8P`%Il0w=ewX$v4u|RWDxgG?=&UyoUj=`twW0 z``8ZL;_3Sua`G(CWk=y-kC~H>UMqN~>Fkks zJ=JByv1Y-bUr{29s^qvU<0kb5%?Xs!bl~G{CY9GYS9e%t4dh5J2QiqIY+8PIKCCu`l!4)Oz0f z+zC7GTDlf5>)q?F|K4xQwneH9``+KTd0xtyQx^HRlWVu+mU+vRZ9|TIF_K|R`1f=3 z^8KGH{THl%V;*Yt>mv6y<_5<3c6%O~|NnY!{))gv_n)D+|Hz)Js;YVXd7icTx<89P zUpN1<>6B)`stUo=@%E*MX_UU;Ug&PQy*Uw!AIb9`Uc~owqu`fK#ml^o z$1%t;@MZKgGw@wDna9nLmwS8L*X7O4%%IaVjAr&6Id*K)>+2z}mv8&u75?W(`Qcrm zG5=(Jo}YVHuU=Jnd%m^iv#tM&_RlUf*|ov-r{93tVUHrNwUDrjV8s9if zZAiOfZ7*=(jI;H1tsiH8Hs0^OA9B-V`Rj`!4(jJ^v-3VyzPqk3xTIjAQ_`wCQI}2T z_g&Gp=Q*%vu621$5p>n=!Gnz*N0UP5bMB1sTN0FcOYqin#XB+2(@gH%7isu;db-b+ zR?{G(?waSj>UNsVGkkWUXCcG0`PP*xhmHJi*X`%zPTilV5E|slprd5B=gHB}v%~Z& zoSx2Ql{j+DujK9Tz@-^3Z0(|7&)mLXH9_>c-n<8@&;4cWrM#8Zi&tK+;b_?SUgXca z?CZSeBzG-8H_z^5_CJ2+6rCe>)p|3ly;eThnjRfHE#1Q}*0x;Zbdi>w-Ml-y9)6zv zPIdO7JPutZlip67IUUY{Rqv-T2V_pDTpkvE{p`G&XD@#BhM#|D@us$9^OI+h-&dP2 zWnUj>xAXa|^Q`^Z*Y)Lgls#^0KY#J?@0#^-dxaFIv!`|Ui9RWxJau~Qmx|-7zdniB zn6quxbrmzSX*P9#I@Zp9eR}0rla60qhfKb&Tl_q3dPqQN_#Qvk;AdCV`_^yU^QnlT z$31d})xYVz9B0$~I5|HqN&0D|_vKKwyZ()`+Ugk=A8Nx_i}{|rbl7A<6RB0c9!mKdgeX*V*U%0E%RSG?faa6bI-}hRU7!0ybO(c{{M%g!?I`R z7fG(v+qU&|{N*bL&QS|^O4b%t zv9g`N*Hgu4UH10Qyzl>{&GU=;KD}4q{kPU3bvnm^6VLsdDnz5--`w_1w?X%9w7Kmm zb<;Khr(NZl^%K|0a(|8PeaC&fW3_NYq2l-azfVlluZME&dKUX~o*8?>w;TUIh1;E< zI>+W)v(%h58*fc;najFvs^J7VS?fLRy%#psM6)}r z){C`TebT1YY2wSiTWh0DE*&)%%?w#0-QanC9$R`u+LcwI+E@3_wc6DGx6LlZ@vTh` zL;cL_3ri>0n*2J^RB>f#SAg&-f8CWjKG|E+&MTHq>)BP2B(8sDakP2{spe;1JO z_;PW|{@>r<+^S@~pPzSmQ)Sz`mFbH9m3M=GZ(CpM{$6t%-G7kDAf z&vtUT{$7(=OfR-%PrmGH_kJM<$Lg1=7aHG{8dm-2-cb4H>#HlX4sJhit!Tne%PPsT zh2l}$7gw8qn)SasUGdEy_dxv$)2b7nF8&N>P6%3^)hfx!IdgZukFRg%+e34x5&i~G>b&6UaR$soK?>zO+Iulm^;x9{V zEJY5eoIcomZe7gINuY$r&d#2co4eLY{MFsn%UeE4?*1QZZlV8l>wiUmdDS4+@X7U` z11kfkY028YzPf7L2DhtTyS2l$>X!wzZZbbLUHftPzL=Q}pHfe=Owm8y!!_ss+JJRE z^+!LY=7+9~dFb?2YiggUW=w&0gK6|N%QQ>dlb0?{x-qC42GB%j$O?UkSgm_;AYGsC3hLfm&0ova7b7+Oz!N zt_nBbXIIw+=DImC+0QgTpLfW1)~8Ez_pSbYFju?Mwfo-Qx@jD24F{W~1VdlU)OA&! z`1FOPe|E@%ny}_~@#-fVx4!&#C{RPh>UF-8^E|bwTA^M}vOLKvkKYk-xE~uGlTx#9 zrrY{UcQ^0an*C|t@?$)&%O~CoUUp@}i?T-z()+8mo+P$C4VnDws`#~)k*VcdwM5T{ ztO|JM*7_;+kJc1@@6@2oFtepSpHly5hiO!=E;?EiXSyovPW&1VMRuv&Ot15;h)YI&pl}mzqv?nwVH6MY8A7mt5(gOAk{A3%d0|WO2{u-cquG|L(-|%HBgH0 z{l638zk2_)uMArowIpn9l-81ow$a!3FOQp&cjfgBriPjCd%5>~GW3_VmvFos`zydr z&-16U`ErMdEvcW`;##xs@2~X*EfMIcI&kyPuY3G|YAVkDf3nee*R%7w1!6nb&6&B9 zsnFQi7&M5Lb?*Dq&&N|{No6d2e#K#1rk^dt-g`Fn6SUTwn5ngWd3iH5JpApUD-A!~ zyWKU-_rBn|T)M{L`g%6o@;ia;R%%i~&fBBiCx7dfXJuE9j*0@8nGYT~+_`h7BSues zzFn=?veuK$D;M41b9kRU{oKb}|C@i`Eq!Y*-nK!?bOPJu72U$Vo;O$%{H2o3XQ(x0 zXC!`gV(6#KDAk^pey(Ea+#-}=dJL#I#b$Z|9;K}K0e{L zyr-Y<+}~e6@zPSSyk%}>(N_1JrsS_;c(Ebr+>*n){>ABtEsxHTm6vzdnxcL7nbr11 zf39&jl)qf+y{F>Y4aM&~C-;0^J?+z^$~pNGezpr_8NO5&grCa(C+;u*z^&+2z`v93 z`xW*7{?F|FGe=~~Ck82*oBJw?lbmi@&D*$f<2kEI1y9?bwDG=*U7CKh%}w=oz|rON z=f9C!&vA2QGW-6Nl=EimVoUq3&-^Lq`RV!j-E)HDFUmQ*Z)e@J>D-2UE8FWYOpLQ`MK$6)?JI;XRXa%Wlxip)=83`oisDH^EEPw$kxR_=*pO)6YwmI}~3!Rla`Gfd!Ud zmdANJA2^;m`=_bi1pE1}IajvtUtFusfB4YNn~`7dFK+*`-(|0c(z@p#kALTgdu?#N z?v`v6gT^I}*_&EFZDlCgTlx7}wB7riZ))w@xc2S~iI^=R`BYNoYx8}(bK7Pwvi$FK z>)HG2v&O+YU!|p`fyQh*T$G$R6fYI4-#pgx%ZE2a`&HKEHUCt6Ph4(ksW7VRi3)%F z&*SB)*p|fyURBlQ`R&-H@U&g&%cIAANndQjm@X{vJG<(ylbrpZvu>I)va+31d-mqv^OJL{KU~+JU-5ST*&P>m{g__rCbGnD%B?FiUOJ2JtZ(|3#W?|brj-fr`~H;u2){^VfH z5WA;8m;c%4nEln|b;?Wi*}CV?n{WO7^m4vE7ruVa%gb}o5nCR)<8MHnd7oRx*_C@% z^Dc;-cW0-rlG2ZpdtM43OYwMCIp6xE_cL3bFRA+z8EV6i?{TYabNT<{6n}2!I~B7@ zhh3Xb_5>Zg7A(phQ2TmSW?A9JiJ9j-RfJx)T<-1bQ@Xo*_OB+#%%sJO&#o-GcI<@4 z`3dq9|2+9~Co=fmvW@AkH*I%6Ep8RR_U7&D@Z`*_^!Q!-)ZE-E+1&p>5Pvv3+1hCN z(<}S02%b50-D=L1>vyV5v?4e@e==6*lU-0DcYyn&myVe5OdmJU*1gS}H%r};(LetD zI!DlQx2Lrx-tDfASH-8)IKEnwxj*smrPH&D_v(L7e#(`-M9PJ?H|qJTVD|0HUsY7U zJhSk9!13dzEx))z(~qidKAxxgzwpz?kAbBVd;fvb`svp$wvxFoTyH1-+Mzi6XXTYg zo~>M>W*1Dvd|6s-uB^Vq(6IB<-|D!JPeZk*wKh2FzI0?we;ygEzU$Mh`WP9_@O5u~ z^_=dpeSUtX#+h6Fc|lR- z>L67m`5=J>|4u$Qu{8C`vlt0cMw8v@yMJ{GEQ@cA(Nh=dbh-N1!p?41f_k*^MBJDs1EM(RsTF= zX=yprBtNEJeM@<1XtPAfzRH8E)l#mWnyOfGc6Y$yMXU{R`f?{L59;NY-u*F2%OrNf zrPHeNY>7C&z^1mS=a2j+l>9d0lukP_+>C`kzrVd)Eq4FscH_KF{Z%a{QxDqfmV~&*ZqkmE-%(r=x&4{2M9DJID~oUT zy2)q8kGrFm%jZj9PftCzePduR)0M;59ICz*?6Q@Ok~F{DE^^}RHiljD zxAu2m|Hsbu}%MRw9=ww@M z`v1+1YZX~VM*A1!%r?vAQ&>7PO_|}?*Q_wvc>?FxCsxd#XWN&3(m8E*i0S*3OXtk? z?%dq_!^YNjtCaZTV?8@OK3}}8ywqUlbUbht}Vsw{kz!8 z-A?Yj(lvrSNnznx5nn9IznSRItN--E(S|=?HQGIt#bK#gZdB(Kuchad+t%st=6BX`DH|Ja!= zmknnzBGxc%^`PsE>SUgWH-w!}3=Gt6#{^-<%Ty zYQn0kt1C_Q@+>GY;N;{~oHuV?VU_S4jzv;`^%q8txgPrX{wWhAT zmV4%fV0b3WUfsLJd%tT0dM{lOzW9_yF8AFfj=p+!d6mp3?k9ad^_uC$&qo{Ub$;3} z@?AY`&w_h(!RwxXyg9l3V$HnQ4FxZ2!kuZUsZ*bRuc`PyFW1(- zLu&O~#u@gtNAmw!Z_lq>o%}EB;Spx`Z?O+Q&kIjHf8*!(=S%8dD4R~uE;(c0zCXND zNHyKl?h+G=@wv-|bf#cn+1v#c`z_#FRPd~AJ;MfsI&zIunt-`+6GX@9+J z;qJ1xQoGJ(UcB&j_4LSh_jhNXxTq}0>_6Y`?)xt%AIrYj_0ns4lKz1|CA_b8U-)N{}rZ&sP-F4!M74j;t zj`M#~o-6qEF?(lUmr{P*UY{jiDe_ffUdl@uwi-2*{r>jWbGzWI)vH%)Wj%cPa^<(p zD^7S!GG8wkEuG{edgT~H)xBva7d1CGd#0qQboTe3H&MDGx7|12Sm|?F?%g+s)Bo1H z)Tz6-PEg^NSf)(z3dqbNRk9&amaHJMen;_xHC~FOd{U`!aK>#j%{i zU3_!-=M_0^WAHH^00Z$^}U?C=y(Qew#Ib!1e=r- z4^(eGi(TR&==@^oQsb$M-e$FDE)UWSJm17CC?6i06Svsw=){kOyM8Z73C}n)Va4*5 zFC@NxD_@WqkgGLKKV9_v<hH4|d@-@C%Cp%uUG%!wWM|NN5d z-6&P&c>G^_imtI$$fo53R>mzF@%#RC>@I&V({eWo)#KFNdWfAiylYn|=0LQ2*I?7OpK%e!?w7g`F#rf)j%dCjKfPV!Yx>TOl#?siO# z$(Z_bxlMi3OS!!rR*JU+m+oZwx@$V~g)L4$KPmq>_4DC0=aemRYxGN3g}QTX3iZvp zz_X|PwUxeu`1@}0x{NE0ou{U2TfZ{*x17p$K6Uw=U+ircBdx_v^Sqc>)c?EjPe*yd z&0DuXi*Q1H!y+OiKx;gLR+?O{%{I||^jY1g?#zjFliUh9iGZ2cu51hl@xREW_n_zG zJ==FHd7fHt&o8ddl=SHr(zDAGe|fTYy{UTLza0l3K3*j{J3qqmdq&mttM#3BwH3#! z0(CSVo3kctO8tB3aLv5x=jU=KsrPdkF4GL!RlMopr=Tm!H{T~$RBW0%R~EE*(9h2= ztE*x9^yyqrU3J8SeUEkvI6XVNk$*wrvAmESWswH;a_fKo@90sf?CrTUyWW}MuhRZh zTOMx?MZV&+Uy7w0m)LDs8(MJM{d?~2*>h{eBqb%|H@o$UeVHSAQ7K~Q!?#+0tG`Qp z2>hw%{PRrNHnTdDt(&xW|3BxQ_UYFD74ll^zd7{&J#Tn(^T|}!^_Itv{#8r$o*v_^ zzwuds`{w}e#`^!CCW@cei`!$-F!@|mx0K;lO@98xU9*IPtn_v-HH60obR^k_RclY#Wz4JVs`IdeKmB)jvXl$ zT@Ic$JjN z@bz7ceYvUa;zOrSbwxx+3+wBz53%2`zI$T8hJ=HQWt4+mD%Yq4S*eFJT}YcNygy&9 zWy0xu;*0a|@A#&A;rqMe#}7KnJIS%{um1Ms;_l`BP4`*Z@7DkSP?zxItoFV6$%__O z>`iaITqG8<(Asp0&vf0W1Mlbk`qwKV`E5mc&e-KyHx z*9STndB@J3g8u&gi$b(IWAyx0^^KfC6Cmv0-uA5w+4v__>-)2dx2AvdaJ+bG`SL6O z@0hTzHfwmtShsKGge%+fZ+~L**=Tn={jfmQlobyjf2;ieDNswd;9kk=-JsdXZ8!F? zHJmeFq8_*WsKu;`{ZTi@y@`w{DMoN=UhPbiL z)_?o(;le{x{k^=DuC5L%WDQ<(tCK5d^WWd!_HEg^RaHz(?8w1`ikBxY%bvdX@+^C4 zzZ}b}w~|!nfA#nAQ3%xzzrk|1wY*BuiodpYU%LAIclS4bY-uZas-^R$HBiFgsL@id zEnK|c`WLZrg3hoDbvXU$(9YuL9!I&JnqB<+-h-Fhc>Uwuhjyf!nVC&Ha{Tz@j*bo< z(Z~08S8BQ)|Mz^xo1L{!E%c`>d(aS_6CQr{+}kY0g4=<6r+wu5sIEG3*Va|Ll$PF@ zx_0AAhx^%1dp8}<;BDXyeWKo^8S`|}1)qig&8A7Y*uF5%4pLpo5j0C{+g!WEC$r9+ znX3EbS?5erL{{3Htk{ z^2FjLUZSVxvR-aa)%m+`*Od&-11le{U|g{I%bA7KpXe`4^Obu4>`LQS=7h3uPXgnr z%Yv)^`Jd2qUKlecYPFjB_uMl@~d-Rb_5udj>x zwAbzHsqzfjM^#dDrF`D+jhZ8}`%cxR%Fq+bK|RB){(Cd$H~*{7%=BHV!M&jJdYSK= zExvoQo)+oYt+Sh|k$WtlmSOMx{gq<#r#+gp&Z+9{D|z9N^>O>oggjPT8#g7@TfU&H zYt}{YyD>jMDX#zVX_IRA{6N>H);&6BPMU^2Y}&mhUOpo^**W5I)7yEcpIK$O>DbuV zTrpVol<^;D!iI(H7eF&fbqD!p{$yuoU(L1g&fUA65jtu@oi5o=n!V3yPqS^VVs_8{ zY;IXyF(%3!if*>+`<(A1MDprwJJrRe77=3Dzdu3NWG<-mKn-F0vNZD+rrucNYbcTPcp z0jT^xc<`W#o!z`2zkV&7owTKJYx0UdP*J!zq~(KEar>QE5vhC2lx|gAJDvR0*6w}f zw}^A|EQ_UFHJq<6w=mUv6%cu;@7z-9uWP<9d#Uy}v!z7gYajoT|9NhEFYB&Iik>T_ zYx-jU%=vbY{wZwsV!0kru|B|YF8_kSxwlN-?<~LZd4dHyd%KRa&$`kmky(s06+hW* ziawYA*M3j+>AJ%Tzx0F|{@&kLbE><(Y?n@*U#b~*`%Jm>n^$(LGF-9PQ2KCEi^biS z?~WZi=At4bIMHK?>E1V&-BXLY)xNG{jPUNgm=~h9X~VM06>}afXtwQCu4mj^AvcR7 zfpIzC8s>(7`tdf8P3y(g+wB#X^Rz}3Onk-QvVQ)r)Ro(sOtnB!)85|hWj^6#iey*V zk>f`vPFUVQ>HHiUsqGp6&a7YCGn?h|6o11Rb@JVs|7R&LWv*Ij64da2O5HjqyRCB# zQWkH^KRw&L|DfysD_l|E*Uq26>VTffjp_W4T+T^5%ii|6{xo;vrcI|NBtG0$8+~cM zP?&Z3j*nI0MMXxL*VagK``(;q6nuN#TWNn!zh~bi(_*b;7T%LQ%hs_beGgxQ9AkOD zYo->H5xyt3P`5$SEc! z=2CCMj4~s^^pt;!2meisjFc}fE_UKj++DsyifPMit2>|8Y}~!6+kNun$tMH4?Sy8% zx+=I*(D2G74HfrqtDd_3`1K2PRLj$;Zz^^N~;Vv0q*Ca>%?d~a-C<>4QDPt9~*tyqEPr1RB&GB=i8 zc@Vkna6V&J%#`KR>uXo-*}gJrrPKGT-D$d(#WnXO_(Z~7k@3qv`{#1GK`gi!k_b*vYc)4ad@_3-)nc?t44``l`rKz60zH<_w&sYGsWpHKQFCuWw%I zyp*$d%d`ud0}rlUzk+SS;)?&rey?2gW&7T(uKSB#S3kbm#r$`j47Y!+Vs6->4Ic`x z_AIo$ech|naB*+1@2)o2j0}#OI}huA^ygT0<3_}z9TkH5K5xa(&)?ko;JH%hXxqO_8t1ld-Fo)QZZ}@}H_m$>E;Hd> z_WD!nH*rqTMMnZFL%cw_th>A0%W>+-luWJZ@9%3(GBWso>}Z#W)E{FrHSc+~+dh9g z(8#>r;s1raJNJy|>Q(G&PZ6I#&$d#h>)EaT1zh>5zt-7!G&<-oF1XhB)%&`N+L7gt zip9mnmBhM(TURP8E1x{EP%J!S7w_)>%U(}2{C(bcc94dM%ff&O9UUB@R>>|dETA@k zii*qG3s*M%w`{z$wCz$!!f~y*^moU<>z}MFdhVsYfBvVOg9rB~{V;tzE7AH^`==c1 zB_&7Ctxk-%a$`r$wHF6or|0eGua-G0-ZYK>=8YQy^73lgNe_LZx0$)PELJLIEV;2e z`7WyyM`1z1i7h-zEdoz>oA0V<3+?b?&Ino-vT@=5`j5=AF}n)*qJyu^)mnM?TV8bG z#Pi1X^;a}Em!9M{Q(gIK!@t-nSGPSUKe4H+sZ98&%-$Z9ufILq)m2OTM(LTOw#K{7 zb$2`b6Pjh3{LA)K`P~;gU+yZrn-y0*jqUv3@YmWms z_SODg&&100gLwzj1DS@&41LTNY!5UVlufq2RA{J8U{Kq}Sis1<`<;XA?8PtbN|s%` z8g)e@t@^{0wmRN@cRU>JOn1vy*iJ1@zOEKJ%~RdEt8S$zdtKl@ucZm+XBa$@dhTSz zQWImE{9@ht*8W{ZPP#femrQla-WGV>=*;U9FRu^WmW`=$3`fXd!W%MQI-F7< zpF-DjPkQ_?hpWd$Nl~cNMf4dDCuiVN$Bn$#OgxKTwX9?7i#cDHt=^t#y=j-*vuDpz zZf;6dssHy!djiwjX%mx9&hcW`@e^G;Pk$cEpHq5|w$K}v47ICu&x__r_T$09=|fg%f{BW(?>0Msl(2l zI|XO@EbGeH_%f(Ppy<(!hxQi_OulWrB)j2E_w|{(Yv0D0%+R}$CUsA3YsQq%P4(p; zD$lQ;{^JdH4TohM*n930F^3ud!Z@c}qzj{^FrCWm1Gr?y(dITjYt&H4i z6fJ$JD>(k**LS*^7Se{L1t)5DHx;Y%FIP9#V#?TivhrG;-Tg^ZW_VT8 z>uI(2&HefJ{iP}`TzYR^Wti5`crni5vhDLmN6%TV*KbXe`nveV-pk^e3lw`b^QSHU zw4I^7{;RBOkfk}7xL(G}+}K}VGs<;@1y9@03JT$C_~_Anj(e-`o{Ec3parmbJhj*E z?KHHom=O^X@!}2NsY@RgIxl*6n)&~U+*_-be%${4e&xdZ6K`%#Ke=N2e&w%4+n6rA z&;F4e7dTzC?{o8uhnI62Ry>p3|Kz3Mspb?>Gi`7`)~#A>bR>q& zVe>NH?0>5zO;2d$-rVxgc!tuMi6Jl7ANuI9X>Nk{*4&FrPPdz%H|pJ~@p-ye{X=KZH!S6@17Qm!9|f7OTHW z(b}z_-h3^tp7)`$|Ia-B-Ou(;Y`PP|;E>F+hx;4ut?bXa@!Kn*0 zLyyg3dhy#-$!4N}+R;nr&gp#)WNCld`0_;0D+a5(yOipVJ-41`6HwdCYP!soL1$lG z-SO`FYdW)6dZ%Td;@Z~kV9C&X=+C)5k3ZkDy?wo&{ej>9&ekVuyr!m{U3c!)_pi&# zJD=z;Xm>2ilbyjSEB5dd|DI>>Ez)nzpAg*U^yZ#9L&Cq8&euvs!o$NqJv%%5NfRq~ z72^#r-pXJ5<+7T~qhL9~D9CVs>u5@+!|;|3;Z`d+F15iOF+(W|?O0 z5WXd?P-OdfZ=7B2fz!tO>dtnBCv=6LUGeDF$wPN?EERn&u6I#VT(@pr6!#rvC8drS zJ^!bipgv-0*7aNS&iw%m(HcFu=x_J={*Ee7iL)oqWNb|FYn!3Xn6W$e>zvIu4=$EJ ze0Z|=RGp3UmzmADXshqZI!ACX%W38erTxXW-WSqlUt4i)J^Ry#e$KyU>G{9T-?L{= zNNbhR%pTC;-jbr8o}Np}&Su@V_&r~kK{%^#24^yx?&IC}=H50>w%(roENZpuVv+Mt z_EcP}{p|Ja%*;#aVJrbhYtOFH+&FPQZ`ei9_Q2{pAuD&pu51cocUZkKj5*}>`zKGP zyp-x*vP30l|2DsQfs-rW-?w>mb;|>Z;QNQJO(|u#@H2jO-07dEavmQmEjgK^cmCP3 z?=_MPU!UIF&Gci>_eV36?TeqDI{Ix@!s|a-7rtI;$Z#mVS``v@WznC=si*dC`r@bEB@*$*hAkx^!?)C~JnQ-85Wice=h+)cY`o&_ z6`0F#w>fX_??sj$|K_c}e*n~!nGn<`cjGMgU3G&4_L})|iCDUFwq-i_Q9?@gvcR?b-b;d1tkfe?04*U2bgYx%cPV zl?yJpznFNt`dG-b+ApPoXL*m{qNKZ_S~|(dSLQY+farXGPfU|d3|PY{pXnQ=Vhkz za)b8Yir9B?#lpY4H>aO#iQBc+Tz`ha&+sqbQ=G%zr5H&{TILu;pT9ECiv1O%KQ!Rirl3j?36`(nLo{)dR;-Su&8 zb{^|9b;ZNBi8NSk_giCm^7-6<<#{S1dLa)a8d5#(u2$MVZBEHnB`U8CaGOVU)V;@IM;f+(PlfNl<=;gxz)DSk7l3Rxg~S2vq5h}7mwzzqq+Ys z|37}cf2H2ci_TT^+7ll>UZuE{h4s$E)+w7Z7km4xjWV78Y|DhI?_m??Xos(B|NidI zqf+O$x3_=SJuCjk&ACdK;Y-b{@`u**pU<-?^9W~lF+Km|%}rxfNynR)X7wpfpX@Jx zcrv5Kr7Ko~qBm;a-P<#1;m^$<7O!;r{BE~>P``rpf2CW`_UGPxlw5P|<>}@8caF9A zevzm;vsf&tPW;&I*MEKl79`EH*||N?-6?#D!}1WWVR?{odU5=A&lJ*1G1E zlWy}l%-?4NfuduQLTQJ>tp=^T&j z)w9NTzUG%FJZFl#c;Lniji4O?jN6v25$=unQmM25PVY+MNV4n zd3U3x9?OUpp8W0X_X{f$y=4Wx_dd;^%6_5f){MHS+5exI8d=ob5xMhEsg>>cF_({@ zc6@!Ez0TnMU1Oc)tXI93tJ-&o=_>ViKNbyCPd?tW!@;&+X_xw1?kDHXU!yHjmwpJSyMyO7qeyLqTb2ZzUzA6EiQXFV2v-JZIl&mH2&ooEO!9_&mpN zgJk{Ws_D00&Zy^QheDO9b0-iFo7%Q_vP}fyUV{Gc^tJhOL9+B`SWX~dA7mHtCpCY zpKpKvzzdCK>D{1%VvCDUmo)Fud|djeXVw|+J>}EFO$h`Yz4{u71<%&_9!} z&D5M=fB(RZjJo?Z@88{h(k-s1QdJ%A^JQO!;=@VbUC({+n-KTOZ$jLzDGGZ_G#^g- zew5{<>U);=-QvP~UY<8?pYrc)>dNv%qASar&R;!UxIO>ZpHDWAKF(W~z3JtyMSp&N z=I!i!wmjcwtK?Tu5pXr!p!e>lC)+xH{cF8`D>6Eoy&$OMwNmNfYyYF9W}e!)rS|Wc z5Wb7w-yfQEKxFmz%N-T3ZGDzz{VUFyUcBJhk@s=->sNPg+}FF1iy=yXru|g$y#MEK zL`<@;-*0iq1 z&iD3rE2nx*kMg#ib@pZI!Lz1emB;3{w!J#jylK-WC8L=-X9J$u{EqCm5D$)Kn49h+ z`TAIXEofO)&{=!^^nW?Y%j~>Z?e*W@TDqA>@ym)Z>C#sX-97sKal4CNic4th`*>w_ z)Z}^Jo32!>y0q8(IOD1BTyuZFfBo7!#c1ZL=xt_EyAs?CW~jNW`aA#AdxN;&|9@Zi z589KFm@fN!zVN2ySDQ|T?Ku~d;I}8E&1Ft z>&)*@FM0JV3clz1>05YZRWroS5sUup^s}q`x9h2?dh5K?Ht*HyVp@@8yW{qR_wzUL z83{-W`~Ld+N{Asr`Kj`?6UnmtyL!03+F5V@|Fkr1(&WjWKR-QnX1v3EdGZ6H2JV{{ zDhUrf&4Zi^1WZ|?8DH!kKRMXXdUQ0YQk*qlV@l_vwNL79 zNw;h~*5acUEGe?fDrI{{P`UZt|9)3CyeO>TxBvHbe{t;ff6rUqtYllT`1--Md!ES% zt=U|>`_@e3w>Q$vew(MIrA58&zO=aPSns!sCp_dCY}e1f|JwVX(5st!Ul$sD^~rr1 z8!GRx+*rMT)wTI=51hUhmD2L(-8~Qgv?lL0zsd8Ci5(YHD`})oK)4YJm6`(%l@kp4&Ohk z^L?0A-;g)&_j;{ktB&P~tG?r}e5vut`eVYYPLsW#|6k4M-{t(J_Lbjz?P=$)iG95G zyK05hJWkl)qoo{lV9|&tLTPkIa~R+idUB%CE62T4P!!Pg?k?M?ZSk zm#V1qpmVtA&6{Uc|4+w6Wg^$R#w)^C%gf6@ zdiiqY)^$!#1@G+r%nL~cHV?Mln|xdg5h z>kFqBu$XF{V$3M{IOmCL)I^PI69TlRu3A<$tM%LZc$=%c{`)uOeSUmj_uTr4pBaR+ zP9&Xge)nSdrzF2ROzV7cORqu5(XU<${wJ&{|NTOnALROSpkn*udhqdcg zWW+4JeE+=p$odAI+K4tHZJ~nyid-z;==<*{e3*)tF9WGE^jMI zX0VmFO$gWo8m@3rQUskmee$H{Vb(j=G1p%_k~E#EZn^cZ+Wh>EA3vr=2dgZ4zWV*_ zaQ=$72N%k&7M1#(Ui>vO;^rsT&yuFq(lxqG0?YpQ?c8a(anmNyK@&&LoayOsQJVXr zdR58ZpT>3!Hymw$h3kvA*2TkH4PntuCu)-Y|FFbCFp=DXzyoUM-g8 z@MK`{eeLPu7;;w5_kXR7gva%dCQh@iN%+^7^GGaF6k}bbc-6FraYnn%uJhUdc5hqv zSGed@fXCX6w>KZ(x5pvdEbqnw-?)F_*}*#=2%g%_2Zdyjn=GmDSKl@l2EjDY&^KZ(pdH9((d~ctN($Zxsm>c@O zz6z6^en9x?>8gzL#Zi}>dS3jW#(Lqy%=s=?^F36A1i87nw|<@>_xAQiL!noDwQeaa zO)$%6o04>O=F0HRLhp@@)23XteYI8Yq^EYatL*%@D>g6U{yWq1YAoBODa*DTbNID; z??k5fsQzWUt}$I$71p~d`SL2oGaS6qDgV@;Oj$S~>;38wEpwxH+@xvVZ>R-in=YOuKna;vyey54+(lQ2@+c7fz zpM!MjU4)dEPuADUcz9PNjZAGS4{xcE( zbxjHrJwn=C3knP-o_@OOSjMddZu{&1Pn%<1{%&dJ8T+M%myh%BF=%~$yLUJ9Th@2K zEOz@;9W<bV>MD(YsrT@E_Sw_1VWS25t*IgD z`lRggUerded3NOb`VI9ghYuYO)lU0pR~hJH|j4;rB_~1OEW$%vk82`U>A!CU}-5ZX$-kCy=9(#cHS!S$=nZM9|>zAf<{@TqlxxsrXr^YNP zSQs1P@O8n@IZszUSZ7yuB;oam{P@X6$3J^bZ9HMhBK+vF=T9Tm*aKgV2fY2?D*U_R zv{V}t+uuw5BE-ou@kM{JXZ)RS8b7x)Iv$Vg~6|(yCd^^;q zYE8N8(!0}HIZFOAE3ou8dOJB=$%Yx&Km#=9!oq8eAPWgYJ*dWoomLFW!Ii<)fWFy>0fgv|I)HlW8tibkY%s4 ztNwlAjQjk3XAO7>gW|QHq0A1?Hw%6A_H}2-jsR_`nO4)q1<>^@^;L zecJl}S1)0c6Z~jsTG7({HzHPJMw{TWRe?L-Xymdl4F0|BcS6LE9a$cl`SCB^yb6np zz0Gy@T}ZsA&9IyCO;7h@@kLi%XPfP+VQV(p_&fLqdtBU7nL97dnx890oGT^Tl zKc;o*<$bQtD5&xMz!p`39sYM z|8p&N{r|i3_xg&D9peAjMeqE<`IV#Fj|&AbnmY9e&!pV!9i}9Psh0^2h4r( z&+p#zeXm*Pe{X49AyxKmaoo>aAq(Gp{#M#`X7i>^UdFyb(zy|)@#5zTxcywGt425f zs5#s{LE)RUPR6W0&W3*v-_JiLeCUepi>x0r#Bw7or)z)CQdnvj(R-Hrn7-$axnE1Z zT~Azia;o-JYxV@u8CI=&9{a;xccr`ie5Sd+cwgn=T?R`QG-uA6*%acQsbgE*ByMo< z^YViir|7@BoZ%YGP#f23`@H?kwp$-TYhHqSZti{mS4&01@A8I(lZOvCS5#H4k`#Tj ze`DX#soLRtS`r&Mo_>*C&(tqrxZ<@p+~+1ne9;lCV%f`l?-_FpS| zwKvzl3Dq`oF$q@Mw2wAdTrgJ6?skBz{+`df3A*oOUaYI}CF|m_u&^T_M_XG9 zuMC-$W$U7JQ80u3Xh8PApCNVK;Zr`}XngxV(z>P?>+5^#%#(j{x3}dQ|9#WdZQC?$MX?+e6u6@5(#xu58ZkzFD(Kv_;_3+Qo+2pKr`+FJf4wJO5UB z%$MySblSD{)%^2_GS4qyK46uyF5Goi`m+4*Va7ieef;|F>S1A@T-WSbNr&%lUKFA> z+h)@5Pgch6{O_uLdY?WE`JQ<@@=Bswyyex6wWsGy1659|x%zLLuTP&nXO0W#Ag`%Y zr+U3VapC7g576O-cXyXsuT6gce|1|cm(8Omjiz=hW!w&aFIiY2C(>M-e)_# z&&xb`^tj0S(5vc=k|pzHrPqD5e3Ga?Pd#w`ZL4m^TK#7&iG|O;bV@K(GvwUbRj9lE zSJ#E(2Xhws*=x<1#q>hu-cG&CtPjtfI|sVMMt4)%YcsY6$LK`vFOd%eq#PzsQtjgX z`!#s?yaz8{c+8nQH&oMSmWZUJXHs(V$p?nw<5Lb^Freo9@)7K42)8{JM;frMW6-u2x6y zw|6(+&cAER*T!%5{o0-S@4Vax+k0Qm+j-)IM^bLCZ%j-~ zM~GIa@eWZg*CMxbF)xK&+yDJL>AhZc@-e=tLHh3n7^bzCt=Tzs;{MBPrUq3O&u>+0 zTDdeqdHL3tv&0vbyQng(JvCL=xGi7#Lg(Y-cNhG*)Ts3fG}*tkR9Ii2r#ye&>qnAX zzpjU#wmd^_^K!nuj(h*bt~9)RHu-px==pS3tB92q2hZJaT9$H+A>i;P|JnBhyOu}t z?fw5t(wpteDutHi_dQ?KoO$iYhU#l8Vs08W*ZqIAJ^k_V zJ{zaX#k{fi&#jZb_How!N1-=BvvA8K!r3mIJAC#dlVVFmboAsCCr%Fi2Y&Fj^e&N_vZtDHld`XaI zXMex?@qXFgd~aEQWgQLo^M3n1yP9vd_RB|)obKGcTiW)u{?CttVymNq`qQi#_NIiZ z%;!k_6`it;VX}bJx%u}0MSbpimh&=4@LFbGTVfdfb4~r1{`X4~8u#RET$|Ro77ZZkKMYiQCr_F7o61`uHUg8yDp$Z=6<=FU|C# z?D;d(I-BB}^?LIHqyOtl%kq8dj`**#)Jvpr*~LYECP^1>zu(q!{m)+i_y4_qwtro9 zeSP@eoOb{9e>T5a37S?6R_m$aOVBpDzgp?8aq)Mf{l#@J56$$Ds`P$+W=mO=$@J?p zJA3~4_4M?J1uWh#YpPdu@6*mh+5gi0yLitA&c3{B)~XLbetcXkucM>0X-}Embbr^& zd(E2@8#tbttZXc=`9I5w$?|5}j4KRt=IlBgA{%vO=8{}v=_@ODiGmKb+jisrzM5yD zIkw5Gas|#R#_r1eJ8QYhY)y>|=8bMHVb9Oc&oA{Ud1l+MG|}Vh|K@1s&Zc z+VF4U{Y~5Wa{m23)XH5V`r`Sss$==F)}Os@7vH&arvr4=Rbip$RJNl_PY1p9H#izz z`;s-A>3~wqN*^vhKDD^GxFbi8ss@s(*m&CaR-;a2D?bNBRKmWdVo8(@3pmVqXpGj08yF+ti@bUA#oqea? zJ$9(ki%+=jpZkBm`<~~eed1^5FI?*wuuf)ztdkwoq*}JG_;G~9{;&H_)iFm0r!XZv_`d$ngqPFK&X;lc zzJT4AH}mtaf0c2pKUYsb%imtLzH6Gt%g~AD-05C_&(u6CKX-k7mO)a`EAY2!m#2?iv913KNd@@W|M2jN&Q8uH zH9I#|9~4=uXH%8&|M#1)C1N*jw_TdTc)U|M_gvaj$z{uy9l3F11}LDX=&bv6Z|hR= zoZlxGv#&k(>QBVsLwD}PEK+@MEPi}KcEq-lkB$?g)})1phd+Aw(DBZlJC}03w$|L- zByOU*nEfkD>81@58`SLV=DE1Jfldcj5$e=pnk4Au=co4d)z#ZxwoS*R*bH9ZObX}Sg!wT+S_3mpP?G`)C_SJgw zy_wpfdrmCKpFefa6v^$r+VKJJKL;>0=N{*~cc}cG*xz4s++J0!iTRSG&AK3PG22&n zSNG4&ze{d!>daNS*6MaSi#a1V?_RoT{JfR1Yn$}u1$IBtzTf)E>C26sH(#3ihQIKf zdgWa3|F=iyKVKbs$8T|fEn^Aiq<1^cKcC6|E$6pmaGC6ct#P86^Ja1?SADiKPP46= zbMaug=J$}9mzww2c0MRgyJoq*>X_lJTTCxZ(w-Eg@2d`595oeG`7e{0&YWO#X3yoM zebx83ZeBI7gH`aC{`K$`jpZJFyMJb`b8oosd(AUDfFp9}j(JO~#rc(L? z?w4GL4;&ATek1&-dC!EPre>zcjB6N!{}}y07WzK_=1P~^pG$o7A{6#pH!Nj%Hvfao zELDB4hzJQoGc&ciP15^UK0iH2Ze1FK)%*`Pp3T2%xoN|OW4cjqu1vZ&dA8PusSI0e z>r*E8Z}VX7wwx>IGVR=4D>>$7pUbUWZ{9`6n6nEUx)RF5&Mw^P;xuROT;n->qJn}4 zpRLM%w)WX0iABe*DYNN&`#ow`yR$sHI`-(cUmomhco*FM`T6<28M9_BYx#8Qr1F}2^f{H4t1@5Pp zU9kP`bmc*A`L7!f*=z0_-&k~C@|6DD43o8T4SloC*Z6P!m$Y%lmG$xV&gXe~zg<6S zoHg-J-&<+lXUx~VI24)B`koJXe0NHn`}fK0KR?!-aNf^SwZ4bZ;K8BBrQ$zq-hVo3 zTnM@Zl&isart#9(LGz@_KM4SJPpGv_w()0oBT0ycfr%yDyQD( zc%`VGivGDdv7pk7|LO7=wh5osGrg~nsCZnhbvOHSmYD3>1p=F{d?>WvTRH2Lvt{lf z4N1_!{<#~U)|FRkI{dyHmTjl!q%ZW}9CI`yC&$NZ zU1{3h^4LtjTy6$i`TP67E3ZDEdU5)%S+nIAE_}bt!||VnM{D`w`u4B$J{m{ueQ^`i zsi~|K)YsQn66?O)>fQ5WNlN#6w#y|A-xz+K$h-H)k(Whj`svQqtF-9Z?XTPVlx_O?`k8S>w@BZoLd4I3DN4HgZvzwfnd|c_%?deZCIyjUdlNW}j zrmCQeHqV{wyK(cTAZTOSix(a_xw)1ror~j`BhKx#>1Euq^HHsyj`ev4b6veZdz4g_RuH)$|rG&YgP0vdvng&OV=ZLm)X?Jw@y`ynZ5>0Uv}^EqABvP zm<_o1*0+A2DQUQ3`a0uaF$d+>iOtWBeCU~^Xeoq|CIlD<0oiL zRN(s0tF|xREnQ!8?cJlFi|r453EJqy#Zut*)5vyS>TlDjPb9S6s?79yURY+uDAez3 zj9PrGwt53cWX|`pz3v59ing$q<>#)?eU$1o)xe}CrflQvDLQdEFV4^36TowF#>B(5 zD=y`8Cw#kYzFv5<_rk9J-@a1UR#*0Lt#}!#6<*@w^I&@HrM=bPi?39tJF#ZJR%+$u z{V6%S^oWGm-j^2+GQU6gMJv-?|HG#*56tFRB|d3-KR-@AW0`$rWu@TC5U&)Y$hKKQ zKV$5~J$rZ9<o zr@c9$9a5OrK1VwtnDZCNWB(+j4@bLIRKBt+?oRKG7g+dYexI6cvC3(GpUNy>UHwkn5O(|-ZNJ&aVeqG zoByTX`mu0Vh1=fCYu{{{biR6z{+vFh%RFc2JiFS>C9Y+lW7ejAzF($5y1{wh9=G6R z<)2qix7hLeaZS75TmS8ZzTZck58*#n|K1pX&#vp|zlVh-Pj>&l7=QTBB76Jq-F+4B z#Q&O}(f{>Zd;g2~>;EpQ-}9~e-$IU#e+xhK|NCfX@awnq{}&lg|E`$v;dfx*d!{;% z?>8ea&T60L$}KMOOS^4*tm7WlmFIf8-pefWj}rR$k@>y#pGU2qV=S-oHF!RBVr@Tq z?1Qzr@c*s9z>_0~T+*VS1rR|^m-uKey<^T52x83vo^V!e84fEseI{tn6SNKKz z>EVo}j{?7JUha6&(b4fDe^b+<=6Cn|`F7RY|N2*3xg|!ge;PZR+i7Oz#m&u3i|qGL zbpKx=eWItF@#6frU#|6BpZkCPIArhj^N_vPjpq}3mN|+!JiBnd=uzK#h6P`P+CSdj zveq+?`OUp`ZT-~=rx%3;^z;A8mzJ{A+kHcnaZB8;jB|E&JyOELzFZn_WwU!%kXtE-YdnI@|x;cS)7~y@|^d_2M1)T z;`e;W{JU#w`rK*yrLnt@-8_3X_xI0eyXl7~3tjyx4O-Mb(WAphO}S`ijP{l_VNdIi zHnEqi-F@*x(eqB>+;19FZ@qtaCSkX_s@kLj2M&BFets_2Vteu1b;Y}{<$tr=^0~vO z>fOid9sW0y46O8L3bHJ_agF8IYlrpI_$pq$Y2*=IynE+PL8lpYN{iRFu?Om}678*< zsWZ#CIM}Ji=DlfAdAT}QYZGXnJLpWXr%#s}35cJYxoYSC*qCX4k4pQJlao9aHnD~U zE#4H#XX$W-w=j^C{dr1A`I^J~KZEMSHx0X-7oqFE(x%0dGT>d_1<_S%I z`Z=BbVo8`cL-X`=vr80qKl}G)Vg8eyi}UU+=ij+&uKlZRPus2wp4{C2eTwHzlkcK_ ztDNrknXs4i7E_a-ubS>ymLJ}nv-fGOl4#4VgL7ZsJGkLP;Z6_Px##9ve(m8GzPGdVuX?Xq z4|_uF(xRhBZ=QV8%=Tp;+p>)hSQv!!JkEd6;`zR_sx@^W{O=#mJ-&uF zc$Vz~(AnX~j=4SESyoUGAey~7cB*mH!Fe+#IJ~;HZd+^BY^$KhD}HZV8!b0se*o+}9?>I0_6Z-fq;nVbh*=D)lf+{c0S_ZmZ_vfDHig7l=1>bk+%?s4FkhNd5Tls#z zLEgm*ebWcl!G{mMIWX_-o@ej%C;ww(p7^ff+lOW1Z9B@>H?6N-zROviq1N{My5HJA z^gzqi*N0u5`f0A0-(1UA2eZ$on6C%*mOQ?SYE{0hE&44#ar&CY!8&5Xpf1XzM^10v z2CF|_@|0t)b>;&Zt@KluR=DcfzI=Xk<-rS|e*=ilcQ+~Xa4357GQHaz zG*K%j*ZSC@3m*zUUpTsseL?t%$?f}p7(D#un;jSAS}W2Jc$n?m{i(4$|6V-&%fgVo za(Mwy1Lvvo{ED3)pPdbLTwA(q;reF`RrmJRSvI||advVF@!c@ROBFO-JoDC(LkD*4 z-YpEdHLYX$^7LK2`G4O3_~XL$&bFKT-tSATn+59+w|;)~^013RhGy-=rU_|FmKO(1 zTGsZZ`unTMwx3#th7(KPWfb*FT~TKIvMzA#s|n)g=ly%O+YU5ZD-kL$FCXe&zBI@) z#Yl3e(%uvA>g#9OU6ym$U#|b|v(@pu*>mInH8Pofy|u2|eE&aQo8LB13YF5=volDD zY3%;;G=D~Q#Eov3S2JF^+wR$#ajt&-h2sbJRHS|1_H|c<+u8?TI(}=#xgOA;*S_Jt z!2~x;Ylau!pESy^|Ct}X--U76_cNcKA1tqveDrUw-3B+mY{g#;5@qjit=!-AJ}++n zGGD*1ytQ8%u3P2b+wcuEBED*Uf@tz)@&0$N&%f;3xqCP08l}*)Q+MyKZVOb6?Bb}O z-7+O@vgks4jR$+SJX@T3^i!%^#_VkK%Y5w#33qSr6eu|M*zL=eF8-(;3I9Y5WNPlz zTXf%Dllj=qtR|SXs{DOPliZhu3~m-qmt`+-o{f0+t1apGNlk4Xt`%Gl)HrR7DaQBAsuwD2* z?fla7H#gel@Vcj@sC@kLMI|mS&P8b==-BE< zxBeAn$kv*szg1K5-*(4$^RFsgzWZgL6idPx=lc2ko8BMm-|DBjT*`EXd87XMuW#=@ z2E~|S==EP+PrZ9Pe$V~y|mJ|W@qz0CB+k;Ts3{Yuw zWO(T>da5eKQvQd*1G)FXuiw3!xA0N6Q%96|THgDvElOgHb>)v4EG~Y{@K)B#W#HLW z9Q`d^BlBC?w(SQLmTYaW6TB3%;{!vRd(D}M!z)*;&jdpZ2s zE+5GIx@hL(JjqA*YJYywll1w&I&jOj=l9wFne)zj|L)$-wV{4HcddE2HGRHa+kZ{V zRE@8qnq40!y<{)0x(^yCpFUl@v!_SJYw4tpqe+jRJaJJG@?19W@s@;L_CX7tXus0* zZukAUo^iqFrN!;@v(J6L)H?b8!7r+>{N^gK1;VI8sI5j-&zhCHz9h)0l-d?H7 zi?OSn5?&tolJz9NL9D6nO7;91PmWxCe)Hgy>azU*9&1kqhD_k$-l6++>N{o2+E3cY ztFJeFy~il=ruZe#`z<{^-?|lAR{T;Ba0+P+%shDJ*s)^*!jt*ZUpN{p7AuR@+R}b! z$D64ue=ZNLm>Mi1{(bfo-QXx;Mcw&wyxm+Sf7i&R8>~H)I`^}?L9f(uW{I6O7w-gn zT2)nPh;VKF@3-C}UTLC$zP>)_K!e${r9Xc96m<28i@W>8Fx^?3e&6ptw_BBAbG4oL z&$*Ag)9VBJYy1|M6fSm|R+zd^&;*4`5nqnPfaOu(3v3%yzc?;>C+ga$jGIdV1w-c6jC6n@jE0 zm-8&$=X7=Jzf&`tEu)xIva`MC%$Wn451Ke}BIw*&(A_)k?#F#xbwKrgvz6&K=l^H9 zckOJfKAj&mx1Tj zi#;~MpRczketb~(Am4x^bMM0X7L%x~;0=1EUy zllpb1`N_W+mqTh-CSGD`u)H5-`h00|$;Y0kgD)As`|j!Leb0Wc_wkcg&`guWJ${x;|9qG? ze@;=xmysn{g^{JC>|7S`6QzsvyL@FCV6{599Bf1VweQHzvUUh%oK zv$L;Aug_g~c9zKv#=p%cmdx65O53>bO2S%$gvz4lNgoSmgNJ=>&Dp-ceRyEHWVFf3 z?X#CTeq9pR^6>lL_aF2Ob`^X};hCYPw|Irnt@JY!?&UF!p{bZ|r zec`M`$*#G#x2ZLms=e{(nrLWS@odtDIgGwi*Y8gVul>4ajn2bIN4pPA=~q*|ka}c& zU~?7syZcw~uUFO8^}Uc`;^g7sF|W%taLSvP!D=4Y_iJ;$ZezH`Bl+W8jPv!Qn^*o0 zEWvcdcOOA704mBrXs@-H~9zwtTGDb5?4G+*d*wZC<|*TuJY z*A~-=vdSITt$7}7zIOI*`H8}}n>KH5eI~aq+JmiZ@tiG-!_nr!-^wf|2n?dZAphfAH|ZF$YUU*dNg z=UbMB=w#n&o{__=y!&n3>MI+wFRzktHhU<~dCN;D zt_6eiNmiY(vcQXtYgJ|c_h?S8(^~uS|Ig(Qk3HpY+gl%UygB_0S7uOnW;uhg*qOPd zy4Kd)&zw7RMx?H5@1ILYj-*I8s7}?2JhQLp<(zv4^M3rOP_(g$;o#yD`t$d1YfDQD zQ?WLSOG*?`DVtM&^{5ieUx`ony;UYZM`40+>{%l!zVd5`_ zd-wM1-dJEe`NQw8d%pE-vG5SKUi$XKe>?LvH!e+J+}qb2%JOB|_ZORTFBdf*tABp2 zH=MzVfn{B+UHCNB{`YsTgq?rwU%lRR?#z?HYPAKCeq5D7K|y8z>uNtg4c@&yo9A)x z_IiD9JJsobxY!wT&DQ@mS)_B#P(i`r_6$=!JwFakPQgEa{&b~S$eMrJD1RSa>02!@cZddPvqmRGf2+JL+_rP)O#33C_dT(S zYn9H#<>%%WuBrO|hjUH-(L;yXzdd=iROy={CpY(HEwO$3 z_BkabEfSEFTxnkKrei#3>QvR1_V#SaimG)=HE*94m~O}i|)Y|)Nu7sZ}Eb6oD{HlQUVk;qw>L?jtjrhhT(4}K z|JiSz&zY5*miEfOI(|<~`R6 zW$0bcjZ$0+3738teq8Q1*U00eiAZE*$Ju8Y~J#KOiVwo9T{f#cBU^#5F2v%}&W=V+}s zc50yrZv-#n7r$NQ#?xhfRJ5&+xN_)*Ys#1Qz=-Rs{>|Ix`R>lXt9D*LCVSV$WE$`H z^XDmfTyIrrY0`=&~J}-7O#(qjeXzJ(jrk(y{q6` zdkNR+7d>;hc$T@P-JAMCX7^;%56TSL(mTz6D84!Hul}gPvSjze|5-P%9=O!t`Z@V) zrRI@692;j&SigR~LEaq;MI9ZV+pf`C6OM8vC3)`OvBTn_W6-1xb$4g=wDG=rzWv{| zBO6{be(Q=3bVSo*XAS!SA7SCi6I{8U-}SBgvB2fr zwTbzM;#Y*M+V5<4KV?Ev;X9v_wj;0KxIGSgF>ia=Jh?zY_x;yCb!&&Ody%UV8evm2 zL8V8^^3TNP=Gu+ii7xf>nzs489*yhx7X<%GK0M3f+&` zvbRD?%F3;q)6ZvB=ZcEi$NqRI+3Hw2)#c@stv%w-|8f~k-d{cIo&Rj-t%G&C5rN#v zYBOG!2H#}Ncx#{iHU9OqP=#G{>mv`8C#oQb*!E|_t>F3K5Kqmm?IHaY;0^i zUyb**?z-oT?!9~Ppde&v&{2)tT)ov(wr$jUTbz?Lm1}lH>)L60+EcqWmuWraOjrLJ zXKcLLKjYy2MLV;T^3tv?jePt|{`&gYdjj9SC^&J?uQY09NX&vl!%b6df)k}z2WaTs zTp4n)kB{&E4vUrBXU(4NugG|H!nMOq*OqXtO*P*2!iO#U)b{m`d##>_>%`8ede$DS zKX1uP^BmFX3xEIk!BPC|jNrLrF8lB7s4K17Z?`vZcGwyT&IjH_n))o>A+LR%LPNB) zJl8ZYGpVbVs+SKs6~=hu`i;F0k1q8Vv+wKdtD8A5uHxvM{paU%PgLK3R?4m5%>)iPjzEEI?mDsa1*{E$9hNsuY-A&lK*m=g@y?-;OdX+k^49Pm* z60}LJ#7s|f>ZuHN_TS2S=lrCKi;F+X?4CR+bQVw8oX@XPdOt6kv)q!wEOcei&lg)x zPJUNg`{KdpcK)tqDR=&A8&*H>%bl5fKdV^y04u}v{5w1HE~KXYofR6ie)Hxdr&mso zx3IRJA8$|}mv!ak37em;^RDfCe!j){VxWH7Z{PZa)Kp342RmlYd}&x+eKoV%I(3WJ zN{i)Nw(k5Pbw2op(E81y=kHlsPyMvy*2Tp6y`{My_iSCXa~pHO_DQXk?bGCV(@Zl0 z%p=x@wcosbd+xSi&71QSlZp<6c};&KVs_DwuS@ysoVQE&#FwA%c(|>M!RGZYi@F!j zR`HdD-F~|@spW1a&3!0e{-dX`qjR&-#J;=MeZ-;ZQWln zWA^N_tY;6+R3r*6Bp(W|v|O;BR(Nxw|twPgVvpGvhfxAdN14v9YWJpOih=_`x*@jDXY zUcC&SsDG(z$9t})f2%&Z{P=k1=JeTSY|FpDeHz9UZGJSr?PSnty%GIPdvm z$~2Llq9>MXXZ{ro7vFkpQO?gPG9uksCew2@s~!h4NHN@Ju;5i-J0PhX%yXBYZ}P)j z#t5U5?4Xw3iO!LY6%&{nwwL8{_FTDp{`&fVb6ky9VFzH z;+380_j>WN)2aDMQ@Bs=-94S}b9oc~(n=z}v?2+=l<9e%ld z_LaBDZZ0E>(~tgGUi|mM{khVCqc;nW*XPC5emwhd!xc~AV{=MY$D1cy`B45{e}?VX z<5N%n$zK<->&3nF#?wJzwPHU?QXh1EIdDK!vawOyh$-A4O46hH!Ddm(Zn1OTv#qP$ zPTjbuJZV??>!RaFm)>}t@A!NBlJgrUKZ%*L?ZTRtIe(UI`?BtGXL`=!z2%o~-h5dU zKmXqL<-W7O9r!=_=gQM!`d-od^L&53ntFOZo6gTKAA4Q~%kxxi|3CknpWk!_ndR?g z83e+PAAQR1tRHgko^0vvO;H#Bh*LaJKH(zGh$F^biIbVUZ$F**WOM6yicNN^T^0d*t zX7cRP9pj+>Db|sC?!h^KvQA}R5Sf@>vM7D$g}Thl2S3sScz*15QO!LkE z&np^I`m!e|E^|wK8q&W`R#?qnYVwzpb0jrSi=Fq6{(N)Oa_MVqX*m(nGd3pvebvMJ zT4jr!MzZsVSv?OPm`a|W_G7v3jMvjYU2M7NSzB9mXJ!2Lum7j|OGa-L;B7nWIdP7Q zQ7!M>#ri1@(H;7%O`-EAf0B__c75rgTx|7UqV|n^>^`|&(Z%x@3GX?1Ax_k2g`Qg2 z-U8+epY039i&?j<=lk%xm2dBySC7L~4rVy>?BX?C{{3LqPd}yY#c?JRTaHwxSZ26( zFItd(YogJGc{=+KzifIP&EUIer<51_3f;47Wo^SOQ{S-U3#ZD1X@bUgoTk66P1(rFT+pFs(*Akj`WKtoU+mufA|X#f z@s1H-RauK3woFVI`B*YH#*O;7f}qg1%W-#zUjdrMUq{$$9x zU#jX`u;WN!>x}=NUv@s+BJYwK=;{;9*W_qbZ+bG~!mKIXh3@rT#$_OH$| zTl-Lh>#v00e>v~-`sXTzZFQIKP1kxMVKr-Fk>P}UiB5)y7St zk9~`lZ#b`|tCi7r_SDQdTJLL4-C)!AuDWjZ<(=(`YV%3wPO!|pkg;p>*NYD=LwiM* zCcDiuDrb0av*VvkO?*sRVHFoQc zSjA7B(V!g>6p_7Q*9Fec_Q0^0QM(vyeS-JVDf2 zOki`Y%eqtkFN3y3eEO{P>kQMcbH~5%#3yZVJ~``h@3Gr0*W6r-wYWql+k6YCd;H$R z>9cJT!@jCx`vZ*3>^EuksvTV-Zo8QG>~3+*iq@I``@UG}Z*W<+%Vb-YN!U&fw!(ip znfALGUlp4ujh4d3ewBE=z4PQ zw=n))I=xFyyT<)4wTnHpd}4#NXV-fR26^||a+|9HM<2NyF<)7+S9`UI<4u9OjT2r7 z2mMO-Ja&<4bZmwC$lZ(`r-(#^$eX~1CbXWGS3o=_KoVfqZXyLXa%a7Pu z9-H#<(loAl%J*KcHTPVSc2-K;<5&mhvu6`L>soCY*7JJXTP?B9&^oHV`_~RDrof*1 zkV(HUb*|Z}_j7_VC)dTv0kJ|-34Yh6tWpUGDT&lLRqVPtgxB``TBq~6uPS6qk7=jY z?J7=o`hULb*n%a`cT8^jA!c}ZU5aC6``5K7H2Oz?mhAPEwAJ8ldn14|FQd`#F3BRr}nH>kJywREfm4~LXyv<|C@cV_#39mf4*DhT$|-=*uWlOzJ+%{QW%ji=v<&hd=WMO12Y%#wPP?MAN%IjnHXd_5_3_)QS#xSexoL6Gk}R)t6BoCLOU%A9$$FY@ z@8(T{se868J#?GBobBnWsG6UTex@%mIla*HeKxcB=C9VSZTbI|!!`H)y`35O@$mwoGYoBv|xY*P4B^6p1`%FP$58!ug5Zn?()b!N|3{k6q02RZ(n zaCv@7n=7z-?&oLgHpiDf58BdEHq*L#*)f5okFKr`cVgaNCGENJi_5)G=dRQGTvo+b zzs#}JWQy^0p4u}5R1}?(na*zcb=e2a$;%eR6O_k))r4#jc@JmW%yG2$)Y^+l_K-+PG0|~ z7nX!qD;)W?T%JO7f;=@ERC0*jgc_Ax^drB)5mAB|12|- zn7whYXi}=d@zu}y<*Me*{8Uu1-7NXwDdFwv-Sea@pVpl{_3+p9@b1{U-=TBrwI6Nu z{hQ{)U-9$OhE4CK&GY`S>%4c2GF_6SIoEujyv2?=j~*D*+|Qm}eD0I%qV18>XU=?? zv|+=3HG{gzac>W7{aSc^{hWHI@(bbhy`rxl|7zH&z`d!Yu%JNVyHEGkOKaM{ynpdi z=d@MHq&-_N>3IYRGd$tRZ@PUhF;ZeczWm z`hK*rwQW7v%;wq{YMABx=ia3Cmh9~8?Kz1|Vxle9->or*E4tPMn!=)Trt} z1@E6C$2V;+xE6daci+Efx%CIz+h!*>+3B&fyU!Dk+~_&)(Lee0`kuW4`}o(Ka^*Id zzREbFqe0YAvF@Ob?LmdJTUR)KUdPb=e%oc|K89Bjp+@<;^6xIvUHSh{YC-$0GiP`f zW=+-Fv|8%W!Gi}6PJI7&k5xor`?8^D1z2$4+dsVe3 ztNN`o&lp5rJO1>+gA<>PvKbfrTA2H9?*E;#qRn$u63sV!P~Uh&Fr9!0f+x+l+xPkQS{9e3 zP4PP3;%O%DzpjdiEUTLrSG3UA)iL75xs(lg_mXDbyfwkSIG7Iv{u;1;F5AucqVoB% zqdu|s_GNY64`oO`IP3N*&u7wq>-5(4-+u1-syU|VeY2z8amJp8o>z~H3JRXAj_8QZ zS$cN%65g3Rf&$H6D@^0e*;aM!#n)p2T5`*maqzy{{f@rV@^>1yB^h4Ne^tuBeIRR&IqT`=t6AQaK6~)s!Gz5++gVO` zez~QQU@SF>Gs_haGOjk}olOMG6t#crK+N)W`V zWh%Kx(wOdvtXiYEYvXI?7lqHWa?&ETMXgQe+cOEUJkxs5FzrD6+!p@(>@qSkGM`#F zXQba`byzOH|88yc^!@H~HzzYCXf^01yyUs6F!>MHM!UT2();K6UzV*naZ7d6n*P%V z4+g5RHpeTSmWwjq*4_R2gLveB-QcB8n+tQb8Uz@O8TT-U8M-j0u|Bq$)7;$byw8C3 z^!aRt1>g7DuX`$_a9Z52lhr_K&BL|I5hpfZOx?T9Ze6NsH{-9C;ClJ@&J1nMSC4OH zUatbmz=0C2=O$I8y)Jzn);4Xb)5KY`w0!<%T#{voW<0}cFyqH|sWXd??iB@lWSYEK zLa5B_()SN6UFFy3N1V@8Zct>H)hyYo1M-Jx!?e%o^#W_GUrc#Yf8^JWzlw{0?Eq;s zYM&ARkZD13$d#A3m#z)4ss9(lad)fj<&!60RvY*qjoGkd-?jwB08`Ho1^KL?vTe^( z_tXIC4&~k9b1y&rZod9#8siM+u$SuAfeb z;};?Jwb0VS!Xkw)b4KR%-R1A6Maf**y1HS~e&XD@x;C|w)czE|&sTi6eSZAh zKi?{@J)dos;v;4MZQtg}msJ^#GrVEmzT{sS zL5o4R&SKHd1^#*_xgq7+4g3n5%>+azUanXier4r{`V#hi*{4rMGq^EjFo%8W`o12d zQ$ym`v5Ew-rG*S(3^!c697Gz7Sp#?iO=|y%G~_eNuoiF}klQd}`Ba8yjiNUtJnGLg zpOKE8{KG6<3siPJ>E%jrwa;Q&VP5{ILGss>F5&pMbv$8d+w>cbC1i3vD|+y8S%P8Y zJBD8}wtJrY-#sXQW1k-5fq*9__clCueeU4FgMk|VqGZ>!yJqkD;Lo~&<$x8#Y{r^E zj$2Nr4y!S|W?aLzL8if;!Jc9Afv)T?j28rTI?s#hOk6MZF-Pv-k%I>hD%LMO#G|w1 zq+rAKubsau!}pzR2M) z-}3UYy5+x_%HQ9qU`&vRSm`8Mu`&{r0uCKuIU^9vdq(3im)N{3TsjMP)he!(4UFC} z;YwIST<5Wb#5H;eAGconvfZV%sag{p-0K5oG_)FqvKsT4?koN2;S^_C9yV>N8S@OD z1==$%u2M@0af-QBvv~UC#dn2j^*81hANa0vW6ps|+jky#^x(k*jfjL9lZpaa&vYzi zI2~H7QWqt#QuT?){m_fWYYy57hkDF3Sib+btq3UheQM|Y_{QtVY1wH$@*7bD8w_qJCTMb%CA32Bw<{5=J)cidoP@gulM*_bb8VGgR=@& zyhvSj>ASXga6r+cBb~zPese4eAAM1qToJyGE9}Z*vr6e0{|vEpzJGMJEbW&%ZO#le zieT)Ynb2xAtD)8R0u8PY*~^zc`&x8e-$iBK4dE4$HpxF8u$9V6 zHy!{^0G~+$*2ozkI1#QB^fwlaPuiLjDJaziok_{1&W^2T}m2NR-a8480RB+5){$EIp z;;d=Yj+Jkg(Za%u${#jdE!)WW@i`I(cdrr=+PrDpPdpm6&nNu1Qa-$6japIo=HW!xU?*|n88wC zU+=j1BFDmo3!N$|c073hK7PgX_SQV_{98A4xeh!}IP2fu7|OYZJ#5EeAtSvdU!tbl zZ%C6)W?YkTd6DOnhs?V#J>7ROL~H6B{>J(9=RbJ;T03S>#m8Q&4Kgw^KNnYjf7dj9 zdicEQPcF5!x4Z8Q)%n!Cdi839+*>C54q8}Pa2+|?E#A6g#}1+DdFv+r`1kj>Q(D@x zu!)@f{NhbbO)UowIDlL?apFX$l$0eKvajnMynfyM{PSaR9Vcg*roPE#_|33}HM_}* zWsTA56(JFUjslV5Z&r9Phc<=Qz2dxfQD5M|yQz$y-{0L=`B?P+ELV32hlXpcYFXP; zJ0HcQ9XfpY=b^%aDGE;n+MYap`ql01%N2o(e;j-CV}G;PQlTqZU$cv>6crb`=%3Bk zTC`}9*O48!*TwFR+27sKA)ptxXGN$M6Eicby}f;|L`X%&4gpC?P0&2TKm*(rNCaXv?&}({0lT2;u7x0*|Q2TJveYd@$b5K z_jkX|ytCeZua9r#jK8n0o;JEK0rIE|Cui3En^Ne6{5I5_*_=_|{o7pt=_=5E+$!l=y9v#em{M-xL(p$0Z+jz!_A zg&#}e<(LyxruNlNzr<(7kiocs@$SyGj3J87^+!Lg3V8B-?+P#dmkihJ_82nw2btUo zT2@sJE*GIjyj)sVlK)M~brGj4n`Q8n0NqZf#He|DMOZ8KeO{_+D=+8W$+SjvCv(Ji zd(#ScS0t@VmQ0(V93i(^sDU?Pb-PwV=gqYIN$ra^c)7V&6>@v2Y-G`{J&F{R%lDj| z^zOV^g6)$f^E!*x2mIl;ICC&Y@y-M#1_lPz64!{5l*E!$tK_28#FA77BLhPVT?1oX zBjXT56DtD?D`QJ-0|P4qgA?z9%271r=BH$)RpQpLbMvdy3=9kmp00i_>zopr0N5RP Ad;kCd literal 55418 zcmeAS@N?(olHy`uVBq!ia0y~yU>0LwV3^Or#=yXk^3q?6fq{V~-O<;Pfnj4m_n$;o z1_lO&WRD&6 zg#iqHI`6J$U|`@Z@Q5sCVBi)4Va7{$>;5n>G%$F&IEGZ*dJ|h7A#(j*U3p?+4BO%~zu#BCs~@^AuXJsH(&Bp8HT$^*6dW2D z7@1f&1QZU~Xk2rT|DE{%UFQ#L?z=9H0?Zp&6PO(i{o2pV!*#6w@MkWB>I+j6w0T@+ zUSPZ+Ra^2vODgSSx$u@wb|;=@r9}1vbypu1-c3JSQ8lsJ{eNB1%Hrsi+3xHc=XRfP zOUi$1$DP5Fc77f&!;LMO!JD_lM?`Sw>+9>p?U8tWZSCf7kGTW_)W!7UcsgB}dfk|N z-I%vV^|Eq{C7hU`*qfDpc9!XhGiO?&*1CCka40D&Gcs&WJG<$d^1oaG0fB~Yas8;> z(jfm_ShL`ZRY>THFXnlop?15fzdrlw{qpv_*j>-W8A2IWF?8M<;4txq$3<_Vs>7-wf=cN zufM;4cDdt$dPy!Wt_N@5=DyA25IE52k<%=-w>LsX%-U|%Hcp+3nsz#SsvhoT|Eb>Z z-dmk2$Y7eGx|nSX`{5(iAIk%DI;J0D+fwet z6z!DRUH*PsS-3@jhDgBbtJmJOF);QXJ3HIF@XZaw3=^pyS?h0|*U!(hmF8+?;%a3Q z>SUQWZ{CEHDQEu3TbJo9TD;iu{>0PL+wZQtnl;&s#e^?wtCZ2qGq>($7|K|e@hH3X zY$!ATw>rV5or{Z0VWP*HySj`_1#fN`YKU+hTd_K9^}-OXiSy_8D>}DL*nDQ)=JEqK zq-Vw^^}o6M_26mwzhztwtQq`mo!=L2)fPMAt;m?b@9^#KE7n>ypBZ0VmtQcnU2}Km ze(kRAZpG=RrB(i1VeNH091$X|{pLz*Gdn+5m#eIYr>7vxk^PJv4rZB`RBFE6O#krx zyZO$vUteBMIGHlx^wT-~AFr$o(K<8B^z@r@>F#Awv;Uut*qU|q|CHlNXJ?rd@Sd-}BX-{0S}YnFQ-sdztK z>Dd39i+5kY_3(4pe_;p7jQ6cjLc#@~c*GG?%*2L`Gec*WR@?{7*dbwCF^Nk%kD@vvRGeT>t+4 z^EpuwD`ED1arpH;W?SVM)GxTzOK&LJ7M=ZR+r}Wp{d2bb^`AdurQz4wmzP>)YTtA& zUUg*2kx4yg_DniteX8qI*QsaRH^dPo#)J3#6KAi!v(J6I-lqi%7`7KCyI1`^;cIOKYSWC!bb__fM1xHIHcrf>TrWmAy0f7iYZzy3aTm9P2a%azgV$!hg%HIsuX zPvq;;OG%uFg6xAmPtuj`tPdEh&Ya|Rm_1MM;JwV5m3w>k7udf4()@0r^D%}1CJolP z`3tjiyI4K1Ok*tQzWeKGd-L-BrpNEJ-ZuXm^zq@W^G5nHT00n{qP5sQ2yAHzWOR1o z++DN)$s0@=0Lka7Jub*1yq}MVzNnToBe!o^cYHix-@c7!lsu__ntP6ITUOX$5 z-^$EzUD>+s*U>w!_5VKA_dnN(s1i63%dkCL{+V4yzN_VnN3uCfo#KCoI_^Y-nL-2i zq~wF&qCy&`EzM={IRAXvw4W?3rx+9d{rTC^)5GHMvnk9;qHM*rMG+Hj=v6bE`~T~~ z(dEp){l1y*%eWrDf7iWFL3o7cvK99$4$!7w3S zr{Y7!?>9G#oI9k9UiZlB0I8PDk4l1_!&MH!ZEt^nSg1oj=)8Tl6}ENYl44 zfu&7*ShhJSf|3t3bQ*p+ZnV3)Aoa7+1w}utxqi{UtBNNtTBoO{XLMm<@LI2p3b!WO zGAvJ@_fB5uLUxa5(~0u=>-S8aGH*8Xt>8e82Yd}e7raEXLaGH5BsDIuRq1B@ z+{M*!Yj5xFDIpW5pG=wHp;ECXD72}J$H4VdRCki&qn&fa^k-~7@}ueW^UWpe_x}FK zc%f3XoI#{9OzVcLB}=OltPXZ)V5n1QtFq0IjJ|GtTmoF_oYR*YPL5dki zn{?+#&&`|Gd7nw)wb+f@cYicpPJeu^v21fl)48<*hZeAK2qf^eNSzmJc>7!5Kg`9& zHNP_btNH7M6&zYEF3{xiwRz%s>#C}XA1udDi0Q>}bhM|9xV0iOI{;^0)bxH?EH0NDN?N;V@wP7<7Ya!WW*G5C7ch?halb zcjl*=qVDuRz8@l>Y2j=0}6d;e|6&-XIx|L&bp zx|RVF2?uO$bhSE1xSW@0bz=N9(L=?<&oi*md)1MN=hucFZ_*Ge`4g5fWBy0hnJZ70 zJ5+1m$O&jl0_8lWvLBOe8D2h=-JhF(-}FTFsU;t69jjeR*Syx`kn@KazCf?wk_eOY zA!||F3YMKQ=VB(zm{GyI?2~2jwkYq730ChEwibWtmC!QZ_u$IR%{w0)%jf(FN_Ywn zT7sDhemri^-~aiAlu5$p_4ajBCQOXyZC>8gv>*f)IE}^Ye*OAUVpa8J#$FetMz5tz z3?ky#QZ35y~Q6vHK4_ygOZeW{cxgG4a6qx3*JRqm+$q7cw%j{5gLp zVr9Xd4P|G!{NFFgewP)niFOi&Y8s+TQm ztJHa$&pqF6ZOv{qSUPj-s^d+8g;`y~t5eBmFKO7{CYBXr}Dh`U+AA9lMjBU=T>udUZFP`tcS<<<^F(=N9Vafab zM!H2WXJ^-y6lE%(^0NAsaI`%>XVu%YKSqh%y3Wsu9Wzf<43+@Y`VzrIYJx% z<#L?(rI6ms*Cr72?Z4*Y*U`c^GPy3jxVQIj+54NxtAkc92wVN}cK&`whHdX{r?6c9 zB`ULJOVYuYKVEaI^_%Tm@Zucr-;+Pic&})dzwWgnTghyzn^%jvk>O4I=*9ZS3|}=h zTr1dMuJ*Vvi{l38@s#AOwVo&5SZ3zD-N>p?`Sz&hy@Ll2Ud+9{?fdjwr*GZzmc4r< zN!ohi47JirfmQ(m&Z}24GTi8Lz0lY+x0l0AY3{aNt9CiXudR!T{rlt9*Vo&N_TS&} z`q78Pzt2~Ccdt_1B)EU?qrX?Te!t!nrWJMio}xp8=|z#}tp#EnKXxDf(W6wP@px)Q z_QM_LoY`Ey6_yurPuL!~W%9{6ce6~YR>tw)@NjAH=y}!U|8@v%*xtPN zjG&o_YiP(y`PW-^&ARmHQS|qB_fOkSoiOv$>u-y_E*#p<_T{F_IhAjf_hub<65bgbi9#Ft~uCxXG_)3!nG`J z39s(li`|v<@J3$N+O@u=zDs?3qjDFE-@YJiqRQl=#3163>DYNhLqF6xM}1+mAoH$Q zS+}mMOm=*v;940es&{|gBAGWwLmGDXp7UII;iQc0s`%)?hf5{Yl&gi)x%10D&#T=w z+i(5k7bQ{By?*J+%M_Y8E(9~Ma$N|#(Ad=5(KI)rUu&-Jk*&u&7yFaXCe@jIli{smq4@7dRUmx|9ed1?!&h(Yn z?4qs5+*U7lN!sXxL)8L=T>gE=<6@Z#M1P)TFig(mFYt z!kcZC!R=}6>|Z!K{LkvHe9L`uwZeNZfd-a8`pq}H_gHP2xNmnt$o5THr{>BbF*^=ln_qnJ0k@JM&+euyoMeAJ1Z~W#f6XeL-(}KgaYkJFb=9*0Y!G`MCLXL%rzzi*`FoU*;tq z{Mr1z_E-IXuamn%xSB7n-nv%tQ{Nkg6G}=-PJD7!J(ZuI8H%SYQL|+*|GzVIO5+CB z2W$uA54@26nHf4o@Y+CGk z?$6(kFXjLG_V%`y5x2#ywfm3WXEj?;%n-v^qM^Gh>}-1764{vl(l1IMGgRqqYun+w zZQ=pR2KV_M^Bat-|84#JZmUdb@OnX}wQkOTKQG>1$86xJw6XS?S6mXSYhcL5wb{4i z_tn(vH`p=k$-Y0`AfEM)esgtM?$3tnHpCy9^SflN>;pCOz1Yl zi?9hhRF`V1M`vbge!W|Mzp!rko_XIT8uH)np41p8v*Pb{#s;Q_a>u+op`YeZE2l5>IhM(^C)*TQr>nx^x7aeK1$`}Ol?tGe^pMDDh2I3eiI`~O1B z{kd~f{~uFhkImgzr0C9_z}ir_V5?gB1^v6THn6UJ zTgE2v^+8(RhKf31T)1$thUA~c_is=KB?v1F`D<0ivO}g-Tk8Hz%-2Xp+3C#bfxo>hj zbArGN=Gew-3o~vv-V?a(D=B&Teaxqg)xJB`ULE>=zpha9fIY(=vCGtDKiE@pZ$;ew|37Z8T<~J~Ewk^v|9^a4-tHY= z{XF39-=+WmyxBb6y+;N#S~NM^Ik|1?&3~6?`6qJR6nM6-;lHavdU%CLzuvpIRTdvJ zb-um1sdJ&LD*MAME`bETImWN%s$Q@YVk!5ukkOHV!5T^X@~{mwykjZ>F@G)M!os<$j#;@37mhE8pjCuuFDp-nQaI z!e8I$hK6Zu*8A>!ocdhNXWPcDH7moyrX;>?TYJ-Bjwch#7PEqLD>gb;|K9WUp1O6+ z?b7Yr%Z{H>T=0E`0e|^U_9*vttik&aUAuN{<@pDNdB?<$9GiEpbzvRr!kJ57Wvx*? zAXo76!oG*LR%QG~oQ1!#zb|w#mffy)BWg~vgGUI@`EL?BF*^jh#r2Q9xw+Z*U)gWJ zKuw=k#po+ytkM6^PxX$uy(Ry`4N);Mr=>wxf0lQ;Fts{0HZ?IFIey%D|Md(L51$VG zwSO<}=xbp3oN!t5blfcC%o%rl6E`}nzIr9$?t1IX+4Wo0?&<{Qc%E5x`?>u3f2)1n z|EJyGaDHCr)pPTV|8Iy}U(d1N%j?4P}CZ!@f z(x;g6B+M}qIDfXLYQoO$Z!%UhIiu|Am8MpE%Wd;HK7Xc7+MJK_=TlX$-_g|C7k~Ss z)z89ci6f_#SRdRts=mcJ*i>iYg{rAOYQ{fr_a2J=eo$2DWK$u7g1kY>lND|Ej-Ni= z9Vm0gQEz&4NSKa}PD|8U&`_kHv~>5ABS&5v6c}u8`(et`y=Aw} zF<7zS!wP}N+(pKdx*fGe*J|!>`nbtQ>gw_Piznw#KI-VHB2-ab?W{CWK~=T&^Y$}q zip>w+-E(y7`*WF3U!U)P^-5kd`_11yd-uNn662vFbmD0d!npQer>bytYl6po3wLtp6z?s`}+DyPJjE_PY)Mg zVq$P*2=R`uT6h1(^5s<~TY9tBx^X%8wQl_!%)*hOxnb@0OA9YL-nHG$`k5=zrtD9O z*^Y}WQ5@-w4cD08Ntza&ipeftp}1nr8bzP^*LYf!PU~)3@PH%#G4~{4q4x(u?A90m zjdtER;V0X76G1*9;Ya$1O!gnTB`v-<;!IuIsT<33BGe{3E)8;2nwaqS*Vi-eO--+Q zoVBVKkKt$ZWGkCzk@~8}`~AugE#EqKr-dp)oGC_+b99VQ}Dl5NO?Rw(b4C{|8%+Z7F{DskeQ>ap#0qp%44nf?jz2IyC2Fva8bR{$IzJ zs$MzAyu3Jpqgeoy8-y*=ue9agt39`Pvj67i|4doe#c1oW?hU)CVynv=bSC_jR(Vmc zq`{S&KbjV+`z>26xXHs?LrmuN$v2*dm2PeMY*hI3&%Vb6Mm~?Xui^9)b=u#s;li?< zn6+WfYr~A0Y(GX#xfA~C;MyH$MUGZix%@vcA#U34?_J&9zIE<4qFk*^^XAQ)aQf+l z(@#D8d^FguN8OXsTChE>;E_oDEaS|cxqF+B_D-E{duW-g`{fG&rXi zA1|NniHwYtOglSc-pr|!r?WobYe-_4YX9f=>{MB+(##F3e>`MX6`fx6PL5~x)&&t9 zKjInHwaA9Lxei4tEGTU%cKiC~?)H=CR?L{8=DpgqF)X@y?Qg%> zhJ&;7*8bsgvQUoQl<>^sG53^mu9e1|E5$Dy_`|gzwPJ;($>zsyyt0Wkj&6@muG&=e zRe6ivYm3D^j1x*fay~x#E}3U(5NE3sBSXN-kci!7x@NhzTHN`&JnWbQbvz`deBQKF zf1lFE%{JmE=Oj5!k#@3P9iX8w{q)9<+v7hc2IzDIXv?UTHs_iacDy>8?|#b5Gax+d z>WTwrEjN`(OzHN|_@CAteKo_RBJ z+EumfxwqS1US4kelUJ&jZL*s0p=|wgsp{(%Z{y!o#ue@wvR_bf+Wm=bQEQ*6^i)?> zIVnvvm?zBe;>JehZ*T1efv%R-}k(2>v$V<4Az9J+x0G8s&cRG>t}6?lP~i3 zn`G|ju0DL@gw8?f)6>NAZf?^Sb5MLCu)=8P=E-mFez&i1%(=W{&$caFrbHX~nuxY2 zGXCdI*i*9j7rVAr$Wc@NuI{5(uSym6hUs5>sTt7Fk*%=Qp-!x^DMDpYPOgKes?y(u zht(f3PC2vyJhT?YZIOOuw!XjgE0ypMR*P4y()xJlPkOgm{@qf^FOo5_ztw-+Z_6pa zv$@*;y70#I-8W1=`53vyg?(a{;1FDsy5s2+``_&DrH1N*doibTlrFQPzdG+bjr~C&?Ya?$rUzv4~ z^ZV=j)=PFzFBjOKa&oe|@dc|-+B5E~Xk=#Zd2lms?vD@6Q~CGB|Gyk~!Ru%&Lq9{p z;r;gYyLab5zW?-~^Ks*Z8N08kH3=vzP*r5w8~&p2$o$=xPi}v%#Bi6Pf~kPnH$QTI z$P#8<7aOLv5AHKKoNK;TV8<=saKJ3)bQ_PX#hm!>Q z+B^QoRi`agJzn1R(!67OTA`WVJ0_mC=xlctkKJW?_sukvj;YjD|6iD_xgb?=+r*oz zx>(yIGf#2{pZRn?|8BV!cW=l2EXIOE+pAcD$b6h- z!7ugGQMxab|>%@oCb z!(?;cT&v%|KW6HvD|>#wT5dmwt$_Q>9(_jJ_eU38_lst@%Ku(Gw3%=3CXT7EivIjL zelKOlyg=Q`W5rKCKYunuNF;Xuto5hQ?XHmR^$E`KJbFk`%OtDgBWrs9`}G$xw(veX zo~vjOHRsUTn`pjou!n8~N*0-i5G>(F;Cnty0-$w(0x5_^;bkIX~RYo1;_EV74G*8Tm@e1Yl4WUY(BOP2^aNM!@&`uWnAi{GT4T@}v2V3u=( zfni7Sb3ehJLko`e&p*>W`RDHU`+t@t{h|VL$rD{QR4pG$MTKW9Wnk3hToe(~80XLL!0maRF^08ZC*ypk3#aS^ z*LkejxnUa17O?{5q-Xw84v z!dDcBRh^2R@k|#qRyi@6$w|qF%Rzm)is*qYb!UZt-@GHoo%C@_`4r0?E?Md66NCJ5)cwb6)Whn+s# zvtB1O^bXrvmpjaBC#-f@FQ56gR%>~0^{ME0=lah)zcBIfwQ1Fsl?(SOGwu5Jf!j22 zTG?CM9Gz|x53wA-qfN>Mx^uqwcs_dGyeRt0#LFk2N66;${uGtbU6<{UB0le}sYKLT zw&(gWJA!}zDPzcqudV#2Z6@?@Yn%udtBDjZ7dQ9A_wV@|_?nd#1}G{j2CNM6@Y@;7 z@jCkSf4>Jgd5hclC1RlrIQO`?vJWpM92z>)s!$HG3z1eXhhc;{}Z0R|-e2 z{HSUW`eu!*u{NWEtf|E&_x3zTp?SGX406+K4t&X+ER=U=PbuG)phD>_sVk%!zWhFa zFIwzs{*Kv8-=;59*>dD}^(7njGw1Iwn|HW(=K5#9u1E!3udbOS;3N6>zSQql)$_N4 zKDYg~J^1*{(ffbrWUYF>X7&HIFC|}9o4JK?e|dRh-)8?QM=Mt_6nwgJGv|U_myv|d zmn9yC!nML8LI=B#sOTH7T=Pxt*qYh8oQ4q#&rJ*ze0WU!Ny@Sf-74l@cKP50)Y{@& zV!BVkT6^uqKRa|8o~7!~vCZ5Qai)Lu4#SF&qWK(-+ZbfxqV{}YP5)lz8)fgjGGx($ z1q}D@-P6#~Y4KXxw0*ld!-Del^L`!e7LRv4{7L(U^wb$&HyZxhsn^)ZTReM<99y}~ z@BdHo-@K1(I`(aT!(H)3ELIE!1!W}@ez&* z+eAg5&M^Nz^URYgZ+HqOZ`EeF!S_!1q3!RZsgo=A?mzOwdxdp+_j%_H&%1bEC+E$R zIG^~fM$z8<8-sf85NjT`SbeP<|seYWlE_Fvz6etqNqHt(Xy zZ`S*r@z*Oh&Y#M=ZF%EgnVRRm$pPWN*RHIpP411YUtav`{T~0VDl`6cg~!h^I(O_? z(e3MtC;h(iZLj*~1iPriY+E<2nLBrGa)8Qy<9Sn=Gv3O01u@(@sJ~;nr{LKmM_Rl$ z7%bVbQ?xs(F6R8U#>Bn8M)u|JY_oD?w{J^2=xNs9^G^8cB=h=+n)Om`OLBj&3|`KY z@v3@7h?d&&MLTv#96fsU!}ss)E=rC;NluzOxKBqor{?cV*?6-_E}fI%w)wO(+;7BX zuioBV8(nXm>l;0D@0F|fE=Foi-0l6P%63(DiBd<7L+6nNTdp>2<0|V5@>+lWQDLFy zP7jt`U)Rb?-=~kGT~FP9ZhY?P^7@aL|E=Cyn;5Q|etC0b(TNSe&)XdCI=Xo8?{8c$ zue)75*DqwbrMR%HptPW1Lf28VZ&AJTn%3=#Ss!}0He!uWed<;DXe0eQN?VHc^v}<= zaC-J8>*KRlQ3e-<=??{`_3o zw;*$A>*$qp*Sajb9DL#BS0(F=g&S74HHYv-TSt4vFLw1U4P|u=l$zM0wZ0;zZ26Wa z4|g8vDVCJ~SN%HGq;7wLcHURbEdN=?QvzqtdH%QV>y-s@4;7td=iJ%tDH~(e;ZhdV zc_mU!>~=@#tyf%L@xd#vhTEO6D%bvgGpJkxV zBOQHreuZD{&vTm__g1-on`X7^x3_G}Eh`JlolIsy(VcUTh$(d}37Q!8gh5udkvD6> z@*@{sYkIBLYu>eJk<5imO|SU4g;h1L6AK^yT(hO+OaJxvd2cMQh9n>RH+{GNS;?1{ z>91xK=H=Qp%glK?_o#q(?wb@NuBx?u!LduVwKdl-Ji;$`XJ3_`>G!Ndue0kmmdww} zoM3xYtU<+QO}f8b@6*&H)0_F~ld82(+&o?JKK<+*tDG}CJ}%m^!=n40bD+q!_jWg4 z>=HQp;hhBknU00EPF58^XGC1s{?6uzowu}Vx5@ORgD0=mSN?l)@tC+s-2OHG=Pdk< z&P96*n)$_4es5S&W^+4R#7j81b^?Gx2GdpC> zX1AEGQzCf%M&XA8^O$B_Uve`{V3Xr*#tG{pwq+EQ%%35?>+1`_OJ{HI@9kb)Jz37? zGQ*lbZ~ER%{Iuv(;Kiel^J{;64tIZC?D>Lc_R#N^I%jNbh z%(ZIOcq3~orFFy4L+bChSD!t9Z%Wszcz*Y^`4qm3wZC{CeO|Lu^5oT{{Gt2_e}9SI zu~GgX$F+}l-~LBi5B<-%BgTCz*ikEc`Zc@xm(At({i?a2C~Wm<=keA%TVDNEUCN(u z;<^yyhWO9FO!RyECWVAuyYa##%8+$$1i!Vzl6IFh&3joEe5uMXwem<6@>1EhH0OxY zsjwy2!&f-Y^*N>McTW4t8M*7L@4nhDw(jE#LE8g2jc*7pQuh~?Pl%d-^1$i*x^>kx z>hGWRu73W%W8RJ$<{cqBp7G^vOE_}odZzN?Tl+uIO$$>H3w)<1WSg+~YsT|M>jSRaRDGU*yZeA@Wde6aPU<1PhQDt-nQwiUv#DG; zfBpXed;9(8;$nAs9I<(|Z^OqcHV@YJUw`GD7rU$cyW78$@9Tbjo*(^ft}fGe0rTzg z1ydUOr`cckja|GwI6ON?V{cqcWTfi4Rjb-ObliH~n4>pxSgqv~=nPoQsJc}=@LQ1d zDMzhqr)5=tUGB6zdUEFVY^yEBg*QH2mG<8K+tv5go7uAk;-$6i@%0}* zeD+^GCH&H7p-F!Ae;%E>ACxt}`OVp5U5c0ge_g$-ygDQ(b2($qmRVATuC0DK?-Q6O zda&%3+ptx%`BJdJ&07vR$?lyl3sk=GRk6Ff&-Hn?z`jPsbLabrtkh_8_1mJwZPl5% zE|0Q$&$%&2OWP_m-4GMF%`}DYLS{f<6yL;Ni88*j4I3vf*tABx1v}l<3I>qIg z!^_pHzUr+zXO%uPWcJMBf8Vw-FF$?Y>#JF|%m4lO_4MFhHl7N{cNdk9Ts*wHcW?4+ zHQVKC_SBw}S9+BhRnUkX-Ep3>ZoxFPc#*ItA&G*pk^FM$6%)ATh z@4hOJk9>U5G^e3B+TPvd!0k88KCi7sBffk~w+g*@b+-As_&>^3N4R-!E?>jim%h0= zA%)$p_vzCm_ZfUw`moe(dvo~8idiPB-Zw0tf3xN5>+8uE7rFNCJO6dHc*)Gl>G=)W zHd~Harz#1x@ye!65}!4gkQ2He0ccQUOd3fVncE=XG1sx5Ay@w z1FT=enRD|x9JqttGPsdeSZ`m>)WLRv*&&_5?%=*yH@h9xv8TV=+1GtP$;;5~@Lsc#VUJx+>9c}; zZ`VcHWIo(@|60ykJ^hQHbGsL5tXlIT>F7oKYkSys32oZ*t#Evk~gi($d{#n~VGe{3n%Pxh8+Fk7&6F{^}k5AUAKzc|L))O z|I**4AJVh3Ot)rUR?|{eUhFwIpA7!F^MN4(Rt~c4QCudi> zCx6-h*Wq@TAN;%CdVhayvQ@*o>V1`8d)4Hps2$qAI$k<#x1C2W-#I(^N4Jlf|GaQM zx;y{rs_0$$p`xk3?)<1-ezwlKpeExoIV&bF5`P;6o2=(3UFB-qv zqUgi@uWy5|wfMfZC}+IDejtZob=LWrcNzQ`ESMkU$j-maz{h-p>47xEdL{{G1&I@~&Dsp{49fb?kAA+@Q2ysbn}l>K-xkNw#1>-w+v>9FW_ z^RVf5TP%K>DkyxT$Vutg4hWgBIBsXf zr^^dO71U>h>vc37`||(GG}HT2r^e(@Iy|p;Yy6)2ean{33YRuk@4LbNAQCi1%%B^w z?aM5IW;>R>3}5d5{~i9aX5P!~^Y_*BJg{fD$85m-Me)MoZ$Ec2ba+_(dcJg-MDt7k z{u}HGdJT*WO$? z3YYdu_B&_nW~^KLaOvh*N9*@hm5Sdl`@X)uR`j)G#{oYU8*zrW`>V>Y-C$=;e;+W# z@t$SD1BR~;4mPXRFWVIm6B4oa$I|EN&0#aV-=Xd;35vr$JXWae2hWXF4nxn}}*}m+& zqh9--|K!<^GBqC^Di=#_sc}3OeCpnF{`{Zcjvqg|-SpbK=ZAMszcPQ{_8WIBk4kR7 z{JZYCX<91()LTm)N6)I8e<^cC&y)RU-UeT5^L_jK4TplvmOGz>8m2PrW7@!Xp#N*l zHRd1U4gC(%JC-+?Rg|)>b@5E#Sp1bi;MU2_XN^s-{`q$LdVJkCo`%Y;&lA)m+}}-Y zF!N(!l!#xlXYuaJ&uYu(Z(i1K&y(Qy*7{|K+bN~93mXeIePutwQudXv!{DL!-F?3c zxYo#f=iSLyTX)A?!D7Wy>w>Shd_@`Bk9Nn+DR_NNS1n|vWk5hc!=Xb?M~)p^v|)pQ zr>EyJ9tIw3QHJI71QYN2&9#{F;^o!HM-RLA-KwgrbX1${sJ3~>DqH<6ujO8Sc-7^< ztzTN?CiAnk6I>2VWGaxdHrexf?&;%?+0NGd4^{uZ&i7Ekkz;2nyO~sMG8#ksy;jU+ z_fI|aD=}bB=>=tlOV=;8@x8ef_Vv%{^^;cJGC!cZjg^7#|DWTBH21cj-||C_Whq2U zO4Gdkw{E2uWWIlTd%pi}C28xAJ0iPh)#wY{_7E_9wY1W@KFXAx?Vv}{?R-s!>FdL6 zZomI=(OEJsF?msr${r5?Gf98eTvz{)xqX+D>)Gg!!CWtx@A1VP^sFot=5+ zjE{!MnheK{E;bc!v?reZC?jY4t6JvI=lJ~xt^}R`a(`i=2v@ZE=bpgWzlcJ3MdEuWY3A>+-`L?KdcHi09<*z#nK7T2V_;btp zwtA0bPK{sTvzXasb1Qpi%9%Zy@z8j7-F%_jN{g;vskHw8r|C`b+N0Ty9DJ)Bj4kgn z&)r=v=%Cl&!yxJZBZb+5{Q*~ol3m)ce&C}pFTCYElzxqxprv; zL&KuY`|m!N-~U7L+4ufGvHOSXw&$1E?RNj2X6@jb6wM=L{Mq(G znD@4ZC!e0)-pr<7_xtnPb8l;AZ@Xj3&2@g=o^SuNpHDh1w@Pb?!Pjjk7KbHTvN5gOn_m>uFvz0v#+mP`#JyM-{oIkO251<+V(+8h*^*M!Ly5|P1onx%T6y5 zZE%0im%F?CLwC`WzmH}!78Y_=E)b1!TUn9z>&S!ue|}ZZDK98d&;H)eyR&`z-C3dk z4eXX%oLUgxuMn5~?9s9H3DLCzow)*HhF@$iyl#7|y4kE`LGOa63#Kv!#s1@JsJYXH+&<~A&&rTT z&*#@4+q=km>eZ{JE@B&3@VFFL>dg2hdhp;wwP~~8d|4ti`#}cBi?!KI?zwh4bTY47+8IJWzr(gYdt@X>3CD9w|e8v3&Pj8=oMk-rBcTdd3 z>9g0)x2U{zkZaefZ@dy2sh*<2oD9=#qyPOa-L1#?XSF?(hqtFr%fcud)&qGT|8O=x z$+d|-%ow45tAwW@#wxwU{z9VjIff^f-M)Q`{qpR%wCtTV`GsrwBcB&>Cq@*jyb0iP zklX+NcE1ywt+`){+QHa`0W(6i7_R*My{y4U&AG6!@OWMA@3un^QWHP#wBBcseoMf0 z_pj$Y%a^M=*98Uy9C*{|+xbg`+j?eq#?9`_&zoMq+{FA~$D^m3&N8vLBW<2*diDSR z{d7GyLyY*jxn_sLE+wVTk>crH#`e1I)(ozwg;SXdc)omp`{k+l|2x+YuCCs!`KacB z_%-tj=a)GA8+V*G`L`39LCp$}wlT>f}=Y4Go+-Fa(XZcPZE9^PyhE!UvN zx|265vf|Qnv4-7S?`yBkZGY?fV8YLmuY4aLU4D3G%Mzt6ea7=TJvjJyzhBKTIdSHU zOJbrTgMy{zOFkdZnlr8;_gZ7xcVX=!RtiY%{WnNIOqdR3IWnmt{ow(gTffqBj`p)b$t_x)eo zo4!GK=e^69g%>Vd81{CvrHoCPlI$JR#Ipt()(o3g#MMg0CVu(0R{BZ{r*OZ$M&hch z`%JmKTC96LI~gtN{=92?`0%gV=S3VTj}JV2e5CaB21j0LqY2@nU#2G(S4$TjkvPOtu4J@wPywZEd!FZO=+NdXNr5iZue`}=wm z54ZWU>MGnk?BJTkf1vQd0msF!f7uy+5)l(q(%0uVn#mIv7w03pVA+wYtHWRa-JO11 z&&5(nPFa)TxT5pxclFKhX3t-~Hzpv0`GDar|NCK*Y^8SkyMH}fYaMFPvg=g+kNx@e zudi%%U;SkrL&MyVw(0ZdyPnh3%#yssV8JJMq5t}fts=j^y|!Pq?f+WE^GyMK*^cwI zMHfu%c3-eMUA#F=;?*ya>v7*X4kQ;iAGmpCuMoqfjtTE%txEVGFHM!VFVtecBjtT9 zsb&hpgj=_7Tk^{p1%Y;Lb_%N-#XY&a{QQ$cA$Iv8_Oov(9ozVaU;2XeisJD4Xa)~I zzhf5`Ix{jnFWRj8?0Bx)hOHJe%N;D%pX!?SVBV*`x@%W9HpbRAMduu>s;+*#`MllX z>GSI<#M?TTxV~-M`{n3Qhduzgv(CQ0KOC=gU z@6x|N=b5&0ob;0$S&1VkY`+IYz{`zOa>rc5o{K`~Y{zkHFoEySu^)lqwW&7#=AGoBBbeC;cEr^fwcxzYkO^D}RjbK)< z;O6K1ek@%(cjd#1tE)mI_Ev4Z`b%f}X~oGW0|Emtin2Mku&^zjq@!SP!+&j9@}(u7 z5nD0@_w3!f@M4C5q^I>gV`F2+22OU>{rP-3cXkMVescqe z36<5Q|DxXno0$n6ayxd;e^c5L&fUvAgPV0vTkY9YaLd9@ad&^$`@rb$a_1TP_q3|j zsl6;NUe3e(Vy}^Kb02Q!U7B`&-dxssn>>nl+?x4gZQa1ODngEnFD6`C z;yK}DidbdDwYAahjLd8f3j-3qzq{*u@Bf-B6{0-r+_RsC7kG%Xedm08Yh(1`!&9`h zP8sH(GoIvz4JA1-?Wr4~X_CIL$x5{?5_;A2;64+A5W`b=GVRZUsxr#y$3G zJ?BH;sk|4INDZv>@Lue+m_6&Wj+?FRXV&cR%M~r=PyQs)X1UsNtzpvT|9d~z{FbZr zc{KCW=g*Q$l~hz(I2D!donLn9s#Vz=2_s|Uhc91p`uqD=R971>oNY9dhn1Ce!`6+8 z)AF_@DNfyOv75Ek&FXZDkxu+R8FqfTBOQXu6Xwt7XXxndO`UY^c%SU;H}`IReSQ7< z%7_&q{iX}PTU%ez5|ewUmp8Xox#H~4V0HgE_65CMpTEDja`pVJu*}UCb&sxCUJ#2H zWVrd|X0ceOR6y{tTPxPANt+*>#Bj+huW0+b#y`i_Ed8)yhYP>+i`duo5C0s{6q1&@ z*B#HeZ_SjV3tXz4*Hf?m&D1P7w4mx+k0eLKX8UE!RYMkVrc7KGrgI|U24ew7cgF*d z1s5+~yz$|${rkq(d|A4Q0c8v__v%XR)}N{OUbx)lk)yNw_6nb`f2+M--8i}VrU3_s z5(A&Ujd59l`Tc~SJBy#sxMAJEr|RYD=~z-y(!GE2u7cO^_6BX}Qe>R4cWcG93FmB; zV!64w4XeN99E)0cF+)mM;LH2_@+$ux;03RY z{{H?ye*bn}7~rt@qCw|1p-z_X@9*n3E9OjU@$-6qcBbK_i=Fd~RrYjlcrLhJSNg1P zOkliHb>hRhLK4@sSsivIz1*z)R#s>J=g_HHIk!tcC^7uqQmCvv>+3@um&}*SS=Z{=uuGfjV%`K5y&^EW=3So`pqvxLz0wP(4m z-bv`mVUXF&{M%#|!~J=-)eqjkKmW#G-S7C_mape4`fB8ar0($=RKznXn5yoaaMizi zb(8tlYbWJ+B0XH*n;jEBa{TD#o9$}?&)t!bIjW?kwdrEvQ{P6%!)`aaa-;4!OqnDR z&Ue^FDKVfg`FKy&wZn&-H~wmEX)#D-Ttf&H`}dd0dbK%vY)+F9 ziDcij;6mH+iap=YNw@C*_fdTJs&BCpD}H-q%;IUd-L*ZuMt7>E`HO%g?yxs|dmA-nCz3cgG=9|G>TwE4jM;{&SHmv>L%h<;Lz#zq=KJDC^*xh2A)6RnCbk+Rk+{jUp z`nqtR%Qs`rO!0)0vaj#%c3+=kKYemoY}mSW3=3YHCpb(OtAD_zV6E)C_F{&X!~2Po zZeE^0PbbSEH8b0J{q^M6({i65OOl@oO@o%5Jr+?Dk5+%EIxyy?uH~qF%yj-p4c<|sJ|Ca3O=d#y}-wR!MEvWZa z*PML^C;A*;ym;}(s;^mXyRP5(6d^xpve1{?+jBLwHFhjprom+zb>RH@^O+YHx%#aR zUoTc!UHy3V`hA-$8b2rHwSD{a_4f9}+E=OPtUhqQdU|n!e(lej?)?9Lp8f8g_#tFM zlxXUL>*ktv&o({2FTd~Y_3RJAnR7Z7PJ}5qIXMXk2{Ab-IqVUAn!5DXq1)x}4^5C) zVM~ygkUH9Zu=znu9N*T;%k!W96xR>S*c!#9BxqIkLZQ0yV$$>t9UA{WfB$58_v~#i zUWVffKD`IR|@YZcBTWbmaK)#XEM)_$ZNOBBe3aE5k%;&#zaj=VV`B8_m9T7gK%i zuf5Nnth}-5)2HLRTDiq<=|^t5@$|&R#Y#(qI^Xa6eeQ|ey?gh1!i5Y}qMkp0?yNTX z;QjmZ7cXA4D1RsO_1WzFXNMoCrk~(yYC5!wVawLS6B86aeEYvR0?!YBD!^SGcIWw_IHHqv6&*`)@&SjVCOrj12$p5%*c$ z*7PG|7H{3cy}x#Uc$;3VV5<63EJAU&qhRf9m0~+3T0N zZPJTze!XDk(%0cW^HV-KZ0B14a`NR(pJp$b@4Gf)f^U>nfkXY|g7zyv9#5Sb%45II zbmy;|wPr`Ay0e#kd?R*8<;(PX@i+D-M6^^ARlY53wB1w1;`XVJ{r8{Crm64u{&&=K z4NQHYrMF2pdi!?E@_#WE?RCmzH{FA=Bze|^X^8W5YeT_Na|NQ;5+4QOQzmJZ5u7O7` z9XWH~w?4PnzW!ZIMf!TZKd+`QSw4kn!^=xMn-{J27g)b{`JOdA=g-crO+WtbugaFb zz0YLo{-iEGJ#TKktM3e(X7SgDcD@M_dKAXVY`RrP<2PM#4{Oq@sD@}w z?M!^~>ZYcC-Yr~#BHf=)FkH}4~nV|k~etb>PzjM2_&z_rU zZ=PSezu;d@#qx7;yt9l;D?N*hg-(Lfr|0{E`+c&z*gnnr?9L~@mtldDn$m%%*S2zt znod98z1p;Dwp6d*lB>ZOHTy z``*NZveu>Fp56VQzb_*A-?QEFR}7zT+Zk_BueT>Tz3%swlQ(uG6%;f7i=N7@bli*4 z!v6c6;$XKPiHE0_AN+jtWd8-LA`QuBmrty?SKCv3J81Ic8$0Lic~LOidE*9lh3*cM z)D%yDPn9>$VxJ$IG0#YPy$H zsQ50w`dpKki6@i3=f6qzTDqaK_GL%X@BI<42xK{S{OI$;6SioxCG0Oaw}rFx>;8pa zNBLjx)BgYDa{V#suk#l^to`ty@zsgOz4t!HRdj|gD2<7^;~Fu)YG!bC+LaRz7tj0B z>damiezx|XYFTJ*5JP`#N(blqs4Y*nZtcsoLtFVp8mbN%eTxosB{ar``+2#uUzu* zY67QWYz=Sg&3(V$S+9xQ+_pGCqFTM@qX&Ih$Qm>AS{&N?H!G^jIjbK1Mn>rFTIa!LNAQTO{P``6pr_tux6ld-Qm@_py?_?!!KR(fwd;o-fL^RSdKtC5j@@E= zc+4T?S$v@F^&5+}9Z1i}==i^Ub@;wB+nG5F)AgIbJ=pwNEb7>i0G)%YGhSFe#F$`EYdVp{Qa-ZQXq$ zF|#5K88TfeMD*EO7VR!yVSc~rxk&?)1lNTrjdI!U7urLoZd2|x%`-Hv?D$w3OIjMD9wAuf!wlYH#({ zu*Ykz2lH9Y?Yki6gS7aM*MW&r!ZRY6fEBf#A^SDXz zfx*ACPu|gVJ}fftuI2Mix5WoL1eK*^{C>XOeqUp~NX%*Gz0clVy?2;xOG0#DT->^_ z)mQaY%9B1nJL|(SC2DP(*HWj%#KgTRT);|L!bawrtg+gT>4AmZlxwcUW`5cbi2KH`v=hKi+%xtWVN)Mve8g`u*AU z?pbvvS6-bB)0*?f4e`6YM1BjF|qgcH8p!{ z;qc8ndun)s`?DMDKdQ@lID1pFiY93E)&Ax;kDTQctSKgQ?tbg$d1lcGdH*+Vwp?Id zs^k)Rd+xE5f8Ia4zj>|b?@Nz7JpFbt1)pB*yuE=V?xSt=_CNm?gnZq>uqC06`%7Cm zU)4N|#orP#uJ5y5?>c+>+_1k3o&*~1=xS~DS2+Lg|Igpe$5WqPkNB(J#k&0eyth9> zz0dmit_hkNDsWoowouB}U!u7&b7QMnT(3&T*M6*7SNCbkN_K6nE8&Sz4E-EARR!j` zf7kE-TPEb-&LHa`U!k|)`dr>K(G!lW2rXf-sQ>?WfAznAzu)&95SNtfyz*qps!gA| z+6`KsbTE1}AFlo=_5W=BpJVg(Z%?$?;JTo74Hv_U8;$Xy?>}3vH0}2~eTpGqq2S)w z*SpQMw78^tmz}H9I?n%oFMHI=9dWnQonH3dvRln~<4YIMQ&H=BL+hoxo=jXN5tDkZ z?#>HAwa(|gDx zO>Ee?olFIy+?))N<^NB70}a%#4Dr$PNZwF-S)bo4H1$~VvOV9JUzcTXn|Id#RGYvB*E5|{S<6ne8Z&%%-feCx zYn-s+=%!OXUu(W@S!!s$cG-(MPfnia zI<{$bj(d*f{C*ZMXQQQC{mAa>%EeEo-Y}Kooj2Qj`LFBo^{QQVff>==#}7qJOfcSi zlWD_To3aJZCpg+xm%V%Q^0i8F*6P4;>r*Lx=O)}*ylahH%IgH~i5@J1uANi*zZms@ zo4fb!ojW3T|NOZ8YW{h@m0|a^72ltmbu?e{XU(-UoXI!qKYaOeuaX3lzTeSE)b zx0s=Q_ExE!dxZv!Zqtqz`hVqqcjIXL^*uj|FHcLkARVj7$Y}+LG7Oj3%1Gb`uOU<{A{zy|L(8)J7vb}{oC^c7FRGOCnp=GbT~fu z^Y_$gI_R49_J%hnL;KV2^!`a!GwRnwx0z)*LQzUNlCd9ZCLmJ zpz_THx_`H4{q_^lD}1}(j3K7_+q=sPmi*Z@Vcwhq{x5T$Y7{pvoak6{%eMO0lgFRB zx(?m?C*CwKJk+3qzP|p7tFP2287*0^Hs#O* z*%X@?(7A>$@6G+T?Z@xmi#KeTpvaz~@$b%_wd*XCgRAYM8S?5H5Ax14ekRi0bH(Ko zPmf{7u@=R~F21{!XMeuk&A+5U?3R4vJnO3lbNYFgN~Au|vSiFC&iLK0&ns(t_3EX% zqjPN+SC*aI6T9{OHjXcLN>Y|36Ux=~>z;pIb~akN#P4J5bIFyR-xIg^pPgf*wqosa z@%_cy-dP^Mx%>~4l-={5jb(46cH9iV&t|Ld!RM9D(W>;E?PHg)RQ&J!@clNc($~*B zzhmoHzRzDil@Ew~k>RgW1|2pO*oefB@X5eFV zywkzg>(;zw%98esLnf`u!gSs+p7_(G?3<*y*=SP!!7X*Js~66cwXeG2G4JixtTnN_ zr!9_{bN=L&JGxZ`@@%J-8E*8-8&48{`gE$dc*)Di%IA*qOy3hyQkiW1wf@%ZdAs}j zho@6rs*Jvs@bx@;t?nyxK3ise+_~$iDaL>Gn-t5oO0_jbO}!U4?^~T?V(+W}vrMxE z-oqUhKvut3oTy&D++0cjT5> zy7hhQp66Qn=grLSHQLHb6|LV@@al@>r*o32aY@;aZ=BsfU3z|*{~U`#&M$S2_bLrv z>|D(J;L)o`EBO06CLQ}?d}EE0vhv2t&uI+2izoQ`dMe6AZ3{}Vulk~KZk~HqqKQbj z-m{mNHl3S2+xU&``c>}R^)9`$W8}SOye@8U)~DT3`o`tw>`mWvS_Xc7_^tQ!t|MFa ztX{yn;J87HNzj9~30K&+1t~Hs+}iuGJKW8`cH_Mbrw$!*dUJF0@tl8Wm;UMgFve4_ipd!Utj#{%grA)61_L4 zEIWDFwPC9ZuLc(|xFlIUo3hnfu;WFomyVF_ zv>Uf

sBa(=P%pQ4=I?znNUa2dlA<73}HNA1eEx4dp4GkaypmuwTxW6$T;^Yywh z`}_NYjvDp7baK@xuA2Xs->WAW$VKh0Yqe#F^zcZjE_<{sM$bJch^ab1$Fz&pIr-`_ z-*-~CsyjN{YJS`}$ur~Fr0D342`sA)Y=~ z-F`EMC5eK8dvy9MEhYOMqJMZNY$)3Bo{?dZs<#;b)5!_Zzg{SAP5*zixp3UjBE!AZ@zwQikJsaju3JSH;tLHg3)RQE6PHQrmar*s-Lir>1ID7W7*c zyeTnTvtP|(wx2_aPxxc*E25$^jH}(!f>zyJbt|V$>hZqUi60_fIOa$6CvGs>=%^F0 zM6C05LtSl6c1l2xpiX4&xePHC%*m`+qw1q z-^91ZAy>Xd^D~@|uPNIQlJ?4TwrRH5;+QM!z0265x4rdinD|tp!MP%WCHy9~U!8gI&%$lnroFF}^5y+^W0y6f+pz@~JnGWJp=# zt7pyBynp+@tM||U8nxGL)ru7w9x6hcEuCFY?Y{El{6nv9 zi{x>RU1St-UE|ERpc{+@8TZ5V{%0RnzyDq8(;1JMn|HfbUwC$Q_QC)SskcjOg!Ws>b|jlU7{I*rGDgpZ$QF(#EN!-}#?k z{eR?$%Hw~Nd#7Cf|H7_T`fmNsm~%OCk|#etwVE5pnpfAlb<(ak3?9|(Kg(afk&aSGb%k6_Q)i#teC$rtvV;Jg8(eIHC1;<83e2)UwS0GY`~12;5C8Vo z=ZT$6F{-GnH2liJ#l;m+@wm#8$7{Y^L+{$&UY$MZChI@iSAWZi{XBif_bprZ*K;_} zxLA9EX{zii@k1IH9-rZ8-L}mvk5O@Nh3LkevxMuJ*;)_%NJ!A~cK_D(^6YcF=S4v$ zXDKuFNHpACkl4)jG1FXKd-JXxPZT+e6RSl!p5D;g<$vF5b3vm?oRHXX!==uN$|2B^NHs-8wF>-(|Rv{(8TxPqdK#t zNr~(S6fLeCNcEdAd*TO)I}t_M>i-M2?AR`5Z|w8z&9z^r%Re1xvn@eedeMf)r~%io+7c)j#Zi+?pk+5Y@L z=gor8UGEAguw!E?pTF@KVBYtMC<$=Av(cQ=QFIy&6 z{axNjuD&c*u^)OkJc{J;JW=?)}N_d zZ=!Rf$fHf{4=$K)@K^VK&&;r~Q1VSd*rDV4Zv{mTce|OGnm*;rSlSd3d$Y&)8-vWB zLyKO2c{Slt^;b>tn>TMBaX$UAz<0J;?gkg7hkNQ5tuSFRHNARc*Yb0ghi@7)IUlNg zTlwuo<$FWWsjx$#KU$!`@_`ZfPb1vMaS`{1RGyZ-)K5uix#WpWj-x*R}Jd)>N*I8#i)rayGgxPIS_|`S4NAhF{I~ zPhxl0?PmBA`BQ@JnQyk6iiL~IH^Y-2{{G&oUdfYN92tEVM-==hWIhwJ$Jf(uA7k*k zy6kpG!&3qO8<{I2@BHISQ0Glws=9LZs%)=B5jT^R9};ozA3i$TZR)jj6Gx0!Vv&bo z)aM%;lmFUSmpw84&L?Y=vPQy_jaT~M>i?C`KV`kUyW5}dz145~yfYd1%VhURiI!J? zc@cQ-JUgGf@?Z7to3|1J_!jP6WO;4p`u{(V{?*_2Yuc4h8jTCxSP$ngy<>CvlF~qKSS{R@(>F6@ei5>-CBtHM^==8jl|KPyE znmD((JioKekA#XJpSRmkYQVAY)-5}a1dBEEOA?sB>{Dh}ko|YXBQCDxb@->!o6kSx zH%Q01KGS(TRaQXu=H9*2&DS&4RDXZ#-RijED$|DVuirhrbya^xxbF1B?R?7*3;a8> zEO08r1im-om$w#|-?#d`ujr{4XbzAeW12?ssiQBA3o9SAb=+i_@a^^W{D8tj!^IvM zCQ>V|zGBlBd%kIN);oKRx<~U2t9}I3uU~g>&$m4{ZbVFu_{-?r_VLzdz320<-`Tl( z5C7>!oEAI*d#k^{`E>Dk{6EF%yJzxlo@rZc7NR98!sR;G)YtCEgXY`P=Kl(%wkS5s z7OiBQE0AYi@LDR3yusMUf*7B zzuwS#`sB#qlJ}0q?}LBcGBerwR=|Jt)^nOgb{6}$ro39P-R?)x+{xXkYkIoH_1l&& zS5MARWi{BlXOC3O^Hp|#e!tf5`uFv(zq_OM5toe#(wfn~?iwyU_m6R*norh8&dw#% z!X`^v{?rnaNmJdQH}^Jsi|g!=Nq07WFEHBiG5T7Vj>V~f?Q)8L(l6iVkks^C5};_! z7cC_sceUAncVuK_%4XwlK7}?e&h0#s*45u~a&B!ox#;(uy~XbHC(NnhyrUHOZJ(Xp zo@0i(mJ?;np4nudX*A9~w#9JT-Ns{In@<0Fa%Ru!2T`-vY)us2l{z!Nz#@6Bb={YO ztJC&xi+d@3`S#75H&?E0U!<#AUN~ju@w+n{uuG(_hYe|q-{Nja2f+S78b180` z8nCHs-jpi`V1Cqca(+BpEt8w z^v*BsZ;A^O_Z+j=R^GesBRdbfUgbO~6Puk=53rfso@&dWrC_i@dcNKBXHO^Ch;Ngg z{bizpw9J7UlIPR&zh+yPRdRV&%%lIRA^LGgqqnrwB4k z^k|v%h<%r{d%v)ol3A?b=J+%9i3eNMzs|j~al+}RYG36~g=ppc%4QFA+4)oS;X~UK z<*7!JQ@m8Wy1S+4q)(hWG3NT5hi@u{)opCIIr3g>JiaO@=k8X0-k9VGwcq_@E6)DB zv!-O5`f|f-Uf(`jo?7y)>+Edv_usyJF`0d2bHPI=4;3K~6`>3hsbylk(y#x&|Ls1% z?$^si35|Bo9Q&2&LD9u34cCp+)6xXGijwn9Hg;Gu70k0JJY-?_eP{iDyHcHRZ!8PW zYwniYSNG@F{CU@eev2d+aJ)>+QpnQWaJW?Vw$`27dbN)a&({srx>xhr_gKWz01XKz zflimE%*)F@zS3|FjQD+aI)7Ys@lm}CJhlEx=9wqU)#qB3dM#PLT+{W}J6rY}U$tkc zsO;9X5$ic%n&0-)X-}P{|Mc>YQnTf^hhAO(;@ZyUMcw`xbH&VqY@Y1rboZNcszGqG zcl)=ucXt2$VcunTRbs1{Y4JSGZPk(2mgnD}u$q;%;`3Q^#fcsd-oKC6|G&rZ(xuBc zI9F9Mn91JSUjF&p)9e2?7jizIccH$TVbg&F33076H(k2yv1zVl;)bOM47twCG+Vgb z{dZr_(vK@AE?(;2D|7e!qic*YyGkb zn*vWBPWPXCs=dLI2}wzlMSqEim}(;oTXTDQapeRW`?%!Q zHWn&P-Tk!46141@i_1c8(=UPQUpdX+_FU-Th+FdGrsPXesou7^!D`=f?w`AAKI8rz zd(rByz0XarM4b%OV%V{Kj_s%E+qe7A4T(~@ud;*E8am@SLzSwB<`wa)4S*726u-kv*?Tu(@B9DDdi^^`F~b1RRVZ#x6S<&8p|HT&GV;Xe@^4j-m9)Hr`pWnr5Ti@G#Eb8!#b9&4V4XUna2;03o($cbO z(Md-3AFVsfBgC8N#9fbw^<&j%+{~X{ASTPw|1_$yiLUhzwK}D z3x0opZ&}~5W0Q~Ms`aEC{WSf!hsrc}FBLVlgv-l(-+YkURy{LW^8LNFvzsE;d*qlL zJlM=W^HDg1LGCRRVXc!#e*9pPIJ)-SZ1eIdbLT$&TfZhK@%Xt||5x_0GjHwAKD<-o ztb(rXUWRMSs+9pw5~G*S z!l$pVf8_Xa^A~e%!lowue#iXm8BgW^GxMIyOI&I@|J&c&b06>GKV9MCx-y~nZ+=w? znPPuz+5WPPYp3#_TyOBrXqW1dchS;!vJ2)uz54w8{PR7Xma7Yj{z$%EWBK{}p$98> zFjvV5x^|sOefhduyyxlW^UMc6pSPFaS8{R@!^$g;+EXoGt1zz=%cy2UBeyD z-ThyG8ZS` zyURDWrJbL5c8BoqBS%(jjnZ8hYOJ^DFh{Vkx}U^{m+A96O{92}j|ORofEHs1tpvq} z2zRH;p#V=lNh6lHxVQ_izuwrE8?D6CCFpzq`Sa`PA0HhJ(3<+;`}gBbtlUyhGrjzM zgRWuB7XE%0CnH^QT z|A!){s9{;MvEB#Q^L?*g-a7W_)$S>A{khR~{w(G4>StW|v*)jt+0vxYdhl2FAI0|$ z;kVr^Gai0ajJS9F)_ZHFg1Xd)Z~o=wTa553pt<^9xm za&N_DmE}o4KRxB$6<$`AU-JV@e(gy9qX4#`G1gEg=f{WZ?d;s+kPGW zkonmuttl!tGPJ8LTKlFK=z@^L^?zTVwQD}cyZXHycwMTLR4-fd@gn6z>z>TN>_6A= z@r0G-#|nh)LuPwMChh)bR} zcUHi{izdJAu0|dBn6ZCr$-UWq=RUcuS3ab{ap9+k%5tZrL5_H0yt z%l<6=m3X*bFJ^z?Z>twE3PB6L=#@jO0zdnTjGBF-9a_Zwe@f9oIYvK(y8lKx48CPu5O|1>s=cZD;a+N6p!}VxTEf^ zR8GZ*1i3m?$Rn z*h7SeDe38@43issDvd+5M3?!_T(dW@;gJF^p|4?ZSZYuj(7E4%(Y z(Jp)6H;Zl3l7OI&UJc=ITmP4{E|4%vDOlXKKhs32@AzlGhoygKs+p zpI7eS>DE-6EG+!`w($(x_4)T-EUdZr|L*PWU($twK4rgmjyU>;*=e!W=S*{B-H&`y z;=Ttsy>I?_|2>U&{+CNlyFSG)TC_-_G4J9c*BPeSV$a`yf3LYx^78U|`-;EE+41lM zd`~#B{bGZ(sN!e-z9(DLqPW7>$6R{)WbSUhcb2NWeBDn>(=s)6H~DWB6L>tGr@=;R z*?d_`6c7eT#nj& zssDEtDK6T+#(kF zwYBSU+n4X=?*rpEr}2hpi3&}gB;Oz{q`=9=^+rg<=llL0J0zrf+X4elEDMT=h*;15 z_{PV_FAe++4tzZIv+diu?UQn1CCu|=_+%^^mON3pRA2U&EBi^fgw87N<^2T(C7D9I zQo9yy$a=bJvB3qIO_TpIEKYfQcXs{HMejQ_c`_Mp{^%4sk@i~BD23yZzr6bUevM<3 z?mhe$yX$wG(dX$JD_Xn+DvCNT{&RMJCG~$<&GQ~3^Cj^q+rQ1Ntz5e^*}ebyff^6l z^mD&hzCL-{d+Mx56@#9sdf`mrqfHuIS66J+t1kUgQd#-$%!~sUCU}TnH=COhG;{Ud zy&-Ao`RUoo+8eiS-P(LaOu##5<*Y8R8`c&97p^x5c{{$`dg0ZUM_FH!3vc_`N`*d7 z{`%@_#pJE~QDS?%9hJ&Qqu5 z9`8&~Pf2+idx|Z5WrF(dSB~q&ITe1X z`Q!fDmwZVnejmJ+HRoW2nTFMs{oVEc-9_3@iY!%xIIm=x+SuA&+#Rl;b^P4i(E8k) zLB4@iwMln0yS7!lSQ!*L(@lj<&R*}bh`q*2y*9;!5&WH2+lMV_>G#^qv)T4jmv{znH z-5oWC&zsWE&IwWv=GwUAdb{`ZPl{sQ(J7Z!T+O<(v$$O)HL9g)b$F?zrKNd7$q762 z;wupoPZZr<@#0}sr_Wk{>ux+{L7upnX=T1C3Rd>#b>;FGDKR@O_`*3G3 z2PdavO^uC>t?k3NZ_jFoweT4z+V%AaC)duiDtseRcBs6j#%9st#WR1g9l07C6VvnO zPtCC+*Jp?4Mz{XD@ncJOMjbQ9p6s%cSobK~rYg&|$rsm4o-X}`7@CT)EBH~ikdmG)CFDE$t}W}I2vcUi4x zR>sR4r&Em7RJQ#%*u1LYz=1udPI(Ds9j|MD(^4K(-5Gm+vCx;@`pj=9R`57aJaqiQ zGcAG0>$BWS)UH@6s2pnfXl$I?n+sU0SH&&kxKG+r&+j#dk-{c=vZTr@zufHeApc}B_ zYL={`S6=^svt$+Tl{r9D* z`8RJAtvzZqlZRVOCt=d-8ymI?CV&5@{ANe0AVc+It#?H`Wi&N4dy14MpWIOQx9V8) z#F;ZYCrl7Xvr|z$CfQ$K-0Em3w&TD9gSc!xedCQz-r;%X%Oeb$-gYfDZugee)jt** zy7Jii`gcl}j&C-meEX+7dw-?krvEFh+gSbF-N?Q)H`sA$&_mG9*9DEtAFr?bt76`= zQHFT}8_UJ_`xSqhKbtU5DE|JO#81)psz3j{_$}!4>6#a%R)2P8W((~ozNe>QF-83J z^_^>u{Q8z-X0cUkS83k+on>#!Z$IhM6U*+MzozQ*IsMsX^O_u2D!7`TKG6I5*_xRX zHWb8VFI&3cYSzZu<9d?~xp}yrnWnw;{HVLpf2-Jr^BTtwT;S+FK2L&AX33>f&*#k`NLk_=tJ3sMFH1`wT>Gf-aQ@T<$G0-IEoywz^);$MR5ZI$v+vatmC5cdyk>@Z zG8QFD+-F1L&jlTAdVFoZZDBx$^!YqB*Fv*A+c`|1TW7Cf&5Q6ZSQ5Ey;#BSMq^qk! z1GJ`oH4~Gr_WJwHT6>l)ClAB5wekOd{OA6F)@7f0Cx6NjX83U0-`-}&g!-RMFD9^+B`T!&$#p- zY+xyUD|jgTZ0b_uskb{XwuRh#x@PALyV}ai#d=ScgxKn>u3%|a?OT<5JMZTq&Bpb6 zcI5<5f57->htzC|+uL#v|M~g3&`>|Pc+*F@DapJt7>vJCN z`M+YG?e9;O)BY6CoYgdY`?~`g%TK5qOnN?VZpig{XWKmOu6&fWf0K3lXc7Mz{nz`n z{yy0Jp6_q~L;sak3EHB^mPnddM+AthPtVhgv6#MkXYF%8!5ztJyxkA3|KD=u$+R2G zqquJ*zn2gZygbc6Sy;_y0TVN`KchnDwUl!cH@CztZm!U|af&t2pkq?t(O>)7*19ib z*pU;(cY2yl@}%VOPY?LE{;x37-0@STKXq~9O4d1#7s=Sxba*z!mYrI;>e6x17WwJ9 zf*Y4*cWhKSJJ)b!xitUhrw^Q+oHkT{&+9A5;+gB${#f15_RWQj$(v`tcyxZ=HEXL= zTh^_c_F7b`mu2TuD*g@uhZ~@bSKm7dLix^UmIOZHASf+GIr|BO#&ABP!S8)?ZJ4f3LPwwBSkA z)0$=-y|icV-}mp~S!S?stML07TYo>=JXu|$npfxG-bG5U7Mse;v#brVVaOF+)o}2T z@1)|p*K7BGThA9;BYk$~jCrS2W*c35zVdOK%eMC?=I%cd%qa1qJJkrZr*vV^$_*J8 zmE2Z>I>DRYGgSYXeR%V!z-MCT=H3auc<=NhQ+5XHZ!$)4#m^3%O}YD5sY3L@X&=uN zVcrQ{SN){z>T6HEs$XY+@75HqrbCCERMb_49yTUh&a=;U@-KI-e)iY=TJpl{uQ!$+ z-v^#QfALQE*3!UUX+?eYsV&0BDbnZ9ONl;wcd_&OyuG={5AOPw!}P6Ellj54!XL-) z@2U3RU{U$&!@adr_4j=`Cs&Y}>bYq3M%H4cZKP*Z+Cf zmG^$#8TWf9W7WKSOlQNj=dS>6vZust1pxT1h((Z#*hGbPN=rK(So(mp%s^~vMO zi3?`(_L^v_OrAUQ(6i%P!zQiTX?OXk)3Kg9rC_hxuiBe78+}cEnwrJWAJx$|sS{@-`k zdi&>3-?nO0_B?oUa`Md$`;K;QE<3EWXwj@i7whZ4pWQmCy+5xZ?Pvu@GwURkgi{PV zWbHTnoql3pv+g5ryCNGiX}2%Ei|0uNse6YP78)ukD=SVux!_{Pf&dL4t$%U5CM@1t z^;Qj(G#C!utZw`I@@V$iyE`jg>(w;dL-N*de&*FtFMhu7u5-oNn~#_Kr61n#%!MK4 z{=VG>KQ?=Z)#{gSvN^J9Cul>|pAUbxKTnLv?|J%TSe0)F8a;?d&h2XoIlrtjhU%u1B;4go^^|i$T+~&(QSSD95XY+ z$r%@wD|>HF<=%PAJ3QayJ7@&K(?-s=#y~%8x1w`f!pBEP)g84tTo&pwPT$IDu*ZAb z^Fup6S=`=yQEHFyvjc{CKYq?`vr2!Oa?izhnP$YQh=NSv=Bn8r9?!EXZHtw?6vgUv zM z+F};Ad{<4LLvwhuS|{_~umAdOgW=@r$fEw=uH`Eit3Te9I3-?CBI^4e)9L=nJ#W6K z1RYti^L4mHQ54hR%C$T9taTOP#2Y)mD{vl7<;r9#`0$mVm*K#No90s-niRCx-m^UXBtC!*mycBl1n9LW+zH)E!^#gW$UWp$$dUUg7@|nVyx0xq= z?RjTts}6 z9&TfQu<6g#>GS59{$Kj@*cmxq-#h;Pz54Be9vyr4&egGKy8p-5E9sej=i&6@73QKd zKB%nRJ9l%w3(tDHC;^v<3aVfE9#}BLLJnj;FT-^_!^6r^2 zHzG1F@F#~(e|K~9-Zi`H_2WLPE53W9D$%uMRFJe`x7?fqLPI-CU)S&X_GO0PyRx!r)mP+Kdu^;d%@v4k1JNJ_;y}G)I({8eZ8HSZd8iUGA0S98A8HB zc}>~1TdIGyMmo=psW8}Z&iyX~L--|67srr$A)$%e7p`Ofs5D^?L!b4==>7+N)9$vq zxkY{Qogw$^n$E1p28nk%F4jofls?M1`fRQB`35nu8y_#JoV;H7;{oHs)AuXi7tdU* zdA@P~e*2)HpamB*X4ps+d!=O+J>o48P2Me@<}dY1XM4@Ru<+1F{rkVEAN=#f{J8b> zegE!UdDwSu+WE-2Va@UX@5F{bEjz>#G+ROLjP`#;UDcOrJWgv`;FGx}@!vA>pA(m%mv(=Se^R`j+jPMHB3s z*1QP;EoFXj_o;Eax04vpR;{jt6Z==4&ORM!oUc32Hs)E%Pvc;bR?o@m@p@WXN?uXHn?GJ{ zxOcnTvHhk^gW~=(bw4LPZ?m+D)XNVE4^6zhZSUE={#(Tgj@5nSzT9T9d)vksw~JRE z9B5?jT<|teQ{maL4{kJ{qrAlpPPSL!_~NYzfPzQ&(V6PMLu2sQGNA`cbA3S4ZTyJKM?B4mh&-2imo5ocMg@uM!vP`?WyA`LOo;ZCv`vC{#$ne<=6Q<7& zj*SU&;%nUHB(+4j?aSA^`!{EYw|(9g%ibe=WbMO)kJsGIyUSG3dOg!rYR$h4(?G3v zhZPK7WW9g<;@z`b@4EH({W-jO@${2Fjvqg+Y-A)P)ysDA;>8IbDgjzk)10q;leL(` z)4Y|B;mxmaZx45W)G#+*y6a0}C1;eu{zdWk?e<)|GqwBXtl8V&&s=?nZv)>GMdqsC z)g^Bf85<@lyMtyT)RwUMA3C?U{Zc}J(9+ZKu^VoLDY<5U4`Vp+@UXklLEgVx7!`W^ z%=XkDVpE-bazo|kv^5bQQ(86EwYNs4)}3QmW1IZVc(K#1EpHF4W_WurdAV_7Nb!pL z|BZXjt@GZgdG&jjcXy&yy~UPIfeY*IPW$`#^!?-hGjk8C*+uNDsoYzw)#$hUu(Wsl zjxGOBWCpE%B=*8UWSjfub+!{Wr!A`f`l!8tLpu5||!)~cPq8*<^wK7Y{{wIAx< z8sB1=aOB9Bho)(jk(yVR_Me_r4QirF?04&vGMnL_{QT1;Q&m+}uM5eC>+1jazUMPA z>L~llX>QoDY}v9HSL4&qr{&c6{F%0SakF>E{N+AQU41gvQ+vZ=_8&TKzhm`BR?vxD z=8>~|TUuIz7(!*O%CfEntoZ+Xe`z>l$gwZ70s2dGQ&Lo_zPt#0-Z+2aEEf^mbBfXe z_jbp%KK1nQ^;6J`e;g6}?wLW-kr}^kC2syPqd9^l_TEnJ@Wdq&tu3x);VVNlj==anHwp_{H|nLc{_Skm#wv8&y?*6cZbJ<(;Sq~O)b*Z-V7lMr!i*5rgH??Tx_ z>(5(8u5`&*xjpU70ma3~`eZDHggTc5p2=ouW&OG9$(hgB4@mjnUvO`s??%@xL+ux*3Z_Jn$ z71bN6W0AKi{F%Q@UXA0)zt&g&J@!lq23-L0W_s@X$9J!8&gQS5oHDIf+FVIrpI_Q6 zry{A@y-#*O=Ymyx)7#TNM=V*UlKEJ8a(-3$>#X;$<^LSv`S@#1$8UalzxIoYub*E& zx;VMtBd*6V-EY3)<1_2bPA-dCa<_2e#DibAK7RQUG`h9{7Bb$oxn2G9^DAqHBgf}n)s5Wr zq$=;;PNf3f<2>nq-^E%xA3AhMXWO^*)Mb;Ml4RHn*Pokv>nAIlHN$}|nU^=z{jExy zAF;QpwE32usC4x8IS<9=e&Kxdl=qBhzxpA8$-z&a-@dsx`ME<}a)Ht`FwL&4c7mg-(`DS2sGmR`0MLC8|S)TmrLwBCT?`R0bhbB!70+aqGPcw?a~od1f6w3R*4)&@bmD2zX3_25-tvLgW$(<~4IF;u zuZS0vIM*F)VXFGmXwCkeh1c@#?=#$Uh`TQ0`}^JId17&lYa=FnV3U1OSpM(J;qv*j z&64w)RRlX-KqDV1X=$J>V@Ho3ol~%4bNXYw!x?{`pPgaic1ZdCiZ2(Pv#$S3j?B3C z!K6>L`r_x!$085uOq)3qbdJ)A6r(qHiW{!TuP8su`%eCEir1Q|2~%cx*tA$NY|}qG z-!3ZWaQ^OY>sl}KnjK8YJxN)Xpnm-D&KFCc zANPuQKffig?%U0D-mL9k0u8rT|1T^qZu|T1?OPSIb8)dvcciam#GaoZ;yA{8(WwyCE6e5{H$K>VRsEifB*XS2Z{yd0eQP^0(Wj@oJNt@lpWKbW ztqCV*S378nwA}j4c;@;l1NL*XDxbD`imjDoDs^Qodv|X#gVpxOd@l@CCq$PhGXvR3x| zwZ{%G&fP5XCQ$2r(EdN4viTZLH8Qh*TEu+zRKl9_H(6J|*&bH@u~8;<$tqJR-&oFH zXPz0VpXqs6)UG_U_h*YEo|EmxT@q|=3| z*R8ozSbb6b|9@v@WSUC-+4`8lGc4_xz16Pp_iW~QY?d=midxN`*JFP(VRluFMYaF= zdlz}*isS45n*RCwS5Qdk&>K(nKKbDA@bKx6IJ4hc& zazoZ<#2u=utdtbfsWDvXwsLh@7=pxoqhbE0ncJ_#VHEc z3OO0t zw17?s5?p`n)t5Jm;(Q_$8Ll(iudT37JC%J{C)ZwEH_p2B*`2*rd;hWR@M5*z|K4*` zL*S=Op7q6A#>#6~Epn=r|6&))kikqP!Wx3+L*Ut5!?cV|zf@slD;^_sHB$9gYh zm_%$yU}R9x)m^%36KKr-_tW~tL2mcto#ierjqc#AbSZiid8p}RSkUY{Co(&e6d4ol zuMLiFjd!URp11FBd!O*Ph1Y`0<^^|}X{fC6TQ+6N6p=SKH!qLdUXhe^Xz#7`%hg+Q zuj{z#Z2Px$X~g1-Qy5pgle~Mq(?5FU$-DJa(A4BVHN;7894GaGAVByIh?Cswl znbrqSp3IeKcWsa6LEj~xxhs?AFZZ9{H(`Q6MRoPz+qY*6OU;-x$tj}gRcvuHJHO1Y zCBLt20q5R zI^iF8p1U1<`sqrK%%o_yXIq>DG9=FbTfXfGXml|#l=~yU$;wZD9Aaj9cR032oz)O~ z62CL1FZp<%nTc~u#skM*WzJAWU zzOj1opUvFjdM(qZi|^U9#~}Zn&7ZBs@+WT_geh3EJ3Ayy@Q=-{`}_5Jnq&jV;^4$Y z#YsVvJU3|t_NdfWyMOuck$1v`maI;fCPn8qhowP|Yr~9xihX@}z)`K|^o_k|PV&FJ zw^MliBb%F&o-PeaVZzzDd1r3L+T_2g@aA5gnz|(O|JJg*ff9Q}Q@6f9$Jg+>ZT_|Y zS9i|#Uz|MUO4im+1zv`knVnDm8iwv^|H}LN;Z@}s;@;QqG5a(wcoy`{Li+ECg@0?U zs;-{bF{}QTbK+@{hl)^JOGB@+d;ikId(3Be`w5C1)UGkoH~(uFA$Q2|@bA+6>nDGA zrn}ZoS!@6Q(|i*Nt^4=bY|FK>e(N*aZu6TM7`TUJ$XTk~3ES+z1wlmZ2=rO!> z_ddp3_i$~${f4dOIVH0h0zN&ETjoEvBn|0=un95^*qduI3Zv$Mm~ovXjSY4lM${PMebrI2-8!F7YYwk&WW^v!x@#?1bu^&yvk)BI4YTvM)aWgIc)>G)e zYlj_o*uksXzdnoW-D3<86?pLcn#^3=qKx{Zy|c}yGH9v$&ie4=RN~hMr;dKURs56n z$fu(+o6h^pHrTdN$Nk>DdjT3E9esUniHQsC6ct}Gy;`NLgCKI3J?2I{gWYP8Z-R19IoS)OV zo8>aE^aC;D;!m7!-=0e6@tbdXdYwc5+OxgVaTly_Jvx+`eXV8+kMp5zTx|hj)8p&@ zy?lOhbNq&m-SsCXD5kYun!MakxQQX{Pr9F^@v@0$ivub?&$3groGall%Q$c5P5tG* zb8X&vX6N1ARXQhW;t_6khSt{BkeV8sNbVy{Ih&q|oW@nA(^eK~OG0&RX96&1w`)b$SQTSsD7ri zJ3;;N!&#P}CH?mK7ZnvPzO}dZbC;c-=J7jo68G2t_M4Y`tK^;F(bK18rWcsWAG1uo ze9Wl0?&qhcy?Mcr6`}P;dY^@Oirsk}%yNC+A2^y{|Fd~=bai)(Xz0|eJqG1zX;I&f z`k1T>bB#^7c4m!c^1K~subd}-;w$}e;$uv~_sV28)5zW1EoWZ}}K={y{Icv65XDp04f2>01MxIvtJ4QjZKRYxvPhL;h$F+Iu zfsHDxZ7wYzGIf-7dyg!?_T|I7hqq*8|9w0zzd0Z~wCmmN{^?)!taWD|nOyWqo9VEU zw6FBeq@!G*Gt2MYyLV%6ws@k>%IV9#ZVeajnPxTP6sZ1g^igYeQF1IS+!z^GvNNXd zc)$GP0|%Qm4Nk4+=}k)w_-E$fA0i3b^)X#% zt@|a~*`kd1J8?NYlNCq}e7J?Vx_o8%d)pZ-&aJtoFANL+{CjPhf42TzYh3zcp;>D# z_lGXMQT(7ns^^%!iA~pat8*uPG+PyQ7O7^W$u>1N&D-(pNs%S!l<;Tik1kC={q)4y zlQ|b=MeloY^WrzYX{Wco`gHupj?{dqh*pl~LrT&qXV-R{YM5JpHq3DS!kCe|Xv??A zEnEMxF?`&l+U@p9lO-xPv~{g@*`yk^W&asunw*_01D~cXJu-FCJIlj+{%^k@Wf7H> zZpj%?TB>T6XXo=td&Z$UM#VPE`!}jo7$!^>jOS{e;L5n+`|DfR{{DWy|Ng2ETpLb& zU3dNU#+sYn;osye=W;}?)NnbR9Xf+K{cOqCXXa^^kuOuuUJ3u~x-I45pO4>yP9OJK zs&(}J>}^jEo_HlED0p!7|C_p-K_j9<{j#@M+WcpkaPBUDziq|F;+ut{8PAjo*7C@F z>eI7(sMeX4{#ZzFQESf}-mO6eVm|jd3;!xS2h zv{VFjhF!k6d2e=bxtX=HYxR#8ou3)51g+d_XP~j>;=Y%R%sei!oF5C1RJrp-MlwijtcSGPBRb*rP1rqQ@|v*lYf}z=NyvElhs!N;mQkKZ z!S8dn^D+V=b`&TwMD3VsTWz*#^{Nm3^?T}>mMI2Yx;}l6LEgXa)6Y7OCiNwp5tm%q z`D)dxSwRxL`|~q+^p7o`BI4J$VA_fG1z&i%@=NBs_eeDE*<({tUH$me&X~t@6gFq; zsV$RV|Ks21oiAUldiBakBI$$by}HCb5`B7c7WL9wj1KxasczhR#`@Lu_4gC(zMnkh zvp#609B72$*x~~d4C0E_Y)x0LvpoFuiF@1kr^WN{^c-0=$vsu|fmHL7eT;j5p8J`d z5E{t-peW_Ke)R3K*Qpzq{_8ejhv%LJQ@N7PY&zm}Cerxd!#~$5cz_NBu!oV zx$xiZ`>oxs#cnFd>RG*eC4151Wwt6h`)=A=^cL0|9Xk2h*vDD$)A`g){W#4%yusg? zvY&^0FnEaXHCR4BTAIIm^4d}>-EHq~%mku`Sz-5SMP|9{uwy^|(Q^4O%s$+=;sMWK_AbgR>wr%#WHT$}8n0$S-M zeWko>5$L|p$1G}PYfKI=mlwKudbwlowZ=C*YB#UVlC$Z1U|e-&h5D}N_W%DBd#DKc z%(s(W9k%w+GT+%7K0cTCE;=7?!|!~yD~n;$#KUYq_kVr2%3pSFg{#mE*QzX`hqu#? z)xW$m(QsW?pV;~My>adPx4l(+y~r{%ZRXYuPkyE+-MO`8>x%O#EDGA{%NhJ5igRP; z-aVYu_Q9*p&);_!x0vtiML&b9cJA1|)kcoh!7WWpa6*sveWTAt8VB|#roOnt@a<-Mo}GCn%l>+nvCQL8^Yx?f>1H&LvhHeeL2``;uOX>nAUn)&GC`UvB^RhvMvs3#RVnZa#Q$QjF2L zS&=`^ypS;GKYiVjLB@XOha;w!uQ^{_R(_vx&ov)6H!H&}hHQIwZcca8w$X|H%wU^# zo9FrW`f3Rg_psT9WeG0s>)-8>F#j%VbMhSH-~9D|4;psx$=h8~DKWMEnvjP}-z@2KFfDlz%-bcrj$8awk%{Z~clIl4&E_so zua4Vz;F!kF^-K0ef6tc5T5IdiE1wp)gI)8(^vUyr{%-hUc>9woQ-XQUjezd^%$@VY z?(MDS|B{qCy*WKvW=?(N?}I@*CtlkFT9y~BIMKu6WW=+AS64iP(wokx?q2BJ#xvPN zMaI9?MXAwiY1WNuJGZcKfq8a4TbK%S_h6#42B^@W{ZLj>C#=>IKGyUPIpFU@=&h{!UW=qf% zWB$cbntA_XyZGYc7awm_c{t^yrj${I!FtR3pD}IQ9z47Id+Ynys)EPt`K|pGH*UmH6Z}Q%2*8y}I-#!+D#{G9nC*KC7!gBYFR>^@Wx_%DS2l^`bUR3v*^=;^U3@ zen3O`)xjrERLTT5q&+^K%d$g%w>y8FkLJslk}9+Ju{9hy8>^Um>fF2gU!U8SriOaH zwOtXwo%zaxx1;5VimK0KiKUDS1M8-3;cgIoVqNm$!K9f}U5`!MlOBCxYIN-U`G!_$ zH-1z$-@Jc!N1^iMIje(K`gGltSo~w(B&%YxcQQLpwv`D!Gx=YgO^Rs`Sa(Z>)q)PG0ZMwAv2HD|B*{^LD#K(W1 zF~e?#NhWAliHQ{Np1pe|^@Rd&g=mRx%e~FU@Z;O-`g?o+FZf}_Bj#z#aC4h({U13I zshcV5xPqp$Fm$~W2~zh{pWm#w--+kIy4~?A`%CA{@{uS9O|9(xe&P?4vu<25ORQCS zL8rgl-0XKZH5Vt%o42*VV1D(T@O#Vp=5$%}PuqIO-r~+||Je)=-ao#pW@veL$NMFh zHvhRgeZIVD*`q54cHb)^f}Gyo**srD$>OKz-(N1j8B2;PPr>gFQXV2Ecqd~^>;!J+YU?DZ~OiQ?s-;I=H}#?TfOam-G@I<0yp2=JmZgo zv2LJ!<*hXpd*jwK$=*7~7d)j=?snT6^`Na$?9CIDS#>|0W;$H;DbD!ro?E+Bmd}ng z_G5VRIn77T;PK6!dz`LM0o}QE{zz;?py9Cv4?sJMW>38a9_~)x&+}IFaQ8xOZRM4F zw)t9L(VDQ;{&Q`8$XoaD-xm)Qta}}CeT&Hq<9m)-??t3cPh9=cl&qdqd{9^9#u~SC zZ5m=S=2w?I-23Nt8K=R|d)H#wJq1^%Jw2YwBH=x0_v$;k3MxI*8A^VYcvqUV0HF?;t)```4OFmYnz@_AKV8w4jhU%Pkn4*>P={{X{)O z{r2D+{`?L)lTXe$tgI9R+O`*>B`7O935O5ky%;MVQH!2#@?q--CYx_TYURg*zR}d%T9Y0 z@6MbZ6}7U`^JA0v8G)VmLqps|rU*(*eQ0#}%;7Vie?OjS{P_&4L`8$-?ay_4=ZR~a zpJREx^4!mPpKYI4Pdu6OOr=S_<^!Wd+rb`5;|V#Zo|b((llgeR-LDjR9kqZe2D$rn zUvEa&??_*EbtpAA`6(q0oPbs;6T;^ftak-g$DsSua9lv8ASNX0{wLbRa zy8ig<%)AT^iDhaZ8xt5d{QXn=^l%$@_cUgP&(G~mpYFf^cMJ0zrHAa@O7H)l7hP}r z>CvO`>D3iwcQd6KK7IN$E1|H&^u5gQpTE9zN}4X?Kj7N0EcnFg@W=a?Zoe`Pn;7xP zU7f>AX~yKa7mxgwQ)cK~-@iTI96zl*OjM_U$^%> zZdb3Y@=&X)^yrZ@+8C%db)!&chp6ONgBKDKJ!-qv49gu;jCuvSccxA5NX#*HdZn1^ zs&wE+R)W9Wue^(2(yz~9d2spo_1*6$JUlc{lHu9;>ZDKn)_fn1_w2mC_uq7T+fT1% zYlr>duu;|4F<}oim_O;~uM>Zh9=UU``oHn<@oHzko!rm1&hk%QdJfG-=m#{Vd+|JzL-Y>4%cy^ZypRKDefo z!h3u1zIo^7Ma=N+lB;@2sUY9TF0@r{1-jwQK#$FE_cx6TKw9K5zZ3?zJR#yWYz6`wz<5R!!OenU!JF z^!O-?yV3W)b{MK~o(=x|jGv2#Cnh#3YSzlDS$b7fRVV-a`oh`U-RHHd_S2Qdq|T-9 zR)?*1a&c*~+};wkwoFSi)bHBK?hQ9U3 zv;5xI_7$&Qy{ZYBzmsQTg!bg$ydPu*gybhrkdYP8uvuJH7Usq(W8Lvx?b<)l@As`+ z{~Wxil>PP9RR)X6Tc12h$uN=n^ZD=hu4vx2)en3YY+*Q(uUGx^;&QP+C-wZw+`U*C zwB4(h266VfHJfH%b69+F#^M%MHnvA8$2z+=)cv1#diuHf?=;{4s#%+vcZ@%}T!7u| z_Jp-}?>;kPxYzyv$Cr})%Ilw)Kg|4i|bD(=s6b#?Ae1J@mo`M?X)(VLflCa+!V)9Ry@{q^%} zX(<^i9ZMrK&4@d^rRPssRdVtvJ=pu>P4M?qtUvx|n4Z1y;qkm}zj*G8oK>%JdBos& zzTgu}C7aR5>NAx!-%57+U;n))>~f2I*)lO^f&B*W_uYQ-@6exAw;mbSNvBGs*Zxxb z*8l%T5ZeNNhWkg)+uGdqK42{Tt}^4_fTorxpWfVOtO7GO)-zT2L)g>w_E_}TB z_fDv>nU}a^Wgfj&b||><>Fcl3n-3oC%w|ydc`Z7* zbxQbz>DO~iq@)uj?^ntTiJAUcoFQh46sY%8Uw^0geJ%65o!|GdGrZfPU~eyfyZr6Z zWxCNDGcGErsHi;XHNWRjP+)K+YpdlVkwCv&hcDdf$~Vii{8mP~PyLVfh@9&dA8Jw6=e{ zb?xPvRWEV>KEeFGH}c!}dYy@7MncndBO@a_IyxGh7BU<*`0)L^`D{l+p60XmZ*BNa zzq4dGaZL5Tn$9D?#60iKZr+bxe|~)HyGxP{KSNw+XXoSHs~>P)ekW~^C}sX^m-MvM zjk(|F=|srnFHLqk&V8%#xv`Di&H9R(Pqv4=i_Xm3`+HO3-eMir2d0IOTpTz34+-@1 z4&Hp&j`@Qh^Ze>Z{K>yrTRBTCY&|9|oG2{b@43BK{K|9h&&DNZrE<9$PHtHlylbs~ znR;mY=Bv|Jh1MR}x;nn*Pln@Xk@*)-mh(!?tqJe%nR)G6SkA3Khu3eI7%ZGOTj9lA z(I=_j+vXIBuQA)Nc27^oDLh@lZt)Qz=e1#v7x&vS9avlXZr|^`B}&DYQ|U>AR}^|F3?ncSK~l5YLm_^Zo}lpmYK?C;3hd~Rak#6%}9 z?K7u?4lOc~%#)t3qVb7+{-sAv*JO8pf8Mk?{3_#t4>Js7y^P!}3JkUii5V+>ei!>< z!3IaCQ>;3>&pi3QX_L|ByPsZNUA-~yuGQyrTYc0HKRVid(17PkmT8EV=#{L}_P%RB zZ|=`LKQ&%S@Yoq9YonTu2fx0vb!`%I{+Q`18e?x5ptp$}%xYi)DoIJNk4w1&vj zwl{Cy6y0c_`L(Z0Qg_YyC(pNCO_xQZ-v?c>u<=xgY<_nz_d@)8R9|K^Oa z>9S8tlph~2x8w@(4~m#j%;*qb&}}mR!a{TR{ii+b*X^xX`H5@I-vc&_A0OlBHkvy7 z_UgWEdTn!lRWg0(lbNV+WBF=j(9yOB4mf;%Y5CDq#fw$m$o=M`T~VojKCGVm^ud{x zOAF?H-d0(xoRSdW5R$X$uFU@QcrE)5pY<-{uRS(CXm9u&_2I~uLdS!NW%GaL{bnrp zvd$O1Y;LDlR&b?5!m;mKb?~>R&CjRU*=RWhM7Y>R*WW7QoAb8Hm?7;{ZfA27JHKFx z^oQFY<2{4S>T+`V?d$6u1N#_2(=Q7H7A#r9a`526j=sLU%Ue8`1~E2FRdVu)zm)%E}D{NAtlx8vvTWAXLYfed=hdE5*q zkLBGN14CE@?S#K6V7&xFb_`nw=#<$@3`>rl7Mx?`mUe?!~y%y{3hgxO8$ zj-QoYu2d5mnQAj>S|D5Z?55iqVri2X?S8+7pD}#K-__eZF9-2|KUI)%&$BA&++yR_ z8}iq$#-)Cjw~J%yPCCfOFDG(Ec52AgtDEMp`T58|CoSOEarv2+z8*8DPMvyea^%hD z34veEcvknYEq=fl5Ej<9X_L|NISQRl8!J90X-xH6aWyL>EG+5cqocWXYUaO})V;la zUzXYbrqN$dF2%%IRTIDT+}T`E`;Y6uq7-ii4@tN8Qw%b5a*jm5-&4#nC*IYVA?N0f zcYi&Dm*4(cy)RRGV{mT&nl(C`7ysRsds|`p>9c)*1qB5sboKnwwf|egGmY~$hr_Ss zuHESz8;^!xy}Ch@y-+QHUooSww$k3Q?=@UvPV8SoO@io0NSSyOXz0Y5o0u_hd=+ zFZXk9RPdM;z3M-&J412F`K#ArQop||zwx}TzpHhsc$dfd)Lz^aF;cDRJlT*=XHc$M% z?(J4z-?LjEoLTUNVZs!fgF7F*%AGKOdNBX*yG0BF@w>woi$4cTb1EwGOo;BRbNxH=fd%~CRKa+?*H9zHZVy! zT+t}@(X7?sU(VG$c&-0Gc=3*ck4!u2uKYSTyMFHPAHnCXc-T+ff62+iQ!+#T@V9>l z4mfB`_1c_pJ;P*%VKUpSSyCHIUIzX9t$xwW#;w1{OXL#A&z+GeGM^tG`rb0fXuCOs zr*m!XaX(kRwu`SfR=z&JdW$K+$;Z??BDuo_g{)SpWX(dOSB4UU5FUAp04L1%ZP7GS<5*9Y?>Ppu7=j}5N z30}H%>CD15Q7%>ny-6Vj1qMBC%G31XO0>2wn6an+QLzfs15=% zy{=0~wN9O1*&=><^AwS%uU~~+|5+Qxe;^>_#lOdILp&GmTefW*o0;cRh7;}X$GP4Z z&&>TQxtjH23+HyuA`4yJbC<7QiCx|LwX-|iXU~S6uU)FDOnth%Vh*)9D5icDsoW_k zp2*p}l6ir?)~UkVb?GKj8*^TsUcRZQNaoba6)!RxU-#yOpU@0XoVwLcD=gyLuf7Q< zQ=U!u{_o$v1c_s>t{jRy*eT_FuZk+CI9#N{V9i7 zUw{54!ma&#Eo-sdtVb`Ft=-Kpe(0;;D!$i$PW&zJm9o+Cny~-SwYR&C66b#LzoM_; zP;l+7^Y8jhJ=@xCGIyBPu{IR`Tl`(^i@d<4)MEL?7aQd3Z+VsN^Ke(1>-qoTt@Yop z#;<>UY4^>o+2U$`b8fsmzxU%Y>1X%Nb8bBNFz;FzTmGJJ*Sk!!?d>@hNIB^0JWEu$ zz2V>CtN(A7`#!Dt8(;tT>pHX4>6$0buW$U?IZ?ZOjz>-|Tf@8itL<*D&de*SQ1&$Y z@t!{{E+Zpj4eNs5-af8hKQ5bg*Veo_T)OIN){-SlZfNq?@WZG7)0{?s);aK`*-=IsAmf(-qU#_zgBU#;F&`uyIu zUp-f!h5ngQ*d*h(+1U7m@r28fFZY(;Gb{QKkXU^E{O<45nGAa5rHu_tYL?ud`DCL` zw{Gorz+#wU*%?JHqNSa>#~2B zqKi&l{UCm9-eck9!-tfTs;`9Qe|>fJ*@R6h9X$Wt} zUgi1N?_8R17A-mx5Ky#@N$lt$4u?D2;~O3@ZYaF`{pN$58`8e1-OK#DD?Be>iY9~phEp_22~;%(d7=31xwo!lQ@JBMij z*PH`t%+uf8dclw}B|JO(UVXajzRh3D%{J>jytLGNZk=0npNwr3OZH`la6cZmg5)6f z1v__qxzqZ;`u*Bq6-@#8wnT-g9lZ1Fe||M&I2#u??~$+c{#xaV4*|PbJtHF}FI~E{ zAZ+!*5Us$-$eRoESr4cl+1$$!7QHw{zWz(&q^sHcx7Gfa3f_HEZr;~|>Bg+g2V9Rv zI@eu%$@S%&rcmIsFAQ6%zb_Yif9qdz|J_uNRsRJ-O0a+;*pF(!EK+?;0xCZhNrO zoi%lBxmeOK7p2file><~Rr9#_%ayL`d3?OSm|fm$wZZ0OVWCMm`5Ibhb~B2*f*QmI z?@#r3dh~4BtEg^0`N;97@6YY35)e4<8F^+!h2umkKk>9!_U*-fIe()WC4RH>32f0W zT(x9H>Fe{m{ThOG&Io(O)HqFXaC`uwD+kkx6&5A zy`!k|t4TRZlI?!}oduG{X=e`R+P}A8TfpR?+OT?qS@WgOum8WirT=~Jw^yg1M@2>5 z`upz4kt2L>|NaaK4^KWj%hXEo{Otwn(zoaRw`9L&y<(kNbCOSKCQHHF`Tu`ad|%xy zKKHsw^#1=-rikqMdacW8@x>b)4LA2B-ksF)aeH*@I&Do&$E++ZFE6h%|Ca}?RG55n z!n}F!0y=$seO;rXW<|~rjt*-}{P5O1KJ(Gz$Nca9JUw6-vHyS7hc{2%kM#+e^nETi z`uTXr^0(6>3yPY)-2AokvsjKzjlt67v#Te^>?~rLN?0ltu6&wR=n13Tod@zb{|$vb8m}onKyTNd;GHqD0P*Z~JFmT1+8k>x9|{mIfU|#Y~_48coZUE7q(r(H1{>@}yt>oL5m>ZtQ%1fHT5R zC+4a1N&l4(WG$7>=>@$!Dg5&JLnYP~wnq=;1c^vIxL^KeZSdPe4NGM#T+~#`Ew??k z_Um#xqRLUU>D;+fHms+WwzD?aX=r#nd4AtN;7Zrq=z1IG1#DtRovt50&wlu^5bILu zzi)3$R4O>s_ddr@>>2NavWQjoKfd3ZqA9GtMAqx>Vq=M_Jf8_47S_DV%Kmutmg!l} zWcT#*)oBO)mVV0OZ1~Ke$FPIv^hYB}j+BXM>;A9ux4&I{{7L8W?@QlY-M)3Tt54n> z#m7fDA3r%cSzAe2nbq{z%SngQ_Rb5O`O529i?%x3rW042W^c%1jQN@JHoW?HzrWSC zx69?XJo#HueR7NDZ@wo?8CB&+rTOjt{IFR)M=>=uHDLAC01c59Yu30_Rqe9e85-PQ(X--MlpL>X9&A%^?pI!V|c=Np7|3l|yMNM7&{XWZSwN?$Aq#X+i z=S-em%k}N?B6E>$HilBGz5h;q`7L+j$F)!9daGY$?SATAcXRLR(mOi}!w(&9=hRxh zWQWJ%>&8dk1Z3};bx=BA+y0mTDOursU+6yz?r5t;~+E z{d)E2j2k!fPF`->^Cqp$u-|<1WlM$@_kOV}>7R=Iwp~v@Q+%f7$;YNi=R}{Sni%`6 z<`O%)NR+`^NiQ(qud%WJyyla0Ov*|&CCooCPr+P$vB;f2UNY09eM`d_SNtowTOT}a z-zJr{3ijdGZ`^osWo1TrV0d`<`Tv`@Rlb>Fc$0fxZC<*suWx&imX=l21#9gWv6fG> z)?CY)c=2OXQMu)5clp|s>6y20CYUe;M9sKb^tSC6*P7=)?!|qNn)&B`b$HPeUB$pM z>mAYCXPOl9nZNwz-P0O6_rEYd$#NbW2tD5hcM0 zF&!6$+Me{nLtRIb=0>PwefjWVN7>S-%C^KApC7Pe@ z!Gss-22!;LHch)MIBn~fxQQGMCo}}Rw+eMGiPI9i9v2v=d+qht=Lcl3PGa39I4A5j z`vC@qW=0-H0k(vIl8}lYe|{D(R`=U;IRDEHl}!2n`^tJ(UCdCJUjA>(|9`*VyXWNS zq@CMwJ|JSkV%wT08M&wSUHKH&{LpI0$;E69mrAZSoc`c*==;RGQk*;Xz2H~iaL`!) zPqENYSy{gR&qu+@?`J%kK4FH&$FHS&Jlo=yAKsXpd1hJf>?yPBe>{|7h;?vixN`aO zMdnriv*;kmii6X(y*f7(2G-n_mqUrO#2pSR7(2#_u+F52SWC$q|SM%9u# z7e4+@KOj5t``0fMc;!sB>{f1cv~{_CNhrr)6QkSWi|whAni0z8CtOncn9QfSDlPU< zx#qQ0XseIb+Py(*bqssEy&`1vIv3~rZ`~;qb7_6!gI})$7!vpGvr9a0XRBX$YRbyL z>VEScNtz@yTxN}5w^z-jt|Nr^u zwNbCzZI#KMz07PZmCdP3-ITRcd)+i$l(auv|MM1dTq4}<>Kn8&Wa-r`(b84fOBwW< zf@euG6zTi-PuTJBp{K9UYk^)j`5c2SY#ZDb_g_@`y|d`eB4;UAoz+uM9?9Zgxn_9)&~LiQ&TVm^me9xSV^^nW_m?DJ`?b8| ze###8&3mWbQ4wNXle&&IL8RLyYGufpX`U)ur%x?Cy3A}JPu?5jW!rc+y)A$E(E0Fl zJ45xVQ&U#fc|Jbo{nz^9`#B32E@WJ)dbF*nsU|loE9>pPTJ||Jm+KUrx?EgP6B84Z zoP1cow_EQXYG5HHb!Vq^|~r&JMOM5VbI-p#$8b8YWbVo{ryr=@ ztctL*$rP^-p3Ba}VHV5mbN?;7gPfJclKUMG5C3j$=l?wQ_m5Lgigq5k9j*86!-TDs zyHuGJ#F%?~d)MmfMjih8`ufaOr?1Z1oPPSXwqD$xyehXO=hbZGL5q!IOP86gY)@U@ zCZF1P!??ORxXn~+&`MTlFw2#iAr+jkN-Y)ptc_GupcCyf&B@0@%{_nAN@l<|q z&k-Xp>SdqO&vm`}^DT<8ID0?q%nbJK<+tX7l@6;m3*1&TPCNKfjkwNpZCkTG>9` zLuaC7@0t^PTpp~IJ#qEQjSH(TZgwY2iR5;rcY*q`X!_UqTzkCT7>`sKBE@7|+9D?_eaS!1|m%NB`M>qE9{ z=*0x2r#%gOE!lP?^!aS=S!ct2r!VO(f1R->bY|VP*{^ilQ<)d3|LT#L);sIpvhPw^ zS&JDiTj%FHUb$vGVMTyY@O=rL1^=!mT5>Y%aE-DL{yRr=^>T&JqLE8JKG)t9F#TZE zx$TzzM_t^%cK7sr`1<~`yV~?>?>&2Kj~LBtnZ5i-kaX`9;UJxcW50fdt#wP@QTW)Z z_@~#_Wp8pS|L!b0`hU@!B2}S?XG<72obhxqE8FtzrEZ61q417>1)^dzou5_6R+aau zdqoN~D603py;*Zx_ItFe^6gETdq16AF20Zd0Z)VXgJ0psRi2Dlr^64Ns?)a0TQj#e zjZu8plpo2*TV<*PjFCRfhh zw|sGx;j*HWEl!(^jrV+4czE^tZsD)F&#q2aF@5aLV9@aT53gD2N_O=lznX-f?F*g0 zdhaT|@ajh|42=#>_KdsY80%po^T@zwPFv}Q8@c8))>Yke&B^)sw?lqsLw;1!?P*^h zluh_G^VR#{z`%#Gfq@ShPcyaZ-|%c%A~yTi4XgS|t$kNI)76%_^*&HzepKO?v+r)A z&xCJ}K{yf|8I@W2fg$z2Uile#hKH1*= z`pbQHQ1S z$GJ=l>($fkbxtgcj;uX8W7@aZk`eB_ii{R>CW%iC4d0`+dR@h#sy!2r1iE~iQ11Ce zK2Yz+#5q5@YNENjwjGl;Y*qUG%=TuwhyC@L|J-D{r4HymIBAjD{cT>OM&uIPT~YOq z);k>AW4@zu;jxpOs=B`2njtSWcS~^l=PL&f@84B4Z`aMIQ?xh6uJ-gje9d+ZObE0FjVw%$eR=#S&?G>eoL

eD(kHJ+eRlhXFjkK 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 Z`jYB*%T61HGB7YOc)I$ztaD0e0syF#mE!;a From ac74f6f20411a4ba8d285072901d1c6ec8c19ee2 Mon Sep 17 00:00:00 2001 From: Silarn Date: Mon, 26 Mar 2018 19:58:42 -0500 Subject: [PATCH 0463/1544] Improved save plugins parsing and image rendering --- src/gamebryosavegame.cpp | 87 +++++++++++++++++++++------------------- src/gamebryosavegame.h | 20 +++++++-- 2 files changed, 63 insertions(+), 44 deletions(-) diff --git a/src/gamebryosavegame.cpp b/src/gamebryosavegame.cpp index fae0a24f..e59e973c 100644 --- a/src/gamebryosavegame.cpp +++ b/src/gamebryosavegame.cpp @@ -86,7 +86,7 @@ GamebryoSaveGame::FileWrapper::FileWrapper(GamebryoSaveGame *game, m_Game(game), m_File(game->m_FileName), m_HasFieldMarkers(false), - m_BZString(false) + m_PluginString(StringType::TYPE_WSTRING) { if (!m_File.open(QIODevice::ReadOnly)) { throw std::runtime_error(QObject::tr("failed to open %1").arg(game->m_FileName).toUtf8().constData()); @@ -108,28 +108,32 @@ void GamebryoSaveGame::FileWrapper::setHasFieldMarkers(bool state) m_HasFieldMarkers = state; } -void GamebryoSaveGame::FileWrapper::setBZString(bool state) +void GamebryoSaveGame::FileWrapper::setPluginString(StringType type) { - m_BZString = state; + m_PluginString = type; } template <> void GamebryoSaveGame::FileWrapper::read(QString &value) { unsigned short length; - if (m_BZString) { + if (m_PluginString == StringType::TYPE_BSTRING || m_PluginString == StringType::TYPE_BZSTRING) { unsigned char len; read(len); length = len; } else { read(length); } - std::vector buffer(length); + + if (m_HasFieldMarkers) { + skip(); + } + + std::vector buffer(m_PluginString == StringType::TYPE_BSTRING ? length+1 : length); read(buffer.data(), length); - if (m_BZString) { - length -= 1; - } + if (m_PluginString == StringType::TYPE_BSTRING) + buffer[buffer.size()] = '\0'; if (m_HasFieldMarkers) { skip(); @@ -160,10 +164,10 @@ void GamebryoSaveGame::FileWrapper::readImage(unsigned long width, unsigned long int bpp = alpha ? 4 : 3; QScopedArrayPointer buffer(new unsigned char[width * height * bpp]); read(buffer.data(), width * height * bpp); - QImage image(buffer.data(), width, height, alpha ? QImage::Format_RGBA8888 - : QImage::Format_RGB888); + QImage image(buffer.data(), width, height, alpha ? QImage::Format_RGBA8888_Premultiplied + : QImage::Format_RGB888); if (scale != 0) { - m_Game->m_Screenshot = image.scaledToWidth(scale); + m_Game->m_Screenshot = image.copy().scaledToWidth(scale); } else { // why do I have to copy here? without the copy, the buffer seems to get // deleted after the temporary vanishes, but shouldn't Qts implicit sharing @@ -198,12 +202,12 @@ template <> void readQDataStream(QDataStream &data, QString &value) void GamebryoSaveGame::FileWrapper::closeCompressedData() { - if (m_Game->compressionType == 0) { + if (m_Game->m_CompressionType == 0) { } - else if (m_Game->compressionType == 1) { + else if (m_Game->m_CompressionType == 1) { m_Game->m_Plugins.push_back("Please create an issue on the MO github labeled \"Found zlib Compressed\" with your savefile attached"); } - else if (m_Game->compressionType == 2) { + else if (m_Game->m_CompressionType == 2) { delete m_Data; } else @@ -212,16 +216,16 @@ void GamebryoSaveGame::FileWrapper::closeCompressedData() bool GamebryoSaveGame::FileWrapper::openCompressedData(int bytesToIgnore) { - if (m_Game->compressionType == 0) { + if (m_Game->m_CompressionType == 0) { if (bytesToIgnore>0)//Just to make certain skip(bytesToIgnore); return false; } - else if (m_Game->compressionType == 1) { + else if (m_Game->m_CompressionType == 1) { m_Game->m_Plugins.push_back("Please create an issue on the MO github labeled \"Found zlib Compressed\" with your savefile attached"); return false; } - else if (m_Game->compressionType == 2) { + else if (m_Game->m_CompressionType == 2) { uint32_t uncompressedSize; read(uncompressedSize); uint32_t compressedSize; @@ -245,18 +249,18 @@ bool GamebryoSaveGame::FileWrapper::openCompressedData(int bytesToIgnore) uint8_t GamebryoSaveGame::FileWrapper::readChar(int bytesToIgnore) { - if (m_Game->compressionType == 0) { + if (m_Game->m_CompressionType == 0) { if (bytesToIgnore>0)//Just to make certain skip(bytesToIgnore); uint8_t version; read(version); return version; } - else if (m_Game->compressionType == 1) { + else if (m_Game->m_CompressionType == 1) { m_Game->m_Plugins.push_back("Please create an issue on the MO github labeled \"Found zlib Compressed\" with your savefile attached"); return 0; } - else if (m_Game->compressionType == 2) { + else if (m_Game->m_CompressionType == 2) { // decompression already done by readSaveGameVersion m_Data->skipRawData(bytesToIgnore); @@ -273,18 +277,18 @@ uint8_t GamebryoSaveGame::FileWrapper::readChar(int bytesToIgnore) uint16_t GamebryoSaveGame::FileWrapper::readShort(int bytesToIgnore) { - if (m_Game->compressionType == 0) { + if (m_Game->m_CompressionType == 0) { if (bytesToIgnore>0)//Just to make certain skip(bytesToIgnore); uint16_t size; read(size); return size; } - else if (m_Game->compressionType == 1) { + else if (m_Game->m_CompressionType == 1) { m_Game->m_Plugins.push_back("Please create an issue on the MO github labeled \"Found zlib Compressed\" with your savefile attached"); return 0; } - else if (m_Game->compressionType == 2) { + else if (m_Game->m_CompressionType == 2) { // decompression already done by readSaveGameVersion m_Data->skipRawData(bytesToIgnore); @@ -300,18 +304,18 @@ uint16_t GamebryoSaveGame::FileWrapper::readShort(int bytesToIgnore) uint32_t GamebryoSaveGame::FileWrapper::readInt(int bytesToIgnore) { - if (m_Game->compressionType == 0) { + if (m_Game->m_CompressionType == 0) { if (bytesToIgnore>0)//Just to make certain skip(bytesToIgnore); uint32_t size; read(size); return size; } - else if (m_Game->compressionType == 1) { + else if (m_Game->m_CompressionType == 1) { m_Game->m_Plugins.push_back("Please create an issue on the MO github labeled \"Found zlib Compressed\" with your savefile attached"); return 0; } - else if (m_Game->compressionType == 2) { + else if (m_Game->m_CompressionType == 2) { // decompression already done by readSaveGameVersion m_Data->skipRawData(bytesToIgnore); @@ -327,26 +331,27 @@ uint32_t GamebryoSaveGame::FileWrapper::readInt(int bytesToIgnore) void GamebryoSaveGame::FileWrapper::readPlugins(int bytesToIgnore) { - if(m_Game->compressionType==0){ + if(m_Game->m_CompressionType ==0){ if(bytesToIgnore>0)//Just to make certain skip(bytesToIgnore); - uint8_t count; - read(count); - m_Game->m_Plugins.reserve(count); - for (std::size_t i = 0; i < count; ++i) { + uint8_t count; + read(count); + uint16_t finalCount = count; + m_Game->m_Plugins.reserve(finalCount); + for (std::size_t i = 0; i < finalCount; ++i) { QString name; read(name); m_Game->m_Plugins.push_back(name); } - }else if(m_Game->compressionType==1){ + } else if (m_Game->m_CompressionType ==1) { m_Game->m_Plugins.push_back("Please create an issue on the MO github labeled \"Found zlib Compressed\" with your savefile attached"); - }else if(m_Game->compressionType==2){ + } else if (m_Game->m_CompressionType ==2) { m_Data->skipRawData(bytesToIgnore); - - unsigned char count; - readQDataStream(*m_Data,count); - m_Game->m_Plugins.reserve(count); - for(std::size_t i=0;im_Plugins.reserve(finalCount); + for(std::size_t i=0;im_Plugins.push_back(name); @@ -356,7 +361,7 @@ void GamebryoSaveGame::FileWrapper::readPlugins(int bytesToIgnore) void GamebryoSaveGame::FileWrapper::readLightPlugins(int bytesToIgnore) { - if (m_Game->compressionType == 0) { + if (m_Game->m_CompressionType == 0) { if (bytesToIgnore>0)//Just to make certain skip(bytesToIgnore); uint16_t count; @@ -368,10 +373,10 @@ void GamebryoSaveGame::FileWrapper::readLightPlugins(int bytesToIgnore) m_Game->m_LightPlugins.push_back(name); } } - else if (m_Game->compressionType == 1) { + else if (m_Game->m_CompressionType == 1) { m_Game->m_Plugins.push_back("Please create an issue on the MO github labeled \"Found zlib Compressed\" with your savefile attached"); } - else if (m_Game->compressionType == 2) { + else if (m_Game->m_CompressionType == 2) { m_Data->skipRawData(bytesToIgnore); uint16_t count; diff --git a/src/gamebryosavegame.h b/src/gamebryosavegame.h index b956fda9..6f7956b3 100644 --- a/src/gamebryosavegame.h +++ b/src/gamebryosavegame.h @@ -43,6 +43,13 @@ public: QImage const &getScreenshot() const { return m_Screenshot; } bool const &isLightEnabled() const { return m_LightEnabled; } + enum StringType + { + TYPE_BZSTRING, + TYPE_BSTRING, + TYPE_WSTRING + }; + protected: friend class FileWrapper; @@ -62,7 +69,7 @@ protected: /** Set bz string mode (1 byte length, null terminated) **/ - void setBZString(bool); + void setPluginString(StringType); template void skip(int count = 1) { @@ -82,6 +89,13 @@ protected: } } + void seek(unsigned long pos) + { + if (!m_File.seek(pos - m_File.pos())) { + throw std::runtime_error("unexpected end of file"); + } + } + void read(void *buff, std::size_t length); /* Reads RGB image from save @@ -118,7 +132,7 @@ protected: GamebryoSaveGame *m_Game; QFile m_File; bool m_HasFieldMarkers; - bool m_BZString; + StringType m_PluginString; QDataStream* m_Data; }; @@ -134,7 +148,7 @@ protected: QStringList m_LightPlugins; QImage m_Screenshot; MOBase::IPluginGame const *m_Game; - uint16_t compressionType = 0; + uint16_t m_CompressionType = 0; bool m_LightEnabled; }; From a10537e93210777e6eeb5eac3f741cf0bca1456b Mon Sep 17 00:00:00 2001 From: Silarn Date: Mon, 26 Mar 2018 19:58:42 -0500 Subject: [PATCH 0464/1544] [game_falloutnv] Improved save plugins parsing and image rendering --- src/games/falloutnv/src/falloutnvsavegame.cpp | 1 + 1 file changed, 1 insertion(+) diff --git a/src/games/falloutnv/src/falloutnvsavegame.cpp b/src/games/falloutnv/src/falloutnvsavegame.cpp index a9d4b2ff..36a8d787 100644 --- a/src/games/falloutnv/src/falloutnvsavegame.cpp +++ b/src/games/falloutnv/src/falloutnvsavegame.cpp @@ -18,6 +18,7 @@ FalloutNVSaveGame::FalloutNVSaveGame(QString const &fileName, MOBase::IPluginGam } file.setHasFieldMarkers(true); + file.setPluginString(GamebryoSaveGame::StringType::TYPE_BZSTRING); unsigned long width; file.read(width); From 4a72d37919f2d2babd55d743e78beb4c98022cdd Mon Sep 17 00:00:00 2001 From: Silarn Date: Mon, 26 Mar 2018 19:58:43 -0500 Subject: [PATCH 0465/1544] [game_fallout3] Improved save plugins parsing and image rendering --- src/games/fallout3/src/fallout3savegame.cpp | 1 + 1 file changed, 1 insertion(+) diff --git a/src/games/fallout3/src/fallout3savegame.cpp b/src/games/fallout3/src/fallout3savegame.cpp index 89bf0d5c..7edda109 100644 --- a/src/games/fallout3/src/fallout3savegame.cpp +++ b/src/games/fallout3/src/fallout3savegame.cpp @@ -8,6 +8,7 @@ Fallout3SaveGame::Fallout3SaveGame(QString const &fileName, MOBase::IPluginGame file.skip(); //Save header size file.setHasFieldMarkers(true); + file.setPluginString(GamebryoSaveGame::StringType::TYPE_BZSTRING); file.skip(); //File version ? file.skip(); //delimiter From 6b1fed2ff254736ceaccdfdbb4b185ea158ccaa5 Mon Sep 17 00:00:00 2001 From: Silarn Date: Mon, 26 Mar 2018 19:58:43 -0500 Subject: [PATCH 0466/1544] [game_skyrimse] Improved save plugins parsing and image rendering --- src/games/skyrimse/src/skyrimsesavegame.cpp | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/src/games/skyrimse/src/skyrimsesavegame.cpp b/src/games/skyrimse/src/skyrimsesavegame.cpp index 61cd5a7c..dbc4f100 100644 --- a/src/games/skyrimse/src/skyrimsesavegame.cpp +++ b/src/games/skyrimse/src/skyrimsesavegame.cpp @@ -6,7 +6,8 @@ SkyrimSESaveGame::SkyrimSESaveGame(QString const &fileName, MOBase::IPluginGame GamebryoSaveGame(fileName, game, lightEnabled) { FileWrapper file(this, "TESV_SAVEGAME"); //10bytes - file.skip(); // header size "TESV_SAVEGAME" + unsigned long headerSize; + file.read(headerSize); // header size "TESV_SAVEGAME" file.skip(); // header version 74. Original Skyrim is 79 file.read(m_SaveNumber); @@ -46,14 +47,13 @@ SkyrimSESaveGame::SkyrimSESaveGame(QString const &fileName, MOBase::IPluginGame ::FileTimeToSystemTime(&ftime, &ctime); setCreationTime(ctime); - //file.skip(); unsigned long width; unsigned long height; file.read(width); file.read(height); - file.read(compressionType); + file.read(m_CompressionType); file.readImage(width,height,320,true); From c9ebd5531d021dd0ddd9db4714c4ccf8bb6a9ed6 Mon Sep 17 00:00:00 2001 From: Silarn Date: Mon, 26 Mar 2018 19:58:44 -0500 Subject: [PATCH 0467/1544] [game_oblivion] Improved save plugins parsing and image rendering --- src/games/oblivion/src/oblivionsavegame.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/games/oblivion/src/oblivionsavegame.cpp b/src/games/oblivion/src/oblivionsavegame.cpp index a639895b..1ee5b37e 100644 --- a/src/games/oblivion/src/oblivionsavegame.cpp +++ b/src/games/oblivion/src/oblivionsavegame.cpp @@ -6,7 +6,7 @@ OblivionSaveGame::OblivionSaveGame(QString const &fileName, MOBase::IPluginGame GamebryoSaveGame(fileName, game) { FileWrapper file(this, "TES4SAVEGAME"); - file.setBZString(true); + file.setPluginString(GamebryoSaveGame::StringType::TYPE_BSTRING); file.skip(); //Major version file.skip(); //Minor version From 38b8c2cafe483c09478de810dd3d2e94864240d3 Mon Sep 17 00:00:00 2001 From: Silarn Date: Mon, 26 Mar 2018 20:02:52 -0500 Subject: [PATCH 0468/1544] [game_morrowind] Modernize plugins class --- src/games/morrowind/src/gamemorrowind.cpp | 2 +- .../morrowind/src/morrowindgameplugins.cpp | 50 +++++++++++++++---- .../morrowind/src/morrowindgameplugins.h | 2 +- 3 files changed, 41 insertions(+), 13 deletions(-) diff --git a/src/games/morrowind/src/gamemorrowind.cpp b/src/games/morrowind/src/gamemorrowind.cpp index 76935d29..120b7233 100644 --- a/src/games/morrowind/src/gamemorrowind.cpp +++ b/src/games/morrowind/src/gamemorrowind.cpp @@ -148,7 +148,7 @@ QString GameMorrowind::steamAPPId() const QStringList GameMorrowind::primaryPlugins() const { - return { "Morrowind.esm" }; + return { "morrowind.esm" }; } QString GameMorrowind::binaryName() const diff --git a/src/games/morrowind/src/morrowindgameplugins.cpp b/src/games/morrowind/src/morrowindgameplugins.cpp index 77085bdb..425925ae 100644 --- a/src/games/morrowind/src/morrowindgameplugins.cpp +++ b/src/games/morrowind/src/morrowindgameplugins.cpp @@ -50,12 +50,10 @@ void MorrowindGamePlugins::readPluginLists(MOBase::IPluginList *pluginList) { if (loadOrderIsNew || !pluginsIsNew) { // read both files if they are both new or both older than the last read readLoadOrderList(pluginList, loadOrderPath); - readPluginList(pluginList, pluginsPath, false); + readPluginList(pluginList, false); } else { - // if the plugin list is new but the load order isn't, this probably means - // an external tool that handles only the plugins.txt has been run in the - // meantime. We have to use plugins.txt for the load order as well. - readPluginList(pluginList, pluginsPath, true); + // If the plugins is new but not loadorder, we must reparse the load order from the plugin files + readPluginList(pluginList, true); } m_LastRead = QDateTime::currentDateTime(); @@ -109,8 +107,43 @@ void MorrowindGamePlugins::writeList(const IPluginList *pluginList, } } -bool MorrowindGamePlugins::readPluginList(MOBase::IPluginList *pluginList, const QString &filePath, bool useLoadOrder) { +bool MorrowindGamePlugins::readPluginList(MOBase::IPluginList *pluginList, + bool useLoadOrder) { + QStringList primary = organizer()->managedGame()->primaryPlugins(); + for (const QString &pluginName : primary) { + if (pluginList->state(pluginName) != IPluginList::STATE_MISSING) { + pluginList->setState(pluginName, IPluginList::STATE_ACTIVE); + } + } QStringList plugins = pluginList->pluginNames(); + // Do not sort the primary plugins. Their load order should be locked as defined in "primaryPlugins". + for (QString plugin : plugins) { + if (primary.contains(plugin, Qt::CaseInsensitive)) + plugins.removeAll(plugin); + } + + if (useLoadOrder) { + // Always use filetime loadorder to get the actual load order + std::sort(plugins.begin(), plugins.end(), [&](const QString &lhs, const QString &rhs) { + MOBase::IModInterface *lhm = organizer()->getMod(pluginList->origin(lhs)); + MOBase::IModInterface *rhm = organizer()->getMod(pluginList->origin(rhs)); + QDir lhd = organizer()->managedGame()->dataDirectory(); + QDir rhd = organizer()->managedGame()->dataDirectory(); + if (lhm != nullptr) + lhd = lhm->absolutePath(); + if (rhm != nullptr) + rhd = rhm->absolutePath(); + QString lhp = lhd.absoluteFilePath(lhs); + QString rhp = rhd.absoluteFilePath(rhs); + return QFileInfo(lhp).lastModified() < + QFileInfo(rhp).lastModified(); + }); + + // Add the primary plugins to the beginning of the load order + pluginList->setLoadOrder(primary + plugins); + } + + QString filePath = organizer()->profile()->absolutePath() + "/Morrowind.ini"; wchar_t buffer[256]; QStringList result; std::wstring iniFileW = QDir::toNativeSeparators(filePath).toStdWString(); @@ -126,7 +159,6 @@ bool MorrowindGamePlugins::readPluginList(MOBase::IPluginList *pluginList, const pluginName=QString::fromStdWString(buffer).trimmed(); pluginList->setState(pluginName, IPluginList::STATE_ACTIVE); plugins.removeAll(pluginName); - loadOrder.append(pluginName); i++; } @@ -134,9 +166,5 @@ bool MorrowindGamePlugins::readPluginList(MOBase::IPluginList *pluginList, const pluginList->setState(pluginName, IPluginList::STATE_INACTIVE); } - if (useLoadOrder) { - pluginList->setLoadOrder(loadOrder); - } - return true; } \ No newline at end of file diff --git a/src/games/morrowind/src/morrowindgameplugins.h b/src/games/morrowind/src/morrowindgameplugins.h index 4cafdbef..fb03be14 100644 --- a/src/games/morrowind/src/morrowindgameplugins.h +++ b/src/games/morrowind/src/morrowindgameplugins.h @@ -15,7 +15,7 @@ public: protected: virtual void writePluginList(const MOBase::IPluginList *pluginList, const QString &filePath); - virtual bool readPluginList(MOBase::IPluginList *pluginList, const QString &filePath, bool useLoadOrder); + virtual bool readPluginList(MOBase::IPluginList *pluginList, bool useLoadOrder); private: virtual void writeList(const MOBase::IPluginList *pluginList, const QString &filePath, From 22af585ac114513ac9ba32f185432b2433248bf8 Mon Sep 17 00:00:00 2001 From: Silarn Date: Tue, 27 Mar 2018 00:52:14 -0500 Subject: [PATCH 0469/1544] Fix up some overflows and data types --- src/gamebryosavegame.cpp | 16 +++++++++------- 1 file changed, 9 insertions(+), 7 deletions(-) diff --git a/src/gamebryosavegame.cpp b/src/gamebryosavegame.cpp index e59e973c..b58e8f2b 100644 --- a/src/gamebryosavegame.cpp +++ b/src/gamebryosavegame.cpp @@ -119,7 +119,7 @@ template <> void GamebryoSaveGame::FileWrapper::read(QString &value) if (m_PluginString == StringType::TYPE_BSTRING || m_PluginString == StringType::TYPE_BZSTRING) { unsigned char len; read(len); - length = len; + length = m_PluginString == StringType::TYPE_BZSTRING ? len + 1 : len; } else { read(length); } @@ -128,18 +128,20 @@ template <> void GamebryoSaveGame::FileWrapper::read(QString &value) skip(); } - std::vector buffer(m_PluginString == StringType::TYPE_BSTRING ? length+1 : length); + char *buffer = new char[length]; - read(buffer.data(), length); - - if (m_PluginString == StringType::TYPE_BSTRING) - buffer[buffer.size()] = '\0'; + read(buffer, m_PluginString == StringType::TYPE_BZSTRING ? length-1 : length); + + if (m_PluginString == StringType::TYPE_BZSTRING) + buffer[length-1] = '\0'; if (m_HasFieldMarkers) { skip(); } - value = QString::fromLatin1(buffer.data(), length); + value = QString::fromLatin1(buffer, length); + + delete buffer; } void GamebryoSaveGame::FileWrapper::read(void *buff, std::size_t length) From a18f16ff631f38513e53c7a17fee002085bcc922 Mon Sep 17 00:00:00 2001 From: Silarn Date: Tue, 27 Mar 2018 00:52:14 -0500 Subject: [PATCH 0470/1544] [game_falloutnv] Fix up some overflows and data types --- src/games/falloutnv/src/falloutnvsavegame.cpp | 1 + 1 file changed, 1 insertion(+) diff --git a/src/games/falloutnv/src/falloutnvsavegame.cpp b/src/games/falloutnv/src/falloutnvsavegame.cpp index 36a8d787..24c5505b 100644 --- a/src/games/falloutnv/src/falloutnvsavegame.cpp +++ b/src/games/falloutnv/src/falloutnvsavegame.cpp @@ -47,5 +47,6 @@ FalloutNVSaveGame::FalloutNVSaveGame(QString const &fileName, MOBase::IPluginGam file.skip(5); // unknown byte, size of plugin data //Abstract this + file.setPluginString(GamebryoSaveGame::StringType::TYPE_BSTRING); file.readPlugins(); } From 185baebf991a81ee7fae706363041d4ff772f0f3 Mon Sep 17 00:00:00 2001 From: Silarn Date: Tue, 27 Mar 2018 00:52:14 -0500 Subject: [PATCH 0471/1544] [game_fallout3] Fix up some overflows and data types --- src/games/fallout3/src/fallout3savegame.cpp | 1 + 1 file changed, 1 insertion(+) diff --git a/src/games/fallout3/src/fallout3savegame.cpp b/src/games/fallout3/src/fallout3savegame.cpp index 7edda109..e62e726e 100644 --- a/src/games/fallout3/src/fallout3savegame.cpp +++ b/src/games/fallout3/src/fallout3savegame.cpp @@ -39,6 +39,7 @@ Fallout3SaveGame::Fallout3SaveGame(QString const &fileName, MOBase::IPluginGame file.skip(5); // unknown (1 byte), plugin size (4 bytes) + file.setPluginString(GamebryoSaveGame::StringType::TYPE_BSTRING); file.readPlugins(); } From ac35ecb7bd3d8bdf54996a7c41110ae7c4645b01 Mon Sep 17 00:00:00 2001 From: Silarn Date: Tue, 27 Mar 2018 00:52:15 -0500 Subject: [PATCH 0472/1544] [game_oblivion] Fix up some overflows and data types --- src/games/oblivion/src/oblivionsavegame.cpp | 1 + 1 file changed, 1 insertion(+) diff --git a/src/games/oblivion/src/oblivionsavegame.cpp b/src/games/oblivion/src/oblivionsavegame.cpp index 1ee5b37e..62c80ac0 100644 --- a/src/games/oblivion/src/oblivionsavegame.cpp +++ b/src/games/oblivion/src/oblivionsavegame.cpp @@ -39,5 +39,6 @@ OblivionSaveGame::OblivionSaveGame(QString const &fileName, MOBase::IPluginGame file.readImage(); + //file.setPluginString(GamebryoSaveGame::StringType::TYPE_BSTRING); file.readPlugins(); } From 80d2f8014798c8f6c0aa8e8237e66048b7091025 Mon Sep 17 00:00:00 2001 From: Silarn Date: Thu, 29 Mar 2018 21:42:53 -0500 Subject: [PATCH 0473/1544] [game_morrowind] Improved save parsing (and comments) and custom save info widget --- src/games/morrowind/src/game_morrowind_en.ts | 56 +++++++- src/games/morrowind/src/gamemorrowind.cpp | 1 + src/games/morrowind/src/gamemorrowind.h | 11 +- src/games/morrowind/src/morrowindsavegame.cpp | 126 ++++++++++-------- src/games/morrowind/src/morrowindsavegame.h | 12 ++ .../morrowind/src/morrowindsavegameinfo.cpp | 8 +- .../morrowind/src/morrowindsavegameinfo.h | 7 + 7 files changed, 163 insertions(+), 58 deletions(-) diff --git a/src/games/morrowind/src/game_morrowind_en.ts b/src/games/morrowind/src/game_morrowind_en.ts index e3f9d226..87d98747 100644 --- a/src/games/morrowind/src/game_morrowind_en.ts +++ b/src/games/morrowind/src/game_morrowind_en.ts @@ -5,20 +5,70 @@ GameMorrowind - Adds support for the game Morrowind + Adds support for the game Morrowind. +Splash by %1 Adds support for the game Morrowind + + MorrowindSaveGameInfoWidget + + + Save # + + + + + Character + + + + + Level + + + + + Location + + + + + Date + + + + + Has Script Extender Data + + + + + Missing ESPs + + + + + + None + + + + + Missing ESLs + + + QObject - + failed to set game file key (errorcode %1) - + Some of your plugins have invalid names! These plugins can not be loaded by the game. Please see mo_interface.log for a list of affected plugins and rename them. diff --git a/src/games/morrowind/src/gamemorrowind.cpp b/src/games/morrowind/src/gamemorrowind.cpp index 120b7233..c183d1c9 100644 --- a/src/games/morrowind/src/gamemorrowind.cpp +++ b/src/games/morrowind/src/gamemorrowind.cpp @@ -45,6 +45,7 @@ bool GameMorrowind::init(IOrganizer *moInfo) registerFeature(new GamebryoLocalSavegames(gameDirectory().absolutePath(), "morrowind.ini")); registerFeature(new MorrowindGamePlugins(moInfo)); registerFeature(new GamebryoUnmangedMods(this)); + m_Organizer = moInfo; return true; } diff --git a/src/games/morrowind/src/gamemorrowind.h b/src/games/morrowind/src/gamemorrowind.h index 0f82ccda..d2010ef8 100644 --- a/src/games/morrowind/src/gamemorrowind.h +++ b/src/games/morrowind/src/gamemorrowind.h @@ -10,9 +10,12 @@ class GameMorrowind : public GameGamebryo { Q_OBJECT #if QT_VERSION >= QT_VERSION_CHECK(5,0,0) - Q_PLUGIN_METADATA(IID "com.schilduin.GameMorrowind" FILE "gamemorrowind.json") + Q_PLUGIN_METADATA(IID "com.schilduin.GameMorrowind" FILE "gamemorrowind.json") #endif + friend class MorrowindSaveGameInfo; + friend class MorrowindSaveGameInfoWidget; + public: GameMorrowind(); @@ -48,6 +51,12 @@ public: // IPlugin interface virtual MOBase::VersionInfo version() const; virtual bool isActive() const; virtual QList settings() const; + +private: + + MOBase::IOrganizer *m_Organizer; }; + + #endif // GAMEMORROWIND_H diff --git a/src/games/morrowind/src/morrowindsavegame.cpp b/src/games/morrowind/src/morrowindsavegame.cpp index 41bd55c6..88a987bd 100644 --- a/src/games/morrowind/src/morrowindsavegame.cpp +++ b/src/games/morrowind/src/morrowindsavegame.cpp @@ -2,47 +2,67 @@ #include #include +#include MorrowindSaveGame::MorrowindSaveGame(QString const &fileName, MOBase::IPluginGame const *game) : GamebryoSaveGame(fileName, game) { FileWrapper file(this, "TES3"); - //file.skip(); // header size - //file.skip(); // header version - file.skip(79); //Mostly empty header Data - //file.readPlugins(); normal readPlugins function does not work - file.skip(); - uint8_t count; - file.read(count); - this->m_Plugins.reserve(count); + file.skip(3); // data size + file.skip(4); // HEDR tag + file.skip(); // header size + file.skip(); // header version + file.skip(); // following data chunk size? seems to be 9 groupings of 32 bytes + file.skip(32); // Author empty for save files + std::vector saveName(256); // 31 char save name with a null terminator + file.read(saveName.data(), 256); + m_SaveName = QString::fromLatin1(saveName.data(), 256).trimmed(); // The defined save name. This is technically the description, but is likely only 31+\0 chars max. + file.skip(); // NumRecords (for the entire save) std::vector buffer(255); - file.skip(); file.read(buffer.data(), 4); - while(QString::fromLatin1(buffer.data(), 4)=="MAST"){ - uint32_t len; - file.read(len); - QString name; - file.read(buffer.data(), len-1); - name=QString::fromLatin1(buffer.data(), len-1); - file.skip(); - file.skip(4); - file.read(buffer.data(), 4); + // Parse the MAST/DATA records + while (QString::fromLatin1(buffer.data(), 4)=="MAST") { + uint32_t len; + file.read(len); // Length of master name + QString name; + file.read(buffer.data(), len); // Name of master + name = QString::fromLatin1(buffer.data(), len - 1); + file.skip(4); // DATA record + file.read(len); // Length + file.skip(len); // Typically size 8 - contains length of master data for version checking + + file.read(buffer.data(), 4); // Get next record type this->m_Plugins.push_back(name); } - file.skip(7); + // Start of GMDT + file.skip(); // size of record + + file.read(m_PCCurrentHealth); + file.read(m_PCCMaxHealth); + + file.skip(); // current stam? + file.skip(); // max stam? + //file.skip(2); // unknown values + file.read(buffer.data(), 64); - m_PCLocation=QString::fromLatin1(buffer.data(), 64).trimmed(); - - file.skip(); + m_PCLocation = QString::fromLatin1(buffer.data(), 64).trimmed(); + + file.read(m_GameDays); + file.read(buffer.data(), 32); - m_PCName=QString::fromLatin1(buffer.data(), 32).trimmed(); + + // End of GMDT - file.skip(36); - + file.skip(28); // Skip the SCRD + // I believe this tells the engine what color each pixel represents and the bitness of the image + + // Start of screenshot + file.skip(4); // SCRS + file.skip(); // Size of screenshot always 65536 (128x128x4) RGBA8888 file.readImage(128, 128, 0, 1); - + //Color correction, I am unable to get it to work in a more efficient way this->m_Screenshot=this->m_Screenshot.rgbSwapped(); unsigned int rgb; @@ -54,47 +74,47 @@ MorrowindSaveGame::MorrowindSaveGame(QString const &fileName, MOBase::IPluginGam } } this->m_Screenshot=this->m_Screenshot.scaled(252,192); + //definitively have to use another method to access the player level //it is stored in the fifth byte of the NPDT subrecord of the first NPC_ record - //file.skip(8); //Record SCRD - //file.skip(16385); //Record SCRS - //file.skip(8445); //Globals - //Globals, Scripts, Regions //file.skip(); std::vector buff(4); file.read(buff.data(), 4); - while(QString::fromLatin1(buff.data(), 4)!="NPC_") + while (QString::fromLatin1(buff.data(), 4) != "NPC_") { uint32_t len; - file.read(len); - file.skip(8+len); - file.read(buff.data(), 4); + file.read(len); + file.skip(8 + len); + file.read(buff.data(), 4); } - while(QString::fromLatin1(buff.data(), 4)=="NPC_"){ + while (QString::fromLatin1(buff.data(), 4) == "NPC_") { uint32_t size; file.read(size); file.skip(3); - uint32_t len; - file.read(len); - file.read(buffer.data(), len); - if(QString::fromLatin1(buffer.data(), len-1)=="player"){ - file.read(buff.data(), 4); - while(QString::fromLatin1(buff.data(), 4)!="NPDT") + uint32_t len; + file.read(len); + file.read(buffer.data(), len); + if (QString::fromLatin1(buffer.data(), len - 1) == "player") { + file.read(buff.data(), 4); + while (QString::fromLatin1(buff.data(), 4) != "NPDT") { uint32_t len; - file.read(len); - file.skip(len); - file.read(buff.data(), 4); + file.read(len); + file.skip(len); + file.read(buff.data(), 4); } - file.skip(); - file.read(m_PCLevel); - } - else - { - file.skip(size-len-8); - } + file.skip(); + file.read(m_PCLevel); + } + else + { + file.skip(size - len - 8); + } } - m_SaveNumber=fileName.chopped(4).right(4).toInt(); -} + + std::experimental::filesystem::path realFile(fileName.toStdWString()); + QString realFileName = QString::fromStdWString(realFile.filename().wstring()); + m_SaveNumber = realFileName.mid(4, 5).remove(QRegExp("0+$")).toInt(); +} \ No newline at end of file diff --git a/src/games/morrowind/src/morrowindsavegame.h b/src/games/morrowind/src/morrowindsavegame.h index a4a63761..77f5bad6 100644 --- a/src/games/morrowind/src/morrowindsavegame.h +++ b/src/games/morrowind/src/morrowindsavegame.h @@ -9,6 +9,18 @@ class MorrowindSaveGame : public GamebryoSaveGame { public: MorrowindSaveGame(QString const &fileName, MOBase::IPluginGame const *game); + + //Simple getters + QString getSaveName() const { return m_SaveName; } + float getPCCurrentHealth() const { return m_PCCurrentHealth; } + float getPCMaxHealth() const { return m_PCCMaxHealth; } + float getGameDays() const { return m_GameDays; } + +protected: + QString m_SaveName; + float m_PCCurrentHealth; + float m_PCCMaxHealth; + float m_GameDays; }; #endif // MORROWINDSAVEGAME_H diff --git a/src/games/morrowind/src/morrowindsavegameinfo.cpp b/src/games/morrowind/src/morrowindsavegameinfo.cpp index 82c1d321..292bb0b7 100644 --- a/src/games/morrowind/src/morrowindsavegameinfo.cpp +++ b/src/games/morrowind/src/morrowindsavegameinfo.cpp @@ -1,11 +1,12 @@ #include "morrowindsavegameinfo.h" - +#include "morrowindsavegameinfowidget.h" #include "morrowindsavegame.h" #include "gamegamebryo.h" MorrowindSaveGameInfo::MorrowindSaveGameInfo(GameGamebryo const *game) : GamebryoSaveGameInfo(game) { + m_Game = dynamic_cast(game); } MorrowindSaveGameInfo::~MorrowindSaveGameInfo() @@ -17,3 +18,8 @@ MOBase::ISaveGame const *MorrowindSaveGameInfo::getSaveGameInfo(QString const &f { return new MorrowindSaveGame(file, m_Game); } + +MOBase::ISaveGameInfoWidget *MorrowindSaveGameInfo::getSaveGameWidget(QWidget *parent) const +{ + return new MorrowindSaveGameInfoWidget(this, parent); +} diff --git a/src/games/morrowind/src/morrowindsavegameinfo.h b/src/games/morrowind/src/morrowindsavegameinfo.h index aac29fdd..91adc9a3 100644 --- a/src/games/morrowind/src/morrowindsavegameinfo.h +++ b/src/games/morrowind/src/morrowindsavegameinfo.h @@ -2,6 +2,7 @@ #define MORROWINDSAVEGAMEINFO_H #include "gamebryosavegameinfo.h" +#include "gamemorrowind.h" class GameGamebryo; @@ -11,7 +12,13 @@ public: MorrowindSaveGameInfo(GameGamebryo const *game); ~MorrowindSaveGameInfo(); + virtual MOBase::ISaveGameInfoWidget *getSaveGameWidget(QWidget *) const override; + virtual MOBase::ISaveGame const *getSaveGameInfo(QString const &file) const override; + +protected: + friend class MorrowindSaveGameInfoWidget; + GameMorrowind const *m_Game; }; #endif // MORROWINDSAVEGAMEINFO_H From 1db0905a83260cb38ccd6bb8dc88a29128f3dc8c Mon Sep 17 00:00:00 2001 From: Silarn Date: Thu, 29 Mar 2018 22:53:03 -0500 Subject: [PATCH 0474/1544] [game_morrowind] Custom image parser to reduce required postprocessing of image data --- src/games/morrowind/src/morrowindsavegame.cpp | 39 ++++++++++++------- src/games/morrowind/src/morrowindsavegame.h | 3 ++ 2 files changed, 29 insertions(+), 13 deletions(-) diff --git a/src/games/morrowind/src/morrowindsavegame.cpp b/src/games/morrowind/src/morrowindsavegame.cpp index 88a987bd..39d7623c 100644 --- a/src/games/morrowind/src/morrowindsavegame.cpp +++ b/src/games/morrowind/src/morrowindsavegame.cpp @@ -61,19 +61,8 @@ MorrowindSaveGame::MorrowindSaveGame(QString const &fileName, MOBase::IPluginGam // Start of screenshot file.skip(4); // SCRS file.skip(); // Size of screenshot always 65536 (128x128x4) RGBA8888 - file.readImage(128, 128, 0, 1); - - //Color correction, I am unable to get it to work in a more efficient way - this->m_Screenshot=this->m_Screenshot.rgbSwapped(); - unsigned int rgb; - - for(int y=0;ym_Screenshot.height();y++){ - for(int x=0;xm_Screenshot.width();x++){ - rgb=this->m_Screenshot.pixel(x,y); - this->m_Screenshot.setPixel(x,y,qRgba(qRed(rgb),qGreen(rgb),qBlue(rgb),255)); - } - } - this->m_Screenshot=this->m_Screenshot.scaled(252,192); + readImageBGRA(file, 128, 128, 0, 1); + this->m_Screenshot = this->m_Screenshot.scaled(252,192); //definitively have to use another method to access the player level //it is stored in the fifth byte of the NPDT subrecord of the first NPC_ record @@ -117,4 +106,28 @@ MorrowindSaveGame::MorrowindSaveGame(QString const &fileName, MOBase::IPluginGam std::experimental::filesystem::path realFile(fileName.toStdWString()); QString realFileName = QString::fromStdWString(realFile.filename().wstring()); m_SaveNumber = realFileName.mid(4, 5).remove(QRegExp("0+$")).toInt(); +} + +void MorrowindSaveGame::readImageBGRA(GamebryoSaveGame::FileWrapper &file, unsigned long width, unsigned long height, int scale = 0, bool alpha = false) +{ + QImage image(width, height, QImage::Format_RGBA8888); + for (unsigned long h = 0; h < width; h++) { + for (unsigned long w = 0; w < width; w++) { + uint8_t blue; + file.read(blue); + uint8_t green; + file.read(green); + uint8_t red; + file.read(red); + uint8_t alpha; + file.read(alpha); + alpha = 255 - alpha; + QColor color(red, green, blue, alpha); + image.setPixel(w, h, color.rgba()); + } + } + if (scale != 0) + m_Screenshot = image.copy().scaledToWidth(scale); + else + m_Screenshot = image.copy(); } \ No newline at end of file diff --git a/src/games/morrowind/src/morrowindsavegame.h b/src/games/morrowind/src/morrowindsavegame.h index 77f5bad6..972f37e7 100644 --- a/src/games/morrowind/src/morrowindsavegame.h +++ b/src/games/morrowind/src/morrowindsavegame.h @@ -21,6 +21,9 @@ protected: float m_PCCurrentHealth; float m_PCCMaxHealth; float m_GameDays; + +protected: + void readImageBGRA(GamebryoSaveGame::FileWrapper &file, unsigned long width, unsigned long height, int scale, bool alpha); }; #endif // MORROWINDSAVEGAME_H From ddf64dd036b1beefc183db1035dccfc42638949a Mon Sep 17 00:00:00 2001 From: Silarn Date: Fri, 30 Mar 2018 23:12:56 -0500 Subject: [PATCH 0475/1544] Fix up logic problem with plugin parsing --- src/gamebryogameplugins.cpp | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/src/gamebryogameplugins.cpp b/src/gamebryogameplugins.cpp index db24b580..38c75879 100644 --- a/src/gamebryogameplugins.cpp +++ b/src/gamebryogameplugins.cpp @@ -132,9 +132,8 @@ bool GamebryoGamePlugins::readLoadOrderList(MOBase::IPluginList *pluginList, ON_BLOCK_EXIT([&file]() { file.close(); }); if (file.size() == 0) { - // MO stores at least a header in the file. if it's completely empty the - // file is broken - return false; + readPluginList(pluginList, true); + return true; } while (!file.atEnd()) { QByteArray line = file.readLine().trimmed(); @@ -165,8 +164,9 @@ bool GamebryoGamePlugins::readPluginList(MOBase::IPluginList *pluginList, } } QStringList plugins = pluginList->pluginNames(); + QStringList pluginsClone(plugins); // Do not sort the primary plugins. Their load order should be locked as defined in "primaryPlugins". - for (QString plugin : plugins) { + for (QString plugin : pluginsClone) { if (primary.contains(plugin, Qt::CaseInsensitive)) plugins.removeAll(plugin); } From 81077a90d5c90efa7e9bebcd79c231cee3b8e386 Mon Sep 17 00:00:00 2001 From: Silarn Date: Fri, 30 Mar 2018 23:13:27 -0500 Subject: [PATCH 0476/1544] [game_ttw] Don't really need to define DLC which is force-enabled --- src/games/ttw/src/gamefalloutttw.cpp | 9 ++------- 1 file changed, 2 insertions(+), 7 deletions(-) diff --git a/src/games/ttw/src/gamefalloutttw.cpp b/src/games/ttw/src/gamefalloutttw.cpp index 8c8053e1..812b7292 100644 --- a/src/games/ttw/src/gamefalloutttw.cpp +++ b/src/games/ttw/src/gamefalloutttw.cpp @@ -148,17 +148,12 @@ QString GameFalloutTTW::gameNexusName() const QStringList GameFalloutTTW::iniFiles() const { - return { "fallout.ini", "falloutprefs.ini", "falloutcustom.ini", "custom.ini"}; + return { "fallout.ini", "falloutprefs.ini", "falloutcustom.ini", "custom.ini" }; } QStringList GameFalloutTTW::DLCPlugins() const { - return { "FalloutNV.esm", "DeadMoney.esm", "HonestHearts.esm", - "OldWorldBlues.esm", "LonesomeRoad.esm", "GunRunnersArsenal.esm", - "CaravanPack.esm", "ClassicPack.esm", "MercenaryPack.esm", - "TribalPack.esm", "Fallout3.esm", "Anchorage.esm", - "ThePitt.esm", "BrokenSteel.esm", "PointLookout.esm", - "Zeta.esm", "TaleOfTwoWastelands.esm"}; + return {}; } int GameFalloutTTW::nexusModOrganizerID() const From f0ceea4bf1de5864e85b8ce85b70d094fc68fdb7 Mon Sep 17 00:00:00 2001 From: Silarn Date: Tue, 3 Apr 2018 18:22:59 -0500 Subject: [PATCH 0477/1544] [game_morrowind] Add missing widget files --- .../src/morrowindsavegameinfowidget.cpp | 112 ++++++++ .../src/morrowindsavegameinfowidget.h | 28 ++ .../src/morrowindsavegameinfowidget.ui | 248 ++++++++++++++++++ 3 files changed, 388 insertions(+) create mode 100644 src/games/morrowind/src/morrowindsavegameinfowidget.cpp create mode 100644 src/games/morrowind/src/morrowindsavegameinfowidget.h create mode 100644 src/games/morrowind/src/morrowindsavegameinfowidget.ui diff --git a/src/games/morrowind/src/morrowindsavegameinfowidget.cpp b/src/games/morrowind/src/morrowindsavegameinfowidget.cpp new file mode 100644 index 00000000..93dcd124 --- /dev/null +++ b/src/games/morrowind/src/morrowindsavegameinfowidget.cpp @@ -0,0 +1,112 @@ +#include "morrowindsavegameinfowidget.h" +#include "ui_morrowindsavegameinfowidget.h" + +#include "gamemorrowind.h" +#include "morrowindsavegame.h" +#include "morrowindsavegameinfo.h" +#include "imoinfo.h" +#include "ipluginlist.h" + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include + +#include + +MorrowindSaveGameInfoWidget::MorrowindSaveGameInfoWidget(MorrowindSaveGameInfo const *info, + QWidget *parent) + : MOBase::ISaveGameInfoWidget(parent), ui(new Ui::MorrowindSaveGameInfoWidget), m_Info(info) { + ui->setupUi(this); + this->setWindowFlags(Qt::ToolTip | Qt::BypassGraphicsProxyWidget); + setWindowOpacity(style()->styleHint(QStyle::SH_ToolTipLabel_Opacity, 0, this) / qreal(255.0)); + ui->gameFrame->setStyleSheet("background-color: transparent;"); + + QVBoxLayout *gameLayout = new QVBoxLayout(); + gameLayout->setMargin(0); + gameLayout->setSpacing(2); + ui->gameFrame->setLayout(gameLayout); +} + +MorrowindSaveGameInfoWidget::~MorrowindSaveGameInfoWidget() { + delete ui; +} + +void MorrowindSaveGameInfoWidget::setSave(QString const &file) { + std::unique_ptr < MorrowindSaveGame const> save( + std::move(dynamic_cast(m_Info->getSaveGameInfo(file)))); + ui->saveNameLabel->setText(QString("%1 (Day %2)").arg(save->getSaveName()).arg(save->getGameDays())); + ui->saveNumLabel->setText(QString("%1").arg(save->getSaveNumber())); + ui->healthLabel->setText(QString("%1 / %2").arg(round(save->getPCCurrentHealth())).arg(save->getPCMaxHealth())); + ui->characterLabel->setText(save->getPCName()); + ui->locationLabel->setText(save->getPCLocation()); + ui->levelLabel->setText(QString("%1").arg(save->getPCLevel())); + //This somewhat contorted code is because on my system at least, the + //old way of doing this appears to give short date and long time. + QDateTime t = save->getCreationTime(); + ui->dateLabel->setText(t.date().toString(Qt::DefaultLocaleShortDate) + " " + + t.time().toString(Qt::DefaultLocaleLongDate)); + ui->screenshotLabel->setPixmap(QPixmap::fromImage(save->getScreenshot())); + if (ui->gameFrame->layout() != nullptr) { + QLayoutItem *item = nullptr; + while ((item = ui->gameFrame->layout()->takeAt(0)) != nullptr) { + delete item->widget(); + delete item; + } + ui->gameFrame->layout()->setSizeConstraint(QLayout::SetFixedSize); + } + + // Resize box to new content + this->resize(0, 0); + + QLayout *layout = ui->gameFrame->layout(); + QLabel *header = new QLabel(tr("Missing ESPs")); + QFont headerFont = header->font(); + QFont contentFont = headerFont; + headerFont.setItalic(true); + contentFont.setBold(true); + contentFont.setPointSize(7); + header->setFont(headerFont); + layout->addWidget(header); + int count = 0; + MOBase::IPluginList *pluginList = m_Info->m_Game->m_Organizer->pluginList(); + for (QString const &pluginName : save->getPlugins()) { + if (pluginList->state(pluginName) == MOBase::IPluginList::STATE_ACTIVE) { + continue; + } + + ++count; + + if (count > 7) { + break; + } + + QLabel *pluginLabel = new QLabel(pluginName); + pluginLabel->setIndent(10); + pluginLabel->setFont(contentFont); + layout->addWidget(pluginLabel); + } + if (count > 7) { + QLabel *dotDotLabel = new QLabel("..."); + dotDotLabel->setIndent(10); + dotDotLabel->setFont(contentFont); + layout->addWidget(dotDotLabel); + } + if (count == 0) { + QLabel *dotDotLabel = new QLabel(tr("None")); + dotDotLabel->setIndent(10); + dotDotLabel->setFont(contentFont); + layout->addWidget(dotDotLabel); + } +} diff --git a/src/games/morrowind/src/morrowindsavegameinfowidget.h b/src/games/morrowind/src/morrowindsavegameinfowidget.h new file mode 100644 index 00000000..298f5916 --- /dev/null +++ b/src/games/morrowind/src/morrowindsavegameinfowidget.h @@ -0,0 +1,28 @@ +#ifndef MORROWINDSAVEGAMEINFOWIDGET_H +#define MORROWINDSAVEGAMEINFOWIDGET_H + +#include "isavegameinfowidget.h" +#include "morrowindsavegameinfo.h" + +#include + +class GamebryoGame; + +namespace Ui { class MorrowindSaveGameInfoWidget; } + +class MorrowindSaveGameInfoWidget : public MOBase::ISaveGameInfoWidget +{ + Q_OBJECT + +public: + MorrowindSaveGameInfoWidget(MorrowindSaveGameInfo const *info, QWidget *parent); + ~MorrowindSaveGameInfoWidget(); + + virtual void setSave(QString const &) override; + +private: + Ui::MorrowindSaveGameInfoWidget *ui; + MorrowindSaveGameInfo const *m_Info; +}; + +#endif // MORROWINDSAVEGAMEINFOWIDGET_H diff --git a/src/games/morrowind/src/morrowindsavegameinfowidget.ui b/src/games/morrowind/src/morrowindsavegameinfowidget.ui new file mode 100644 index 00000000..9ba6ba16 --- /dev/null +++ b/src/games/morrowind/src/morrowindsavegameinfowidget.ui @@ -0,0 +1,248 @@ + + + MorrowindSaveGameInfoWidget + + + + 0 + 0 + 400 + 300 + + + + + 0 + 0 + + + + + + + + + + + + + + 10 + 75 + true + + + + + + + + + + + QFormLayout::AllNonFixedFieldsGrow + + + + + + true + + + + Save # + + + + + + + + 75 + true + + + + + + + + + + + + true + + + + Character + + + + + + + + 75 + true + + + + + + + + + + + + true + + + + Level + + + + + + + + 75 + true + + + + + + + + + + + + true + + + + Health + + + + + + + + 75 + true + + + + + + + + + + + + true + + + + Location + + + + + + + + 75 + true + + + + + + + + + + + + true + + + + Date + + + + + + + + 75 + true + + + + + + + + + + + + + + 0 + 0 + + + + + 0 + 0 + + + + QFrame::StyledPanel + + + QFrame::Raised + + + + + + + + 0 + 0 + + + + + 16777215 + 16777215 + + + + false + + + + + + Qt::AlignCenter + + + + + + + + From 8fa71ef2e2bc3a26719e6dde3fd82f3c9fe23701 Mon Sep 17 00:00:00 2001 From: Silarn Date: Tue, 3 Apr 2018 22:54:25 -0500 Subject: [PATCH 0478/1544] [game_skyrimvr] Initial code from ThomasBrixLarsen/modorganizer-game_skyrimVR --- src/games/skyrimvr/.gitignore | 8 + src/games/skyrimvr/CMakeLists.txt | 16 + src/games/skyrimvr/src/CMakeLists.txt | 72 ++++ src/games/skyrimvr/src/SConscript | 13 + src/games/skyrimvr/src/game_skyrimvr_en.ts | 30 ++ src/games/skyrimvr/src/gameskyrimvr.cpp | 363 ++++++++++++++++++ src/games/skyrimvr/src/gameskyrimvr.h | 68 ++++ src/games/skyrimvr/src/gameskyrimvr.json | 1 + src/games/skyrimvr/src/gameskyrimvr.pro | 50 +++ .../skyrimvr/src/skyrimvrdataarchives.cpp | 57 +++ src/games/skyrimvr/src/skyrimvrdataarchives.h | 29 ++ .../skyrimvr/src/skyrimvrgameplugins.cpp | 165 ++++++++ src/games/skyrimvr/src/skyrimvrgameplugins.h | 26 ++ src/games/skyrimvr/src/skyrimvrsavegame.cpp | 73 ++++ src/games/skyrimvr/src/skyrimvrsavegame.h | 14 + .../skyrimvr/src/skyrimvrsavegameinfo.cpp | 18 + src/games/skyrimvr/src/skyrimvrsavegameinfo.h | 17 + .../skyrimvr/src/skyrimvrscriptextender.cpp | 24 ++ .../skyrimvr/src/skyrimvrscriptextender.h | 20 + .../skyrimvr/src/skyrimvrunmanagedmods.cpp | 30 ++ .../skyrimvr/src/skyrimvrunmanagedmods.h | 15 + 21 files changed, 1109 insertions(+) create mode 100644 src/games/skyrimvr/.gitignore create mode 100644 src/games/skyrimvr/CMakeLists.txt create mode 100644 src/games/skyrimvr/src/CMakeLists.txt create mode 100644 src/games/skyrimvr/src/SConscript create mode 100644 src/games/skyrimvr/src/game_skyrimvr_en.ts create mode 100644 src/games/skyrimvr/src/gameskyrimvr.cpp create mode 100644 src/games/skyrimvr/src/gameskyrimvr.h create mode 100644 src/games/skyrimvr/src/gameskyrimvr.json create mode 100644 src/games/skyrimvr/src/gameskyrimvr.pro create mode 100644 src/games/skyrimvr/src/skyrimvrdataarchives.cpp create mode 100644 src/games/skyrimvr/src/skyrimvrdataarchives.h create mode 100644 src/games/skyrimvr/src/skyrimvrgameplugins.cpp create mode 100644 src/games/skyrimvr/src/skyrimvrgameplugins.h create mode 100644 src/games/skyrimvr/src/skyrimvrsavegame.cpp create mode 100644 src/games/skyrimvr/src/skyrimvrsavegame.h create mode 100644 src/games/skyrimvr/src/skyrimvrsavegameinfo.cpp create mode 100644 src/games/skyrimvr/src/skyrimvrsavegameinfo.h create mode 100644 src/games/skyrimvr/src/skyrimvrscriptextender.cpp create mode 100644 src/games/skyrimvr/src/skyrimvrscriptextender.h create mode 100644 src/games/skyrimvr/src/skyrimvrunmanagedmods.cpp create mode 100644 src/games/skyrimvr/src/skyrimvrunmanagedmods.h diff --git a/src/games/skyrimvr/.gitignore b/src/games/skyrimvr/.gitignore new file mode 100644 index 00000000..4c4fa01e --- /dev/null +++ b/src/games/skyrimvr/.gitignore @@ -0,0 +1,8 @@ +CMakeLists.txt.user +edit +build +std*.log +build +vsbuild +vs_stderr.log +vs_stdout.log diff --git a/src/games/skyrimvr/CMakeLists.txt b/src/games/skyrimvr/CMakeLists.txt new file mode 100644 index 00000000..4731285b --- /dev/null +++ b/src/games/skyrimvr/CMakeLists.txt @@ -0,0 +1,16 @@ +CMAKE_MINIMUM_REQUIRED(VERSION 2.8) + +SET(PROJ_NAME game_skyrimvr) + +PROJECT(${PROJ_NAME}) + +SET(DEPENDENCIES_DIR CACHE PATH "") + +# hint to find qt in dependencies path +LIST(APPEND CMAKE_PREFIX_PATH ${QT_ROOT}/lib/cmake) +LIST(APPEND CMAKE_PREFIX_PATH ${LZ4_ROOT}/dll) + +FILE(GLOB_RECURSE BOOST_ROOT ${DEPENDENCIES_DIR}/boost*/project-config.jam) +GET_FILENAME_COMPONENT(BOOST_ROOT ${BOOST_ROOT} DIRECTORY) + +ADD_SUBDIRECTORY(src) diff --git a/src/games/skyrimvr/src/CMakeLists.txt b/src/games/skyrimvr/src/CMakeLists.txt new file mode 100644 index 00000000..a0cdda19 --- /dev/null +++ b/src/games/skyrimvr/src/CMakeLists.txt @@ -0,0 +1,72 @@ +CMAKE_MINIMUM_REQUIRED (VERSION 2.8) + +CMAKE_POLICY(SET CMP0020 NEW) + +FILE(GLOB ${PROJ_NAME}_SRCS *.cpp) +FILE(GLOB ${PROJ_NAME}_HDRS *.h) +FILE(GLOB ${PROJ_NAME}_FORMS *.ui) + + +SET(CMAKE_INCLUDE_CURRENT_DIR ON) +SET(CMAKE_AUTOMOC ON) +SET(CMAKE_AUTOUIC ON) +FIND_PACKAGE(Qt5Widgets REQUIRED) +QT5_WRAP_UI(${PROJ_NAME}_UIHDRS ${${PROJ_NAME}_FORMS}) +FIND_PACKAGE(Qt5LinguistTools) +QT5_CREATE_TRANSLATION(${PROJ_NAME}_translations_qm ${CMAKE_SOURCE_DIR}/src ${CMAKE_SOURCE_DIR}/src/${PROJ_NAME}_en.ts) + +SET(Boost_USE_STATIC_LIBS ON) +SET(Boost_USE_MULTITHREADED ON) +SET(Boost_USE_STATIC_RUNTIME OFF) +FIND_PACKAGE(Boost) + +IF (Boost_FOUND) + INCLUDE_DIRECTORIES(${Boost_INCLUDE_DIRS}) +ENDIF () + +SET(default_project_path "${CMAKE_SOURCE_DIR}/..") +GET_FILENAME_COMPONENT(${default_project_path} ${default_project_path} REALPATH) + +SET(project_path "${default_project_path}" CACHE PATH "path to the other mo projects") +SET(lib_path "${project_path}/../../install/libs") + +INCLUDE_DIRECTORIES(${project_path}/uibase/src + ${project_path}/game_features/src + ${project_path}/game_gamebryo/src) +LINK_DIRECTORIES(${project_path}/uibase/build/src + ${lib_path} + ${LZ4_ROOT}/dll) + +ADD_DEFINITIONS(-DUNICODE -D_UNICODE) + +ADD_LIBRARY(${PROJ_NAME} SHARED ${${PROJ_NAME}_HDRS} ${${PROJ_NAME}_SRCS} ${${PROJ_NAME}_UIHDRS} ${${PROJ_NAME}_translations_qm}) +TARGET_LINK_LIBRARIES(${PROJ_NAME} + Qt5::Widgets + ${Boost_LIBRARIES} + DbgHelp + uibase + game_gamebryo + liblz4 + version) + +IF(MSVC) + SET_TARGET_PROPERTIES(${PROJ_NAME} PROPERTIES LINK_FLAGS "/LARGEADDRESSAWARE") +ELSE(MSVC) + SET_TARGET_PROPERTIES(${PROJ_NAME} PROPERTIES LINK_FLAGS "-std=c++11") +ENDIF(MSVC) + +IF (NOT "${OPTIMIZE_COMPILE_FLAGS}" STREQUAL "") + SET_TARGET_PROPERTIES(${PROJ_NAME} PROPERTIES COMPILE_FLAGS_RELWITHDEBINFO ${OPTIMIZE_COMPILE_FLAGS}) +ENDIF() +IF (NOT "${OPTIMIZE_LINK_FLAGS}" STREQUAL "") + SET_TARGET_PROPERTIES(${PROJ_NAME} PROPERTIES LINK_FLAGS_RELWITHDEBINFO ${OPTIMIZE_LINK_FLAGS}) +ENDIF() + +QT5_USE_MODULES(${PROJ_NAME} Widgets) + +############### +## Installation + +INSTALL(TARGETS ${PROJ_NAME} + RUNTIME DESTINATION bin/plugins) +INSTALL(FILES ${CMAKE_CURRENT_BINARY_DIR}/${PROJ_NAME}.pdb DESTINATION pdb) diff --git a/src/games/skyrimvr/src/SConscript b/src/games/skyrimvr/src/SConscript new file mode 100644 index 00000000..42e6f0a5 --- /dev/null +++ b/src/games/skyrimvr/src/SConscript @@ -0,0 +1,13 @@ +Import('qt_env') + +env = qt_env.Clone() + +env.AppendUnique(CPPDEFINES = [ 'GAMESKYRIMVR_LIBRARY' ]) + +env.RequiresGamebryo() + +lib = env.SharedLibrary('gameSkyrimVR', env.Glob('*.cpp')) +env.InstallModule(lib) + +res = env['QT_USED_MODULES'] +Return('res') diff --git a/src/games/skyrimvr/src/game_skyrimvr_en.ts b/src/games/skyrimvr/src/game_skyrimvr_en.ts new file mode 100644 index 00000000..069b6cf1 --- /dev/null +++ b/src/games/skyrimvr/src/game_skyrimvr_en.ts @@ -0,0 +1,30 @@ + + + + + GameSkyrimVR + + + Adds support for the game Skyrim VR. + + + + + QObject + + + failed to query registry path (preflight): %1 + + + + + failed to query registry path (read): %1 + + + + + Some of your plugins have invalid names! These plugins can not be loaded by the game. Please see mo_interface.log for a list of affected plugins and rename them. + + + + diff --git a/src/games/skyrimvr/src/gameskyrimvr.cpp b/src/games/skyrimvr/src/gameskyrimvr.cpp new file mode 100644 index 00000000..86c17699 --- /dev/null +++ b/src/games/skyrimvr/src/gameskyrimvr.cpp @@ -0,0 +1,363 @@ +#include "gameskyrimvr.h" + +#include "skyrimvrdataarchives.h" +#include "skyrimvrscriptextender.h" +#include "skyrimvrsavegameinfo.h" +#include "skyrimvrgameplugins.h" +#include "skyrimvrunmanagedmods.h" + +#include +#include "iplugingame.h" +#include +#include +#include +#include "versioninfo.h" + +#include +#include +#include +#include +#include +#include +#include + +#include + +#include "utility.h" +#include +#include +#include "scopeguard.h" + +namespace { + + std::unique_ptr getRegValue(HKEY key, LPCWSTR path, LPCWSTR value, + DWORD flags, LPDWORD type = nullptr) + { + DWORD size = 0; + HKEY subKey; + LONG res = ::RegOpenKeyExW(key, path, 0, + KEY_QUERY_VALUE | KEY_WOW64_32KEY, &subKey); + if (res != ERROR_SUCCESS) { + return std::unique_ptr(); + } + res = ::RegGetValueW(subKey, L"", value, flags, type, nullptr, &size); + if (res == ERROR_FILE_NOT_FOUND || res == ERROR_UNSUPPORTED_TYPE) { + return std::unique_ptr(); + } + if (res != ERROR_SUCCESS && res != ERROR_MORE_DATA) { + throw MOBase::MyException(QObject::tr("failed to query registry path (preflight): %1").arg(res, 0, 16)); + } + + std::unique_ptr result(new BYTE[size]); + res = ::RegGetValueW(subKey, L"", value, flags, type, result.get(), &size); + + if (res != ERROR_SUCCESS) { + throw MOBase::MyException(QObject::tr("failed to query registry path (read): %1").arg(res, 0, 16)); + } + + return result; + } + + QString findInRegistry(HKEY baseKey, LPCWSTR path, LPCWSTR value) + { + std::unique_ptr buffer = getRegValue(baseKey, path, value, RRF_RT_REG_SZ | RRF_NOEXPAND); + + return QString::fromUtf16(reinterpret_cast(buffer.get())); + } + + QString getKnownFolderPath(REFKNOWNFOLDERID folderId, bool useDefault) + { + PWSTR path = nullptr; + ON_BLOCK_EXIT([&]() { + if (path != nullptr) ::CoTaskMemFree(path); + }); + + if (::SHGetKnownFolderPath(folderId, useDefault ? KF_FLAG_DEFAULT_PATH : 0, NULL, &path) == S_OK) { + return QDir::fromNativeSeparators(QString::fromWCharArray(path)); + } + else { + return QString(); + } + } + + + QString getSpecialPath(const QString &name) + { + QString base = findInRegistry(HKEY_CURRENT_USER, + L"Software\\Microsoft\\Windows\\CurrentVersion\\Explorer\\User Shell Folders", + name.toStdWString().c_str()); + + WCHAR temp[MAX_PATH]; + if (::ExpandEnvironmentStringsW(base.toStdWString().c_str(), temp, MAX_PATH) != 0) { + return QString::fromWCharArray(temp); + } + else { + return base; + } + } + + QString determineMyGamesPath(const QString &gameName) + { + // a) this is the way it should work. get the configured My Documents directory + QString result = getKnownFolderPath(FOLDERID_Documents, false); + + // b) if there is no directory there, look in the default directory + if (result.isEmpty() + || !QFileInfo(result + "/My Games/" + gameName).exists()) { + result = getKnownFolderPath(FOLDERID_Documents, true); + } + // c) finally, look in the registry. This is discouraged + if (result.isEmpty() + || !QFileInfo(result + "/My Games/" + gameName).exists()) { + result = getSpecialPath("Personal"); + } + + return result + "/My Games/" + gameName; + } + + +} + + +using namespace MOBase; + +GameSkyrimVR::GameSkyrimVR() +{ +} + +void GameSkyrimVR::setGamePath(const QString &path) +{ + m_GamePath = path; +} + +QDir GameSkyrimVR::documentsDirectory() const +{ + return m_MyGamesPath; +} + +QString GameSkyrimVR::identifyGamePath() const +{ + QString path = "Software\\Bethesda Softworks\\" + gameName(); + return findInRegistry(HKEY_LOCAL_MACHINE, path.toStdWString().c_str(), L"Installed Path"); +} + +QDir GameSkyrimVR::savesDirectory() const +{ + return QDir(m_MyGamesPath + "/Saves"); +} + +QString GameSkyrimVR::myGamesPath() const +{ + return m_MyGamesPath; +} + +bool GameSkyrimVR::isInstalled() const +{ + return !m_GamePath.isEmpty(); +} + +bool GameSkyrimVR::init(IOrganizer *moInfo) +{ + if (!GameGamebryo::init(moInfo)) { + return false; + } + + m_Organizer = moInfo; + m_GamePath = GameSkyrimVR::identifyGamePath(); + m_MyGamesPath = determineMyGamesPath(gameName()); + + + registerFeature(new SkyrimVRScriptExtender(this)); + registerFeature(new SkyrimVRDataArchives(myGamesPath())); + registerFeature(new GamebryoLocalSavegames(myGamesPath(), "SkyrimPrefs.ini")); + registerFeature(new SkyrimVRSaveGameInfo(this)); + registerFeature(new SkyrimVRGamePlugins(moInfo)); + registerFeature(new SkyrimVRUnmangedMods(this)); + + return true; +} + + + +QString GameSkyrimVR::gameName() const +{ + return "Skyrim VR"; +} + +QList GameSkyrimVR::executables() const +{ + return QList() + << ExecutableInfo("SKSE", findInGameFolder(feature()->loaderName())) + << ExecutableInfo("Skyrim VR", findInGameFolder(binaryName())) + << ExecutableInfo("Creation Kit", findInGameFolder("CreationKit.exe")) + << ExecutableInfo("LOOT", getLootPath()).withArgument("--game=\"Skyrim Special Edition\"") + ; +} + +QFileInfo GameSkyrimVR::findInGameFolder(const QString &relativePath) const +{ + return QFileInfo(m_GamePath + "/" + relativePath); +} + +QString GameSkyrimVR::name() const +{ + return "Skyrim VR Support Plugin"; +} + +QString GameSkyrimVR::author() const +{ + return "Brixified"; +} + +QString GameSkyrimVR::description() const +{ + return tr("Adds support for the game Skyrim VR."); +} + +MOBase::VersionInfo GameSkyrimVR::version() const +{ + return VersionInfo(0, 1, 5, VersionInfo::RELEASE_ALPHA); +} + +bool GameSkyrimVR::isActive() const +{ + return qApp->property("managed_game").value() == this; +} + +QList GameSkyrimVR::settings() const +{ + return QList(); +} + +void GameSkyrimVR::initializeProfile(const QDir &path, ProfileSettings settings) const +{ + if (settings.testFlag(IPluginGame::MODS)) { + copyToProfile(localAppFolder() + "/Skyrim VR", path, "plugins.txt"); + copyToProfile(localAppFolder() + "/Skyrim VR", path, "loadorder.txt"); + } + + if (settings.testFlag(IPluginGame::CONFIGURATION)) { + copyToProfile(myGamesPath(), path, "skyrimprefs.ini"); + } +} + +QString GameSkyrimVR::savegameExtension() const +{ + return "ess"; +} + +QString GameSkyrimVR::savegameSEExtension() const +{ + return "skse"; +} + +QString GameSkyrimVR::steamAPPId() const +{ + return "611670"; +} + +QStringList GameSkyrimVR::primaryPlugins() const { + QStringList plugins = { "skyrim.esm", "update.esm", "dawnguard.esm", "hearthfires.esm", "dragonborn.esm", "skyrimvr.esm" }; + + plugins.append(CCPlugins()); + + return plugins; +} + +QStringList GameSkyrimVR::gameVariants() const +{ + return{ "Regular" }; +} + +QString GameSkyrimVR::gameShortName() const +{ + return "SkyrimSE"; +} + +QString GameSkyrimVR::gameNexusName() const +{ + return "skyrimspecialedition"; +} + + +QStringList GameSkyrimVR::iniFiles() const +{ + return{ "skyrimprefs.ini" }; +} + +QStringList GameSkyrimVR::DLCPlugins() const +{ + return{ "dawnguard.esm", "hearthfires.esm", "dragonborn.esm" }; +} + +QStringList GameSkyrimVR::CCPlugins() const +{ + QStringList plugins = {}; + QFile file(gameDirectory().filePath("Skyrim.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::LoadOrderMechanism GameSkyrimVR::loadOrderMechanism() const +{ + return IPluginGame::LoadOrderMechanism::PluginsTxt; +} + +int GameSkyrimVR::nexusModOrganizerID() const +{ + return 6194; //... Should be 0? +} + +int GameSkyrimVR::nexusGameID() const +{ + return 1704; //1704 +} + +QString GameSkyrimVR::getLauncherName() const +{ + return binaryName(); // Skyrim VR has no Launcher, so we just return the name of the game binary +} + +QDir GameSkyrimVR::gameDirectory() const +{ + return QDir(m_GamePath); +} + +QString GameSkyrimVR::binaryName() const +{ + return "SkyrimVR.exe"; +} + +// Not to delete all the spaces... +MappingType GameSkyrimVR::mappings() const +{ + MappingType result; + + for (const QString &profileFile : { "plugins.txt", "loadorder.txt" }) { + result.push_back({ m_Organizer->profilePath() + "/" + profileFile, + localAppFolder() + "/" + gameName() + "/" + profileFile, + false }); + } + + return result; +} + diff --git a/src/games/skyrimvr/src/gameskyrimvr.h b/src/games/skyrimvr/src/gameskyrimvr.h new file mode 100644 index 00000000..05047707 --- /dev/null +++ b/src/games/skyrimvr/src/gameskyrimvr.h @@ -0,0 +1,68 @@ +#ifndef _GAMESKYRIMVR_H +#define _GAMESKYRIMVR_H + +#include "gamegamebryo.h" + +#include +#include + +class GameSkyrimVR : public GameGamebryo +{ + Q_OBJECT + Q_PLUGIN_METADATA(IID "com.soundcontactstudio.GameSkyrimVR" FILE "gameskyrimVR.json") + +public: + GameSkyrimVR(); + + virtual bool init(MOBase::IOrganizer *moInfo) override; + +public: // IPluginGame interface + virtual QString gameName() const override; + + virtual QList executables() const override; + virtual void initializeProfile(const QDir &path, ProfileSettings settings) const override; + virtual QString savegameExtension() const override; + virtual QString savegameSEExtension() const override; + virtual QString steamAPPId() const override; + virtual QStringList primaryPlugins() const override; + virtual QStringList gameVariants() const override; + virtual QString gameShortName() const override; + virtual QString gameNexusName() const override; + virtual QStringList iniFiles() const override; + virtual QStringList DLCPlugins() const override; + virtual QStringList CCPlugins() const override; + virtual LoadOrderMechanism loadOrderMechanism() const override; + virtual int nexusModOrganizerID() const override; + virtual int nexusGameID() const override; + virtual QString getLauncherName() const override; + virtual QString GameSkyrimVR::binaryName() const; + + 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 author() const override; + virtual QString description() const override; + virtual MOBase::VersionInfo version() const override; + virtual bool isActive() const override; + virtual QList settings() const override; + +public: // IPluginFileMapper + virtual MappingType mappings() const; + +protected: + QDir documentsDirectory() const; + QDir savesDirectory() const; + QFileInfo findInGameFolder(const QString &relativePath) const; + QString myGamesPath() const; + +private: + MOBase::IOrganizer *m_Organizer; + QString identifyGamePath() const; + QString m_GamePath; + QString m_MyGamesPath; +}; + +#endif // _GAMESKYRIMVR_H diff --git a/src/games/skyrimvr/src/gameskyrimvr.json b/src/games/skyrimvr/src/gameskyrimvr.json new file mode 100644 index 00000000..0967ef42 --- /dev/null +++ b/src/games/skyrimvr/src/gameskyrimvr.json @@ -0,0 +1 @@ +{} diff --git a/src/games/skyrimvr/src/gameskyrimvr.pro b/src/games/skyrimvr/src/gameskyrimvr.pro new file mode 100644 index 00000000..5237d62b --- /dev/null +++ b/src/games/skyrimvr/src/gameskyrimvr.pro @@ -0,0 +1,50 @@ +#------------------------------------------------- +# +# Project created by QtCreator 2016-10-28T12:24:19 +# +#------------------------------------------------- + + +TARGET = gameSkyrimVR +TEMPLATE = lib + +CONFIG += plugins +CONFIG += dll + +DEFINES += GAMESKYRIMVR_LIBRARY + +SOURCES += gameskyrimvr.cpp \ + skyrimvrbsainvalidation.cpp \ + skyrimvrscriptextender.cpp \ + skyrimvrdataarchives.cpp \ + skyrimvrsavegame.cpp \ + skyrimvrsavegameinfo.cpp + +HEADERS += gameskyrimvr.h \ + skyrimvrbsainvalidation.h \ + skyrimvrscriptextender.h \ + skyrimvrdataarchives.h \ + skyrimvrsavegame.h \ + skyrimvrsavegameinfo.h + +CONFIG(debug, debug|release) { + LIBS += -L"$${OUT_PWD}/../gameGamebryo/debug" + PRE_TARGETDEPS += \ + $$OUT_PWD/../gameGamebryo/debug/gameGamebryo.lib +} else { + LIBS += -L"$${OUT_PWD}/../gameGamebryo/release" + PRE_TARGETDEPS += \ + $$OUT_PWD/../gameGamebryo/release/gameGamebryo.lib +} + +include(../plugin_template.pri) + +INCLUDEPATH += "$${BOOSTPATH}" "$${PWD}/../gamefeatures" "$${PWD}/../gamegamebryo" + +LIBS += -ladvapi32 -lole32 -lgameGamebryo + +OTHER_FILES += \ + gameskyrimvr.json\ + SConscript \ + CMakeLists.txt + diff --git a/src/games/skyrimvr/src/skyrimvrdataarchives.cpp b/src/games/skyrimvr/src/skyrimvrdataarchives.cpp new file mode 100644 index 00000000..e286faf5 --- /dev/null +++ b/src/games/skyrimvr/src/skyrimvrdataarchives.cpp @@ -0,0 +1,57 @@ +#include "skyrimvrdataarchives.h" + +#include "iprofile.h" +#include + +SkyrimVRDataArchives::SkyrimVRDataArchives(const QDir &myGamesDir) : + GamebryoDataArchives(myGamesDir) +{} + +QStringList SkyrimVRDataArchives::vanillaArchives() const +{ + return{ "Skyrim - Textures0.bsa" + , "Skyrim - Textures1.bsa" + , "Skyrim - Textures2.bsa" + , "Skyrim - Textures3.bsa" + , "Skyrim - Textures4.bsa" + , "Skyrim - Textures5.bsa" + , "Skyrim - Textures6.bsa" + , "Skyrim - Textures7.bsa" + , "Skyrim - Textures8.bsa" + , "Skyrim - Meshes0.bsa" + , "Skyrim - Meshes1.bsa" + , "Skyrim - Voices_en0.bsa" + , "Skyrim - Sounds.bsa" + , "Skyrim - Interface.bsa" + , "Skyrim - Animations.bsa" + , "Skyrim - Shaders.bsa" + , "Skyrim - Misc.bsa" + , "Skyrim - Patch.bsa" + , "Skyrim_VR - Main.bsa" }; +} + + +QStringList SkyrimVRDataArchives::archives(const MOBase::IProfile *profile) const +{ + QStringList result; + + QString iniFile = profile->localSettingsEnabled() ? QDir(profile->absolutePath()).absoluteFilePath("skyrim.ini") : m_LocalGameDir.absoluteFilePath("skyrim.ini"); + result.append(getArchivesFromKey(iniFile, "SResourceArchiveList")); + result.append(getArchivesFromKey(iniFile, "SResourceArchiveList2")); + + return result; +} + +void SkyrimVRDataArchives::writeArchiveList(MOBase::IProfile *profile, const QStringList &before) +{ + QString list = before.join(", "); + + QString iniFile = profile->localSettingsEnabled() ? QDir(profile->absolutePath()).absoluteFilePath("skyrim.ini") : m_LocalGameDir.absoluteFilePath("skyrim.ini"); + if (list.length() > 255) { + int splitIdx = list.lastIndexOf(",", 256); + setArchivesToKey(iniFile, "SResourceArchiveList", list.mid(0, splitIdx)); + setArchivesToKey(iniFile, "SResourceArchiveList2", list.mid(splitIdx + 2)); + } else { + setArchivesToKey(iniFile, "SResourceArchiveList", list); + } +} diff --git a/src/games/skyrimvr/src/skyrimvrdataarchives.h b/src/games/skyrimvr/src/skyrimvrdataarchives.h new file mode 100644 index 00000000..7ed603bb --- /dev/null +++ b/src/games/skyrimvr/src/skyrimvrdataarchives.h @@ -0,0 +1,29 @@ +#ifndef _SKYRIMVRDATAARCHIVES_H +#define _SKYRIMVRDATAARCHIVES_H + +#include "gamebryodataarchives.h" +#include +#include + +namespace MOBase { class IProfile; } + + +class SkyrimVRDataArchives : public GamebryoDataArchives +{ + +public: + + SkyrimVRDataArchives(const QDir &myGamesDir); + +public: + + 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 // _SKYRIMVRDATAARCHIVES_H diff --git a/src/games/skyrimvr/src/skyrimvrgameplugins.cpp b/src/games/skyrimvr/src/skyrimvrgameplugins.cpp new file mode 100644 index 00000000..df0700b1 --- /dev/null +++ b/src/games/skyrimvr/src/skyrimvrgameplugins.cpp @@ -0,0 +1,165 @@ +#include "skyrimvrgameplugins.h" +#include +#include +#include +#include +#include + +#include +#include +#include + + +using MOBase::IPluginGame; +using MOBase::IPluginList; +using MOBase::IOrganizer; +using MOBase::SafeWriteFile; +using MOBase::reportError; + +SkyrimVRGamePlugins::SkyrimVRGamePlugins(IOrganizer *organizer) + : GamebryoGamePlugins(organizer) +{ +} + +void SkyrimVRGamePlugins::writePluginList(const IPluginList *pluginList, + const QString &filePath) { + SafeWriteFile file(filePath); + + QTextCodec *textCodec = localCodec(); + + file->resize(0); + + file->write(textCodec->fromUnicode( + "# This file was automatically generated by Mod Organizer.\r\n")); + + bool invalidFileNames = false; + int writtenCount = 0; + + QStringList plugins = pluginList->pluginNames(); + std::sort(plugins.begin(), plugins.end(), + [pluginList](const QString &lhs, const QString &rhs) { + return pluginList->priority(lhs) < pluginList->priority(rhs); + }); + + QStringList PrimaryPlugins = organizer()->managedGame()->primaryPlugins(); + + //TODO: do not write plugins in OFFICIAL_FILES container + for (const QString &pluginName : plugins) { + if (!PrimaryPlugins.contains(pluginName,Qt::CaseInsensitive)) { + if (pluginList->state(pluginName) == IPluginList::STATE_ACTIVE) { + if (!textCodec->canEncode(pluginName)) { + invalidFileNames = true; + qCritical("invalid plugin name %s", qPrintable(pluginName)); + } + else + { + file->write("*"); + file->write(textCodec->fromUnicode(pluginName)); + } + file->write("\r\n"); + ++writtenCount; + } + else + { + if (!textCodec->canEncode(pluginName)) { + invalidFileNames = true; + qCritical("invalid plugin name %s", qPrintable(pluginName)); + } + else + { + file->write(textCodec->fromUnicode(pluginName)); + } + file->write("\r\n"); + ++writtenCount; + } + } + } + + if (invalidFileNames) { + reportError(QObject::tr("Some of your plugins have invalid names! These " + "plugins can not be loaded by the game. Please see " + "mo_interface.log for a list of affected plugins " + "and rename them.")); + } + + if (file.commitIfDifferent(m_LastSaveHash[filePath])) { + qDebug("%s saved", qPrintable(QDir::toNativeSeparators(filePath))); + } +} + +bool SkyrimVRGamePlugins::readPluginList(MOBase::IPluginList *pluginList, + bool useLoadOrder) +{ + QStringList plugins = pluginList->pluginNames(); + QStringList primaryPlugins = organizer()->managedGame()->primaryPlugins(); + QStringList loadOrder(primaryPlugins); + + for (const QString &pluginName : loadOrder) { + if (pluginList->state(pluginName) != IPluginList::STATE_MISSING) { + pluginList->setState(pluginName, IPluginList::STATE_ACTIVE); + } + } + + QString filePath = organizer()->profile()->absolutePath() + "/plugins.txt"; + QFile file(filePath); + if (!file.open(QIODevice::ReadOnly)) { + qWarning("%s not found", qPrintable(filePath)); + return false; + } + ON_BLOCK_EXIT([&]() { file.close(); }); + + if (file.size() == 0) { + // MO stores at least a header in the file. if it's completely empty the + // file is broken + qWarning("%s empty", qPrintable(filePath)); + return false; + } + + while (!file.atEnd()) { + QByteArray line = file.readLine(); + QString pluginName; + if ((line.size() > 0) && (line.at(0) != '#')) { + pluginName = localCodec()->toUnicode(line.trimmed().constData()); + } + if (!primaryPlugins.contains(pluginName, Qt::CaseInsensitive)) { + if (pluginName.startsWith('*')) { + pluginName.remove(0, 1); + if (pluginName.size() > 0) { + pluginList->setState(pluginName, IPluginList::STATE_ACTIVE); + plugins.removeAll(pluginName); + if (!loadOrder.contains(pluginName, Qt::CaseInsensitive)) { + loadOrder.append(pluginName); + } + } + } + else + { + if (pluginName.size() > 0) { + pluginList->setState(pluginName, IPluginList::STATE_INACTIVE); + plugins.removeAll(pluginName); + if (!loadOrder.contains(pluginName, Qt::CaseInsensitive)) { + loadOrder.append(pluginName); + } + } + } + } + else + { + pluginName.remove(0, 1); + plugins.removeAll(pluginName); + } + } + + file.close(); + + // we removed each plugin found in the file, so what's left are inactive mods + for (const QString &pluginName : plugins) { + pluginList->setState(pluginName, IPluginList::STATE_INACTIVE); + } + + if (useLoadOrder) { + pluginList->setLoadOrder(loadOrder); + } + + return true; +} diff --git a/src/games/skyrimvr/src/skyrimvrgameplugins.h b/src/games/skyrimvr/src/skyrimvrgameplugins.h new file mode 100644 index 00000000..775e2a72 --- /dev/null +++ b/src/games/skyrimvr/src/skyrimvrgameplugins.h @@ -0,0 +1,26 @@ +#ifndef _SKYRIMVRGAMEPLUGINS_H +#define _SKYRIMVRGAMEPLUGINS_H + + +#include +#include +#include +#include + + +class SkyrimVRGamePlugins : public GamebryoGamePlugins +{ +public: + SkyrimVRGamePlugins(MOBase::IOrganizer *organizer); + +protected: + virtual void writePluginList(const MOBase::IPluginList *pluginList, + const QString &filePath) override; + virtual bool readPluginList(MOBase::IPluginList *pluginList, + bool useLoadOrder) override; + +private: + std::map m_LastSaveHash; +}; + +#endif // _SKYRIMVRGAMEPLUGINS_H diff --git a/src/games/skyrimvr/src/skyrimvrsavegame.cpp b/src/games/skyrimvr/src/skyrimvrsavegame.cpp new file mode 100644 index 00000000..b05b914d --- /dev/null +++ b/src/games/skyrimvr/src/skyrimvrsavegame.cpp @@ -0,0 +1,73 @@ +#include "skyrimvrsavegame.h" + +#include + +SkyrimVRSaveGame::SkyrimVRSaveGame(QString const &fileName, MOBase::IPluginGame const *game, bool const lightEnabled) : + GamebryoSaveGame(fileName, game, lightEnabled) +{ + FileWrapper file(this, "TESV_SAVEGAME"); //10bytes + unsigned long headerSize; + file.read(headerSize); // header size "TESV_SAVEGAME" + file.skip(); // header version 74. Original Skyrim is 79 + file.read(m_SaveNumber); + + file.read(m_PCName); + + unsigned long temp; + file.read(temp); + m_PCLevel = static_cast(temp); + + file.read(m_PCLocation); + + QString timeOfDay; + file.read(timeOfDay); + + QString race; + file.read(race); // race name (i.e. BretonRace) + + file.skip(); // Player gender (0 = male) + file.skip(2); // experience gathered, experience required + + FILETIME ftime; + file.read(ftime); //filetime + //A file time is a 64-bit value that represents the number of 100-nanosecond + //intervals that have elapsed since 12:00 A.M. January 1, 1601 Coordinated Universal Time (UTC). + //So we need to convert that to something useful + + //For some reason, the file time is off by about 6 hours. + //So we need to subtract those 6 hours from the filetime. + _ULARGE_INTEGER time; + time.LowPart = ftime.dwLowDateTime; + time.HighPart = ftime.dwHighDateTime; + time.QuadPart -= 2.16e11; + ftime.dwHighDateTime = time.HighPart; + ftime.dwLowDateTime = time.LowPart; + + SYSTEMTIME ctime; + ::FileTimeToSystemTime(&ftime, &ctime); + + setCreationTime(ctime); + + unsigned long width; + unsigned long height; + file.read(width); + file.read(height); + + file.read(m_CompressionType); + + file.readImage(width, height, 320, true); + + file.openCompressedData(); + + uint8_t saveGameVersion = file.readChar(); + uint8_t pluginInfoSize = file.readChar(); + uint16_t other = file.readShort(); //Unknown + + file.readPlugins(1); // Just empty data + + if (saveGameVersion >= 78) { + file.readLightPlugins(); + } + + file.closeCompressedData(); +} diff --git a/src/games/skyrimvr/src/skyrimvrsavegame.h b/src/games/skyrimvr/src/skyrimvrsavegame.h new file mode 100644 index 00000000..5f274dac --- /dev/null +++ b/src/games/skyrimvr/src/skyrimvrsavegame.h @@ -0,0 +1,14 @@ +#ifndef _SKYRIMVRSAVEGAME_H +#define _SKYRIMVRSAVEGAME_H + +#include "gamebryosavegame.h" + +namespace MOBase { class IPluginGame; } + +class SkyrimVRSaveGame : public GamebryoSaveGame +{ +public: + SkyrimVRSaveGame(QString const &fileName, MOBase::IPluginGame const *game, bool const lightEnabled = true); +}; + +#endif // _SKYRIMVRSAVEGAME_H diff --git a/src/games/skyrimvr/src/skyrimvrsavegameinfo.cpp b/src/games/skyrimvr/src/skyrimvrsavegameinfo.cpp new file mode 100644 index 00000000..9f1bd18f --- /dev/null +++ b/src/games/skyrimvr/src/skyrimvrsavegameinfo.cpp @@ -0,0 +1,18 @@ +#include "skyrimvrsavegameinfo.h" + +#include "skyrimvrsavegame.h" +#include "gamegamebryo.h" + +SkyrimVRSaveGameInfo::SkyrimVRSaveGameInfo(GameGamebryo const *game) : + GamebryoSaveGameInfo(game) +{ +} + +SkyrimVRSaveGameInfo::~SkyrimVRSaveGameInfo() +{ +} + +const MOBase::ISaveGame *SkyrimVRSaveGameInfo::getSaveGameInfo(const QString &file) const +{ + return new SkyrimVRSaveGame(file, m_Game); +} diff --git a/src/games/skyrimvr/src/skyrimvrsavegameinfo.h b/src/games/skyrimvr/src/skyrimvrsavegameinfo.h new file mode 100644 index 00000000..677ec1dc --- /dev/null +++ b/src/games/skyrimvr/src/skyrimvrsavegameinfo.h @@ -0,0 +1,17 @@ +#ifndef _SKYRIMVRSAVEGAMEINFO_H +#define _SKYRIMVRSAVEGAMEINFO_H + +#include "gamebryosavegameinfo.h" + +class GameGamebryo; + +class SkyrimVRSaveGameInfo : public GamebryoSaveGameInfo +{ +public: + SkyrimVRSaveGameInfo(GameGamebryo const *game); + ~SkyrimVRSaveGameInfo(); + + virtual MOBase::ISaveGame const *getSaveGameInfo(QString const &file) const override; +}; + +#endif // _SKYRIMVRSAVEGAMEINFO_H diff --git a/src/games/skyrimvr/src/skyrimvrscriptextender.cpp b/src/games/skyrimvr/src/skyrimvrscriptextender.cpp new file mode 100644 index 00000000..6a133545 --- /dev/null +++ b/src/games/skyrimvr/src/skyrimvrscriptextender.cpp @@ -0,0 +1,24 @@ +#include "skyrimvrscriptextender.h" + +#include +#include + +SkyrimVRScriptExtender::SkyrimVRScriptExtender(GameGamebryo const *game) : + GamebryoScriptExtender(game) +{ +} + +QString SkyrimVRScriptExtender::BinaryName() const +{ + return "skse64_loader.exe"; +} + +QString SkyrimVRScriptExtender::PluginPath() const +{ + return "skse/plugins"; +} + +QStringList SkyrimVRScriptExtender::saveGameAttachmentExtensions() const +{ + return { }; +} diff --git a/src/games/skyrimvr/src/skyrimvrscriptextender.h b/src/games/skyrimvr/src/skyrimvrscriptextender.h new file mode 100644 index 00000000..4afc8a0e --- /dev/null +++ b/src/games/skyrimvr/src/skyrimvrscriptextender.h @@ -0,0 +1,20 @@ +#ifndef _SKYRIMVRSCRIPTEXTENDER_H +#define _SKYRIMVRSCRIPTEXTENDER_H + +#include "gamebryoscriptextender.h" + +class GameGamebryo; + +class SkyrimVRScriptExtender : public GamebryoScriptExtender +{ +public: + SkyrimVRScriptExtender(GameGamebryo const *game); + + virtual QString BinaryName() const override; + virtual QString PluginPath() const override; + + virtual QStringList saveGameAttachmentExtensions() const override; + +}; + +#endif // _SKYRIMVRSCRIPTEXTENDER_H diff --git a/src/games/skyrimvr/src/skyrimvrunmanagedmods.cpp b/src/games/skyrimvr/src/skyrimvrunmanagedmods.cpp new file mode 100644 index 00000000..a75a43db --- /dev/null +++ b/src/games/skyrimvr/src/skyrimvrunmanagedmods.cpp @@ -0,0 +1,30 @@ +#include "skyrimvrunmanagedmods.h" + +SkyrimVRUnmangedMods::SkyrimVRUnmangedMods(const GameGamebryo *game) + : GamebryoUnmangedMods(game) +{} + +SkyrimVRUnmangedMods::~SkyrimVRUnmangedMods() +{} + +QStringList SkyrimVRUnmangedMods::mods(bool onlyOfficial) const { + QStringList result; + + QStringList pluginList = game()->primaryPlugins(); + QStringList otherPlugins = game()->DLCPlugins(); + otherPlugins.append(game()->CCPlugins()); + for (QString plugin : otherPlugins) { + pluginList.removeAll(plugin); + } + QDir dataDir(game()->dataDirectory()); + for (const QString &fileName : dataDir.entryList({ "*.esp", "*.esl", "*.esm" })) { + if (!pluginList.contains(fileName, Qt::CaseInsensitive)) { + if (!onlyOfficial || pluginList.contains(fileName, Qt::CaseInsensitive)) { + QFileInfo file(fileName); + result.append(file.baseName()); + } + } + } + + return result; +} diff --git a/src/games/skyrimvr/src/skyrimvrunmanagedmods.h b/src/games/skyrimvr/src/skyrimvrunmanagedmods.h new file mode 100644 index 00000000..67846b63 --- /dev/null +++ b/src/games/skyrimvr/src/skyrimvrunmanagedmods.h @@ -0,0 +1,15 @@ +#ifndef _SKYRIMVRUNMANAGEDMODS_H +#define _SKYRIMVRUNMANAGEDMODS_H + +#include "gamebryounmanagedmods.h" +#include + +class SkyrimVRUnmangedMods : public GamebryoUnmangedMods { +public: + SkyrimVRUnmangedMods(const GameGamebryo *game); + ~SkyrimVRUnmangedMods(); + + virtual QStringList mods(bool onlyOfficial) const override; +}; + +#endif // _SKYRIMVRUNMANAGEDMODS_H From b6099ed372ae0b0b1f7a8bf2c58c76dab5fcb825 Mon Sep 17 00:00:00 2001 From: Silarn Date: Sat, 7 Apr 2018 17:12:14 -0500 Subject: [PATCH 0479/1544] [game_fallout4vr] Fix up CMAKE to use /MP and allow building through umbrella --- src/games/fallout4vr/CMakeLists.txt | 4 +++- src/games/fallout4vr/src/CMakeLists.txt | 3 ++- 2 files changed, 5 insertions(+), 2 deletions(-) diff --git a/src/games/fallout4vr/CMakeLists.txt b/src/games/fallout4vr/CMakeLists.txt index 7f463b5a..f31144fc 100644 --- a/src/games/fallout4vr/CMakeLists.txt +++ b/src/games/fallout4vr/CMakeLists.txt @@ -1,4 +1,6 @@ -CMAKE_MINIMUM_REQUIRED(VERSION 2.8) +CMAKE_MINIMUM_REQUIRED(VERSION 2.8.12) + +ADD_COMPILE_OPTIONS($<$:/MP>) SET(PROJ_NAME game_fallout4vr) diff --git a/src/games/fallout4vr/src/CMakeLists.txt b/src/games/fallout4vr/src/CMakeLists.txt index c96b6133..0dba3828 100644 --- a/src/games/fallout4vr/src/CMakeLists.txt +++ b/src/games/fallout4vr/src/CMakeLists.txt @@ -73,4 +73,5 @@ QT5_USE_MODULES(${PROJ_NAME} Widgets) INSTALL(TARGETS ${PROJ_NAME} RUNTIME DESTINATION bin/plugins) -INSTALL(FILES ${CMAKE_CURRENT_BINARY_DIR}/${PROJ_NAME}.pdb DESTINATION pdb) +INSTALL(FILES $ + DESTINATION pdb) From d22bab2e0da787b129564f1c6a918025dce59ac6 Mon Sep 17 00:00:00 2001 From: Silarn Date: Sat, 7 Apr 2018 17:12:15 -0500 Subject: [PATCH 0480/1544] [game_morrowind] Fix up CMAKE to use /MP and allow building through umbrella --- src/games/morrowind/CMakeLists.txt | 4 +++- src/games/morrowind/src/CMakeLists.txt | 3 ++- 2 files changed, 5 insertions(+), 2 deletions(-) diff --git a/src/games/morrowind/CMakeLists.txt b/src/games/morrowind/CMakeLists.txt index f960b421..30035581 100644 --- a/src/games/morrowind/CMakeLists.txt +++ b/src/games/morrowind/CMakeLists.txt @@ -1,4 +1,6 @@ -CMAKE_MINIMUM_REQUIRED(VERSION 2.8) +CMAKE_MINIMUM_REQUIRED(VERSION 2.8.12) + +ADD_COMPILE_OPTIONS($<$:/MP>) SET(PROJ_NAME game_morrowind) diff --git a/src/games/morrowind/src/CMakeLists.txt b/src/games/morrowind/src/CMakeLists.txt index f9e8de37..e240005d 100644 --- a/src/games/morrowind/src/CMakeLists.txt +++ b/src/games/morrowind/src/CMakeLists.txt @@ -74,4 +74,5 @@ QT5_USE_MODULES(${PROJ_NAME} Widgets) INSTALL(TARGETS ${PROJ_NAME} RUNTIME DESTINATION bin/plugins) -INSTALL(FILES ${CMAKE_CURRENT_BINARY_DIR}/${PROJ_NAME}.pdb DESTINATION pdb) +INSTALL(FILES $ + DESTINATION pdb) From ba8fc1824519201069c5a0143680d7cbf81dbf3f Mon Sep 17 00:00:00 2001 From: Silarn Date: Sat, 7 Apr 2018 17:12:16 -0500 Subject: [PATCH 0481/1544] [game_falloutnv] Fix up CMAKE to use /MP and allow building through umbrella --- src/games/falloutnv/CMakeLists.txt | 4 +++- src/games/falloutnv/src/CMakeLists.txt | 3 ++- 2 files changed, 5 insertions(+), 2 deletions(-) diff --git a/src/games/falloutnv/CMakeLists.txt b/src/games/falloutnv/CMakeLists.txt index 3bd2ca8d..7274faf8 100644 --- a/src/games/falloutnv/CMakeLists.txt +++ b/src/games/falloutnv/CMakeLists.txt @@ -1,4 +1,6 @@ -CMAKE_MINIMUM_REQUIRED(VERSION 2.8) +CMAKE_MINIMUM_REQUIRED(VERSION 2.8.12) + +ADD_COMPILE_OPTIONS($<$:/MP>) SET(PROJ_NAME game_falloutNV) diff --git a/src/games/falloutnv/src/CMakeLists.txt b/src/games/falloutnv/src/CMakeLists.txt index 6b2a0f5d..5bc317e7 100644 --- a/src/games/falloutnv/src/CMakeLists.txt +++ b/src/games/falloutnv/src/CMakeLists.txt @@ -68,4 +68,5 @@ QT5_USE_MODULES(${PROJ_NAME} Widgets) INSTALL(TARGETS ${PROJ_NAME} RUNTIME DESTINATION bin/plugins) -INSTALL(FILES ${CMAKE_CURRENT_BINARY_DIR}/${PROJ_NAME}.pdb DESTINATION pdb) +INSTALL(FILES $ + DESTINATION pdb) From 056062bd5b908ddad00695b7ad13e6e8b76ef065 Mon Sep 17 00:00:00 2001 From: Silarn Date: Sat, 7 Apr 2018 17:12:18 -0500 Subject: [PATCH 0482/1544] [game_fallout76] Fix up CMAKE to use /MP and allow building through umbrella --- src/games/fallout76/CMakeLists.txt | 4 +++- src/games/fallout76/src/CMakeLists.txt | 3 ++- 2 files changed, 5 insertions(+), 2 deletions(-) diff --git a/src/games/fallout76/CMakeLists.txt b/src/games/fallout76/CMakeLists.txt index 53ea565d..47e51ba6 100644 --- a/src/games/fallout76/CMakeLists.txt +++ b/src/games/fallout76/CMakeLists.txt @@ -1,4 +1,6 @@ -CMAKE_MINIMUM_REQUIRED(VERSION 2.8) +CMAKE_MINIMUM_REQUIRED(VERSION 2.8.12) + +ADD_COMPILE_OPTIONS($<$:/MP>) SET(PROJ_NAME game_fallout4) diff --git a/src/games/fallout76/src/CMakeLists.txt b/src/games/fallout76/src/CMakeLists.txt index 73c9c557..4d9e4596 100644 --- a/src/games/fallout76/src/CMakeLists.txt +++ b/src/games/fallout76/src/CMakeLists.txt @@ -73,4 +73,5 @@ QT5_USE_MODULES(${PROJ_NAME} Widgets) INSTALL(TARGETS ${PROJ_NAME} RUNTIME DESTINATION bin/plugins) -INSTALL(FILES ${CMAKE_CURRENT_BINARY_DIR}/${PROJ_NAME}.pdb DESTINATION pdb) +INSTALL(FILES $ + DESTINATION pdb) From 7b4d8e77435d99bcaadfc028cd8fc05251eccd64 Mon Sep 17 00:00:00 2001 From: Silarn Date: Sat, 7 Apr 2018 17:12:18 -0500 Subject: [PATCH 0483/1544] [game_fallout4] Fix up CMAKE to use /MP and allow building through umbrella --- src/games/fallout4/CMakeLists.txt | 4 +++- src/games/fallout4/src/CMakeLists.txt | 3 ++- 2 files changed, 5 insertions(+), 2 deletions(-) diff --git a/src/games/fallout4/CMakeLists.txt b/src/games/fallout4/CMakeLists.txt index 53ea565d..47e51ba6 100644 --- a/src/games/fallout4/CMakeLists.txt +++ b/src/games/fallout4/CMakeLists.txt @@ -1,4 +1,6 @@ -CMAKE_MINIMUM_REQUIRED(VERSION 2.8) +CMAKE_MINIMUM_REQUIRED(VERSION 2.8.12) + +ADD_COMPILE_OPTIONS($<$:/MP>) SET(PROJ_NAME game_fallout4) diff --git a/src/games/fallout4/src/CMakeLists.txt b/src/games/fallout4/src/CMakeLists.txt index 73c9c557..4d9e4596 100644 --- a/src/games/fallout4/src/CMakeLists.txt +++ b/src/games/fallout4/src/CMakeLists.txt @@ -73,4 +73,5 @@ QT5_USE_MODULES(${PROJ_NAME} Widgets) INSTALL(TARGETS ${PROJ_NAME} RUNTIME DESTINATION bin/plugins) -INSTALL(FILES ${CMAKE_CURRENT_BINARY_DIR}/${PROJ_NAME}.pdb DESTINATION pdb) +INSTALL(FILES $ + DESTINATION pdb) From c82340cbe1cd3f92a5082dbcb0aff4e2c8c32617 Mon Sep 17 00:00:00 2001 From: Silarn Date: Sat, 7 Apr 2018 17:12:18 -0500 Subject: [PATCH 0484/1544] [game_fallout3] Fix up CMAKE to use /MP and allow building through umbrella --- src/games/fallout3/CMakeLists.txt | 4 +++- src/games/fallout3/src/CMakeLists.txt | 3 ++- 2 files changed, 5 insertions(+), 2 deletions(-) diff --git a/src/games/fallout3/CMakeLists.txt b/src/games/fallout3/CMakeLists.txt index ebc30185..f0a0e661 100644 --- a/src/games/fallout3/CMakeLists.txt +++ b/src/games/fallout3/CMakeLists.txt @@ -1,4 +1,6 @@ -CMAKE_MINIMUM_REQUIRED(VERSION 2.8) +CMAKE_MINIMUM_REQUIRED(VERSION 2.8.12) + +ADD_COMPILE_OPTIONS($<$:/MP>) SET(PROJ_NAME game_fallout3) diff --git a/src/games/fallout3/src/CMakeLists.txt b/src/games/fallout3/src/CMakeLists.txt index 6b2a0f5d..5bc317e7 100644 --- a/src/games/fallout3/src/CMakeLists.txt +++ b/src/games/fallout3/src/CMakeLists.txt @@ -68,4 +68,5 @@ QT5_USE_MODULES(${PROJ_NAME} Widgets) INSTALL(TARGETS ${PROJ_NAME} RUNTIME DESTINATION bin/plugins) -INSTALL(FILES ${CMAKE_CURRENT_BINARY_DIR}/${PROJ_NAME}.pdb DESTINATION pdb) +INSTALL(FILES $ + DESTINATION pdb) From ab4fc7f02756c55b48b004f0e85b43a6e8b343de Mon Sep 17 00:00:00 2001 From: Silarn Date: Sat, 7 Apr 2018 17:12:19 -0500 Subject: [PATCH 0485/1544] Fix up CMAKE to use /MP and allow building through umbrella --- CMakeLists.txt | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/CMakeLists.txt b/CMakeLists.txt index 0939b7ec..55bc6c7c 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -1,4 +1,6 @@ -CMAKE_MINIMUM_REQUIRED(VERSION 2.8) +CMAKE_MINIMUM_REQUIRED(VERSION 2.8.12) + +ADD_COMPILE_OPTIONS($<$:/MP>) SET(PROJ_NAME game_gamebryo) PROJECT(${PROJ_NAME}) From bd7f66ace25eda2588f0acdd8865ecb6ae9725cc Mon Sep 17 00:00:00 2001 From: Silarn Date: Sat, 7 Apr 2018 17:12:19 -0500 Subject: [PATCH 0486/1544] [game_oblivion] Fix up CMAKE to use /MP and allow building through umbrella --- src/games/oblivion/CMakeLists.txt | 4 +++- src/games/oblivion/src/CMakeLists.txt | 3 ++- 2 files changed, 5 insertions(+), 2 deletions(-) diff --git a/src/games/oblivion/CMakeLists.txt b/src/games/oblivion/CMakeLists.txt index 29c3d048..5ffb31f3 100644 --- a/src/games/oblivion/CMakeLists.txt +++ b/src/games/oblivion/CMakeLists.txt @@ -1,4 +1,6 @@ -CMAKE_MINIMUM_REQUIRED(VERSION 2.8) +CMAKE_MINIMUM_REQUIRED(VERSION 2.8.12) + +ADD_COMPILE_OPTIONS($<$:/MP>) SET(PROJ_NAME game_oblivion) diff --git a/src/games/oblivion/src/CMakeLists.txt b/src/games/oblivion/src/CMakeLists.txt index 0bc4f5fe..f725b7da 100644 --- a/src/games/oblivion/src/CMakeLists.txt +++ b/src/games/oblivion/src/CMakeLists.txt @@ -68,4 +68,5 @@ QT5_USE_MODULES(${PROJ_NAME} Widgets) INSTALL(TARGETS ${PROJ_NAME} RUNTIME DESTINATION bin/plugins) -INSTALL(FILES ${CMAKE_CURRENT_BINARY_DIR}/${PROJ_NAME}.pdb DESTINATION pdb) +INSTALL(FILES $ + DESTINATION pdb) From 6b3fb68130e2377f4b02a9ab561d462de6f75805 Mon Sep 17 00:00:00 2001 From: Silarn Date: Sat, 7 Apr 2018 17:12:20 -0500 Subject: [PATCH 0487/1544] [game_skyrimse] Fix up CMAKE to use /MP and allow building through umbrella --- src/games/skyrimse/CMakeLists.txt | 4 +++- src/games/skyrimse/src/CMakeLists.txt | 3 ++- 2 files changed, 5 insertions(+), 2 deletions(-) diff --git a/src/games/skyrimse/CMakeLists.txt b/src/games/skyrimse/CMakeLists.txt index ba8e4e09..bff9599f 100644 --- a/src/games/skyrimse/CMakeLists.txt +++ b/src/games/skyrimse/CMakeLists.txt @@ -1,4 +1,6 @@ -CMAKE_MINIMUM_REQUIRED(VERSION 2.8) +CMAKE_MINIMUM_REQUIRED(VERSION 2.8.12) + +ADD_COMPILE_OPTIONS($<$:/MP>) SET(PROJ_NAME game_skyrimse) diff --git a/src/games/skyrimse/src/CMakeLists.txt b/src/games/skyrimse/src/CMakeLists.txt index 838e9a41..3ff080d2 100644 --- a/src/games/skyrimse/src/CMakeLists.txt +++ b/src/games/skyrimse/src/CMakeLists.txt @@ -69,4 +69,5 @@ QT5_USE_MODULES(${PROJ_NAME} Widgets) INSTALL(TARGETS ${PROJ_NAME} RUNTIME DESTINATION bin/plugins) -INSTALL(FILES ${CMAKE_CURRENT_BINARY_DIR}/${PROJ_NAME}.pdb DESTINATION pdb) +INSTALL(FILES $ + DESTINATION pdb) From 423ec4cd317f11382ca84caca9f9b5caea248dad Mon Sep 17 00:00:00 2001 From: Silarn Date: Sat, 7 Apr 2018 17:12:21 -0500 Subject: [PATCH 0488/1544] [game_skyrimvr] Fix up CMAKE to use /MP and allow building through umbrella --- src/games/skyrimvr/CMakeLists.txt | 4 +++- src/games/skyrimvr/src/CMakeLists.txt | 3 ++- 2 files changed, 5 insertions(+), 2 deletions(-) diff --git a/src/games/skyrimvr/CMakeLists.txt b/src/games/skyrimvr/CMakeLists.txt index 4731285b..da9350f1 100644 --- a/src/games/skyrimvr/CMakeLists.txt +++ b/src/games/skyrimvr/CMakeLists.txt @@ -1,4 +1,6 @@ -CMAKE_MINIMUM_REQUIRED(VERSION 2.8) +CMAKE_MINIMUM_REQUIRED(VERSION 2.8.12) + +ADD_COMPILE_OPTIONS($<$:/MP>) SET(PROJ_NAME game_skyrimvr) diff --git a/src/games/skyrimvr/src/CMakeLists.txt b/src/games/skyrimvr/src/CMakeLists.txt index a0cdda19..2e60f386 100644 --- a/src/games/skyrimvr/src/CMakeLists.txt +++ b/src/games/skyrimvr/src/CMakeLists.txt @@ -69,4 +69,5 @@ QT5_USE_MODULES(${PROJ_NAME} Widgets) INSTALL(TARGETS ${PROJ_NAME} RUNTIME DESTINATION bin/plugins) -INSTALL(FILES ${CMAKE_CURRENT_BINARY_DIR}/${PROJ_NAME}.pdb DESTINATION pdb) +INSTALL(FILES $ + DESTINATION pdb) From 1875f822d20d1ae90a79f344e3f5aab6fbb2a227 Mon Sep 17 00:00:00 2001 From: Silarn Date: Sat, 7 Apr 2018 17:12:23 -0500 Subject: [PATCH 0489/1544] [game_skyrim] Fix up CMAKE to use /MP and allow building through umbrella --- src/games/skyrim/CMakeLists.txt | 4 +++- src/games/skyrim/src/CMakeLists.txt | 3 ++- 2 files changed, 5 insertions(+), 2 deletions(-) diff --git a/src/games/skyrim/CMakeLists.txt b/src/games/skyrim/CMakeLists.txt index 93c5aab6..3917085f 100644 --- a/src/games/skyrim/CMakeLists.txt +++ b/src/games/skyrim/CMakeLists.txt @@ -1,4 +1,6 @@ -CMAKE_MINIMUM_REQUIRED(VERSION 2.8) +CMAKE_MINIMUM_REQUIRED(VERSION 2.8.12) + +ADD_COMPILE_OPTIONS($<$:/MP>) SET(PROJ_NAME game_skyrim) diff --git a/src/games/skyrim/src/CMakeLists.txt b/src/games/skyrim/src/CMakeLists.txt index b9895cea..c8d01218 100644 --- a/src/games/skyrim/src/CMakeLists.txt +++ b/src/games/skyrim/src/CMakeLists.txt @@ -69,4 +69,5 @@ QT5_USE_MODULES(${PROJ_NAME} Widgets) INSTALL(TARGETS ${PROJ_NAME} RUNTIME DESTINATION bin/plugins) -INSTALL(FILES ${CMAKE_CURRENT_BINARY_DIR}/${PROJ_NAME}.pdb DESTINATION pdb) +INSTALL(FILES $ + DESTINATION pdb) From ba837e62c628c949e60162839867ecb150d91d5a Mon Sep 17 00:00:00 2001 From: Silarn Date: Sat, 7 Apr 2018 17:12:25 -0500 Subject: [PATCH 0490/1544] [game_ttw] Fix up CMAKE to use /MP and allow building through umbrella --- src/games/ttw/CMakeLists.txt | 4 +++- src/games/ttw/src/CMakeLists.txt | 3 ++- 2 files changed, 5 insertions(+), 2 deletions(-) diff --git a/src/games/ttw/CMakeLists.txt b/src/games/ttw/CMakeLists.txt index 6250189b..ee9f3502 100644 --- a/src/games/ttw/CMakeLists.txt +++ b/src/games/ttw/CMakeLists.txt @@ -1,4 +1,6 @@ -CMAKE_MINIMUM_REQUIRED(VERSION 2.8) +CMAKE_MINIMUM_REQUIRED(VERSION 2.8.12) + +ADD_COMPILE_OPTIONS($<$:/MP>) SET(PROJ_NAME game_ttw) diff --git a/src/games/ttw/src/CMakeLists.txt b/src/games/ttw/src/CMakeLists.txt index 6b2a0f5d..5bc317e7 100644 --- a/src/games/ttw/src/CMakeLists.txt +++ b/src/games/ttw/src/CMakeLists.txt @@ -68,4 +68,5 @@ QT5_USE_MODULES(${PROJ_NAME} Widgets) INSTALL(TARGETS ${PROJ_NAME} RUNTIME DESTINATION bin/plugins) -INSTALL(FILES ${CMAKE_CURRENT_BINARY_DIR}/${PROJ_NAME}.pdb DESTINATION pdb) +INSTALL(FILES $ + DESTINATION pdb) From 7873c6162d2e3720600814da987f6e2970913abd Mon Sep 17 00:00:00 2001 From: Silarn Date: Tue, 10 Apr 2018 23:28:23 -0500 Subject: [PATCH 0491/1544] [game_fallout4vr] Prep for Qt 5.11 (backward-compatible) --- src/games/fallout4vr/src/CMakeLists.txt | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/src/games/fallout4vr/src/CMakeLists.txt b/src/games/fallout4vr/src/CMakeLists.txt index 0dba3828..73d4accc 100644 --- a/src/games/fallout4vr/src/CMakeLists.txt +++ b/src/games/fallout4vr/src/CMakeLists.txt @@ -1,4 +1,4 @@ -CMAKE_MINIMUM_REQUIRED (VERSION 2.8) +CMAKE_MINIMUM_REQUIRED (VERSION 2.8.11) CMAKE_POLICY(SET CMP0020 NEW) @@ -65,8 +65,6 @@ IF (NOT "${OPTIMIZE_LINK_FLAGS}" STREQUAL "") SET_TARGET_PROPERTIES(${PROJ_NAME} PROPERTIES LINK_FLAGS_RELWITHDEBINFO ${OPTIMIZE_LINK_FLAGS}) ENDIF() -QT5_USE_MODULES(${PROJ_NAME} Widgets) - ############### ## Installation From a46c0623ec29fed97c3beda3a95dd6e72dcd9a42 Mon Sep 17 00:00:00 2001 From: Silarn Date: Tue, 10 Apr 2018 23:28:25 -0500 Subject: [PATCH 0492/1544] [game_falloutnv] Prep for Qt 5.11 (backward-compatible) --- src/games/falloutnv/src/CMakeLists.txt | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/src/games/falloutnv/src/CMakeLists.txt b/src/games/falloutnv/src/CMakeLists.txt index 5bc317e7..664079ec 100644 --- a/src/games/falloutnv/src/CMakeLists.txt +++ b/src/games/falloutnv/src/CMakeLists.txt @@ -1,4 +1,4 @@ -CMAKE_MINIMUM_REQUIRED (VERSION 2.8) +CMAKE_MINIMUM_REQUIRED (VERSION 2.8.11) CMAKE_POLICY(SET CMP0020 NEW) @@ -61,8 +61,6 @@ IF (NOT "${OPTIMIZE_LINK_FLAGS}" STREQUAL "") SET_TARGET_PROPERTIES(${PROJ_NAME} PROPERTIES LINK_FLAGS_RELWITHDEBINFO ${OPTIMIZE_LINK_FLAGS}) ENDIF() -QT5_USE_MODULES(${PROJ_NAME} Widgets) - ############### ## Installation From e750732ec7a2f131d1202b1828cba8aea460e6fe Mon Sep 17 00:00:00 2001 From: Silarn Date: Tue, 10 Apr 2018 23:28:26 -0500 Subject: [PATCH 0493/1544] [game_morrowind] Prep for Qt 5.11 (backward-compatible) --- src/games/morrowind/src/CMakeLists.txt | 2 -- src/games/morrowind/src/game_morrowind_en.ts | 32 ++++++++------------ 2 files changed, 13 insertions(+), 21 deletions(-) diff --git a/src/games/morrowind/src/CMakeLists.txt b/src/games/morrowind/src/CMakeLists.txt index e240005d..39cbca6f 100644 --- a/src/games/morrowind/src/CMakeLists.txt +++ b/src/games/morrowind/src/CMakeLists.txt @@ -66,8 +66,6 @@ IF (NOT "${OPTIMIZE_LINK_FLAGS}" STREQUAL "") SET_TARGET_PROPERTIES(${PROJ_NAME} PROPERTIES LINK_FLAGS_RELWITHDEBINFO ${OPTIMIZE_LINK_FLAGS}) ENDIF() -QT5_USE_MODULES(${PROJ_NAME} Widgets) - ############### ## Installation diff --git a/src/games/morrowind/src/game_morrowind_en.ts b/src/games/morrowind/src/game_morrowind_en.ts index 87d98747..464dfbd6 100644 --- a/src/games/morrowind/src/game_morrowind_en.ts +++ b/src/games/morrowind/src/game_morrowind_en.ts @@ -4,7 +4,7 @@ GameMorrowind - + Adds support for the game Morrowind. Splash by %1 Adds support for the game Morrowind @@ -14,51 +14,45 @@ Splash by %1 MorrowindSaveGameInfoWidget - + Save # - + Character - + Level - + + Health + + + + Location - + Date - - Has Script Extender Data - - - - + Missing ESPs - - + None - - - Missing ESLs - - QObject From 748c5b98ad863f478d472e24cf5d71bb75d478f0 Mon Sep 17 00:00:00 2001 From: Silarn Date: Tue, 10 Apr 2018 23:28:28 -0500 Subject: [PATCH 0494/1544] [game_skyrimvr] Prep for Qt 5.11 (backward-compatible) --- src/games/skyrimvr/src/CMakeLists.txt | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/src/games/skyrimvr/src/CMakeLists.txt b/src/games/skyrimvr/src/CMakeLists.txt index 2e60f386..850748ae 100644 --- a/src/games/skyrimvr/src/CMakeLists.txt +++ b/src/games/skyrimvr/src/CMakeLists.txt @@ -1,4 +1,4 @@ -CMAKE_MINIMUM_REQUIRED (VERSION 2.8) +CMAKE_MINIMUM_REQUIRED (VERSION 2.8.11) CMAKE_POLICY(SET CMP0020 NEW) @@ -62,8 +62,6 @@ IF (NOT "${OPTIMIZE_LINK_FLAGS}" STREQUAL "") SET_TARGET_PROPERTIES(${PROJ_NAME} PROPERTIES LINK_FLAGS_RELWITHDEBINFO ${OPTIMIZE_LINK_FLAGS}) ENDIF() -QT5_USE_MODULES(${PROJ_NAME} Widgets) - ############### ## Installation From f83ab1c498e7e2fc1d871e2bf6f0a79fc589456f Mon Sep 17 00:00:00 2001 From: Silarn Date: Tue, 10 Apr 2018 23:28:29 -0500 Subject: [PATCH 0495/1544] Prep for Qt 5.11 (backward-compatible) --- src/CMakeLists.txt | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/src/CMakeLists.txt b/src/CMakeLists.txt index ce0a5f0c..8f16b606 100644 --- a/src/CMakeLists.txt +++ b/src/CMakeLists.txt @@ -1,4 +1,4 @@ -CMAKE_MINIMUM_REQUIRED (VERSION 2.8) +CMAKE_MINIMUM_REQUIRED (VERSION 2.8.11) CMAKE_POLICY(SET CMP0020 NEW) @@ -57,8 +57,6 @@ IF (NOT "${OPTIMIZE_LINK_FLAGS}" STREQUAL "") SET_TARGET_PROPERTIES(${PROJ_NAME} PROPERTIES LINK_FLAGS_RELWITHDEBINFO ${OPTIMIZE_LINK_FLAGS}) ENDIF() -QT5_USE_MODULES(${PROJ_NAME} Widgets) - ############### ## Installation From 8f0d8a0db2748c3177281848defaaad56da88d7b Mon Sep 17 00:00:00 2001 From: Silarn Date: Tue, 10 Apr 2018 23:28:29 -0500 Subject: [PATCH 0496/1544] [game_fallout76] Prep for Qt 5.11 (backward-compatible) --- src/games/fallout76/src/CMakeLists.txt | 4 +--- src/games/fallout76/src/game_fallout4_en.ts | 4 ++-- 2 files changed, 3 insertions(+), 5 deletions(-) diff --git a/src/games/fallout76/src/CMakeLists.txt b/src/games/fallout76/src/CMakeLists.txt index 4d9e4596..b5b22c9d 100644 --- a/src/games/fallout76/src/CMakeLists.txt +++ b/src/games/fallout76/src/CMakeLists.txt @@ -1,4 +1,4 @@ -CMAKE_MINIMUM_REQUIRED (VERSION 2.8) +CMAKE_MINIMUM_REQUIRED (VERSION 2.8.11) CMAKE_POLICY(SET CMP0020 NEW) @@ -65,8 +65,6 @@ IF (NOT "${OPTIMIZE_LINK_FLAGS}" STREQUAL "") SET_TARGET_PROPERTIES(${PROJ_NAME} PROPERTIES LINK_FLAGS_RELWITHDEBINFO ${OPTIMIZE_LINK_FLAGS}) ENDIF() -QT5_USE_MODULES(${PROJ_NAME} Widgets) - ############### ## Installation diff --git a/src/games/fallout76/src/game_fallout4_en.ts b/src/games/fallout76/src/game_fallout4_en.ts index 7fd0409f..ac13ed09 100644 --- a/src/games/fallout76/src/game_fallout4_en.ts +++ b/src/games/fallout76/src/game_fallout4_en.ts @@ -4,7 +4,7 @@ GameFallout4 - + Adds support for the game Fallout 4. Splash by %1 @@ -13,7 +13,7 @@ Splash by %1 QObject - + Some of your plugins have invalid names! These plugins can not be loaded by the game. Please see mo_interface.log for a list of affected plugins and rename them. From a91267e503cd5f4b6ec7128007b89a1bd0d77d36 Mon Sep 17 00:00:00 2001 From: Silarn Date: Tue, 10 Apr 2018 23:28:29 -0500 Subject: [PATCH 0497/1544] [game_fallout4] Prep for Qt 5.11 (backward-compatible) --- src/games/fallout4/src/CMakeLists.txt | 4 +--- src/games/fallout4/src/game_fallout4_en.ts | 4 ++-- 2 files changed, 3 insertions(+), 5 deletions(-) diff --git a/src/games/fallout4/src/CMakeLists.txt b/src/games/fallout4/src/CMakeLists.txt index 4d9e4596..b5b22c9d 100644 --- a/src/games/fallout4/src/CMakeLists.txt +++ b/src/games/fallout4/src/CMakeLists.txt @@ -1,4 +1,4 @@ -CMAKE_MINIMUM_REQUIRED (VERSION 2.8) +CMAKE_MINIMUM_REQUIRED (VERSION 2.8.11) CMAKE_POLICY(SET CMP0020 NEW) @@ -65,8 +65,6 @@ IF (NOT "${OPTIMIZE_LINK_FLAGS}" STREQUAL "") SET_TARGET_PROPERTIES(${PROJ_NAME} PROPERTIES LINK_FLAGS_RELWITHDEBINFO ${OPTIMIZE_LINK_FLAGS}) ENDIF() -QT5_USE_MODULES(${PROJ_NAME} Widgets) - ############### ## Installation diff --git a/src/games/fallout4/src/game_fallout4_en.ts b/src/games/fallout4/src/game_fallout4_en.ts index 7fd0409f..ac13ed09 100644 --- a/src/games/fallout4/src/game_fallout4_en.ts +++ b/src/games/fallout4/src/game_fallout4_en.ts @@ -4,7 +4,7 @@ GameFallout4 - + Adds support for the game Fallout 4. Splash by %1 @@ -13,7 +13,7 @@ Splash by %1 QObject - + Some of your plugins have invalid names! These plugins can not be loaded by the game. Please see mo_interface.log for a list of affected plugins and rename them. From 23e3a86c293f5c41eaeac7dbe98061eb2c9e79cd Mon Sep 17 00:00:00 2001 From: Silarn Date: Tue, 10 Apr 2018 23:28:29 -0500 Subject: [PATCH 0498/1544] [game_fallout3] Prep for Qt 5.11 (backward-compatible) --- src/games/fallout3/src/CMakeLists.txt | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/src/games/fallout3/src/CMakeLists.txt b/src/games/fallout3/src/CMakeLists.txt index 5bc317e7..664079ec 100644 --- a/src/games/fallout3/src/CMakeLists.txt +++ b/src/games/fallout3/src/CMakeLists.txt @@ -1,4 +1,4 @@ -CMAKE_MINIMUM_REQUIRED (VERSION 2.8) +CMAKE_MINIMUM_REQUIRED (VERSION 2.8.11) CMAKE_POLICY(SET CMP0020 NEW) @@ -61,8 +61,6 @@ IF (NOT "${OPTIMIZE_LINK_FLAGS}" STREQUAL "") SET_TARGET_PROPERTIES(${PROJ_NAME} PROPERTIES LINK_FLAGS_RELWITHDEBINFO ${OPTIMIZE_LINK_FLAGS}) ENDIF() -QT5_USE_MODULES(${PROJ_NAME} Widgets) - ############### ## Installation From 83439089c663c52be88a85b53b3c440d4b183aa1 Mon Sep 17 00:00:00 2001 From: Silarn Date: Tue, 10 Apr 2018 23:28:30 -0500 Subject: [PATCH 0499/1544] [game_oblivion] Prep for Qt 5.11 (backward-compatible) --- src/games/oblivion/src/CMakeLists.txt | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/src/games/oblivion/src/CMakeLists.txt b/src/games/oblivion/src/CMakeLists.txt index f725b7da..56ff8913 100644 --- a/src/games/oblivion/src/CMakeLists.txt +++ b/src/games/oblivion/src/CMakeLists.txt @@ -1,4 +1,4 @@ -CMAKE_MINIMUM_REQUIRED (VERSION 2.8) +CMAKE_MINIMUM_REQUIRED (VERSION 2.8.11) CMAKE_POLICY(SET CMP0020 NEW) @@ -61,8 +61,6 @@ IF (NOT "${OPTIMIZE_LINK_FLAGS}" STREQUAL "") SET_TARGET_PROPERTIES(${PROJ_NAME} PROPERTIES LINK_FLAGS_RELWITHDEBINFO ${OPTIMIZE_LINK_FLAGS}) ENDIF() -QT5_USE_MODULES(${PROJ_NAME} Widgets) - ############### ## Installation From 2933aa4e73e5a5015c42739850f4011b46708ff4 Mon Sep 17 00:00:00 2001 From: Silarn Date: Tue, 10 Apr 2018 23:28:32 -0500 Subject: [PATCH 0500/1544] [game_skyrimse] Prep for Qt 5.11 (backward-compatible) --- src/games/skyrimse/src/CMakeLists.txt | 4 +--- src/games/skyrimse/src/game_skyrimse_en.ts | 2 +- 2 files changed, 2 insertions(+), 4 deletions(-) diff --git a/src/games/skyrimse/src/CMakeLists.txt b/src/games/skyrimse/src/CMakeLists.txt index 3ff080d2..56f3152a 100644 --- a/src/games/skyrimse/src/CMakeLists.txt +++ b/src/games/skyrimse/src/CMakeLists.txt @@ -1,4 +1,4 @@ -CMAKE_MINIMUM_REQUIRED (VERSION 2.8) +CMAKE_MINIMUM_REQUIRED (VERSION 2.8.11) CMAKE_POLICY(SET CMP0020 NEW) @@ -62,8 +62,6 @@ IF (NOT "${OPTIMIZE_LINK_FLAGS}" STREQUAL "") SET_TARGET_PROPERTIES(${PROJ_NAME} PROPERTIES LINK_FLAGS_RELWITHDEBINFO ${OPTIMIZE_LINK_FLAGS}) ENDIF() -QT5_USE_MODULES(${PROJ_NAME} Widgets) - ############### ## Installation diff --git a/src/games/skyrimse/src/game_skyrimse_en.ts b/src/games/skyrimse/src/game_skyrimse_en.ts index f1e83405..aea8c4b8 100644 --- a/src/games/skyrimse/src/game_skyrimse_en.ts +++ b/src/games/skyrimse/src/game_skyrimse_en.ts @@ -22,7 +22,7 @@ - + Some of your plugins have invalid names! These plugins can not be loaded by the game. Please see mo_interface.log for a list of affected plugins and rename them. From a73ebc9d18557e64811baf00aaafa0dcabc46a44 Mon Sep 17 00:00:00 2001 From: Silarn Date: Tue, 10 Apr 2018 23:28:34 -0500 Subject: [PATCH 0501/1544] [game_skyrim] Prep for Qt 5.11 (backward-compatible) --- src/games/skyrim/src/CMakeLists.txt | 2 -- src/games/skyrim/src/game_skyrim_en.ts | 2 +- 2 files changed, 1 insertion(+), 3 deletions(-) diff --git a/src/games/skyrim/src/CMakeLists.txt b/src/games/skyrim/src/CMakeLists.txt index c8d01218..122e1156 100644 --- a/src/games/skyrim/src/CMakeLists.txt +++ b/src/games/skyrim/src/CMakeLists.txt @@ -62,8 +62,6 @@ IF (NOT "${OPTIMIZE_LINK_FLAGS}" STREQUAL "") SET_TARGET_PROPERTIES(${PROJ_NAME} PROPERTIES LINK_FLAGS_RELWITHDEBINFO ${OPTIMIZE_LINK_FLAGS}) ENDIF() -QT5_USE_MODULES(${PROJ_NAME} Widgets) - ############### ## Installation diff --git a/src/games/skyrim/src/game_skyrim_en.ts b/src/games/skyrim/src/game_skyrim_en.ts index d59eced1..bea30796 100644 --- a/src/games/skyrim/src/game_skyrim_en.ts +++ b/src/games/skyrim/src/game_skyrim_en.ts @@ -4,7 +4,7 @@ GameSkyrim - + Adds support for the game Skyrim From 32095a8ff892e667886af197a85f3ec9045a2fc8 Mon Sep 17 00:00:00 2001 From: Silarn Date: Tue, 10 Apr 2018 23:28:35 -0500 Subject: [PATCH 0502/1544] [game_ttw] Prep for Qt 5.11 (backward-compatible) --- src/games/ttw/src/CMakeLists.txt | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/src/games/ttw/src/CMakeLists.txt b/src/games/ttw/src/CMakeLists.txt index 5bc317e7..664079ec 100644 --- a/src/games/ttw/src/CMakeLists.txt +++ b/src/games/ttw/src/CMakeLists.txt @@ -1,4 +1,4 @@ -CMAKE_MINIMUM_REQUIRED (VERSION 2.8) +CMAKE_MINIMUM_REQUIRED (VERSION 2.8.11) CMAKE_POLICY(SET CMP0020 NEW) @@ -61,8 +61,6 @@ IF (NOT "${OPTIMIZE_LINK_FLAGS}" STREQUAL "") SET_TARGET_PROPERTIES(${PROJ_NAME} PROPERTIES LINK_FLAGS_RELWITHDEBINFO ${OPTIMIZE_LINK_FLAGS}) ENDIF() -QT5_USE_MODULES(${PROJ_NAME} Widgets) - ############### ## Installation From 537f971e59afb7094c7c896cebe078348acda8c1 Mon Sep 17 00:00:00 2001 From: Silarn Date: Wed, 11 Apr 2018 23:54:16 -0500 Subject: [PATCH 0503/1544] [game_fallout4vr] Add correct launch argument to LOOT --- src/games/fallout4vr/src/gamefallout4vr.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/games/fallout4vr/src/gamefallout4vr.cpp b/src/games/fallout4vr/src/gamefallout4vr.cpp index c7a93bc1..28bc6c9e 100644 --- a/src/games/fallout4vr/src/gamefallout4vr.cpp +++ b/src/games/fallout4vr/src/gamefallout4vr.cpp @@ -108,7 +108,7 @@ QList GameFallout4VR::executables() const << ExecutableInfo("Fallout 4 VR", findInGameFolder(binaryName())) //<< ExecutableInfo("Fallout Launcher", findInGameFolder(getLauncherName())) // Fallout 4 VR does not have a launcher << ExecutableInfo("Creation Kit", findInGameFolder("CreationKit.exe")) - << ExecutableInfo("LOOT", getLootPath()).withArgument("--game=\"Fallout4\"") + << ExecutableInfo("LOOT", getLootPath()).withArgument("--game=\"Fallout4VR\"") ; } From d2f1b5bd977f36b36edaae09b58d9b311fa0fb69 Mon Sep 17 00:00:00 2001 From: Silarn Date: Thu, 12 Apr 2018 01:05:50 -0500 Subject: [PATCH 0504/1544] Parse filetime and move inactive plugins to the bottom of the load order --- src/gamebryogameplugins.cpp | 53 ++++++++++++++++++++----------------- 1 file changed, 29 insertions(+), 24 deletions(-) diff --git a/src/gamebryogameplugins.cpp b/src/gamebryogameplugins.cpp index 38c75879..043848fb 100644 --- a/src/gamebryogameplugins.cpp +++ b/src/gamebryogameplugins.cpp @@ -171,26 +171,21 @@ bool GamebryoGamePlugins::readPluginList(MOBase::IPluginList *pluginList, plugins.removeAll(plugin); } - if (useLoadOrder) { - // Always use filetime loadorder to get the actual load order - std::sort(plugins.begin(), plugins.end(), [&](const QString &lhs, const QString &rhs) { - MOBase::IModInterface *lhm = organizer()->getMod(pluginList->origin(lhs)); - MOBase::IModInterface *rhm = organizer()->getMod(pluginList->origin(rhs)); - QDir lhd = organizer()->managedGame()->dataDirectory(); - QDir rhd = organizer()->managedGame()->dataDirectory(); - if (lhm != nullptr) - lhd = lhm->absolutePath(); - if (rhm != nullptr) - rhd = rhm->absolutePath(); - QString lhp = lhd.absoluteFilePath(lhs); - QString rhp = rhd.absoluteFilePath(rhs); - return QFileInfo(lhp).lastModified() < - QFileInfo(rhp).lastModified(); - }); - - // Add the primary plugins to the beginning of the load order - pluginList->setLoadOrder(primary + plugins); - } + // Always use filetime loadorder to get the actual load order + std::sort(plugins.begin(), plugins.end(), [&](const QString &lhs, const QString &rhs) { + MOBase::IModInterface *lhm = organizer()->getMod(pluginList->origin(lhs)); + MOBase::IModInterface *rhm = organizer()->getMod(pluginList->origin(rhs)); + QDir lhd = organizer()->managedGame()->dataDirectory(); + QDir rhd = organizer()->managedGame()->dataDirectory(); + if (lhm != nullptr) + lhd = lhm->absolutePath(); + if (rhm != nullptr) + rhd = rhm->absolutePath(); + QString lhp = lhd.absoluteFilePath(lhs); + QString rhp = rhd.absoluteFilePath(rhs); + return QFileInfo(lhp).lastModified() < + QFileInfo(rhp).lastModified(); + }); // Determine plugin active state by the plugins.txt file. bool pluginsTxtExists = true; @@ -210,6 +205,8 @@ bool GamebryoGamePlugins::readPluginList(MOBase::IPluginList *pluginList, pluginsTxtExists = false; } + QStringList activePlugins; + QStringList inactivePlugins; if (pluginsTxtExists) { while (!file.atEnd()) { QByteArray line = file.readLine(); @@ -219,14 +216,19 @@ bool GamebryoGamePlugins::readPluginList(MOBase::IPluginList *pluginList, } if (pluginName.size() > 0) { pluginList->setState(pluginName, IPluginList::STATE_ACTIVE); - plugins.removeAll(pluginName); + activePlugins.push_back(pluginName); } } - file.close(); - // we removed each plugin found in the file, so what's left are inactive mods - for (const QString &pluginName : plugins) { + for (const QString &pluginName : activePlugins) { + if (!activePlugins.contains(pluginName)) { + inactivePlugins.push_back(pluginName); + plugins.removeAll(pluginName); + } + } + + for (const QString &pluginName : inactivePlugins) { pluginList->setState(pluginName, IPluginList::STATE_INACTIVE); } } else { @@ -235,5 +237,8 @@ bool GamebryoGamePlugins::readPluginList(MOBase::IPluginList *pluginList, } } + if (useLoadOrder) + pluginList->setLoadOrder(primary + plugins + inactivePlugins); + return true; } From 77b326bd88da2d1f96a2cb0d1610e945a1eed5a9 Mon Sep 17 00:00:00 2001 From: Silarn Date: Thu, 12 Apr 2018 01:32:08 -0500 Subject: [PATCH 0505/1544] [game_morrowind] Don't override filetime order and move inactive plugins to the bottom #2 --- .../morrowind/src/morrowindgameplugins.cpp | 70 ++++++++++--------- .../morrowind/src/morrowindgameplugins.h | 5 +- 2 files changed, 40 insertions(+), 35 deletions(-) diff --git a/src/games/morrowind/src/morrowindgameplugins.cpp b/src/games/morrowind/src/morrowindgameplugins.cpp index 425925ae..452eaeb9 100644 --- a/src/games/morrowind/src/morrowindgameplugins.cpp +++ b/src/games/morrowind/src/morrowindgameplugins.cpp @@ -122,49 +122,55 @@ bool MorrowindGamePlugins::readPluginList(MOBase::IPluginList *pluginList, plugins.removeAll(plugin); } - if (useLoadOrder) { - // Always use filetime loadorder to get the actual load order - std::sort(plugins.begin(), plugins.end(), [&](const QString &lhs, const QString &rhs) { - MOBase::IModInterface *lhm = organizer()->getMod(pluginList->origin(lhs)); - MOBase::IModInterface *rhm = organizer()->getMod(pluginList->origin(rhs)); - QDir lhd = organizer()->managedGame()->dataDirectory(); - QDir rhd = organizer()->managedGame()->dataDirectory(); - if (lhm != nullptr) - lhd = lhm->absolutePath(); - if (rhm != nullptr) - rhd = rhm->absolutePath(); - QString lhp = lhd.absoluteFilePath(lhs); - QString rhp = rhd.absoluteFilePath(rhs); - return QFileInfo(lhp).lastModified() < - QFileInfo(rhp).lastModified(); - }); - - // Add the primary plugins to the beginning of the load order - pluginList->setLoadOrder(primary + plugins); - } + // Always use filetime loadorder to get the actual load order + std::sort(plugins.begin(), plugins.end(), [&](const QString &lhs, const QString &rhs) { + MOBase::IModInterface *lhm = organizer()->getMod(pluginList->origin(lhs)); + MOBase::IModInterface *rhm = organizer()->getMod(pluginList->origin(rhs)); + QDir lhd = organizer()->managedGame()->dataDirectory(); + QDir rhd = organizer()->managedGame()->dataDirectory(); + if (lhm != nullptr) + lhd = lhm->absolutePath(); + if (rhm != nullptr) + rhd = rhm->absolutePath(); + QString lhp = lhd.absoluteFilePath(lhs); + QString rhp = rhd.absoluteFilePath(rhs); + return QFileInfo(lhp).lastModified() < + QFileInfo(rhp).lastModified(); + }); QString filePath = organizer()->profile()->absolutePath() + "/Morrowind.ini"; wchar_t buffer[256]; QStringList result; std::wstring iniFileW = QDir::toNativeSeparators(filePath).toStdWString(); - + errno = 0; - QStringList loadOrder; + QStringList activePlugins; + QStringList inactivePlugins; QString key = "GameFile"; - int i=0; - while (::GetPrivateProfileStringW(L"Game Files", (key+QString::number(i)).toStdWString().c_str(), - L"", buffer, 256, iniFileW.c_str()) != 0) { - QString pluginName; - pluginName=QString::fromStdWString(buffer).trimmed(); - pluginList->setState(pluginName, IPluginList::STATE_ACTIVE); - plugins.removeAll(pluginName); - i++; + int i = 0; + while (::GetPrivateProfileStringW(L"Game Files", (key + QString::number(i)).toStdWString().c_str(), + L"", buffer, 256, iniFileW.c_str()) != 0) { + QString pluginName; + pluginName = QString::fromStdWString(buffer).trimmed(); + pluginList->setState(pluginName, IPluginList::STATE_ACTIVE); + activePlugins.push_back(pluginName); + i++; } - for (const QString &pluginName : plugins) { + // we removed each plugin found in the file, so what's left are inactive mods + for (const QString &pluginName : plugins) + if (!activePlugins.contains(pluginName)) + inactivePlugins.push_back(pluginName); + + for (const QString &pluginName : inactivePlugins) + plugins.removeAll(pluginName); + + for (const QString &pluginName : inactivePlugins) pluginList->setState(pluginName, IPluginList::STATE_INACTIVE); - } + + if (useLoadOrder) + pluginList->setLoadOrder(primary + plugins + inactivePlugins); return true; } \ No newline at end of file diff --git a/src/games/morrowind/src/morrowindgameplugins.h b/src/games/morrowind/src/morrowindgameplugins.h index fb03be14..7c60628b 100644 --- a/src/games/morrowind/src/morrowindgameplugins.h +++ b/src/games/morrowind/src/morrowindgameplugins.h @@ -13,9 +13,8 @@ public: virtual void readPluginLists(MOBase::IPluginList *pluginList) override; protected: - virtual void writePluginList(const MOBase::IPluginList *pluginList, - const QString &filePath); - virtual bool readPluginList(MOBase::IPluginList *pluginList, bool useLoadOrder); + virtual void writePluginList(const MOBase::IPluginList *pluginList, const QString &filePath) override; + virtual bool readPluginList(MOBase::IPluginList *pluginList, bool useLoadOrder) override; private: virtual void writeList(const MOBase::IPluginList *pluginList, const QString &filePath, From b728886c2f5a6cb82b3ab0f39ea81d7790787a5d Mon Sep 17 00:00:00 2001 From: Silarn Date: Thu, 12 Apr 2018 01:32:08 -0500 Subject: [PATCH 0506/1544] Don't override filetime order and move inactive plugins to the bottom #2 --- src/gamebryogameplugins.cpp | 16 +++++++--------- 1 file changed, 7 insertions(+), 9 deletions(-) diff --git a/src/gamebryogameplugins.cpp b/src/gamebryogameplugins.cpp index 043848fb..788fcaa4 100644 --- a/src/gamebryogameplugins.cpp +++ b/src/gamebryogameplugins.cpp @@ -220,17 +220,15 @@ bool GamebryoGamePlugins::readPluginList(MOBase::IPluginList *pluginList, } } - // we removed each plugin found in the file, so what's left are inactive mods - for (const QString &pluginName : activePlugins) { - if (!activePlugins.contains(pluginName)) { + for (const QString &pluginName : plugins) + if (!activePlugins.contains(pluginName)) inactivePlugins.push_back(pluginName); - plugins.removeAll(pluginName); - } - } - for (const QString &pluginName : inactivePlugins) { - pluginList->setState(pluginName, IPluginList::STATE_INACTIVE); - } + for (const QString &pluginName : inactivePlugins) + plugins.removeAll(pluginName); + + for (const QString &pluginName : inactivePlugins) + pluginList->setState(pluginName, IPluginList::STATE_INACTIVE); } else { for (const QString &pluginName : plugins) { pluginList->setState(pluginName, IPluginList::STATE_INACTIVE); From 1a871f1db9f761b2753822b5176cabb6a562c75b Mon Sep 17 00:00:00 2001 From: Jeremy Rimpo Date: Fri, 13 Apr 2018 00:38:19 -0500 Subject: [PATCH 0507/1544] [game_fallout4vr] Remove extraneous search code --- src/games/fallout4vr/CMakeLists.txt | 3 --- 1 file changed, 3 deletions(-) diff --git a/src/games/fallout4vr/CMakeLists.txt b/src/games/fallout4vr/CMakeLists.txt index f31144fc..8288c438 100644 --- a/src/games/fallout4vr/CMakeLists.txt +++ b/src/games/fallout4vr/CMakeLists.txt @@ -12,7 +12,4 @@ SET(DEPENDENCIES_DIR CACHE PATH "") LIST(APPEND CMAKE_PREFIX_PATH ${QT_ROOT}/lib/cmake) LIST(APPEND CMAKE_PREFIX_PATH ${LZ4_ROOT}/dll) -FILE(GLOB_RECURSE BOOST_ROOT ${DEPENDENCIES_DIR}/boost*/project-config.jam) -GET_FILENAME_COMPONENT(BOOST_ROOT ${BOOST_ROOT} DIRECTORY) - ADD_SUBDIRECTORY(src) From f30766eee281ea03f269e95f6c89b402d2c228cb Mon Sep 17 00:00:00 2001 From: Jeremy Rimpo Date: Fri, 13 Apr 2018 00:38:20 -0500 Subject: [PATCH 0508/1544] [game_morrowind] Remove extraneous search code --- src/games/morrowind/CMakeLists.txt | 3 --- 1 file changed, 3 deletions(-) diff --git a/src/games/morrowind/CMakeLists.txt b/src/games/morrowind/CMakeLists.txt index 30035581..5e4f1635 100644 --- a/src/games/morrowind/CMakeLists.txt +++ b/src/games/morrowind/CMakeLists.txt @@ -12,7 +12,4 @@ SET(DEPENDENCIES_DIR CACHE PATH "") LIST(APPEND CMAKE_PREFIX_PATH ${QT_ROOT}/lib/cmake) LIST(APPEND CMAKE_PREFIX_PATH ${LZ4_ROOT}/dll) -FILE(GLOB_RECURSE BOOST_ROOT ${DEPENDENCIES_DIR}/boost*/project-config.jam) -GET_FILENAME_COMPONENT(BOOST_ROOT ${BOOST_ROOT} DIRECTORY) - ADD_SUBDIRECTORY(src) From 20098bc55d3c1e524c7c324bf7ab4e0f44d2789f Mon Sep 17 00:00:00 2001 From: Jeremy Rimpo Date: Fri, 13 Apr 2018 00:38:20 -0500 Subject: [PATCH 0509/1544] [game_falloutnv] Remove extraneous search code --- src/games/falloutnv/CMakeLists.txt | 3 --- 1 file changed, 3 deletions(-) diff --git a/src/games/falloutnv/CMakeLists.txt b/src/games/falloutnv/CMakeLists.txt index 7274faf8..414d3cc7 100644 --- a/src/games/falloutnv/CMakeLists.txt +++ b/src/games/falloutnv/CMakeLists.txt @@ -13,7 +13,4 @@ LIST(APPEND CMAKE_PREFIX_PATH ${QT_ROOT}/lib/cmake) LIST(APPEND CMAKE_PREFIX_PATH ${LZ4_ROOT}/dll) -FILE(GLOB_RECURSE BOOST_ROOT ${DEPENDENCIES_DIR}/boost*/project-config.jam) -GET_FILENAME_COMPONENT(BOOST_ROOT ${BOOST_ROOT} DIRECTORY) - ADD_SUBDIRECTORY(src) From 7fdb200a2dd8c319f3983a6a4388b980c290a6ac Mon Sep 17 00:00:00 2001 From: Jeremy Rimpo Date: Fri, 13 Apr 2018 00:38:21 -0500 Subject: [PATCH 0510/1544] [game_skyrimvr] Remove extraneous search code --- src/games/skyrimvr/CMakeLists.txt | 3 --- 1 file changed, 3 deletions(-) diff --git a/src/games/skyrimvr/CMakeLists.txt b/src/games/skyrimvr/CMakeLists.txt index da9350f1..7a72d215 100644 --- a/src/games/skyrimvr/CMakeLists.txt +++ b/src/games/skyrimvr/CMakeLists.txt @@ -12,7 +12,4 @@ SET(DEPENDENCIES_DIR CACHE PATH "") LIST(APPEND CMAKE_PREFIX_PATH ${QT_ROOT}/lib/cmake) LIST(APPEND CMAKE_PREFIX_PATH ${LZ4_ROOT}/dll) -FILE(GLOB_RECURSE BOOST_ROOT ${DEPENDENCIES_DIR}/boost*/project-config.jam) -GET_FILENAME_COMPONENT(BOOST_ROOT ${BOOST_ROOT} DIRECTORY) - ADD_SUBDIRECTORY(src) From aca955f5ef8d3db13d64190cdecea15ce52c2833 Mon Sep 17 00:00:00 2001 From: Jeremy Rimpo Date: Fri, 13 Apr 2018 00:38:22 -0500 Subject: [PATCH 0511/1544] Remove extraneous search code --- CMakeLists.txt | 3 --- 1 file changed, 3 deletions(-) diff --git a/CMakeLists.txt b/CMakeLists.txt index 55bc6c7c..cbfa46ca 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -13,7 +13,4 @@ LIST(APPEND CMAKE_PREFIX_PATH ${QT_ROOT}/lib/cmake) LIST(APPEND CMAKE_PREFIX_PATH ${LZ4_ROOT}/dll) message(${LZ4_ROOT}) -FILE(GLOB_RECURSE BOOST_ROOT ${DEPENDENCIES_DIR}/boost*/project-config.jam) -GET_FILENAME_COMPONENT(BOOST_ROOT ${BOOST_ROOT} DIRECTORY) - ADD_SUBDIRECTORY(src) From 88a57a703d99596ee1fd157e91765039302ef2d2 Mon Sep 17 00:00:00 2001 From: Jeremy Rimpo Date: Fri, 13 Apr 2018 00:38:22 -0500 Subject: [PATCH 0512/1544] [game_skyrimse] Remove extraneous search code --- src/games/skyrimse/CMakeLists.txt | 3 --- 1 file changed, 3 deletions(-) diff --git a/src/games/skyrimse/CMakeLists.txt b/src/games/skyrimse/CMakeLists.txt index bff9599f..41613096 100644 --- a/src/games/skyrimse/CMakeLists.txt +++ b/src/games/skyrimse/CMakeLists.txt @@ -12,7 +12,4 @@ SET(DEPENDENCIES_DIR CACHE PATH "") LIST(APPEND CMAKE_PREFIX_PATH ${QT_ROOT}/lib/cmake) LIST(APPEND CMAKE_PREFIX_PATH ${LZ4_ROOT}/dll) -FILE(GLOB_RECURSE BOOST_ROOT ${DEPENDENCIES_DIR}/boost*/project-config.jam) -GET_FILENAME_COMPONENT(BOOST_ROOT ${BOOST_ROOT} DIRECTORY) - ADD_SUBDIRECTORY(src) From 593637af67e0c457bcdd4eec2403a4a2285e2147 Mon Sep 17 00:00:00 2001 From: Jeremy Rimpo Date: Fri, 13 Apr 2018 00:38:22 -0500 Subject: [PATCH 0513/1544] [game_fallout76] Remove extraneous search code --- src/games/fallout76/CMakeLists.txt | 3 --- 1 file changed, 3 deletions(-) diff --git a/src/games/fallout76/CMakeLists.txt b/src/games/fallout76/CMakeLists.txt index 47e51ba6..40f51534 100644 --- a/src/games/fallout76/CMakeLists.txt +++ b/src/games/fallout76/CMakeLists.txt @@ -12,7 +12,4 @@ SET(DEPENDENCIES_DIR CACHE PATH "") LIST(APPEND CMAKE_PREFIX_PATH ${QT_ROOT}/lib/cmake) LIST(APPEND CMAKE_PREFIX_PATH ${LZ4_ROOT}/dll) -FILE(GLOB_RECURSE BOOST_ROOT ${DEPENDENCIES_DIR}/boost*/project-config.jam) -GET_FILENAME_COMPONENT(BOOST_ROOT ${BOOST_ROOT} DIRECTORY) - ADD_SUBDIRECTORY(src) From 3b7e8899daf750eff5e9d9c162e6e3ef41ab5133 Mon Sep 17 00:00:00 2001 From: Jeremy Rimpo Date: Fri, 13 Apr 2018 00:38:22 -0500 Subject: [PATCH 0514/1544] [game_fallout4] Remove extraneous search code --- src/games/fallout4/CMakeLists.txt | 3 --- 1 file changed, 3 deletions(-) diff --git a/src/games/fallout4/CMakeLists.txt b/src/games/fallout4/CMakeLists.txt index 47e51ba6..40f51534 100644 --- a/src/games/fallout4/CMakeLists.txt +++ b/src/games/fallout4/CMakeLists.txt @@ -12,7 +12,4 @@ SET(DEPENDENCIES_DIR CACHE PATH "") LIST(APPEND CMAKE_PREFIX_PATH ${QT_ROOT}/lib/cmake) LIST(APPEND CMAKE_PREFIX_PATH ${LZ4_ROOT}/dll) -FILE(GLOB_RECURSE BOOST_ROOT ${DEPENDENCIES_DIR}/boost*/project-config.jam) -GET_FILENAME_COMPONENT(BOOST_ROOT ${BOOST_ROOT} DIRECTORY) - ADD_SUBDIRECTORY(src) From 579c4a1459d11f1fe14bacf21a9dae8fdedda461 Mon Sep 17 00:00:00 2001 From: Jeremy Rimpo Date: Fri, 13 Apr 2018 00:38:22 -0500 Subject: [PATCH 0515/1544] [game_fallout3] Remove extraneous search code --- src/games/fallout3/CMakeLists.txt | 3 --- 1 file changed, 3 deletions(-) diff --git a/src/games/fallout3/CMakeLists.txt b/src/games/fallout3/CMakeLists.txt index f0a0e661..bc4627d8 100644 --- a/src/games/fallout3/CMakeLists.txt +++ b/src/games/fallout3/CMakeLists.txt @@ -12,7 +12,4 @@ SET(DEPENDENCIES_DIR CACHE PATH "") LIST(APPEND CMAKE_PREFIX_PATH ${QT_ROOT}/lib/cmake) LIST(APPEND CMAKE_PREFIX_PATH ${LZ4_ROOT}/dll) -FILE(GLOB_RECURSE BOOST_ROOT ${DEPENDENCIES_DIR}/boost*/project-config.jam) -GET_FILENAME_COMPONENT(BOOST_ROOT ${BOOST_ROOT} DIRECTORY) - ADD_SUBDIRECTORY(src) From 5e6779a546dd10bd323922646f1c790953786036 Mon Sep 17 00:00:00 2001 From: Jeremy Rimpo Date: Fri, 13 Apr 2018 00:38:22 -0500 Subject: [PATCH 0516/1544] [game_oblivion] Remove extraneous search code --- src/games/oblivion/CMakeLists.txt | 3 --- 1 file changed, 3 deletions(-) diff --git a/src/games/oblivion/CMakeLists.txt b/src/games/oblivion/CMakeLists.txt index 5ffb31f3..f0e6b4bb 100644 --- a/src/games/oblivion/CMakeLists.txt +++ b/src/games/oblivion/CMakeLists.txt @@ -12,7 +12,4 @@ SET(DEPENDENCIES_DIR CACHE PATH "") LIST(APPEND CMAKE_PREFIX_PATH ${QT_ROOT}/lib/cmake) LIST(APPEND CMAKE_PREFIX_PATH ${LZ4_ROOT}/dll) -FILE(GLOB_RECURSE BOOST_ROOT ${DEPENDENCIES_DIR}/boost*/project-config.jam) -GET_FILENAME_COMPONENT(BOOST_ROOT ${BOOST_ROOT} DIRECTORY) - ADD_SUBDIRECTORY(src) From bc85eea80344491874ce877721caf9acf61e9c34 Mon Sep 17 00:00:00 2001 From: Jeremy Rimpo Date: Fri, 13 Apr 2018 00:38:23 -0500 Subject: [PATCH 0517/1544] [game_skyrim] Remove extraneous search code --- src/games/skyrim/CMakeLists.txt | 3 --- 1 file changed, 3 deletions(-) diff --git a/src/games/skyrim/CMakeLists.txt b/src/games/skyrim/CMakeLists.txt index 3917085f..41920872 100644 --- a/src/games/skyrim/CMakeLists.txt +++ b/src/games/skyrim/CMakeLists.txt @@ -12,7 +12,4 @@ SET(DEPENDENCIES_DIR CACHE PATH "") LIST(APPEND CMAKE_PREFIX_PATH ${QT_ROOT}/lib/cmake) LIST(APPEND CMAKE_PREFIX_PATH ${LZ4_ROOT}/dll) -FILE(GLOB_RECURSE BOOST_ROOT ${DEPENDENCIES_DIR}/boost*/project-config.jam) -GET_FILENAME_COMPONENT(BOOST_ROOT ${BOOST_ROOT} DIRECTORY) - ADD_SUBDIRECTORY(src) From 0030a7e823f07fde19ddbe9c63391902f5f8465b Mon Sep 17 00:00:00 2001 From: Jeremy Rimpo Date: Fri, 13 Apr 2018 00:38:24 -0500 Subject: [PATCH 0518/1544] [game_ttw] Remove extraneous search code --- src/games/ttw/CMakeLists.txt | 3 --- 1 file changed, 3 deletions(-) diff --git a/src/games/ttw/CMakeLists.txt b/src/games/ttw/CMakeLists.txt index ee9f3502..eefc4cc3 100644 --- a/src/games/ttw/CMakeLists.txt +++ b/src/games/ttw/CMakeLists.txt @@ -13,7 +13,4 @@ LIST(APPEND CMAKE_PREFIX_PATH ${QT_ROOT}/lib/cmake) LIST(APPEND CMAKE_PREFIX_PATH ${DEPENDENCIES_DIR}/lz4/dll) -FILE(GLOB_RECURSE BOOST_ROOT ${DEPENDENCIES_DIR}/boost*/project-config.jam) -GET_FILENAME_COMPONENT(BOOST_ROOT ${BOOST_ROOT} DIRECTORY) - ADD_SUBDIRECTORY(src) From 93a9378b60e8c871bbfcffdb449b2df023acac31 Mon Sep 17 00:00:00 2001 From: AnyOldName3 Date: Mon, 16 Apr 2018 00:37:30 +0100 Subject: [PATCH 0519/1544] [game_morrowind] Spell my name correctly. --- src/games/morrowind/src/gamemorrowind.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/games/morrowind/src/gamemorrowind.cpp b/src/games/morrowind/src/gamemorrowind.cpp index c183d1c9..247cd5f6 100644 --- a/src/games/morrowind/src/gamemorrowind.cpp +++ b/src/games/morrowind/src/gamemorrowind.cpp @@ -97,7 +97,7 @@ QString GameMorrowind::author() const QString GameMorrowind::description() const { return tr("Adds support for the game Morrowind.\n" - "Splash by %1").arg("AnyOldName"); + "Splash by %1").arg("AnyOldName3"); } MOBase::VersionInfo GameMorrowind::version() const From 39e0631a46d2bd2cf902f0ac6e026ecf1486009e Mon Sep 17 00:00:00 2001 From: Silarn Date: Mon, 16 Apr 2018 12:51:05 -0500 Subject: [PATCH 0520/1544] [game_skyrimvr] Adding correct inis and adding multi-game support --- src/games/skyrimvr/src/gameskyrimvr.cpp | 20 +++++++++++++++---- src/games/skyrimvr/src/gameskyrimvr.h | 1 + .../skyrimvr/src/skyrimvrdataarchives.cpp | 4 ++-- 3 files changed, 19 insertions(+), 6 deletions(-) diff --git a/src/games/skyrimvr/src/gameskyrimvr.cpp b/src/games/skyrimvr/src/gameskyrimvr.cpp index 86c17699..327dcc19 100644 --- a/src/games/skyrimvr/src/gameskyrimvr.cpp +++ b/src/games/skyrimvr/src/gameskyrimvr.cpp @@ -169,7 +169,7 @@ bool GameSkyrimVR::init(IOrganizer *moInfo) registerFeature(new SkyrimVRScriptExtender(this)); registerFeature(new SkyrimVRDataArchives(myGamesPath())); - registerFeature(new GamebryoLocalSavegames(myGamesPath(), "SkyrimPrefs.ini")); + registerFeature(new GamebryoLocalSavegames(myGamesPath(), "SkyrimVR.ini")); registerFeature(new SkyrimVRSaveGameInfo(this)); registerFeature(new SkyrimVRGamePlugins(moInfo)); registerFeature(new SkyrimVRUnmangedMods(this)); @@ -237,7 +237,14 @@ void GameSkyrimVR::initializeProfile(const QDir &path, ProfileSettings settings) } if (settings.testFlag(IPluginGame::CONFIGURATION)) { - copyToProfile(myGamesPath(), path, "skyrimprefs.ini"); + if (settings.testFlag(IPluginGame::PREFER_DEFAULTS) + || !QFileInfo(myGamesPath() + "/skyrimvr.ini").exists()) { + copyToProfile(gameDirectory().absolutePath(), path, "skyrim.ini", "skyrimvr.ini"); + } else { + copyToProfile(myGamesPath(), path, "skyrimvr.ini"); + } + + copyToProfile(myGamesPath(), path, "skyrimprefs.ini"); } } @@ -271,7 +278,12 @@ QStringList GameSkyrimVR::gameVariants() const QString GameSkyrimVR::gameShortName() const { - return "SkyrimSE"; + return "SkyrimVR"; +} + +QStringList GameSkyrimVR::validShortNames() const +{ + return { "Skyrim", "SkyrimSE" }; } QString GameSkyrimVR::gameNexusName() const @@ -282,7 +294,7 @@ QString GameSkyrimVR::gameNexusName() const QStringList GameSkyrimVR::iniFiles() const { - return{ "skyrimprefs.ini" }; + return{ "skyrimvr.ini", "skyrimprefs.ini" }; } QStringList GameSkyrimVR::DLCPlugins() const diff --git a/src/games/skyrimvr/src/gameskyrimvr.h b/src/games/skyrimvr/src/gameskyrimvr.h index 05047707..44809fcc 100644 --- a/src/games/skyrimvr/src/gameskyrimvr.h +++ b/src/games/skyrimvr/src/gameskyrimvr.h @@ -27,6 +27,7 @@ public: // IPluginGame interface virtual QStringList primaryPlugins() const override; virtual QStringList gameVariants() 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; diff --git a/src/games/skyrimvr/src/skyrimvrdataarchives.cpp b/src/games/skyrimvr/src/skyrimvrdataarchives.cpp index e286faf5..423f6242 100644 --- a/src/games/skyrimvr/src/skyrimvrdataarchives.cpp +++ b/src/games/skyrimvr/src/skyrimvrdataarchives.cpp @@ -35,7 +35,7 @@ QStringList SkyrimVRDataArchives::archives(const MOBase::IProfile *profile) cons { QStringList result; - QString iniFile = profile->localSettingsEnabled() ? QDir(profile->absolutePath()).absoluteFilePath("skyrim.ini") : m_LocalGameDir.absoluteFilePath("skyrim.ini"); + QString iniFile = profile->localSettingsEnabled() ? QDir(profile->absolutePath()).absoluteFilePath("skyrimvr.ini") : m_LocalGameDir.absoluteFilePath("skyrimvr.ini"); result.append(getArchivesFromKey(iniFile, "SResourceArchiveList")); result.append(getArchivesFromKey(iniFile, "SResourceArchiveList2")); @@ -46,7 +46,7 @@ void SkyrimVRDataArchives::writeArchiveList(MOBase::IProfile *profile, const QSt { QString list = before.join(", "); - QString iniFile = profile->localSettingsEnabled() ? QDir(profile->absolutePath()).absoluteFilePath("skyrim.ini") : m_LocalGameDir.absoluteFilePath("skyrim.ini"); + QString iniFile = profile->localSettingsEnabled() ? QDir(profile->absolutePath()).absoluteFilePath("skyrimvr.ini") : m_LocalGameDir.absoluteFilePath("skyrimvr.ini"); if (list.length() > 255) { int splitIdx = list.lastIndexOf(",", 256); setArchivesToKey(iniFile, "SResourceArchiveList", list.mid(0, splitIdx)); From f348a9b2fbeb6b49e747ad03ea70f37f907d44a1 Mon Sep 17 00:00:00 2001 From: Silarn Date: Mon, 16 Apr 2018 12:51:38 -0500 Subject: [PATCH 0521/1544] [game_fallout4vr] Support for multi-game downloads --- src/games/fallout4vr/src/gamefallout4vr.cpp | 5 +++++ src/games/fallout4vr/src/gamefallout4vr.h | 1 + 2 files changed, 6 insertions(+) diff --git a/src/games/fallout4vr/src/gamefallout4vr.cpp b/src/games/fallout4vr/src/gamefallout4vr.cpp index 28bc6c9e..ee2f2350 100644 --- a/src/games/fallout4vr/src/gamefallout4vr.cpp +++ b/src/games/fallout4vr/src/gamefallout4vr.cpp @@ -205,6 +205,11 @@ QString GameFallout4VR::gameShortName() const return "Fallout4VR"; } +QStringList GameFallout4VR::validShortNames() const +{ + return { "Fallout4" }; +} + QString GameFallout4VR::gameNexusName() const { return "Fallout4"; diff --git a/src/games/fallout4vr/src/gamefallout4vr.h b/src/games/fallout4vr/src/gamefallout4vr.h index 12a6056d..1c8dd3ab 100644 --- a/src/games/fallout4vr/src/gamefallout4vr.h +++ b/src/games/fallout4vr/src/gamefallout4vr.h @@ -30,6 +30,7 @@ public: // IPluginGame interface virtual QStringList primaryPlugins() const override; virtual QStringList gameVariants() 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; From b3cae18d1db034e8904311c0bdee172f358cff55 Mon Sep 17 00:00:00 2001 From: Silarn Date: Mon, 16 Apr 2018 12:51:39 -0500 Subject: [PATCH 0522/1544] Support for multi-game downloads --- src/gamegamebryo.cpp | 5 +++++ src/gamegamebryo.h | 1 + 2 files changed, 6 insertions(+) diff --git a/src/gamegamebryo.cpp b/src/gamegamebryo.cpp index c2683f8f..31fb67f5 100644 --- a/src/gamegamebryo.cpp +++ b/src/gamegamebryo.cpp @@ -173,6 +173,11 @@ QString GameGamebryo::binaryName() const return gameShortName() + ".exe"; } +QStringList GameGamebryo::validShortNames() const +{ + return {}; +} + QStringList GameGamebryo::CCPlugins() const { return {}; diff --git a/src/gamegamebryo.h b/src/gamegamebryo.h index 282b7b5e..be02d138 100644 --- a/src/gamegamebryo.h +++ b/src/gamegamebryo.h @@ -57,6 +57,7 @@ public: // IPluginGame interface virtual void setGameVariant(const QString &variant) override; virtual QString binaryName() const override; //gameShortName + virtual QStringList validShortNames() const override; //iniFiles //DLCPlugins virtual QStringList CCPlugins() const override; From ff76827b1339306110cafdd5c284b3f1615d3948 Mon Sep 17 00:00:00 2001 From: Silarn Date: Mon, 16 Apr 2018 12:51:40 -0500 Subject: [PATCH 0523/1544] [game_skyrimse] Support for multi-game downloads --- src/games/skyrimse/src/gameskyrimse.cpp | 6 +++++- src/games/skyrimse/src/gameskyrimse.h | 1 + 2 files changed, 6 insertions(+), 1 deletion(-) diff --git a/src/games/skyrimse/src/gameskyrimse.cpp b/src/games/skyrimse/src/gameskyrimse.cpp index b8528369..2cf455bb 100644 --- a/src/games/skyrimse/src/gameskyrimse.cpp +++ b/src/games/skyrimse/src/gameskyrimse.cpp @@ -283,12 +283,16 @@ QString GameSkyrimSE::gameShortName() const return "skyrimse"; } +QStringList GameSkyrimSE::validShortNames() const +{ + return { "skyrim" }; +} + QString GameSkyrimSE::gameNexusName() const { return "skyrimspecialedition"; } - QStringList GameSkyrimSE::iniFiles() const { return{ "skyrim.ini", "skyrimprefs.ini" }; diff --git a/src/games/skyrimse/src/gameskyrimse.h b/src/games/skyrimse/src/gameskyrimse.h index 14811d04..69c60358 100644 --- a/src/games/skyrimse/src/gameskyrimse.h +++ b/src/games/skyrimse/src/gameskyrimse.h @@ -32,6 +32,7 @@ public: // IPluginGame interface virtual QStringList gameVariants() const override; virtual QString gameShortName() const override; virtual QString gameNexusName() const override; + virtual QStringList validShortNames() const override; virtual QStringList iniFiles() const override; virtual QStringList DLCPlugins() const override; virtual QStringList CCPlugins() const override; From 45f886b9dc07ff1ffcf20c382cd6178cd7151042 Mon Sep 17 00:00:00 2001 From: Silarn Date: Mon, 16 Apr 2018 12:51:41 -0500 Subject: [PATCH 0524/1544] [game_ttw] Support for multi-game downloads --- src/games/ttw/src/gamefalloutttw.cpp | 7 ++++++- src/games/ttw/src/gamefalloutttw.h | 1 + 2 files changed, 7 insertions(+), 1 deletion(-) diff --git a/src/games/ttw/src/gamefalloutttw.cpp b/src/games/ttw/src/gamefalloutttw.cpp index 812b7292..c9da02a0 100644 --- a/src/games/ttw/src/gamefalloutttw.cpp +++ b/src/games/ttw/src/gamefalloutttw.cpp @@ -138,7 +138,12 @@ QStringList GameFalloutTTW::primaryPlugins() const QString GameFalloutTTW::gameShortName() const { - return "FalloutNV"; + return "TTW"; +} + +QStringList GameFalloutTTW::validShortNames() const +{ + return { "Fallout3", "FalloutNV" }; } QString GameFalloutTTW::gameNexusName() const diff --git a/src/games/ttw/src/gamefalloutttw.h b/src/games/ttw/src/gamefalloutttw.h index dc89840b..6e0d3970 100644 --- a/src/games/ttw/src/gamefalloutttw.h +++ b/src/games/ttw/src/gamefalloutttw.h @@ -29,6 +29,7 @@ public: // IPluginGame interface virtual QString steamAPPId() const override; virtual QStringList primaryPlugins() 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; From 9a8ca3b6322690302f17209270b91239c566feb3 Mon Sep 17 00:00:00 2001 From: Silarn Date: Mon, 16 Apr 2018 14:21:20 -0500 Subject: [PATCH 0525/1544] [game_morrowind] Do not sort inactive plugins to the bottom --- src/games/morrowind/src/morrowindgameplugins.cpp | 5 +---- 1 file changed, 1 insertion(+), 4 deletions(-) diff --git a/src/games/morrowind/src/morrowindgameplugins.cpp b/src/games/morrowind/src/morrowindgameplugins.cpp index 452eaeb9..d3803c65 100644 --- a/src/games/morrowind/src/morrowindgameplugins.cpp +++ b/src/games/morrowind/src/morrowindgameplugins.cpp @@ -163,14 +163,11 @@ bool MorrowindGamePlugins::readPluginList(MOBase::IPluginList *pluginList, if (!activePlugins.contains(pluginName)) inactivePlugins.push_back(pluginName); - for (const QString &pluginName : inactivePlugins) - plugins.removeAll(pluginName); - for (const QString &pluginName : inactivePlugins) pluginList->setState(pluginName, IPluginList::STATE_INACTIVE); if (useLoadOrder) - pluginList->setLoadOrder(primary + plugins + inactivePlugins); + pluginList->setLoadOrder(primary + plugins); return true; } \ No newline at end of file From 285d5ef45826a0931dcba9ed3d0c710d84c4b2bc Mon Sep 17 00:00:00 2001 From: Silarn Date: Mon, 16 Apr 2018 14:21:20 -0500 Subject: [PATCH 0526/1544] Do not sort inactive plugins to the bottom --- src/gamebryogameplugins.cpp | 5 +---- 1 file changed, 1 insertion(+), 4 deletions(-) diff --git a/src/gamebryogameplugins.cpp b/src/gamebryogameplugins.cpp index 788fcaa4..a65a2a12 100644 --- a/src/gamebryogameplugins.cpp +++ b/src/gamebryogameplugins.cpp @@ -224,9 +224,6 @@ bool GamebryoGamePlugins::readPluginList(MOBase::IPluginList *pluginList, if (!activePlugins.contains(pluginName)) inactivePlugins.push_back(pluginName); - for (const QString &pluginName : inactivePlugins) - plugins.removeAll(pluginName); - for (const QString &pluginName : inactivePlugins) pluginList->setState(pluginName, IPluginList::STATE_INACTIVE); } else { @@ -236,7 +233,7 @@ bool GamebryoGamePlugins::readPluginList(MOBase::IPluginList *pluginList, } if (useLoadOrder) - pluginList->setLoadOrder(primary + plugins + inactivePlugins); + pluginList->setLoadOrder(primary + plugins); return true; } From f16e2e1208bdeb0f94fac4ffe773b360a7f6df1c Mon Sep 17 00:00:00 2001 From: Silarn Date: Mon, 16 Apr 2018 16:59:48 -0500 Subject: [PATCH 0527/1544] [game_fallout4vr] Add Gamebyro strings to translations --- src/games/fallout4vr/src/CMakeLists.txt | 13 ++-- .../fallout4vr/src/game_fallout4vr_en.ts | 77 +++++++++++++++++++ 2 files changed, 85 insertions(+), 5 deletions(-) diff --git a/src/games/fallout4vr/src/CMakeLists.txt b/src/games/fallout4vr/src/CMakeLists.txt index 73d4accc..774f7067 100644 --- a/src/games/fallout4vr/src/CMakeLists.txt +++ b/src/games/fallout4vr/src/CMakeLists.txt @@ -16,8 +16,15 @@ SET(CMAKE_AUTOUIC ON) FIND_PACKAGE(Qt5Widgets REQUIRED) QT5_WRAP_UI(${PROJ_NAME}_UIHDRS ${${PROJ_NAME}_FORMS}) QT5_ADD_RESOURCES(${PROJ_NAME}_RCCPPS ${${PROJ_NAME}_QRCS}) + +SET(default_project_path "${CMAKE_SOURCE_DIR}/..") +GET_FILENAME_COMPONENT(${default_project_path} ${default_project_path} REALPATH) + +SET(project_path "${default_project_path}" CACHE PATH "path to the other mo projects") + FIND_PACKAGE(Qt5LinguistTools) -QT5_CREATE_TRANSLATION(${PROJ_NAME}_translations_qm ${CMAKE_SOURCE_DIR}/src ${CMAKE_SOURCE_DIR}/src/${PROJ_NAME}_en.ts) +SET(translation_sources ${CMAKE_SOURCE_DIR}/src ${project_path}/game_gamebryo/src) +QT5_CREATE_TRANSLATION(${PROJ_NAME}_translations_qm ${translation_sources} ${CMAKE_SOURCE_DIR}/src/${PROJ_NAME}_en.ts) SET(Boost_USE_STATIC_LIBS ON) SET(Boost_USE_MULTITHREADED ON) @@ -28,10 +35,6 @@ IF (Boost_FOUND) INCLUDE_DIRECTORIES(${Boost_INCLUDE_DIRS}) ENDIF () -SET(default_project_path "${CMAKE_SOURCE_DIR}/..") -GET_FILENAME_COMPONENT(${default_project_path} ${default_project_path} REALPATH) - -SET(project_path "${default_project_path}" CACHE PATH "path to the other mo projects") SET(lib_path "${project_path}/../../install/libs") INCLUDE_DIRECTORIES(${project_path}/uibase/src diff --git a/src/games/fallout4vr/src/game_fallout4vr_en.ts b/src/games/fallout4vr/src/game_fallout4vr_en.ts index 326872d3..60dde6cf 100644 --- a/src/games/fallout4vr/src/game_fallout4vr_en.ts +++ b/src/games/fallout4vr/src/game_fallout4vr_en.ts @@ -10,22 +10,99 @@ Splash by %1 + + GamebryoSaveGameInfoWidget + + + Save # + + + + + Character + + + + + Level + + + + + Location + + + + + Date + + + + + Has Script Extender Data + + + + + Missing ESPs + + + + + + None + + + + + Missing ESLs + + + QObject + Some of your plugins have invalid names! These plugins can not be loaded by the game. Please see mo_interface.log for a list of affected plugins and rename them. + failed to query registry path (preflight): %1 + failed to query registry path (read): %1 + + + failed to deactivate BSA invalidation in "%1" (errorcode %2) + + + + + failed to activate BSA invalidation in "%1" (errorcode %2) + + + + + failed to set archive key (errorcode %1) + + + + + failed to open %1 + + + + + wrong file format - expected %1 got %2 + + From 7eedcd5a5f1d04cbbb8a0ad5f99bba992f739480 Mon Sep 17 00:00:00 2001 From: Silarn Date: Mon, 16 Apr 2018 16:59:48 -0500 Subject: [PATCH 0528/1544] [game_morrowind] Add Gamebyro strings to translations --- src/games/morrowind/src/CMakeLists.txt | 13 ++-- src/games/morrowind/src/game_morrowind_en.ts | 81 ++++++++++++++++++++ 2 files changed, 89 insertions(+), 5 deletions(-) diff --git a/src/games/morrowind/src/CMakeLists.txt b/src/games/morrowind/src/CMakeLists.txt index 39cbca6f..1130bfa4 100644 --- a/src/games/morrowind/src/CMakeLists.txt +++ b/src/games/morrowind/src/CMakeLists.txt @@ -16,8 +16,15 @@ SET(CMAKE_AUTOUIC ON) FIND_PACKAGE(Qt5Widgets REQUIRED) QT5_WRAP_UI(${PROJ_NAME}_UIHDRS ${${PROJ_NAME}_FORMS}) QT5_ADD_RESOURCES(${PROJ_NAME}_RCCPPS ${${PROJ_NAME}_QRCS}) + +SET(default_project_path "${CMAKE_SOURCE_DIR}/..") +GET_FILENAME_COMPONENT(${default_project_path} ${default_project_path} REALPATH) + +SET(project_path "${default_project_path}" CACHE PATH "path to the other mo projects") + FIND_PACKAGE(Qt5LinguistTools) -QT5_CREATE_TRANSLATION(${PROJ_NAME}_translations_qm ${CMAKE_SOURCE_DIR}/src ${CMAKE_SOURCE_DIR}/src/${PROJ_NAME}_en.ts) +SET(translation_sources ${CMAKE_SOURCE_DIR}/src ${project_path}/game_gamebryo/src) +QT5_CREATE_TRANSLATION(${PROJ_NAME}_translations_qm ${translation_sources} ${CMAKE_SOURCE_DIR}/src/${PROJ_NAME}_en.ts) SET(Boost_USE_STATIC_LIBS ON) SET(Boost_USE_MULTITHREADED ON) @@ -28,10 +35,6 @@ IF (Boost_FOUND) INCLUDE_DIRECTORIES(${Boost_INCLUDE_DIRS}) ENDIF () -SET(default_project_path "${CMAKE_SOURCE_DIR}/..") -GET_FILENAME_COMPONENT(${default_project_path} ${default_project_path} REALPATH) - -SET(project_path "${default_project_path}" CACHE PATH "path to the other mo projects") SET(lib_path "${project_path}/../../install/libs") INCLUDE_DIRECTORIES(${project_path}/uibase/src diff --git a/src/games/morrowind/src/game_morrowind_en.ts b/src/games/morrowind/src/game_morrowind_en.ts index 464dfbd6..7115db47 100644 --- a/src/games/morrowind/src/game_morrowind_en.ts +++ b/src/games/morrowind/src/game_morrowind_en.ts @@ -11,6 +11,55 @@ Splash by %1 + + GamebryoSaveGameInfoWidget + + + Save # + + + + + Character + + + + + Level + + + + + Location + + + + + Date + + + + + Has Script Extender Data + + + + + Missing ESPs + + + + + + None + + + + + Missing ESLs + + + MorrowindSaveGameInfoWidget @@ -62,14 +111,46 @@ Splash by %1 + Some of your plugins have invalid names! These plugins can not be loaded by the game. Please see mo_interface.log for a list of affected plugins and rename them. + failed to set archive key (errorcode %1) + + + failed to deactivate BSA invalidation in "%1" (errorcode %2) + + + + + failed to activate BSA invalidation in "%1" (errorcode %2) + + + + + failed to open %1 + + + + + wrong file format - expected %1 got %2 + + + + + failed to query registry path (preflight): %1 + + + + + failed to query registry path (read): %1 + + From 99ba9048517ef7097d8ccc3e7f737d55b54c4ae8 Mon Sep 17 00:00:00 2001 From: Silarn Date: Mon, 16 Apr 2018 16:59:48 -0500 Subject: [PATCH 0529/1544] [game_falloutnv] Add Gamebyro strings to translations --- src/games/falloutnv/src/CMakeLists.txt | 13 +-- src/games/falloutnv/src/game_falloutNV_en.ts | 92 ++++++++++++++++++++ 2 files changed, 100 insertions(+), 5 deletions(-) diff --git a/src/games/falloutnv/src/CMakeLists.txt b/src/games/falloutnv/src/CMakeLists.txt index 664079ec..0cd515a1 100644 --- a/src/games/falloutnv/src/CMakeLists.txt +++ b/src/games/falloutnv/src/CMakeLists.txt @@ -12,8 +12,15 @@ SET(CMAKE_AUTOMOC ON) SET(CMAKE_AUTOUIC ON) FIND_PACKAGE(Qt5Widgets REQUIRED) QT5_WRAP_UI(${PROJ_NAME}_UIHDRS ${${PROJ_NAME}_FORMS}) + +SET(default_project_path "${CMAKE_SOURCE_DIR}/..") +GET_FILENAME_COMPONENT(${default_project_path} ${default_project_path} REALPATH) + +SET(project_path "${default_project_path}" CACHE PATH "path to the other mo projects") + FIND_PACKAGE(Qt5LinguistTools) -QT5_CREATE_TRANSLATION(${PROJ_NAME}_translations_qm ${CMAKE_SOURCE_DIR}/src ${CMAKE_SOURCE_DIR}/src/${PROJ_NAME}_en.ts) +SET(translation_sources ${CMAKE_SOURCE_DIR}/src ${project_path}/game_gamebryo/src) +QT5_CREATE_TRANSLATION(${PROJ_NAME}_translations_qm ${translation_sources} ${CMAKE_SOURCE_DIR}/src/${PROJ_NAME}_en.ts) SET(Boost_USE_STATIC_LIBS ON) SET(Boost_USE_MULTITHREADED ON) @@ -24,10 +31,6 @@ IF (Boost_FOUND) INCLUDE_DIRECTORIES(${Boost_INCLUDE_DIRS}) ENDIF () -SET(default_project_path "${CMAKE_SOURCE_DIR}/..") -GET_FILENAME_COMPONENT(${default_project_path} ${default_project_path} REALPATH) - -SET(project_path "${default_project_path}" CACHE PATH "path to the other mo projects") SET(lib_path "${project_path}/../../install/libs") INCLUDE_DIRECTORIES(${project_path}/uibase/src diff --git a/src/games/falloutnv/src/game_falloutNV_en.ts b/src/games/falloutnv/src/game_falloutNV_en.ts index b1111848..b3ba02aa 100644 --- a/src/games/falloutnv/src/game_falloutNV_en.ts +++ b/src/games/falloutnv/src/game_falloutNV_en.ts @@ -9,4 +9,96 @@ + + GamebryoSaveGameInfoWidget + + + Save # + + + + + Character + + + + + Level + + + + + Location + + + + + Date + + + + + Has Script Extender Data + + + + + Missing ESPs + + + + + + None + + + + + Missing ESLs + + + + + QObject + + + failed to deactivate BSA invalidation in "%1" (errorcode %2) + + + + + failed to activate BSA invalidation in "%1" (errorcode %2) + + + + + failed to set archive key (errorcode %1) + + + + + Some of your plugins have invalid names! These plugins can not be loaded by the game. Please see mo_interface.log for a list of affected plugins and rename them. + + + + + failed to open %1 + + + + + wrong file format - expected %1 got %2 + + + + + failed to query registry path (preflight): %1 + + + + + failed to query registry path (read): %1 + + + From 0edf15c9a9b848c1f4a81acbf94d62cc5612cb91 Mon Sep 17 00:00:00 2001 From: Silarn Date: Mon, 16 Apr 2018 16:59:49 -0500 Subject: [PATCH 0530/1544] [game_skyrimvr] Add Gamebyro strings to translations --- src/games/skyrimvr/src/CMakeLists.txt | 13 ++-- src/games/skyrimvr/src/game_skyrimvr_en.ts | 77 ++++++++++++++++++++++ 2 files changed, 85 insertions(+), 5 deletions(-) diff --git a/src/games/skyrimvr/src/CMakeLists.txt b/src/games/skyrimvr/src/CMakeLists.txt index 850748ae..a88e92f4 100644 --- a/src/games/skyrimvr/src/CMakeLists.txt +++ b/src/games/skyrimvr/src/CMakeLists.txt @@ -12,8 +12,15 @@ SET(CMAKE_AUTOMOC ON) SET(CMAKE_AUTOUIC ON) FIND_PACKAGE(Qt5Widgets REQUIRED) QT5_WRAP_UI(${PROJ_NAME}_UIHDRS ${${PROJ_NAME}_FORMS}) + +SET(default_project_path "${CMAKE_SOURCE_DIR}/..") +GET_FILENAME_COMPONENT(${default_project_path} ${default_project_path} REALPATH) + +SET(project_path "${default_project_path}" CACHE PATH "path to the other mo projects") + FIND_PACKAGE(Qt5LinguistTools) -QT5_CREATE_TRANSLATION(${PROJ_NAME}_translations_qm ${CMAKE_SOURCE_DIR}/src ${CMAKE_SOURCE_DIR}/src/${PROJ_NAME}_en.ts) +SET(translation_sources ${CMAKE_SOURCE_DIR}/src ${project_path}/game_gamebryo/src) +QT5_CREATE_TRANSLATION(${PROJ_NAME}_translations_qm ${translation_sources} ${CMAKE_SOURCE_DIR}/src/${PROJ_NAME}_en.ts) SET(Boost_USE_STATIC_LIBS ON) SET(Boost_USE_MULTITHREADED ON) @@ -24,10 +31,6 @@ IF (Boost_FOUND) INCLUDE_DIRECTORIES(${Boost_INCLUDE_DIRS}) ENDIF () -SET(default_project_path "${CMAKE_SOURCE_DIR}/..") -GET_FILENAME_COMPONENT(${default_project_path} ${default_project_path} REALPATH) - -SET(project_path "${default_project_path}" CACHE PATH "path to the other mo projects") SET(lib_path "${project_path}/../../install/libs") INCLUDE_DIRECTORIES(${project_path}/uibase/src diff --git a/src/games/skyrimvr/src/game_skyrimvr_en.ts b/src/games/skyrimvr/src/game_skyrimvr_en.ts index 069b6cf1..ba1ad280 100644 --- a/src/games/skyrimvr/src/game_skyrimvr_en.ts +++ b/src/games/skyrimvr/src/game_skyrimvr_en.ts @@ -9,22 +9,99 @@ + + GamebryoSaveGameInfoWidget + + + Save # + + + + + Character + + + + + Level + + + + + Location + + + + + Date + + + + + Has Script Extender Data + + + + + Missing ESPs + + + + + + None + + + + + Missing ESLs + + + QObject + failed to query registry path (preflight): %1 + failed to query registry path (read): %1 + Some of your plugins have invalid names! These plugins can not be loaded by the game. Please see mo_interface.log for a list of affected plugins and rename them. + + + failed to deactivate BSA invalidation in "%1" (errorcode %2) + + + + + failed to activate BSA invalidation in "%1" (errorcode %2) + + + + + failed to set archive key (errorcode %1) + + + + + failed to open %1 + + + + + wrong file format - expected %1 got %2 + + From 1fbe96630ef2b9d5f606e4607170dc0c1bc7c36a Mon Sep 17 00:00:00 2001 From: Silarn Date: Mon, 16 Apr 2018 16:59:49 -0500 Subject: [PATCH 0531/1544] [game_fallout76] Add Gamebyro strings to translations --- src/games/fallout76/src/CMakeLists.txt | 13 ++-- src/games/fallout76/src/game_fallout4_en.ts | 85 +++++++++++++++++++++ 2 files changed, 93 insertions(+), 5 deletions(-) diff --git a/src/games/fallout76/src/CMakeLists.txt b/src/games/fallout76/src/CMakeLists.txt index b5b22c9d..f1f0ec8b 100644 --- a/src/games/fallout76/src/CMakeLists.txt +++ b/src/games/fallout76/src/CMakeLists.txt @@ -16,8 +16,15 @@ SET(CMAKE_AUTOUIC ON) FIND_PACKAGE(Qt5Widgets REQUIRED) QT5_WRAP_UI(${PROJ_NAME}_UIHDRS ${${PROJ_NAME}_FORMS}) QT5_ADD_RESOURCES(${PROJ_NAME}_RCCPPS ${${PROJ_NAME}_QRCS}) + +SET(default_project_path "${CMAKE_SOURCE_DIR}/..") +GET_FILENAME_COMPONENT(${default_project_path} ${default_project_path} REALPATH) + +SET(project_path "${default_project_path}" CACHE PATH "path to the other mo projects") + FIND_PACKAGE(Qt5LinguistTools) -QT5_CREATE_TRANSLATION(${PROJ_NAME}_translations_qm ${CMAKE_SOURCE_DIR}/src ${CMAKE_SOURCE_DIR}/src/${PROJ_NAME}_en.ts) +SET(translation_sources ${CMAKE_SOURCE_DIR}/src ${project_path}/game_gamebryo/src) +QT5_CREATE_TRANSLATION(${PROJ_NAME}_translations_qm ${translation_sources} ${CMAKE_SOURCE_DIR}/src/${PROJ_NAME}_en.ts) SET(Boost_USE_STATIC_LIBS ON) SET(Boost_USE_MULTITHREADED ON) @@ -28,10 +35,6 @@ IF (Boost_FOUND) INCLUDE_DIRECTORIES(${Boost_INCLUDE_DIRS}) ENDIF () -SET(default_project_path "${CMAKE_SOURCE_DIR}/..") -GET_FILENAME_COMPONENT(${default_project_path} ${default_project_path} REALPATH) - -SET(project_path "${default_project_path}" CACHE PATH "path to the other mo projects") SET(lib_path "${project_path}/../../install/libs") INCLUDE_DIRECTORIES(${project_path}/uibase/src diff --git a/src/games/fallout76/src/game_fallout4_en.ts b/src/games/fallout76/src/game_fallout4_en.ts index ac13ed09..dddeac6c 100644 --- a/src/games/fallout76/src/game_fallout4_en.ts +++ b/src/games/fallout76/src/game_fallout4_en.ts @@ -10,12 +10,97 @@ Splash by %1 + + GamebryoSaveGameInfoWidget + + + Save # + + + + + Character + + + + + Level + + + + + Location + + + + + Date + + + + + Has Script Extender Data + + + + + Missing ESPs + + + + + + None + + + + + Missing ESLs + + + QObject + Some of your plugins have invalid names! These plugins can not be loaded by the game. Please see mo_interface.log for a list of affected plugins and rename them. + + + failed to deactivate BSA invalidation in "%1" (errorcode %2) + + + + + failed to activate BSA invalidation in "%1" (errorcode %2) + + + + + failed to set archive key (errorcode %1) + + + + + failed to open %1 + + + + + wrong file format - expected %1 got %2 + + + + + failed to query registry path (preflight): %1 + + + + + failed to query registry path (read): %1 + + From a6fc07eee6521026b4ecf953f6d820c6bb8a6020 Mon Sep 17 00:00:00 2001 From: Silarn Date: Mon, 16 Apr 2018 16:59:49 -0500 Subject: [PATCH 0532/1544] [game_fallout4] Add Gamebyro strings to translations --- src/games/fallout4/src/CMakeLists.txt | 13 ++-- src/games/fallout4/src/game_fallout4_en.ts | 85 ++++++++++++++++++++++ 2 files changed, 93 insertions(+), 5 deletions(-) diff --git a/src/games/fallout4/src/CMakeLists.txt b/src/games/fallout4/src/CMakeLists.txt index b5b22c9d..f1f0ec8b 100644 --- a/src/games/fallout4/src/CMakeLists.txt +++ b/src/games/fallout4/src/CMakeLists.txt @@ -16,8 +16,15 @@ SET(CMAKE_AUTOUIC ON) FIND_PACKAGE(Qt5Widgets REQUIRED) QT5_WRAP_UI(${PROJ_NAME}_UIHDRS ${${PROJ_NAME}_FORMS}) QT5_ADD_RESOURCES(${PROJ_NAME}_RCCPPS ${${PROJ_NAME}_QRCS}) + +SET(default_project_path "${CMAKE_SOURCE_DIR}/..") +GET_FILENAME_COMPONENT(${default_project_path} ${default_project_path} REALPATH) + +SET(project_path "${default_project_path}" CACHE PATH "path to the other mo projects") + FIND_PACKAGE(Qt5LinguistTools) -QT5_CREATE_TRANSLATION(${PROJ_NAME}_translations_qm ${CMAKE_SOURCE_DIR}/src ${CMAKE_SOURCE_DIR}/src/${PROJ_NAME}_en.ts) +SET(translation_sources ${CMAKE_SOURCE_DIR}/src ${project_path}/game_gamebryo/src) +QT5_CREATE_TRANSLATION(${PROJ_NAME}_translations_qm ${translation_sources} ${CMAKE_SOURCE_DIR}/src/${PROJ_NAME}_en.ts) SET(Boost_USE_STATIC_LIBS ON) SET(Boost_USE_MULTITHREADED ON) @@ -28,10 +35,6 @@ IF (Boost_FOUND) INCLUDE_DIRECTORIES(${Boost_INCLUDE_DIRS}) ENDIF () -SET(default_project_path "${CMAKE_SOURCE_DIR}/..") -GET_FILENAME_COMPONENT(${default_project_path} ${default_project_path} REALPATH) - -SET(project_path "${default_project_path}" CACHE PATH "path to the other mo projects") SET(lib_path "${project_path}/../../install/libs") INCLUDE_DIRECTORIES(${project_path}/uibase/src diff --git a/src/games/fallout4/src/game_fallout4_en.ts b/src/games/fallout4/src/game_fallout4_en.ts index ac13ed09..dddeac6c 100644 --- a/src/games/fallout4/src/game_fallout4_en.ts +++ b/src/games/fallout4/src/game_fallout4_en.ts @@ -10,12 +10,97 @@ Splash by %1 + + GamebryoSaveGameInfoWidget + + + Save # + + + + + Character + + + + + Level + + + + + Location + + + + + Date + + + + + Has Script Extender Data + + + + + Missing ESPs + + + + + + None + + + + + Missing ESLs + + + QObject + Some of your plugins have invalid names! These plugins can not be loaded by the game. Please see mo_interface.log for a list of affected plugins and rename them. + + + failed to deactivate BSA invalidation in "%1" (errorcode %2) + + + + + failed to activate BSA invalidation in "%1" (errorcode %2) + + + + + failed to set archive key (errorcode %1) + + + + + failed to open %1 + + + + + wrong file format - expected %1 got %2 + + + + + failed to query registry path (preflight): %1 + + + + + failed to query registry path (read): %1 + + From c5c7a6d618a6cb335efec9414ff1aa416c3bf913 Mon Sep 17 00:00:00 2001 From: Silarn Date: Mon, 16 Apr 2018 16:59:50 -0500 Subject: [PATCH 0533/1544] [game_fallout3] Add Gamebyro strings to translations --- src/games/fallout3/src/CMakeLists.txt | 13 +-- src/games/fallout3/src/game_fallout3_en.ts | 92 ++++++++++++++++++++++ 2 files changed, 100 insertions(+), 5 deletions(-) diff --git a/src/games/fallout3/src/CMakeLists.txt b/src/games/fallout3/src/CMakeLists.txt index 664079ec..0cd515a1 100644 --- a/src/games/fallout3/src/CMakeLists.txt +++ b/src/games/fallout3/src/CMakeLists.txt @@ -12,8 +12,15 @@ SET(CMAKE_AUTOMOC ON) SET(CMAKE_AUTOUIC ON) FIND_PACKAGE(Qt5Widgets REQUIRED) QT5_WRAP_UI(${PROJ_NAME}_UIHDRS ${${PROJ_NAME}_FORMS}) + +SET(default_project_path "${CMAKE_SOURCE_DIR}/..") +GET_FILENAME_COMPONENT(${default_project_path} ${default_project_path} REALPATH) + +SET(project_path "${default_project_path}" CACHE PATH "path to the other mo projects") + FIND_PACKAGE(Qt5LinguistTools) -QT5_CREATE_TRANSLATION(${PROJ_NAME}_translations_qm ${CMAKE_SOURCE_DIR}/src ${CMAKE_SOURCE_DIR}/src/${PROJ_NAME}_en.ts) +SET(translation_sources ${CMAKE_SOURCE_DIR}/src ${project_path}/game_gamebryo/src) +QT5_CREATE_TRANSLATION(${PROJ_NAME}_translations_qm ${translation_sources} ${CMAKE_SOURCE_DIR}/src/${PROJ_NAME}_en.ts) SET(Boost_USE_STATIC_LIBS ON) SET(Boost_USE_MULTITHREADED ON) @@ -24,10 +31,6 @@ IF (Boost_FOUND) INCLUDE_DIRECTORIES(${Boost_INCLUDE_DIRS}) ENDIF () -SET(default_project_path "${CMAKE_SOURCE_DIR}/..") -GET_FILENAME_COMPONENT(${default_project_path} ${default_project_path} REALPATH) - -SET(project_path "${default_project_path}" CACHE PATH "path to the other mo projects") SET(lib_path "${project_path}/../../install/libs") INCLUDE_DIRECTORIES(${project_path}/uibase/src diff --git a/src/games/fallout3/src/game_fallout3_en.ts b/src/games/fallout3/src/game_fallout3_en.ts index db164c9f..67b7b320 100644 --- a/src/games/fallout3/src/game_fallout3_en.ts +++ b/src/games/fallout3/src/game_fallout3_en.ts @@ -9,4 +9,96 @@ + + GamebryoSaveGameInfoWidget + + + Save # + + + + + Character + + + + + Level + + + + + Location + + + + + Date + + + + + Has Script Extender Data + + + + + Missing ESPs + + + + + + None + + + + + Missing ESLs + + + + + QObject + + + failed to deactivate BSA invalidation in "%1" (errorcode %2) + + + + + failed to activate BSA invalidation in "%1" (errorcode %2) + + + + + failed to set archive key (errorcode %1) + + + + + Some of your plugins have invalid names! These plugins can not be loaded by the game. Please see mo_interface.log for a list of affected plugins and rename them. + + + + + failed to open %1 + + + + + wrong file format - expected %1 got %2 + + + + + failed to query registry path (preflight): %1 + + + + + failed to query registry path (read): %1 + + + From ddc98fbbd4f159a320dbff6485316143c4b19acc Mon Sep 17 00:00:00 2001 From: Silarn Date: Mon, 16 Apr 2018 16:59:50 -0500 Subject: [PATCH 0534/1544] [game_oblivion] Add Gamebyro strings to translations --- src/games/oblivion/src/CMakeLists.txt | 13 +-- src/games/oblivion/src/game_oblivion_en.ts | 92 ++++++++++++++++++++++ 2 files changed, 100 insertions(+), 5 deletions(-) diff --git a/src/games/oblivion/src/CMakeLists.txt b/src/games/oblivion/src/CMakeLists.txt index 56ff8913..e3df2f60 100644 --- a/src/games/oblivion/src/CMakeLists.txt +++ b/src/games/oblivion/src/CMakeLists.txt @@ -12,8 +12,15 @@ SET(CMAKE_AUTOMOC ON) SET(CMAKE_AUTOUIC ON) FIND_PACKAGE(Qt5Widgets REQUIRED) QT5_WRAP_UI(${PROJ_NAME}_UIHDRS ${${PROJ_NAME}_FORMS}) + +SET(default_project_path "${CMAKE_SOURCE_DIR}/..") +GET_FILENAME_COMPONENT(${default_project_path} ${default_project_path} REALPATH) + +SET(project_path "${default_project_path}" CACHE PATH "path to the other mo projects") + FIND_PACKAGE(Qt5LinguistTools) -QT5_CREATE_TRANSLATION(${PROJ_NAME}_translations_qm ${CMAKE_SOURCE_DIR}/src ${CMAKE_SOURCE_DIR}/src/${PROJ_NAME}_en.ts) +SET(translation_sources ${CMAKE_SOURCE_DIR}/src ${project_path}/game_gamebryo/src) +QT5_CREATE_TRANSLATION(${PROJ_NAME}_translations_qm ${translation_sources} ${CMAKE_SOURCE_DIR}/src/${PROJ_NAME}_en.ts) SET(Boost_USE_STATIC_LIBS ON) SET(Boost_USE_MULTITHREADED ON) @@ -24,10 +31,6 @@ IF (Boost_FOUND) INCLUDE_DIRECTORIES(${Boost_INCLUDE_DIRS}) ENDIF () -SET(default_project_path "${CMAKE_SOURCE_DIR}/..") -GET_FILENAME_COMPONENT(${default_project_path} ${default_project_path} REALPATH) - -SET(project_path "${default_project_path}" CACHE PATH "path to the other mo projects") SET(lib_path "${project_path}/../../install/libs") INCLUDE_DIRECTORIES(${project_path}/uibase/src diff --git a/src/games/oblivion/src/game_oblivion_en.ts b/src/games/oblivion/src/game_oblivion_en.ts index 8110ae36..f356a91c 100644 --- a/src/games/oblivion/src/game_oblivion_en.ts +++ b/src/games/oblivion/src/game_oblivion_en.ts @@ -9,4 +9,96 @@ + + GamebryoSaveGameInfoWidget + + + Save # + + + + + Character + + + + + Level + + + + + Location + + + + + Date + + + + + Has Script Extender Data + + + + + Missing ESPs + + + + + + None + + + + + Missing ESLs + + + + + QObject + + + failed to deactivate BSA invalidation in "%1" (errorcode %2) + + + + + failed to activate BSA invalidation in "%1" (errorcode %2) + + + + + failed to set archive key (errorcode %1) + + + + + Some of your plugins have invalid names! These plugins can not be loaded by the game. Please see mo_interface.log for a list of affected plugins and rename them. + + + + + failed to open %1 + + + + + wrong file format - expected %1 got %2 + + + + + failed to query registry path (preflight): %1 + + + + + failed to query registry path (read): %1 + + + From c910efbd12e24bd0fb9f22a1c739dcf421708357 Mon Sep 17 00:00:00 2001 From: Silarn Date: Mon, 16 Apr 2018 16:59:51 -0500 Subject: [PATCH 0535/1544] [game_ttw] Add Gamebyro strings to translations --- src/games/ttw/src/CMakeLists.txt | 13 +-- src/games/ttw/src/game_falloutTTW_en.ts | 12 --- src/games/ttw/src/game_ttw_en.ts | 104 ++++++++++++++++++++++++ 3 files changed, 112 insertions(+), 17 deletions(-) delete mode 100644 src/games/ttw/src/game_falloutTTW_en.ts create mode 100644 src/games/ttw/src/game_ttw_en.ts diff --git a/src/games/ttw/src/CMakeLists.txt b/src/games/ttw/src/CMakeLists.txt index 664079ec..0cd515a1 100644 --- a/src/games/ttw/src/CMakeLists.txt +++ b/src/games/ttw/src/CMakeLists.txt @@ -12,8 +12,15 @@ SET(CMAKE_AUTOMOC ON) SET(CMAKE_AUTOUIC ON) FIND_PACKAGE(Qt5Widgets REQUIRED) QT5_WRAP_UI(${PROJ_NAME}_UIHDRS ${${PROJ_NAME}_FORMS}) + +SET(default_project_path "${CMAKE_SOURCE_DIR}/..") +GET_FILENAME_COMPONENT(${default_project_path} ${default_project_path} REALPATH) + +SET(project_path "${default_project_path}" CACHE PATH "path to the other mo projects") + FIND_PACKAGE(Qt5LinguistTools) -QT5_CREATE_TRANSLATION(${PROJ_NAME}_translations_qm ${CMAKE_SOURCE_DIR}/src ${CMAKE_SOURCE_DIR}/src/${PROJ_NAME}_en.ts) +SET(translation_sources ${CMAKE_SOURCE_DIR}/src ${project_path}/game_gamebryo/src) +QT5_CREATE_TRANSLATION(${PROJ_NAME}_translations_qm ${translation_sources} ${CMAKE_SOURCE_DIR}/src/${PROJ_NAME}_en.ts) SET(Boost_USE_STATIC_LIBS ON) SET(Boost_USE_MULTITHREADED ON) @@ -24,10 +31,6 @@ IF (Boost_FOUND) INCLUDE_DIRECTORIES(${Boost_INCLUDE_DIRS}) ENDIF () -SET(default_project_path "${CMAKE_SOURCE_DIR}/..") -GET_FILENAME_COMPONENT(${default_project_path} ${default_project_path} REALPATH) - -SET(project_path "${default_project_path}" CACHE PATH "path to the other mo projects") SET(lib_path "${project_path}/../../install/libs") INCLUDE_DIRECTORIES(${project_path}/uibase/src diff --git a/src/games/ttw/src/game_falloutTTW_en.ts b/src/games/ttw/src/game_falloutTTW_en.ts deleted file mode 100644 index 8da7a685..00000000 --- a/src/games/ttw/src/game_falloutTTW_en.ts +++ /dev/null @@ -1,12 +0,0 @@ - - - - - GameFalloutTTW - - - Adds support for the game Fallout TTW - - - - diff --git a/src/games/ttw/src/game_ttw_en.ts b/src/games/ttw/src/game_ttw_en.ts new file mode 100644 index 00000000..7b8c19a6 --- /dev/null +++ b/src/games/ttw/src/game_ttw_en.ts @@ -0,0 +1,104 @@ + + + + + GameFalloutTTW + + + Adds support for the game Fallout TTW + + + + + GamebryoSaveGameInfoWidget + + + Save # + + + + + Character + + + + + Level + + + + + Location + + + + + Date + + + + + Has Script Extender Data + + + + + Missing ESPs + + + + + + None + + + + + Missing ESLs + + + + + QObject + + + failed to deactivate BSA invalidation in "%1" (errorcode %2) + + + + + failed to activate BSA invalidation in "%1" (errorcode %2) + + + + + failed to set archive key (errorcode %1) + + + + + Some of your plugins have invalid names! These plugins can not be loaded by the game. Please see mo_interface.log for a list of affected plugins and rename them. + + + + + failed to open %1 + + + + + wrong file format - expected %1 got %2 + + + + + failed to query registry path (preflight): %1 + + + + + failed to query registry path (read): %1 + + + + From be3c61aadc5b88c38c76844f6c9a5733589ae811 Mon Sep 17 00:00:00 2001 From: Silarn Date: Mon, 16 Apr 2018 16:59:51 -0500 Subject: [PATCH 0536/1544] [game_skyrimse] Add Gamebyro strings to translations --- src/games/skyrimse/src/CMakeLists.txt | 13 ++-- src/games/skyrimse/src/game_skyrimse_en.ts | 77 ++++++++++++++++++++++ 2 files changed, 85 insertions(+), 5 deletions(-) diff --git a/src/games/skyrimse/src/CMakeLists.txt b/src/games/skyrimse/src/CMakeLists.txt index 56f3152a..ad5c8dfa 100644 --- a/src/games/skyrimse/src/CMakeLists.txt +++ b/src/games/skyrimse/src/CMakeLists.txt @@ -12,8 +12,15 @@ SET(CMAKE_AUTOMOC ON) SET(CMAKE_AUTOUIC ON) FIND_PACKAGE(Qt5Widgets REQUIRED) QT5_WRAP_UI(${PROJ_NAME}_UIHDRS ${${PROJ_NAME}_FORMS}) + +SET(default_project_path "${CMAKE_SOURCE_DIR}/..") +GET_FILENAME_COMPONENT(${default_project_path} ${default_project_path} REALPATH) + +SET(project_path "${default_project_path}" CACHE PATH "path to the other mo projects") + FIND_PACKAGE(Qt5LinguistTools) -QT5_CREATE_TRANSLATION(${PROJ_NAME}_translations_qm ${CMAKE_SOURCE_DIR}/src ${CMAKE_SOURCE_DIR}/src/${PROJ_NAME}_en.ts) +SET(translation_sources ${CMAKE_SOURCE_DIR}/src ${project_path}/game_gamebryo/src) +QT5_CREATE_TRANSLATION(${PROJ_NAME}_translations_qm ${translation_sources} ${CMAKE_SOURCE_DIR}/src/${PROJ_NAME}_en.ts) SET(Boost_USE_STATIC_LIBS ON) SET(Boost_USE_MULTITHREADED ON) @@ -24,10 +31,6 @@ IF (Boost_FOUND) INCLUDE_DIRECTORIES(${Boost_INCLUDE_DIRS}) ENDIF () -SET(default_project_path "${CMAKE_SOURCE_DIR}/..") -GET_FILENAME_COMPONENT(${default_project_path} ${default_project_path} REALPATH) - -SET(project_path "${default_project_path}" CACHE PATH "path to the other mo projects") SET(lib_path "${project_path}/../../install/libs") INCLUDE_DIRECTORIES(${project_path}/uibase/src diff --git a/src/games/skyrimse/src/game_skyrimse_en.ts b/src/games/skyrimse/src/game_skyrimse_en.ts index aea8c4b8..1c092880 100644 --- a/src/games/skyrimse/src/game_skyrimse_en.ts +++ b/src/games/skyrimse/src/game_skyrimse_en.ts @@ -9,22 +9,99 @@ + + GamebryoSaveGameInfoWidget + + + Save # + + + + + Character + + + + + Level + + + + + Location + + + + + Date + + + + + Has Script Extender Data + + + + + Missing ESPs + + + + + + None + + + + + Missing ESLs + + + QObject + failed to query registry path (preflight): %1 + failed to query registry path (read): %1 + Some of your plugins have invalid names! These plugins can not be loaded by the game. Please see mo_interface.log for a list of affected plugins and rename them. + + + failed to deactivate BSA invalidation in "%1" (errorcode %2) + + + + + failed to activate BSA invalidation in "%1" (errorcode %2) + + + + + failed to set archive key (errorcode %1) + + + + + failed to open %1 + + + + + wrong file format - expected %1 got %2 + + From 33be7f5a6c38d091fcbabf44be4bea90e37ada2e Mon Sep 17 00:00:00 2001 From: Silarn Date: Mon, 16 Apr 2018 16:59:51 -0500 Subject: [PATCH 0537/1544] [game_skyrim] Add Gamebyro strings to translations --- src/games/skyrim/src/CMakeLists.txt | 13 ++-- src/games/skyrim/src/game_skyrim_en.ts | 92 ++++++++++++++++++++++++++ 2 files changed, 100 insertions(+), 5 deletions(-) diff --git a/src/games/skyrim/src/CMakeLists.txt b/src/games/skyrim/src/CMakeLists.txt index 122e1156..38d13578 100644 --- a/src/games/skyrim/src/CMakeLists.txt +++ b/src/games/skyrim/src/CMakeLists.txt @@ -12,8 +12,15 @@ SET(CMAKE_AUTOMOC ON) SET(CMAKE_AUTOUIC ON) FIND_PACKAGE(Qt5Widgets REQUIRED) QT5_WRAP_UI(${PROJ_NAME}_UIHDRS ${${PROJ_NAME}_FORMS}) + +SET(default_project_path "${CMAKE_SOURCE_DIR}/..") +GET_FILENAME_COMPONENT(${default_project_path} ${default_project_path} REALPATH) + +SET(project_path "${default_project_path}" CACHE PATH "path to the other mo projects") + FIND_PACKAGE(Qt5LinguistTools) -QT5_CREATE_TRANSLATION(${PROJ_NAME}_translations_qm ${CMAKE_SOURCE_DIR}/src ${CMAKE_SOURCE_DIR}/src/${PROJ_NAME}_en.ts) +SET(translation_sources ${CMAKE_SOURCE_DIR}/src ${project_path}/game_gamebryo/src) +QT5_CREATE_TRANSLATION(${PROJ_NAME}_translations_qm ${translation_sources} ${CMAKE_SOURCE_DIR}/src/${PROJ_NAME}_en.ts) SET(Boost_USE_STATIC_LIBS ON) SET(Boost_USE_MULTITHREADED ON) @@ -24,10 +31,6 @@ IF (Boost_FOUND) INCLUDE_DIRECTORIES(${Boost_INCLUDE_DIRS}) ENDIF () -SET(default_project_path "${CMAKE_SOURCE_DIR}/..") -GET_FILENAME_COMPONENT(${default_project_path} ${default_project_path} REALPATH) - -SET(project_path "${default_project_path}" CACHE PATH "path to the other mo projects") SET(lib_path "${project_path}/../../install/libs") INCLUDE_DIRECTORIES(${project_path}/uibase/src diff --git a/src/games/skyrim/src/game_skyrim_en.ts b/src/games/skyrim/src/game_skyrim_en.ts index bea30796..7e2499f9 100644 --- a/src/games/skyrim/src/game_skyrim_en.ts +++ b/src/games/skyrim/src/game_skyrim_en.ts @@ -9,4 +9,96 @@ + + GamebryoSaveGameInfoWidget + + + Save # + + + + + Character + + + + + Level + + + + + Location + + + + + Date + + + + + Has Script Extender Data + + + + + Missing ESPs + + + + + + None + + + + + Missing ESLs + + + + + QObject + + + failed to deactivate BSA invalidation in "%1" (errorcode %2) + + + + + failed to activate BSA invalidation in "%1" (errorcode %2) + + + + + failed to set archive key (errorcode %1) + + + + + Some of your plugins have invalid names! These plugins can not be loaded by the game. Please see mo_interface.log for a list of affected plugins and rename them. + + + + + failed to open %1 + + + + + wrong file format - expected %1 got %2 + + + + + failed to query registry path (preflight): %1 + + + + + failed to query registry path (read): %1 + + + From 7b19ceee298b638294f631586678b8aa3fcaac5f Mon Sep 17 00:00:00 2001 From: Silarn Date: Tue, 17 Apr 2018 02:46:19 -0500 Subject: [PATCH 0538/1544] [game_ttw] Changes to allow custom shortname --- src/games/ttw/src/gamefalloutttw.cpp | 61 +++++++++++++++++++++++++++- src/games/ttw/src/gamefalloutttw.h | 6 +++ 2 files changed, 66 insertions(+), 1 deletion(-) diff --git a/src/games/ttw/src/gamefalloutttw.cpp b/src/games/ttw/src/gamefalloutttw.cpp index c9da02a0..e13b4153 100644 --- a/src/games/ttw/src/gamefalloutttw.cpp +++ b/src/games/ttw/src/gamefalloutttw.cpp @@ -7,6 +7,7 @@ #include "executableinfo.h" #include "pluginsetting.h" +#include "iplugingame.h" #include "versioninfo.h" #include #include @@ -22,6 +23,48 @@ #include +#include "utility.h" +#include +#include +#include "scopeguard.h" + +namespace { + std::unique_ptr getRegValue(HKEY key, LPCWSTR path, LPCWSTR value, + DWORD flags, LPDWORD type = nullptr) + { + DWORD size = 0; + HKEY subKey; + LONG res = ::RegOpenKeyExW(key, path, 0, + KEY_QUERY_VALUE | KEY_WOW64_32KEY, &subKey); + if (res != ERROR_SUCCESS) { + return std::unique_ptr(); + } + res = ::RegGetValueW(subKey, L"", value, flags, type, nullptr, &size); + if (res == ERROR_FILE_NOT_FOUND || res == ERROR_UNSUPPORTED_TYPE) { + return std::unique_ptr(); + } + if (res != ERROR_SUCCESS && res != ERROR_MORE_DATA) { + throw MOBase::MyException(QObject::tr("failed to query registry path (preflight): %1").arg(res, 0, 16)); + } + + std::unique_ptr result(new BYTE[size]); + res = ::RegGetValueW(subKey, L"", value, flags, type, result.get(), &size); + + if (res != ERROR_SUCCESS) { + throw MOBase::MyException(QObject::tr("failed to query registry path (read): %1").arg(res, 0, 16)); + } + + return result; + } + + QString findInRegistry(HKEY baseKey, LPCWSTR path, LPCWSTR value) + { + std::unique_ptr buffer = getRegValue(baseKey, path, value, RRF_RT_REG_SZ | RRF_NOEXPAND); + + return QString::fromUtf16(reinterpret_cast(buffer.get())); + } +} + using namespace MOBase; GameFalloutTTW::GameFalloutTTW() @@ -136,6 +179,11 @@ QStringList GameFalloutTTW::primaryPlugins() const "mercenarypack.esm", "tribalpack.esm", "taleoftwowastelands.esm" }; } +QString GameFalloutTTW::binaryName() const +{ + return "FalloutNV.exe"; +} + QString GameFalloutTTW::gameShortName() const { return "TTW"; @@ -143,7 +191,7 @@ QString GameFalloutTTW::gameShortName() const QStringList GameFalloutTTW::validShortNames() const { - return { "Fallout3", "FalloutNV" }; + return { "FalloutNV", "Fallout3" }; } QString GameFalloutTTW::gameNexusName() const @@ -170,3 +218,14 @@ int GameFalloutTTW::nexusGameID() const { return 130; } + +QString GameFalloutTTW::getLauncherName() const +{ + return "FalloutNVLauncher.exe"; +} + +QString GameFalloutTTW::identifyGamePath() const +{ + QString path = "Software\\Bethesda Softworks\\FalloutNV"; + return findInRegistry(HKEY_LOCAL_MACHINE, path.toStdWString().c_str(), L"Installed Path"); +} diff --git a/src/games/ttw/src/gamefalloutttw.h b/src/games/ttw/src/gamefalloutttw.h index 6e0d3970..1b162b48 100644 --- a/src/games/ttw/src/gamefalloutttw.h +++ b/src/games/ttw/src/gamefalloutttw.h @@ -28,6 +28,7 @@ public: // IPluginGame interface virtual QString savegameSEExtension() const override; virtual QString steamAPPId() const override; virtual QStringList primaryPlugins() const override; + virtual QString binaryName() const override; virtual QString gameShortName() const override; virtual QStringList validShortNames() const override; virtual QString gameNexusName() const override; @@ -35,6 +36,7 @@ public: // IPluginGame interface virtual QStringList DLCPlugins() const override; virtual int nexusModOrganizerID() const override; virtual int nexusGameID() const override; + virtual QString getLauncherName() const override; public: // IPlugin interface @@ -45,6 +47,10 @@ public: // IPlugin interface virtual bool isActive() const; virtual QList settings() const; +private: + + QString identifyGamePath() const; + }; #endif // GAMEFALLOUTTTW_H From c6daa6eaa6053c5e43dee13d20435d6338bb9f65 Mon Sep 17 00:00:00 2001 From: Silarn Date: Tue, 17 Apr 2018 15:33:22 -0500 Subject: [PATCH 0539/1544] Move functions and properties to protected so children can modify them --- src/gamegamebryo.cpp | 170 +++++++++++++++++++++---------------------- src/gamegamebryo.h | 20 +++-- 2 files changed, 97 insertions(+), 93 deletions(-) diff --git a/src/gamegamebryo.cpp b/src/gamegamebryo.cpp index 31fb67f5..dfaf1bec 100644 --- a/src/gamegamebryo.cpp +++ b/src/gamegamebryo.cpp @@ -25,92 +25,6 @@ #include #include -namespace { - -std::unique_ptr getRegValue(HKEY key, LPCWSTR path, LPCWSTR value, - DWORD flags, LPDWORD type = nullptr) -{ - DWORD size = 0; - HKEY subKey; - LONG res = ::RegOpenKeyExW(key, path, 0, - KEY_QUERY_VALUE | KEY_WOW64_32KEY, &subKey); - if (res != ERROR_SUCCESS) { - return std::unique_ptr(); - } - res = ::RegGetValueW(subKey, L"", value, flags, type, nullptr, &size); - if (res == ERROR_FILE_NOT_FOUND || res == ERROR_UNSUPPORTED_TYPE) { - return std::unique_ptr(); - } - if (res != ERROR_SUCCESS && res != ERROR_MORE_DATA) { - throw MOBase::MyException(QObject::tr("failed to query registry path (preflight): %1").arg(res, 0, 16)); - } - - std::unique_ptr result(new BYTE[size]); - res = ::RegGetValueW(subKey, L"", value, flags, type, result.get(), &size); - - if (res != ERROR_SUCCESS) { - throw MOBase::MyException(QObject::tr("failed to query registry path (read): %1").arg(res, 0, 16)); - } - - return result; -} - -QString findInRegistry(HKEY baseKey, LPCWSTR path, LPCWSTR value) -{ - std::unique_ptr buffer = getRegValue(baseKey, path, value, RRF_RT_REG_SZ | RRF_NOEXPAND); - - return QString::fromUtf16(reinterpret_cast(buffer.get())); -} - -QString getKnownFolderPath(REFKNOWNFOLDERID folderId, bool useDefault) -{ - PWSTR path = nullptr; - ON_BLOCK_EXIT([&] () { - if (path != nullptr) ::CoTaskMemFree(path); - }); - - if (::SHGetKnownFolderPath(folderId, useDefault ? KF_FLAG_DEFAULT_PATH : 0, NULL, &path) == S_OK) { - return QDir::fromNativeSeparators(QString::fromWCharArray(path)); - } else { - return QString(); - } -} - -QString getSpecialPath(const QString &name) -{ - QString base = findInRegistry(HKEY_CURRENT_USER, - L"Software\\Microsoft\\Windows\\CurrentVersion\\Explorer\\User Shell Folders", - name.toStdWString().c_str()); - - WCHAR temp[MAX_PATH]; - if (::ExpandEnvironmentStringsW(base.toStdWString().c_str(), temp, MAX_PATH) != 0) { - return QString::fromWCharArray(temp); - } else { - return base; - } -} - -QString determineMyGamesPath(const QString &gameName) -{ - // a) this is the way it should work. get the configured My Documents directory - QString result = getKnownFolderPath(FOLDERID_Documents, false); - - // b) if there is no directory there, look in the default directory - if (result.isEmpty() - || !QFileInfo(result + "/My Games/" + gameName).exists()) { - result = getKnownFolderPath(FOLDERID_Documents, true); - } - // c) finally, look in the registry. This is discouraged - if (result.isEmpty() - || !QFileInfo(result + "/My Games/" + gameName).exists()) { - result = getSpecialPath("Personal"); - } - - return result + "/My Games/" + gameName; -} - -} - GameGamebryo::GameGamebryo() { } @@ -343,3 +257,87 @@ MappingType GameGamebryo::mappings() const return result; } + +std::unique_ptr GameGamebryo::getRegValue(HKEY key, LPCWSTR path, LPCWSTR value, + DWORD flags, LPDWORD type = nullptr) +{ + DWORD size = 0; + HKEY subKey; + LONG res = ::RegOpenKeyExW(key, path, 0, + KEY_QUERY_VALUE | KEY_WOW64_32KEY, &subKey); + if (res != ERROR_SUCCESS) { + return std::unique_ptr(); + } + res = ::RegGetValueW(subKey, L"", value, flags, type, nullptr, &size); + if (res == ERROR_FILE_NOT_FOUND || res == ERROR_UNSUPPORTED_TYPE) { + return std::unique_ptr(); + } + if (res != ERROR_SUCCESS && res != ERROR_MORE_DATA) { + throw MOBase::MyException(QObject::tr("failed to query registry path (preflight): %1").arg(res, 0, 16)); + } + + std::unique_ptr result(new BYTE[size]); + res = ::RegGetValueW(subKey, L"", value, flags, type, result.get(), &size); + + if (res != ERROR_SUCCESS) { + throw MOBase::MyException(QObject::tr("failed to query registry path (read): %1").arg(res, 0, 16)); + } + + return result; +} + +QString GameGamebryo::findInRegistry(HKEY baseKey, LPCWSTR path, LPCWSTR value) +{ + std::unique_ptr buffer = getRegValue(baseKey, path, value, RRF_RT_REG_SZ | RRF_NOEXPAND); + + return QString::fromUtf16(reinterpret_cast(buffer.get())); +} + +QString GameGamebryo::getKnownFolderPath(REFKNOWNFOLDERID folderId, bool useDefault) +{ + PWSTR path = nullptr; + ON_BLOCK_EXIT([&]() { + if (path != nullptr) ::CoTaskMemFree(path); + }); + + if (::SHGetKnownFolderPath(folderId, useDefault ? KF_FLAG_DEFAULT_PATH : 0, NULL, &path) == S_OK) { + return QDir::fromNativeSeparators(QString::fromWCharArray(path)); + } + else { + return QString(); + } +} + +QString GameGamebryo::getSpecialPath(const QString &name) +{ + QString base = findInRegistry(HKEY_CURRENT_USER, + L"Software\\Microsoft\\Windows\\CurrentVersion\\Explorer\\User Shell Folders", + name.toStdWString().c_str()); + + WCHAR temp[MAX_PATH]; + if (::ExpandEnvironmentStringsW(base.toStdWString().c_str(), temp, MAX_PATH) != 0) { + return QString::fromWCharArray(temp); + } + else { + return base; + } +} + +QString GameGamebryo::determineMyGamesPath(const QString &gameName) +{ + // a) this is the way it should work. get the configured My Documents directory + QString result = getKnownFolderPath(FOLDERID_Documents, false); + + // b) if there is no directory there, look in the default directory + if (result.isEmpty() + || !QFileInfo(result + "/My Games/" + gameName).exists()) { + result = getKnownFolderPath(FOLDERID_Documents, true); + } + // c) finally, look in the registry. This is discouraged + if (result.isEmpty() + || !QFileInfo(result + "/My Games/" + gameName).exists()) { + result = getSpecialPath("Personal"); + } + + return result + "/My Games/" + gameName; +} \ No newline at end of file diff --git a/src/gamegamebryo.h b/src/gamegamebryo.h index be02d138..2ae12359 100644 --- a/src/gamegamebryo.h +++ b/src/gamegamebryo.h @@ -96,6 +96,18 @@ protected: const QString &sourceFileName, const QString &destinationFileName); + virtual QString identifyGamePath() const; + + static std::unique_ptr getRegValue(HKEY key, LPCWSTR path, LPCWSTR value, DWORD flags, LPDWORD type); + + static QString findInRegistry(HKEY baseKey, LPCWSTR path, LPCWSTR value); + + static QString getKnownFolderPath(REFKNOWNFOLDERID folderId, bool useDefault); + + static QString getSpecialPath(const QString &name); + + static QString determineMyGamesPath(const QString &gameName); + protected: std::map featureList() const; @@ -117,17 +129,11 @@ protected: m_FeatureList[std::type_index(typeid(T))] = type; } -private: - - QString identifyGamePath() const; - -private: +protected: QString m_GamePath; QString m_MyGamesPath; - QString m_GameVariant; - MOBase::IOrganizer *m_Organizer; std::map m_FeatureList; From 8363da680a6148965877c64655a335244120a7c6 Mon Sep 17 00:00:00 2001 From: Silarn Date: Tue, 17 Apr 2018 15:34:11 -0500 Subject: [PATCH 0540/1544] [game_ttw] Fix TTW to properly parse registry and game directory --- src/games/ttw/src/gamefalloutttw.cpp | 45 ++-------------------------- src/games/ttw/src/gamefalloutttw.h | 4 +-- 2 files changed, 4 insertions(+), 45 deletions(-) diff --git a/src/games/ttw/src/gamefalloutttw.cpp b/src/games/ttw/src/gamefalloutttw.cpp index e13b4153..bc256c1e 100644 --- a/src/games/ttw/src/gamefalloutttw.cpp +++ b/src/games/ttw/src/gamefalloutttw.cpp @@ -7,7 +7,6 @@ #include "executableinfo.h" #include "pluginsetting.h" -#include "iplugingame.h" #include "versioninfo.h" #include #include @@ -23,48 +22,6 @@ #include -#include "utility.h" -#include -#include -#include "scopeguard.h" - -namespace { - std::unique_ptr getRegValue(HKEY key, LPCWSTR path, LPCWSTR value, - DWORD flags, LPDWORD type = nullptr) - { - DWORD size = 0; - HKEY subKey; - LONG res = ::RegOpenKeyExW(key, path, 0, - KEY_QUERY_VALUE | KEY_WOW64_32KEY, &subKey); - if (res != ERROR_SUCCESS) { - return std::unique_ptr(); - } - res = ::RegGetValueW(subKey, L"", value, flags, type, nullptr, &size); - if (res == ERROR_FILE_NOT_FOUND || res == ERROR_UNSUPPORTED_TYPE) { - return std::unique_ptr(); - } - if (res != ERROR_SUCCESS && res != ERROR_MORE_DATA) { - throw MOBase::MyException(QObject::tr("failed to query registry path (preflight): %1").arg(res, 0, 16)); - } - - std::unique_ptr result(new BYTE[size]); - res = ::RegGetValueW(subKey, L"", value, flags, type, result.get(), &size); - - if (res != ERROR_SUCCESS) { - throw MOBase::MyException(QObject::tr("failed to query registry path (read): %1").arg(res, 0, 16)); - } - - return result; - } - - QString findInRegistry(HKEY baseKey, LPCWSTR path, LPCWSTR value) - { - std::unique_ptr buffer = getRegValue(baseKey, path, value, RRF_RT_REG_SZ | RRF_NOEXPAND); - - return QString::fromUtf16(reinterpret_cast(buffer.get())); - } -} - using namespace MOBase; GameFalloutTTW::GameFalloutTTW() @@ -76,6 +33,8 @@ bool GameFalloutTTW::init(IOrganizer *moInfo) if (!GameGamebryo::init(moInfo)) { return false; } + m_GamePath = identifyGamePath(); + m_MyGamesPath = determineMyGamesPath("FalloutNV"); registerFeature(new FalloutTTWScriptExtender(this)); registerFeature(new FalloutTTWDataArchives(myGamesPath())); registerFeature(new FalloutTTWBSAInvalidation(feature(), this)); diff --git a/src/games/ttw/src/gamefalloutttw.h b/src/games/ttw/src/gamefalloutttw.h index 1b162b48..f77f26d1 100644 --- a/src/games/ttw/src/gamefalloutttw.h +++ b/src/games/ttw/src/gamefalloutttw.h @@ -47,9 +47,9 @@ public: // IPlugin interface virtual bool isActive() const; virtual QList settings() const; -private: +protected: - QString identifyGamePath() const; + virtual QString identifyGamePath() const override; }; From 9ba55e3067e914b7d77bfc2f6df50df2310df564 Mon Sep 17 00:00:00 2001 From: Silarn Date: Tue, 17 Apr 2018 15:34:55 -0500 Subject: [PATCH 0541/1544] [game_skyrimvr] Remove and streamline extraneous gode --- src/games/skyrimvr/src/game_skyrimvr_en.ts | 8 +- src/games/skyrimvr/src/gameskyrimvr.cpp | 103 --------------------- src/games/skyrimvr/src/gameskyrimvr.h | 10 +- 3 files changed, 5 insertions(+), 116 deletions(-) diff --git a/src/games/skyrimvr/src/game_skyrimvr_en.ts b/src/games/skyrimvr/src/game_skyrimvr_en.ts index ba1ad280..8ee38856 100644 --- a/src/games/skyrimvr/src/game_skyrimvr_en.ts +++ b/src/games/skyrimvr/src/game_skyrimvr_en.ts @@ -4,7 +4,7 @@ GameSkyrimVR - + Adds support for the game Skyrim VR. @@ -61,14 +61,12 @@ QObject - - + failed to query registry path (preflight): %1 - - + failed to query registry path (read): %1 diff --git a/src/games/skyrimvr/src/gameskyrimvr.cpp b/src/games/skyrimvr/src/gameskyrimvr.cpp index 327dcc19..998f3abd 100644 --- a/src/games/skyrimvr/src/gameskyrimvr.cpp +++ b/src/games/skyrimvr/src/gameskyrimvr.cpp @@ -7,7 +7,6 @@ #include "skyrimvrunmanagedmods.h" #include -#include "iplugingame.h" #include #include #include @@ -22,103 +21,8 @@ #include #include - -#include "utility.h" -#include -#include #include "scopeguard.h" -namespace { - - std::unique_ptr getRegValue(HKEY key, LPCWSTR path, LPCWSTR value, - DWORD flags, LPDWORD type = nullptr) - { - DWORD size = 0; - HKEY subKey; - LONG res = ::RegOpenKeyExW(key, path, 0, - KEY_QUERY_VALUE | KEY_WOW64_32KEY, &subKey); - if (res != ERROR_SUCCESS) { - return std::unique_ptr(); - } - res = ::RegGetValueW(subKey, L"", value, flags, type, nullptr, &size); - if (res == ERROR_FILE_NOT_FOUND || res == ERROR_UNSUPPORTED_TYPE) { - return std::unique_ptr(); - } - if (res != ERROR_SUCCESS && res != ERROR_MORE_DATA) { - throw MOBase::MyException(QObject::tr("failed to query registry path (preflight): %1").arg(res, 0, 16)); - } - - std::unique_ptr result(new BYTE[size]); - res = ::RegGetValueW(subKey, L"", value, flags, type, result.get(), &size); - - if (res != ERROR_SUCCESS) { - throw MOBase::MyException(QObject::tr("failed to query registry path (read): %1").arg(res, 0, 16)); - } - - return result; - } - - QString findInRegistry(HKEY baseKey, LPCWSTR path, LPCWSTR value) - { - std::unique_ptr buffer = getRegValue(baseKey, path, value, RRF_RT_REG_SZ | RRF_NOEXPAND); - - return QString::fromUtf16(reinterpret_cast(buffer.get())); - } - - QString getKnownFolderPath(REFKNOWNFOLDERID folderId, bool useDefault) - { - PWSTR path = nullptr; - ON_BLOCK_EXIT([&]() { - if (path != nullptr) ::CoTaskMemFree(path); - }); - - if (::SHGetKnownFolderPath(folderId, useDefault ? KF_FLAG_DEFAULT_PATH : 0, NULL, &path) == S_OK) { - return QDir::fromNativeSeparators(QString::fromWCharArray(path)); - } - else { - return QString(); - } - } - - - QString getSpecialPath(const QString &name) - { - QString base = findInRegistry(HKEY_CURRENT_USER, - L"Software\\Microsoft\\Windows\\CurrentVersion\\Explorer\\User Shell Folders", - name.toStdWString().c_str()); - - WCHAR temp[MAX_PATH]; - if (::ExpandEnvironmentStringsW(base.toStdWString().c_str(), temp, MAX_PATH) != 0) { - return QString::fromWCharArray(temp); - } - else { - return base; - } - } - - QString determineMyGamesPath(const QString &gameName) - { - // a) this is the way it should work. get the configured My Documents directory - QString result = getKnownFolderPath(FOLDERID_Documents, false); - - // b) if there is no directory there, look in the default directory - if (result.isEmpty() - || !QFileInfo(result + "/My Games/" + gameName).exists()) { - result = getKnownFolderPath(FOLDERID_Documents, true); - } - // c) finally, look in the registry. This is discouraged - if (result.isEmpty() - || !QFileInfo(result + "/My Games/" + gameName).exists()) { - result = getSpecialPath("Personal"); - } - - return result + "/My Games/" + gameName; - } - - -} - - using namespace MOBase; GameSkyrimVR::GameSkyrimVR() @@ -162,11 +66,9 @@ bool GameSkyrimVR::init(IOrganizer *moInfo) return false; } - m_Organizer = moInfo; m_GamePath = GameSkyrimVR::identifyGamePath(); m_MyGamesPath = determineMyGamesPath(gameName()); - registerFeature(new SkyrimVRScriptExtender(this)); registerFeature(new SkyrimVRDataArchives(myGamesPath())); registerFeature(new GamebryoLocalSavegames(myGamesPath(), "SkyrimVR.ini")); @@ -354,11 +256,6 @@ QDir GameSkyrimVR::gameDirectory() const return QDir(m_GamePath); } -QString GameSkyrimVR::binaryName() const -{ - return "SkyrimVR.exe"; -} - // Not to delete all the spaces... MappingType GameSkyrimVR::mappings() const { diff --git a/src/games/skyrimvr/src/gameskyrimvr.h b/src/games/skyrimvr/src/gameskyrimvr.h index 44809fcc..13ddd88a 100644 --- a/src/games/skyrimvr/src/gameskyrimvr.h +++ b/src/games/skyrimvr/src/gameskyrimvr.h @@ -36,7 +36,6 @@ public: // IPluginGame interface virtual int nexusModOrganizerID() const override; virtual int nexusGameID() const override; virtual QString getLauncherName() const override; - virtual QString GameSkyrimVR::binaryName() const; virtual bool isInstalled() const override; virtual void setGamePath(const QString &path) override; @@ -51,19 +50,14 @@ public: // IPlugin interface virtual QList settings() const override; public: // IPluginFileMapper - virtual MappingType mappings() const; + virtual MappingType mappings() const override; protected: QDir documentsDirectory() const; QDir savesDirectory() const; QFileInfo findInGameFolder(const QString &relativePath) const; QString myGamesPath() const; - -private: - MOBase::IOrganizer *m_Organizer; - QString identifyGamePath() const; - QString m_GamePath; - QString m_MyGamesPath; + virtual QString identifyGamePath() const override; }; #endif // _GAMESKYRIMVR_H From 53a01b7d437bdb2c19c460c34a92640fc1b96769 Mon Sep 17 00:00:00 2001 From: Silarn Date: Tue, 17 Apr 2018 15:34:56 -0500 Subject: [PATCH 0542/1544] [game_fallout76] Remove and streamline extraneous gode --- src/games/fallout76/src/gamefallout4.cpp | 4 ---- 1 file changed, 4 deletions(-) diff --git a/src/games/fallout76/src/gamefallout4.cpp b/src/games/fallout76/src/gamefallout4.cpp index 85b69b53..bf7d958d 100644 --- a/src/games/fallout76/src/gamefallout4.cpp +++ b/src/games/fallout76/src/gamefallout4.cpp @@ -7,7 +7,6 @@ #include "fallout4unmanagedmods.h" #include -#include "iplugingame.h" #include #include #include @@ -23,9 +22,6 @@ #include -#include "utility.h" -#include -#include #include "scopeguard.h" using namespace MOBase; From 77f8ce1d162d8defaee0dc4727d18e2aa8da495c Mon Sep 17 00:00:00 2001 From: Silarn Date: Tue, 17 Apr 2018 15:34:56 -0500 Subject: [PATCH 0543/1544] [game_fallout4] Remove and streamline extraneous gode --- src/games/fallout4/src/gamefallout4.cpp | 4 ---- 1 file changed, 4 deletions(-) diff --git a/src/games/fallout4/src/gamefallout4.cpp b/src/games/fallout4/src/gamefallout4.cpp index 85b69b53..bf7d958d 100644 --- a/src/games/fallout4/src/gamefallout4.cpp +++ b/src/games/fallout4/src/gamefallout4.cpp @@ -7,7 +7,6 @@ #include "fallout4unmanagedmods.h" #include -#include "iplugingame.h" #include #include #include @@ -23,9 +22,6 @@ #include -#include "utility.h" -#include -#include #include "scopeguard.h" using namespace MOBase; From e0d35741602e1145e239a48c2e364b6f3c26dbf5 Mon Sep 17 00:00:00 2001 From: Silarn Date: Tue, 17 Apr 2018 15:34:56 -0500 Subject: [PATCH 0544/1544] [game_skyrimse] Remove and streamline extraneous gode --- src/games/skyrimse/src/gameskyrimse.cpp | 98 ------------------------- src/games/skyrimse/src/gameskyrimse.h | 11 +-- 2 files changed, 2 insertions(+), 107 deletions(-) diff --git a/src/games/skyrimse/src/gameskyrimse.cpp b/src/games/skyrimse/src/gameskyrimse.cpp index 2cf455bb..d336a67e 100644 --- a/src/games/skyrimse/src/gameskyrimse.cpp +++ b/src/games/skyrimse/src/gameskyrimse.cpp @@ -7,7 +7,6 @@ #include "skyrimseunmanagedmods.h" #include -#include "iplugingame.h" #include #include #include @@ -22,103 +21,8 @@ #include #include - -#include "utility.h" -#include -#include #include "scopeguard.h" -namespace { - - std::unique_ptr getRegValue(HKEY key, LPCWSTR path, LPCWSTR value, - DWORD flags, LPDWORD type = nullptr) - { - DWORD size = 0; - HKEY subKey; - LONG res = ::RegOpenKeyExW(key, path, 0, - KEY_QUERY_VALUE | KEY_WOW64_32KEY, &subKey); - if (res != ERROR_SUCCESS) { - return std::unique_ptr(); - } - res = ::RegGetValueW(subKey, L"", value, flags, type, nullptr, &size); - if (res == ERROR_FILE_NOT_FOUND || res == ERROR_UNSUPPORTED_TYPE) { - return std::unique_ptr(); - } - if (res != ERROR_SUCCESS && res != ERROR_MORE_DATA) { - throw MOBase::MyException(QObject::tr("failed to query registry path (preflight): %1").arg(res, 0, 16)); - } - - std::unique_ptr result(new BYTE[size]); - res = ::RegGetValueW(subKey, L"", value, flags, type, result.get(), &size); - - if (res != ERROR_SUCCESS) { - throw MOBase::MyException(QObject::tr("failed to query registry path (read): %1").arg(res, 0, 16)); - } - - return result; - } - - QString findInRegistry(HKEY baseKey, LPCWSTR path, LPCWSTR value) - { - std::unique_ptr buffer = getRegValue(baseKey, path, value, RRF_RT_REG_SZ | RRF_NOEXPAND); - - return QString::fromUtf16(reinterpret_cast(buffer.get())); - } - - QString getKnownFolderPath(REFKNOWNFOLDERID folderId, bool useDefault) - { - PWSTR path = nullptr; - ON_BLOCK_EXIT([&]() { - if (path != nullptr) ::CoTaskMemFree(path); - }); - - if (::SHGetKnownFolderPath(folderId, useDefault ? KF_FLAG_DEFAULT_PATH : 0, NULL, &path) == S_OK) { - return QDir::fromNativeSeparators(QString::fromWCharArray(path)); - } - else { - return QString(); - } - } - - - QString getSpecialPath(const QString &name) - { - QString base = findInRegistry(HKEY_CURRENT_USER, - L"Software\\Microsoft\\Windows\\CurrentVersion\\Explorer\\User Shell Folders", - name.toStdWString().c_str()); - - WCHAR temp[MAX_PATH]; - if (::ExpandEnvironmentStringsW(base.toStdWString().c_str(), temp, MAX_PATH) != 0) { - return QString::fromWCharArray(temp); - } - else { - return base; - } - } - - QString determineMyGamesPath(const QString &gameName) - { - // a) this is the way it should work. get the configured My Documents directory - QString result = getKnownFolderPath(FOLDERID_Documents, false); - - // b) if there is no directory there, look in the default directory - if (result.isEmpty() - || !QFileInfo(result + "/My Games/" + gameName).exists()) { - result = getKnownFolderPath(FOLDERID_Documents, true); - } - // c) finally, look in the registry. This is discouraged - if (result.isEmpty() - || !QFileInfo(result + "/My Games/" + gameName).exists()) { - result = getSpecialPath("Personal"); - } - - return result + "/My Games/" + gameName; - } - - -} - - using namespace MOBase; GameSkyrimSE::GameSkyrimSE() @@ -162,11 +66,9 @@ bool GameSkyrimSE::init(IOrganizer *moInfo) return false; } - m_Organizer = moInfo; m_GamePath = GameSkyrimSE::identifyGamePath(); m_MyGamesPath = determineMyGamesPath(gameName()); - registerFeature(new SkyrimSEScriptExtender(this)); registerFeature(new SkyrimSEDataArchives(myGamesPath())); registerFeature(new GamebryoLocalSavegames(myGamesPath(), "Skyrim.ini")); diff --git a/src/games/skyrimse/src/gameskyrimse.h b/src/games/skyrimse/src/gameskyrimse.h index 69c60358..5caaeb7d 100644 --- a/src/games/skyrimse/src/gameskyrimse.h +++ b/src/games/skyrimse/src/gameskyrimse.h @@ -52,6 +52,7 @@ public: // IPlugin interface virtual MOBase::VersionInfo version() const override; virtual bool isActive() const override; virtual QList settings() const override; + virtual MappingType mappings() const override; protected: @@ -60,15 +61,7 @@ protected: QFileInfo findInGameFolder(const QString &relativePath) const; QString myGamesPath() const; -public: // IPluginFileMapper - virtual MappingType mappings() const; - - -private: - MOBase::IOrganizer *m_Organizer; - QString identifyGamePath() const; - QString m_GamePath; - QString m_MyGamesPath; + virtual QString identifyGamePath() const override; }; From c72086dbcf8625e71bd69fbf936540e0aef50b1d Mon Sep 17 00:00:00 2001 From: Silarn Date: Tue, 17 Apr 2018 16:25:22 -0500 Subject: [PATCH 0545/1544] [game_fallout4vr] Clean up duplicated code and update settings files --- src/games/fallout4vr/src/gamefallout4vr.cpp | 61 ++------------------- src/games/fallout4vr/src/gamefallout4vr.h | 4 +- 2 files changed, 8 insertions(+), 57 deletions(-) diff --git a/src/games/fallout4vr/src/gamefallout4vr.cpp b/src/games/fallout4vr/src/gamefallout4vr.cpp index ee2f2350..e2e8313c 100644 --- a/src/games/fallout4vr/src/gamefallout4vr.cpp +++ b/src/games/fallout4vr/src/gamefallout4vr.cpp @@ -7,7 +7,6 @@ #include "fallout4vrunmanagedmods.h" #include -#include "iplugingame.h" #include #include #include @@ -23,54 +22,10 @@ #include -#include "utility.h" -#include -#include #include "scopeguard.h" using namespace MOBase; - -// Need to duplicate code from gamegamebryo.cpp here since it's otherwise unaccessible. -namespace { - -std::unique_ptr getRegValue(HKEY key, LPCWSTR path, LPCWSTR value, - DWORD flags, LPDWORD type = nullptr) -{ - DWORD size = 0; - HKEY subKey; - LONG res = ::RegOpenKeyExW(key, path, 0, - KEY_QUERY_VALUE | KEY_WOW64_32KEY, &subKey); - if (res != ERROR_SUCCESS) { - return std::unique_ptr(); - } - res = ::RegGetValueW(subKey, L"", value, flags, type, nullptr, &size); - if (res == ERROR_FILE_NOT_FOUND || res == ERROR_UNSUPPORTED_TYPE) { - return std::unique_ptr(); - } - if (res != ERROR_SUCCESS && res != ERROR_MORE_DATA) { - throw MOBase::MyException(QObject::tr("failed to query registry path (preflight): %1").arg(res, 0, 16)); - } - - std::unique_ptr result(new BYTE[size]); - res = ::RegGetValueW(subKey, L"", value, flags, type, result.get(), &size); - - if (res != ERROR_SUCCESS) { - throw MOBase::MyException(QObject::tr("failed to query registry path (read): %1").arg(res, 0, 16)); - } - - return result; -} - -QString findInRegistry(HKEY baseKey, LPCWSTR path, LPCWSTR value) -{ - std::unique_ptr buffer = getRegValue(baseKey, path, value, RRF_RT_REG_SZ | RRF_NOEXPAND); - - return QString::fromUtf16(reinterpret_cast(buffer.get())); -} - -} - GameFallout4VR::GameFallout4VR() { } @@ -81,10 +36,7 @@ bool GameFallout4VR::init(IOrganizer *moInfo) return false; } - // GameGamebryo::init() searches for the wrong registry key when setting the game path, - // and we cannot just override it because the corresponding code is in a private non-virtual function. - // So we need to set the correct path AFTER we have called GameGamebryo::init(). - setGamePath(identifyGamePathVR()); + m_GamePath = identifyGamePath(); registerFeature(new Fallout4VRScriptExtender(this)); registerFeature(new Fallout4VRDataArchives(myGamesPath())); @@ -156,16 +108,15 @@ void GameFallout4VR::initializeProfile(const QDir &path, ProfileSettings setting The only files in the MyGames directory are fallout4custom.ini, fallout4prefs.ini and fallout4vrcustom.ini. All settings you would expect in the fallout4.ini can be put into the fallout4custom.ini. */ - /*if (settings.testFlag(IPluginGame::PREFER_DEFAULTS) + if (settings.testFlag(IPluginGame::PREFER_DEFAULTS) || !QFileInfo(myGamesPath() + "/fallout4.ini").exists()) { copyToProfile(gameDirectory().absolutePath(), path, "fallout4.ini"); } else { copyToProfile(myGamesPath(), path, "fallout4.ini"); - }*/ + } - copyToProfile(myGamesPath(), path, "fallout4custom.ini"); copyToProfile(myGamesPath(), path, "fallout4prefs.ini"); - copyToProfile(myGamesPath(), path, "fallout4vrcustom.ini"); + copyToProfile(myGamesPath(), path, "fallout4custom.ini"); } } @@ -217,7 +168,7 @@ QString GameFallout4VR::gameNexusName() const QStringList GameFallout4VR::iniFiles() const { - return { "fallout4prefs.ini", "fallout4custom.ini", "fallout4vrcustom.ini" }; + return { "fallout4.ini", "fallout4custom.ini", "fallout4prefs.ini" }; } QStringList GameFallout4VR::DLCPlugins() const @@ -273,7 +224,7 @@ QString GameFallout4VR::getLauncherName() const return binaryName(); // Fallout 4 VR has no Launcher, so we just return the name of the game binary } -QString GameFallout4VR::identifyGamePathVR() const +QString GameFallout4VR::identifyGamePath() const { // In every other Bethesda game they use gameShortName() as registry key, but for Fallout 4 VR they use gameName() QString path = "Software\\Bethesda Softworks\\" + gameName(); diff --git a/src/games/fallout4vr/src/gamefallout4vr.h b/src/games/fallout4vr/src/gamefallout4vr.h index 1c8dd3ab..a6028e88 100644 --- a/src/games/fallout4vr/src/gamefallout4vr.h +++ b/src/games/fallout4vr/src/gamefallout4vr.h @@ -49,9 +49,9 @@ public: // IPlugin interface virtual bool isActive() const override; virtual QList settings() const override; -private: +protected: - QString identifyGamePathVR() const; + virtual QString identifyGamePath() const override; }; From 3ab280aa8e2e05466eb95aa1e757e1cfd9b51401 Mon Sep 17 00:00:00 2001 From: Silarn Date: Wed, 18 Apr 2018 03:30:08 -0500 Subject: [PATCH 0546/1544] [game_morrowind] Add SortMechanism check --- src/games/morrowind/src/game_morrowind_en.ts | 4 ++-- src/games/morrowind/src/gamemorrowind.cpp | 5 +++++ src/games/morrowind/src/gamemorrowind.h | 1 + 3 files changed, 8 insertions(+), 2 deletions(-) diff --git a/src/games/morrowind/src/game_morrowind_en.ts b/src/games/morrowind/src/game_morrowind_en.ts index 7115db47..3288e451 100644 --- a/src/games/morrowind/src/game_morrowind_en.ts +++ b/src/games/morrowind/src/game_morrowind_en.ts @@ -143,12 +143,12 @@ Splash by %1 - + failed to query registry path (preflight): %1 - + failed to query registry path (read): %1 diff --git a/src/games/morrowind/src/gamemorrowind.cpp b/src/games/morrowind/src/gamemorrowind.cpp index 247cd5f6..4aed74bc 100644 --- a/src/games/morrowind/src/gamemorrowind.cpp +++ b/src/games/morrowind/src/gamemorrowind.cpp @@ -178,6 +178,11 @@ QStringList GameMorrowind::DLCPlugins() const return { "Tribunal.esm", "Bloodmoon.esm" }; } +MOBase::IPluginGame::SortMechanism GameMorrowind::sortMechanism() const +{ + return SortMechanism::NONE; +} + namespace { //Note: This is ripped off from shared/util. And in an upcoming move, the fomod //installer requires something similar. I suspect I should abstract this out diff --git a/src/games/morrowind/src/gamemorrowind.h b/src/games/morrowind/src/gamemorrowind.h index d2010ef8..72fe2595 100644 --- a/src/games/morrowind/src/gamemorrowind.h +++ b/src/games/morrowind/src/gamemorrowind.h @@ -40,6 +40,7 @@ public: // IPluginGame interface virtual QString gameNexusName() const override; virtual QStringList iniFiles() const override; virtual QStringList DLCPlugins() const override; + virtual SortMechanism sortMechanism() const override; virtual int nexusModOrganizerID() const override; virtual int nexusGameID() const override; From 9b2a31d0cb19500f49f80f01ecbec74844dd0612 Mon Sep 17 00:00:00 2001 From: Silarn Date: Wed, 18 Apr 2018 03:30:08 -0500 Subject: [PATCH 0547/1544] [game_skyrimvr] Add SortMechanism check --- src/games/skyrimvr/src/gameskyrimvr.cpp | 7 ++++++- src/games/skyrimvr/src/gameskyrimvr.h | 1 + 2 files changed, 7 insertions(+), 1 deletion(-) diff --git a/src/games/skyrimvr/src/gameskyrimvr.cpp b/src/games/skyrimvr/src/gameskyrimvr.cpp index 998f3abd..61ea30d2 100644 --- a/src/games/skyrimvr/src/gameskyrimvr.cpp +++ b/src/games/skyrimvr/src/gameskyrimvr.cpp @@ -92,7 +92,7 @@ QList GameSkyrimVR::executables() const << ExecutableInfo("SKSE", findInGameFolder(feature()->loaderName())) << ExecutableInfo("Skyrim VR", findInGameFolder(binaryName())) << ExecutableInfo("Creation Kit", findInGameFolder("CreationKit.exe")) - << ExecutableInfo("LOOT", getLootPath()).withArgument("--game=\"Skyrim Special Edition\"") + //<< ExecutableInfo("LOOT", getLootPath()).withArgument("--game=\"Skyrim Special Edition\"") Let's not make an entry for a different game ; } @@ -236,6 +236,11 @@ IPluginGame::LoadOrderMechanism GameSkyrimVR::loadOrderMechanism() const return IPluginGame::LoadOrderMechanism::PluginsTxt; } +MOBase::IPluginGame::SortMechanism GameSkyrimVR::sortMechanism() const +{ + return SortMechanism::NONE; +} + int GameSkyrimVR::nexusModOrganizerID() const { return 6194; //... Should be 0? diff --git a/src/games/skyrimvr/src/gameskyrimvr.h b/src/games/skyrimvr/src/gameskyrimvr.h index 13ddd88a..ff6bf41e 100644 --- a/src/games/skyrimvr/src/gameskyrimvr.h +++ b/src/games/skyrimvr/src/gameskyrimvr.h @@ -33,6 +33,7 @@ public: // IPluginGame interface virtual QStringList DLCPlugins() const override; virtual QStringList CCPlugins() const override; virtual LoadOrderMechanism loadOrderMechanism() const override; + virtual SortMechanism sortMechanism() const override; virtual int nexusModOrganizerID() const override; virtual int nexusGameID() const override; virtual QString getLauncherName() const override; From 2f891caf77d7cffc60f020659daa0b835c1a6289 Mon Sep 17 00:00:00 2001 From: Silarn Date: Wed, 18 Apr 2018 03:30:09 -0500 Subject: [PATCH 0548/1544] Add SortMechanism check --- src/gamegamebryo.cpp | 5 +++++ src/gamegamebryo.h | 1 + 2 files changed, 6 insertions(+) diff --git a/src/gamegamebryo.cpp b/src/gamegamebryo.cpp index dfaf1bec..b4673af6 100644 --- a/src/gamegamebryo.cpp +++ b/src/gamegamebryo.cpp @@ -102,6 +102,11 @@ MOBase::IPluginGame::LoadOrderMechanism GameGamebryo::loadOrderMechanism() const return LoadOrderMechanism::FileTime; } +MOBase::IPluginGame::SortMechanism GameGamebryo::sortMechanism() const +{ + return SortMechanism::LOOT; +} + bool GameGamebryo::looksValid(QDir const &path) const { //Check for .exe and Launcher.exe for now. diff --git a/src/gamegamebryo.h b/src/gamegamebryo.h index 2ae12359..6054ebf9 100644 --- a/src/gamegamebryo.h +++ b/src/gamegamebryo.h @@ -62,6 +62,7 @@ public: // IPluginGame interface //DLCPlugins virtual QStringList CCPlugins() const override; virtual LoadOrderMechanism loadOrderMechanism() const override; + virtual SortMechanism sortMechanism() const override; //nexusModOrganizerID //nexusGameID virtual bool looksValid(QDir const &) const override; From 5a4a7f0b7e8d9bf5d57064b78f8d1efc25399550 Mon Sep 17 00:00:00 2001 From: Silarn Date: Wed, 18 Apr 2018 03:30:10 -0500 Subject: [PATCH 0549/1544] [game_ttw] Add SortMechanism check --- src/games/ttw/src/gamefalloutttw.cpp | 5 +++++ src/games/ttw/src/gamefalloutttw.h | 1 + 2 files changed, 6 insertions(+) diff --git a/src/games/ttw/src/gamefalloutttw.cpp b/src/games/ttw/src/gamefalloutttw.cpp index bc256c1e..1fe8b4dd 100644 --- a/src/games/ttw/src/gamefalloutttw.cpp +++ b/src/games/ttw/src/gamefalloutttw.cpp @@ -168,6 +168,11 @@ QStringList GameFalloutTTW::DLCPlugins() const return {}; } +MOBase::IPluginGame::SortMechanism GameFalloutTTW::sortMechanism() const +{ + return SortMechanism::NONE; +} + int GameFalloutTTW::nexusModOrganizerID() const { return 42572; diff --git a/src/games/ttw/src/gamefalloutttw.h b/src/games/ttw/src/gamefalloutttw.h index f77f26d1..38c54729 100644 --- a/src/games/ttw/src/gamefalloutttw.h +++ b/src/games/ttw/src/gamefalloutttw.h @@ -34,6 +34,7 @@ public: // IPluginGame interface virtual QString gameNexusName() const override; virtual QStringList iniFiles() const override; virtual QStringList DLCPlugins() const override; + virtual SortMechanism sortMechanism() const override; virtual int nexusModOrganizerID() const override; virtual int nexusGameID() const override; virtual QString getLauncherName() const override; From 291188062584b3329d2697004016346601c15fa9 Mon Sep 17 00:00:00 2001 From: Silarn Date: Wed, 18 Apr 2018 22:31:20 -0500 Subject: [PATCH 0550/1544] [game_ttw] Include custom profile mappings --- src/games/ttw/src/gamefalloutttw.cpp | 13 +++++++++++++ src/games/ttw/src/gamefalloutttw.h | 16 ++++++++++------ 2 files changed, 23 insertions(+), 6 deletions(-) diff --git a/src/games/ttw/src/gamefalloutttw.cpp b/src/games/ttw/src/gamefalloutttw.cpp index 1fe8b4dd..c8992419 100644 --- a/src/games/ttw/src/gamefalloutttw.cpp +++ b/src/games/ttw/src/gamefalloutttw.cpp @@ -193,3 +193,16 @@ QString GameFalloutTTW::identifyGamePath() const QString path = "Software\\Bethesda Softworks\\FalloutNV"; return findInRegistry(HKEY_LOCAL_MACHINE, path.toStdWString().c_str(), L"Installed Path"); } + +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 }); + } + + return result; +} \ No newline at end of file diff --git a/src/games/ttw/src/gamefalloutttw.h b/src/games/ttw/src/gamefalloutttw.h index 38c54729..babf356e 100644 --- a/src/games/ttw/src/gamefalloutttw.h +++ b/src/games/ttw/src/gamefalloutttw.h @@ -41,12 +41,16 @@ public: // IPluginGame interface public: // IPlugin interface - virtual QString name() const; - virtual QString author() const; - virtual QString description() const; - virtual MOBase::VersionInfo version() const; - virtual bool isActive() const; - virtual QList settings() const; + virtual QString name() const override; + virtual QString author() const override; + virtual QString description() const override; + virtual MOBase::VersionInfo version() const override; + virtual bool isActive() const override; + virtual QList settings() const override; + +public: // IPluginFileMapper interface + + virtual MappingType mappings() const override; protected: From 6e502c1b7f10f6d24b525b7d738ab6881ab8b34f Mon Sep 17 00:00:00 2001 From: Silarn Date: Thu, 19 Apr 2018 01:43:52 -0500 Subject: [PATCH 0551/1544] [game_fallout4vr] Remove remnants of QtScript and fix some CMake issues --- src/games/fallout4vr/src/CMakeLists.txt | 14 ++++++++------ 1 file changed, 8 insertions(+), 6 deletions(-) diff --git a/src/games/fallout4vr/src/CMakeLists.txt b/src/games/fallout4vr/src/CMakeLists.txt index 774f7067..ae7b8f70 100644 --- a/src/games/fallout4vr/src/CMakeLists.txt +++ b/src/games/fallout4vr/src/CMakeLists.txt @@ -49,17 +49,19 @@ ADD_LIBRARY(${PROJ_NAME} SHARED ${${PROJ_NAME}_HDRS} ${${PROJ_NAME}_SRCS} ${${PR TARGET_LINK_LIBRARIES(${PROJ_NAME} Qt5::Widgets ${Boost_LIBRARIES} - DbgHelp + DbgHelp uibase Version - liblz4 + liblz4 game_gamebryo) -IF(MSVC) +IF (MSVC) + SET_TARGET_PROPERTIES(${PROJ_NAME} PROPERTIES COMPILE_FLAGS "/std:c++latest") +ENDIF() +IF (MSVC AND CMAKE_SIZEOF_VOID_P EQUAL 4) + # 32 bits SET_TARGET_PROPERTIES(${PROJ_NAME} PROPERTIES LINK_FLAGS "/LARGEADDRESSAWARE") -ELSE(MSVC) - SET_TARGET_PROPERTIES(${PROJ_NAME} PROPERTIES LINK_FLAGS "-std=c++11") -ENDIF(MSVC) +ENDIF() IF (NOT "${OPTIMIZE_COMPILE_FLAGS}" STREQUAL "") SET_TARGET_PROPERTIES(${PROJ_NAME} PROPERTIES COMPILE_FLAGS_RELWITHDEBINFO ${OPTIMIZE_COMPILE_FLAGS}) From 149393093afb0ea02929146742d200730726115e Mon Sep 17 00:00:00 2001 From: Silarn Date: Thu, 19 Apr 2018 01:43:52 -0500 Subject: [PATCH 0552/1544] [game_morrowind] Remove remnants of QtScript and fix some CMake issues --- src/games/morrowind/src/CMakeLists.txt | 10 ++++++---- 1 file changed, 6 insertions(+), 4 deletions(-) diff --git a/src/games/morrowind/src/CMakeLists.txt b/src/games/morrowind/src/CMakeLists.txt index 1130bfa4..6ea551a9 100644 --- a/src/games/morrowind/src/CMakeLists.txt +++ b/src/games/morrowind/src/CMakeLists.txt @@ -56,11 +56,13 @@ TARGET_LINK_LIBRARIES(${PROJ_NAME} liblz4 version) -IF(MSVC) +IF (MSVC) + SET_TARGET_PROPERTIES(${PROJ_NAME} PROPERTIES COMPILE_FLAGS "/std:c++latest") +ENDIF() +IF (MSVC AND CMAKE_SIZEOF_VOID_P EQUAL 4) + # 32 bits SET_TARGET_PROPERTIES(${PROJ_NAME} PROPERTIES LINK_FLAGS "/LARGEADDRESSAWARE") -ELSE(MSVC) - SET_TARGET_PROPERTIES(${PROJ_NAME} PROPERTIES LINK_FLAGS "-std=c++11") -ENDIF(MSVC) +ENDIF() IF (NOT "${OPTIMIZE_COMPILE_FLAGS}" STREQUAL "") SET_TARGET_PROPERTIES(${PROJ_NAME} PROPERTIES COMPILE_FLAGS_RELWITHDEBINFO ${OPTIMIZE_COMPILE_FLAGS}) From c9b8e80aacacb3ef79f62a39b216a5cbd7645d4b Mon Sep 17 00:00:00 2001 From: Silarn Date: Thu, 19 Apr 2018 01:43:53 -0500 Subject: [PATCH 0553/1544] [game_falloutnv] Remove remnants of QtScript and fix some CMake issues --- src/games/falloutnv/src/CMakeLists.txt | 14 ++++++++------ 1 file changed, 8 insertions(+), 6 deletions(-) diff --git a/src/games/falloutnv/src/CMakeLists.txt b/src/games/falloutnv/src/CMakeLists.txt index 0cd515a1..faeaa98f 100644 --- a/src/games/falloutnv/src/CMakeLists.txt +++ b/src/games/falloutnv/src/CMakeLists.txt @@ -45,17 +45,19 @@ ADD_LIBRARY(${PROJ_NAME} SHARED ${${PROJ_NAME}_HDRS} ${${PROJ_NAME}_SRCS} ${${PR TARGET_LINK_LIBRARIES(${PROJ_NAME} Qt5::Widgets ${Boost_LIBRARIES} - DbgHelp + DbgHelp uibase game_gamebryo - liblz4 + liblz4 Version) -IF(MSVC) +IF (MSVC) + SET_TARGET_PROPERTIES(${PROJ_NAME} PROPERTIES COMPILE_FLAGS "/std:c++latest") +ENDIF() +IF (MSVC AND CMAKE_SIZEOF_VOID_P EQUAL 4) + # 32 bits SET_TARGET_PROPERTIES(${PROJ_NAME} PROPERTIES LINK_FLAGS "/LARGEADDRESSAWARE") -ELSE(MSVC) - SET_TARGET_PROPERTIES(${PROJ_NAME} PROPERTIES LINK_FLAGS "-std=c++11") -ENDIF(MSVC) +ENDIF() IF (NOT "${OPTIMIZE_COMPILE_FLAGS}" STREQUAL "") SET_TARGET_PROPERTIES(${PROJ_NAME} PROPERTIES COMPILE_FLAGS_RELWITHDEBINFO ${OPTIMIZE_COMPILE_FLAGS}) From 0c733128dc4884df47e99e9507ae04efc0fad55f Mon Sep 17 00:00:00 2001 From: Silarn Date: Thu, 19 Apr 2018 01:43:54 -0500 Subject: [PATCH 0554/1544] [game_fallout76] Remove remnants of QtScript and fix some CMake issues --- src/games/fallout76/src/CMakeLists.txt | 14 ++++++++------ 1 file changed, 8 insertions(+), 6 deletions(-) diff --git a/src/games/fallout76/src/CMakeLists.txt b/src/games/fallout76/src/CMakeLists.txt index f1f0ec8b..c9138d98 100644 --- a/src/games/fallout76/src/CMakeLists.txt +++ b/src/games/fallout76/src/CMakeLists.txt @@ -49,17 +49,19 @@ ADD_LIBRARY(${PROJ_NAME} SHARED ${${PROJ_NAME}_HDRS} ${${PROJ_NAME}_SRCS} ${${PR TARGET_LINK_LIBRARIES(${PROJ_NAME} Qt5::Widgets ${Boost_LIBRARIES} - DbgHelp + DbgHelp uibase Version - liblz4 + liblz4 game_gamebryo) -IF(MSVC) +IF (MSVC) + SET_TARGET_PROPERTIES(${PROJ_NAME} PROPERTIES COMPILE_FLAGS "/std:c++latest") +ENDIF() +IF (MSVC AND CMAKE_SIZEOF_VOID_P EQUAL 4) + # 32 bits SET_TARGET_PROPERTIES(${PROJ_NAME} PROPERTIES LINK_FLAGS "/LARGEADDRESSAWARE") -ELSE(MSVC) - SET_TARGET_PROPERTIES(${PROJ_NAME} PROPERTIES LINK_FLAGS "-std=c++11") -ENDIF(MSVC) +ENDIF() IF (NOT "${OPTIMIZE_COMPILE_FLAGS}" STREQUAL "") SET_TARGET_PROPERTIES(${PROJ_NAME} PROPERTIES COMPILE_FLAGS_RELWITHDEBINFO ${OPTIMIZE_COMPILE_FLAGS}) From 9a3639ecf0075aaa30641e9ddddd6a0b2f832d25 Mon Sep 17 00:00:00 2001 From: Silarn Date: Thu, 19 Apr 2018 01:43:54 -0500 Subject: [PATCH 0555/1544] [game_fallout4] Remove remnants of QtScript and fix some CMake issues --- src/games/fallout4/src/CMakeLists.txt | 14 ++++++++------ 1 file changed, 8 insertions(+), 6 deletions(-) diff --git a/src/games/fallout4/src/CMakeLists.txt b/src/games/fallout4/src/CMakeLists.txt index f1f0ec8b..c9138d98 100644 --- a/src/games/fallout4/src/CMakeLists.txt +++ b/src/games/fallout4/src/CMakeLists.txt @@ -49,17 +49,19 @@ ADD_LIBRARY(${PROJ_NAME} SHARED ${${PROJ_NAME}_HDRS} ${${PROJ_NAME}_SRCS} ${${PR TARGET_LINK_LIBRARIES(${PROJ_NAME} Qt5::Widgets ${Boost_LIBRARIES} - DbgHelp + DbgHelp uibase Version - liblz4 + liblz4 game_gamebryo) -IF(MSVC) +IF (MSVC) + SET_TARGET_PROPERTIES(${PROJ_NAME} PROPERTIES COMPILE_FLAGS "/std:c++latest") +ENDIF() +IF (MSVC AND CMAKE_SIZEOF_VOID_P EQUAL 4) + # 32 bits SET_TARGET_PROPERTIES(${PROJ_NAME} PROPERTIES LINK_FLAGS "/LARGEADDRESSAWARE") -ELSE(MSVC) - SET_TARGET_PROPERTIES(${PROJ_NAME} PROPERTIES LINK_FLAGS "-std=c++11") -ENDIF(MSVC) +ENDIF() IF (NOT "${OPTIMIZE_COMPILE_FLAGS}" STREQUAL "") SET_TARGET_PROPERTIES(${PROJ_NAME} PROPERTIES COMPILE_FLAGS_RELWITHDEBINFO ${OPTIMIZE_COMPILE_FLAGS}) From 0eaae11a04eb91d4bbe91c4e6333f126dccb538f Mon Sep 17 00:00:00 2001 From: Silarn Date: Thu, 19 Apr 2018 01:43:54 -0500 Subject: [PATCH 0556/1544] [game_skyrimvr] Remove remnants of QtScript and fix some CMake issues --- src/games/skyrimvr/src/CMakeLists.txt | 10 ++++++---- 1 file changed, 6 insertions(+), 4 deletions(-) diff --git a/src/games/skyrimvr/src/CMakeLists.txt b/src/games/skyrimvr/src/CMakeLists.txt index a88e92f4..e90ce67f 100644 --- a/src/games/skyrimvr/src/CMakeLists.txt +++ b/src/games/skyrimvr/src/CMakeLists.txt @@ -52,11 +52,13 @@ TARGET_LINK_LIBRARIES(${PROJ_NAME} liblz4 version) -IF(MSVC) +IF (MSVC) + SET_TARGET_PROPERTIES(${PROJ_NAME} PROPERTIES COMPILE_FLAGS "/std:c++latest") +ENDIF() +IF (MSVC AND CMAKE_SIZEOF_VOID_P EQUAL 4) + # 32 bits SET_TARGET_PROPERTIES(${PROJ_NAME} PROPERTIES LINK_FLAGS "/LARGEADDRESSAWARE") -ELSE(MSVC) - SET_TARGET_PROPERTIES(${PROJ_NAME} PROPERTIES LINK_FLAGS "-std=c++11") -ENDIF(MSVC) +ENDIF() IF (NOT "${OPTIMIZE_COMPILE_FLAGS}" STREQUAL "") SET_TARGET_PROPERTIES(${PROJ_NAME} PROPERTIES COMPILE_FLAGS_RELWITHDEBINFO ${OPTIMIZE_COMPILE_FLAGS}) From c87ef2f4cedc57e54ba53c5c6ee6eb668371d7fc Mon Sep 17 00:00:00 2001 From: Silarn Date: Thu, 19 Apr 2018 01:43:55 -0500 Subject: [PATCH 0557/1544] Remove remnants of QtScript and fix some CMake issues --- src/CMakeLists.txt | 12 +++++++----- 1 file changed, 7 insertions(+), 5 deletions(-) diff --git a/src/CMakeLists.txt b/src/CMakeLists.txt index 8f16b606..eae52991 100644 --- a/src/CMakeLists.txt +++ b/src/CMakeLists.txt @@ -41,14 +41,16 @@ TARGET_LINK_LIBRARIES(${PROJ_NAME} Qt5::Widgets ${Boost_LIBRARIES} uibase - liblz4 + liblz4 Version) -IF(MSVC) +IF (MSVC) + SET_TARGET_PROPERTIES(${PROJ_NAME} PROPERTIES COMPILE_FLAGS "/std:c++latest") +ENDIF() +IF (MSVC AND CMAKE_SIZEOF_VOID_P EQUAL 4) + # 32 bits SET_TARGET_PROPERTIES(${PROJ_NAME} PROPERTIES LINK_FLAGS "/LARGEADDRESSAWARE") -ELSE(MSVC) - SET_TARGET_PROPERTIES(${PROJ_NAME} PROPERTIES LINK_FLAGS "-std=c++11") -ENDIF(MSVC) +ENDIF() IF (NOT "${OPTIMIZE_COMPILE_FLAGS}" STREQUAL "") SET_TARGET_PROPERTIES(${PROJ_NAME} PROPERTIES COMPILE_FLAGS_RELWITHDEBINFO ${OPTIMIZE_COMPILE_FLAGS}) From 35a03da0938cd1aaa8a4a9bc346d6aad58b8d016 Mon Sep 17 00:00:00 2001 From: Silarn Date: Thu, 19 Apr 2018 01:43:55 -0500 Subject: [PATCH 0558/1544] [game_fallout3] Remove remnants of QtScript and fix some CMake issues --- src/games/fallout3/src/CMakeLists.txt | 14 ++++++++------ 1 file changed, 8 insertions(+), 6 deletions(-) diff --git a/src/games/fallout3/src/CMakeLists.txt b/src/games/fallout3/src/CMakeLists.txt index 0cd515a1..faeaa98f 100644 --- a/src/games/fallout3/src/CMakeLists.txt +++ b/src/games/fallout3/src/CMakeLists.txt @@ -45,17 +45,19 @@ ADD_LIBRARY(${PROJ_NAME} SHARED ${${PROJ_NAME}_HDRS} ${${PROJ_NAME}_SRCS} ${${PR TARGET_LINK_LIBRARIES(${PROJ_NAME} Qt5::Widgets ${Boost_LIBRARIES} - DbgHelp + DbgHelp uibase game_gamebryo - liblz4 + liblz4 Version) -IF(MSVC) +IF (MSVC) + SET_TARGET_PROPERTIES(${PROJ_NAME} PROPERTIES COMPILE_FLAGS "/std:c++latest") +ENDIF() +IF (MSVC AND CMAKE_SIZEOF_VOID_P EQUAL 4) + # 32 bits SET_TARGET_PROPERTIES(${PROJ_NAME} PROPERTIES LINK_FLAGS "/LARGEADDRESSAWARE") -ELSE(MSVC) - SET_TARGET_PROPERTIES(${PROJ_NAME} PROPERTIES LINK_FLAGS "-std=c++11") -ENDIF(MSVC) +ENDIF() IF (NOT "${OPTIMIZE_COMPILE_FLAGS}" STREQUAL "") SET_TARGET_PROPERTIES(${PROJ_NAME} PROPERTIES COMPILE_FLAGS_RELWITHDEBINFO ${OPTIMIZE_COMPILE_FLAGS}) From df8e1bea8d6a2ce8de5da1d3479e3a4fdb592355 Mon Sep 17 00:00:00 2001 From: Silarn Date: Thu, 19 Apr 2018 01:43:56 -0500 Subject: [PATCH 0559/1544] [game_skyrimse] Remove remnants of QtScript and fix some CMake issues --- src/games/skyrimse/src/CMakeLists.txt | 12 +++++++----- 1 file changed, 7 insertions(+), 5 deletions(-) diff --git a/src/games/skyrimse/src/CMakeLists.txt b/src/games/skyrimse/src/CMakeLists.txt index ad5c8dfa..e90ce67f 100644 --- a/src/games/skyrimse/src/CMakeLists.txt +++ b/src/games/skyrimse/src/CMakeLists.txt @@ -46,17 +46,19 @@ ADD_LIBRARY(${PROJ_NAME} SHARED ${${PROJ_NAME}_HDRS} ${${PROJ_NAME}_SRCS} ${${PR TARGET_LINK_LIBRARIES(${PROJ_NAME} Qt5::Widgets ${Boost_LIBRARIES} - DbgHelp + DbgHelp uibase game_gamebryo liblz4 version) -IF(MSVC) +IF (MSVC) + SET_TARGET_PROPERTIES(${PROJ_NAME} PROPERTIES COMPILE_FLAGS "/std:c++latest") +ENDIF() +IF (MSVC AND CMAKE_SIZEOF_VOID_P EQUAL 4) + # 32 bits SET_TARGET_PROPERTIES(${PROJ_NAME} PROPERTIES LINK_FLAGS "/LARGEADDRESSAWARE") -ELSE(MSVC) - SET_TARGET_PROPERTIES(${PROJ_NAME} PROPERTIES LINK_FLAGS "-std=c++11") -ENDIF(MSVC) +ENDIF() IF (NOT "${OPTIMIZE_COMPILE_FLAGS}" STREQUAL "") SET_TARGET_PROPERTIES(${PROJ_NAME} PROPERTIES COMPILE_FLAGS_RELWITHDEBINFO ${OPTIMIZE_COMPILE_FLAGS}) From 9362a7fb87f268dde68129bd1ee9acdda39b16e1 Mon Sep 17 00:00:00 2001 From: Silarn Date: Thu, 19 Apr 2018 01:43:56 -0500 Subject: [PATCH 0560/1544] [game_oblivion] Remove remnants of QtScript and fix some CMake issues --- src/games/oblivion/src/CMakeLists.txt | 14 ++++++++------ 1 file changed, 8 insertions(+), 6 deletions(-) diff --git a/src/games/oblivion/src/CMakeLists.txt b/src/games/oblivion/src/CMakeLists.txt index e3df2f60..81d0944e 100644 --- a/src/games/oblivion/src/CMakeLists.txt +++ b/src/games/oblivion/src/CMakeLists.txt @@ -45,17 +45,19 @@ ADD_LIBRARY(${PROJ_NAME} SHARED ${${PROJ_NAME}_HDRS} ${${PROJ_NAME}_SRCS} ${${PR TARGET_LINK_LIBRARIES(${PROJ_NAME} Qt5::Widgets ${Boost_LIBRARIES} - DbgHelp + DbgHelp uibase game_gamebryo - liblz4 + liblz4 version) -IF(MSVC) +IF (MSVC) + SET_TARGET_PROPERTIES(${PROJ_NAME} PROPERTIES COMPILE_FLAGS "/std:c++latest") +ENDIF() +IF (MSVC AND CMAKE_SIZEOF_VOID_P EQUAL 4) + # 32 bits SET_TARGET_PROPERTIES(${PROJ_NAME} PROPERTIES LINK_FLAGS "/LARGEADDRESSAWARE") -ELSE(MSVC) - SET_TARGET_PROPERTIES(${PROJ_NAME} PROPERTIES LINK_FLAGS "-std=c++11") -ENDIF(MSVC) +ENDIF() IF (NOT "${OPTIMIZE_COMPILE_FLAGS}" STREQUAL "") SET_TARGET_PROPERTIES(${PROJ_NAME} PROPERTIES COMPILE_FLAGS_RELWITHDEBINFO ${OPTIMIZE_COMPILE_FLAGS}) From d01c067536e39d00d164843d3dddf5c53248af97 Mon Sep 17 00:00:00 2001 From: Silarn Date: Thu, 19 Apr 2018 01:43:58 -0500 Subject: [PATCH 0561/1544] [game_skyrim] Remove remnants of QtScript and fix some CMake issues --- src/games/skyrim/src/CMakeLists.txt | 14 ++++++++------ 1 file changed, 8 insertions(+), 6 deletions(-) diff --git a/src/games/skyrim/src/CMakeLists.txt b/src/games/skyrim/src/CMakeLists.txt index 38d13578..e9369a1b 100644 --- a/src/games/skyrim/src/CMakeLists.txt +++ b/src/games/skyrim/src/CMakeLists.txt @@ -46,17 +46,19 @@ ADD_LIBRARY(${PROJ_NAME} SHARED ${${PROJ_NAME}_HDRS} ${${PROJ_NAME}_SRCS} ${${PR TARGET_LINK_LIBRARIES(${PROJ_NAME} Qt5::Widgets ${Boost_LIBRARIES} - DbgHelp + DbgHelp uibase game_gamebryo - liblz4 + liblz4 version) -IF(MSVC) +IF (MSVC) + SET_TARGET_PROPERTIES(${PROJ_NAME} PROPERTIES COMPILE_FLAGS "/std:c++latest") +ENDIF() +IF (MSVC AND CMAKE_SIZEOF_VOID_P EQUAL 4) + # 32 bits SET_TARGET_PROPERTIES(${PROJ_NAME} PROPERTIES LINK_FLAGS "/LARGEADDRESSAWARE") -ELSE(MSVC) - SET_TARGET_PROPERTIES(${PROJ_NAME} PROPERTIES LINK_FLAGS "-std=c++11") -ENDIF(MSVC) +ENDIF() IF (NOT "${OPTIMIZE_COMPILE_FLAGS}" STREQUAL "") SET_TARGET_PROPERTIES(${PROJ_NAME} PROPERTIES COMPILE_FLAGS_RELWITHDEBINFO ${OPTIMIZE_COMPILE_FLAGS}) From 96a1ca9bee06fc488a8c5db666bedf47a40bb3ed Mon Sep 17 00:00:00 2001 From: Silarn Date: Thu, 19 Apr 2018 01:43:59 -0500 Subject: [PATCH 0562/1544] [game_ttw] Remove remnants of QtScript and fix some CMake issues --- src/games/ttw/src/CMakeLists.txt | 14 ++++++++------ 1 file changed, 8 insertions(+), 6 deletions(-) diff --git a/src/games/ttw/src/CMakeLists.txt b/src/games/ttw/src/CMakeLists.txt index 0cd515a1..faeaa98f 100644 --- a/src/games/ttw/src/CMakeLists.txt +++ b/src/games/ttw/src/CMakeLists.txt @@ -45,17 +45,19 @@ ADD_LIBRARY(${PROJ_NAME} SHARED ${${PROJ_NAME}_HDRS} ${${PROJ_NAME}_SRCS} ${${PR TARGET_LINK_LIBRARIES(${PROJ_NAME} Qt5::Widgets ${Boost_LIBRARIES} - DbgHelp + DbgHelp uibase game_gamebryo - liblz4 + liblz4 Version) -IF(MSVC) +IF (MSVC) + SET_TARGET_PROPERTIES(${PROJ_NAME} PROPERTIES COMPILE_FLAGS "/std:c++latest") +ENDIF() +IF (MSVC AND CMAKE_SIZEOF_VOID_P EQUAL 4) + # 32 bits SET_TARGET_PROPERTIES(${PROJ_NAME} PROPERTIES LINK_FLAGS "/LARGEADDRESSAWARE") -ELSE(MSVC) - SET_TARGET_PROPERTIES(${PROJ_NAME} PROPERTIES LINK_FLAGS "-std=c++11") -ENDIF(MSVC) +ENDIF() IF (NOT "${OPTIMIZE_COMPILE_FLAGS}" STREQUAL "") SET_TARGET_PROPERTIES(${PROJ_NAME} PROPERTIES COMPILE_FLAGS_RELWITHDEBINFO ${OPTIMIZE_COMPILE_FLAGS}) From 48a3d057b1f16cf69e3f37bea000ad022746c479 Mon Sep 17 00:00:00 2001 From: Silarn Date: Mon, 30 Apr 2018 16:38:17 -0500 Subject: [PATCH 0563/1544] Unify spacing and fix memory leak in compressed data reader --- src/gamebryosavegame.cpp | 334 ++++++++++++++--------------- src/gamebryosavegame.h | 64 +++--- src/gamebryosavegameinfowidget.cpp | 2 +- 3 files changed, 198 insertions(+), 202 deletions(-) diff --git a/src/gamebryosavegame.cpp b/src/gamebryosavegame.cpp index b58e8f2b..272264a7 100644 --- a/src/gamebryosavegame.cpp +++ b/src/gamebryosavegame.cpp @@ -58,7 +58,7 @@ QStringList GamebryoSaveGame::allFiles() const QFileInfo SEfile(file.absolutePath() + "/" + file.completeBaseName() + "." + m_Game->savegameSEExtension()); if (SEfile.exists()) { - res.push_back(SEfile.absoluteFilePath()); + res.push_back(SEfile.absoluteFilePath()); } } return res; @@ -66,9 +66,9 @@ QStringList GamebryoSaveGame::allFiles() const bool GamebryoSaveGame::hasScriptExtenderFile() const { - QFileInfo file(m_FileName); - QFileInfo SEfile(file.absolutePath() + "/" + file.completeBaseName() + "." + m_Game->savegameSEExtension()); - return SEfile.exists(); + QFileInfo file(m_FileName); + QFileInfo SEfile(file.absolutePath() + "/" + file.completeBaseName() + "." + m_Game->savegameSEExtension()); + return SEfile.exists(); } void GamebryoSaveGame::setCreationTime(_SYSTEMTIME const &ctime) @@ -99,7 +99,7 @@ GamebryoSaveGame::FileWrapper::FileWrapper(GamebryoSaveGame *game, QString id(fileID.data()); if (expected != id) { throw std::runtime_error( - QObject::tr("wrong file format - expected %1 got %2").arg(expected).arg(id).toUtf8().constData()); + QObject::tr("wrong file format - expected %1 got %2").arg(expected).arg(id).toUtf8().constData()); } } @@ -110,7 +110,7 @@ void GamebryoSaveGame::FileWrapper::setHasFieldMarkers(bool state) void GamebryoSaveGame::FileWrapper::setPluginString(StringType type) { - m_PluginString = type; + m_PluginString = type; } template <> void GamebryoSaveGame::FileWrapper::read(QString &value) @@ -125,15 +125,15 @@ template <> void GamebryoSaveGame::FileWrapper::read(QString &value) } if (m_HasFieldMarkers) { - skip(); + skip(); } char *buffer = new char[length]; - read(buffer, m_PluginString == StringType::TYPE_BZSTRING ? length-1 : length); - + read(buffer, m_PluginString == StringType::TYPE_BZSTRING ? length - 1 : length); + if (m_PluginString == StringType::TYPE_BZSTRING) - buffer[length-1] = '\0'; + buffer[length - 1] = '\0'; if (m_HasFieldMarkers) { skip(); @@ -167,9 +167,9 @@ void GamebryoSaveGame::FileWrapper::readImage(unsigned long width, unsigned long QScopedArrayPointer buffer(new unsigned char[width * height * bpp]); read(buffer.data(), width * height * bpp); QImage image(buffer.data(), width, height, alpha ? QImage::Format_RGBA8888_Premultiplied - : QImage::Format_RGB888); + : QImage::Format_RGB888); if (scale != 0) { - m_Game->m_Screenshot = image.copy().scaledToWidth(scale); + m_Game->m_Screenshot = image.copy().scaledToWidth(scale); } else { // why do I have to copy here? without the copy, the buffer seems to get // deleted after the temporary vanishes, but shouldn't Qts implicit sharing @@ -177,15 +177,15 @@ void GamebryoSaveGame::FileWrapper::readImage(unsigned long width, unsigned long m_Game->m_Screenshot = image.copy(); } } -void readQDataStream(QDataStream &data, void *buff, std::size_t length){ - int read = data.readRawData(static_cast(buff), static_cast(length)); +void readQDataStream(QDataStream &data, void *buff, std::size_t length) { + int read = data.readRawData(static_cast(buff), static_cast(length)); if (read != length) { throw std::runtime_error("unexpected end of file"); } } -template void readQDataStream(QDataStream &data,T &value){ - int read = data.readRawData(reinterpret_cast(&value),sizeof(T)); - if (read != sizeof(T)) { +template void readQDataStream(QDataStream &data, T &value) { + int read = data.readRawData(reinterpret_cast(&value), sizeof(T)); + if (read != sizeof(T)) { throw std::runtime_error("unexpected end of file"); } } @@ -193,7 +193,7 @@ template void readQDataStream(QDataStream &data,T &value){ template <> void readQDataStream(QDataStream &data, QString &value) { unsigned short length; - readQDataStream(data,length); + readQDataStream(data, length); std::vector buffer(length); @@ -204,191 +204,185 @@ template <> void readQDataStream(QDataStream &data, QString &value) void GamebryoSaveGame::FileWrapper::closeCompressedData() { - if (m_Game->m_CompressionType == 0) { - } - else if (m_Game->m_CompressionType == 1) { - m_Game->m_Plugins.push_back("Please create an issue on the MO github labeled \"Found zlib Compressed\" with your savefile attached"); - } - else if (m_Game->m_CompressionType == 2) { - delete m_Data; - } - else - m_Game->m_Plugins.push_back("Please create an issue on the MO github labeled \"Found unknown Compressed\" with your savefile attached"); + if (m_Game->m_CompressionType == 0) { + } + else if (m_Game->m_CompressionType == 1) { + m_Game->m_Plugins.push_back("Please create an issue on the MO github labeled \"Found zlib Compressed\" with your savefile attached"); + } + else if (m_Game->m_CompressionType == 2) { + m_Data->device()->close(); + delete m_Data; + } + else + m_Game->m_Plugins.push_back("Please create an issue on the MO github labeled \"Found unknown Compressed\" with your savefile attached"); } bool GamebryoSaveGame::FileWrapper::openCompressedData(int bytesToIgnore) { - if (m_Game->m_CompressionType == 0) { - if (bytesToIgnore>0)//Just to make certain - skip(bytesToIgnore); - return false; - } - else if (m_Game->m_CompressionType == 1) { - m_Game->m_Plugins.push_back("Please create an issue on the MO github labeled \"Found zlib Compressed\" with your savefile attached"); - return false; - } - else if (m_Game->m_CompressionType == 2) { - uint32_t uncompressedSize; - read(uncompressedSize); - uint32_t compressedSize; - read(compressedSize); - char* compressed = new char[compressedSize]; - read(compressed, compressedSize); - char * decompressed = new char[uncompressedSize]; - LZ4_decompress_safe_partial(compressed, decompressed, compressedSize, uncompressedSize, uncompressedSize); - delete[] compressed; + if (m_Game->m_CompressionType == 0) { + if (bytesToIgnore>0)//Just to make certain + skip(bytesToIgnore); + return false; + } else if (m_Game->m_CompressionType == 1) { + m_Game->m_Plugins.push_back("Please create an issue on the MO github labeled \"Found zlib Compressed\" with your savefile attached"); + return false; + } else if (m_Game->m_CompressionType == 2) { + uint32_t uncompressedSize; + read(uncompressedSize); + uint32_t compressedSize; + read(compressedSize); + QByteArray compressed; + compressed.resize(compressedSize); + read(compressed.data(), compressedSize); + QByteArray decompressed; + decompressed.resize(uncompressedSize); + LZ4_decompress_safe_partial(compressed.data(), decompressed.data(), compressedSize, uncompressedSize, uncompressedSize); + compressed.clear(); - m_Data = new QDataStream(QByteArray(decompressed, uncompressedSize)); - m_Data->skipRawData(bytesToIgnore); + m_Data = new QDataStream(decompressed); + m_Data->skipRawData(bytesToIgnore); - return true; - } - else { - m_Game->m_Plugins.push_back("Please create an issue on the MO github labeled \"Found unknown Compressed\" with your savefile attached"); - return false; - } + return true; + } else { + m_Game->m_Plugins.push_back("Please create an issue on the MO github labeled \"Found unknown Compressed\" with your savefile attached"); + return false; + } } uint8_t GamebryoSaveGame::FileWrapper::readChar(int bytesToIgnore) { - if (m_Game->m_CompressionType == 0) { - if (bytesToIgnore>0)//Just to make certain - skip(bytesToIgnore); - uint8_t version; - read(version); - return version; - } - else if (m_Game->m_CompressionType == 1) { - m_Game->m_Plugins.push_back("Please create an issue on the MO github labeled \"Found zlib Compressed\" with your savefile attached"); - return 0; - } - else if (m_Game->m_CompressionType == 2) { - // decompression already done by readSaveGameVersion - m_Data->skipRawData(bytesToIgnore); + if (m_Game->m_CompressionType == 0) { + if (bytesToIgnore>0)//Just to make certain + skip(bytesToIgnore); + uint8_t version; + read(version); + return version; + } else if (m_Game->m_CompressionType == 1) { + m_Game->m_Plugins.push_back("Please create an issue on the MO github labeled \"Found zlib Compressed\" with your savefile attached"); + return 0; + } else if (m_Game->m_CompressionType == 2) { + // decompression already done by readSaveGameVersion + m_Data->skipRawData(bytesToIgnore); - uint8_t version; - readQDataStream(*m_Data, version); - return version; + uint8_t version; + readQDataStream(*m_Data, version); + return version; - } - else { - m_Game->m_Plugins.push_back("Please create an issue on the MO github labeled \"Found unknown Compressed\" with your savefile attached"); - return 0; - } + } else { + m_Game->m_Plugins.push_back("Please create an issue on the MO github labeled \"Found unknown Compressed\" with your savefile attached"); + return 0; + } } uint16_t GamebryoSaveGame::FileWrapper::readShort(int bytesToIgnore) { - if (m_Game->m_CompressionType == 0) { - if (bytesToIgnore>0)//Just to make certain - skip(bytesToIgnore); - uint16_t size; - read(size); - return size; - } - else if (m_Game->m_CompressionType == 1) { - m_Game->m_Plugins.push_back("Please create an issue on the MO github labeled \"Found zlib Compressed\" with your savefile attached"); - return 0; - } - else if (m_Game->m_CompressionType == 2) { - // decompression already done by readSaveGameVersion - m_Data->skipRawData(bytesToIgnore); + if (m_Game->m_CompressionType == 0) { + if (bytesToIgnore>0)//Just to make certain + skip(bytesToIgnore); + uint16_t size; + read(size); + return size; + } else if (m_Game->m_CompressionType == 1) { + m_Game->m_Plugins.push_back("Please create an issue on the MO github labeled \"Found zlib Compressed\" with your savefile attached"); + return 0; + } else if (m_Game->m_CompressionType == 2) { + // decompression already done by readSaveGameVersion + m_Data->skipRawData(bytesToIgnore); - uint16_t size; - readQDataStream(*m_Data, size); - return size; - } - else { - m_Game->m_Plugins.push_back("Please create an issue on the MO github labeled \"Found unknown Compressed\" with your savefile attached"); - return 0; - } + uint16_t size; + readQDataStream(*m_Data, size); + return size; + } else { + m_Game->m_Plugins.push_back("Please create an issue on the MO github labeled \"Found unknown Compressed\" with your savefile attached"); + return 0; + } } uint32_t GamebryoSaveGame::FileWrapper::readInt(int bytesToIgnore) { - if (m_Game->m_CompressionType == 0) { - if (bytesToIgnore>0)//Just to make certain - skip(bytesToIgnore); - uint32_t size; - read(size); - return size; - } - else if (m_Game->m_CompressionType == 1) { - m_Game->m_Plugins.push_back("Please create an issue on the MO github labeled \"Found zlib Compressed\" with your savefile attached"); - return 0; - } - else if (m_Game->m_CompressionType == 2) { - // decompression already done by readSaveGameVersion - m_Data->skipRawData(bytesToIgnore); + if (m_Game->m_CompressionType == 0) { + if (bytesToIgnore>0)//Just to make certain + skip(bytesToIgnore); + uint32_t size; + read(size); + return size; + } else if (m_Game->m_CompressionType == 1) { + m_Game->m_Plugins.push_back("Please create an issue on the MO github labeled \"Found zlib Compressed\" with your savefile attached"); + return 0; + } else if (m_Game->m_CompressionType == 2) { + // decompression already done by readSaveGameVersion + m_Data->skipRawData(bytesToIgnore); - uint32_t size; - readQDataStream(*m_Data, size); - return size; - } - else { - m_Game->m_Plugins.push_back("Please create an issue on the MO github labeled \"Found unknown Compressed\" with your savefile attached"); - return 0; - } + uint32_t size; + readQDataStream(*m_Data, size); + return size; + } else { + m_Game->m_Plugins.push_back("Please create an issue on the MO github labeled \"Found unknown Compressed\" with your savefile attached"); + return 0; + } } void GamebryoSaveGame::FileWrapper::readPlugins(int bytesToIgnore) { - if(m_Game->m_CompressionType ==0){ - if(bytesToIgnore>0)//Just to make certain - skip(bytesToIgnore); - uint8_t count; - read(count); - uint16_t finalCount = count; - m_Game->m_Plugins.reserve(finalCount); + if (m_Game->m_CompressionType == 0) { + if (bytesToIgnore>0)//Just to make certain + skip(bytesToIgnore); + uint8_t count; + read(count); + uint16_t finalCount = count; + m_Game->m_Plugins.reserve(finalCount); for (std::size_t i = 0; i < finalCount; ++i) { - QString name; - read(name); - m_Game->m_Plugins.push_back(name); + QString name; + read(name); + m_Game->m_Plugins.push_back(name); + } + } else if (m_Game->m_CompressionType == 1) { + m_Game->m_Plugins.push_back("Please create an issue on the MO github labeled \"Found zlib Compressed\" with your savefile attached"); + } else if (m_Game->m_CompressionType == 2) { + m_Data->skipRawData(bytesToIgnore); + uint8_t count; + readQDataStream(*m_Data, count); + uint16_t finalCount = count; + m_Game->m_Plugins.reserve(finalCount); + for (std::size_t i = 0; im_Plugins.push_back(name); } - } else if (m_Game->m_CompressionType ==1) { - m_Game->m_Plugins.push_back("Please create an issue on the MO github labeled \"Found zlib Compressed\" with your savefile attached"); - } else if (m_Game->m_CompressionType ==2) { - m_Data->skipRawData(bytesToIgnore); - uint8_t count; - readQDataStream(*m_Data, count); - uint16_t finalCount = count; - m_Game->m_Plugins.reserve(finalCount); - for(std::size_t i=0;im_Plugins.push_back(name); - } } } void GamebryoSaveGame::FileWrapper::readLightPlugins(int bytesToIgnore) { - if (m_Game->m_CompressionType == 0) { - if (bytesToIgnore>0)//Just to make certain - skip(bytesToIgnore); - uint16_t count; - read(count); - m_Game->m_LightPlugins.reserve(count); - for (std::size_t i = 0; i < count; ++i) { - QString name; - read(name); - m_Game->m_LightPlugins.push_back(name); - } - } - else if (m_Game->m_CompressionType == 1) { - m_Game->m_Plugins.push_back("Please create an issue on the MO github labeled \"Found zlib Compressed\" with your savefile attached"); - } - else if (m_Game->m_CompressionType == 2) { - m_Data->skipRawData(bytesToIgnore); + if (m_Game->m_CompressionType == 0) { + if (bytesToIgnore>0)//Just to make certain + skip(bytesToIgnore); + uint16_t count; + read(count); + m_Game->m_LightPlugins.reserve(count); + for (std::size_t i = 0; i < count; ++i) { + QString name; + read(name); + m_Game->m_LightPlugins.push_back(name); + } + } else if (m_Game->m_CompressionType == 1) { + m_Game->m_Plugins.push_back("Please create an issue on the MO github labeled \"Found zlib Compressed\" with your savefile attached"); + } else if (m_Game->m_CompressionType == 2) { + m_Data->skipRawData(bytesToIgnore); - uint16_t count; - readQDataStream(*m_Data, count); - m_Game->m_LightPlugins.reserve(count); - for (std::size_t i = 0; im_LightPlugins.push_back(name); - } + uint16_t count; + readQDataStream(*m_Data, count); + m_Game->m_LightPlugins.reserve(count); + for (std::size_t i = 0; im_LightPlugins.push_back(name); + } - } + } } + +void GamebryoSaveGame::FileWrapper::close() +{ + m_File.close(); +} \ No newline at end of file diff --git a/src/gamebryosavegame.h b/src/gamebryosavegame.h index 6f7956b3..28e21aa8 100644 --- a/src/gamebryosavegame.h +++ b/src/gamebryosavegame.h @@ -45,9 +45,9 @@ public: enum StringType { - TYPE_BZSTRING, - TYPE_BSTRING, - TYPE_WSTRING + TYPE_BZSTRING, + TYPE_BSTRING, + TYPE_WSTRING }; protected: @@ -58,17 +58,17 @@ protected: { public: /** Construct the save file information. - * @params expected - expect bytes at start of file - **/ + * @params expected - expect bytes at start of file + **/ FileWrapper(GamebryoSaveGame *game, QString const &expected); /** Set this for save games that have a marker at the end of each - * field. Specifically fallout - **/ + * field. Specifically fallout + **/ void setHasFieldMarkers(bool); /** Set bz string mode (1 byte length, null terminated) - **/ + **/ void setPluginString(StringType); template void skip(int count = 1) @@ -89,51 +89,53 @@ protected: } } - void seek(unsigned long pos) - { - if (!m_File.seek(pos - m_File.pos())) { - throw std::runtime_error("unexpected end of file"); - } - } + void seek(unsigned long pos) + { + if (!m_File.seek(pos - m_File.pos())) { + throw std::runtime_error("unexpected end of file"); + } + } void read(void *buff, std::size_t length); /* Reads RGB image from save - * Assumes picture dimentions come immediately before the save - */ + * Assumes picture dimentions come immediately before the save + */ void readImage(int scale = 0, bool alpha = false); /* Reads RGB image from save */ void readImage(unsigned long width, unsigned long height, int scale = 0, bool alpha = false); - /* uncompress the begining of the compressed block */ - bool openCompressedData(int bytesToIgnore = 0); + /* uncompress the begining of the compressed block */ + bool openCompressedData(int bytesToIgnore = 0); - /* frees the uncompressed block */ - void closeCompressedData(); + /* frees the uncompressed block */ + void closeCompressedData(); - /* Read the save game version in the compressed block */ - uint8_t readChar(int bytesToIgnore=0); + /* Read the save game version in the compressed block */ + uint8_t readChar(int bytesToIgnore = 0); - uint16_t readShort(int bytesToIgnore = 0); + uint16_t readShort(int bytesToIgnore = 0); - uint32_t readInt(int bytesToIgnore = 0); + uint32_t readInt(int bytesToIgnore = 0); - /* Read the plugin list */ - void readPlugins(int bytesToIgnore=0); + /* Read the plugin list */ + void readPlugins(int bytesToIgnore = 0); - /* Read the light plugin list */ - void readLightPlugins(int bytesToIgnore = 0); + /* Read the light plugin list */ + void readLightPlugins(int bytesToIgnore = 0); - /* Set the creation time from a system date */ + /* Set the creation time from a system date */ void setCreationTime(::_SYSTEMTIME const &); + void close(); + private: GamebryoSaveGame *m_Game; QFile m_File; bool m_HasFieldMarkers; - StringType m_PluginString; - QDataStream* m_Data; + StringType m_PluginString; + QDataStream *m_Data; }; void setCreationTime(_SYSTEMTIME const &time); diff --git a/src/gamebryosavegameinfowidget.cpp b/src/gamebryosavegameinfowidget.cpp index d003c5b2..dda5a5bb 100644 --- a/src/gamebryosavegameinfowidget.cpp +++ b/src/gamebryosavegameinfowidget.cpp @@ -44,7 +44,7 @@ GamebryoSaveGameInfoWidget::~GamebryoSaveGameInfoWidget() { } void GamebryoSaveGameInfoWidget::setSave(QString const &file) { - std::unique_ptr < GamebryoSaveGame const> save( + std::unique_ptr save( std::move(dynamic_cast(m_Info->getSaveGameInfo(file)))); ui->saveNumLabel->setText(QString("%1").arg(save->getSaveNumber())); ui->characterLabel->setText(save->getPCName()); From 3d1dafc639268e9fd6f9911c6e2573381174b133 Mon Sep 17 00:00:00 2001 From: Silarn Date: Mon, 30 Apr 2018 16:38:57 -0500 Subject: [PATCH 0564/1544] [game_skyrimse] Unify whitespace --- src/games/skyrimse/src/skyrimsesavegame.cpp | 94 ++++++++++----------- 1 file changed, 47 insertions(+), 47 deletions(-) diff --git a/src/games/skyrimse/src/skyrimsesavegame.cpp b/src/games/skyrimse/src/skyrimsesavegame.cpp index dbc4f100..6c209043 100644 --- a/src/games/skyrimse/src/skyrimsesavegame.cpp +++ b/src/games/skyrimse/src/skyrimsesavegame.cpp @@ -5,69 +5,69 @@ SkyrimSESaveGame::SkyrimSESaveGame(QString const &fileName, MOBase::IPluginGame const *game, bool const lightEnabled) : GamebryoSaveGame(fileName, game, lightEnabled) { - FileWrapper file(this, "TESV_SAVEGAME"); //10bytes - unsigned long headerSize; - file.read(headerSize); // header size "TESV_SAVEGAME" - file.skip(); // header version 74. Original Skyrim is 79 - file.read(m_SaveNumber); + FileWrapper file(this, "TESV_SAVEGAME"); //10bytes + unsigned long headerSize; + file.read(headerSize); // header size "TESV_SAVEGAME" + file.skip(); // header version 74. Original Skyrim is 79 + file.read(m_SaveNumber); - file.read(m_PCName); + file.read(m_PCName); - unsigned long temp; - file.read(temp); - m_PCLevel = static_cast(temp); + unsigned long temp; + file.read(temp); + m_PCLevel = static_cast(temp); - file.read(m_PCLocation); + file.read(m_PCLocation); - QString timeOfDay; - file.read(timeOfDay); + QString timeOfDay; + file.read(timeOfDay); - QString race; - file.read(race); // race name (i.e. BretonRace) + QString race; + file.read(race); // race name (i.e. BretonRace) - file.skip(); // Player gender (0 = male) - file.skip(2); // experience gathered, experience required + file.skip(); // Player gender (0 = male) + file.skip(2); // experience gathered, experience required - FILETIME ftime; - file.read(ftime); //filetime - //A file time is a 64-bit value that represents the number of 100-nanosecond - //intervals that have elapsed since 12:00 A.M. January 1, 1601 Coordinated Universal Time (UTC). - //So we need to convert that to something useful + FILETIME ftime; + file.read(ftime); //filetime + //A file time is a 64-bit value that represents the number of 100-nanosecond + //intervals that have elapsed since 12:00 A.M. January 1, 1601 Coordinated Universal Time (UTC). + //So we need to convert that to something useful - //For some reason, the file time is off by about 6 hours. - //So we need to subtract those 6 hours from the filetime. - _ULARGE_INTEGER time; - time.LowPart=ftime.dwLowDateTime; - time.HighPart=ftime.dwHighDateTime; - time.QuadPart-=2.16e11; - ftime.dwHighDateTime=time.HighPart; - ftime.dwLowDateTime=time.LowPart; + //For some reason, the file time is off by about 6 hours. + //So we need to subtract those 6 hours from the filetime. + _ULARGE_INTEGER time; + time.LowPart = ftime.dwLowDateTime; + time.HighPart = ftime.dwHighDateTime; + time.QuadPart -= 2.16e11; + ftime.dwHighDateTime = time.HighPart; + ftime.dwLowDateTime = time.LowPart; - SYSTEMTIME ctime; - ::FileTimeToSystemTime(&ftime, &ctime); + SYSTEMTIME ctime; + ::FileTimeToSystemTime(&ftime, &ctime); - setCreationTime(ctime); + setCreationTime(ctime); - unsigned long width; - unsigned long height; - file.read(width); - file.read(height); + unsigned long width; + unsigned long height; + file.read(width); + file.read(height); - file.read(m_CompressionType); + file.read(m_CompressionType); - file.readImage(width,height,320,true); + file.readImage(width, height, 320, true); - file.openCompressedData(); + file.openCompressedData(); - uint8_t saveGameVersion = file.readChar(); - uint8_t pluginInfoSize = file.readChar(); - uint16_t other = file.readShort(); //Unknown + uint8_t saveGameVersion = file.readChar(); + uint8_t pluginInfoSize = file.readChar(); + uint16_t other = file.readShort(); //Unknown - file.readPlugins(1); // Just empty data + file.readPlugins(1); // Just empty data - if (saveGameVersion >= 78) { - file.readLightPlugins(); - } + if (saveGameVersion >= 78) { + file.readLightPlugins(); + } - file.closeCompressedData(); + file.closeCompressedData(); } From a3ca36ed05b8b90f2aca5d79e9a4db403c004f49 Mon Sep 17 00:00:00 2001 From: Silarn Date: Mon, 30 Apr 2018 19:05:44 -0500 Subject: [PATCH 0565/1544] Support reading UTF8 strings from saves --- src/gamebryosavegame.cpp | 9 ++++----- 1 file changed, 4 insertions(+), 5 deletions(-) diff --git a/src/gamebryosavegame.cpp b/src/gamebryosavegame.cpp index 272264a7..544ba127 100644 --- a/src/gamebryosavegame.cpp +++ b/src/gamebryosavegame.cpp @@ -128,9 +128,10 @@ template <> void GamebryoSaveGame::FileWrapper::read(QString &value) skip(); } - char *buffer = new char[length]; + QByteArray buffer; + buffer.resize(length); - read(buffer, m_PluginString == StringType::TYPE_BZSTRING ? length - 1 : length); + read(buffer.data(), m_PluginString == StringType::TYPE_BZSTRING ? length - 1 : length); if (m_PluginString == StringType::TYPE_BZSTRING) buffer[length - 1] = '\0'; @@ -139,9 +140,7 @@ template <> void GamebryoSaveGame::FileWrapper::read(QString &value) skip(); } - value = QString::fromLatin1(buffer, length); - - delete buffer; + value = QString::fromUtf8(buffer.constData()); } void GamebryoSaveGame::FileWrapper::read(void *buff, std::size_t length) From 5f5671487215b0b66eab4519f305fa3cc0e985de Mon Sep 17 00:00:00 2001 From: Silarn Date: Tue, 1 May 2018 16:59:34 -0500 Subject: [PATCH 0566/1544] [game_fallout4vr] Update translation files --- src/games/fallout4vr/src/game_fallout4vr_en.ts | 8 +++----- 1 file changed, 3 insertions(+), 5 deletions(-) diff --git a/src/games/fallout4vr/src/game_fallout4vr_en.ts b/src/games/fallout4vr/src/game_fallout4vr_en.ts index 60dde6cf..d6c8c5ca 100644 --- a/src/games/fallout4vr/src/game_fallout4vr_en.ts +++ b/src/games/fallout4vr/src/game_fallout4vr_en.ts @@ -4,7 +4,7 @@ GameFallout4VR - + Adds support for the game Fallout 4 VR. Splash by %1 @@ -68,14 +68,12 @@ Splash by %1 - - + failed to query registry path (preflight): %1 - - + failed to query registry path (read): %1 From dd759af6ffc629c81624a2147c03b6904801fcc7 Mon Sep 17 00:00:00 2001 From: Silarn Date: Tue, 1 May 2018 16:59:35 -0500 Subject: [PATCH 0567/1544] [game_falloutnv] Update translation files --- src/games/falloutnv/src/game_falloutNV_en.ts | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/games/falloutnv/src/game_falloutNV_en.ts b/src/games/falloutnv/src/game_falloutNV_en.ts index b3ba02aa..169797c9 100644 --- a/src/games/falloutnv/src/game_falloutNV_en.ts +++ b/src/games/falloutnv/src/game_falloutNV_en.ts @@ -91,12 +91,12 @@ - + failed to query registry path (preflight): %1 - + failed to query registry path (read): %1 From 69e7596b5606bad850ac243e6d00867845fa1bdd Mon Sep 17 00:00:00 2001 From: Silarn Date: Tue, 1 May 2018 16:59:35 -0500 Subject: [PATCH 0568/1544] [game_fallout3] Update translation files --- src/games/fallout3/src/game_fallout3_en.ts | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/games/fallout3/src/game_fallout3_en.ts b/src/games/fallout3/src/game_fallout3_en.ts index 67b7b320..f0f579ca 100644 --- a/src/games/fallout3/src/game_fallout3_en.ts +++ b/src/games/fallout3/src/game_fallout3_en.ts @@ -91,12 +91,12 @@ - + failed to query registry path (preflight): %1 - + failed to query registry path (read): %1 From b7258d6e77a33b07f6c9a0fb5ea8a7adf893852c Mon Sep 17 00:00:00 2001 From: Silarn Date: Tue, 1 May 2018 16:59:36 -0500 Subject: [PATCH 0569/1544] [game_fallout76] Update translation files --- src/games/fallout76/src/game_fallout4_en.ts | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/src/games/fallout76/src/game_fallout4_en.ts b/src/games/fallout76/src/game_fallout4_en.ts index dddeac6c..5e48c096 100644 --- a/src/games/fallout76/src/game_fallout4_en.ts +++ b/src/games/fallout76/src/game_fallout4_en.ts @@ -4,7 +4,7 @@ GameFallout4 - + Adds support for the game Fallout 4. Splash by %1 @@ -93,12 +93,12 @@ Splash by %1 - + failed to query registry path (preflight): %1 - + failed to query registry path (read): %1 From 2b30e49c481ad26b64cd1204a1753a6908e6ae8e Mon Sep 17 00:00:00 2001 From: Silarn Date: Tue, 1 May 2018 16:59:36 -0500 Subject: [PATCH 0570/1544] [game_fallout4] Update translation files --- src/games/fallout4/src/game_fallout4_en.ts | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/src/games/fallout4/src/game_fallout4_en.ts b/src/games/fallout4/src/game_fallout4_en.ts index dddeac6c..5e48c096 100644 --- a/src/games/fallout4/src/game_fallout4_en.ts +++ b/src/games/fallout4/src/game_fallout4_en.ts @@ -4,7 +4,7 @@ GameFallout4 - + Adds support for the game Fallout 4. Splash by %1 @@ -93,12 +93,12 @@ Splash by %1 - + failed to query registry path (preflight): %1 - + failed to query registry path (read): %1 From 629fffe954c31a6393f437407f81cfd7231397af Mon Sep 17 00:00:00 2001 From: Silarn Date: Tue, 1 May 2018 16:59:36 -0500 Subject: [PATCH 0571/1544] [game_skyrimvr] Update translation files --- src/games/skyrimvr/src/game_skyrimvr_en.ts | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/games/skyrimvr/src/game_skyrimvr_en.ts b/src/games/skyrimvr/src/game_skyrimvr_en.ts index 8ee38856..d6b123e6 100644 --- a/src/games/skyrimvr/src/game_skyrimvr_en.ts +++ b/src/games/skyrimvr/src/game_skyrimvr_en.ts @@ -61,12 +61,12 @@ QObject - + failed to query registry path (preflight): %1 - + failed to query registry path (read): %1 From 9dac6ea16f8d321eab7c30b5329d02289c166656 Mon Sep 17 00:00:00 2001 From: Silarn Date: Tue, 1 May 2018 16:59:36 -0500 Subject: [PATCH 0572/1544] [game_skyrimse] Update translation files --- src/games/skyrimse/src/game_skyrimse_en.ts | 8 +++----- 1 file changed, 3 insertions(+), 5 deletions(-) diff --git a/src/games/skyrimse/src/game_skyrimse_en.ts b/src/games/skyrimse/src/game_skyrimse_en.ts index 1c092880..fa0bdaee 100644 --- a/src/games/skyrimse/src/game_skyrimse_en.ts +++ b/src/games/skyrimse/src/game_skyrimse_en.ts @@ -4,7 +4,7 @@ GameSkyrimSE - + Adds support for the game Skyrim Special Edition. @@ -61,14 +61,12 @@ QObject - - + failed to query registry path (preflight): %1 - - + failed to query registry path (read): %1 From cb407dcf285196e8efc4b96ff6d88001796c42af Mon Sep 17 00:00:00 2001 From: Silarn Date: Tue, 1 May 2018 16:59:37 -0500 Subject: [PATCH 0573/1544] [game_oblivion] Update translation files --- src/games/oblivion/src/game_oblivion_en.ts | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/games/oblivion/src/game_oblivion_en.ts b/src/games/oblivion/src/game_oblivion_en.ts index f356a91c..2a408dc7 100644 --- a/src/games/oblivion/src/game_oblivion_en.ts +++ b/src/games/oblivion/src/game_oblivion_en.ts @@ -91,12 +91,12 @@ - + failed to query registry path (preflight): %1 - + failed to query registry path (read): %1 From e485375b0375fe1bc7a8c583c44383f2310fe5e4 Mon Sep 17 00:00:00 2001 From: Silarn Date: Tue, 1 May 2018 16:59:38 -0500 Subject: [PATCH 0574/1544] [game_skyrim] Update translation files --- src/games/skyrim/src/game_skyrim_en.ts | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/games/skyrim/src/game_skyrim_en.ts b/src/games/skyrim/src/game_skyrim_en.ts index 7e2499f9..cfaed2ee 100644 --- a/src/games/skyrim/src/game_skyrim_en.ts +++ b/src/games/skyrim/src/game_skyrim_en.ts @@ -91,12 +91,12 @@ - + failed to query registry path (preflight): %1 - + failed to query registry path (read): %1 From d04c414f954b864ac4c89a594fad69c2a002487f Mon Sep 17 00:00:00 2001 From: Silarn Date: Tue, 1 May 2018 16:59:38 -0500 Subject: [PATCH 0575/1544] [game_ttw] Update translation files --- src/games/ttw/src/game_ttw_en.ts | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/src/games/ttw/src/game_ttw_en.ts b/src/games/ttw/src/game_ttw_en.ts index 7b8c19a6..baf902f7 100644 --- a/src/games/ttw/src/game_ttw_en.ts +++ b/src/games/ttw/src/game_ttw_en.ts @@ -4,7 +4,7 @@ GameFalloutTTW - + Adds support for the game Fallout TTW @@ -91,12 +91,12 @@ - + failed to query registry path (preflight): %1 - + failed to query registry path (read): %1 From e934ad4b70b02ccfcd016eef7a10953a15e49f0a Mon Sep 17 00:00:00 2001 From: Silarn Date: Wed, 2 May 2018 13:22:33 -0500 Subject: [PATCH 0576/1544] [game_fallout76] Update the nexus ID for MO --- src/games/fallout76/src/gamefallout4.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/games/fallout76/src/gamefallout4.cpp b/src/games/fallout76/src/gamefallout4.cpp index bf7d958d..17924359 100644 --- a/src/games/fallout76/src/gamefallout4.cpp +++ b/src/games/fallout76/src/gamefallout4.cpp @@ -197,7 +197,7 @@ IPluginGame::LoadOrderMechanism GameFallout4::loadOrderMechanism() const int GameFallout4::nexusModOrganizerID() const { - return 0; //... + return 28715; } int GameFallout4::nexusGameID() const From 81b67444b1a3f7d54c5a67217ff5efb4fec07326 Mon Sep 17 00:00:00 2001 From: Silarn Date: Wed, 2 May 2018 13:22:33 -0500 Subject: [PATCH 0577/1544] [game_fallout4] Update the nexus ID for MO --- src/games/fallout4/src/gamefallout4.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/games/fallout4/src/gamefallout4.cpp b/src/games/fallout4/src/gamefallout4.cpp index bf7d958d..17924359 100644 --- a/src/games/fallout4/src/gamefallout4.cpp +++ b/src/games/fallout4/src/gamefallout4.cpp @@ -197,7 +197,7 @@ IPluginGame::LoadOrderMechanism GameFallout4::loadOrderMechanism() const int GameFallout4::nexusModOrganizerID() const { - return 0; //... + return 28715; } int GameFallout4::nexusGameID() const From c28fe52761ca673b496f8684dd803014834bdb66 Mon Sep 17 00:00:00 2001 From: Silarn Date: Thu, 3 May 2018 16:16:02 -0500 Subject: [PATCH 0578/1544] [game_skyrim] Changes to prevent sending disabled mods to the bottom of the load order --- src/games/skyrim/src/skyrimgameplugins.cpp | 23 ++++++++++++++++++++++ src/games/skyrim/src/skyrimgameplugins.h | 2 ++ 2 files changed, 25 insertions(+) diff --git a/src/games/skyrim/src/skyrimgameplugins.cpp b/src/games/skyrim/src/skyrimgameplugins.cpp index 94fad0f4..44c9f260 100644 --- a/src/games/skyrim/src/skyrimgameplugins.cpp +++ b/src/games/skyrim/src/skyrimgameplugins.cpp @@ -22,6 +22,29 @@ SkyrimGamePlugins::SkyrimGamePlugins(IOrganizer *organizer) m_LocalCodec = QTextCodec::codecForName("Windows-1252"); } +void SkyrimGamePlugins::readPluginLists(MOBase::IPluginList *pluginList) { + QString loadOrderPath = + organizer()->profile()->absolutePath() + "/loadorder.txt"; + QString pluginsPath = organizer()->profile()->absolutePath() + "/plugins.txt"; + + bool loadOrderIsNew = !m_LastRead.isValid() || + !QFileInfo(loadOrderPath).exists() || + QFileInfo(loadOrderPath).lastModified() > m_LastRead; + bool pluginsIsNew = !m_LastRead.isValid() || + QFileInfo(pluginsPath).lastModified() > m_LastRead; + + if (pluginsIsNew && !loadOrderIsNew) { + // If the plugins is new but not loadorder, we must reparse the load order from the plugin files + readPluginList(pluginList, true); + } else { + // read both files if they are both new or both older than the last read + readLoadOrderList(pluginList, loadOrderPath); + readPluginList(pluginList, false); + } + + m_LastRead = QDateTime::currentDateTime(); +} + bool SkyrimGamePlugins::readPluginList(MOBase::IPluginList *pluginList, bool useLoadOrder) { diff --git a/src/games/skyrim/src/skyrimgameplugins.h b/src/games/skyrim/src/skyrimgameplugins.h index 13839af4..3eb68212 100644 --- a/src/games/skyrim/src/skyrimgameplugins.h +++ b/src/games/skyrim/src/skyrimgameplugins.h @@ -13,6 +13,8 @@ class SkyrimGamePlugins : public GamebryoGamePlugins public: SkyrimGamePlugins(MOBase::IOrganizer *organizer); + virtual void readPluginLists(MOBase::IPluginList *pluginList) override; + protected: virtual bool readPluginList(MOBase::IPluginList *pluginList, bool useLoadOrder) override; From 62cc46fb1f26328fb8b0cec82075726ee96e4dd5 Mon Sep 17 00:00:00 2001 From: Silarn Date: Thu, 3 May 2018 16:17:38 -0500 Subject: [PATCH 0579/1544] [game_fallout4vr] Allow for primary game sources and marking mods as converted/working --- src/games/fallout4vr/src/gamefallout4vr.h | 1 + 1 file changed, 1 insertion(+) diff --git a/src/games/fallout4vr/src/gamefallout4vr.h b/src/games/fallout4vr/src/gamefallout4vr.h index a6028e88..1d99b711 100644 --- a/src/games/fallout4vr/src/gamefallout4vr.h +++ b/src/games/fallout4vr/src/gamefallout4vr.h @@ -30,6 +30,7 @@ public: // IPluginGame interface virtual QStringList primaryPlugins() const override; virtual QStringList gameVariants() const override; virtual QString gameShortName() const override; + virtual QStringList primarySources() const override { return validShortNames(); }; virtual QStringList validShortNames() const override; virtual QString gameNexusName() const override; virtual QStringList iniFiles() const override; From 0d822659e51d2c6d4ffe5bf505ef4f3b09d46f36 Mon Sep 17 00:00:00 2001 From: Silarn Date: Thu, 3 May 2018 16:17:38 -0500 Subject: [PATCH 0580/1544] [game_skyrimvr] Allow for primary game sources and marking mods as converted/working --- src/games/skyrimvr/src/gameskyrimvr.cpp | 5 +++++ src/games/skyrimvr/src/gameskyrimvr.h | 1 + 2 files changed, 6 insertions(+) diff --git a/src/games/skyrimvr/src/gameskyrimvr.cpp b/src/games/skyrimvr/src/gameskyrimvr.cpp index 61ea30d2..bd3e8efd 100644 --- a/src/games/skyrimvr/src/gameskyrimvr.cpp +++ b/src/games/skyrimvr/src/gameskyrimvr.cpp @@ -183,6 +183,11 @@ QString GameSkyrimVR::gameShortName() const return "SkyrimVR"; } +QStringList GameSkyrimVR::primarySources() const +{ + return { "SkyrimSE" }; +} + QStringList GameSkyrimVR::validShortNames() const { return { "Skyrim", "SkyrimSE" }; diff --git a/src/games/skyrimvr/src/gameskyrimvr.h b/src/games/skyrimvr/src/gameskyrimvr.h index ff6bf41e..84322847 100644 --- a/src/games/skyrimvr/src/gameskyrimvr.h +++ b/src/games/skyrimvr/src/gameskyrimvr.h @@ -27,6 +27,7 @@ public: // IPluginGame interface virtual QStringList primaryPlugins() const override; virtual QStringList gameVariants() const override; virtual QString gameShortName() const override; + virtual QStringList primarySources() const override; virtual QStringList validShortNames() const override; virtual QString gameNexusName() const override; virtual QStringList iniFiles() const override; From fc12940bacab1c5ec60d7b46fa1a38c4f8c08b0f Mon Sep 17 00:00:00 2001 From: Silarn Date: Thu, 3 May 2018 16:17:39 -0500 Subject: [PATCH 0581/1544] Allow for primary game sources and marking mods as converted/working --- src/gamebryogameplugins.h | 5 ++++- src/gamegamebryo.cpp | 5 +++++ src/gamegamebryo.h | 1 + 3 files changed, 10 insertions(+), 1 deletion(-) diff --git a/src/gamebryogameplugins.h b/src/gamebryogameplugins.h index b41c5395..0e714b9c 100644 --- a/src/gamebryogameplugins.h +++ b/src/gamebryogameplugins.h @@ -28,6 +28,10 @@ protected: const QString &filePath); virtual bool readPluginList(MOBase::IPluginList *pluginList, bool useLoadOrder); +protected: + + QDateTime m_LastRead; + private: void writeList(const MOBase::IPluginList *pluginList, const QString &filePath, bool loadOrder); @@ -37,7 +41,6 @@ private: QTextCodec *m_Utf8Codec; QTextCodec *m_LocalCodec; - QDateTime m_LastRead; std::map m_LastSaveHash; }; diff --git a/src/gamegamebryo.cpp b/src/gamegamebryo.cpp index b4673af6..d4f1b912 100644 --- a/src/gamegamebryo.cpp +++ b/src/gamegamebryo.cpp @@ -87,6 +87,11 @@ QString GameGamebryo::binaryName() const return gameShortName() + ".exe"; } +QStringList GameGamebryo::primarySources() const +{ + return {}; +} + QStringList GameGamebryo::validShortNames() const { return {}; diff --git a/src/gamegamebryo.h b/src/gamegamebryo.h index 6054ebf9..70a35920 100644 --- a/src/gamegamebryo.h +++ b/src/gamegamebryo.h @@ -57,6 +57,7 @@ public: // IPluginGame interface virtual void setGameVariant(const QString &variant) override; virtual QString binaryName() const override; //gameShortName + virtual QStringList primarySources() const override; virtual QStringList validShortNames() const override; //iniFiles //DLCPlugins From 4c5acb843dc80e3da26ebdd9b0531ff4f90613cc Mon Sep 17 00:00:00 2001 From: Silarn Date: Thu, 3 May 2018 16:17:40 -0500 Subject: [PATCH 0582/1544] [game_ttw] Allow for primary game sources and marking mods as converted/working --- src/games/ttw/src/gamefalloutttw.cpp | 5 +++++ src/games/ttw/src/gamefalloutttw.h | 1 + 2 files changed, 6 insertions(+) diff --git a/src/games/ttw/src/gamefalloutttw.cpp b/src/games/ttw/src/gamefalloutttw.cpp index c8992419..9bee6723 100644 --- a/src/games/ttw/src/gamefalloutttw.cpp +++ b/src/games/ttw/src/gamefalloutttw.cpp @@ -148,6 +148,11 @@ QString GameFalloutTTW::gameShortName() const return "TTW"; } +QStringList GameFalloutTTW::primarySources() const +{ + return { "FalloutNV" }; +} + QStringList GameFalloutTTW::validShortNames() const { return { "FalloutNV", "Fallout3" }; diff --git a/src/games/ttw/src/gamefalloutttw.h b/src/games/ttw/src/gamefalloutttw.h index babf356e..93bdaceb 100644 --- a/src/games/ttw/src/gamefalloutttw.h +++ b/src/games/ttw/src/gamefalloutttw.h @@ -30,6 +30,7 @@ public: // IPluginGame interface virtual QStringList primaryPlugins() const override; virtual QString binaryName() const override; virtual QString gameShortName() const override; + virtual QStringList primarySources() const override; virtual QStringList validShortNames() const override; virtual QString gameNexusName() const override; virtual QStringList iniFiles() const override; From 721d78e10fa117f789e24fd7fa21e7cd266c154f Mon Sep 17 00:00:00 2001 From: Silarn Date: Thu, 3 May 2018 20:45:39 -0500 Subject: [PATCH 0583/1544] [game_fallout4vr] Remove the script extender code from FO4VR and bump version --- src/games/fallout4vr/src/gamefallout4vr.cpp | 19 +++---------------- 1 file changed, 3 insertions(+), 16 deletions(-) diff --git a/src/games/fallout4vr/src/gamefallout4vr.cpp b/src/games/fallout4vr/src/gamefallout4vr.cpp index e2e8313c..ba6e72e9 100644 --- a/src/games/fallout4vr/src/gamefallout4vr.cpp +++ b/src/games/fallout4vr/src/gamefallout4vr.cpp @@ -1,7 +1,6 @@ #include "gameFallout4vr.h" #include "fallout4vrdataarchives.h" -#include "fallout4vrscriptextender.h" #include "fallout4vrsavegameinfo.h" #include "fallout4vrgameplugins.h" #include "fallout4vrunmanagedmods.h" @@ -38,7 +37,6 @@ bool GameFallout4VR::init(IOrganizer *moInfo) m_GamePath = identifyGamePath(); - registerFeature(new Fallout4VRScriptExtender(this)); registerFeature(new Fallout4VRDataArchives(myGamesPath())); registerFeature(new GamebryoLocalSavegames(myGamesPath(), "fallout4custom.ini")); registerFeature(new Fallout4VRSaveGameInfo(this)); @@ -56,9 +54,7 @@ QString GameFallout4VR::gameName() const QList GameFallout4VR::executables() const { return QList() - << ExecutableInfo("F4SE", findInGameFolder(feature()->loaderName())) << ExecutableInfo("Fallout 4 VR", findInGameFolder(binaryName())) - //<< ExecutableInfo("Fallout Launcher", findInGameFolder(getLauncherName())) // Fallout 4 VR does not have a launcher << ExecutableInfo("Creation Kit", findInGameFolder("CreationKit.exe")) << ExecutableInfo("LOOT", getLootPath()).withArgument("--game=\"Fallout4VR\"") ; @@ -66,12 +62,12 @@ QList GameFallout4VR::executables() const QString GameFallout4VR::name() const { - return "Fallout4VR Support Plugin"; + return "Fallout 4 VR Support Plugin"; } QString GameFallout4VR::author() const { - return "Tannin"; + return "MO2 Contibutors"; } QString GameFallout4VR::description() const @@ -82,7 +78,7 @@ QString GameFallout4VR::description() const MOBase::VersionInfo GameFallout4VR::version() const { - return VersionInfo(0, 3, 0, VersionInfo::RELEASE_BETA); + return VersionInfo(0, 4, 0, VersionInfo::RELEASE_CANDIDATE); } bool GameFallout4VR::isActive() const @@ -103,11 +99,6 @@ void GameFallout4VR::initializeProfile(const QDir &path, ProfileSettings setting } if (settings.testFlag(IPluginGame::CONFIGURATION)) { - /* - There is a fallout4.ini in the game installation directory, but it never get copied to "My Games/Fallout4VR". - The only files in the MyGames directory are fallout4custom.ini, fallout4prefs.ini and fallout4vrcustom.ini. - All settings you would expect in the fallout4.ini can be put into the fallout4custom.ini. - */ if (settings.testFlag(IPluginGame::PREFER_DEFAULTS) || !QFileInfo(myGamesPath() + "/fallout4.ini").exists()) { copyToProfile(gameDirectory().absolutePath(), path, "fallout4.ini"); @@ -136,9 +127,6 @@ QString GameFallout4VR::steamAPPId() const } QStringList GameFallout4VR::primaryPlugins() const { - /*QStringList plugins = {"fallout4.esm", "fallout4_vr.esm", "dlcrobot.esm", "dlcworkshop01.esm", "dlccoast.esm", "dlcworkshop02.esm", - "dlcworkshop03.esm", "dlcnukaworld.esm"};*/ - // Fallout 4 VR does not support the DLCs, so we need to tread them as unmanaged plugins. QStringList plugins = {"fallout4.esm", "fallout4_vr.esm"}; plugins.append(CCPlugins()); @@ -226,7 +214,6 @@ QString GameFallout4VR::getLauncherName() const QString GameFallout4VR::identifyGamePath() const { - // In every other Bethesda game they use gameShortName() as registry key, but for Fallout 4 VR they use gameName() QString path = "Software\\Bethesda Softworks\\" + gameName(); return findInRegistry(HKEY_LOCAL_MACHINE, path.toStdWString().c_str(), L"Installed Path"); } From 8fdf059d0bb4309070c0f88374cac81e7c53cbbc Mon Sep 17 00:00:00 2001 From: Silarn Date: Thu, 3 May 2018 20:47:47 -0500 Subject: [PATCH 0584/1544] [game_skyrimvr] Set the correct name for sksevr, unify spacing, bump version --- src/games/skyrimvr/src/gameskyrimvr.cpp | 123 +++++++++--------- .../skyrimvr/src/skyrimvrscriptextender.cpp | 2 +- 2 files changed, 62 insertions(+), 63 deletions(-) diff --git a/src/games/skyrimvr/src/gameskyrimvr.cpp b/src/games/skyrimvr/src/gameskyrimvr.cpp index bd3e8efd..8ee5bde4 100644 --- a/src/games/skyrimvr/src/gameskyrimvr.cpp +++ b/src/games/skyrimvr/src/gameskyrimvr.cpp @@ -31,59 +31,59 @@ GameSkyrimVR::GameSkyrimVR() void GameSkyrimVR::setGamePath(const QString &path) { - m_GamePath = path; + m_GamePath = path; } QDir GameSkyrimVR::documentsDirectory() const { - return m_MyGamesPath; + return m_MyGamesPath; } QString GameSkyrimVR::identifyGamePath() const { - QString path = "Software\\Bethesda Softworks\\" + gameName(); - return findInRegistry(HKEY_LOCAL_MACHINE, path.toStdWString().c_str(), L"Installed Path"); + QString path = "Software\\Bethesda Softworks\\" + gameName(); + return findInRegistry(HKEY_LOCAL_MACHINE, path.toStdWString().c_str(), L"Installed Path"); } QDir GameSkyrimVR::savesDirectory() const { - return QDir(m_MyGamesPath + "/Saves"); + return QDir(m_MyGamesPath + "/Saves"); } QString GameSkyrimVR::myGamesPath() const { - return m_MyGamesPath; + return m_MyGamesPath; } bool GameSkyrimVR::isInstalled() const { - return !m_GamePath.isEmpty(); + return !m_GamePath.isEmpty(); } bool GameSkyrimVR::init(IOrganizer *moInfo) { - if (!GameGamebryo::init(moInfo)) { - return false; - } + if (!GameGamebryo::init(moInfo)) { + return false; + } - m_GamePath = GameSkyrimVR::identifyGamePath(); - m_MyGamesPath = determineMyGamesPath(gameName()); + m_GamePath = GameSkyrimVR::identifyGamePath(); + m_MyGamesPath = determineMyGamesPath(gameName()); - registerFeature(new SkyrimVRScriptExtender(this)); - registerFeature(new SkyrimVRDataArchives(myGamesPath())); - registerFeature(new GamebryoLocalSavegames(myGamesPath(), "SkyrimVR.ini")); - registerFeature(new SkyrimVRSaveGameInfo(this)); - registerFeature(new SkyrimVRGamePlugins(moInfo)); - registerFeature(new SkyrimVRUnmangedMods(this)); + registerFeature(new SkyrimVRScriptExtender(this)); + registerFeature(new SkyrimVRDataArchives(myGamesPath())); + registerFeature(new GamebryoLocalSavegames(myGamesPath(), "SkyrimVR.ini")); + registerFeature(new SkyrimVRSaveGameInfo(this)); + registerFeature(new SkyrimVRGamePlugins(moInfo)); + registerFeature(new SkyrimVRUnmangedMods(this)); - return true; + return true; } QString GameSkyrimVR::gameName() const { - return "Skyrim VR"; + return "Skyrim VR"; } QList GameSkyrimVR::executables() const @@ -98,71 +98,71 @@ QList GameSkyrimVR::executables() const QFileInfo GameSkyrimVR::findInGameFolder(const QString &relativePath) const { - return QFileInfo(m_GamePath + "/" + relativePath); + return QFileInfo(m_GamePath + "/" + relativePath); } QString GameSkyrimVR::name() const { - return "Skyrim VR Support Plugin"; + return "Skyrim VR Support Plugin"; } QString GameSkyrimVR::author() const { - return "Brixified"; + return "Brixified & MO2 Team"; } QString GameSkyrimVR::description() const { - return tr("Adds support for the game Skyrim VR."); + return tr("Adds support for the game Skyrim VR."); } MOBase::VersionInfo GameSkyrimVR::version() const { - return VersionInfo(0, 1, 5, VersionInfo::RELEASE_ALPHA); + return VersionInfo(0, 2, 0, VersionInfo::RELEASE_CANDIDATE); } bool GameSkyrimVR::isActive() const { - return qApp->property("managed_game").value() == this; + return qApp->property("managed_game").value() == this; } QList GameSkyrimVR::settings() const { - return QList(); + return QList(); } void GameSkyrimVR::initializeProfile(const QDir &path, ProfileSettings settings) const { - if (settings.testFlag(IPluginGame::MODS)) { - copyToProfile(localAppFolder() + "/Skyrim VR", path, "plugins.txt"); - copyToProfile(localAppFolder() + "/Skyrim VR", path, "loadorder.txt"); + if (settings.testFlag(IPluginGame::MODS)) { + copyToProfile(localAppFolder() + "/Skyrim VR", path, "plugins.txt"); + copyToProfile(localAppFolder() + "/Skyrim VR", path, "loadorder.txt"); + } + + if (settings.testFlag(IPluginGame::CONFIGURATION)) { + if (settings.testFlag(IPluginGame::PREFER_DEFAULTS) + || !QFileInfo(myGamesPath() + "/skyrimvr.ini").exists()) { + copyToProfile(gameDirectory().absolutePath(), path, "skyrim.ini", "skyrimvr.ini"); + } else { + copyToProfile(myGamesPath(), path, "skyrimvr.ini"); } - if (settings.testFlag(IPluginGame::CONFIGURATION)) { - if (settings.testFlag(IPluginGame::PREFER_DEFAULTS) - || !QFileInfo(myGamesPath() + "/skyrimvr.ini").exists()) { - copyToProfile(gameDirectory().absolutePath(), path, "skyrim.ini", "skyrimvr.ini"); - } else { - copyToProfile(myGamesPath(), path, "skyrimvr.ini"); - } - - copyToProfile(myGamesPath(), path, "skyrimprefs.ini"); - } + copyToProfile(myGamesPath(), path, "skyrimprefs.ini"); + } } QString GameSkyrimVR::savegameExtension() const { - return "ess"; + return "ess"; } QString GameSkyrimVR::savegameSEExtension() const { - return "skse"; + return "skse"; } QString GameSkyrimVR::steamAPPId() const { - return "611670"; + return "611670"; } QStringList GameSkyrimVR::primaryPlugins() const { @@ -175,27 +175,27 @@ QStringList GameSkyrimVR::primaryPlugins() const { QStringList GameSkyrimVR::gameVariants() const { - return{ "Regular" }; + return{ "Regular" }; } QString GameSkyrimVR::gameShortName() const { - return "SkyrimVR"; + return "SkyrimVR"; } QStringList GameSkyrimVR::primarySources() const { - return { "SkyrimSE" }; + return { "SkyrimSE" }; } QStringList GameSkyrimVR::validShortNames() const { - return { "Skyrim", "SkyrimSE" }; + return { "Skyrim", "SkyrimSE" }; } QString GameSkyrimVR::gameNexusName() const { - return "skyrimspecialedition"; + return "skyrimspecialedition"; } @@ -206,7 +206,7 @@ QStringList GameSkyrimVR::iniFiles() const QStringList GameSkyrimVR::DLCPlugins() const { - return{ "dawnguard.esm", "hearthfires.esm", "dragonborn.esm" }; + return{ "dawnguard.esm", "hearthfires.esm", "dragonborn.esm" }; } QStringList GameSkyrimVR::CCPlugins() const @@ -238,7 +238,7 @@ QStringList GameSkyrimVR::CCPlugins() const IPluginGame::LoadOrderMechanism GameSkyrimVR::loadOrderMechanism() const { - return IPluginGame::LoadOrderMechanism::PluginsTxt; + return IPluginGame::LoadOrderMechanism::PluginsTxt; } MOBase::IPluginGame::SortMechanism GameSkyrimVR::sortMechanism() const @@ -248,35 +248,34 @@ MOBase::IPluginGame::SortMechanism GameSkyrimVR::sortMechanism() const int GameSkyrimVR::nexusModOrganizerID() const { - return 6194; //... Should be 0? + return 6194; } int GameSkyrimVR::nexusGameID() const { - return 1704; //1704 + return 1704; } QString GameSkyrimVR::getLauncherName() const { - return binaryName(); // Skyrim VR has no Launcher, so we just return the name of the game binary + return binaryName(); // Skyrim VR has no Launcher, so we just return the name of the game binary } QDir GameSkyrimVR::gameDirectory() const { - return QDir(m_GamePath); + return QDir(m_GamePath); } // Not to delete all the spaces... MappingType GameSkyrimVR::mappings() const { - MappingType result; + MappingType result; - for (const QString &profileFile : { "plugins.txt", "loadorder.txt" }) { - result.push_back({ m_Organizer->profilePath() + "/" + profileFile, - localAppFolder() + "/" + gameName() + "/" + profileFile, - false }); - } + for (const QString &profileFile : { "plugins.txt", "loadorder.txt" }) { + result.push_back({ m_Organizer->profilePath() + "/" + profileFile, + localAppFolder() + "/" + gameName() + "/" + profileFile, + false }); + } - return result; + return result; } - diff --git a/src/games/skyrimvr/src/skyrimvrscriptextender.cpp b/src/games/skyrimvr/src/skyrimvrscriptextender.cpp index 6a133545..c272231f 100644 --- a/src/games/skyrimvr/src/skyrimvrscriptextender.cpp +++ b/src/games/skyrimvr/src/skyrimvrscriptextender.cpp @@ -10,7 +10,7 @@ SkyrimVRScriptExtender::SkyrimVRScriptExtender(GameGamebryo const *game) : QString SkyrimVRScriptExtender::BinaryName() const { - return "skse64_loader.exe"; + return "sksevr_loader.exe"; } QString SkyrimVRScriptExtender::PluginPath() const From 60bdb157eede8ed954d89f2d4edaff592010644d Mon Sep 17 00:00:00 2001 From: Silarn Date: Fri, 4 May 2018 00:15:44 -0500 Subject: [PATCH 0585/1544] [game_fallout4vr] Update translation file --- src/games/fallout4vr/src/game_fallout4vr_en.ts | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/src/games/fallout4vr/src/game_fallout4vr_en.ts b/src/games/fallout4vr/src/game_fallout4vr_en.ts index d6c8c5ca..e221f8bc 100644 --- a/src/games/fallout4vr/src/game_fallout4vr_en.ts +++ b/src/games/fallout4vr/src/game_fallout4vr_en.ts @@ -4,7 +4,7 @@ GameFallout4VR - + Adds support for the game Fallout 4 VR. Splash by %1 @@ -68,12 +68,12 @@ Splash by %1 - + failed to query registry path (preflight): %1 - + failed to query registry path (read): %1 From effddf9aaa71685c89bed1cd04edd29223f52301 Mon Sep 17 00:00:00 2001 From: Silarn Date: Fri, 4 May 2018 00:15:44 -0500 Subject: [PATCH 0586/1544] [game_morrowind] Update translation file --- src/games/morrowind/src/game_morrowind_en.ts | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/games/morrowind/src/game_morrowind_en.ts b/src/games/morrowind/src/game_morrowind_en.ts index 3288e451..08f74294 100644 --- a/src/games/morrowind/src/game_morrowind_en.ts +++ b/src/games/morrowind/src/game_morrowind_en.ts @@ -143,12 +143,12 @@ Splash by %1 - + failed to query registry path (preflight): %1 - + failed to query registry path (read): %1 From 8601e07e0fd6db29d172b63fe569ec77ced59e0d Mon Sep 17 00:00:00 2001 From: Silarn Date: Fri, 4 May 2018 00:15:45 -0500 Subject: [PATCH 0587/1544] [game_falloutnv] Update translation file --- src/games/falloutnv/src/game_falloutNV_en.ts | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/games/falloutnv/src/game_falloutNV_en.ts b/src/games/falloutnv/src/game_falloutNV_en.ts index 169797c9..d9801c6d 100644 --- a/src/games/falloutnv/src/game_falloutNV_en.ts +++ b/src/games/falloutnv/src/game_falloutNV_en.ts @@ -91,12 +91,12 @@ - + failed to query registry path (preflight): %1 - + failed to query registry path (read): %1 From f3a794ae3d27481e861cedd778032b51b7059f80 Mon Sep 17 00:00:00 2001 From: Silarn Date: Fri, 4 May 2018 00:15:45 -0500 Subject: [PATCH 0588/1544] [game_fallout3] Update translation file --- src/games/fallout3/src/game_fallout3_en.ts | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/games/fallout3/src/game_fallout3_en.ts b/src/games/fallout3/src/game_fallout3_en.ts index f0f579ca..e0610157 100644 --- a/src/games/fallout3/src/game_fallout3_en.ts +++ b/src/games/fallout3/src/game_fallout3_en.ts @@ -91,12 +91,12 @@ - + failed to query registry path (preflight): %1 - + failed to query registry path (read): %1 From 8546ff0ea3e078456be4b1c31dcf04ff1a47bae9 Mon Sep 17 00:00:00 2001 From: Silarn Date: Fri, 4 May 2018 00:15:46 -0500 Subject: [PATCH 0589/1544] [game_skyrimvr] Update translation file --- src/games/skyrimvr/src/game_skyrimvr_en.ts | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/games/skyrimvr/src/game_skyrimvr_en.ts b/src/games/skyrimvr/src/game_skyrimvr_en.ts index d6b123e6..79ff361e 100644 --- a/src/games/skyrimvr/src/game_skyrimvr_en.ts +++ b/src/games/skyrimvr/src/game_skyrimvr_en.ts @@ -61,12 +61,12 @@ QObject - + failed to query registry path (preflight): %1 - + failed to query registry path (read): %1 From 6ef0d30bd8dc304c3b7fc2c6cfdf60e72db1cb00 Mon Sep 17 00:00:00 2001 From: Silarn Date: Fri, 4 May 2018 00:15:46 -0500 Subject: [PATCH 0590/1544] [game_fallout76] Update translation file --- src/games/fallout76/src/game_fallout4_en.ts | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/games/fallout76/src/game_fallout4_en.ts b/src/games/fallout76/src/game_fallout4_en.ts index 5e48c096..6bbc83d4 100644 --- a/src/games/fallout76/src/game_fallout4_en.ts +++ b/src/games/fallout76/src/game_fallout4_en.ts @@ -93,12 +93,12 @@ Splash by %1 - + failed to query registry path (preflight): %1 - + failed to query registry path (read): %1 From a6c6b51ddffc70e5fd95ac30df93f720d0087646 Mon Sep 17 00:00:00 2001 From: Silarn Date: Fri, 4 May 2018 00:15:46 -0500 Subject: [PATCH 0591/1544] [game_fallout4] Update translation file --- src/games/fallout4/src/game_fallout4_en.ts | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/games/fallout4/src/game_fallout4_en.ts b/src/games/fallout4/src/game_fallout4_en.ts index 5e48c096..6bbc83d4 100644 --- a/src/games/fallout4/src/game_fallout4_en.ts +++ b/src/games/fallout4/src/game_fallout4_en.ts @@ -93,12 +93,12 @@ Splash by %1 - + failed to query registry path (preflight): %1 - + failed to query registry path (read): %1 From 73b0eb233b29e5912e9ea84ae8d5739d5a0e97a8 Mon Sep 17 00:00:00 2001 From: Silarn Date: Fri, 4 May 2018 00:15:47 -0500 Subject: [PATCH 0592/1544] [game_skyrimse] Update translation file --- src/games/skyrimse/src/game_skyrimse_en.ts | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/games/skyrimse/src/game_skyrimse_en.ts b/src/games/skyrimse/src/game_skyrimse_en.ts index fa0bdaee..25184940 100644 --- a/src/games/skyrimse/src/game_skyrimse_en.ts +++ b/src/games/skyrimse/src/game_skyrimse_en.ts @@ -61,12 +61,12 @@ QObject - + failed to query registry path (preflight): %1 - + failed to query registry path (read): %1 From 5a2b7002c9d5a063c54aaa7d6959725ccd6b4b3d Mon Sep 17 00:00:00 2001 From: Silarn Date: Fri, 4 May 2018 00:15:47 -0500 Subject: [PATCH 0593/1544] [game_oblivion] Update translation file --- src/games/oblivion/src/game_oblivion_en.ts | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/games/oblivion/src/game_oblivion_en.ts b/src/games/oblivion/src/game_oblivion_en.ts index 2a408dc7..2463f150 100644 --- a/src/games/oblivion/src/game_oblivion_en.ts +++ b/src/games/oblivion/src/game_oblivion_en.ts @@ -91,12 +91,12 @@ - + failed to query registry path (preflight): %1 - + failed to query registry path (read): %1 From 3e348a3252c8e6e1321de9d83e3945ca9e068e5f Mon Sep 17 00:00:00 2001 From: Silarn Date: Fri, 4 May 2018 00:15:49 -0500 Subject: [PATCH 0594/1544] [game_skyrim] Update translation file --- src/games/skyrim/src/game_skyrim_en.ts | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/games/skyrim/src/game_skyrim_en.ts b/src/games/skyrim/src/game_skyrim_en.ts index cfaed2ee..b50c0f0c 100644 --- a/src/games/skyrim/src/game_skyrim_en.ts +++ b/src/games/skyrim/src/game_skyrim_en.ts @@ -91,12 +91,12 @@ - + failed to query registry path (preflight): %1 - + failed to query registry path (read): %1 From 243a12eef658a57abecbaccc908da0c7481346c7 Mon Sep 17 00:00:00 2001 From: Silarn Date: Fri, 4 May 2018 00:15:49 -0500 Subject: [PATCH 0595/1544] [game_ttw] Update translation file --- src/games/ttw/src/game_ttw_en.ts | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/games/ttw/src/game_ttw_en.ts b/src/games/ttw/src/game_ttw_en.ts index baf902f7..5e9e9042 100644 --- a/src/games/ttw/src/game_ttw_en.ts +++ b/src/games/ttw/src/game_ttw_en.ts @@ -91,12 +91,12 @@ - + failed to query registry path (preflight): %1 - + failed to query registry path (read): %1 From 85943cc9a8d10bd0e413d32c8891c4f46099d26e Mon Sep 17 00:00:00 2001 From: Silarn Date: Fri, 4 May 2018 00:28:37 -0500 Subject: [PATCH 0596/1544] [game_fallout4vr] Updating gitignore --- src/games/fallout4vr/.gitignore | 11 ++++------- 1 file changed, 4 insertions(+), 7 deletions(-) diff --git a/src/games/fallout4vr/.gitignore b/src/games/fallout4vr/.gitignore index 4c4fa01e..cf71be77 100644 --- a/src/games/fallout4vr/.gitignore +++ b/src/games/fallout4vr/.gitignore @@ -1,8 +1,5 @@ -CMakeLists.txt.user edit -build -std*.log -build -vsbuild -vs_stderr.log -vs_stdout.log +CMakeLists.txt.user +/msbuild.log +/*std*.log +/*build From 0f06bc847d31ba692a20b225cdfdda900eb1a5e4 Mon Sep 17 00:00:00 2001 From: Silarn Date: Fri, 4 May 2018 00:28:38 -0500 Subject: [PATCH 0597/1544] [game_morrowind] Updating gitignore --- src/games/morrowind/.gitignore | 11 ++++------- 1 file changed, 4 insertions(+), 7 deletions(-) diff --git a/src/games/morrowind/.gitignore b/src/games/morrowind/.gitignore index 4c4fa01e..cf71be77 100644 --- a/src/games/morrowind/.gitignore +++ b/src/games/morrowind/.gitignore @@ -1,8 +1,5 @@ -CMakeLists.txt.user edit -build -std*.log -build -vsbuild -vs_stderr.log -vs_stdout.log +CMakeLists.txt.user +/msbuild.log +/*std*.log +/*build From ef9682b9041badda58845a8ff15853690b48f482 Mon Sep 17 00:00:00 2001 From: Silarn Date: Fri, 4 May 2018 00:28:40 -0500 Subject: [PATCH 0598/1544] [game_skyrimse] Updating gitignore --- src/games/skyrimse/.gitignore | 11 ++++------- 1 file changed, 4 insertions(+), 7 deletions(-) diff --git a/src/games/skyrimse/.gitignore b/src/games/skyrimse/.gitignore index 4c4fa01e..cf71be77 100644 --- a/src/games/skyrimse/.gitignore +++ b/src/games/skyrimse/.gitignore @@ -1,8 +1,5 @@ -CMakeLists.txt.user edit -build -std*.log -build -vsbuild -vs_stderr.log -vs_stdout.log +CMakeLists.txt.user +/msbuild.log +/*std*.log +/*build From 68ecbaffd02717afcfed70c1aa6c509d0f927e29 Mon Sep 17 00:00:00 2001 From: Silarn Date: Fri, 4 May 2018 00:28:40 -0500 Subject: [PATCH 0599/1544] [game_falloutnv] Updating gitignore --- src/games/falloutnv/.gitignore | 11 ++++------- 1 file changed, 4 insertions(+), 7 deletions(-) diff --git a/src/games/falloutnv/.gitignore b/src/games/falloutnv/.gitignore index 4c4fa01e..cf71be77 100644 --- a/src/games/falloutnv/.gitignore +++ b/src/games/falloutnv/.gitignore @@ -1,8 +1,5 @@ -CMakeLists.txt.user edit -build -std*.log -build -vsbuild -vs_stderr.log -vs_stdout.log +CMakeLists.txt.user +/msbuild.log +/*std*.log +/*build From 77ca963a28c04dbc35d6369761195a03925507c8 Mon Sep 17 00:00:00 2001 From: Silarn Date: Fri, 4 May 2018 00:28:41 -0500 Subject: [PATCH 0600/1544] Updating gitignore --- .gitignore | 11 ++++------- 1 file changed, 4 insertions(+), 7 deletions(-) diff --git a/.gitignore b/.gitignore index 4c4fa01e..cf71be77 100644 --- a/.gitignore +++ b/.gitignore @@ -1,8 +1,5 @@ -CMakeLists.txt.user edit -build -std*.log -build -vsbuild -vs_stderr.log -vs_stdout.log +CMakeLists.txt.user +/msbuild.log +/*std*.log +/*build From d8f1433b2dd884266cd0228d38c5a1868bfa7e27 Mon Sep 17 00:00:00 2001 From: Silarn Date: Fri, 4 May 2018 00:28:41 -0500 Subject: [PATCH 0601/1544] [game_oblivion] Updating gitignore --- src/games/oblivion/.gitignore | 11 ++++------- 1 file changed, 4 insertions(+), 7 deletions(-) diff --git a/src/games/oblivion/.gitignore b/src/games/oblivion/.gitignore index 4c4fa01e..cf71be77 100644 --- a/src/games/oblivion/.gitignore +++ b/src/games/oblivion/.gitignore @@ -1,8 +1,5 @@ -CMakeLists.txt.user edit -build -std*.log -build -vsbuild -vs_stderr.log -vs_stdout.log +CMakeLists.txt.user +/msbuild.log +/*std*.log +/*build From a02a906c9009e13514a58cd56162c1875358be27 Mon Sep 17 00:00:00 2001 From: Silarn Date: Fri, 4 May 2018 00:28:42 -0500 Subject: [PATCH 0602/1544] [game_skyrimvr] Updating gitignore --- src/games/skyrimvr/.gitignore | 11 ++++------- 1 file changed, 4 insertions(+), 7 deletions(-) diff --git a/src/games/skyrimvr/.gitignore b/src/games/skyrimvr/.gitignore index 4c4fa01e..cf71be77 100644 --- a/src/games/skyrimvr/.gitignore +++ b/src/games/skyrimvr/.gitignore @@ -1,8 +1,5 @@ -CMakeLists.txt.user edit -build -std*.log -build -vsbuild -vs_stderr.log -vs_stdout.log +CMakeLists.txt.user +/msbuild.log +/*std*.log +/*build From f943e002acaa7367bae8ab525494d82fe3098293 Mon Sep 17 00:00:00 2001 From: Silarn Date: Fri, 4 May 2018 00:28:42 -0500 Subject: [PATCH 0603/1544] [game_fallout76] Updating gitignore --- src/games/fallout76/.gitignore | 11 ++++------- 1 file changed, 4 insertions(+), 7 deletions(-) diff --git a/src/games/fallout76/.gitignore b/src/games/fallout76/.gitignore index 4c4fa01e..cf71be77 100644 --- a/src/games/fallout76/.gitignore +++ b/src/games/fallout76/.gitignore @@ -1,8 +1,5 @@ -CMakeLists.txt.user edit -build -std*.log -build -vsbuild -vs_stderr.log -vs_stdout.log +CMakeLists.txt.user +/msbuild.log +/*std*.log +/*build From 60ef638b74b869525951e28dcb0761cb240024a6 Mon Sep 17 00:00:00 2001 From: Silarn Date: Fri, 4 May 2018 00:28:42 -0500 Subject: [PATCH 0604/1544] [game_fallout4] Updating gitignore --- src/games/fallout4/.gitignore | 11 ++++------- 1 file changed, 4 insertions(+), 7 deletions(-) diff --git a/src/games/fallout4/.gitignore b/src/games/fallout4/.gitignore index 4c4fa01e..cf71be77 100644 --- a/src/games/fallout4/.gitignore +++ b/src/games/fallout4/.gitignore @@ -1,8 +1,5 @@ -CMakeLists.txt.user edit -build -std*.log -build -vsbuild -vs_stderr.log -vs_stdout.log +CMakeLists.txt.user +/msbuild.log +/*std*.log +/*build From 018021954fe229b77238afa00a84afaba6e53a96 Mon Sep 17 00:00:00 2001 From: Silarn Date: Fri, 4 May 2018 00:28:42 -0500 Subject: [PATCH 0605/1544] [game_fallout3] Updating gitignore --- src/games/fallout3/.gitignore | 11 ++++------- 1 file changed, 4 insertions(+), 7 deletions(-) diff --git a/src/games/fallout3/.gitignore b/src/games/fallout3/.gitignore index 4c4fa01e..cf71be77 100644 --- a/src/games/fallout3/.gitignore +++ b/src/games/fallout3/.gitignore @@ -1,8 +1,5 @@ -CMakeLists.txt.user edit -build -std*.log -build -vsbuild -vs_stderr.log -vs_stdout.log +CMakeLists.txt.user +/msbuild.log +/*std*.log +/*build From 1fbc8dff07fda099fc6e4ff4025f1c007354d029 Mon Sep 17 00:00:00 2001 From: Silarn Date: Fri, 4 May 2018 00:28:44 -0500 Subject: [PATCH 0606/1544] [game_skyrim] Updating gitignore --- src/games/skyrim/.gitignore | 11 ++++------- 1 file changed, 4 insertions(+), 7 deletions(-) diff --git a/src/games/skyrim/.gitignore b/src/games/skyrim/.gitignore index 4c4fa01e..cf71be77 100644 --- a/src/games/skyrim/.gitignore +++ b/src/games/skyrim/.gitignore @@ -1,8 +1,5 @@ -CMakeLists.txt.user edit -build -std*.log -build -vsbuild -vs_stderr.log -vs_stdout.log +CMakeLists.txt.user +/msbuild.log +/*std*.log +/*build From 3cd30a9bf720631c00cb080f09d86b7293aa5d38 Mon Sep 17 00:00:00 2001 From: Silarn Date: Fri, 4 May 2018 00:28:45 -0500 Subject: [PATCH 0607/1544] [game_ttw] Updating gitignore --- src/games/ttw/.gitignore | 9 ++++----- 1 file changed, 4 insertions(+), 5 deletions(-) diff --git a/src/games/ttw/.gitignore b/src/games/ttw/.gitignore index 08f775e4..cf71be77 100644 --- a/src/games/ttw/.gitignore +++ b/src/games/ttw/.gitignore @@ -1,6 +1,5 @@ -std*.log -build -CMakeLists.txt.user edit -build -vsbuild +CMakeLists.txt.user +/msbuild.log +/*std*.log +/*build From 4a198d511f85cb3d47d87f5fecb87ba8af6b6d95 Mon Sep 17 00:00:00 2001 From: Silarn Date: Mon, 7 May 2018 16:52:42 -0500 Subject: [PATCH 0608/1544] [game_morrowind] Remove the Morrowing Script Extender feature as it is irrelevant --- src/games/morrowind/src/gamemorrowind.cpp | 9 +++---- .../morrowind/src/morrowindscriptextender.cpp | 24 ------------------- .../morrowind/src/morrowindscriptextender.h | 20 ---------------- 3 files changed, 3 insertions(+), 50 deletions(-) delete mode 100644 src/games/morrowind/src/morrowindscriptextender.cpp delete mode 100644 src/games/morrowind/src/morrowindscriptextender.h diff --git a/src/games/morrowind/src/gamemorrowind.cpp b/src/games/morrowind/src/gamemorrowind.cpp index 4aed74bc..0abb7a0c 100644 --- a/src/games/morrowind/src/gamemorrowind.cpp +++ b/src/games/morrowind/src/gamemorrowind.cpp @@ -1,7 +1,6 @@ #include "gamemorrowind.h" #include "morrowindbsainvalidation.h" -#include "morrowindscriptextender.h" #include "morrowinddataarchives.h" #include "morrowindsavegameinfo.h" #include "morrowindgameplugins.h" @@ -38,7 +37,6 @@ bool GameMorrowind::init(IOrganizer *moInfo) if (!GameGamebryo::init(moInfo)) { return false; } - registerFeature(new MorrowindScriptExtender(this)); registerFeature(new MorrowindDataArchives(gameDirectory().absolutePath())); registerFeature(new MorrowindBSAInvalidation(feature(), this)); registerFeature(new MorrowindSaveGameInfo(this)); @@ -77,10 +75,9 @@ QDir GameMorrowind::documentsDirectory() const QList GameMorrowind::executables() const { return QList() - // << ExecutableInfo("MWSE", findInGameFolder(feature()->loaderName())) - << ExecutableInfo("Morrowind", findInGameFolder(binaryName())) - << ExecutableInfo("Morrowind Launcher", findInGameFolder(getLauncherName())) - << ExecutableInfo("MGE XE", findInGameFolder("MGEXEgui.exe")) + << ExecutableInfo("Morrowind", findInGameFolder(binaryName())) + << ExecutableInfo("Morrowind Launcher", findInGameFolder(getLauncherName())) + << ExecutableInfo("MGE XE", findInGameFolder("MGEXEgui.exe")) ; } diff --git a/src/games/morrowind/src/morrowindscriptextender.cpp b/src/games/morrowind/src/morrowindscriptextender.cpp deleted file mode 100644 index 91240340..00000000 --- a/src/games/morrowind/src/morrowindscriptextender.cpp +++ /dev/null @@ -1,24 +0,0 @@ -#include "morrowindscriptextender.h" - -#include -#include - -MorrowindScriptExtender::MorrowindScriptExtender(GameGamebryo const *game) : - GamebryoScriptExtender(game) -{ -} - -QString MorrowindScriptExtender::BinaryName() const -{ - return "skse_loader.exe"; -} - -QString MorrowindScriptExtender::PluginPath() const -{ - return "skse/plugins"; -} - -QStringList MorrowindScriptExtender::saveGameAttachmentExtensions() const -{ - return { "skse" }; -} diff --git a/src/games/morrowind/src/morrowindscriptextender.h b/src/games/morrowind/src/morrowindscriptextender.h deleted file mode 100644 index 5809a496..00000000 --- a/src/games/morrowind/src/morrowindscriptextender.h +++ /dev/null @@ -1,20 +0,0 @@ -#ifndef MORROWINDSCRIPTEXTENDER_H -#define MORROWINDSCRIPTEXTENDER_H - -#include "gamebryoscriptextender.h" - -class GameGamebryo; - -class MorrowindScriptExtender : public GamebryoScriptExtender -{ -public: - MorrowindScriptExtender(const GameGamebryo *game); - - virtual QString BinaryName() const override; - virtual QString PluginPath() const override; - - virtual QStringList saveGameAttachmentExtensions() const override; - -}; - -#endif // MORROWINDSCRIPTEXTENDER_H From 6629af2dd2661ababd9e8d0b571cc41e8ace44f0 Mon Sep 17 00:00:00 2001 From: Silarn Date: Mon, 7 May 2018 17:19:43 -0500 Subject: [PATCH 0609/1544] [game_morrowind] Add old MWSE Launcher to launchers just in case --- src/games/morrowind/src/gamemorrowind.cpp | 1 + 1 file changed, 1 insertion(+) diff --git a/src/games/morrowind/src/gamemorrowind.cpp b/src/games/morrowind/src/gamemorrowind.cpp index 0abb7a0c..dc4db857 100644 --- a/src/games/morrowind/src/gamemorrowind.cpp +++ b/src/games/morrowind/src/gamemorrowind.cpp @@ -75,6 +75,7 @@ QDir GameMorrowind::documentsDirectory() const QList GameMorrowind::executables() const { return QList() + << ExecutableInfo("MWSE (Launcher Method)", findInGameFolder("MWSE Launcher.exe")) << ExecutableInfo("Morrowind", findInGameFolder(binaryName())) << ExecutableInfo("Morrowind Launcher", findInGameFolder(getLauncherName())) << ExecutableInfo("MGE XE", findInGameFolder("MGEXEgui.exe")) From e52ed63315f06945aa92b42a3f352631fcaf8a22 Mon Sep 17 00:00:00 2001 From: Lost Dragonist Date: Mon, 4 Jun 2018 21:07:50 -0500 Subject: [PATCH 0610/1544] [game_ttw] Fix TTW save game parsing The lines added were taken from the FalloutNV save game code. There is no reason for the two to be different as TTW is essentially FalloutNV with specific mods. TTW save games can now be correctly read. Also includes a small fix to a build file that's probably unused. --- src/games/ttw/src/falloutttwsavegame.cpp | 2 ++ src/games/ttw/src/gameFalloutTTW.pro | 4 ++-- 2 files changed, 4 insertions(+), 2 deletions(-) diff --git a/src/games/ttw/src/falloutttwsavegame.cpp b/src/games/ttw/src/falloutttwsavegame.cpp index af206733..32bc2545 100644 --- a/src/games/ttw/src/falloutttwsavegame.cpp +++ b/src/games/ttw/src/falloutttwsavegame.cpp @@ -18,6 +18,7 @@ FalloutTTWSaveGame::FalloutTTWSaveGame(QString const &fileName, MOBase::IPluginG } file.setHasFieldMarkers(true); + file.setPluginString(GamebryoSaveGame::StringType::TYPE_BZSTRING); unsigned long width; file.read(width); @@ -46,5 +47,6 @@ FalloutTTWSaveGame::FalloutTTWSaveGame(QString const &fileName, MOBase::IPluginG file.skip(5); // unknown byte, size of plugin data //Abstract this + file.setPluginString(GamebryoSaveGame::StringType::TYPE_BSTRING); file.readPlugins(); } diff --git a/src/games/ttw/src/gameFalloutTTW.pro b/src/games/ttw/src/gameFalloutTTW.pro index bd08c6dc..b1349547 100644 --- a/src/games/ttw/src/gameFalloutTTW.pro +++ b/src/games/ttw/src/gameFalloutTTW.pro @@ -14,14 +14,14 @@ CONFIG += dll DEFINES += GAMEFALLOUTTTW_LIBRARY SOURCES += gamefalloutTTW.cpp \ - falloutttwbsaittwalidation.cpp \ + falloutttwbsainvalidation.cpp \ falloutttwscriptextender.cpp \ falloutttwdataarchives.cpp \ falloutttwsavegame.cpp \ falloutttwsavegameinfo.cpp HEADERS += gamefalloutttw.h \ - falloutttwbsaittwalidation.h \ + falloutttwbsainvalidation.h \ falloutttwscriptextender.h \ falloutttwdataarchives.h \ falloutttwsavegame.h \ From c6b2fda4a5399ea084a5667b7a051378edc1631c Mon Sep 17 00:00:00 2001 From: Silarn Date: Fri, 8 Jun 2018 17:27:03 -0500 Subject: [PATCH 0611/1544] [game_skyrimvr] Update for compatibility with latest LOOT --- src/games/skyrimvr/src/gameskyrimvr.cpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/games/skyrimvr/src/gameskyrimvr.cpp b/src/games/skyrimvr/src/gameskyrimvr.cpp index 8ee5bde4..317275aa 100644 --- a/src/games/skyrimvr/src/gameskyrimvr.cpp +++ b/src/games/skyrimvr/src/gameskyrimvr.cpp @@ -92,7 +92,7 @@ QList GameSkyrimVR::executables() const << ExecutableInfo("SKSE", findInGameFolder(feature()->loaderName())) << ExecutableInfo("Skyrim VR", findInGameFolder(binaryName())) << ExecutableInfo("Creation Kit", findInGameFolder("CreationKit.exe")) - //<< ExecutableInfo("LOOT", getLootPath()).withArgument("--game=\"Skyrim Special Edition\"") Let's not make an entry for a different game + << ExecutableInfo("LOOT", getLootPath()).withArgument("--game=\"SkyrimVR\"") ; } @@ -243,7 +243,7 @@ IPluginGame::LoadOrderMechanism GameSkyrimVR::loadOrderMechanism() const MOBase::IPluginGame::SortMechanism GameSkyrimVR::sortMechanism() const { - return SortMechanism::NONE; + return SortMechanism::LOOT; } int GameSkyrimVR::nexusModOrganizerID() const From c4229c23c229e3d8010f46d43847cdfeaa9f9580 Mon Sep 17 00:00:00 2001 From: Silarn Date: Mon, 25 Jun 2018 20:52:35 -0500 Subject: [PATCH 0612/1544] [game_skyrimvr] Corrected LOOT launch arg --- src/games/skyrimvr/src/gameskyrimvr.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/games/skyrimvr/src/gameskyrimvr.cpp b/src/games/skyrimvr/src/gameskyrimvr.cpp index 317275aa..1589650a 100644 --- a/src/games/skyrimvr/src/gameskyrimvr.cpp +++ b/src/games/skyrimvr/src/gameskyrimvr.cpp @@ -92,7 +92,7 @@ QList GameSkyrimVR::executables() const << ExecutableInfo("SKSE", findInGameFolder(feature()->loaderName())) << ExecutableInfo("Skyrim VR", findInGameFolder(binaryName())) << ExecutableInfo("Creation Kit", findInGameFolder("CreationKit.exe")) - << ExecutableInfo("LOOT", getLootPath()).withArgument("--game=\"SkyrimVR\"") + << ExecutableInfo("LOOT", getLootPath()).withArgument("--game=\"Skyrim VR\"") ; } From a8067d86762f65540de45ebb791646c7f190d12f Mon Sep 17 00:00:00 2001 From: LostDragonist Date: Tue, 24 Jul 2018 13:38:34 -0500 Subject: [PATCH 0613/1544] [game_morrowind] Update translation file --- src/games/morrowind/src/game_morrowind_en.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/games/morrowind/src/game_morrowind_en.ts b/src/games/morrowind/src/game_morrowind_en.ts index 08f74294..7316146b 100644 --- a/src/games/morrowind/src/game_morrowind_en.ts +++ b/src/games/morrowind/src/game_morrowind_en.ts @@ -4,7 +4,7 @@ GameMorrowind - + Adds support for the game Morrowind. Splash by %1 Adds support for the game Morrowind From a482351abdfc97c98134fcc49fb8c5deae49457e Mon Sep 17 00:00:00 2001 From: LostDragonist Date: Sun, 26 Aug 2018 09:58:14 -0500 Subject: [PATCH 0614/1544] [game_morrowind] Use local game settings when reading or writing plugin list --- .../morrowind/src/morrowindgameplugins.cpp | 21 +++++++++++++++++-- 1 file changed, 19 insertions(+), 2 deletions(-) diff --git a/src/games/morrowind/src/morrowindgameplugins.cpp b/src/games/morrowind/src/morrowindgameplugins.cpp index d3803c65..a78733f5 100644 --- a/src/games/morrowind/src/morrowindgameplugins.cpp +++ b/src/games/morrowind/src/morrowindgameplugins.cpp @@ -28,8 +28,18 @@ void MorrowindGamePlugins::writePluginLists(const IPluginList *pluginList) { return; } - writePluginList(pluginList, - organizer()->profile()->absolutePath() + "/Morrowind.ini"); + if (organizer()->profile()->localSettingsEnabled()) { + writePluginList( + pluginList, + organizer()->profile()->absolutePath() + "/Morrowind.ini" + ); + } else { + writePluginList( + pluginList, + organizer()->managedGame()->gameDirectory().absolutePath() + "/Morrowind.ini" + ); + } + writeLoadOrderList(pluginList, organizer()->profile()->absolutePath() + "/loadorder.txt"); @@ -39,7 +49,11 @@ void MorrowindGamePlugins::writePluginLists(const IPluginList *pluginList) { void MorrowindGamePlugins::readPluginLists(MOBase::IPluginList *pluginList) { QString loadOrderPath = organizer()->profile()->absolutePath() + "/loadorder.txt"; + QString pluginsPath = organizer()->profile()->absolutePath() + "/Morrowind.ini"; + if (!organizer()->profile()->localSettingsEnabled()) { + pluginsPath = organizer()->managedGame()->gameDirectory().absolutePath() + "/Morrowind.ini"; + } bool loadOrderIsNew = !m_LastRead.isValid() || !QFileInfo(loadOrderPath).exists() || @@ -139,6 +153,9 @@ bool MorrowindGamePlugins::readPluginList(MOBase::IPluginList *pluginList, }); QString filePath = organizer()->profile()->absolutePath() + "/Morrowind.ini"; + if (!organizer()->profile()->localSettingsEnabled()) { + filePath = organizer()->managedGame()->gameDirectory().absolutePath() + "/Morrowind.ini"; + } wchar_t buffer[256]; QStringList result; std::wstring iniFileW = QDir::toNativeSeparators(filePath).toStdWString(); From e3b538825e4d64d51887149adcb14a61c3656280 Mon Sep 17 00:00:00 2001 From: LostDragonist Date: Sun, 26 Aug 2018 10:00:04 -0500 Subject: [PATCH 0615/1544] [game_morrowind] Do not use My Games for Morrowind --- src/games/morrowind/src/gamemorrowind.cpp | 7 +------ 1 file changed, 1 insertion(+), 6 deletions(-) diff --git a/src/games/morrowind/src/gamemorrowind.cpp b/src/games/morrowind/src/gamemorrowind.cpp index dc4db857..a5e2b012 100644 --- a/src/games/morrowind/src/gamemorrowind.cpp +++ b/src/games/morrowind/src/gamemorrowind.cpp @@ -121,12 +121,7 @@ void GameMorrowind::initializeProfile(const QDir &path, ProfileSettings settings } if (settings.testFlag(IPluginGame::CONFIGURATION)) { - if (settings.testFlag(IPluginGame::PREFER_DEFAULTS) - || !QFileInfo(myGamesPath() + "/morrowind.ini").exists()) { - copyToProfile(gameDirectory().absolutePath(), path, "Morrowind.ini"); - } else { - copyToProfile(myGamesPath(), path, "Morrowind.ini"); - } + copyToProfile(gameDirectory().absolutePath(), path, "Morrowind.ini"); } } From 8e4e94b4a8acd330ed8516ff469faf5b87ea1c21 Mon Sep 17 00:00:00 2001 From: LostDragonist Date: Sun, 26 Aug 2018 11:50:00 -0500 Subject: [PATCH 0616/1544] [game_morrowind] Disable local save games as they don't work anyways --- src/games/morrowind/src/game_morrowind_en.ts | 4 ++-- src/games/morrowind/src/gamemorrowind.cpp | 2 +- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/src/games/morrowind/src/game_morrowind_en.ts b/src/games/morrowind/src/game_morrowind_en.ts index 7316146b..5ad9dfa1 100644 --- a/src/games/morrowind/src/game_morrowind_en.ts +++ b/src/games/morrowind/src/game_morrowind_en.ts @@ -106,13 +106,13 @@ Splash by %1 QObject - + failed to set game file key (errorcode %1) - + Some of your plugins have invalid names! These plugins can not be loaded by the game. Please see mo_interface.log for a list of affected plugins and rename them. diff --git a/src/games/morrowind/src/gamemorrowind.cpp b/src/games/morrowind/src/gamemorrowind.cpp index a5e2b012..a6527a20 100644 --- a/src/games/morrowind/src/gamemorrowind.cpp +++ b/src/games/morrowind/src/gamemorrowind.cpp @@ -40,7 +40,7 @@ bool GameMorrowind::init(IOrganizer *moInfo) registerFeature(new MorrowindDataArchives(gameDirectory().absolutePath())); registerFeature(new MorrowindBSAInvalidation(feature(), this)); registerFeature(new MorrowindSaveGameInfo(this)); - registerFeature(new GamebryoLocalSavegames(gameDirectory().absolutePath(), "morrowind.ini")); + //registerFeature(new GamebryoLocalSavegames(gameDirectory().absolutePath(), "morrowind.ini")); // local save games are not functional yet registerFeature(new MorrowindGamePlugins(moInfo)); registerFeature(new GamebryoUnmangedMods(this)); m_Organizer = moInfo; From 7d8215537768d4b7ea6b551bc1cb3056d66ded66 Mon Sep 17 00:00:00 2001 From: LostDragonist Date: Sun, 26 Aug 2018 10:07:52 -0500 Subject: [PATCH 0617/1544] [game_morrowind] Change version to 0.2.1 --- src/games/morrowind/src/gamemorrowind.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/games/morrowind/src/gamemorrowind.cpp b/src/games/morrowind/src/gamemorrowind.cpp index a6527a20..6317c157 100644 --- a/src/games/morrowind/src/gamemorrowind.cpp +++ b/src/games/morrowind/src/gamemorrowind.cpp @@ -100,7 +100,7 @@ QString GameMorrowind::description() const MOBase::VersionInfo GameMorrowind::version() const { - return VersionInfo(0, 2, 0, VersionInfo::RELEASE_FINAL); + return VersionInfo(0, 2, 1, VersionInfo::RELEASE_FINAL); } bool GameMorrowind::isActive() const From 095feb546eb155715969c167aa3247a91ae22287 Mon Sep 17 00:00:00 2001 From: LostDragonist Date: Sun, 26 Aug 2018 17:00:49 -0500 Subject: [PATCH 0618/1544] Implement local save game update function --- src/gamebryolocalsavegames.cpp | 22 ++++++++++++++-------- src/gamebryolocalsavegames.h | 1 + 2 files changed, 15 insertions(+), 8 deletions(-) diff --git a/src/gamebryolocalsavegames.cpp b/src/gamebryolocalsavegames.cpp index 1808c2b0..408a39cf 100644 --- a/src/gamebryolocalsavegames.cpp +++ b/src/gamebryolocalsavegames.cpp @@ -36,6 +36,17 @@ GamebryoLocalSavegames::GamebryoLocalSavegames(const QDir &myGamesDir, {} +MappingType GamebryoLocalSavegames::mappings(const QDir &profileSaveDir) const +{ + return {{ + profileSaveDir.absolutePath(), + m_LocalSavesDir.absolutePath(), + true, + true + }}; +} + + void GamebryoLocalSavegames::prepareProfile(MOBase::IProfile *profile) { bool enable = profile->localSavesEnabled(); @@ -88,12 +99,7 @@ void GamebryoLocalSavegames::prepareProfile(MOBase::IProfile *profile) } -MappingType GamebryoLocalSavegames::mappings(const QDir &profileSaveDir) const +bool GamebryoLocalSavegames::updateSaveGames(MOBase::IProfile *profile) { - return {{ - profileSaveDir.absolutePath(), - m_LocalSavesDir.absolutePath(), - true, - true - }}; -} + return false; +} \ No newline at end of file diff --git a/src/gamebryolocalsavegames.h b/src/gamebryolocalsavegames.h index eef7b9f3..550ba242 100644 --- a/src/gamebryolocalsavegames.h +++ b/src/gamebryolocalsavegames.h @@ -34,6 +34,7 @@ public: virtual MappingType mappings(const QDir &profileSaveDir) const override; virtual void prepareProfile(MOBase::IProfile *profile) override; + virtual bool updateSaveGames(MOBase::IProfile *profile) override; private: From f3304f4bda9ef02f7bae92991983190db47213f4 Mon Sep 17 00:00:00 2001 From: LostDragonist Date: Sun, 26 Aug 2018 13:30:25 -0500 Subject: [PATCH 0619/1544] [game_morrowind] Implement local game saves --- src/games/morrowind/src/gameMorrowind.pro | 6 +- src/games/morrowind/src/game_morrowind_en.ts | 25 ++++--- src/games/morrowind/src/gamemorrowind.cpp | 8 +-- .../morrowind/src/morrowindlocalsavegames.cpp | 70 +++++++++++++++++++ .../morrowind/src/morrowindlocalsavegames.h | 46 ++++++++++++ 5 files changed, 136 insertions(+), 19 deletions(-) create mode 100644 src/games/morrowind/src/morrowindlocalsavegames.cpp create mode 100644 src/games/morrowind/src/morrowindlocalsavegames.h diff --git a/src/games/morrowind/src/gameMorrowind.pro b/src/games/morrowind/src/gameMorrowind.pro index 96916e2c..e8128290 100644 --- a/src/games/morrowind/src/gameMorrowind.pro +++ b/src/games/morrowind/src/gameMorrowind.pro @@ -16,17 +16,19 @@ SOURCES += gamemorrowind.cpp \ morrowindbsainvalidation.cpp \ morrowindscriptextender.cpp \ morrowinddataarchives.cpp \ + morrowindlocalsavegames.cpp \ morrowindsavegame.cpp \ morrowindsavegameinfo.cpp \ - morrowindgameplugins.cpp + morrowindgameplugins.cpp HEADERS += gamemorrowind.h \ morrowindbsainvalidation.h \ morrowindscriptextender.h \ morrowinddataarchives.h \ + morrowindlocalsavegames.h \ morrowindsavegame.h \ morrowindsavegameinfo.h \ - morrowindgameplugins.h + morrowindgameplugins.h CONFIG(debug, debug|release) { LIBS += -L"$${OUT_PWD}/../gameGamebryo/debug" diff --git a/src/games/morrowind/src/game_morrowind_en.ts b/src/games/morrowind/src/game_morrowind_en.ts index 5ad9dfa1..636f9592 100644 --- a/src/games/morrowind/src/game_morrowind_en.ts +++ b/src/games/morrowind/src/game_morrowind_en.ts @@ -7,7 +7,6 @@ Adds support for the game Morrowind. Splash by %1 - Adds support for the game Morrowind @@ -106,14 +105,13 @@ Splash by %1 QObject - - failed to set game file key (errorcode %1) + + failed to deactivate BSA invalidation in "%1" (errorcode %2) - - - Some of your plugins have invalid names! These plugins can not be loaded by the game. Please see mo_interface.log for a list of affected plugins and rename them. + + failed to activate BSA invalidation in "%1" (errorcode %2) @@ -123,13 +121,9 @@ Splash by %1 - - failed to deactivate BSA invalidation in "%1" (errorcode %2) - - - - - failed to activate BSA invalidation in "%1" (errorcode %2) + + + Some of your plugins have invalid names! These plugins can not be loaded by the game. Please see mo_interface.log for a list of affected plugins and rename them. @@ -152,5 +146,10 @@ Splash by %1 failed to query registry path (read): %1 + + + failed to set game file key (errorcode %1) + + diff --git a/src/games/morrowind/src/gamemorrowind.cpp b/src/games/morrowind/src/gamemorrowind.cpp index 6317c157..eafa7e8c 100644 --- a/src/games/morrowind/src/gamemorrowind.cpp +++ b/src/games/morrowind/src/gamemorrowind.cpp @@ -2,13 +2,13 @@ #include "morrowindbsainvalidation.h" #include "morrowinddataarchives.h" -#include "morrowindsavegameinfo.h" #include "morrowindgameplugins.h" +#include "morrowindlocalsavegames.h" +#include "morrowindsavegameinfo.h" #include "executableinfo.h" #include "pluginsetting.h" -#include #include #include @@ -40,7 +40,7 @@ bool GameMorrowind::init(IOrganizer *moInfo) registerFeature(new MorrowindDataArchives(gameDirectory().absolutePath())); registerFeature(new MorrowindBSAInvalidation(feature(), this)); registerFeature(new MorrowindSaveGameInfo(this)); - //registerFeature(new GamebryoLocalSavegames(gameDirectory().absolutePath(), "morrowind.ini")); // local save games are not functional yet + registerFeature(new MorrowindLocalSavegames(gameDirectory().absolutePath())); registerFeature(new MorrowindGamePlugins(moInfo)); registerFeature(new GamebryoUnmangedMods(this)); m_Organizer = moInfo; @@ -100,7 +100,7 @@ QString GameMorrowind::description() const MOBase::VersionInfo GameMorrowind::version() const { - return VersionInfo(0, 2, 1, VersionInfo::RELEASE_FINAL); + return VersionInfo(0, 2, 2, VersionInfo::RELEASE_FINAL); } bool GameMorrowind::isActive() const diff --git a/src/games/morrowind/src/morrowindlocalsavegames.cpp b/src/games/morrowind/src/morrowindlocalsavegames.cpp new file mode 100644 index 00000000..056db597 --- /dev/null +++ b/src/games/morrowind/src/morrowindlocalsavegames.cpp @@ -0,0 +1,70 @@ +/* +Copyright (C) 2015 Sebastian Herbord. All rights reserved. + +This library is free software; you can redistribute it and/or +modify it under the terms of the GNU Lesser General Public +License as published by the Free Software Foundation; either +version 3 of the License, or (at your option) any later version. + +This library is distributed in the hope that it will be useful, +but WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +Lesser General Public License for more details. + +You should have received a copy of the GNU Lesser General Public +License along with this library; if not, write to the Free Software +Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA +*/ + + +#include "morrowindlocalsavegames.h" +#include +#include +#include +#include +#include + + +MorrowindLocalSavegames::MorrowindLocalSavegames(const QDir &gameInstallDir) + : m_GameInstallDir(gameInstallDir.absolutePath()) +{} + +void MorrowindLocalSavegames::prepareProfile(MOBase::IProfile *profile) +{ + updateSaveGames(profile); +} + + +MappingType MorrowindLocalSavegames::mappings(const QDir &profileSaveDir) const +{ + return {{ + profileSaveDir.absolutePath(), + m_GameInstallDir.absolutePath() + "/Saves", + true, + true + }}; +} + + +bool MorrowindLocalSavegames::updateSaveGames(MOBase::IProfile *profile) +{ + bool dirty = false; + + if (profile->localSavesEnabled()) { + if (m_GameInstallDir.exists("Saves")) { + if (!m_GameInstallDir.rename("Saves", "_Saves")) { + qCritical("Unable to enable Morrowind local save games!"); + } + dirty = true; + } + } else { + if (m_GameInstallDir.exists("_Saves")) { + if (!m_GameInstallDir.rename("_Saves", "Saves")) { + qCritical("Unable to disable Morrowind local save games!"); + } + dirty = true; + } + } + + return dirty; +} diff --git a/src/games/morrowind/src/morrowindlocalsavegames.h b/src/games/morrowind/src/morrowindlocalsavegames.h new file mode 100644 index 00000000..cd1e8e8e --- /dev/null +++ b/src/games/morrowind/src/morrowindlocalsavegames.h @@ -0,0 +1,46 @@ +/* +Copyright (C) 2015 Sebastian Herbord. All rights reserved. + +This library is free software; you can redistribute it and/or +modify it under the terms of the GNU Lesser General Public +License as published by the Free Software Foundation; either +version 3 of the License, or (at your option) any later version. + +This library is distributed in the hope that it will be useful, +but WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +Lesser General Public License for more details. + +You should have received a copy of the GNU Lesser General Public +License along with this library; if not, write to the Free Software +Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA +*/ + + +#ifndef MORROWINDLOCALSAVEGAMES_H +#define MORROWINDLOCALSAVEGAMES_H + + +#include + +#include +#include + +class MorrowindLocalSavegames : public LocalSavegames +{ + +public: + MorrowindLocalSavegames(const QDir &m_GameInstallDir); + + virtual MappingType mappings(const QDir &profileSaveDir) const override; + virtual void prepareProfile(MOBase::IProfile *profile) override; + virtual bool updateSaveGames(MOBase::IProfile *profile) override; + +private: + + QDir m_GameInstallDir; + +}; + + +#endif // MORROWINDLOCALSAVEGAMES_H From fc2e033b9eab8cf5e22114edbb82f348f8691b2a Mon Sep 17 00:00:00 2001 From: LostDragonist Date: Sat, 1 Sep 2018 20:42:42 -0500 Subject: [PATCH 0620/1544] [game_ttw] Fix priority of plugins based on TTW documentation --- src/games/ttw/src/gamefalloutttw.cpp | 26 +++++++++++++++++++------- 1 file changed, 19 insertions(+), 7 deletions(-) diff --git a/src/games/ttw/src/gamefalloutttw.cpp b/src/games/ttw/src/gamefalloutttw.cpp index 9bee6723..337e5b98 100644 --- a/src/games/ttw/src/gamefalloutttw.cpp +++ b/src/games/ttw/src/gamefalloutttw.cpp @@ -80,7 +80,7 @@ QString GameFalloutTTW::description() const MOBase::VersionInfo GameFalloutTTW::version() const { - return VersionInfo(1, 0, 0, VersionInfo::RELEASE_FINAL); + return VersionInfo(1, 1, 0, VersionInfo::RELEASE_FINAL); } bool GameFalloutTTW::isActive() const @@ -131,11 +131,23 @@ QString GameFalloutTTW::steamAPPId() const 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" }; + return { "falloutnv.esm", + "deadmoney.esm", + "honesthearts.esm", + "oldworldblues.esm", + "lonesomeroad.esm", + "gunrunnersarsenal.esm", + "caravanpack.esm", + "classicpack.esm", + "mercenarypack.esm", + "tribalpack.esm", + "fallout3.esm", + "anchorage.esm", + "thepitt.esm", + "brokensteel.esm", + "pointlookout.esm", + "zeta.esm", + "taleoftwowastelands.esm" }; } QString GameFalloutTTW::binaryName() const @@ -210,4 +222,4 @@ MappingType GameFalloutTTW::mappings() const } return result; -} \ No newline at end of file +} From 2b48502ba5b20684f98313b5ac5c0eae78a1a68c Mon Sep 17 00:00:00 2001 From: LostDragonist Date: Thu, 6 Sep 2018 11:48:20 -0500 Subject: [PATCH 0621/1544] [game_fallout76] Add Ultra High Resolution DLC to the list of primary plugins --- src/games/fallout76/src/gamefallout4.cpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/games/fallout76/src/gamefallout4.cpp b/src/games/fallout76/src/gamefallout4.cpp index 17924359..3c4c5922 100644 --- a/src/games/fallout76/src/gamefallout4.cpp +++ b/src/games/fallout76/src/gamefallout4.cpp @@ -80,7 +80,7 @@ QString GameFallout4::description() const MOBase::VersionInfo GameFallout4::version() const { - return VersionInfo(0, 3, 0, VersionInfo::RELEASE_BETA); + return VersionInfo(0, 3, 1, VersionInfo::RELEASE_FINAL); } bool GameFallout4::isActive() const @@ -130,7 +130,7 @@ QString GameFallout4::steamAPPId() const QStringList GameFallout4::primaryPlugins() const { QStringList plugins = {"fallout4.esm", "dlcrobot.esm", "dlcworkshop01.esm", "dlccoast.esm", "dlcworkshop02.esm", - "dlcworkshop03.esm", "dlcnukaworld.esm"}; + "dlcworkshop03.esm", "dlcnukaworld.esm", "dlcultrahighresolution.esm"}; plugins.append(CCPlugins()); From 3ff5f1f97932016c5e1aef083fc6913e4394d91f Mon Sep 17 00:00:00 2001 From: LostDragonist Date: Thu, 6 Sep 2018 11:48:20 -0500 Subject: [PATCH 0622/1544] [game_fallout4] Add Ultra High Resolution DLC to the list of primary plugins --- src/games/fallout4/src/gamefallout4.cpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/games/fallout4/src/gamefallout4.cpp b/src/games/fallout4/src/gamefallout4.cpp index 17924359..3c4c5922 100644 --- a/src/games/fallout4/src/gamefallout4.cpp +++ b/src/games/fallout4/src/gamefallout4.cpp @@ -80,7 +80,7 @@ QString GameFallout4::description() const MOBase::VersionInfo GameFallout4::version() const { - return VersionInfo(0, 3, 0, VersionInfo::RELEASE_BETA); + return VersionInfo(0, 3, 1, VersionInfo::RELEASE_FINAL); } bool GameFallout4::isActive() const @@ -130,7 +130,7 @@ QString GameFallout4::steamAPPId() const QStringList GameFallout4::primaryPlugins() const { QStringList plugins = {"fallout4.esm", "dlcrobot.esm", "dlcworkshop01.esm", "dlccoast.esm", "dlcworkshop02.esm", - "dlcworkshop03.esm", "dlcnukaworld.esm"}; + "dlcworkshop03.esm", "dlcnukaworld.esm", "dlcultrahighresolution.esm"}; plugins.append(CCPlugins()); From 598a4144ca5bc0feca04804b49c59b2d533c5cbc Mon Sep 17 00:00:00 2001 From: Al Date: Sun, 9 Sep 2018 23:28:32 +0200 Subject: [PATCH 0623/1544] Archive conflicts (#4) * Necessary changes for querying plugin loadorder for archive sorting * Necessary changes for querying plugin loadorder for archive sorting * Merge fixes for archive parsing * Don't override filetime order and move inactive plugins to the bottom * Necessary changes for querying plugin loadorder for archive sorting * Necessary changes for querying plugin loadorder for archive sorting * Merge fixes for archive parsing * Don't override filetime order and move inactive plugins to the bottom * Compile fixes --- src/gamebryogameplugins.cpp | 59 ++++++++++++++++++++++--------------- src/gamebryogameplugins.h | 9 +++--- 2 files changed, 41 insertions(+), 27 deletions(-) diff --git a/src/gamebryogameplugins.cpp b/src/gamebryogameplugins.cpp index a65a2a12..6b2c51d4 100644 --- a/src/gamebryogameplugins.cpp +++ b/src/gamebryogameplugins.cpp @@ -50,16 +50,36 @@ void GamebryoGamePlugins::readPluginLists(MOBase::IPluginList *pluginList) { if (loadOrderIsNew || !pluginsIsNew) { // read both files if they are both new or both older than the last read - readLoadOrderList(pluginList, loadOrderPath); - readPluginList(pluginList, false); + QStringList loadOrder = readLoadOrderList(pluginList, loadOrderPath); + pluginList->setLoadOrder(loadOrder); + readPluginList(pluginList); } else { - // If the plugins is new but not loadorder, we must reparse the load order from the plugin files - readPluginList(pluginList, true); + // If the plugins is new but not loadorder, we must reparse the load order from the plugin files + QStringList loadOrder = readPluginList(pluginList); + pluginList->setLoadOrder(loadOrder); } m_LastRead = QDateTime::currentDateTime(); } +void GamebryoGamePlugins::getLoadOrder(QStringList &loadOrder) { + QString loadOrderPath = + organizer()->profile()->absolutePath() + "/loadorder.txt"; + QString pluginsPath = organizer()->profile()->absolutePath() + "/plugins.txt"; + + bool loadOrderIsNew = !m_LastRead.isValid() || + !QFileInfo(loadOrderPath).exists() || + QFileInfo(loadOrderPath).lastModified() > m_LastRead; + bool pluginsIsNew = !m_LastRead.isValid() || + QFileInfo(pluginsPath).lastModified() > m_LastRead; + + if (loadOrderIsNew || !pluginsIsNew) { + loadOrder = readLoadOrderList(m_Organizer->pluginList(), loadOrderPath); + } else { + loadOrder = readPluginList(m_Organizer->pluginList()); + } +} + void GamebryoGamePlugins::writePluginList(const MOBase::IPluginList *pluginList, const QString &filePath) { return writeList(pluginList, filePath, false); @@ -121,19 +141,18 @@ void GamebryoGamePlugins::writeList(const IPluginList *pluginList, } } -bool GamebryoGamePlugins::readLoadOrderList(MOBase::IPluginList *pluginList, +QStringList GamebryoGamePlugins::readLoadOrderList(MOBase::IPluginList *pluginList, const QString &filePath) { QFile file(filePath); if (!file.open(QIODevice::ReadOnly)) { - readPluginList(pluginList, true); + return readPluginList(pluginList); } else { - QStringList plugins = organizer()->managedGame()->primaryPlugins(); + QStringList pluginNames = organizer()->managedGame()->primaryPlugins(); ON_BLOCK_EXIT([&file]() { file.close(); }); if (file.size() == 0) { - readPluginList(pluginList, true); - return true; + return readPluginList(pluginList); } while (!file.atEnd()) { QByteArray line = file.readLine().trimmed(); @@ -143,20 +162,17 @@ bool GamebryoGamePlugins::readLoadOrderList(MOBase::IPluginList *pluginList, } if (modName.size() > 0) { - if (!plugins.contains(modName, Qt::CaseInsensitive)) { - plugins.append(modName); + if (!pluginNames.contains(modName, Qt::CaseInsensitive)) { + pluginNames.append(modName); } } } - pluginList->setLoadOrder(plugins); + return pluginNames; } - - return true; } -bool GamebryoGamePlugins::readPluginList(MOBase::IPluginList *pluginList, - bool useLoadOrder) { +QStringList GamebryoGamePlugins::readPluginList(MOBase::IPluginList *pluginList) { QStringList primary = organizer()->managedGame()->primaryPlugins(); for (const QString &pluginName : primary) { if (pluginList->state(pluginName) != IPluginList::STATE_MISSING) { @@ -221,19 +237,16 @@ bool GamebryoGamePlugins::readPluginList(MOBase::IPluginList *pluginList, } for (const QString &pluginName : plugins) - if (!activePlugins.contains(pluginName)) - inactivePlugins.push_back(pluginName); + if (!activePlugins.contains(pluginName)) + inactivePlugins.push_back(pluginName); for (const QString &pluginName : inactivePlugins) - pluginList->setState(pluginName, IPluginList::STATE_INACTIVE); + pluginList->setState(pluginName, IPluginList::STATE_INACTIVE); } else { for (const QString &pluginName : plugins) { pluginList->setState(pluginName, IPluginList::STATE_INACTIVE); } } - if (useLoadOrder) - pluginList->setLoadOrder(primary + plugins); - - return true; + return primary + plugins; } diff --git a/src/gamebryogameplugins.h b/src/gamebryogameplugins.h index 0e714b9c..7fff3c9c 100644 --- a/src/gamebryogameplugins.h +++ b/src/gamebryogameplugins.h @@ -6,6 +6,7 @@ #include #include #include +#include class GamebryoGamePlugins : public GamePlugins { public: @@ -13,6 +14,7 @@ public: virtual void writePluginLists(const MOBase::IPluginList *pluginList) override; virtual void readPluginLists(MOBase::IPluginList *pluginList) override; + virtual void getLoadOrder(QStringList &loadOrder) override; protected: QTextCodec *utf8Codec() const { return m_Utf8Codec; } @@ -24,12 +26,12 @@ protected: const QString &filePath); virtual void writeLoadOrderList(const MOBase::IPluginList *pluginList, const QString &filePath); - virtual bool readLoadOrderList(MOBase::IPluginList *pluginList, + virtual QStringList readLoadOrderList(MOBase::IPluginList *pluginList, const QString &filePath); - virtual bool readPluginList(MOBase::IPluginList *pluginList, bool useLoadOrder); + virtual QStringList readPluginList(MOBase::IPluginList *pluginList); protected: - + MOBase::IOrganizer *m_Organizer; QDateTime m_LastRead; private: @@ -37,7 +39,6 @@ private: bool loadOrder); private: - MOBase::IOrganizer *m_Organizer; QTextCodec *m_Utf8Codec; QTextCodec *m_LocalCodec; From 8016cddbbc392e7e32145123b32b6dfdd6f21214 Mon Sep 17 00:00:00 2001 From: Al Date: Sun, 9 Sep 2018 23:29:12 +0200 Subject: [PATCH 0624/1544] [game_morrowind] Don't override filetime order and move inactive plugins to the bottom #2 (#8) --- .../morrowind/src/morrowindgameplugins.cpp | 18 ++++++++---------- src/games/morrowind/src/morrowindgameplugins.h | 2 +- 2 files changed, 9 insertions(+), 11 deletions(-) diff --git a/src/games/morrowind/src/morrowindgameplugins.cpp b/src/games/morrowind/src/morrowindgameplugins.cpp index a78733f5..d4236bbe 100644 --- a/src/games/morrowind/src/morrowindgameplugins.cpp +++ b/src/games/morrowind/src/morrowindgameplugins.cpp @@ -63,11 +63,13 @@ void MorrowindGamePlugins::readPluginLists(MOBase::IPluginList *pluginList) { if (loadOrderIsNew || !pluginsIsNew) { // read both files if they are both new or both older than the last read - readLoadOrderList(pluginList, loadOrderPath); - readPluginList(pluginList, false); + QStringList loadOrder = readLoadOrderList(pluginList, loadOrderPath); + pluginList->setLoadOrder(loadOrder); + readPluginList(pluginList); } else { - // If the plugins is new but not loadorder, we must reparse the load order from the plugin files - readPluginList(pluginList, true); + // If the plugins is new but not loadorder, we must reparse the load order from the plugin files + QStringList loadOrder = readPluginList(pluginList); + pluginList->setLoadOrder(loadOrder); } m_LastRead = QDateTime::currentDateTime(); @@ -121,8 +123,7 @@ void MorrowindGamePlugins::writeList(const IPluginList *pluginList, } } -bool MorrowindGamePlugins::readPluginList(MOBase::IPluginList *pluginList, - bool useLoadOrder) { +QStringList MorrowindGamePlugins::readPluginList(MOBase::IPluginList *pluginList) { QStringList primary = organizer()->managedGame()->primaryPlugins(); for (const QString &pluginName : primary) { if (pluginList->state(pluginName) != IPluginList::STATE_MISSING) { @@ -183,8 +184,5 @@ bool MorrowindGamePlugins::readPluginList(MOBase::IPluginList *pluginList, for (const QString &pluginName : inactivePlugins) pluginList->setState(pluginName, IPluginList::STATE_INACTIVE); - if (useLoadOrder) - pluginList->setLoadOrder(primary + plugins); - - return true; + return primary + plugins; } \ No newline at end of file diff --git a/src/games/morrowind/src/morrowindgameplugins.h b/src/games/morrowind/src/morrowindgameplugins.h index 7c60628b..81c31a0c 100644 --- a/src/games/morrowind/src/morrowindgameplugins.h +++ b/src/games/morrowind/src/morrowindgameplugins.h @@ -14,7 +14,7 @@ public: protected: virtual void writePluginList(const MOBase::IPluginList *pluginList, const QString &filePath) override; - virtual bool readPluginList(MOBase::IPluginList *pluginList, bool useLoadOrder) override; + virtual QStringList readPluginList(MOBase::IPluginList *pluginList) override; private: virtual void writeList(const MOBase::IPluginList *pluginList, const QString &filePath, From 4451a29cfbfcb46dcf7cc998e3da5236c8502c78 Mon Sep 17 00:00:00 2001 From: Al Date: Sun, 9 Sep 2018 23:29:28 +0200 Subject: [PATCH 0625/1544] [game_skyrimvr] Merge fixes for archive parsing (#6) --- .../skyrimvr/src/skyrimvrgameplugins.cpp | 114 ++++++++++-------- src/games/skyrimvr/src/skyrimvrgameplugins.h | 4 +- 2 files changed, 67 insertions(+), 51 deletions(-) diff --git a/src/games/skyrimvr/src/skyrimvrgameplugins.cpp b/src/games/skyrimvr/src/skyrimvrgameplugins.cpp index df0700b1..e6818ed1 100644 --- a/src/games/skyrimvr/src/skyrimvrgameplugins.cpp +++ b/src/games/skyrimvr/src/skyrimvrgameplugins.cpp @@ -21,6 +21,25 @@ SkyrimVRGamePlugins::SkyrimVRGamePlugins(IOrganizer *organizer) { } +void SkyrimVRGamePlugins::getLoadOrder(QStringList &loadOrder) { + QString loadOrderPath = + organizer()->profile()->absolutePath() + "/loadorder.txt"; + QString pluginsPath = organizer()->profile()->absolutePath() + "/plugins.txt"; + + bool loadOrderIsNew = !m_LastRead.isValid() || + !QFileInfo(loadOrderPath).exists() || + QFileInfo(loadOrderPath).lastModified() > m_LastRead; + bool pluginsIsNew = !m_LastRead.isValid() || + QFileInfo(pluginsPath).lastModified() > m_LastRead; + + if (loadOrderIsNew || !pluginsIsNew) { + loadOrder = readLoadOrderList(m_Organizer->pluginList(), loadOrderPath); + } + else { + loadOrder = readPluginList(m_Organizer->pluginList()); + } +} + void SkyrimVRGamePlugins::writePluginList(const IPluginList *pluginList, const QString &filePath) { SafeWriteFile file(filePath); @@ -45,22 +64,23 @@ void SkyrimVRGamePlugins::writePluginList(const IPluginList *pluginList, //TODO: do not write plugins in OFFICIAL_FILES container for (const QString &pluginName : plugins) { - if (!PrimaryPlugins.contains(pluginName,Qt::CaseInsensitive)) { - if (pluginList->state(pluginName) == IPluginList::STATE_ACTIVE) { - if (!textCodec->canEncode(pluginName)) { - invalidFileNames = true; - qCritical("invalid plugin name %s", qPrintable(pluginName)); - } - else - { - file->write("*"); - file->write(textCodec->fromUnicode(pluginName)); - } - file->write("\r\n"); - ++writtenCount; + if (!PrimaryPlugins.contains(pluginName,Qt::CaseInsensitive)) { + if (pluginList->state(pluginName) == IPluginList::STATE_ACTIVE) { + if (!textCodec->canEncode(pluginName)) { + invalidFileNames = true; + qCritical("invalid plugin name %s", qPrintable(pluginName)); } else { + file->write("*"); + file->write(textCodec->fromUnicode(pluginName)); + + } + file->write("\r\n"); + ++writtenCount; + } + else + { if (!textCodec->canEncode(pluginName)) { invalidFileNames = true; qCritical("invalid plugin name %s", qPrintable(pluginName)); @@ -87,8 +107,7 @@ void SkyrimVRGamePlugins::writePluginList(const IPluginList *pluginList, } } -bool SkyrimVRGamePlugins::readPluginList(MOBase::IPluginList *pluginList, - bool useLoadOrder) +QStringList SkyrimVRGamePlugins::readPluginList(MOBase::IPluginList *pluginList) { QStringList plugins = pluginList->pluginNames(); QStringList primaryPlugins = organizer()->managedGame()->primaryPlugins(); @@ -100,11 +119,12 @@ bool SkyrimVRGamePlugins::readPluginList(MOBase::IPluginList *pluginList, } } + QString filePath = organizer()->profile()->absolutePath() + "/plugins.txt"; QFile file(filePath); if (!file.open(QIODevice::ReadOnly)) { qWarning("%s not found", qPrintable(filePath)); - return false; + return loadOrder; } ON_BLOCK_EXIT([&]() { file.close(); }); @@ -112,7 +132,7 @@ bool SkyrimVRGamePlugins::readPluginList(MOBase::IPluginList *pluginList, // MO stores at least a header in the file. if it's completely empty the // file is broken qWarning("%s empty", qPrintable(filePath)); - return false; + return loadOrder; } while (!file.atEnd()) { @@ -121,33 +141,33 @@ bool SkyrimVRGamePlugins::readPluginList(MOBase::IPluginList *pluginList, if ((line.size() > 0) && (line.at(0) != '#')) { pluginName = localCodec()->toUnicode(line.trimmed().constData()); } - if (!primaryPlugins.contains(pluginName, Qt::CaseInsensitive)) { - if (pluginName.startsWith('*')) { - pluginName.remove(0, 1); - if (pluginName.size() > 0) { - pluginList->setState(pluginName, IPluginList::STATE_ACTIVE); - plugins.removeAll(pluginName); - if (!loadOrder.contains(pluginName, Qt::CaseInsensitive)) { - loadOrder.append(pluginName); - } - } - } - else - { - if (pluginName.size() > 0) { - pluginList->setState(pluginName, IPluginList::STATE_INACTIVE); - plugins.removeAll(pluginName); - if (!loadOrder.contains(pluginName, Qt::CaseInsensitive)) { - loadOrder.append(pluginName); - } - } - } - } - else - { - pluginName.remove(0, 1); - plugins.removeAll(pluginName); - } + if (!primaryPlugins.contains(pluginName, Qt::CaseInsensitive)) { + if (pluginName.startsWith('*')) { + pluginName.remove(0, 1); + if (pluginName.size() > 0) { + pluginList->setState(pluginName, IPluginList::STATE_ACTIVE); + plugins.removeAll(pluginName); + if (!loadOrder.contains(pluginName, Qt::CaseInsensitive)) { + loadOrder.append(pluginName); + } + } + } + else + { + if (pluginName.size() > 0) { + pluginList->setState(pluginName, IPluginList::STATE_INACTIVE); + plugins.removeAll(pluginName); + if (!loadOrder.contains(pluginName, Qt::CaseInsensitive)) { + loadOrder.append(pluginName); + } + } + } + } + else + { + pluginName.remove(0, 1); + plugins.removeAll(pluginName); + } } file.close(); @@ -157,9 +177,5 @@ bool SkyrimVRGamePlugins::readPluginList(MOBase::IPluginList *pluginList, pluginList->setState(pluginName, IPluginList::STATE_INACTIVE); } - if (useLoadOrder) { - pluginList->setLoadOrder(loadOrder); - } - - return true; + return loadOrder; } diff --git a/src/games/skyrimvr/src/skyrimvrgameplugins.h b/src/games/skyrimvr/src/skyrimvrgameplugins.h index 775e2a72..280ec37f 100644 --- a/src/games/skyrimvr/src/skyrimvrgameplugins.h +++ b/src/games/skyrimvr/src/skyrimvrgameplugins.h @@ -16,8 +16,8 @@ public: protected: virtual void writePluginList(const MOBase::IPluginList *pluginList, const QString &filePath) override; - virtual bool readPluginList(MOBase::IPluginList *pluginList, - bool useLoadOrder) override; + virtual QStringList readPluginList(MOBase::IPluginList *pluginList) override; + virtual void getLoadOrder(QStringList &loadOrder) override; private: std::map m_LastSaveHash; From 109306bfe4c3562bfacff347196d8c55ef20dbab Mon Sep 17 00:00:00 2001 From: Al Date: Sun, 9 Sep 2018 23:29:37 +0200 Subject: [PATCH 0626/1544] [game_skyrimse] Archive conflicts (#3) * Necessary changes for querying plugin loadorder for archive sorting * Necessary changes for querying plugin loadorder for archive sorting * Merge fixes for archive parsing * Necessary changes for querying plugin loadorder for archive sorting * Necessary changes for querying plugin loadorder for archive sorting * Merge fixes for archive parsing --- .../skyrimse/src/skyrimsegameplugins.cpp | 59 ++++++++++++------- src/games/skyrimse/src/skyrimsegameplugins.h | 4 +- 2 files changed, 39 insertions(+), 24 deletions(-) diff --git a/src/games/skyrimse/src/skyrimsegameplugins.cpp b/src/games/skyrimse/src/skyrimsegameplugins.cpp index 7657ab9b..6d9cb95c 100644 --- a/src/games/skyrimse/src/skyrimsegameplugins.cpp +++ b/src/games/skyrimse/src/skyrimsegameplugins.cpp @@ -21,6 +21,25 @@ SkyrimSEGamePlugins::SkyrimSEGamePlugins(IOrganizer *organizer) { } +void SkyrimSEGamePlugins::getLoadOrder(QStringList &loadOrder) { + QString loadOrderPath = + organizer()->profile()->absolutePath() + "/loadorder.txt"; + QString pluginsPath = organizer()->profile()->absolutePath() + "/plugins.txt"; + + bool loadOrderIsNew = !m_LastRead.isValid() || + !QFileInfo(loadOrderPath).exists() || + QFileInfo(loadOrderPath).lastModified() > m_LastRead; + bool pluginsIsNew = !m_LastRead.isValid() || + QFileInfo(pluginsPath).lastModified() > m_LastRead; + + if (loadOrderIsNew || !pluginsIsNew) { + loadOrder = readLoadOrderList(m_Organizer->pluginList(), loadOrderPath); + } + else { + loadOrder = readPluginList(m_Organizer->pluginList()); + } +} + void SkyrimSEGamePlugins::writePluginList(const IPluginList *pluginList, const QString &filePath) { SafeWriteFile file(filePath); @@ -46,20 +65,20 @@ void SkyrimSEGamePlugins::writePluginList(const IPluginList *pluginList, //TODO: do not write plugins in OFFICIAL_FILES container for (const QString &pluginName : plugins) { if (!PrimaryPlugins.contains(pluginName,Qt::CaseInsensitive)) { - if (pluginList->state(pluginName) == IPluginList::STATE_ACTIVE) { - if (!textCodec->canEncode(pluginName)) { - invalidFileNames = true; - qCritical("invalid plugin name %s", qPrintable(pluginName)); - } - else - { - file->write("*"); - file->write(textCodec->fromUnicode(pluginName)); - - } - file->write("\r\n"); - ++writtenCount; + if (pluginList->state(pluginName) == IPluginList::STATE_ACTIVE) { + if (!textCodec->canEncode(pluginName)) { + invalidFileNames = true; + qCritical("invalid plugin name %s", qPrintable(pluginName)); } + else + { + file->write("*"); + file->write(textCodec->fromUnicode(pluginName)); + + } + file->write("\r\n"); + ++writtenCount; + } else { if (!textCodec->canEncode(pluginName)) { @@ -88,8 +107,7 @@ void SkyrimSEGamePlugins::writePluginList(const IPluginList *pluginList, } } -bool SkyrimSEGamePlugins::readPluginList(MOBase::IPluginList *pluginList, - bool useLoadOrder) +QStringList SkyrimSEGamePlugins::readPluginList(MOBase::IPluginList *pluginList) { QStringList plugins = pluginList->pluginNames(); QStringList primaryPlugins = organizer()->managedGame()->primaryPlugins(); @@ -101,11 +119,12 @@ bool SkyrimSEGamePlugins::readPluginList(MOBase::IPluginList *pluginList, } } + QString filePath = organizer()->profile()->absolutePath() + "/plugins.txt"; QFile file(filePath); if (!file.open(QIODevice::ReadOnly)) { qWarning("%s not found", qPrintable(filePath)); - return false; + return loadOrder; } ON_BLOCK_EXIT([&]() { file.close(); }); @@ -113,7 +132,7 @@ bool SkyrimSEGamePlugins::readPluginList(MOBase::IPluginList *pluginList, // MO stores at least a header in the file. if it's completely empty the // file is broken qWarning("%s empty", qPrintable(filePath)); - return false; + return loadOrder; } while (!file.atEnd()) { @@ -158,9 +177,5 @@ bool SkyrimSEGamePlugins::readPluginList(MOBase::IPluginList *pluginList, pluginList->setState(pluginName, IPluginList::STATE_INACTIVE); } - if (useLoadOrder) { - pluginList->setLoadOrder(loadOrder); - } - - return true; + return loadOrder; } diff --git a/src/games/skyrimse/src/skyrimsegameplugins.h b/src/games/skyrimse/src/skyrimsegameplugins.h index 3ef14f71..462abdc7 100644 --- a/src/games/skyrimse/src/skyrimsegameplugins.h +++ b/src/games/skyrimse/src/skyrimsegameplugins.h @@ -16,8 +16,8 @@ public: protected: virtual void writePluginList(const MOBase::IPluginList *pluginList, const QString &filePath) override; - virtual bool readPluginList(MOBase::IPluginList *pluginList, - bool useLoadOrder) override; + virtual QStringList readPluginList(MOBase::IPluginList *pluginList) override; + virtual void getLoadOrder(QStringList &loadOrder) override; private: std::map m_LastSaveHash; From b1c2cdf56cad0cc7b8a2a12a1c0499bdf5e35b11 Mon Sep 17 00:00:00 2001 From: Al Date: Sun, 9 Sep 2018 23:29:49 +0200 Subject: [PATCH 0627/1544] [game_skyrim] Archive conflicts (#3) * Merge fixes for archive parsing * Merge fixes for archive parsing --- src/games/skyrim/src/skyrimgameplugins.cpp | 19 +++++++++---------- src/games/skyrim/src/skyrimgameplugins.h | 3 +-- 2 files changed, 10 insertions(+), 12 deletions(-) diff --git a/src/games/skyrim/src/skyrimgameplugins.cpp b/src/games/skyrim/src/skyrimgameplugins.cpp index 44c9f260..91a446e5 100644 --- a/src/games/skyrim/src/skyrimgameplugins.cpp +++ b/src/games/skyrim/src/skyrimgameplugins.cpp @@ -35,18 +35,19 @@ void SkyrimGamePlugins::readPluginLists(MOBase::IPluginList *pluginList) { if (pluginsIsNew && !loadOrderIsNew) { // If the plugins is new but not loadorder, we must reparse the load order from the plugin files - readPluginList(pluginList, true); + QStringList loadOrder = readPluginList(pluginList); + pluginList->setLoadOrder(loadOrder); } else { // read both files if they are both new or both older than the last read - readLoadOrderList(pluginList, loadOrderPath); - readPluginList(pluginList, false); + QStringList loadOrder = readLoadOrderList(pluginList, loadOrderPath); + pluginList->setLoadOrder(loadOrder); + readPluginList(pluginList); } m_LastRead = QDateTime::currentDateTime(); } -bool SkyrimGamePlugins::readPluginList(MOBase::IPluginList *pluginList, - bool useLoadOrder) +QStringList SkyrimGamePlugins::readPluginList(MOBase::IPluginList *pluginList) { QStringList plugins = pluginList->pluginNames(); QStringList primaryPlugins = organizer()->managedGame()->primaryPlugins(); @@ -82,6 +83,7 @@ bool SkyrimGamePlugins::readPluginList(MOBase::IPluginList *pluginList, pluginsTxtExists = false; } + QStringList disabledPlugins; if (pluginsTxtExists) { while (!file.atEnd()) { QByteArray line = file.readLine(); @@ -92,6 +94,7 @@ bool SkyrimGamePlugins::readPluginList(MOBase::IPluginList *pluginList, if (pluginName.size() > 0) { pluginList->setState(pluginName, IPluginList::STATE_ACTIVE); plugins.removeAll(pluginName); + disabledPlugins.append(pluginName); loadOrder.append(pluginName); } } @@ -108,9 +111,5 @@ bool SkyrimGamePlugins::readPluginList(MOBase::IPluginList *pluginList, } } - if (useLoadOrder) { - pluginList->setLoadOrder(loadOrder); - } - - return true; + return loadOrder + disabledPlugins; } diff --git a/src/games/skyrim/src/skyrimgameplugins.h b/src/games/skyrim/src/skyrimgameplugins.h index 3eb68212..e61c1667 100644 --- a/src/games/skyrim/src/skyrimgameplugins.h +++ b/src/games/skyrim/src/skyrimgameplugins.h @@ -16,8 +16,7 @@ public: virtual void readPluginLists(MOBase::IPluginList *pluginList) override; protected: - virtual bool readPluginList(MOBase::IPluginList *pluginList, - bool useLoadOrder) override; + virtual QStringList readPluginList(MOBase::IPluginList *pluginList) override; private: std::map m_LastSaveHash; From b58a1823d5ff6ae9f3cf9143ce728303579f37a1 Mon Sep 17 00:00:00 2001 From: Al Date: Sun, 9 Sep 2018 23:30:03 +0200 Subject: [PATCH 0628/1544] [game_fallout76] Archive conflicts (#4) * Necessary changes for querying plugin loadorder for archive sorting * Necessary changes for querying plugin loadorder for archive sorting * Merge fixes for archive parsing * Necessary changes for querying plugin loadorder for archive sorting * Necessary changes for querying plugin loadorder for archive sorting * Merge fixes for archive parsing --- .../fallout76/src/fallout4gameplugins.cpp | 32 +++++++++++++------ src/games/fallout76/src/fallout4gameplugins.h | 4 +-- 2 files changed, 25 insertions(+), 11 deletions(-) diff --git a/src/games/fallout76/src/fallout4gameplugins.cpp b/src/games/fallout76/src/fallout4gameplugins.cpp index 678d63e0..bea0b8fb 100644 --- a/src/games/fallout76/src/fallout4gameplugins.cpp +++ b/src/games/fallout76/src/fallout4gameplugins.cpp @@ -22,6 +22,25 @@ Fallout4GamePlugins::Fallout4GamePlugins(IOrganizer *organizer) { } +void Fallout4GamePlugins::getLoadOrder(QStringList &loadOrder) { + QString loadOrderPath = + organizer()->profile()->absolutePath() + "/loadorder.txt"; + QString pluginsPath = organizer()->profile()->absolutePath() + "/plugins.txt"; + + bool loadOrderIsNew = !m_LastRead.isValid() || + !QFileInfo(loadOrderPath).exists() || + QFileInfo(loadOrderPath).lastModified() > m_LastRead; + bool pluginsIsNew = !m_LastRead.isValid() || + QFileInfo(pluginsPath).lastModified() > m_LastRead; + + if (loadOrderIsNew || !pluginsIsNew) { + loadOrder = readLoadOrderList(m_Organizer->pluginList(), loadOrderPath); + } + else { + loadOrder = readPluginList(m_Organizer->pluginList()); + } +} + void Fallout4GamePlugins::writePluginList(const IPluginList *pluginList, const QString &filePath) { SafeWriteFile file(filePath); @@ -91,8 +110,7 @@ void Fallout4GamePlugins::writePluginList(const IPluginList *pluginList, } } -bool Fallout4GamePlugins::readPluginList(MOBase::IPluginList *pluginList, - bool useLoadOrder) +QStringList Fallout4GamePlugins::readPluginList(MOBase::IPluginList *pluginList) { QStringList plugins = pluginList->pluginNames(); QStringList primaryPlugins = organizer()->managedGame()->primaryPlugins(); @@ -108,7 +126,7 @@ bool Fallout4GamePlugins::readPluginList(MOBase::IPluginList *pluginList, QFile file(filePath); if (!file.open(QIODevice::ReadOnly)) { qWarning("%s not found", qPrintable(filePath)); - return false; + return loadOrder; } ON_BLOCK_EXIT([&]() { file.close(); }); @@ -116,7 +134,7 @@ bool Fallout4GamePlugins::readPluginList(MOBase::IPluginList *pluginList, // MO stores at least a header in the file. if it's completely empty the // file is broken qWarning("%s empty", qPrintable(filePath)); - return false; + return loadOrder; } while (!file.atEnd()) { @@ -161,9 +179,5 @@ bool Fallout4GamePlugins::readPluginList(MOBase::IPluginList *pluginList, pluginList->setState(pluginName, IPluginList::STATE_INACTIVE); } - if (useLoadOrder) { - pluginList->setLoadOrder(loadOrder); - } - - return true; + return loadOrder; } diff --git a/src/games/fallout76/src/fallout4gameplugins.h b/src/games/fallout76/src/fallout4gameplugins.h index 091c5ce5..0b591b8b 100644 --- a/src/games/fallout76/src/fallout4gameplugins.h +++ b/src/games/fallout76/src/fallout4gameplugins.h @@ -16,8 +16,8 @@ public: protected: virtual void writePluginList(const MOBase::IPluginList *pluginList, const QString &filePath) override; - virtual bool readPluginList(MOBase::IPluginList *pluginList, - bool useLoadOrder) override; + virtual QStringList readPluginList(MOBase::IPluginList *pluginList) override; + virtual void getLoadOrder(QStringList &loadOrder) override; private: std::map m_LastSaveHash; From 7cb9935e62ed2cc39b3d8ffa8882b12a47b514b2 Mon Sep 17 00:00:00 2001 From: Al Date: Sun, 9 Sep 2018 23:30:03 +0200 Subject: [PATCH 0629/1544] [game_fallout4] Archive conflicts (#4) * Necessary changes for querying plugin loadorder for archive sorting * Necessary changes for querying plugin loadorder for archive sorting * Merge fixes for archive parsing * Necessary changes for querying plugin loadorder for archive sorting * Necessary changes for querying plugin loadorder for archive sorting * Merge fixes for archive parsing --- .../fallout4/src/fallout4gameplugins.cpp | 32 +++++++++++++------ src/games/fallout4/src/fallout4gameplugins.h | 4 +-- 2 files changed, 25 insertions(+), 11 deletions(-) diff --git a/src/games/fallout4/src/fallout4gameplugins.cpp b/src/games/fallout4/src/fallout4gameplugins.cpp index 678d63e0..bea0b8fb 100644 --- a/src/games/fallout4/src/fallout4gameplugins.cpp +++ b/src/games/fallout4/src/fallout4gameplugins.cpp @@ -22,6 +22,25 @@ Fallout4GamePlugins::Fallout4GamePlugins(IOrganizer *organizer) { } +void Fallout4GamePlugins::getLoadOrder(QStringList &loadOrder) { + QString loadOrderPath = + organizer()->profile()->absolutePath() + "/loadorder.txt"; + QString pluginsPath = organizer()->profile()->absolutePath() + "/plugins.txt"; + + bool loadOrderIsNew = !m_LastRead.isValid() || + !QFileInfo(loadOrderPath).exists() || + QFileInfo(loadOrderPath).lastModified() > m_LastRead; + bool pluginsIsNew = !m_LastRead.isValid() || + QFileInfo(pluginsPath).lastModified() > m_LastRead; + + if (loadOrderIsNew || !pluginsIsNew) { + loadOrder = readLoadOrderList(m_Organizer->pluginList(), loadOrderPath); + } + else { + loadOrder = readPluginList(m_Organizer->pluginList()); + } +} + void Fallout4GamePlugins::writePluginList(const IPluginList *pluginList, const QString &filePath) { SafeWriteFile file(filePath); @@ -91,8 +110,7 @@ void Fallout4GamePlugins::writePluginList(const IPluginList *pluginList, } } -bool Fallout4GamePlugins::readPluginList(MOBase::IPluginList *pluginList, - bool useLoadOrder) +QStringList Fallout4GamePlugins::readPluginList(MOBase::IPluginList *pluginList) { QStringList plugins = pluginList->pluginNames(); QStringList primaryPlugins = organizer()->managedGame()->primaryPlugins(); @@ -108,7 +126,7 @@ bool Fallout4GamePlugins::readPluginList(MOBase::IPluginList *pluginList, QFile file(filePath); if (!file.open(QIODevice::ReadOnly)) { qWarning("%s not found", qPrintable(filePath)); - return false; + return loadOrder; } ON_BLOCK_EXIT([&]() { file.close(); }); @@ -116,7 +134,7 @@ bool Fallout4GamePlugins::readPluginList(MOBase::IPluginList *pluginList, // MO stores at least a header in the file. if it's completely empty the // file is broken qWarning("%s empty", qPrintable(filePath)); - return false; + return loadOrder; } while (!file.atEnd()) { @@ -161,9 +179,5 @@ bool Fallout4GamePlugins::readPluginList(MOBase::IPluginList *pluginList, pluginList->setState(pluginName, IPluginList::STATE_INACTIVE); } - if (useLoadOrder) { - pluginList->setLoadOrder(loadOrder); - } - - return true; + return loadOrder; } diff --git a/src/games/fallout4/src/fallout4gameplugins.h b/src/games/fallout4/src/fallout4gameplugins.h index 091c5ce5..0b591b8b 100644 --- a/src/games/fallout4/src/fallout4gameplugins.h +++ b/src/games/fallout4/src/fallout4gameplugins.h @@ -16,8 +16,8 @@ public: protected: virtual void writePluginList(const MOBase::IPluginList *pluginList, const QString &filePath) override; - virtual bool readPluginList(MOBase::IPluginList *pluginList, - bool useLoadOrder) override; + virtual QStringList readPluginList(MOBase::IPluginList *pluginList) override; + virtual void getLoadOrder(QStringList &loadOrder) override; private: std::map m_LastSaveHash; From e4b7e79058ab26c02e2d24b218b5db1104c7ad6c Mon Sep 17 00:00:00 2001 From: Al Date: Sun, 9 Sep 2018 23:30:21 +0200 Subject: [PATCH 0630/1544] [game_fallout4vr] Archive conflicts (#4) * Necessary changes for querying plugin loadorder for archive sorting * Merge fixes for archive parsing * Necessary changes for querying plugin loadorder for archive sorting * Merge fixes for archive parsing --- .../fallout4vr/src/fallout4vrgameplugins.cpp | 32 +++++++++++++------ .../fallout4vr/src/fallout4vrgameplugins.h | 4 +-- 2 files changed, 25 insertions(+), 11 deletions(-) diff --git a/src/games/fallout4vr/src/fallout4vrgameplugins.cpp b/src/games/fallout4vr/src/fallout4vrgameplugins.cpp index daf5ed90..86e67f6d 100644 --- a/src/games/fallout4vr/src/fallout4vrgameplugins.cpp +++ b/src/games/fallout4vr/src/fallout4vrgameplugins.cpp @@ -22,6 +22,25 @@ Fallout4VRGamePlugins::Fallout4VRGamePlugins(IOrganizer *organizer) { } +void Fallout4VRGamePlugins::getLoadOrder(QStringList &loadOrder) { + QString loadOrderPath = + organizer()->profile()->absolutePath() + "/loadorder.txt"; + QString pluginsPath = organizer()->profile()->absolutePath() + "/plugins.txt"; + + bool loadOrderIsNew = !m_LastRead.isValid() || + !QFileInfo(loadOrderPath).exists() || + QFileInfo(loadOrderPath).lastModified() > m_LastRead; + bool pluginsIsNew = !m_LastRead.isValid() || + QFileInfo(pluginsPath).lastModified() > m_LastRead; + + if (loadOrderIsNew || !pluginsIsNew) { + loadOrder = readLoadOrderList(m_Organizer->pluginList(), loadOrderPath); + } + else { + loadOrder = readPluginList(m_Organizer->pluginList()); + } +} + void Fallout4VRGamePlugins::writePluginList(const IPluginList *pluginList, const QString &filePath) { SafeWriteFile file(filePath); @@ -91,8 +110,7 @@ void Fallout4VRGamePlugins::writePluginList(const IPluginList *pluginList, } } -bool Fallout4VRGamePlugins::readPluginList(MOBase::IPluginList *pluginList, - bool useLoadOrder) +QStringList Fallout4VRGamePlugins::readPluginList(MOBase::IPluginList *pluginList) { QStringList plugins = pluginList->pluginNames(); QStringList primaryPlugins = organizer()->managedGame()->primaryPlugins(); @@ -109,7 +127,7 @@ bool Fallout4VRGamePlugins::readPluginList(MOBase::IPluginList *pluginList, QFile file(filePath); if (!file.open(QIODevice::ReadOnly)) { qWarning("%s not found", qPrintable(filePath)); - return false; + return loadOrder; } ON_BLOCK_EXIT([&]() { file.close(); }); @@ -117,7 +135,7 @@ bool Fallout4VRGamePlugins::readPluginList(MOBase::IPluginList *pluginList, // MO stores at least a header in the file. if it's completely empty the // file is broken qWarning("%s empty", qPrintable(filePath)); - return false; + return loadOrder; } while (!file.atEnd()) { @@ -162,9 +180,5 @@ bool Fallout4VRGamePlugins::readPluginList(MOBase::IPluginList *pluginList, pluginList->setState(pluginName, IPluginList::STATE_INACTIVE); } - if (useLoadOrder) { - pluginList->setLoadOrder(loadOrder); - } - - return true; + return loadOrder; } diff --git a/src/games/fallout4vr/src/fallout4vrgameplugins.h b/src/games/fallout4vr/src/fallout4vrgameplugins.h index 8eb21375..e8b6ee0b 100644 --- a/src/games/fallout4vr/src/fallout4vrgameplugins.h +++ b/src/games/fallout4vr/src/fallout4vrgameplugins.h @@ -16,8 +16,8 @@ public: protected: virtual void writePluginList(const MOBase::IPluginList *pluginList, const QString &filePath) override; - virtual bool readPluginList(MOBase::IPluginList *pluginList, - bool useLoadOrder) override; + virtual QStringList readPluginList(MOBase::IPluginList *pluginList) override; + virtual void getLoadOrder(QStringList &loadOrder) override; private: std::map m_LastSaveHash; From 9a7efce47546b27a10273514ab85782e62900273 Mon Sep 17 00:00:00 2001 From: LostDragonist Date: Wed, 26 Sep 2018 23:29:56 -0500 Subject: [PATCH 0631/1544] Allow plugins to define maximum length of archive string --- src/gamebryodataarchives.cpp | 9 +++++---- src/gamebryodataarchives.h | 4 ++-- 2 files changed, 7 insertions(+), 6 deletions(-) diff --git a/src/gamebryodataarchives.cpp b/src/gamebryodataarchives.cpp index fd585d3b..01c33409 100644 --- a/src/gamebryodataarchives.cpp +++ b/src/gamebryodataarchives.cpp @@ -7,9 +7,9 @@ GamebryoDataArchives::GamebryoDataArchives(const QDir &myGamesDir): m_LocalGameDir(myGamesDir.absolutePath()) {} -QStringList GamebryoDataArchives::getArchivesFromKey(const QString &iniFile, const QString &key) const +QStringList GamebryoDataArchives::getArchivesFromKey(const QString &iniFile, const QString &key, const int size) const { - wchar_t buffer[256]; + wchar_t * buffer = new wchar_t[size]; QStringList result; std::wstring iniFileW = QDir::toNativeSeparators(iniFile).toStdWString(); @@ -18,13 +18,14 @@ QStringList GamebryoDataArchives::getArchivesFromKey(const QString &iniFile, con errno = 0; if (::GetPrivateProfileStringW(L"Archive", key.toStdWString().c_str(), - L"", buffer, 256, iniFileW.c_str()) != 0) { + L"", buffer, size, iniFileW.c_str()) != 0) { result.append(QString::fromStdWString(buffer).split(',')); } for (int i = 0; i < result.count(); ++i) { result[i] = result[i].trimmed(); } + delete[] buffer; return result; } @@ -56,4 +57,4 @@ void GamebryoDataArchives::removeArchive(MOBase::IProfile *profile, const QStrin current.removeAll(archiveName); writeArchiveList(profile, current); -} +} \ No newline at end of file diff --git a/src/gamebryodataarchives.h b/src/gamebryodataarchives.h index 055cc3c9..cd8333ba 100644 --- a/src/gamebryodataarchives.h +++ b/src/gamebryodataarchives.h @@ -17,9 +17,9 @@ public: protected: QDir m_LocalGameDir; - QStringList getArchivesFromKey(const QString &iniFile, const QString &key) const; + QStringList getArchivesFromKey(const QString &iniFile, const QString &key, int size=256) const; void setArchivesToKey(const QString &iniFile, const QString &key, const QString &value); - + private: virtual void writeArchiveList(MOBase::IProfile *profile, const QStringList &before) = 0; From 9538fe2b244d25b80ce151e6f81efb2025c709ba Mon Sep 17 00:00:00 2001 From: LostDragonist Date: Thu, 27 Sep 2018 11:13:18 -0500 Subject: [PATCH 0632/1544] [game_falloutnv] Set the maximum archive string length to 8192 to support NVAC --- src/games/falloutnv/src/falloutnvdataarchives.cpp | 4 ++-- src/games/falloutnv/src/game_falloutNV_en.ts | 2 +- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/src/games/falloutnv/src/falloutnvdataarchives.cpp b/src/games/falloutnv/src/falloutnvdataarchives.cpp index 8179b505..7a2dbb64 100644 --- a/src/games/falloutnv/src/falloutnvdataarchives.cpp +++ b/src/games/falloutnv/src/falloutnvdataarchives.cpp @@ -21,7 +21,7 @@ QStringList FalloutNVDataArchives::archives(const MOBase::IProfile *profile) con QStringList result; QString iniFile = profile->localSettingsEnabled() ? QDir(profile->absolutePath()).absoluteFilePath("fallout.ini") : m_LocalGameDir.absoluteFilePath("fallout.ini"); - result.append(getArchivesFromKey(iniFile, "SArchiveList")); + result.append(getArchivesFromKey(iniFile, "SArchiveList", 8192)); //NVAC expands the maximum string limit return result; } @@ -32,4 +32,4 @@ void FalloutNVDataArchives::writeArchiveList(MOBase::IProfile *profile, const QS QString iniFile = profile->localSettingsEnabled() ? QDir(profile->absolutePath()).absoluteFilePath("fallout.ini") : m_LocalGameDir.absoluteFilePath("fallout.ini"); setArchivesToKey(iniFile, "SArchiveList", list); -} +} \ No newline at end of file diff --git a/src/games/falloutnv/src/game_falloutNV_en.ts b/src/games/falloutnv/src/game_falloutNV_en.ts index d9801c6d..fdc9a003 100644 --- a/src/games/falloutnv/src/game_falloutNV_en.ts +++ b/src/games/falloutnv/src/game_falloutNV_en.ts @@ -76,7 +76,7 @@ - + Some of your plugins have invalid names! These plugins can not be loaded by the game. Please see mo_interface.log for a list of affected plugins and rename them. From e461ab5aa09764ee9e89eebb663a5020e8fe47d2 Mon Sep 17 00:00:00 2001 From: Silarn Date: Mon, 1 Oct 2018 00:10:20 -0500 Subject: [PATCH 0633/1544] [game_falloutnv] Add 'creation' game lib for creation engine changes, eliminate duplicate plugin code --- src/games/falloutnv/src/CMakeLists.txt | 4 +-- src/games/falloutnv/src/game_falloutNV_en.ts | 36 ++++++++++---------- 2 files changed, 20 insertions(+), 20 deletions(-) diff --git a/src/games/falloutnv/src/CMakeLists.txt b/src/games/falloutnv/src/CMakeLists.txt index faeaa98f..de7f7d7b 100644 --- a/src/games/falloutnv/src/CMakeLists.txt +++ b/src/games/falloutnv/src/CMakeLists.txt @@ -19,7 +19,7 @@ GET_FILENAME_COMPONENT(${default_project_path} ${default_project_path} REALPATH) SET(project_path "${default_project_path}" CACHE PATH "path to the other mo projects") FIND_PACKAGE(Qt5LinguistTools) -SET(translation_sources ${CMAKE_SOURCE_DIR}/src ${project_path}/game_gamebryo/src) +SET(translation_sources ${CMAKE_SOURCE_DIR}/src ${project_path}/game_gamebryo/src/gamebryo) QT5_CREATE_TRANSLATION(${PROJ_NAME}_translations_qm ${translation_sources} ${CMAKE_SOURCE_DIR}/src/${PROJ_NAME}_en.ts) SET(Boost_USE_STATIC_LIBS ON) @@ -35,7 +35,7 @@ SET(lib_path "${project_path}/../../install/libs") INCLUDE_DIRECTORIES(${project_path}/uibase/src ${project_path}/game_features/src - ${project_path}/game_gamebryo/src) + ${project_path}/game_gamebryo/src/gamebryo) LINK_DIRECTORIES(${project_path}/uibase/build/src ${lib_path} ${LZ4_ROOT}/dll) diff --git a/src/games/falloutnv/src/game_falloutNV_en.ts b/src/games/falloutnv/src/game_falloutNV_en.ts index fdc9a003..c2df0978 100644 --- a/src/games/falloutnv/src/game_falloutNV_en.ts +++ b/src/games/falloutnv/src/game_falloutNV_en.ts @@ -12,48 +12,48 @@ GamebryoSaveGameInfoWidget - + Save # - + Character - + Level - + Location - + Date - + Has Script Extender Data - + Missing ESPs - - + + None - + Missing ESLs @@ -61,42 +61,42 @@ QObject - + failed to deactivate BSA invalidation in "%1" (errorcode %2) - + failed to activate BSA invalidation in "%1" (errorcode %2) - + failed to set archive key (errorcode %1) - + Some of your plugins have invalid names! These plugins can not be loaded by the game. Please see mo_interface.log for a list of affected plugins and rename them. - + failed to open %1 - + wrong file format - expected %1 got %2 - + failed to query registry path (preflight): %1 - + failed to query registry path (read): %1 From d839b7644a5758d075d3931c5470015cda7fc82a Mon Sep 17 00:00:00 2001 From: Silarn Date: Mon, 1 Oct 2018 00:10:20 -0500 Subject: [PATCH 0634/1544] [game_fallout4vr] Add 'creation' game lib for creation engine changes, eliminate duplicate plugin code --- src/games/fallout4vr/src/CMakeLists.txt | 8 +- .../fallout4vr/src/fallout4vrgameplugins.cpp | 184 ------------------ .../fallout4vr/src/fallout4vrgameplugins.h | 26 --- .../fallout4vr/src/game_fallout4vr_en.ts | 40 ++-- src/games/fallout4vr/src/gamefallout4vr.cpp | 5 +- 5 files changed, 27 insertions(+), 236 deletions(-) delete mode 100644 src/games/fallout4vr/src/fallout4vrgameplugins.cpp delete mode 100644 src/games/fallout4vr/src/fallout4vrgameplugins.h diff --git a/src/games/fallout4vr/src/CMakeLists.txt b/src/games/fallout4vr/src/CMakeLists.txt index ae7b8f70..d0a23423 100644 --- a/src/games/fallout4vr/src/CMakeLists.txt +++ b/src/games/fallout4vr/src/CMakeLists.txt @@ -23,7 +23,7 @@ GET_FILENAME_COMPONENT(${default_project_path} ${default_project_path} REALPATH) SET(project_path "${default_project_path}" CACHE PATH "path to the other mo projects") FIND_PACKAGE(Qt5LinguistTools) -SET(translation_sources ${CMAKE_SOURCE_DIR}/src ${project_path}/game_gamebryo/src) +SET(translation_sources ${CMAKE_SOURCE_DIR}/src ${project_path}/game_gamebryo/src/gamebryo ${project_path}/game_gamebryo/src/creation) QT5_CREATE_TRANSLATION(${PROJ_NAME}_translations_qm ${translation_sources} ${CMAKE_SOURCE_DIR}/src/${PROJ_NAME}_en.ts) SET(Boost_USE_STATIC_LIBS ON) @@ -39,7 +39,8 @@ SET(lib_path "${project_path}/../../install/libs") INCLUDE_DIRECTORIES(${project_path}/uibase/src ${project_path}/game_features/src - ${project_path}/game_gamebryo/src) + ${project_path}/game_gamebryo/src/gamebryo + ${project_path}/game_gamebryo/src/creation) LINK_DIRECTORIES(${project_path}/uibase/build/src ${lib_path} ${LZ4_ROOT}/dll) @@ -53,7 +54,8 @@ TARGET_LINK_LIBRARIES(${PROJ_NAME} uibase Version liblz4 - game_gamebryo) + game_gamebryo + game_creation) IF (MSVC) SET_TARGET_PROPERTIES(${PROJ_NAME} PROPERTIES COMPILE_FLAGS "/std:c++latest") diff --git a/src/games/fallout4vr/src/fallout4vrgameplugins.cpp b/src/games/fallout4vr/src/fallout4vrgameplugins.cpp deleted file mode 100644 index 86e67f6d..00000000 --- a/src/games/fallout4vr/src/fallout4vrgameplugins.cpp +++ /dev/null @@ -1,184 +0,0 @@ -#include "fallout4vrgameplugins.h" -#include -#include -#include -#include -#include - -#include -#include -#include -#include - - -using MOBase::IPluginGame; -using MOBase::IPluginList; -using MOBase::IOrganizer; -using MOBase::SafeWriteFile; -using MOBase::reportError; - -Fallout4VRGamePlugins::Fallout4VRGamePlugins(IOrganizer *organizer) - : GamebryoGamePlugins(organizer) -{ -} - -void Fallout4VRGamePlugins::getLoadOrder(QStringList &loadOrder) { - QString loadOrderPath = - organizer()->profile()->absolutePath() + "/loadorder.txt"; - QString pluginsPath = organizer()->profile()->absolutePath() + "/plugins.txt"; - - bool loadOrderIsNew = !m_LastRead.isValid() || - !QFileInfo(loadOrderPath).exists() || - QFileInfo(loadOrderPath).lastModified() > m_LastRead; - bool pluginsIsNew = !m_LastRead.isValid() || - QFileInfo(pluginsPath).lastModified() > m_LastRead; - - if (loadOrderIsNew || !pluginsIsNew) { - loadOrder = readLoadOrderList(m_Organizer->pluginList(), loadOrderPath); - } - else { - loadOrder = readPluginList(m_Organizer->pluginList()); - } -} - -void Fallout4VRGamePlugins::writePluginList(const IPluginList *pluginList, - const QString &filePath) { - SafeWriteFile file(filePath); - - QTextCodec *textCodec = localCodec(); - - file->resize(0); - - file->write(textCodec->fromUnicode( - "# This file was automatically generated by Mod Organizer.\r\n")); - - bool invalidFileNames = false; - int writtenCount = 0; - - QStringList plugins = pluginList->pluginNames(); - std::sort(plugins.begin(), plugins.end(), - [pluginList](const QString &lhs, const QString &rhs) { - return pluginList->priority(lhs) < pluginList->priority(rhs); - }); - - QStringList PrimaryPlugins = organizer()->managedGame()->primaryPlugins(); - QSet ManagedMods = PrimaryPlugins.toSet().subtract(organizer()->managedGame()->DLCPlugins().toSet()); - PrimaryPlugins.append(ManagedMods.toList()); - - //TODO: do not write plugins in OFFICIAL_FILES container - for (const QString &pluginName : plugins) { - if (!PrimaryPlugins.contains(pluginName,Qt::CaseInsensitive)) { - if (pluginList->state(pluginName) == IPluginList::STATE_ACTIVE) { - if (!textCodec->canEncode(pluginName)) { - invalidFileNames = true; - qCritical("invalid plugin name %s", qPrintable(pluginName)); - } - else - { - file->write("*"); - file->write(textCodec->fromUnicode(pluginName)); - - } - file->write("\r\n"); - ++writtenCount; - } - else - { - if (!textCodec->canEncode(pluginName)) { - invalidFileNames = true; - qCritical("invalid plugin name %s", qPrintable(pluginName)); - } - else - { - file->write(textCodec->fromUnicode(pluginName)); - } - file->write("\r\n"); - ++writtenCount; - } - } - } - - if (invalidFileNames) { - reportError(QObject::tr("Some of your plugins have invalid names! These " - "plugins can not be loaded by the game. Please see " - "mo_interface.log for a list of affected plugins " - "and rename them.")); - } - - if (file.commitIfDifferent(m_LastSaveHash[filePath])) { - qDebug("%s saved", qPrintable(QDir::toNativeSeparators(filePath))); - } -} - -QStringList Fallout4VRGamePlugins::readPluginList(MOBase::IPluginList *pluginList) -{ - QStringList plugins = pluginList->pluginNames(); - QStringList primaryPlugins = organizer()->managedGame()->primaryPlugins(); - QStringList loadOrder(primaryPlugins); - - for (const QString &pluginName : loadOrder) { - if (pluginList->state(pluginName) != IPluginList::STATE_MISSING) { - pluginList->setState(pluginName, IPluginList::STATE_ACTIVE); - } - } - - - QString filePath = organizer()->profile()->absolutePath() + "/plugins.txt"; - QFile file(filePath); - if (!file.open(QIODevice::ReadOnly)) { - qWarning("%s not found", qPrintable(filePath)); - return loadOrder; - } - ON_BLOCK_EXIT([&]() { file.close(); }); - - if (file.size() == 0) { - // MO stores at least a header in the file. if it's completely empty the - // file is broken - qWarning("%s empty", qPrintable(filePath)); - return loadOrder; - } - - while (!file.atEnd()) { - QByteArray line = file.readLine(); - QString pluginName; - if ((line.size() > 0) && (line.at(0) != '#')) { - pluginName = localCodec()->toUnicode(line.trimmed().constData()); - } - if (!primaryPlugins.contains(pluginName, Qt::CaseInsensitive)) { - if (pluginName.startsWith('*')) { - pluginName.remove(0, 1); - if (pluginName.size() > 0) { - pluginList->setState(pluginName, IPluginList::STATE_ACTIVE); - plugins.removeAll(pluginName); - if (!loadOrder.contains(pluginName, Qt::CaseInsensitive)) { - loadOrder.append(pluginName); - } - } - } - else - { - if (pluginName.size() > 0) { - pluginList->setState(pluginName, IPluginList::STATE_INACTIVE); - plugins.removeAll(pluginName); - if (!loadOrder.contains(pluginName, Qt::CaseInsensitive)) { - loadOrder.append(pluginName); - } - } - } - } - else - { - pluginName.remove(0, 1); - plugins.removeAll(pluginName); - } - } - - file.close(); - - // we removed each plugin found in the file, so what's left are inactive mods - for (const QString &pluginName : plugins) { - pluginList->setState(pluginName, IPluginList::STATE_INACTIVE); - } - - return loadOrder; -} diff --git a/src/games/fallout4vr/src/fallout4vrgameplugins.h b/src/games/fallout4vr/src/fallout4vrgameplugins.h deleted file mode 100644 index e8b6ee0b..00000000 --- a/src/games/fallout4vr/src/fallout4vrgameplugins.h +++ /dev/null @@ -1,26 +0,0 @@ -#ifndef FALLOUT4VRGAMEPLUGINS_H -#define FALLOUT4VRGAMEPLUGINS_H - - -#include -#include -#include -#include - - -class Fallout4VRGamePlugins : public GamebryoGamePlugins -{ -public: - Fallout4VRGamePlugins(MOBase::IOrganizer *organizer); - -protected: - virtual void writePluginList(const MOBase::IPluginList *pluginList, - const QString &filePath) override; - virtual QStringList readPluginList(MOBase::IPluginList *pluginList) override; - virtual void getLoadOrder(QStringList &loadOrder) override; - -private: - std::map m_LastSaveHash; -}; - -#endif // FALLOUT4VRGAMEPLUGINS_H diff --git a/src/games/fallout4vr/src/game_fallout4vr_en.ts b/src/games/fallout4vr/src/game_fallout4vr_en.ts index e221f8bc..a994c825 100644 --- a/src/games/fallout4vr/src/game_fallout4vr_en.ts +++ b/src/games/fallout4vr/src/game_fallout4vr_en.ts @@ -4,7 +4,7 @@ GameFallout4VR - + Adds support for the game Fallout 4 VR. Splash by %1 @@ -13,48 +13,48 @@ Splash by %1 GamebryoSaveGameInfoWidget - + Save # - + Character - + Level - + Location - + Date - + Has Script Extender Data - + Missing ESPs - - + + None - + Missing ESLs @@ -62,43 +62,43 @@ Splash by %1 QObject - - + + Some of your plugins have invalid names! These plugins can not be loaded by the game. Please see mo_interface.log for a list of affected plugins and rename them. - + failed to query registry path (preflight): %1 - + failed to query registry path (read): %1 - + failed to deactivate BSA invalidation in "%1" (errorcode %2) - + failed to activate BSA invalidation in "%1" (errorcode %2) - + failed to set archive key (errorcode %1) - + failed to open %1 - + wrong file format - expected %1 got %2 diff --git a/src/games/fallout4vr/src/gamefallout4vr.cpp b/src/games/fallout4vr/src/gamefallout4vr.cpp index ba6e72e9..d59ba51d 100644 --- a/src/games/fallout4vr/src/gamefallout4vr.cpp +++ b/src/games/fallout4vr/src/gamefallout4vr.cpp @@ -2,13 +2,12 @@ #include "fallout4vrdataarchives.h" #include "fallout4vrsavegameinfo.h" -#include "fallout4vrgameplugins.h" #include "fallout4vrunmanagedmods.h" #include #include #include -#include +#include #include "versioninfo.h" #include @@ -40,7 +39,7 @@ bool GameFallout4VR::init(IOrganizer *moInfo) registerFeature(new Fallout4VRDataArchives(myGamesPath())); registerFeature(new GamebryoLocalSavegames(myGamesPath(), "fallout4custom.ini")); registerFeature(new Fallout4VRSaveGameInfo(this)); - registerFeature(new Fallout4VRGamePlugins(moInfo)); + registerFeature(new CreationGamePlugins(moInfo)); registerFeature(new Fallout4VRUnmangedMods(this)); return true; From 6b0379d9ec83ffd405194b6aee6d7fa4c250b4fc Mon Sep 17 00:00:00 2001 From: Silarn Date: Mon, 1 Oct 2018 00:10:21 -0500 Subject: [PATCH 0635/1544] [game_morrowind] Add 'creation' game lib for creation engine changes, eliminate duplicate plugin code --- src/games/morrowind/src/CMakeLists.txt | 4 +- src/games/morrowind/src/game_morrowind_en.ts | 40 ++++++++++---------- 2 files changed, 22 insertions(+), 22 deletions(-) diff --git a/src/games/morrowind/src/CMakeLists.txt b/src/games/morrowind/src/CMakeLists.txt index 6ea551a9..b85a3aa9 100644 --- a/src/games/morrowind/src/CMakeLists.txt +++ b/src/games/morrowind/src/CMakeLists.txt @@ -23,7 +23,7 @@ GET_FILENAME_COMPONENT(${default_project_path} ${default_project_path} REALPATH) SET(project_path "${default_project_path}" CACHE PATH "path to the other mo projects") FIND_PACKAGE(Qt5LinguistTools) -SET(translation_sources ${CMAKE_SOURCE_DIR}/src ${project_path}/game_gamebryo/src) +SET(translation_sources ${CMAKE_SOURCE_DIR}/src ${project_path}/game_gamebryo/src/gamebryo) QT5_CREATE_TRANSLATION(${PROJ_NAME}_translations_qm ${translation_sources} ${CMAKE_SOURCE_DIR}/src/${PROJ_NAME}_en.ts) SET(Boost_USE_STATIC_LIBS ON) @@ -39,7 +39,7 @@ SET(lib_path "${project_path}/../../install/libs") INCLUDE_DIRECTORIES(${project_path}/uibase/src ${project_path}/game_features/src - ${project_path}/game_gamebryo/src) + ${project_path}/game_gamebryo/src/gamebryo) LINK_DIRECTORIES(${project_path}/uibase/build/src ${lib_path} ${LZ4_ROOT}/dll) diff --git a/src/games/morrowind/src/game_morrowind_en.ts b/src/games/morrowind/src/game_morrowind_en.ts index 636f9592..1ba6d733 100644 --- a/src/games/morrowind/src/game_morrowind_en.ts +++ b/src/games/morrowind/src/game_morrowind_en.ts @@ -13,48 +13,48 @@ Splash by %1 GamebryoSaveGameInfoWidget - + Save # - + Character - + Level - + Location - + Date - + Has Script Extender Data - + Missing ESPs - - + + None - + Missing ESLs @@ -105,49 +105,49 @@ Splash by %1 QObject - + failed to deactivate BSA invalidation in "%1" (errorcode %2) - + failed to activate BSA invalidation in "%1" (errorcode %2) - + failed to set archive key (errorcode %1) - - + + Some of your plugins have invalid names! These plugins can not be loaded by the game. Please see mo_interface.log for a list of affected plugins and rename them. - + failed to open %1 - + wrong file format - expected %1 got %2 - + failed to query registry path (preflight): %1 - + failed to query registry path (read): %1 - + failed to set game file key (errorcode %1) From 7fc96d178a04a7925223d912c638f3c23bdb76f2 Mon Sep 17 00:00:00 2001 From: Silarn Date: Mon, 1 Oct 2018 00:10:23 -0500 Subject: [PATCH 0636/1544] [game_skyrimse] Add 'creation' game lib for creation engine changes, eliminate duplicate plugin code --- src/games/skyrimse/src/CMakeLists.txt | 6 +- src/games/skyrimse/src/game_skyrimse_en.ts | 40 ++-- src/games/skyrimse/src/gameskyrimse.cpp | 5 +- .../skyrimse/src/skyrimsegameplugins.cpp | 181 ------------------ src/games/skyrimse/src/skyrimsegameplugins.h | 26 --- 5 files changed, 26 insertions(+), 232 deletions(-) delete mode 100644 src/games/skyrimse/src/skyrimsegameplugins.cpp delete mode 100644 src/games/skyrimse/src/skyrimsegameplugins.h diff --git a/src/games/skyrimse/src/CMakeLists.txt b/src/games/skyrimse/src/CMakeLists.txt index e90ce67f..6281cdb9 100644 --- a/src/games/skyrimse/src/CMakeLists.txt +++ b/src/games/skyrimse/src/CMakeLists.txt @@ -19,7 +19,7 @@ GET_FILENAME_COMPONENT(${default_project_path} ${default_project_path} REALPATH) SET(project_path "${default_project_path}" CACHE PATH "path to the other mo projects") FIND_PACKAGE(Qt5LinguistTools) -SET(translation_sources ${CMAKE_SOURCE_DIR}/src ${project_path}/game_gamebryo/src) +SET(translation_sources ${CMAKE_SOURCE_DIR}/src ${project_path}/game_gamebryo/src/gamebryo ${project_path}/game_gamebryo/src/creation) QT5_CREATE_TRANSLATION(${PROJ_NAME}_translations_qm ${translation_sources} ${CMAKE_SOURCE_DIR}/src/${PROJ_NAME}_en.ts) SET(Boost_USE_STATIC_LIBS ON) @@ -35,7 +35,8 @@ SET(lib_path "${project_path}/../../install/libs") INCLUDE_DIRECTORIES(${project_path}/uibase/src ${project_path}/game_features/src - ${project_path}/game_gamebryo/src) + ${project_path}/game_gamebryo/src/gamebryo + ${project_path}/game_gamebryo/src/creation) LINK_DIRECTORIES(${project_path}/uibase/build/src ${lib_path} ${LZ4_ROOT}/dll) @@ -49,6 +50,7 @@ TARGET_LINK_LIBRARIES(${PROJ_NAME} DbgHelp uibase game_gamebryo + game_creation liblz4 version) diff --git a/src/games/skyrimse/src/game_skyrimse_en.ts b/src/games/skyrimse/src/game_skyrimse_en.ts index 25184940..53ae2864 100644 --- a/src/games/skyrimse/src/game_skyrimse_en.ts +++ b/src/games/skyrimse/src/game_skyrimse_en.ts @@ -4,7 +4,7 @@ GameSkyrimSE - + Adds support for the game Skyrim Special Edition. @@ -12,48 +12,48 @@ GamebryoSaveGameInfoWidget - + Save # - + Character - + Level - + Location - + Date - + Has Script Extender Data - + Missing ESPs - - + + None - + Missing ESLs @@ -61,43 +61,43 @@ QObject - + failed to query registry path (preflight): %1 - + failed to query registry path (read): %1 - - + + Some of your plugins have invalid names! These plugins can not be loaded by the game. Please see mo_interface.log for a list of affected plugins and rename them. - + failed to deactivate BSA invalidation in "%1" (errorcode %2) - + failed to activate BSA invalidation in "%1" (errorcode %2) - + failed to set archive key (errorcode %1) - + failed to open %1 - + wrong file format - expected %1 got %2 diff --git a/src/games/skyrimse/src/gameskyrimse.cpp b/src/games/skyrimse/src/gameskyrimse.cpp index d336a67e..a4f245f9 100644 --- a/src/games/skyrimse/src/gameskyrimse.cpp +++ b/src/games/skyrimse/src/gameskyrimse.cpp @@ -3,13 +3,12 @@ #include "skyrimsedataarchives.h" #include "skyrimsescriptextender.h" #include "skyrimsesavegameinfo.h" -#include "skyrimsegameplugins.h" #include "skyrimseunmanagedmods.h" #include #include #include -#include +#include #include "versioninfo.h" #include @@ -73,7 +72,7 @@ bool GameSkyrimSE::init(IOrganizer *moInfo) registerFeature(new SkyrimSEDataArchives(myGamesPath())); registerFeature(new GamebryoLocalSavegames(myGamesPath(), "Skyrim.ini")); registerFeature(new SkyrimSESaveGameInfo(this)); - registerFeature(new SkyrimSEGamePlugins(moInfo)); + registerFeature(new CreationGamePlugins(moInfo)); registerFeature(new SkyrimSEUnmangedMods(this)); return true; diff --git a/src/games/skyrimse/src/skyrimsegameplugins.cpp b/src/games/skyrimse/src/skyrimsegameplugins.cpp deleted file mode 100644 index 6d9cb95c..00000000 --- a/src/games/skyrimse/src/skyrimsegameplugins.cpp +++ /dev/null @@ -1,181 +0,0 @@ -#include "skyrimSEgameplugins.h" -#include -#include -#include -#include -#include - -#include -#include -#include - - -using MOBase::IPluginGame; -using MOBase::IPluginList; -using MOBase::IOrganizer; -using MOBase::SafeWriteFile; -using MOBase::reportError; - -SkyrimSEGamePlugins::SkyrimSEGamePlugins(IOrganizer *organizer) - : GamebryoGamePlugins(organizer) -{ -} - -void SkyrimSEGamePlugins::getLoadOrder(QStringList &loadOrder) { - QString loadOrderPath = - organizer()->profile()->absolutePath() + "/loadorder.txt"; - QString pluginsPath = organizer()->profile()->absolutePath() + "/plugins.txt"; - - bool loadOrderIsNew = !m_LastRead.isValid() || - !QFileInfo(loadOrderPath).exists() || - QFileInfo(loadOrderPath).lastModified() > m_LastRead; - bool pluginsIsNew = !m_LastRead.isValid() || - QFileInfo(pluginsPath).lastModified() > m_LastRead; - - if (loadOrderIsNew || !pluginsIsNew) { - loadOrder = readLoadOrderList(m_Organizer->pluginList(), loadOrderPath); - } - else { - loadOrder = readPluginList(m_Organizer->pluginList()); - } -} - -void SkyrimSEGamePlugins::writePluginList(const IPluginList *pluginList, - const QString &filePath) { - SafeWriteFile file(filePath); - - QTextCodec *textCodec = localCodec(); - - file->resize(0); - - file->write(textCodec->fromUnicode( - "# This file was automatically generated by Mod Organizer.\r\n")); - - bool invalidFileNames = false; - int writtenCount = 0; - - QStringList plugins = pluginList->pluginNames(); - std::sort(plugins.begin(), plugins.end(), - [pluginList](const QString &lhs, const QString &rhs) { - return pluginList->priority(lhs) < pluginList->priority(rhs); - }); - - QStringList PrimaryPlugins = organizer()->managedGame()->primaryPlugins(); - - //TODO: do not write plugins in OFFICIAL_FILES container - for (const QString &pluginName : plugins) { - if (!PrimaryPlugins.contains(pluginName,Qt::CaseInsensitive)) { - if (pluginList->state(pluginName) == IPluginList::STATE_ACTIVE) { - if (!textCodec->canEncode(pluginName)) { - invalidFileNames = true; - qCritical("invalid plugin name %s", qPrintable(pluginName)); - } - else - { - file->write("*"); - file->write(textCodec->fromUnicode(pluginName)); - - } - file->write("\r\n"); - ++writtenCount; - } - else - { - if (!textCodec->canEncode(pluginName)) { - invalidFileNames = true; - qCritical("invalid plugin name %s", qPrintable(pluginName)); - } - else - { - file->write(textCodec->fromUnicode(pluginName)); - } - file->write("\r\n"); - ++writtenCount; - } - } - } - - if (invalidFileNames) { - reportError(QObject::tr("Some of your plugins have invalid names! These " - "plugins can not be loaded by the game. Please see " - "mo_interface.log for a list of affected plugins " - "and rename them.")); - } - - if (file.commitIfDifferent(m_LastSaveHash[filePath])) { - qDebug("%s saved", qPrintable(QDir::toNativeSeparators(filePath))); - } -} - -QStringList SkyrimSEGamePlugins::readPluginList(MOBase::IPluginList *pluginList) -{ - QStringList plugins = pluginList->pluginNames(); - QStringList primaryPlugins = organizer()->managedGame()->primaryPlugins(); - QStringList loadOrder(primaryPlugins); - - for (const QString &pluginName : loadOrder) { - if (pluginList->state(pluginName) != IPluginList::STATE_MISSING) { - pluginList->setState(pluginName, IPluginList::STATE_ACTIVE); - } - } - - - QString filePath = organizer()->profile()->absolutePath() + "/plugins.txt"; - QFile file(filePath); - if (!file.open(QIODevice::ReadOnly)) { - qWarning("%s not found", qPrintable(filePath)); - return loadOrder; - } - ON_BLOCK_EXIT([&]() { file.close(); }); - - if (file.size() == 0) { - // MO stores at least a header in the file. if it's completely empty the - // file is broken - qWarning("%s empty", qPrintable(filePath)); - return loadOrder; - } - - while (!file.atEnd()) { - QByteArray line = file.readLine(); - QString pluginName; - if ((line.size() > 0) && (line.at(0) != '#')) { - pluginName = localCodec()->toUnicode(line.trimmed().constData()); - } - if (!primaryPlugins.contains(pluginName, Qt::CaseInsensitive)) { - if (pluginName.startsWith('*')) { - pluginName.remove(0, 1); - if (pluginName.size() > 0) { - pluginList->setState(pluginName, IPluginList::STATE_ACTIVE); - plugins.removeAll(pluginName); - if (!loadOrder.contains(pluginName, Qt::CaseInsensitive)) { - loadOrder.append(pluginName); - } - } - } - else - { - if (pluginName.size() > 0) { - pluginList->setState(pluginName, IPluginList::STATE_INACTIVE); - plugins.removeAll(pluginName); - if (!loadOrder.contains(pluginName, Qt::CaseInsensitive)) { - loadOrder.append(pluginName); - } - } - } - } - else - { - pluginName.remove(0, 1); - plugins.removeAll(pluginName); - } - } - - file.close(); - - // we removed each plugin found in the file, so what's left are inactive mods - for (const QString &pluginName : plugins) { - pluginList->setState(pluginName, IPluginList::STATE_INACTIVE); - } - - return loadOrder; -} diff --git a/src/games/skyrimse/src/skyrimsegameplugins.h b/src/games/skyrimse/src/skyrimsegameplugins.h deleted file mode 100644 index 462abdc7..00000000 --- a/src/games/skyrimse/src/skyrimsegameplugins.h +++ /dev/null @@ -1,26 +0,0 @@ -#ifndef _SKYRIMSEGAMEPLUGINS_H -#define _SKYRIMSEGAMEPLUGINS_H - - -#include -#include -#include -#include - - -class SkyrimSEGamePlugins : public GamebryoGamePlugins -{ -public: - SkyrimSEGamePlugins(MOBase::IOrganizer *organizer); - -protected: - virtual void writePluginList(const MOBase::IPluginList *pluginList, - const QString &filePath) override; - virtual QStringList readPluginList(MOBase::IPluginList *pluginList) override; - virtual void getLoadOrder(QStringList &loadOrder) override; - -private: - std::map m_LastSaveHash; -}; - -#endif // _SKYRIMSEGAMEPLUGINS_H From 7bf617f485f64cb89224be2a5f7a0ec2f448cd2c Mon Sep 17 00:00:00 2001 From: Silarn Date: Mon, 1 Oct 2018 00:10:24 -0500 Subject: [PATCH 0637/1544] [game_oblivion] Add 'creation' game lib for creation engine changes, eliminate duplicate plugin code --- src/games/oblivion/src/CMakeLists.txt | 4 +-- src/games/oblivion/src/game_oblivion_en.ts | 36 +++++++++++----------- 2 files changed, 20 insertions(+), 20 deletions(-) diff --git a/src/games/oblivion/src/CMakeLists.txt b/src/games/oblivion/src/CMakeLists.txt index 81d0944e..dbeec13c 100644 --- a/src/games/oblivion/src/CMakeLists.txt +++ b/src/games/oblivion/src/CMakeLists.txt @@ -19,7 +19,7 @@ GET_FILENAME_COMPONENT(${default_project_path} ${default_project_path} REALPATH) SET(project_path "${default_project_path}" CACHE PATH "path to the other mo projects") FIND_PACKAGE(Qt5LinguistTools) -SET(translation_sources ${CMAKE_SOURCE_DIR}/src ${project_path}/game_gamebryo/src) +SET(translation_sources ${CMAKE_SOURCE_DIR}/src ${project_path}/game_gamebryo/src/gamebryo) QT5_CREATE_TRANSLATION(${PROJ_NAME}_translations_qm ${translation_sources} ${CMAKE_SOURCE_DIR}/src/${PROJ_NAME}_en.ts) SET(Boost_USE_STATIC_LIBS ON) @@ -35,7 +35,7 @@ SET(lib_path "${project_path}/../../install/libs") INCLUDE_DIRECTORIES(${project_path}/uibase/src ${project_path}/game_features/src - ${project_path}/game_gamebryo/src) + ${project_path}/game_gamebryo/src/gamebryo) LINK_DIRECTORIES(${project_path}/uibase/build/src ${lib_path} ${LZ4_ROOT}/dll) diff --git a/src/games/oblivion/src/game_oblivion_en.ts b/src/games/oblivion/src/game_oblivion_en.ts index 2463f150..32d44e8f 100644 --- a/src/games/oblivion/src/game_oblivion_en.ts +++ b/src/games/oblivion/src/game_oblivion_en.ts @@ -12,48 +12,48 @@ GamebryoSaveGameInfoWidget - + Save # - + Character - + Level - + Location - + Date - + Has Script Extender Data - + Missing ESPs - - + + None - + Missing ESLs @@ -61,42 +61,42 @@ QObject - + failed to deactivate BSA invalidation in "%1" (errorcode %2) - + failed to activate BSA invalidation in "%1" (errorcode %2) - + failed to set archive key (errorcode %1) - + Some of your plugins have invalid names! These plugins can not be loaded by the game. Please see mo_interface.log for a list of affected plugins and rename them. - + failed to open %1 - + wrong file format - expected %1 got %2 - + failed to query registry path (preflight): %1 - + failed to query registry path (read): %1 From 38b2375695420fffe86e98e33f6ee8c05e50cde5 Mon Sep 17 00:00:00 2001 From: Silarn Date: Mon, 1 Oct 2018 00:10:26 -0500 Subject: [PATCH 0638/1544] Add 'creation' game lib for creation engine changes, eliminate duplicate plugin code --- CMakeLists.txt | 3 +- src/creation/CMakeLists.txt | 70 ++ src/creation/creationgameplugins.cpp | 182 +++++ src/creation/creationgameplugins.h | 24 + src/{ => gamebryo}/CMakeLists.txt | 2 +- src/{ => gamebryo}/SConscript | 56 +- src/{ => gamebryo}/dummybsa.cpp | 382 +++++----- src/{ => gamebryo}/dummybsa.h | 128 ++-- src/{ => gamebryo}/gameGamebryo.pro | 84 +-- .../gamebryobsainvalidation.cpp | 186 ++--- src/{ => gamebryo}/gamebryobsainvalidation.h | 78 +- src/{ => gamebryo}/gamebryodataarchives.cpp | 118 +-- src/{ => gamebryo}/gamebryodataarchives.h | 58 +- src/{ => gamebryo}/gamebryogameplugins.cpp | 0 src/{ => gamebryo}/gamebryogameplugins.h | 0 src/{ => gamebryo}/gamebryolocalsavegames.cpp | 0 src/{ => gamebryo}/gamebryolocalsavegames.h | 0 src/{ => gamebryo}/gamebryosavegame.cpp | 0 src/{ => gamebryo}/gamebryosavegame.h | 0 src/{ => gamebryo}/gamebryosavegameinfo.cpp | 0 src/{ => gamebryo}/gamebryosavegameinfo.h | 0 .../gamebryosavegameinfowidget.cpp | 0 .../gamebryosavegameinfowidget.h | 0 .../gamebryosavegameinfowidget.ui | 0 src/{ => gamebryo}/gamebryoscriptextender.cpp | 0 src/{ => gamebryo}/gamebryoscriptextender.h | 0 src/{ => gamebryo}/gamebryounmanagedmods.cpp | 0 src/{ => gamebryo}/gamebryounmanagedmods.h | 0 src/{ => gamebryo}/gamegamebryo.cpp | 704 +++++++++--------- src/{ => gamebryo}/gamegamebryo.h | 290 ++++---- 30 files changed, 1321 insertions(+), 1044 deletions(-) create mode 100644 src/creation/CMakeLists.txt create mode 100644 src/creation/creationgameplugins.cpp create mode 100644 src/creation/creationgameplugins.h rename src/{ => gamebryo}/CMakeLists.txt (100%) rename src/{ => gamebryo}/SConscript (94%) rename src/{ => gamebryo}/dummybsa.cpp (97%) rename src/{ => gamebryo}/dummybsa.h (96%) rename src/{ => gamebryo}/gameGamebryo.pro (95%) rename src/{ => gamebryo}/gamebryobsainvalidation.cpp (97%) rename src/{ => gamebryo}/gamebryobsainvalidation.h (95%) rename src/{ => gamebryo}/gamebryodataarchives.cpp (97%) rename src/{ => gamebryo}/gamebryodataarchives.h (96%) rename src/{ => gamebryo}/gamebryogameplugins.cpp (100%) rename src/{ => gamebryo}/gamebryogameplugins.h (100%) rename src/{ => gamebryo}/gamebryolocalsavegames.cpp (100%) rename src/{ => gamebryo}/gamebryolocalsavegames.h (100%) rename src/{ => gamebryo}/gamebryosavegame.cpp (100%) rename src/{ => gamebryo}/gamebryosavegame.h (100%) rename src/{ => gamebryo}/gamebryosavegameinfo.cpp (100%) rename src/{ => gamebryo}/gamebryosavegameinfo.h (100%) rename src/{ => gamebryo}/gamebryosavegameinfowidget.cpp (100%) rename src/{ => gamebryo}/gamebryosavegameinfowidget.h (100%) rename src/{ => gamebryo}/gamebryosavegameinfowidget.ui (100%) rename src/{ => gamebryo}/gamebryoscriptextender.cpp (100%) rename src/{ => gamebryo}/gamebryoscriptextender.h (100%) rename src/{ => gamebryo}/gamebryounmanagedmods.cpp (100%) rename src/{ => gamebryo}/gamebryounmanagedmods.h (100%) rename src/{ => gamebryo}/gamegamebryo.cpp (96%) rename src/{ => gamebryo}/gamegamebryo.h (96%) diff --git a/CMakeLists.txt b/CMakeLists.txt index cbfa46ca..05b2f29d 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -13,4 +13,5 @@ LIST(APPEND CMAKE_PREFIX_PATH ${QT_ROOT}/lib/cmake) LIST(APPEND CMAKE_PREFIX_PATH ${LZ4_ROOT}/dll) message(${LZ4_ROOT}) -ADD_SUBDIRECTORY(src) +ADD_SUBDIRECTORY(src/gamebryo) +ADD_SUBDIRECTORY(src/creation) diff --git a/src/creation/CMakeLists.txt b/src/creation/CMakeLists.txt new file mode 100644 index 00000000..bff1180f --- /dev/null +++ b/src/creation/CMakeLists.txt @@ -0,0 +1,70 @@ +CMAKE_MINIMUM_REQUIRED (VERSION 2.8.11) + +CMAKE_POLICY(SET CMP0020 NEW) + +SET(PROJ_NAME game_creation) +PROJECT(${PROJ_NAME}) + +FILE(GLOB ${PROJ_NAME}_SRCS *.cpp) +FILE(GLOB ${PROJ_NAME}_HDRS *.h) +FILE(GLOB ${PROJ_NAME}_FORMS *.ui) + +SET(CMAKE_INCLUDE_CURRENT_DIR ON) +SET(CMAKE_AUTOMOC ON) +SET(CMAKE_AUTOUIC ON) +FIND_PACKAGE(Qt5Widgets REQUIRED) +QT5_WRAP_UI(${PROJ_NAME}_UIHDRS ${${PROJ_NAME}_FORMS}) + +SET(Boost_USE_STATIC_LIBS ON) +SET(Boost_USE_MULTITHREADED ON) +SET(Boost_USE_STATIC_RUNTIME OFF) +FIND_PACKAGE(Boost) + +IF (Boost_FOUND) + INCLUDE_DIRECTORIES(${Boost_INCLUDE_DIRS}) +ENDIF (Boost_FOUND) + +SET(default_project_path "${CMAKE_SOURCE_DIR}/..") +GET_FILENAME_COMPONENT(${default_project_path} ${default_project_path} REALPATH) + +SET(project_path "${default_project_path}" CACHE PATH "path to the other mo projects") +SET(lib_path "${project_path}/../../install/libs") +SET(plugin_path "${project_path}") + + +INCLUDE_DIRECTORIES(../gamebryo + ${project_path}/uibase/src + ${project_path}/game_features/src + ${LZ4_ROOT}/include) +LINK_DIRECTORIES(${lib_path} + ${LZ4_ROOT}/dll) + +ADD_LIBRARY(${PROJ_NAME} STATIC ${${PROJ_NAME}_HDRS} ${${PROJ_NAME}_SRCS} ${${PROJ_NAME}_UIHDRS}) +TARGET_LINK_LIBRARIES(${PROJ_NAME} + Qt5::Widgets + ${Boost_LIBRARIES} + uibase + liblz4 + Version + game_gamebryo) + +IF (MSVC) + SET_TARGET_PROPERTIES(${PROJ_NAME} PROPERTIES COMPILE_FLAGS "/std:c++latest") +ENDIF() +IF (MSVC AND CMAKE_SIZEOF_VOID_P EQUAL 4) + # 32 bits + SET_TARGET_PROPERTIES(${PROJ_NAME} PROPERTIES LINK_FLAGS "/LARGEADDRESSAWARE") +ENDIF() + +IF (NOT "${OPTIMIZE_COMPILE_FLAGS}" STREQUAL "") + SET_TARGET_PROPERTIES(${PROJ_NAME} PROPERTIES COMPILE_FLAGS_RELWITHDEBINFO ${OPTIMIZE_COMPILE_FLAGS}) +ENDIF() +IF (NOT "${OPTIMIZE_LINK_FLAGS}" STREQUAL "") + SET_TARGET_PROPERTIES(${PROJ_NAME} PROPERTIES LINK_FLAGS_RELWITHDEBINFO ${OPTIMIZE_LINK_FLAGS}) +ENDIF() + +############### +## Installation + +INSTALL(TARGETS ${PROJ_NAME} + ARCHIVE DESTINATION libs) diff --git a/src/creation/creationgameplugins.cpp b/src/creation/creationgameplugins.cpp new file mode 100644 index 00000000..9dbd38a6 --- /dev/null +++ b/src/creation/creationgameplugins.cpp @@ -0,0 +1,182 @@ +#include "creationgameplugins.h" +#include +#include +#include +#include +#include + +#include +#include +#include +#include + +using MOBase::IPluginGame; +using MOBase::IPluginList; +using MOBase::IOrganizer; +using MOBase::SafeWriteFile; +using MOBase::reportError; + +CreationGamePlugins::CreationGamePlugins(IOrganizer *organizer) + : GamebryoGamePlugins(organizer) +{ +} + +void CreationGamePlugins::getLoadOrder(QStringList &loadOrder) { + QString loadOrderPath = + organizer()->profile()->absolutePath() + "/loadorder.txt"; + QString pluginsPath = organizer()->profile()->absolutePath() + "/plugins.txt"; + + bool loadOrderIsNew = !m_LastRead.isValid() || + !QFileInfo(loadOrderPath).exists() || + QFileInfo(loadOrderPath).lastModified() > m_LastRead; + bool pluginsIsNew = !m_LastRead.isValid() || + QFileInfo(pluginsPath).lastModified() > m_LastRead; + + if (loadOrderIsNew || !pluginsIsNew) { + loadOrder = readLoadOrderList(m_Organizer->pluginList(), loadOrderPath); + } + else { + loadOrder = readPluginList(m_Organizer->pluginList()); + } +} + +void CreationGamePlugins::writePluginList(const IPluginList *pluginList, + const QString &filePath) { + SafeWriteFile file(filePath); + + QTextCodec *textCodec = localCodec(); + + file->resize(0); + + file->write(textCodec->fromUnicode( + "# This file was automatically generated by Mod Organizer.\r\n")); + + bool invalidFileNames = false; + int writtenCount = 0; + + QStringList plugins = pluginList->pluginNames(); + std::sort(plugins.begin(), plugins.end(), + [pluginList](const QString &lhs, const QString &rhs) { + return pluginList->priority(lhs) < pluginList->priority(rhs); + }); + + QStringList PrimaryPlugins = organizer()->managedGame()->primaryPlugins(); + QSet ManagedMods = PrimaryPlugins.toSet().subtract(organizer()->managedGame()->DLCPlugins().toSet()); + PrimaryPlugins.append(ManagedMods.toList()); + + //TODO: do not write plugins in OFFICIAL_FILES container + for (const QString &pluginName : plugins) { + if (!PrimaryPlugins.contains(pluginName,Qt::CaseInsensitive)) { + if (pluginList->state(pluginName) == IPluginList::STATE_ACTIVE) { + if (!textCodec->canEncode(pluginName)) { + invalidFileNames = true; + qCritical("invalid plugin name %s", qPrintable(pluginName)); + } + else + { + file->write("*"); + file->write(textCodec->fromUnicode(pluginName)); + + } + file->write("\r\n"); + ++writtenCount; + } + else + { + if (!textCodec->canEncode(pluginName)) { + invalidFileNames = true; + qCritical("invalid plugin name %s", qPrintable(pluginName)); + } + else + { + file->write(textCodec->fromUnicode(pluginName)); + } + file->write("\r\n"); + ++writtenCount; + } + } + } + + if (invalidFileNames) { + reportError(QObject::tr("Some of your plugins have invalid names! These " + "plugins can not be loaded by the game. Please see " + "mo_interface.log for a list of affected plugins " + "and rename them.")); + } + + if (file.commitIfDifferent(m_LastSaveHash[filePath])) { + qDebug("%s saved", qPrintable(QDir::toNativeSeparators(filePath))); + } +} + +QStringList CreationGamePlugins::readPluginList(MOBase::IPluginList *pluginList) +{ + QStringList plugins = pluginList->pluginNames(); + QStringList primaryPlugins = organizer()->managedGame()->primaryPlugins(); + QStringList loadOrder(primaryPlugins); + + for (const QString &pluginName : loadOrder) { + if (pluginList->state(pluginName) != IPluginList::STATE_MISSING) { + pluginList->setState(pluginName, IPluginList::STATE_ACTIVE); + } + } + + QString filePath = organizer()->profile()->absolutePath() + "/plugins.txt"; + QFile file(filePath); + if (!file.open(QIODevice::ReadOnly)) { + qWarning("%s not found", qPrintable(filePath)); + return loadOrder; + } + ON_BLOCK_EXIT([&]() { file.close(); }); + + if (file.size() == 0) { + // MO stores at least a header in the file. if it's completely empty the + // file is broken + qWarning("%s empty", qPrintable(filePath)); + return loadOrder; + } + + while (!file.atEnd()) { + QByteArray line = file.readLine(); + QString pluginName; + if ((line.size() > 0) && (line.at(0) != '#')) { + pluginName = localCodec()->toUnicode(line.trimmed().constData()); + } + if (!primaryPlugins.contains(pluginName, Qt::CaseInsensitive)) { + if (pluginName.startsWith('*')) { + pluginName.remove(0, 1); + if (pluginName.size() > 0) { + pluginList->setState(pluginName, IPluginList::STATE_ACTIVE); + plugins.removeAll(pluginName); + if (!loadOrder.contains(pluginName, Qt::CaseInsensitive)) { + loadOrder.append(pluginName); + } + } + } + else + { + if (pluginName.size() > 0) { + pluginList->setState(pluginName, IPluginList::STATE_INACTIVE); + plugins.removeAll(pluginName); + if (!loadOrder.contains(pluginName, Qt::CaseInsensitive)) { + loadOrder.append(pluginName); + } + } + } + } + else + { + pluginName.remove(0, 1); + plugins.removeAll(pluginName); + } + } + + file.close(); + + // we removed each plugin found in the file, so what's left are inactive mods + for (const QString &pluginName : plugins) { + pluginList->setState(pluginName, IPluginList::STATE_INACTIVE); + } + + return loadOrder; +} \ No newline at end of file diff --git a/src/creation/creationgameplugins.h b/src/creation/creationgameplugins.h new file mode 100644 index 00000000..23e3c33b --- /dev/null +++ b/src/creation/creationgameplugins.h @@ -0,0 +1,24 @@ +#ifndef CREATIONGAMEPLUGINS_H +#define CREATIONGAMEPLUGINS_H + +#include +#include +#include +#include + +class CreationGamePlugins : public GamebryoGamePlugins +{ +public: + CreationGamePlugins(MOBase::IOrganizer *organizer); + +protected: + virtual void writePluginList(const MOBase::IPluginList *pluginList, + const QString &filePath) override; + virtual QStringList readPluginList(MOBase::IPluginList *pluginList) override; + virtual void getLoadOrder(QStringList &loadOrder) override; + +private: + std::map m_LastSaveHash; +}; + +#endif // CREATIONGAMEPLUGINS_H \ No newline at end of file diff --git a/src/CMakeLists.txt b/src/gamebryo/CMakeLists.txt similarity index 100% rename from src/CMakeLists.txt rename to src/gamebryo/CMakeLists.txt index eae52991..84c4dd42 100644 --- a/src/CMakeLists.txt +++ b/src/gamebryo/CMakeLists.txt @@ -6,7 +6,6 @@ FILE(GLOB ${PROJ_NAME}_SRCS *.cpp) FILE(GLOB ${PROJ_NAME}_HDRS *.h) FILE(GLOB ${PROJ_NAME}_FORMS *.ui) - SET(CMAKE_INCLUDE_CURRENT_DIR ON) SET(CMAKE_AUTOMOC ON) SET(CMAKE_AUTOUIC ON) @@ -33,6 +32,7 @@ SET(plugin_path "${project_path}") INCLUDE_DIRECTORIES(${project_path}/uibase/src ${project_path}/game_features/src ${LZ4_ROOT}/include) + LINK_DIRECTORIES(${lib_path} ${LZ4_ROOT}/dll) diff --git a/src/SConscript b/src/gamebryo/SConscript similarity index 94% rename from src/SConscript rename to src/gamebryo/SConscript index c5db0034..8f2d66da 100644 --- a/src/SConscript +++ b/src/gamebryo/SConscript @@ -1,28 +1,28 @@ -import os - -Import('qt_env') - -env = qt_env.Clone() - -env.EnableQtModules('Widgets') - -env['CPPPATH'] += [ - '.', # Why is this necessary? - os.path.join('..', 'gamefeatures'), - '${BOOSTPATH}' -] - -env.Uic(env.Glob('*.ui')) - -#env.AppendUnique(LIBS = [ -# 'advapi32', -# 'ole32', -# 'shell32', -# 'version' -#]) - -lib = env.StaticLibrary('gameGamebryo', env.Glob('*.cpp')) -#env.InstallModule(lib) - -res = env['QT_USED_MODULES'] -Return('res') +import os + +Import('qt_env') + +env = qt_env.Clone() + +env.EnableQtModules('Widgets') + +env['CPPPATH'] += [ + '.', # Why is this necessary? + os.path.join('..', 'gamefeatures'), + '${BOOSTPATH}' +] + +env.Uic(env.Glob('*.ui')) + +#env.AppendUnique(LIBS = [ +# 'advapi32', +# 'ole32', +# 'shell32', +# 'version' +#]) + +lib = env.StaticLibrary('gameGamebryo', env.Glob('*.cpp')) +#env.InstallModule(lib) + +res = env['QT_USED_MODULES'] +Return('res') diff --git a/src/dummybsa.cpp b/src/gamebryo/dummybsa.cpp similarity index 97% rename from src/dummybsa.cpp rename to src/gamebryo/dummybsa.cpp index d5c5096e..290be3ae 100644 --- a/src/dummybsa.cpp +++ b/src/gamebryo/dummybsa.cpp @@ -1,191 +1,191 @@ -/* -Copyright (C) 2012 Sebastian Herbord. All rights reserved. - -This file is part of Mod Organizer. - -Mod Organizer is free software: you can redistribute it and/or modify -it under the terms of the GNU General Public License as published by -the Free Software Foundation, either version 3 of the License, or -(at your option) any later version. - -Mod Organizer is distributed in the hope that it will be useful, -but WITHOUT ANY WARRANTY; without even the implied warranty of -MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -GNU General Public License for more details. - -You should have received a copy of the GNU General Public License -along with Mod Organizer. If not, see . -*/ - -#include "dummybsa.h" -#include -#define WIN32_LEAN_AND_MEAN -#include - - -static void writeUlong(unsigned char* buffer, int offset, unsigned long value) -{ - union { - unsigned long ulValue; - unsigned char cValue[4]; - }; - ulValue = value; - memcpy(buffer + offset, cValue, 4); -} - -static void writeUlonglong(unsigned char* buffer, int offset, unsigned long long value) -{ - union { - unsigned long long ullValue; - unsigned char cValue[8]; - }; - ullValue = value; - memcpy(buffer + offset, cValue, 8); -} - -static unsigned long genHashInt(const unsigned char *pos, const unsigned char *end) -{ - unsigned long hash = 0; - for (; pos < end; ++pos) { - hash *= 0x1003f; - hash += *pos; - } - return hash; -} - -static unsigned long long genHash(const char* fileName) -{ - char fileNameLower[MAX_PATH + 1]; - int i = 0; - for (; i < MAX_PATH && fileName[i] != '\0'; ++i) { - fileNameLower[i] = static_cast(tolower(fileName[i])); - if (fileNameLower[i] == '\\') { - fileNameLower[i] = '/'; - } - } - fileNameLower[i] = '\0'; - - unsigned char *fileNameLowerU = reinterpret_cast(fileNameLower); - - char* ext = strrchr(fileNameLower, '.'); - if (ext == nullptr) { - ext = fileNameLower + strlen(fileNameLower); - } - unsigned char *extU = reinterpret_cast(ext); - - int length = ext - fileNameLower; - - unsigned long long hash = 0ULL; - - if (length > 0) { - hash = *(extU - 1) | - ((length > 2 ? *(ext - 2) : 0) << 8) | - (length << 16) | - (fileNameLowerU[0] << 24); - } - - if (strlen(ext) > 0) { - if (strcmp(ext + 1, "kf") == 0) { - hash |= 0x80; - } else if (strcmp(ext + 1, "nif") == 0) { - hash |= 0x8000; - } else if (strcmp(ext + 1, "dds") == 0) { - hash |= 0x8080; - } else if (strcmp(ext + 1, "wav") == 0) { - hash |= 0x80000000; - } - - unsigned long long temp = static_cast(genHashInt( - fileNameLowerU + 1, extU - 2)); - temp += static_cast(genHashInt( - extU, extU + strlen(ext))); - - hash |= (temp & 0xFFFFFFFF) << 32; - } - return hash; -} - -DummyBSA::DummyBSA(unsigned long bsaVersion) - : m_Version(bsaVersion) - , m_FolderName("") - , m_FileName("dummy.dds") - , m_TotalFileNameLength(0) -{ -} - -void DummyBSA::writeHeader(QFile &file) -{ - unsigned char header[] = { - 'B', 'S', 'A', '\0', // magic string - 0xDE, 0xAD, 0xBE, 0xEF, // version - insert later - 0x24, 0x00, 0x00, 0x00, // offset to folder recors. header size is static - 0xDE, 0xAD, 0xBE, 0xEF, // archive flags - insert later - 0x01, 0x00, 0x00, 0x00, // folder count - 0x01, 0x00, 0x00, 0x00, // file count - 0xDE, 0xAD, 0xBE, 0xEF, // total folder names length - insert later - 0xDE, 0xAD, 0xBE, 0xEF, // total file names length - insert later - 0xDE, 0xAD, 0xBE, 0xEF // file flags - insert later - }; - - writeUlong(header, 4, m_Version); - writeUlong(header, 12, 0x01 | 0x02); // has directories and has files. - writeUlong(header, 24, static_cast(m_FolderName.length()) + 1); // empty folder name - writeUlong(header, 28, m_TotalFileNameLength); // single character file name - - writeUlong(header, 32, 2); // has dds - - file.write(reinterpret_cast(header), sizeof(header)); -} - -void DummyBSA::writeFolderRecord(QFile &file, const std::string &folderName) -{ - unsigned char folderRecord[] = { - 0xDE, 0xAD, 0xBE, 0xEF, 0xDE, 0xAD, 0xBE, 0xEF, // folder hash - 0x01, 0x00, 0x00, 0x00, // file count - 0xDE, 0xAD, 0xBE, 0xEF, // offset to folder name - }; - // we'd usually have to sort folders be the hash value generated here - writeUlonglong(folderRecord, 0, genHash(folderName.c_str())); - writeUlong( folderRecord, 12, 0x34 + m_TotalFileNameLength); // TODO: this should be calculated properly - - file.write(reinterpret_cast(folderRecord), sizeof(folderRecord)); -} - -void DummyBSA::writeFileRecord(QFile &file, const std::string &fileName) -{ - unsigned char fileRecord[] = { - 0xDE, 0xAD, 0xBE, 0xEF, 0xDE, 0xAD, 0xBE, 0xEF, // file name hash - 0xDE, 0xAD, 0xBE, 0xEF, // size - 0xDE, 0xAD, 0xBE, 0xEF, // offset to file data - }; - - // we'd usually have to sort files by the value generated here - writeUlonglong(fileRecord, 0, genHash(fileName.c_str())); - writeUlong( fileRecord, 8, 0); - writeUlong( fileRecord, 12, 0x44 + static_cast(fileName.length() + 1) + 4); // after this record we expect the filename and 4 bytes of file size - - file.write(reinterpret_cast(fileRecord), sizeof(fileRecord)); -} - -void DummyBSA::writeFileRecordBlocks(QFile &file, const std::string &folderName) -{ - file.write(folderName.c_str(), folderName.length() + 1); - - writeFileRecord(file, m_FileName); -} - -void DummyBSA::write(const QString &fileName) -{ - QFile file(fileName); - file.open(QIODevice::WriteOnly); - - m_TotalFileNameLength = static_cast(m_FileName.length() + 1); - - writeHeader(file); - writeFolderRecord(file, m_FolderName); - writeFileRecordBlocks(file, m_FolderName); - file.write(m_FileName.c_str() , m_FileName.length() + 1); - char fileSize[] = { 0x00, 0x00, 0x00, 0x00 }; - file.write(fileSize, sizeof(fileSize)); - file.close(); -} +/* +Copyright (C) 2012 Sebastian Herbord. All rights reserved. + +This file is part of Mod Organizer. + +Mod Organizer is free software: you can redistribute it and/or modify +it under the terms of the GNU General Public License as published by +the Free Software Foundation, either version 3 of the License, or +(at your option) any later version. + +Mod Organizer is distributed in the hope that it will be useful, +but WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +GNU General Public License for more details. + +You should have received a copy of the GNU General Public License +along with Mod Organizer. If not, see . +*/ + +#include "dummybsa.h" +#include +#define WIN32_LEAN_AND_MEAN +#include + + +static void writeUlong(unsigned char* buffer, int offset, unsigned long value) +{ + union { + unsigned long ulValue; + unsigned char cValue[4]; + }; + ulValue = value; + memcpy(buffer + offset, cValue, 4); +} + +static void writeUlonglong(unsigned char* buffer, int offset, unsigned long long value) +{ + union { + unsigned long long ullValue; + unsigned char cValue[8]; + }; + ullValue = value; + memcpy(buffer + offset, cValue, 8); +} + +static unsigned long genHashInt(const unsigned char *pos, const unsigned char *end) +{ + unsigned long hash = 0; + for (; pos < end; ++pos) { + hash *= 0x1003f; + hash += *pos; + } + return hash; +} + +static unsigned long long genHash(const char* fileName) +{ + char fileNameLower[MAX_PATH + 1]; + int i = 0; + for (; i < MAX_PATH && fileName[i] != '\0'; ++i) { + fileNameLower[i] = static_cast(tolower(fileName[i])); + if (fileNameLower[i] == '\\') { + fileNameLower[i] = '/'; + } + } + fileNameLower[i] = '\0'; + + unsigned char *fileNameLowerU = reinterpret_cast(fileNameLower); + + char* ext = strrchr(fileNameLower, '.'); + if (ext == nullptr) { + ext = fileNameLower + strlen(fileNameLower); + } + unsigned char *extU = reinterpret_cast(ext); + + int length = ext - fileNameLower; + + unsigned long long hash = 0ULL; + + if (length > 0) { + hash = *(extU - 1) | + ((length > 2 ? *(ext - 2) : 0) << 8) | + (length << 16) | + (fileNameLowerU[0] << 24); + } + + if (strlen(ext) > 0) { + if (strcmp(ext + 1, "kf") == 0) { + hash |= 0x80; + } else if (strcmp(ext + 1, "nif") == 0) { + hash |= 0x8000; + } else if (strcmp(ext + 1, "dds") == 0) { + hash |= 0x8080; + } else if (strcmp(ext + 1, "wav") == 0) { + hash |= 0x80000000; + } + + unsigned long long temp = static_cast(genHashInt( + fileNameLowerU + 1, extU - 2)); + temp += static_cast(genHashInt( + extU, extU + strlen(ext))); + + hash |= (temp & 0xFFFFFFFF) << 32; + } + return hash; +} + +DummyBSA::DummyBSA(unsigned long bsaVersion) + : m_Version(bsaVersion) + , m_FolderName("") + , m_FileName("dummy.dds") + , m_TotalFileNameLength(0) +{ +} + +void DummyBSA::writeHeader(QFile &file) +{ + unsigned char header[] = { + 'B', 'S', 'A', '\0', // magic string + 0xDE, 0xAD, 0xBE, 0xEF, // version - insert later + 0x24, 0x00, 0x00, 0x00, // offset to folder recors. header size is static + 0xDE, 0xAD, 0xBE, 0xEF, // archive flags - insert later + 0x01, 0x00, 0x00, 0x00, // folder count + 0x01, 0x00, 0x00, 0x00, // file count + 0xDE, 0xAD, 0xBE, 0xEF, // total folder names length - insert later + 0xDE, 0xAD, 0xBE, 0xEF, // total file names length - insert later + 0xDE, 0xAD, 0xBE, 0xEF // file flags - insert later + }; + + writeUlong(header, 4, m_Version); + writeUlong(header, 12, 0x01 | 0x02); // has directories and has files. + writeUlong(header, 24, static_cast(m_FolderName.length()) + 1); // empty folder name + writeUlong(header, 28, m_TotalFileNameLength); // single character file name + + writeUlong(header, 32, 2); // has dds + + file.write(reinterpret_cast(header), sizeof(header)); +} + +void DummyBSA::writeFolderRecord(QFile &file, const std::string &folderName) +{ + unsigned char folderRecord[] = { + 0xDE, 0xAD, 0xBE, 0xEF, 0xDE, 0xAD, 0xBE, 0xEF, // folder hash + 0x01, 0x00, 0x00, 0x00, // file count + 0xDE, 0xAD, 0xBE, 0xEF, // offset to folder name + }; + // we'd usually have to sort folders be the hash value generated here + writeUlonglong(folderRecord, 0, genHash(folderName.c_str())); + writeUlong( folderRecord, 12, 0x34 + m_TotalFileNameLength); // TODO: this should be calculated properly + + file.write(reinterpret_cast(folderRecord), sizeof(folderRecord)); +} + +void DummyBSA::writeFileRecord(QFile &file, const std::string &fileName) +{ + unsigned char fileRecord[] = { + 0xDE, 0xAD, 0xBE, 0xEF, 0xDE, 0xAD, 0xBE, 0xEF, // file name hash + 0xDE, 0xAD, 0xBE, 0xEF, // size + 0xDE, 0xAD, 0xBE, 0xEF, // offset to file data + }; + + // we'd usually have to sort files by the value generated here + writeUlonglong(fileRecord, 0, genHash(fileName.c_str())); + writeUlong( fileRecord, 8, 0); + writeUlong( fileRecord, 12, 0x44 + static_cast(fileName.length() + 1) + 4); // after this record we expect the filename and 4 bytes of file size + + file.write(reinterpret_cast(fileRecord), sizeof(fileRecord)); +} + +void DummyBSA::writeFileRecordBlocks(QFile &file, const std::string &folderName) +{ + file.write(folderName.c_str(), folderName.length() + 1); + + writeFileRecord(file, m_FileName); +} + +void DummyBSA::write(const QString &fileName) +{ + QFile file(fileName); + file.open(QIODevice::WriteOnly); + + m_TotalFileNameLength = static_cast(m_FileName.length() + 1); + + writeHeader(file); + writeFolderRecord(file, m_FolderName); + writeFileRecordBlocks(file, m_FolderName); + file.write(m_FileName.c_str() , m_FileName.length() + 1); + char fileSize[] = { 0x00, 0x00, 0x00, 0x00 }; + file.write(fileSize, sizeof(fileSize)); + file.close(); +} diff --git a/src/dummybsa.h b/src/gamebryo/dummybsa.h similarity index 96% rename from src/dummybsa.h rename to src/gamebryo/dummybsa.h index 35288439..ba82b059 100644 --- a/src/dummybsa.h +++ b/src/gamebryo/dummybsa.h @@ -1,64 +1,64 @@ -/* -Copyright (C) 2012 Sebastian Herbord. All rights reserved. - -This file is part of Mod Organizer. - -Mod Organizer is free software: you can redistribute it and/or modify -it under the terms of the GNU General Public License as published by -the Free Software Foundation, either version 3 of the License, or -(at your option) any later version. - -Mod Organizer is distributed in the hope that it will be useful, -but WITHOUT ANY WARRANTY; without even the implied warranty of -MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -GNU General Public License for more details. - -You should have received a copy of the GNU General Public License -along with Mod Organizer. If not, see . -*/ - -#ifndef DUMMYBSA_H -#define DUMMYBSA_H - -#include -#include - -/** - * @brief Class for creating a dummy bsa used for archive invalidation - **/ -class DummyBSA -{ - -public: - - /** - * @brief constructor - * - **/ - DummyBSA(unsigned long bsaVersion); - - /** - * @brief write to the specified file - * - * @param fileName name of the file to write to - **/ - void write(const QString &fileName); - -private: - - void writeHeader(QFile &file); - void writeFolderRecord(QFile &file, const std::string &folderName); - void writeFileRecord(QFile &file, const std::string &fileName); - void writeFileRecordBlocks(QFile &file, const std::string &folderName); - -private: - - unsigned long m_Version; - std::string m_FolderName; - std::string m_FileName; - unsigned long m_TotalFileNameLength; - -}; - - -#endif // DUMMYBSA_H +/* +Copyright (C) 2012 Sebastian Herbord. All rights reserved. + +This file is part of Mod Organizer. + +Mod Organizer is free software: you can redistribute it and/or modify +it under the terms of the GNU General Public License as published by +the Free Software Foundation, either version 3 of the License, or +(at your option) any later version. + +Mod Organizer is distributed in the hope that it will be useful, +but WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +GNU General Public License for more details. + +You should have received a copy of the GNU General Public License +along with Mod Organizer. If not, see . +*/ + +#ifndef DUMMYBSA_H +#define DUMMYBSA_H + +#include +#include + +/** + * @brief Class for creating a dummy bsa used for archive invalidation + **/ +class DummyBSA +{ + +public: + + /** + * @brief constructor + * + **/ + DummyBSA(unsigned long bsaVersion); + + /** + * @brief write to the specified file + * + * @param fileName name of the file to write to + **/ + void write(const QString &fileName); + +private: + + void writeHeader(QFile &file); + void writeFolderRecord(QFile &file, const std::string &folderName); + void writeFileRecord(QFile &file, const std::string &fileName); + void writeFileRecordBlocks(QFile &file, const std::string &folderName); + +private: + + unsigned long m_Version; + std::string m_FolderName; + std::string m_FileName; + unsigned long m_TotalFileNameLength; + +}; + + +#endif // DUMMYBSA_H diff --git a/src/gameGamebryo.pro b/src/gamebryo/gameGamebryo.pro similarity index 95% rename from src/gameGamebryo.pro rename to src/gamebryo/gameGamebryo.pro index 45f95ace..5ae81b94 100644 --- a/src/gameGamebryo.pro +++ b/src/gamebryo/gameGamebryo.pro @@ -1,42 +1,42 @@ -#------------------------------------------------- -# -# Project created by QtCreator 2015-01-26T19:47:42 -# -#------------------------------------------------- - -TARGET = gameGamebryo -TEMPLATE = lib -CONFIG += staticlib - -QT += widgets - -SOURCES += gamegamebryo.cpp \ - dummybsa.cpp \ - gamebryobsainvalidation.cpp \ - gamebryodataarchives.cpp \ - gamebryoscriptextender.cpp \ - gamebryosavegame.cpp \ - gamebryolocalsavegames.cpp - gamebryosavegameinfo.cpp \ - gamebryosavegameinfowidget.cpp - -HEADERS += gamegamebryo.h \ - dummybsa.h \ - gamebryobsainvalidation.h \ - gamebryodataarchives.h \ - gamebryoscriptextender.h \ - gamebryosavegame.h \ - gamebryolocalsavegames.h - gamebryosavegameinfo.h \ - gamebryosavegameinfowidget.h - -include(../plugin_template.pri) - -INCLUDEPATH += "$${BOOSTPATH}" "$${PWD}/../gamefeatures" - -OTHER_FILES +=\ - SConscript \ - CMakeLists.txt - -FORMS += \ - gamebryosavegameinfowidget.ui +#------------------------------------------------- +# +# Project created by QtCreator 2015-01-26T19:47:42 +# +#------------------------------------------------- + +TARGET = gameGamebryo +TEMPLATE = lib +CONFIG += staticlib + +QT += widgets + +SOURCES += gamegamebryo.cpp \ + dummybsa.cpp \ + gamebryobsainvalidation.cpp \ + gamebryodataarchives.cpp \ + gamebryoscriptextender.cpp \ + gamebryosavegame.cpp \ + gamebryolocalsavegames.cpp + gamebryosavegameinfo.cpp \ + gamebryosavegameinfowidget.cpp + +HEADERS += gamegamebryo.h \ + dummybsa.h \ + gamebryobsainvalidation.h \ + gamebryodataarchives.h \ + gamebryoscriptextender.h \ + gamebryosavegame.h \ + gamebryolocalsavegames.h + gamebryosavegameinfo.h \ + gamebryosavegameinfowidget.h + +include(../plugin_template.pri) + +INCLUDEPATH += "$${BOOSTPATH}" "$${PWD}/../gamefeatures" + +OTHER_FILES +=\ + SConscript \ + CMakeLists.txt + +FORMS += \ + gamebryosavegameinfowidget.ui diff --git a/src/gamebryobsainvalidation.cpp b/src/gamebryo/gamebryobsainvalidation.cpp similarity index 97% rename from src/gamebryobsainvalidation.cpp rename to src/gamebryo/gamebryobsainvalidation.cpp index 7d5774a8..48bf5e07 100644 --- a/src/gamebryobsainvalidation.cpp +++ b/src/gamebryo/gamebryobsainvalidation.cpp @@ -1,93 +1,93 @@ -#include "gamebryobsainvalidation.h" - -#include "dummybsa.h" -#include "iplugingame.h" -#include "iprofile.h" -#include -#include -#include - -#include -#include - -#include - - -GamebryoBSAInvalidation::GamebryoBSAInvalidation(DataArchives *dataArchives - , const QString &iniFilename - , MOBase::IPluginGame const *game) - : m_DataArchives(dataArchives) - , m_IniFileName(iniFilename) - , m_Game(game) -{ -} - -bool GamebryoBSAInvalidation::isInvalidationBSA(const QString &bsaName) -{ - static QStringList invalidation { invalidationBSAName() }; - - for (const QString &file : invalidation) { - if (file.compare(bsaName, Qt::CaseInsensitive) == 0) { - return true; - } - } - return false; -} - -void GamebryoBSAInvalidation::deactivate(MOBase::IProfile *profile) -{ - QStringList archivesBefore = m_DataArchives->archives(profile); - for (const QString &archive : archivesBefore) { - if (isInvalidationBSA(archive)) { - m_DataArchives->removeArchive(profile, archive); - } - } - - QString bsaFile = m_Game->dataDirectory().absoluteFilePath(invalidationBSAName()); - if (QFile::exists(bsaFile)) { - MOBase::shellDeleteQuiet(bsaFile); - } - - QString iniFile = profile->localSettingsEnabled() ? QDir(profile->absolutePath()).absoluteFilePath(m_IniFileName) : m_Game->documentsDirectory().absoluteFilePath(m_IniFileName); - - ::SetFileAttributesW(iniFile.toStdWString().c_str(), FILE_ATTRIBUTE_NORMAL); - - if (!::WritePrivateProfileStringW(L"Archive", L"bInvalidateOlderFiles", L"0", iniFile.toStdWString().c_str()) || - !::WritePrivateProfileStringW(L"Archive", L"SInvalidationFile", L"ArchiveInvalidation.txt", iniFile.toStdWString().c_str())) { - throw MOBase::MyException(QObject::tr("failed to deactivate BSA invalidation in \"%1\" (errorcode %2)").arg(iniFile, ::GetLastError())); - } -} - -void GamebryoBSAInvalidation::activate(MOBase::IProfile *profile) -{ - // set the invalidation bsa up to be loaded - QStringList archives = m_DataArchives->archives(profile); - bool bsaInstalled = false; - for (const QString &archive : archives) { - if (isInvalidationBSA(archive)) { - bsaInstalled = true; - break; - } - } - if (!bsaInstalled) { - m_DataArchives->addArchive(profile, 0, invalidationBSAName()); - } - - // create the dummy bsa if necessary - QString bsaFile = m_Game->dataDirectory().absoluteFilePath(invalidationBSAName()); - if (!QFile::exists(bsaFile)) { - DummyBSA bsa(bsaVersion()); - bsa.write(bsaFile); - } - - // set the remaining ini settings required - QString iniFile = profile->localSettingsEnabled() ? QDir(profile->absolutePath()).absoluteFilePath(m_IniFileName) : m_Game->documentsDirectory().absoluteFilePath(m_IniFileName); - - ::SetFileAttributesW(iniFile.toStdWString().c_str(), FILE_ATTRIBUTE_NORMAL); - - if (!::WritePrivateProfileStringW(L"Archive", L"bInvalidateOlderFiles", L"1", iniFile.toStdWString().c_str()) || - !::WritePrivateProfileStringW(L"Archive", L"SInvalidationFile", L"", iniFile.toStdWString().c_str())) { - throw MOBase::MyException(QObject::tr("failed to activate BSA invalidation in \"%1\" (errorcode %2)").arg(iniFile, ::GetLastError())); - } -} - +#include "gamebryobsainvalidation.h" + +#include "dummybsa.h" +#include "iplugingame.h" +#include "iprofile.h" +#include +#include +#include + +#include +#include + +#include + + +GamebryoBSAInvalidation::GamebryoBSAInvalidation(DataArchives *dataArchives + , const QString &iniFilename + , MOBase::IPluginGame const *game) + : m_DataArchives(dataArchives) + , m_IniFileName(iniFilename) + , m_Game(game) +{ +} + +bool GamebryoBSAInvalidation::isInvalidationBSA(const QString &bsaName) +{ + static QStringList invalidation { invalidationBSAName() }; + + for (const QString &file : invalidation) { + if (file.compare(bsaName, Qt::CaseInsensitive) == 0) { + return true; + } + } + return false; +} + +void GamebryoBSAInvalidation::deactivate(MOBase::IProfile *profile) +{ + QStringList archivesBefore = m_DataArchives->archives(profile); + for (const QString &archive : archivesBefore) { + if (isInvalidationBSA(archive)) { + m_DataArchives->removeArchive(profile, archive); + } + } + + QString bsaFile = m_Game->dataDirectory().absoluteFilePath(invalidationBSAName()); + if (QFile::exists(bsaFile)) { + MOBase::shellDeleteQuiet(bsaFile); + } + + QString iniFile = profile->localSettingsEnabled() ? QDir(profile->absolutePath()).absoluteFilePath(m_IniFileName) : m_Game->documentsDirectory().absoluteFilePath(m_IniFileName); + + ::SetFileAttributesW(iniFile.toStdWString().c_str(), FILE_ATTRIBUTE_NORMAL); + + if (!::WritePrivateProfileStringW(L"Archive", L"bInvalidateOlderFiles", L"0", iniFile.toStdWString().c_str()) || + !::WritePrivateProfileStringW(L"Archive", L"SInvalidationFile", L"ArchiveInvalidation.txt", iniFile.toStdWString().c_str())) { + throw MOBase::MyException(QObject::tr("failed to deactivate BSA invalidation in \"%1\" (errorcode %2)").arg(iniFile, ::GetLastError())); + } +} + +void GamebryoBSAInvalidation::activate(MOBase::IProfile *profile) +{ + // set the invalidation bsa up to be loaded + QStringList archives = m_DataArchives->archives(profile); + bool bsaInstalled = false; + for (const QString &archive : archives) { + if (isInvalidationBSA(archive)) { + bsaInstalled = true; + break; + } + } + if (!bsaInstalled) { + m_DataArchives->addArchive(profile, 0, invalidationBSAName()); + } + + // create the dummy bsa if necessary + QString bsaFile = m_Game->dataDirectory().absoluteFilePath(invalidationBSAName()); + if (!QFile::exists(bsaFile)) { + DummyBSA bsa(bsaVersion()); + bsa.write(bsaFile); + } + + // set the remaining ini settings required + QString iniFile = profile->localSettingsEnabled() ? QDir(profile->absolutePath()).absoluteFilePath(m_IniFileName) : m_Game->documentsDirectory().absoluteFilePath(m_IniFileName); + + ::SetFileAttributesW(iniFile.toStdWString().c_str(), FILE_ATTRIBUTE_NORMAL); + + if (!::WritePrivateProfileStringW(L"Archive", L"bInvalidateOlderFiles", L"1", iniFile.toStdWString().c_str()) || + !::WritePrivateProfileStringW(L"Archive", L"SInvalidationFile", L"", iniFile.toStdWString().c_str())) { + throw MOBase::MyException(QObject::tr("failed to activate BSA invalidation in \"%1\" (errorcode %2)").arg(iniFile, ::GetLastError())); + } +} + diff --git a/src/gamebryobsainvalidation.h b/src/gamebryo/gamebryobsainvalidation.h similarity index 95% rename from src/gamebryobsainvalidation.h rename to src/gamebryo/gamebryobsainvalidation.h index 45bfaf8b..e73e6837 100644 --- a/src/gamebryobsainvalidation.h +++ b/src/gamebryo/gamebryobsainvalidation.h @@ -1,39 +1,39 @@ -#ifndef GAMEBRYOBSAINVALIDATION_H -#define GAMEBRYOBSAINVALIDATION_H - - -#include -#include -#include -#include - -namespace MOBase { - class IPluginGame; -} - -class GamebryoBSAInvalidation : public BSAInvalidation -{ -public: - - GamebryoBSAInvalidation(DataArchives *dataArchives, - const QString &iniFilename, - MOBase::IPluginGame const *game); - - virtual bool isInvalidationBSA(const QString &bsaName) override; - virtual void deactivate(MOBase::IProfile *profile) override; - virtual void activate(MOBase::IProfile *profile) override; - -private: - - virtual QString invalidationBSAName() const = 0; - virtual unsigned long bsaVersion() const = 0; // 0x67 for oblivion, 0x68 for everything else - -private: - - DataArchives *m_DataArchives; - QString m_IniFileName; - MOBase::IPluginGame const *m_Game; - -}; - -#endif // GAMEBRYOBSAINVALIDATION_H +#ifndef GAMEBRYOBSAINVALIDATION_H +#define GAMEBRYOBSAINVALIDATION_H + + +#include +#include +#include +#include + +namespace MOBase { + class IPluginGame; +} + +class GamebryoBSAInvalidation : public BSAInvalidation +{ +public: + + GamebryoBSAInvalidation(DataArchives *dataArchives, + const QString &iniFilename, + MOBase::IPluginGame const *game); + + virtual bool isInvalidationBSA(const QString &bsaName) override; + virtual void deactivate(MOBase::IProfile *profile) override; + virtual void activate(MOBase::IProfile *profile) override; + +private: + + virtual QString invalidationBSAName() const = 0; + virtual unsigned long bsaVersion() const = 0; // 0x67 for oblivion, 0x68 for everything else + +private: + + DataArchives *m_DataArchives; + QString m_IniFileName; + MOBase::IPluginGame const *m_Game; + +}; + +#endif // GAMEBRYOBSAINVALIDATION_H diff --git a/src/gamebryodataarchives.cpp b/src/gamebryo/gamebryodataarchives.cpp similarity index 97% rename from src/gamebryodataarchives.cpp rename to src/gamebryo/gamebryodataarchives.cpp index 01c33409..6045db10 100644 --- a/src/gamebryodataarchives.cpp +++ b/src/gamebryo/gamebryodataarchives.cpp @@ -1,60 +1,60 @@ -#include "gamebryodataarchives.h" -#include -#include - - -GamebryoDataArchives::GamebryoDataArchives(const QDir &myGamesDir): - m_LocalGameDir(myGamesDir.absolutePath()) -{} - -QStringList GamebryoDataArchives::getArchivesFromKey(const QString &iniFile, const QString &key, const int size) const -{ - wchar_t * buffer = new wchar_t[size]; - QStringList result; - std::wstring iniFileW = QDir::toNativeSeparators(iniFile).toStdWString(); - - // epic ms fail: GetPrivateProfileString uses errno (for whatever reason) to signal a fail since the return value - // has a different meaning (number of bytes copied). HOWEVER, it will not set errno to 0 if NO error occured - errno = 0; - - if (::GetPrivateProfileStringW(L"Archive", key.toStdWString().c_str(), - L"", buffer, size, iniFileW.c_str()) != 0) { - result.append(QString::fromStdWString(buffer).split(',')); - } - - for (int i = 0; i < result.count(); ++i) { - result[i] = result[i].trimmed(); - } - delete[] buffer; - return result; -} - -void GamebryoDataArchives::setArchivesToKey(const QString &iniFile, const QString &key, const QString &value) -{ - if (!::WritePrivateProfileStringW(L"Archive", key.toStdWString().c_str(), value.toStdWString().c_str(), iniFile.toStdWString().c_str())) { - throw MOBase::MyException(QObject::tr("failed to set archive key (errorcode %1)").arg(errno)); - } -} - -void GamebryoDataArchives::addArchive(MOBase::IProfile *profile, int index, const QString &archiveName) -{ - QStringList current = archives(profile); - if (current.contains(archiveName, Qt::CaseInsensitive)) { - return; - } - - current.insert(index != INT_MAX ? index : current.size(), archiveName); - - writeArchiveList(profile, current); -} - -void GamebryoDataArchives::removeArchive(MOBase::IProfile *profile, const QString &archiveName) -{ - QStringList current = archives(profile); - if (!current.contains(archiveName, Qt::CaseInsensitive)) { - return; - } - current.removeAll(archiveName); - - writeArchiveList(profile, current); +#include "gamebryodataarchives.h" +#include +#include + + +GamebryoDataArchives::GamebryoDataArchives(const QDir &myGamesDir): + m_LocalGameDir(myGamesDir.absolutePath()) +{} + +QStringList GamebryoDataArchives::getArchivesFromKey(const QString &iniFile, const QString &key, const int size) const +{ + wchar_t * buffer = new wchar_t[size]; + QStringList result; + std::wstring iniFileW = QDir::toNativeSeparators(iniFile).toStdWString(); + + // epic ms fail: GetPrivateProfileString uses errno (for whatever reason) to signal a fail since the return value + // has a different meaning (number of bytes copied). HOWEVER, it will not set errno to 0 if NO error occured + errno = 0; + + if (::GetPrivateProfileStringW(L"Archive", key.toStdWString().c_str(), + L"", buffer, size, iniFileW.c_str()) != 0) { + result.append(QString::fromStdWString(buffer).split(',')); + } + + for (int i = 0; i < result.count(); ++i) { + result[i] = result[i].trimmed(); + } + delete[] buffer; + return result; +} + +void GamebryoDataArchives::setArchivesToKey(const QString &iniFile, const QString &key, const QString &value) +{ + if (!::WritePrivateProfileStringW(L"Archive", key.toStdWString().c_str(), value.toStdWString().c_str(), iniFile.toStdWString().c_str())) { + throw MOBase::MyException(QObject::tr("failed to set archive key (errorcode %1)").arg(errno)); + } +} + +void GamebryoDataArchives::addArchive(MOBase::IProfile *profile, int index, const QString &archiveName) +{ + QStringList current = archives(profile); + if (current.contains(archiveName, Qt::CaseInsensitive)) { + return; + } + + current.insert(index != INT_MAX ? index : current.size(), archiveName); + + writeArchiveList(profile, current); +} + +void GamebryoDataArchives::removeArchive(MOBase::IProfile *profile, const QString &archiveName) +{ + QStringList current = archives(profile); + if (!current.contains(archiveName, Qt::CaseInsensitive)) { + return; + } + current.removeAll(archiveName); + + writeArchiveList(profile, current); } \ No newline at end of file diff --git a/src/gamebryodataarchives.h b/src/gamebryo/gamebryodataarchives.h similarity index 96% rename from src/gamebryodataarchives.h rename to src/gamebryo/gamebryodataarchives.h index cd8333ba..b07b251f 100644 --- a/src/gamebryodataarchives.h +++ b/src/gamebryo/gamebryodataarchives.h @@ -1,29 +1,29 @@ -#ifndef GAMEBRYODATAARCHIVES_H -#define GAMEBRYODATAARCHIVES_H - - -#include "dataarchives.h" -#include - -class GamebryoDataArchives : public DataArchives -{ - -public: - GamebryoDataArchives(const QDir &myGamesDir); - - virtual void addArchive(MOBase::IProfile *profile, int index, const QString &archiveName) override; - virtual void removeArchive(MOBase::IProfile *profile, const QString &archiveName) override; - -protected: - - QDir m_LocalGameDir; - QStringList getArchivesFromKey(const QString &iniFile, const QString &key, int size=256) const; - void setArchivesToKey(const QString &iniFile, const QString &key, const QString &value); - -private: - - virtual void writeArchiveList(MOBase::IProfile *profile, const QStringList &before) = 0; - -}; - -#endif // GAMEBRYODATAARCHIVES_H +#ifndef GAMEBRYODATAARCHIVES_H +#define GAMEBRYODATAARCHIVES_H + + +#include "dataarchives.h" +#include + +class GamebryoDataArchives : public DataArchives +{ + +public: + GamebryoDataArchives(const QDir &myGamesDir); + + virtual void addArchive(MOBase::IProfile *profile, int index, const QString &archiveName) override; + virtual void removeArchive(MOBase::IProfile *profile, const QString &archiveName) override; + +protected: + + QDir m_LocalGameDir; + QStringList getArchivesFromKey(const QString &iniFile, const QString &key, int size=256) const; + void setArchivesToKey(const QString &iniFile, const QString &key, const QString &value); + +private: + + virtual void writeArchiveList(MOBase::IProfile *profile, const QStringList &before) = 0; + +}; + +#endif // GAMEBRYODATAARCHIVES_H diff --git a/src/gamebryogameplugins.cpp b/src/gamebryo/gamebryogameplugins.cpp similarity index 100% rename from src/gamebryogameplugins.cpp rename to src/gamebryo/gamebryogameplugins.cpp diff --git a/src/gamebryogameplugins.h b/src/gamebryo/gamebryogameplugins.h similarity index 100% rename from src/gamebryogameplugins.h rename to src/gamebryo/gamebryogameplugins.h diff --git a/src/gamebryolocalsavegames.cpp b/src/gamebryo/gamebryolocalsavegames.cpp similarity index 100% rename from src/gamebryolocalsavegames.cpp rename to src/gamebryo/gamebryolocalsavegames.cpp diff --git a/src/gamebryolocalsavegames.h b/src/gamebryo/gamebryolocalsavegames.h similarity index 100% rename from src/gamebryolocalsavegames.h rename to src/gamebryo/gamebryolocalsavegames.h diff --git a/src/gamebryosavegame.cpp b/src/gamebryo/gamebryosavegame.cpp similarity index 100% rename from src/gamebryosavegame.cpp rename to src/gamebryo/gamebryosavegame.cpp diff --git a/src/gamebryosavegame.h b/src/gamebryo/gamebryosavegame.h similarity index 100% rename from src/gamebryosavegame.h rename to src/gamebryo/gamebryosavegame.h diff --git a/src/gamebryosavegameinfo.cpp b/src/gamebryo/gamebryosavegameinfo.cpp similarity index 100% rename from src/gamebryosavegameinfo.cpp rename to src/gamebryo/gamebryosavegameinfo.cpp diff --git a/src/gamebryosavegameinfo.h b/src/gamebryo/gamebryosavegameinfo.h similarity index 100% rename from src/gamebryosavegameinfo.h rename to src/gamebryo/gamebryosavegameinfo.h diff --git a/src/gamebryosavegameinfowidget.cpp b/src/gamebryo/gamebryosavegameinfowidget.cpp similarity index 100% rename from src/gamebryosavegameinfowidget.cpp rename to src/gamebryo/gamebryosavegameinfowidget.cpp diff --git a/src/gamebryosavegameinfowidget.h b/src/gamebryo/gamebryosavegameinfowidget.h similarity index 100% rename from src/gamebryosavegameinfowidget.h rename to src/gamebryo/gamebryosavegameinfowidget.h diff --git a/src/gamebryosavegameinfowidget.ui b/src/gamebryo/gamebryosavegameinfowidget.ui similarity index 100% rename from src/gamebryosavegameinfowidget.ui rename to src/gamebryo/gamebryosavegameinfowidget.ui diff --git a/src/gamebryoscriptextender.cpp b/src/gamebryo/gamebryoscriptextender.cpp similarity index 100% rename from src/gamebryoscriptextender.cpp rename to src/gamebryo/gamebryoscriptextender.cpp diff --git a/src/gamebryoscriptextender.h b/src/gamebryo/gamebryoscriptextender.h similarity index 100% rename from src/gamebryoscriptextender.h rename to src/gamebryo/gamebryoscriptextender.h diff --git a/src/gamebryounmanagedmods.cpp b/src/gamebryo/gamebryounmanagedmods.cpp similarity index 100% rename from src/gamebryounmanagedmods.cpp rename to src/gamebryo/gamebryounmanagedmods.cpp diff --git a/src/gamebryounmanagedmods.h b/src/gamebryo/gamebryounmanagedmods.h similarity index 100% rename from src/gamebryounmanagedmods.h rename to src/gamebryo/gamebryounmanagedmods.h diff --git a/src/gamegamebryo.cpp b/src/gamebryo/gamegamebryo.cpp similarity index 96% rename from src/gamegamebryo.cpp rename to src/gamebryo/gamegamebryo.cpp index d4f1b912..ae0cd2bf 100644 --- a/src/gamegamebryo.cpp +++ b/src/gamebryo/gamegamebryo.cpp @@ -1,353 +1,353 @@ -#include "gamegamebryo.h" - -#include "bsainvalidation.h" -#include "dataarchives.h" -#include "savegameinfo.h" -#include "scriptextender.h" -#include "scopeguard.h" -#include "utility.h" - -#include -#include -#include -#include - -#include -#include - -#include -#include -#include -#include -#include - -#include -#include -#include - -GameGamebryo::GameGamebryo() -{ -} - -bool GameGamebryo::init(MOBase::IOrganizer *moInfo) -{ - m_GamePath = identifyGamePath(); - m_MyGamesPath = determineMyGamesPath(gameShortName()); - m_Organizer = moInfo; - return true; -} - -bool GameGamebryo::isInstalled() const -{ - return !m_GamePath.isEmpty(); -} - -QIcon GameGamebryo::gameIcon() const -{ - return MOBase::iconForExecutable(gameDirectory().absoluteFilePath(binaryName())); -} - -QDir GameGamebryo::gameDirectory() const -{ - return QDir(m_GamePath); -} - -QDir GameGamebryo::dataDirectory() const -{ - return gameDirectory().absoluteFilePath("data"); -} - -void GameGamebryo::setGamePath(const QString &path) -{ - m_GamePath = path; -} - -QDir GameGamebryo::documentsDirectory() const -{ - return m_MyGamesPath; -} - -QDir GameGamebryo::savesDirectory() const -{ - return QDir(m_MyGamesPath + "/Saves"); -} - -QStringList GameGamebryo::gameVariants() const -{ - return QStringList(); -} - -void GameGamebryo::setGameVariant(const QString &variant) -{ - m_GameVariant = variant; -} - -QString GameGamebryo::binaryName() const -{ - return gameShortName() + ".exe"; -} - -QStringList GameGamebryo::primarySources() const -{ - return {}; -} - -QStringList GameGamebryo::validShortNames() const -{ - return {}; -} - -QStringList GameGamebryo::CCPlugins() const -{ - return {}; -} - -MOBase::IPluginGame::LoadOrderMechanism GameGamebryo::loadOrderMechanism() const -{ - return LoadOrderMechanism::FileTime; -} - -MOBase::IPluginGame::SortMechanism GameGamebryo::sortMechanism() const -{ - return SortMechanism::LOOT; -} - -bool GameGamebryo::looksValid(QDir const &path) const -{ - //Check for .exe and Launcher.exe for now. - return path.exists(binaryName()) && path.exists(getLauncherName()); -} - -QString GameGamebryo::gameVersion() const -{ - return getVersion(binaryName()); -} - -QString GameGamebryo::getLauncherName() const -{ - return gameShortName() + "Launcher.exe"; -} - -QString GameGamebryo::getVersion(QString const &program) const -{ - //This *really* needs to be factored out - std::wstring app_name = L"\\\\?\\" + - QDir::toNativeSeparators(this->gameDirectory().absoluteFilePath(program)).toStdWString(); - DWORD handle; - DWORD info_len = ::GetFileVersionInfoSizeW(app_name.c_str(), &handle); - if (info_len == 0) { - qDebug("GetFileVersionInfoSizeW Error %d", ::GetLastError()); - return ""; - } - - std::vector buff(info_len); - if( ! ::GetFileVersionInfoW(app_name.c_str(), handle, info_len, buff.data())) { - qDebug("GetFileVersionInfoW Error %d", ::GetLastError()); - return ""; - } - - VS_FIXEDFILEINFO *pFileInfo; - UINT buf_len; - if ( ! ::VerQueryValueW(buff.data(), L"\\", reinterpret_cast(&pFileInfo), &buf_len)) { - qDebug("VerQueryValueW Error %d", ::GetLastError()); - return ""; - } - return QString("%1.%2.%3.%4").arg(HIWORD(pFileInfo->dwFileVersionMS)) - .arg(LOWORD(pFileInfo->dwFileVersionMS)) - .arg(HIWORD(pFileInfo->dwFileVersionLS)) - .arg(LOWORD(pFileInfo->dwFileVersionLS)); -} - -WORD GameGamebryo::getArch(QString const &program) const -{ - WORD arch = 0; - //This *really* needs to be factored out - LPCSTR app_name = ("\\\\?\\" + - QDir::toNativeSeparators(this->gameDirectory().absoluteFilePath(program)).toStdString()).c_str(); - - WIN32_FIND_DATA FindFileData; - HANDLE hFind = ::FindFirstFile(app_name, &FindFileData); - - //exit if the binary was not found - if (hFind == INVALID_HANDLE_VALUE) return arch; - - HANDLE hFile = CreateFile(app_name, GENERIC_READ, FILE_SHARE_READ, NULL, OPEN_EXISTING, FILE_ATTRIBUTE_READONLY, NULL); - if (hFile == INVALID_HANDLE_VALUE) goto cleanup; - - HANDLE hMapping = CreateFileMapping(hFile, NULL, PAGE_READONLY | SEC_IMAGE, 0, 0, program.toStdString().c_str()); - if (hMapping == INVALID_HANDLE_VALUE) goto cleanup; - - LPVOID addrHeader = MapViewOfFile(hMapping, FILE_MAP_READ, 0, 0, 0); - if (addrHeader == NULL) goto cleanup; //couldn't memory map the file - - PIMAGE_NT_HEADERS peHdr = ImageNtHeader(addrHeader); - if (peHdr == NULL) goto cleanup; //couldn't read the header - - arch = peHdr->FileHeader.Machine; - -cleanup: //release all of our handles - FindClose(hFind); - if (hFile != INVALID_HANDLE_VALUE) - CloseHandle(hFile); - if (hMapping != INVALID_HANDLE_VALUE) - CloseHandle(hMapping); - return arch; -} - -QFileInfo GameGamebryo::findInGameFolder(const QString &relativePath) const -{ - return QFileInfo(m_GamePath + "/" + relativePath); -} - -QString GameGamebryo::identifyGamePath() const -{ - QString path = "Software\\Bethesda Softworks\\" + gameShortName(); - return findInRegistry(HKEY_LOCAL_MACHINE, path.toStdWString().c_str(), L"Installed Path"); -} - -QString GameGamebryo::selectedVariant() const -{ - return m_GameVariant; -} - -QString GameGamebryo::myGamesPath() const -{ - return m_MyGamesPath; -} - -/*static*/ QString GameGamebryo::getLootPath() -{ - return findInRegistry(HKEY_LOCAL_MACHINE, L"Software\\LOOT", L"Installed Path") + "/Loot.exe"; -} - -std::map GameGamebryo::featureList() const -{ - return m_FeatureList; -} - -QString GameGamebryo::localAppFolder() -{ - QString result = getKnownFolderPath(FOLDERID_LocalAppData, false); - if (result.isEmpty()) { - // fallback: try the registry - result = getSpecialPath("Local AppData"); - } - return result; -} - -void GameGamebryo::copyToProfile(QString const &sourcePath, - QDir const &destinationDirectory, - QString const &sourceFileName) { - copyToProfile(sourcePath, destinationDirectory, sourceFileName, - sourceFileName); -} - -void GameGamebryo::copyToProfile(QString const &sourcePath, - QDir const &destinationDirectory, - QString const &sourceFileName, - QString const &destinationFileName) { - QString filePath = destinationDirectory.absoluteFilePath(destinationFileName); - if (!QFileInfo(filePath).exists()) { - if (!MOBase::shellCopy(sourcePath + "/" + sourceFileName, filePath)) { - // if copy file fails, create the file empty - QFile(filePath).open(QIODevice::WriteOnly); - } - } -} - -MappingType GameGamebryo::mappings() const -{ - MappingType result; - - for (const QString &profileFile : { "plugins.txt", "loadorder.txt" }) { - result.push_back({ m_Organizer->profilePath() + "/" + profileFile, - localAppFolder() + "/" + gameShortName() + "/" + profileFile, - false }); - } - - return result; -} - -std::unique_ptr GameGamebryo::getRegValue(HKEY key, LPCWSTR path, LPCWSTR value, - DWORD flags, LPDWORD type = nullptr) -{ - DWORD size = 0; - HKEY subKey; - LONG res = ::RegOpenKeyExW(key, path, 0, - KEY_QUERY_VALUE | KEY_WOW64_32KEY, &subKey); - if (res != ERROR_SUCCESS) { - return std::unique_ptr(); - } - res = ::RegGetValueW(subKey, L"", value, flags, type, nullptr, &size); - if (res == ERROR_FILE_NOT_FOUND || res == ERROR_UNSUPPORTED_TYPE) { - return std::unique_ptr(); - } - if (res != ERROR_SUCCESS && res != ERROR_MORE_DATA) { - throw MOBase::MyException(QObject::tr("failed to query registry path (preflight): %1").arg(res, 0, 16)); - } - - std::unique_ptr result(new BYTE[size]); - res = ::RegGetValueW(subKey, L"", value, flags, type, result.get(), &size); - - if (res != ERROR_SUCCESS) { - throw MOBase::MyException(QObject::tr("failed to query registry path (read): %1").arg(res, 0, 16)); - } - - return result; -} - -QString GameGamebryo::findInRegistry(HKEY baseKey, LPCWSTR path, LPCWSTR value) -{ - std::unique_ptr buffer = getRegValue(baseKey, path, value, RRF_RT_REG_SZ | RRF_NOEXPAND); - - return QString::fromUtf16(reinterpret_cast(buffer.get())); -} - -QString GameGamebryo::getKnownFolderPath(REFKNOWNFOLDERID folderId, bool useDefault) -{ - PWSTR path = nullptr; - ON_BLOCK_EXIT([&]() { - if (path != nullptr) ::CoTaskMemFree(path); - }); - - if (::SHGetKnownFolderPath(folderId, useDefault ? KF_FLAG_DEFAULT_PATH : 0, NULL, &path) == S_OK) { - return QDir::fromNativeSeparators(QString::fromWCharArray(path)); - } - else { - return QString(); - } -} - -QString GameGamebryo::getSpecialPath(const QString &name) -{ - QString base = findInRegistry(HKEY_CURRENT_USER, - L"Software\\Microsoft\\Windows\\CurrentVersion\\Explorer\\User Shell Folders", - name.toStdWString().c_str()); - - WCHAR temp[MAX_PATH]; - if (::ExpandEnvironmentStringsW(base.toStdWString().c_str(), temp, MAX_PATH) != 0) { - return QString::fromWCharArray(temp); - } - else { - return base; - } -} - -QString GameGamebryo::determineMyGamesPath(const QString &gameName) -{ - // a) this is the way it should work. get the configured My Documents directory - QString result = getKnownFolderPath(FOLDERID_Documents, false); - - // b) if there is no directory there, look in the default directory - if (result.isEmpty() - || !QFileInfo(result + "/My Games/" + gameName).exists()) { - result = getKnownFolderPath(FOLDERID_Documents, true); - } - // c) finally, look in the registry. This is discouraged - if (result.isEmpty() - || !QFileInfo(result + "/My Games/" + gameName).exists()) { - result = getSpecialPath("Personal"); - } - - return result + "/My Games/" + gameName; +#include "gamegamebryo.h" + +#include "bsainvalidation.h" +#include "dataarchives.h" +#include "savegameinfo.h" +#include "scriptextender.h" +#include "scopeguard.h" +#include "utility.h" + +#include +#include +#include +#include + +#include +#include + +#include +#include +#include +#include +#include + +#include +#include +#include + +GameGamebryo::GameGamebryo() +{ +} + +bool GameGamebryo::init(MOBase::IOrganizer *moInfo) +{ + m_GamePath = identifyGamePath(); + m_MyGamesPath = determineMyGamesPath(gameShortName()); + m_Organizer = moInfo; + return true; +} + +bool GameGamebryo::isInstalled() const +{ + return !m_GamePath.isEmpty(); +} + +QIcon GameGamebryo::gameIcon() const +{ + return MOBase::iconForExecutable(gameDirectory().absoluteFilePath(binaryName())); +} + +QDir GameGamebryo::gameDirectory() const +{ + return QDir(m_GamePath); +} + +QDir GameGamebryo::dataDirectory() const +{ + return gameDirectory().absoluteFilePath("data"); +} + +void GameGamebryo::setGamePath(const QString &path) +{ + m_GamePath = path; +} + +QDir GameGamebryo::documentsDirectory() const +{ + return m_MyGamesPath; +} + +QDir GameGamebryo::savesDirectory() const +{ + return QDir(m_MyGamesPath + "/Saves"); +} + +QStringList GameGamebryo::gameVariants() const +{ + return QStringList(); +} + +void GameGamebryo::setGameVariant(const QString &variant) +{ + m_GameVariant = variant; +} + +QString GameGamebryo::binaryName() const +{ + return gameShortName() + ".exe"; +} + +QStringList GameGamebryo::primarySources() const +{ + return {}; +} + +QStringList GameGamebryo::validShortNames() const +{ + return {}; +} + +QStringList GameGamebryo::CCPlugins() const +{ + return {}; +} + +MOBase::IPluginGame::LoadOrderMechanism GameGamebryo::loadOrderMechanism() const +{ + return LoadOrderMechanism::FileTime; +} + +MOBase::IPluginGame::SortMechanism GameGamebryo::sortMechanism() const +{ + return SortMechanism::LOOT; +} + +bool GameGamebryo::looksValid(QDir const &path) const +{ + //Check for .exe and Launcher.exe for now. + return path.exists(binaryName()) && path.exists(getLauncherName()); +} + +QString GameGamebryo::gameVersion() const +{ + return getVersion(binaryName()); +} + +QString GameGamebryo::getLauncherName() const +{ + return gameShortName() + "Launcher.exe"; +} + +QString GameGamebryo::getVersion(QString const &program) const +{ + //This *really* needs to be factored out + std::wstring app_name = L"\\\\?\\" + + QDir::toNativeSeparators(this->gameDirectory().absoluteFilePath(program)).toStdWString(); + DWORD handle; + DWORD info_len = ::GetFileVersionInfoSizeW(app_name.c_str(), &handle); + if (info_len == 0) { + qDebug("GetFileVersionInfoSizeW Error %d", ::GetLastError()); + return ""; + } + + std::vector buff(info_len); + if( ! ::GetFileVersionInfoW(app_name.c_str(), handle, info_len, buff.data())) { + qDebug("GetFileVersionInfoW Error %d", ::GetLastError()); + return ""; + } + + VS_FIXEDFILEINFO *pFileInfo; + UINT buf_len; + if ( ! ::VerQueryValueW(buff.data(), L"\\", reinterpret_cast(&pFileInfo), &buf_len)) { + qDebug("VerQueryValueW Error %d", ::GetLastError()); + return ""; + } + return QString("%1.%2.%3.%4").arg(HIWORD(pFileInfo->dwFileVersionMS)) + .arg(LOWORD(pFileInfo->dwFileVersionMS)) + .arg(HIWORD(pFileInfo->dwFileVersionLS)) + .arg(LOWORD(pFileInfo->dwFileVersionLS)); +} + +WORD GameGamebryo::getArch(QString const &program) const +{ + WORD arch = 0; + //This *really* needs to be factored out + LPCSTR app_name = ("\\\\?\\" + + QDir::toNativeSeparators(this->gameDirectory().absoluteFilePath(program)).toStdString()).c_str(); + + WIN32_FIND_DATA FindFileData; + HANDLE hFind = ::FindFirstFile(app_name, &FindFileData); + + //exit if the binary was not found + if (hFind == INVALID_HANDLE_VALUE) return arch; + + HANDLE hFile = CreateFile(app_name, GENERIC_READ, FILE_SHARE_READ, NULL, OPEN_EXISTING, FILE_ATTRIBUTE_READONLY, NULL); + if (hFile == INVALID_HANDLE_VALUE) goto cleanup; + + HANDLE hMapping = CreateFileMapping(hFile, NULL, PAGE_READONLY | SEC_IMAGE, 0, 0, program.toStdString().c_str()); + if (hMapping == INVALID_HANDLE_VALUE) goto cleanup; + + LPVOID addrHeader = MapViewOfFile(hMapping, FILE_MAP_READ, 0, 0, 0); + if (addrHeader == NULL) goto cleanup; //couldn't memory map the file + + PIMAGE_NT_HEADERS peHdr = ImageNtHeader(addrHeader); + if (peHdr == NULL) goto cleanup; //couldn't read the header + + arch = peHdr->FileHeader.Machine; + +cleanup: //release all of our handles + FindClose(hFind); + if (hFile != INVALID_HANDLE_VALUE) + CloseHandle(hFile); + if (hMapping != INVALID_HANDLE_VALUE) + CloseHandle(hMapping); + return arch; +} + +QFileInfo GameGamebryo::findInGameFolder(const QString &relativePath) const +{ + return QFileInfo(m_GamePath + "/" + relativePath); +} + +QString GameGamebryo::identifyGamePath() const +{ + QString path = "Software\\Bethesda Softworks\\" + gameShortName(); + return findInRegistry(HKEY_LOCAL_MACHINE, path.toStdWString().c_str(), L"Installed Path"); +} + +QString GameGamebryo::selectedVariant() const +{ + return m_GameVariant; +} + +QString GameGamebryo::myGamesPath() const +{ + return m_MyGamesPath; +} + +/*static*/ QString GameGamebryo::getLootPath() +{ + return findInRegistry(HKEY_LOCAL_MACHINE, L"Software\\LOOT", L"Installed Path") + "/Loot.exe"; +} + +std::map GameGamebryo::featureList() const +{ + return m_FeatureList; +} + +QString GameGamebryo::localAppFolder() +{ + QString result = getKnownFolderPath(FOLDERID_LocalAppData, false); + if (result.isEmpty()) { + // fallback: try the registry + result = getSpecialPath("Local AppData"); + } + return result; +} + +void GameGamebryo::copyToProfile(QString const &sourcePath, + QDir const &destinationDirectory, + QString const &sourceFileName) { + copyToProfile(sourcePath, destinationDirectory, sourceFileName, + sourceFileName); +} + +void GameGamebryo::copyToProfile(QString const &sourcePath, + QDir const &destinationDirectory, + QString const &sourceFileName, + QString const &destinationFileName) { + QString filePath = destinationDirectory.absoluteFilePath(destinationFileName); + if (!QFileInfo(filePath).exists()) { + if (!MOBase::shellCopy(sourcePath + "/" + sourceFileName, filePath)) { + // if copy file fails, create the file empty + QFile(filePath).open(QIODevice::WriteOnly); + } + } +} + +MappingType GameGamebryo::mappings() const +{ + MappingType result; + + for (const QString &profileFile : { "plugins.txt", "loadorder.txt" }) { + result.push_back({ m_Organizer->profilePath() + "/" + profileFile, + localAppFolder() + "/" + gameShortName() + "/" + profileFile, + false }); + } + + return result; +} + +std::unique_ptr GameGamebryo::getRegValue(HKEY key, LPCWSTR path, LPCWSTR value, + DWORD flags, LPDWORD type = nullptr) +{ + DWORD size = 0; + HKEY subKey; + LONG res = ::RegOpenKeyExW(key, path, 0, + KEY_QUERY_VALUE | KEY_WOW64_32KEY, &subKey); + if (res != ERROR_SUCCESS) { + return std::unique_ptr(); + } + res = ::RegGetValueW(subKey, L"", value, flags, type, nullptr, &size); + if (res == ERROR_FILE_NOT_FOUND || res == ERROR_UNSUPPORTED_TYPE) { + return std::unique_ptr(); + } + if (res != ERROR_SUCCESS && res != ERROR_MORE_DATA) { + throw MOBase::MyException(QObject::tr("failed to query registry path (preflight): %1").arg(res, 0, 16)); + } + + std::unique_ptr result(new BYTE[size]); + res = ::RegGetValueW(subKey, L"", value, flags, type, result.get(), &size); + + if (res != ERROR_SUCCESS) { + throw MOBase::MyException(QObject::tr("failed to query registry path (read): %1").arg(res, 0, 16)); + } + + return result; +} + +QString GameGamebryo::findInRegistry(HKEY baseKey, LPCWSTR path, LPCWSTR value) +{ + std::unique_ptr buffer = getRegValue(baseKey, path, value, RRF_RT_REG_SZ | RRF_NOEXPAND); + + return QString::fromUtf16(reinterpret_cast(buffer.get())); +} + +QString GameGamebryo::getKnownFolderPath(REFKNOWNFOLDERID folderId, bool useDefault) +{ + PWSTR path = nullptr; + ON_BLOCK_EXIT([&]() { + if (path != nullptr) ::CoTaskMemFree(path); + }); + + if (::SHGetKnownFolderPath(folderId, useDefault ? KF_FLAG_DEFAULT_PATH : 0, NULL, &path) == S_OK) { + return QDir::fromNativeSeparators(QString::fromWCharArray(path)); + } + else { + return QString(); + } +} + +QString GameGamebryo::getSpecialPath(const QString &name) +{ + QString base = findInRegistry(HKEY_CURRENT_USER, + L"Software\\Microsoft\\Windows\\CurrentVersion\\Explorer\\User Shell Folders", + name.toStdWString().c_str()); + + WCHAR temp[MAX_PATH]; + if (::ExpandEnvironmentStringsW(base.toStdWString().c_str(), temp, MAX_PATH) != 0) { + return QString::fromWCharArray(temp); + } + else { + return base; + } +} + +QString GameGamebryo::determineMyGamesPath(const QString &gameName) +{ + // a) this is the way it should work. get the configured My Documents directory + QString result = getKnownFolderPath(FOLDERID_Documents, false); + + // b) if there is no directory there, look in the default directory + if (result.isEmpty() + || !QFileInfo(result + "/My Games/" + gameName).exists()) { + result = getKnownFolderPath(FOLDERID_Documents, true); + } + // c) finally, look in the registry. This is discouraged + if (result.isEmpty() + || !QFileInfo(result + "/My Games/" + gameName).exists()) { + result = getSpecialPath("Personal"); + } + + return result + "/My Games/" + gameName; } \ No newline at end of file diff --git a/src/gamegamebryo.h b/src/gamebryo/gamegamebryo.h similarity index 96% rename from src/gamegamebryo.h rename to src/gamebryo/gamegamebryo.h index 70a35920..841e7e8a 100644 --- a/src/gamegamebryo.h +++ b/src/gamebryo/gamegamebryo.h @@ -1,145 +1,145 @@ -#ifndef GAMEGAMEBRYO_H -#define GAMEGAMEBRYO_H - -#include "iplugingame.h" - -class BSAInvalidation; -class DataArchives; -class LocalSavegames; -class SaveGameInfo; -class BSAInvalidation; -class LocalSavegames; -class ScriptExtender; -class GamePlugins; -class UnmanagedMods; - -#include -#include -#include -#include -#include -#include -#include - -class GameGamebryo : public MOBase::IPluginGame, - public MOBase::IPluginFileMapper -{ - Q_OBJECT - Q_INTERFACES(MOBase::IPlugin MOBase::IPluginGame MOBase::IPluginFileMapper) - - friend class GamebryoScriptExtender; - friend class GamebryoSaveGameInfo; - friend class GamebryoSaveGameInfoWidget; - -public: - - GameGamebryo(); - - virtual bool init(MOBase::IOrganizer *moInfo) override; - -public: // IPluginGame interface - - //getName - //initializeProfile - //savegameExtension - //savegameSEExtension - virtual bool isInstalled() const override; - virtual QIcon gameIcon() const override; - virtual QDir gameDirectory() const override; - virtual QDir dataDirectory() const override; - virtual void setGamePath(const QString &path) override; - virtual QDir documentsDirectory() const override; - virtual QDir savesDirectory() const override; - //executables - //steamAPPId - //primaryPlugins - virtual QStringList gameVariants() const override; - virtual void setGameVariant(const QString &variant) override; - virtual QString binaryName() const override; - //gameShortName - virtual QStringList primarySources() const override; - virtual QStringList validShortNames() const override; - //iniFiles - //DLCPlugins - virtual QStringList CCPlugins() const override; - virtual LoadOrderMechanism loadOrderMechanism() const override; - virtual SortMechanism sortMechanism() const override; - //nexusModOrganizerID - //nexusGameID - virtual bool looksValid(QDir const &) const override; - virtual QString gameVersion() const override; - virtual QString getLauncherName() const override; - -public: // IPluginFileMapper interface - - virtual MappingType mappings() const; - -protected: - - QFileInfo findInGameFolder(const QString &relativePath) const; - QString myGamesPath() const; - QString selectedVariant() const; - QString getVersion(QString const &program) const; - WORD getArch(QString const &program) const; - - static QString localAppFolder(); - //Arguably this shouldn't really be here but every gamebryo program seems to - //use it - static QString getLootPath(); - - //This function is not terribly well named as it copies exactly where it's told - //to, irrespective of whether it's in the profile... - static void copyToProfile(const QString &sourcePath, - const QDir &destinationDirectory, - const QString &sourceFileName); - - static void copyToProfile(const QString &sourcePath, - const QDir &destinationDirectory, - const QString &sourceFileName, - const QString &destinationFileName); - - virtual QString identifyGamePath() const; - - static std::unique_ptr getRegValue(HKEY key, LPCWSTR path, LPCWSTR value, DWORD flags, LPDWORD type); - - static QString findInRegistry(HKEY baseKey, LPCWSTR path, LPCWSTR value); - - static QString getKnownFolderPath(REFKNOWNFOLDERID folderId, bool useDefault); - - static QString getSpecialPath(const QString &name); - - static QString determineMyGamesPath(const QString &gameName); - -protected: - - std::map featureList() const; - - //These should be implemented by anything that uses gamebryo (I think) - //(and if they don't, it'll be a null pointer and won't look implemented, - //so that's fine too). - /* - std::shared_ptr m_ScriptExtender { nullptr }; - std::shared_ptr m_DataArchives { nullptr }; - std::shared_ptr m_BSAInvalidation { nullptr }; - std::shared_ptr m_SaveGameInfo { nullptr }; - std::shared_ptr m_LocalSavegames { nullptr }; - std::shared_ptr m_GamePlugins { nullptr }; - std::shared_ptr m_UnmanagedMods { nullptr };*/ - - template - void registerFeature(T *type) { - m_FeatureList[std::type_index(typeid(T))] = type; - } - -protected: - - QString m_GamePath; - QString m_MyGamesPath; - QString m_GameVariant; - MOBase::IOrganizer *m_Organizer; - - std::map m_FeatureList; - -}; - -#endif // GAMEGAMEBRYO_H +#ifndef GAMEGAMEBRYO_H +#define GAMEGAMEBRYO_H + +#include "iplugingame.h" + +class BSAInvalidation; +class DataArchives; +class LocalSavegames; +class SaveGameInfo; +class BSAInvalidation; +class LocalSavegames; +class ScriptExtender; +class GamePlugins; +class UnmanagedMods; + +#include +#include +#include +#include +#include +#include +#include + +class GameGamebryo : public MOBase::IPluginGame, + public MOBase::IPluginFileMapper +{ + Q_OBJECT + Q_INTERFACES(MOBase::IPlugin MOBase::IPluginGame MOBase::IPluginFileMapper) + + friend class GamebryoScriptExtender; + friend class GamebryoSaveGameInfo; + friend class GamebryoSaveGameInfoWidget; + +public: + + GameGamebryo(); + + virtual bool init(MOBase::IOrganizer *moInfo) override; + +public: // IPluginGame interface + + //getName + //initializeProfile + //savegameExtension + //savegameSEExtension + virtual bool isInstalled() const override; + virtual QIcon gameIcon() const override; + virtual QDir gameDirectory() const override; + virtual QDir dataDirectory() const override; + virtual void setGamePath(const QString &path) override; + virtual QDir documentsDirectory() const override; + virtual QDir savesDirectory() const override; + //executables + //steamAPPId + //primaryPlugins + virtual QStringList gameVariants() const override; + virtual void setGameVariant(const QString &variant) override; + virtual QString binaryName() const override; + //gameShortName + virtual QStringList primarySources() const override; + virtual QStringList validShortNames() const override; + //iniFiles + //DLCPlugins + virtual QStringList CCPlugins() const override; + virtual LoadOrderMechanism loadOrderMechanism() const override; + virtual SortMechanism sortMechanism() const override; + //nexusModOrganizerID + //nexusGameID + virtual bool looksValid(QDir const &) const override; + virtual QString gameVersion() const override; + virtual QString getLauncherName() const override; + +public: // IPluginFileMapper interface + + virtual MappingType mappings() const; + +protected: + + QFileInfo findInGameFolder(const QString &relativePath) const; + QString myGamesPath() const; + QString selectedVariant() const; + QString getVersion(QString const &program) const; + WORD getArch(QString const &program) const; + + static QString localAppFolder(); + //Arguably this shouldn't really be here but every gamebryo program seems to + //use it + static QString getLootPath(); + + //This function is not terribly well named as it copies exactly where it's told + //to, irrespective of whether it's in the profile... + static void copyToProfile(const QString &sourcePath, + const QDir &destinationDirectory, + const QString &sourceFileName); + + static void copyToProfile(const QString &sourcePath, + const QDir &destinationDirectory, + const QString &sourceFileName, + const QString &destinationFileName); + + virtual QString identifyGamePath() const; + + static std::unique_ptr getRegValue(HKEY key, LPCWSTR path, LPCWSTR value, DWORD flags, LPDWORD type); + + static QString findInRegistry(HKEY baseKey, LPCWSTR path, LPCWSTR value); + + static QString getKnownFolderPath(REFKNOWNFOLDERID folderId, bool useDefault); + + static QString getSpecialPath(const QString &name); + + static QString determineMyGamesPath(const QString &gameName); + +protected: + + std::map featureList() const; + + //These should be implemented by anything that uses gamebryo (I think) + //(and if they don't, it'll be a null pointer and won't look implemented, + //so that's fine too). + /* + std::shared_ptr m_ScriptExtender { nullptr }; + std::shared_ptr m_DataArchives { nullptr }; + std::shared_ptr m_BSAInvalidation { nullptr }; + std::shared_ptr m_SaveGameInfo { nullptr }; + std::shared_ptr m_LocalSavegames { nullptr }; + std::shared_ptr m_GamePlugins { nullptr }; + std::shared_ptr m_UnmanagedMods { nullptr };*/ + + template + void registerFeature(T *type) { + m_FeatureList[std::type_index(typeid(T))] = type; + } + +protected: + + QString m_GamePath; + QString m_MyGamesPath; + QString m_GameVariant; + MOBase::IOrganizer *m_Organizer; + + std::map m_FeatureList; + +}; + +#endif // GAMEGAMEBRYO_H From 4fd8aa590cf83e5c4e07b31e774c000c02e0c0c0 Mon Sep 17 00:00:00 2001 From: Silarn Date: Mon, 1 Oct 2018 00:10:27 -0500 Subject: [PATCH 0639/1544] [game_fallout3] Add 'creation' game lib for creation engine changes, eliminate duplicate plugin code --- src/games/fallout3/src/CMakeLists.txt | 4 +-- src/games/fallout3/src/game_fallout3_en.ts | 36 +++++++++++----------- 2 files changed, 20 insertions(+), 20 deletions(-) diff --git a/src/games/fallout3/src/CMakeLists.txt b/src/games/fallout3/src/CMakeLists.txt index faeaa98f..de7f7d7b 100644 --- a/src/games/fallout3/src/CMakeLists.txt +++ b/src/games/fallout3/src/CMakeLists.txt @@ -19,7 +19,7 @@ GET_FILENAME_COMPONENT(${default_project_path} ${default_project_path} REALPATH) SET(project_path "${default_project_path}" CACHE PATH "path to the other mo projects") FIND_PACKAGE(Qt5LinguistTools) -SET(translation_sources ${CMAKE_SOURCE_DIR}/src ${project_path}/game_gamebryo/src) +SET(translation_sources ${CMAKE_SOURCE_DIR}/src ${project_path}/game_gamebryo/src/gamebryo) QT5_CREATE_TRANSLATION(${PROJ_NAME}_translations_qm ${translation_sources} ${CMAKE_SOURCE_DIR}/src/${PROJ_NAME}_en.ts) SET(Boost_USE_STATIC_LIBS ON) @@ -35,7 +35,7 @@ SET(lib_path "${project_path}/../../install/libs") INCLUDE_DIRECTORIES(${project_path}/uibase/src ${project_path}/game_features/src - ${project_path}/game_gamebryo/src) + ${project_path}/game_gamebryo/src/gamebryo) LINK_DIRECTORIES(${project_path}/uibase/build/src ${lib_path} ${LZ4_ROOT}/dll) diff --git a/src/games/fallout3/src/game_fallout3_en.ts b/src/games/fallout3/src/game_fallout3_en.ts index e0610157..4b045a69 100644 --- a/src/games/fallout3/src/game_fallout3_en.ts +++ b/src/games/fallout3/src/game_fallout3_en.ts @@ -12,48 +12,48 @@ GamebryoSaveGameInfoWidget - + Save # - + Character - + Level - + Location - + Date - + Has Script Extender Data - + Missing ESPs - - + + None - + Missing ESLs @@ -61,42 +61,42 @@ QObject - + failed to deactivate BSA invalidation in "%1" (errorcode %2) - + failed to activate BSA invalidation in "%1" (errorcode %2) - + failed to set archive key (errorcode %1) - + Some of your plugins have invalid names! These plugins can not be loaded by the game. Please see mo_interface.log for a list of affected plugins and rename them. - + failed to open %1 - + wrong file format - expected %1 got %2 - + failed to query registry path (preflight): %1 - + failed to query registry path (read): %1 From ba02e0d031f6a098407b4ffa84182b7c1aa4f226 Mon Sep 17 00:00:00 2001 From: Silarn Date: Mon, 1 Oct 2018 00:10:29 -0500 Subject: [PATCH 0640/1544] [game_fallout76] Add 'creation' game lib for creation engine changes, eliminate duplicate plugin code --- src/games/fallout76/src/CMakeLists.txt | 8 +- .../fallout76/src/fallout4gameplugins.cpp | 183 ------------------ src/games/fallout76/src/fallout4gameplugins.h | 26 --- src/games/fallout76/src/game_fallout4_en.ts | 40 ++-- src/games/fallout76/src/gamefallout4.cpp | 5 +- 5 files changed, 27 insertions(+), 235 deletions(-) delete mode 100644 src/games/fallout76/src/fallout4gameplugins.cpp delete mode 100644 src/games/fallout76/src/fallout4gameplugins.h diff --git a/src/games/fallout76/src/CMakeLists.txt b/src/games/fallout76/src/CMakeLists.txt index c9138d98..b5897bb7 100644 --- a/src/games/fallout76/src/CMakeLists.txt +++ b/src/games/fallout76/src/CMakeLists.txt @@ -23,7 +23,7 @@ GET_FILENAME_COMPONENT(${default_project_path} ${default_project_path} REALPATH) SET(project_path "${default_project_path}" CACHE PATH "path to the other mo projects") FIND_PACKAGE(Qt5LinguistTools) -SET(translation_sources ${CMAKE_SOURCE_DIR}/src ${project_path}/game_gamebryo/src) +SET(translation_sources ${CMAKE_SOURCE_DIR}/src ${project_path}/game_gamebryo/src/gamebryo ${project_path}/game_gamebryo/src/creation) QT5_CREATE_TRANSLATION(${PROJ_NAME}_translations_qm ${translation_sources} ${CMAKE_SOURCE_DIR}/src/${PROJ_NAME}_en.ts) SET(Boost_USE_STATIC_LIBS ON) @@ -39,7 +39,8 @@ SET(lib_path "${project_path}/../../install/libs") INCLUDE_DIRECTORIES(${project_path}/uibase/src ${project_path}/game_features/src - ${project_path}/game_gamebryo/src) + ${project_path}/game_gamebryo/src/gamebryo + ${project_path}/game_gamebryo/src/creation) LINK_DIRECTORIES(${project_path}/uibase/build/src ${lib_path} ${LZ4_ROOT}/dll) @@ -53,7 +54,8 @@ TARGET_LINK_LIBRARIES(${PROJ_NAME} uibase Version liblz4 - game_gamebryo) + game_gamebryo + game_creation) IF (MSVC) SET_TARGET_PROPERTIES(${PROJ_NAME} PROPERTIES COMPILE_FLAGS "/std:c++latest") diff --git a/src/games/fallout76/src/fallout4gameplugins.cpp b/src/games/fallout76/src/fallout4gameplugins.cpp deleted file mode 100644 index bea0b8fb..00000000 --- a/src/games/fallout76/src/fallout4gameplugins.cpp +++ /dev/null @@ -1,183 +0,0 @@ -#include "fallout4gameplugins.h" -#include -#include -#include -#include -#include - -#include -#include -#include -#include - - -using MOBase::IPluginGame; -using MOBase::IPluginList; -using MOBase::IOrganizer; -using MOBase::SafeWriteFile; -using MOBase::reportError; - -Fallout4GamePlugins::Fallout4GamePlugins(IOrganizer *organizer) - : GamebryoGamePlugins(organizer) -{ -} - -void Fallout4GamePlugins::getLoadOrder(QStringList &loadOrder) { - QString loadOrderPath = - organizer()->profile()->absolutePath() + "/loadorder.txt"; - QString pluginsPath = organizer()->profile()->absolutePath() + "/plugins.txt"; - - bool loadOrderIsNew = !m_LastRead.isValid() || - !QFileInfo(loadOrderPath).exists() || - QFileInfo(loadOrderPath).lastModified() > m_LastRead; - bool pluginsIsNew = !m_LastRead.isValid() || - QFileInfo(pluginsPath).lastModified() > m_LastRead; - - if (loadOrderIsNew || !pluginsIsNew) { - loadOrder = readLoadOrderList(m_Organizer->pluginList(), loadOrderPath); - } - else { - loadOrder = readPluginList(m_Organizer->pluginList()); - } -} - -void Fallout4GamePlugins::writePluginList(const IPluginList *pluginList, - const QString &filePath) { - SafeWriteFile file(filePath); - - QTextCodec *textCodec = localCodec(); - - file->resize(0); - - file->write(textCodec->fromUnicode( - "# This file was automatically generated by Mod Organizer.\r\n")); - - bool invalidFileNames = false; - int writtenCount = 0; - - QStringList plugins = pluginList->pluginNames(); - std::sort(plugins.begin(), plugins.end(), - [pluginList](const QString &lhs, const QString &rhs) { - return pluginList->priority(lhs) < pluginList->priority(rhs); - }); - - QStringList PrimaryPlugins = organizer()->managedGame()->primaryPlugins(); - QSet ManagedMods = PrimaryPlugins.toSet().subtract(organizer()->managedGame()->DLCPlugins().toSet()); - PrimaryPlugins.append(ManagedMods.toList()); - - //TODO: do not write plugins in OFFICIAL_FILES container - for (const QString &pluginName : plugins) { - if (!PrimaryPlugins.contains(pluginName,Qt::CaseInsensitive)) { - if (pluginList->state(pluginName) == IPluginList::STATE_ACTIVE) { - if (!textCodec->canEncode(pluginName)) { - invalidFileNames = true; - qCritical("invalid plugin name %s", qPrintable(pluginName)); - } - else - { - file->write("*"); - file->write(textCodec->fromUnicode(pluginName)); - - } - file->write("\r\n"); - ++writtenCount; - } - else - { - if (!textCodec->canEncode(pluginName)) { - invalidFileNames = true; - qCritical("invalid plugin name %s", qPrintable(pluginName)); - } - else - { - file->write(textCodec->fromUnicode(pluginName)); - } - file->write("\r\n"); - ++writtenCount; - } - } - } - - if (invalidFileNames) { - reportError(QObject::tr("Some of your plugins have invalid names! These " - "plugins can not be loaded by the game. Please see " - "mo_interface.log for a list of affected plugins " - "and rename them.")); - } - - if (file.commitIfDifferent(m_LastSaveHash[filePath])) { - qDebug("%s saved", qPrintable(QDir::toNativeSeparators(filePath))); - } -} - -QStringList Fallout4GamePlugins::readPluginList(MOBase::IPluginList *pluginList) -{ - QStringList plugins = pluginList->pluginNames(); - QStringList primaryPlugins = organizer()->managedGame()->primaryPlugins(); - QStringList loadOrder(primaryPlugins); - - for (const QString &pluginName : loadOrder) { - if (pluginList->state(pluginName) != IPluginList::STATE_MISSING) { - pluginList->setState(pluginName, IPluginList::STATE_ACTIVE); - } - } - - QString filePath = organizer()->profile()->absolutePath() + "/plugins.txt"; - QFile file(filePath); - if (!file.open(QIODevice::ReadOnly)) { - qWarning("%s not found", qPrintable(filePath)); - return loadOrder; - } - ON_BLOCK_EXIT([&]() { file.close(); }); - - if (file.size() == 0) { - // MO stores at least a header in the file. if it's completely empty the - // file is broken - qWarning("%s empty", qPrintable(filePath)); - return loadOrder; - } - - while (!file.atEnd()) { - QByteArray line = file.readLine(); - QString pluginName; - if ((line.size() > 0) && (line.at(0) != '#')) { - pluginName = localCodec()->toUnicode(line.trimmed().constData()); - } - if (!primaryPlugins.contains(pluginName, Qt::CaseInsensitive)) { - if (pluginName.startsWith('*')) { - pluginName.remove(0, 1); - if (pluginName.size() > 0) { - pluginList->setState(pluginName, IPluginList::STATE_ACTIVE); - plugins.removeAll(pluginName); - if (!loadOrder.contains(pluginName, Qt::CaseInsensitive)) { - loadOrder.append(pluginName); - } - } - } - else - { - if (pluginName.size() > 0) { - pluginList->setState(pluginName, IPluginList::STATE_INACTIVE); - plugins.removeAll(pluginName); - if (!loadOrder.contains(pluginName, Qt::CaseInsensitive)) { - loadOrder.append(pluginName); - } - } - } - } - else - { - pluginName.remove(0, 1); - plugins.removeAll(pluginName); - } - } - - file.close(); - - // we removed each plugin found in the file, so what's left are inactive mods - for (const QString &pluginName : plugins) { - pluginList->setState(pluginName, IPluginList::STATE_INACTIVE); - } - - return loadOrder; -} diff --git a/src/games/fallout76/src/fallout4gameplugins.h b/src/games/fallout76/src/fallout4gameplugins.h deleted file mode 100644 index 0b591b8b..00000000 --- a/src/games/fallout76/src/fallout4gameplugins.h +++ /dev/null @@ -1,26 +0,0 @@ -#ifndef FALLOUT4GAMEPLUGINS_H -#define FALLOUT4GAMEPLUGINS_H - - -#include -#include -#include -#include - - -class Fallout4GamePlugins : public GamebryoGamePlugins -{ -public: - Fallout4GamePlugins(MOBase::IOrganizer *organizer); - -protected: - virtual void writePluginList(const MOBase::IPluginList *pluginList, - const QString &filePath) override; - virtual QStringList readPluginList(MOBase::IPluginList *pluginList) override; - virtual void getLoadOrder(QStringList &loadOrder) override; - -private: - std::map m_LastSaveHash; -}; - -#endif // FALLOUT4GAMEPLUGINS_H diff --git a/src/games/fallout76/src/game_fallout4_en.ts b/src/games/fallout76/src/game_fallout4_en.ts index 6bbc83d4..636a61b9 100644 --- a/src/games/fallout76/src/game_fallout4_en.ts +++ b/src/games/fallout76/src/game_fallout4_en.ts @@ -4,7 +4,7 @@ GameFallout4 - + Adds support for the game Fallout 4. Splash by %1 @@ -13,48 +13,48 @@ Splash by %1 GamebryoSaveGameInfoWidget - + Save # - + Character - + Level - + Location - + Date - + Has Script Extender Data - + Missing ESPs - - + + None - + Missing ESLs @@ -62,43 +62,43 @@ Splash by %1 QObject - - + + Some of your plugins have invalid names! These plugins can not be loaded by the game. Please see mo_interface.log for a list of affected plugins and rename them. - + failed to deactivate BSA invalidation in "%1" (errorcode %2) - + failed to activate BSA invalidation in "%1" (errorcode %2) - + failed to set archive key (errorcode %1) - + failed to open %1 - + wrong file format - expected %1 got %2 - + failed to query registry path (preflight): %1 - + failed to query registry path (read): %1 diff --git a/src/games/fallout76/src/gamefallout4.cpp b/src/games/fallout76/src/gamefallout4.cpp index 3c4c5922..3bd7b6bf 100644 --- a/src/games/fallout76/src/gamefallout4.cpp +++ b/src/games/fallout76/src/gamefallout4.cpp @@ -3,13 +3,12 @@ #include "fallout4dataarchives.h" #include "fallout4scriptextender.h" #include "fallout4savegameinfo.h" -#include "fallout4gameplugins.h" #include "fallout4unmanagedmods.h" #include #include #include -#include +#include #include "versioninfo.h" #include @@ -40,7 +39,7 @@ bool GameFallout4::init(IOrganizer *moInfo) registerFeature(new Fallout4DataArchives(myGamesPath())); registerFeature(new GamebryoLocalSavegames(myGamesPath(), "Fallout4.ini")); registerFeature(new Fallout4SaveGameInfo(this)); - registerFeature(new Fallout4GamePlugins(moInfo)); + registerFeature(new CreationGamePlugins(moInfo)); registerFeature(new Fallout4UnmangedMods(this)); return true; From e97d69c1b38703cf7f9e6619dd04c0320a7ed175 Mon Sep 17 00:00:00 2001 From: Silarn Date: Mon, 1 Oct 2018 00:10:29 -0500 Subject: [PATCH 0641/1544] [game_fallout4] Add 'creation' game lib for creation engine changes, eliminate duplicate plugin code --- src/games/fallout4/src/CMakeLists.txt | 8 +- .../fallout4/src/fallout4gameplugins.cpp | 183 ------------------ src/games/fallout4/src/fallout4gameplugins.h | 26 --- src/games/fallout4/src/game_fallout4_en.ts | 40 ++-- src/games/fallout4/src/gamefallout4.cpp | 5 +- 5 files changed, 27 insertions(+), 235 deletions(-) delete mode 100644 src/games/fallout4/src/fallout4gameplugins.cpp delete mode 100644 src/games/fallout4/src/fallout4gameplugins.h diff --git a/src/games/fallout4/src/CMakeLists.txt b/src/games/fallout4/src/CMakeLists.txt index c9138d98..b5897bb7 100644 --- a/src/games/fallout4/src/CMakeLists.txt +++ b/src/games/fallout4/src/CMakeLists.txt @@ -23,7 +23,7 @@ GET_FILENAME_COMPONENT(${default_project_path} ${default_project_path} REALPATH) SET(project_path "${default_project_path}" CACHE PATH "path to the other mo projects") FIND_PACKAGE(Qt5LinguistTools) -SET(translation_sources ${CMAKE_SOURCE_DIR}/src ${project_path}/game_gamebryo/src) +SET(translation_sources ${CMAKE_SOURCE_DIR}/src ${project_path}/game_gamebryo/src/gamebryo ${project_path}/game_gamebryo/src/creation) QT5_CREATE_TRANSLATION(${PROJ_NAME}_translations_qm ${translation_sources} ${CMAKE_SOURCE_DIR}/src/${PROJ_NAME}_en.ts) SET(Boost_USE_STATIC_LIBS ON) @@ -39,7 +39,8 @@ SET(lib_path "${project_path}/../../install/libs") INCLUDE_DIRECTORIES(${project_path}/uibase/src ${project_path}/game_features/src - ${project_path}/game_gamebryo/src) + ${project_path}/game_gamebryo/src/gamebryo + ${project_path}/game_gamebryo/src/creation) LINK_DIRECTORIES(${project_path}/uibase/build/src ${lib_path} ${LZ4_ROOT}/dll) @@ -53,7 +54,8 @@ TARGET_LINK_LIBRARIES(${PROJ_NAME} uibase Version liblz4 - game_gamebryo) + game_gamebryo + game_creation) IF (MSVC) SET_TARGET_PROPERTIES(${PROJ_NAME} PROPERTIES COMPILE_FLAGS "/std:c++latest") diff --git a/src/games/fallout4/src/fallout4gameplugins.cpp b/src/games/fallout4/src/fallout4gameplugins.cpp deleted file mode 100644 index bea0b8fb..00000000 --- a/src/games/fallout4/src/fallout4gameplugins.cpp +++ /dev/null @@ -1,183 +0,0 @@ -#include "fallout4gameplugins.h" -#include -#include -#include -#include -#include - -#include -#include -#include -#include - - -using MOBase::IPluginGame; -using MOBase::IPluginList; -using MOBase::IOrganizer; -using MOBase::SafeWriteFile; -using MOBase::reportError; - -Fallout4GamePlugins::Fallout4GamePlugins(IOrganizer *organizer) - : GamebryoGamePlugins(organizer) -{ -} - -void Fallout4GamePlugins::getLoadOrder(QStringList &loadOrder) { - QString loadOrderPath = - organizer()->profile()->absolutePath() + "/loadorder.txt"; - QString pluginsPath = organizer()->profile()->absolutePath() + "/plugins.txt"; - - bool loadOrderIsNew = !m_LastRead.isValid() || - !QFileInfo(loadOrderPath).exists() || - QFileInfo(loadOrderPath).lastModified() > m_LastRead; - bool pluginsIsNew = !m_LastRead.isValid() || - QFileInfo(pluginsPath).lastModified() > m_LastRead; - - if (loadOrderIsNew || !pluginsIsNew) { - loadOrder = readLoadOrderList(m_Organizer->pluginList(), loadOrderPath); - } - else { - loadOrder = readPluginList(m_Organizer->pluginList()); - } -} - -void Fallout4GamePlugins::writePluginList(const IPluginList *pluginList, - const QString &filePath) { - SafeWriteFile file(filePath); - - QTextCodec *textCodec = localCodec(); - - file->resize(0); - - file->write(textCodec->fromUnicode( - "# This file was automatically generated by Mod Organizer.\r\n")); - - bool invalidFileNames = false; - int writtenCount = 0; - - QStringList plugins = pluginList->pluginNames(); - std::sort(plugins.begin(), plugins.end(), - [pluginList](const QString &lhs, const QString &rhs) { - return pluginList->priority(lhs) < pluginList->priority(rhs); - }); - - QStringList PrimaryPlugins = organizer()->managedGame()->primaryPlugins(); - QSet ManagedMods = PrimaryPlugins.toSet().subtract(organizer()->managedGame()->DLCPlugins().toSet()); - PrimaryPlugins.append(ManagedMods.toList()); - - //TODO: do not write plugins in OFFICIAL_FILES container - for (const QString &pluginName : plugins) { - if (!PrimaryPlugins.contains(pluginName,Qt::CaseInsensitive)) { - if (pluginList->state(pluginName) == IPluginList::STATE_ACTIVE) { - if (!textCodec->canEncode(pluginName)) { - invalidFileNames = true; - qCritical("invalid plugin name %s", qPrintable(pluginName)); - } - else - { - file->write("*"); - file->write(textCodec->fromUnicode(pluginName)); - - } - file->write("\r\n"); - ++writtenCount; - } - else - { - if (!textCodec->canEncode(pluginName)) { - invalidFileNames = true; - qCritical("invalid plugin name %s", qPrintable(pluginName)); - } - else - { - file->write(textCodec->fromUnicode(pluginName)); - } - file->write("\r\n"); - ++writtenCount; - } - } - } - - if (invalidFileNames) { - reportError(QObject::tr("Some of your plugins have invalid names! These " - "plugins can not be loaded by the game. Please see " - "mo_interface.log for a list of affected plugins " - "and rename them.")); - } - - if (file.commitIfDifferent(m_LastSaveHash[filePath])) { - qDebug("%s saved", qPrintable(QDir::toNativeSeparators(filePath))); - } -} - -QStringList Fallout4GamePlugins::readPluginList(MOBase::IPluginList *pluginList) -{ - QStringList plugins = pluginList->pluginNames(); - QStringList primaryPlugins = organizer()->managedGame()->primaryPlugins(); - QStringList loadOrder(primaryPlugins); - - for (const QString &pluginName : loadOrder) { - if (pluginList->state(pluginName) != IPluginList::STATE_MISSING) { - pluginList->setState(pluginName, IPluginList::STATE_ACTIVE); - } - } - - QString filePath = organizer()->profile()->absolutePath() + "/plugins.txt"; - QFile file(filePath); - if (!file.open(QIODevice::ReadOnly)) { - qWarning("%s not found", qPrintable(filePath)); - return loadOrder; - } - ON_BLOCK_EXIT([&]() { file.close(); }); - - if (file.size() == 0) { - // MO stores at least a header in the file. if it's completely empty the - // file is broken - qWarning("%s empty", qPrintable(filePath)); - return loadOrder; - } - - while (!file.atEnd()) { - QByteArray line = file.readLine(); - QString pluginName; - if ((line.size() > 0) && (line.at(0) != '#')) { - pluginName = localCodec()->toUnicode(line.trimmed().constData()); - } - if (!primaryPlugins.contains(pluginName, Qt::CaseInsensitive)) { - if (pluginName.startsWith('*')) { - pluginName.remove(0, 1); - if (pluginName.size() > 0) { - pluginList->setState(pluginName, IPluginList::STATE_ACTIVE); - plugins.removeAll(pluginName); - if (!loadOrder.contains(pluginName, Qt::CaseInsensitive)) { - loadOrder.append(pluginName); - } - } - } - else - { - if (pluginName.size() > 0) { - pluginList->setState(pluginName, IPluginList::STATE_INACTIVE); - plugins.removeAll(pluginName); - if (!loadOrder.contains(pluginName, Qt::CaseInsensitive)) { - loadOrder.append(pluginName); - } - } - } - } - else - { - pluginName.remove(0, 1); - plugins.removeAll(pluginName); - } - } - - file.close(); - - // we removed each plugin found in the file, so what's left are inactive mods - for (const QString &pluginName : plugins) { - pluginList->setState(pluginName, IPluginList::STATE_INACTIVE); - } - - return loadOrder; -} diff --git a/src/games/fallout4/src/fallout4gameplugins.h b/src/games/fallout4/src/fallout4gameplugins.h deleted file mode 100644 index 0b591b8b..00000000 --- a/src/games/fallout4/src/fallout4gameplugins.h +++ /dev/null @@ -1,26 +0,0 @@ -#ifndef FALLOUT4GAMEPLUGINS_H -#define FALLOUT4GAMEPLUGINS_H - - -#include -#include -#include -#include - - -class Fallout4GamePlugins : public GamebryoGamePlugins -{ -public: - Fallout4GamePlugins(MOBase::IOrganizer *organizer); - -protected: - virtual void writePluginList(const MOBase::IPluginList *pluginList, - const QString &filePath) override; - virtual QStringList readPluginList(MOBase::IPluginList *pluginList) override; - virtual void getLoadOrder(QStringList &loadOrder) override; - -private: - std::map m_LastSaveHash; -}; - -#endif // FALLOUT4GAMEPLUGINS_H diff --git a/src/games/fallout4/src/game_fallout4_en.ts b/src/games/fallout4/src/game_fallout4_en.ts index 6bbc83d4..636a61b9 100644 --- a/src/games/fallout4/src/game_fallout4_en.ts +++ b/src/games/fallout4/src/game_fallout4_en.ts @@ -4,7 +4,7 @@ GameFallout4 - + Adds support for the game Fallout 4. Splash by %1 @@ -13,48 +13,48 @@ Splash by %1 GamebryoSaveGameInfoWidget - + Save # - + Character - + Level - + Location - + Date - + Has Script Extender Data - + Missing ESPs - - + + None - + Missing ESLs @@ -62,43 +62,43 @@ Splash by %1 QObject - - + + Some of your plugins have invalid names! These plugins can not be loaded by the game. Please see mo_interface.log for a list of affected plugins and rename them. - + failed to deactivate BSA invalidation in "%1" (errorcode %2) - + failed to activate BSA invalidation in "%1" (errorcode %2) - + failed to set archive key (errorcode %1) - + failed to open %1 - + wrong file format - expected %1 got %2 - + failed to query registry path (preflight): %1 - + failed to query registry path (read): %1 diff --git a/src/games/fallout4/src/gamefallout4.cpp b/src/games/fallout4/src/gamefallout4.cpp index 3c4c5922..3bd7b6bf 100644 --- a/src/games/fallout4/src/gamefallout4.cpp +++ b/src/games/fallout4/src/gamefallout4.cpp @@ -3,13 +3,12 @@ #include "fallout4dataarchives.h" #include "fallout4scriptextender.h" #include "fallout4savegameinfo.h" -#include "fallout4gameplugins.h" #include "fallout4unmanagedmods.h" #include #include #include -#include +#include #include "versioninfo.h" #include @@ -40,7 +39,7 @@ bool GameFallout4::init(IOrganizer *moInfo) registerFeature(new Fallout4DataArchives(myGamesPath())); registerFeature(new GamebryoLocalSavegames(myGamesPath(), "Fallout4.ini")); registerFeature(new Fallout4SaveGameInfo(this)); - registerFeature(new Fallout4GamePlugins(moInfo)); + registerFeature(new CreationGamePlugins(moInfo)); registerFeature(new Fallout4UnmangedMods(this)); return true; From 6782333691e487a159e4784061e0d395889f97e6 Mon Sep 17 00:00:00 2001 From: Silarn Date: Mon, 1 Oct 2018 00:10:30 -0500 Subject: [PATCH 0642/1544] [game_skyrimvr] Add 'creation' game lib for creation engine changes, eliminate duplicate plugin code --- src/games/skyrimvr/src/CMakeLists.txt | 6 +- src/games/skyrimvr/src/game_skyrimvr_en.ts | 40 ++-- src/games/skyrimvr/src/gameskyrimvr.cpp | 5 +- .../skyrimvr/src/skyrimvrgameplugins.cpp | 181 ------------------ src/games/skyrimvr/src/skyrimvrgameplugins.h | 26 --- 5 files changed, 26 insertions(+), 232 deletions(-) delete mode 100644 src/games/skyrimvr/src/skyrimvrgameplugins.cpp delete mode 100644 src/games/skyrimvr/src/skyrimvrgameplugins.h diff --git a/src/games/skyrimvr/src/CMakeLists.txt b/src/games/skyrimvr/src/CMakeLists.txt index e90ce67f..6281cdb9 100644 --- a/src/games/skyrimvr/src/CMakeLists.txt +++ b/src/games/skyrimvr/src/CMakeLists.txt @@ -19,7 +19,7 @@ GET_FILENAME_COMPONENT(${default_project_path} ${default_project_path} REALPATH) SET(project_path "${default_project_path}" CACHE PATH "path to the other mo projects") FIND_PACKAGE(Qt5LinguistTools) -SET(translation_sources ${CMAKE_SOURCE_DIR}/src ${project_path}/game_gamebryo/src) +SET(translation_sources ${CMAKE_SOURCE_DIR}/src ${project_path}/game_gamebryo/src/gamebryo ${project_path}/game_gamebryo/src/creation) QT5_CREATE_TRANSLATION(${PROJ_NAME}_translations_qm ${translation_sources} ${CMAKE_SOURCE_DIR}/src/${PROJ_NAME}_en.ts) SET(Boost_USE_STATIC_LIBS ON) @@ -35,7 +35,8 @@ SET(lib_path "${project_path}/../../install/libs") INCLUDE_DIRECTORIES(${project_path}/uibase/src ${project_path}/game_features/src - ${project_path}/game_gamebryo/src) + ${project_path}/game_gamebryo/src/gamebryo + ${project_path}/game_gamebryo/src/creation) LINK_DIRECTORIES(${project_path}/uibase/build/src ${lib_path} ${LZ4_ROOT}/dll) @@ -49,6 +50,7 @@ TARGET_LINK_LIBRARIES(${PROJ_NAME} DbgHelp uibase game_gamebryo + game_creation liblz4 version) diff --git a/src/games/skyrimvr/src/game_skyrimvr_en.ts b/src/games/skyrimvr/src/game_skyrimvr_en.ts index 79ff361e..5c1f7ad8 100644 --- a/src/games/skyrimvr/src/game_skyrimvr_en.ts +++ b/src/games/skyrimvr/src/game_skyrimvr_en.ts @@ -4,7 +4,7 @@ GameSkyrimVR - + Adds support for the game Skyrim VR. @@ -12,48 +12,48 @@ GamebryoSaveGameInfoWidget - + Save # - + Character - + Level - + Location - + Date - + Has Script Extender Data - + Missing ESPs - - + + None - + Missing ESLs @@ -61,43 +61,43 @@ QObject - + failed to query registry path (preflight): %1 - + failed to query registry path (read): %1 - - + + Some of your plugins have invalid names! These plugins can not be loaded by the game. Please see mo_interface.log for a list of affected plugins and rename them. - + failed to deactivate BSA invalidation in "%1" (errorcode %2) - + failed to activate BSA invalidation in "%1" (errorcode %2) - + failed to set archive key (errorcode %1) - + failed to open %1 - + wrong file format - expected %1 got %2 diff --git a/src/games/skyrimvr/src/gameskyrimvr.cpp b/src/games/skyrimvr/src/gameskyrimvr.cpp index 1589650a..3c213b26 100644 --- a/src/games/skyrimvr/src/gameskyrimvr.cpp +++ b/src/games/skyrimvr/src/gameskyrimvr.cpp @@ -3,13 +3,12 @@ #include "skyrimvrdataarchives.h" #include "skyrimvrscriptextender.h" #include "skyrimvrsavegameinfo.h" -#include "skyrimvrgameplugins.h" #include "skyrimvrunmanagedmods.h" #include #include #include -#include +#include #include "versioninfo.h" #include @@ -73,7 +72,7 @@ bool GameSkyrimVR::init(IOrganizer *moInfo) registerFeature(new SkyrimVRDataArchives(myGamesPath())); registerFeature(new GamebryoLocalSavegames(myGamesPath(), "SkyrimVR.ini")); registerFeature(new SkyrimVRSaveGameInfo(this)); - registerFeature(new SkyrimVRGamePlugins(moInfo)); + registerFeature(new CreationGamePlugins(moInfo)); registerFeature(new SkyrimVRUnmangedMods(this)); return true; diff --git a/src/games/skyrimvr/src/skyrimvrgameplugins.cpp b/src/games/skyrimvr/src/skyrimvrgameplugins.cpp deleted file mode 100644 index e6818ed1..00000000 --- a/src/games/skyrimvr/src/skyrimvrgameplugins.cpp +++ /dev/null @@ -1,181 +0,0 @@ -#include "skyrimvrgameplugins.h" -#include -#include -#include -#include -#include - -#include -#include -#include - - -using MOBase::IPluginGame; -using MOBase::IPluginList; -using MOBase::IOrganizer; -using MOBase::SafeWriteFile; -using MOBase::reportError; - -SkyrimVRGamePlugins::SkyrimVRGamePlugins(IOrganizer *organizer) - : GamebryoGamePlugins(organizer) -{ -} - -void SkyrimVRGamePlugins::getLoadOrder(QStringList &loadOrder) { - QString loadOrderPath = - organizer()->profile()->absolutePath() + "/loadorder.txt"; - QString pluginsPath = organizer()->profile()->absolutePath() + "/plugins.txt"; - - bool loadOrderIsNew = !m_LastRead.isValid() || - !QFileInfo(loadOrderPath).exists() || - QFileInfo(loadOrderPath).lastModified() > m_LastRead; - bool pluginsIsNew = !m_LastRead.isValid() || - QFileInfo(pluginsPath).lastModified() > m_LastRead; - - if (loadOrderIsNew || !pluginsIsNew) { - loadOrder = readLoadOrderList(m_Organizer->pluginList(), loadOrderPath); - } - else { - loadOrder = readPluginList(m_Organizer->pluginList()); - } -} - -void SkyrimVRGamePlugins::writePluginList(const IPluginList *pluginList, - const QString &filePath) { - SafeWriteFile file(filePath); - - QTextCodec *textCodec = localCodec(); - - file->resize(0); - - file->write(textCodec->fromUnicode( - "# This file was automatically generated by Mod Organizer.\r\n")); - - bool invalidFileNames = false; - int writtenCount = 0; - - QStringList plugins = pluginList->pluginNames(); - std::sort(plugins.begin(), plugins.end(), - [pluginList](const QString &lhs, const QString &rhs) { - return pluginList->priority(lhs) < pluginList->priority(rhs); - }); - - QStringList PrimaryPlugins = organizer()->managedGame()->primaryPlugins(); - - //TODO: do not write plugins in OFFICIAL_FILES container - for (const QString &pluginName : plugins) { - if (!PrimaryPlugins.contains(pluginName,Qt::CaseInsensitive)) { - if (pluginList->state(pluginName) == IPluginList::STATE_ACTIVE) { - if (!textCodec->canEncode(pluginName)) { - invalidFileNames = true; - qCritical("invalid plugin name %s", qPrintable(pluginName)); - } - else - { - file->write("*"); - file->write(textCodec->fromUnicode(pluginName)); - - } - file->write("\r\n"); - ++writtenCount; - } - else - { - if (!textCodec->canEncode(pluginName)) { - invalidFileNames = true; - qCritical("invalid plugin name %s", qPrintable(pluginName)); - } - else - { - file->write(textCodec->fromUnicode(pluginName)); - } - file->write("\r\n"); - ++writtenCount; - } - } - } - - if (invalidFileNames) { - reportError(QObject::tr("Some of your plugins have invalid names! These " - "plugins can not be loaded by the game. Please see " - "mo_interface.log for a list of affected plugins " - "and rename them.")); - } - - if (file.commitIfDifferent(m_LastSaveHash[filePath])) { - qDebug("%s saved", qPrintable(QDir::toNativeSeparators(filePath))); - } -} - -QStringList SkyrimVRGamePlugins::readPluginList(MOBase::IPluginList *pluginList) -{ - QStringList plugins = pluginList->pluginNames(); - QStringList primaryPlugins = organizer()->managedGame()->primaryPlugins(); - QStringList loadOrder(primaryPlugins); - - for (const QString &pluginName : loadOrder) { - if (pluginList->state(pluginName) != IPluginList::STATE_MISSING) { - pluginList->setState(pluginName, IPluginList::STATE_ACTIVE); - } - } - - - QString filePath = organizer()->profile()->absolutePath() + "/plugins.txt"; - QFile file(filePath); - if (!file.open(QIODevice::ReadOnly)) { - qWarning("%s not found", qPrintable(filePath)); - return loadOrder; - } - ON_BLOCK_EXIT([&]() { file.close(); }); - - if (file.size() == 0) { - // MO stores at least a header in the file. if it's completely empty the - // file is broken - qWarning("%s empty", qPrintable(filePath)); - return loadOrder; - } - - while (!file.atEnd()) { - QByteArray line = file.readLine(); - QString pluginName; - if ((line.size() > 0) && (line.at(0) != '#')) { - pluginName = localCodec()->toUnicode(line.trimmed().constData()); - } - if (!primaryPlugins.contains(pluginName, Qt::CaseInsensitive)) { - if (pluginName.startsWith('*')) { - pluginName.remove(0, 1); - if (pluginName.size() > 0) { - pluginList->setState(pluginName, IPluginList::STATE_ACTIVE); - plugins.removeAll(pluginName); - if (!loadOrder.contains(pluginName, Qt::CaseInsensitive)) { - loadOrder.append(pluginName); - } - } - } - else - { - if (pluginName.size() > 0) { - pluginList->setState(pluginName, IPluginList::STATE_INACTIVE); - plugins.removeAll(pluginName); - if (!loadOrder.contains(pluginName, Qt::CaseInsensitive)) { - loadOrder.append(pluginName); - } - } - } - } - else - { - pluginName.remove(0, 1); - plugins.removeAll(pluginName); - } - } - - file.close(); - - // we removed each plugin found in the file, so what's left are inactive mods - for (const QString &pluginName : plugins) { - pluginList->setState(pluginName, IPluginList::STATE_INACTIVE); - } - - return loadOrder; -} diff --git a/src/games/skyrimvr/src/skyrimvrgameplugins.h b/src/games/skyrimvr/src/skyrimvrgameplugins.h deleted file mode 100644 index 280ec37f..00000000 --- a/src/games/skyrimvr/src/skyrimvrgameplugins.h +++ /dev/null @@ -1,26 +0,0 @@ -#ifndef _SKYRIMVRGAMEPLUGINS_H -#define _SKYRIMVRGAMEPLUGINS_H - - -#include -#include -#include -#include - - -class SkyrimVRGamePlugins : public GamebryoGamePlugins -{ -public: - SkyrimVRGamePlugins(MOBase::IOrganizer *organizer); - -protected: - virtual void writePluginList(const MOBase::IPluginList *pluginList, - const QString &filePath) override; - virtual QStringList readPluginList(MOBase::IPluginList *pluginList) override; - virtual void getLoadOrder(QStringList &loadOrder) override; - -private: - std::map m_LastSaveHash; -}; - -#endif // _SKYRIMVRGAMEPLUGINS_H From 51b81bbc6da932cdbc842e72d709d6a506aa1890 Mon Sep 17 00:00:00 2001 From: Silarn Date: Mon, 1 Oct 2018 00:10:32 -0500 Subject: [PATCH 0643/1544] [game_skyrim] Add 'creation' game lib for creation engine changes, eliminate duplicate plugin code --- src/games/skyrim/src/CMakeLists.txt | 4 +-- src/games/skyrim/src/game_skyrim_en.ts | 36 +++++++++++++------------- 2 files changed, 20 insertions(+), 20 deletions(-) diff --git a/src/games/skyrim/src/CMakeLists.txt b/src/games/skyrim/src/CMakeLists.txt index e9369a1b..b4228951 100644 --- a/src/games/skyrim/src/CMakeLists.txt +++ b/src/games/skyrim/src/CMakeLists.txt @@ -19,7 +19,7 @@ GET_FILENAME_COMPONENT(${default_project_path} ${default_project_path} REALPATH) SET(project_path "${default_project_path}" CACHE PATH "path to the other mo projects") FIND_PACKAGE(Qt5LinguistTools) -SET(translation_sources ${CMAKE_SOURCE_DIR}/src ${project_path}/game_gamebryo/src) +SET(translation_sources ${CMAKE_SOURCE_DIR}/src ${project_path}/game_gamebryo/src/gamebryo) QT5_CREATE_TRANSLATION(${PROJ_NAME}_translations_qm ${translation_sources} ${CMAKE_SOURCE_DIR}/src/${PROJ_NAME}_en.ts) SET(Boost_USE_STATIC_LIBS ON) @@ -35,7 +35,7 @@ SET(lib_path "${project_path}/../../install/libs") INCLUDE_DIRECTORIES(${project_path}/uibase/src ${project_path}/game_features/src - ${project_path}/game_gamebryo/src) + ${project_path}/game_gamebryo/src/gamebryo) LINK_DIRECTORIES(${project_path}/uibase/build/src ${lib_path} ${LZ4_ROOT}/dll) diff --git a/src/games/skyrim/src/game_skyrim_en.ts b/src/games/skyrim/src/game_skyrim_en.ts index b50c0f0c..a83e9525 100644 --- a/src/games/skyrim/src/game_skyrim_en.ts +++ b/src/games/skyrim/src/game_skyrim_en.ts @@ -12,48 +12,48 @@ GamebryoSaveGameInfoWidget - + Save # - + Character - + Level - + Location - + Date - + Has Script Extender Data - + Missing ESPs - - + + None - + Missing ESLs @@ -61,42 +61,42 @@ QObject - + failed to deactivate BSA invalidation in "%1" (errorcode %2) - + failed to activate BSA invalidation in "%1" (errorcode %2) - + failed to set archive key (errorcode %1) - + Some of your plugins have invalid names! These plugins can not be loaded by the game. Please see mo_interface.log for a list of affected plugins and rename them. - + failed to open %1 - + wrong file format - expected %1 got %2 - + failed to query registry path (preflight): %1 - + failed to query registry path (read): %1 From 08b6a348d65978aee3349e206501b1e95cf9b9d8 Mon Sep 17 00:00:00 2001 From: Silarn Date: Mon, 1 Oct 2018 00:10:33 -0500 Subject: [PATCH 0644/1544] [game_ttw] Add 'creation' game lib for creation engine changes, eliminate duplicate plugin code --- src/games/ttw/src/CMakeLists.txt | 4 ++-- src/games/ttw/src/game_ttw_en.ts | 36 ++++++++++++++++---------------- 2 files changed, 20 insertions(+), 20 deletions(-) diff --git a/src/games/ttw/src/CMakeLists.txt b/src/games/ttw/src/CMakeLists.txt index faeaa98f..de7f7d7b 100644 --- a/src/games/ttw/src/CMakeLists.txt +++ b/src/games/ttw/src/CMakeLists.txt @@ -19,7 +19,7 @@ GET_FILENAME_COMPONENT(${default_project_path} ${default_project_path} REALPATH) SET(project_path "${default_project_path}" CACHE PATH "path to the other mo projects") FIND_PACKAGE(Qt5LinguistTools) -SET(translation_sources ${CMAKE_SOURCE_DIR}/src ${project_path}/game_gamebryo/src) +SET(translation_sources ${CMAKE_SOURCE_DIR}/src ${project_path}/game_gamebryo/src/gamebryo) QT5_CREATE_TRANSLATION(${PROJ_NAME}_translations_qm ${translation_sources} ${CMAKE_SOURCE_DIR}/src/${PROJ_NAME}_en.ts) SET(Boost_USE_STATIC_LIBS ON) @@ -35,7 +35,7 @@ SET(lib_path "${project_path}/../../install/libs") INCLUDE_DIRECTORIES(${project_path}/uibase/src ${project_path}/game_features/src - ${project_path}/game_gamebryo/src) + ${project_path}/game_gamebryo/src/gamebryo) LINK_DIRECTORIES(${project_path}/uibase/build/src ${lib_path} ${LZ4_ROOT}/dll) diff --git a/src/games/ttw/src/game_ttw_en.ts b/src/games/ttw/src/game_ttw_en.ts index 5e9e9042..70bdb785 100644 --- a/src/games/ttw/src/game_ttw_en.ts +++ b/src/games/ttw/src/game_ttw_en.ts @@ -12,48 +12,48 @@ GamebryoSaveGameInfoWidget - + Save # - + Character - + Level - + Location - + Date - + Has Script Extender Data - + Missing ESPs - - + + None - + Missing ESLs @@ -61,42 +61,42 @@ QObject - + failed to deactivate BSA invalidation in "%1" (errorcode %2) - + failed to activate BSA invalidation in "%1" (errorcode %2) - + failed to set archive key (errorcode %1) - + Some of your plugins have invalid names! These plugins can not be loaded by the game. Please see mo_interface.log for a list of affected plugins and rename them. - + failed to open %1 - + wrong file format - expected %1 got %2 - + failed to query registry path (preflight): %1 - + failed to query registry path (read): %1 From f01091fcdb411e6a0e1af5b1817978d7f385631c Mon Sep 17 00:00:00 2001 From: LostDragonist Date: Sat, 10 Nov 2018 22:27:13 -0600 Subject: [PATCH 0645/1544] [game_ttw] Change plugin priority to match TTW 3.2 release --- src/games/ttw/src/gamefalloutttw.cpp | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/src/games/ttw/src/gamefalloutttw.cpp b/src/games/ttw/src/gamefalloutttw.cpp index 337e5b98..1c3c7e93 100644 --- a/src/games/ttw/src/gamefalloutttw.cpp +++ b/src/games/ttw/src/gamefalloutttw.cpp @@ -80,7 +80,7 @@ QString GameFalloutTTW::description() const MOBase::VersionInfo GameFalloutTTW::version() const { - return VersionInfo(1, 1, 0, VersionInfo::RELEASE_FINAL); + return VersionInfo(1, 2, 0, VersionInfo::RELEASE_FINAL); } bool GameFalloutTTW::isActive() const @@ -137,16 +137,16 @@ QStringList GameFalloutTTW::primaryPlugins() const "oldworldblues.esm", "lonesomeroad.esm", "gunrunnersarsenal.esm", - "caravanpack.esm", - "classicpack.esm", - "mercenarypack.esm", - "tribalpack.esm", "fallout3.esm", "anchorage.esm", "thepitt.esm", "brokensteel.esm", "pointlookout.esm", "zeta.esm", + "caravanpack.esm", + "classicpack.esm", + "mercenarypack.esm", + "tribalpack.esm", "taleoftwowastelands.esm" }; } From 22294c31a82cc6819eebdc8b541d725a370e1e9a Mon Sep 17 00:00:00 2001 From: LostDragonist Date: Mon, 26 Nov 2018 07:29:56 -0600 Subject: [PATCH 0646/1544] [game_fallout3] Change plugin name to "Fallout 3 Support Plugin" --- src/games/fallout3/src/gamefallout3.cpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/games/fallout3/src/gamefallout3.cpp b/src/games/fallout3/src/gamefallout3.cpp index 47d8b7cc..78cca4d0 100644 --- a/src/games/fallout3/src/gamefallout3.cpp +++ b/src/games/fallout3/src/gamefallout3.cpp @@ -63,7 +63,7 @@ QList GameFallout3::executables() const QString GameFallout3::name() const { - return "Fallout3 Support Plugin"; + return "Fallout 3 Support Plugin"; } QString GameFallout3::author() const @@ -175,4 +175,4 @@ int GameFallout3::nexusGameID() const QString GameFallout3::getLauncherName() const { return "FalloutLauncher.exe"; -} \ No newline at end of file +} From c86e14010fbb280964c2845e513376f81f330b3f Mon Sep 17 00:00:00 2001 From: LostDragonist Date: Mon, 26 Nov 2018 07:31:02 -0600 Subject: [PATCH 0647/1544] [game_fallout76] Change plugin name to "Fallout 4 Support Plugin" --- src/games/fallout76/src/gamefallout4.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/games/fallout76/src/gamefallout4.cpp b/src/games/fallout76/src/gamefallout4.cpp index 3bd7b6bf..97f3417d 100644 --- a/src/games/fallout76/src/gamefallout4.cpp +++ b/src/games/fallout76/src/gamefallout4.cpp @@ -63,7 +63,7 @@ QList GameFallout4::executables() const QString GameFallout4::name() const { - return "Fallout4 Support Plugin"; + return "Fallout 4 Support Plugin"; } QString GameFallout4::author() const From bc382d6e58c9cde3bf1a8cc56134e06cf4552d04 Mon Sep 17 00:00:00 2001 From: LostDragonist Date: Mon, 26 Nov 2018 07:31:02 -0600 Subject: [PATCH 0648/1544] [game_fallout4] Change plugin name to "Fallout 4 Support Plugin" --- src/games/fallout4/src/gamefallout4.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/games/fallout4/src/gamefallout4.cpp b/src/games/fallout4/src/gamefallout4.cpp index 3bd7b6bf..97f3417d 100644 --- a/src/games/fallout4/src/gamefallout4.cpp +++ b/src/games/fallout4/src/gamefallout4.cpp @@ -63,7 +63,7 @@ QList GameFallout4::executables() const QString GameFallout4::name() const { - return "Fallout4 Support Plugin"; + return "Fallout 4 Support Plugin"; } QString GameFallout4::author() const From 65bf36ef9bcc9b44be772359453ea8f169f71ef8 Mon Sep 17 00:00:00 2001 From: LostDragonist Date: Mon, 26 Nov 2018 07:31:34 -0600 Subject: [PATCH 0649/1544] [game_ttw] Change plugin name to "Fallout TTW Support Plugin" --- src/games/ttw/src/gamefalloutttw.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/games/ttw/src/gamefalloutttw.cpp b/src/games/ttw/src/gamefalloutttw.cpp index 1c3c7e93..3709186d 100644 --- a/src/games/ttw/src/gamefalloutttw.cpp +++ b/src/games/ttw/src/gamefalloutttw.cpp @@ -65,7 +65,7 @@ QList GameFalloutTTW::executables() const QString GameFalloutTTW::name() const { - return "FalloutTTW Support Plugin"; + return "Fallout TTW Support Plugin"; } QString GameFalloutTTW::author() const From 53aca4435422e2298c87215d690d4bd972e3d09a Mon Sep 17 00:00:00 2001 From: LostDragonist Date: Mon, 26 Nov 2018 07:32:43 -0600 Subject: [PATCH 0650/1544] [game_falloutnv] Change plugin name to "Fallout NV Support Plugin" --- src/games/falloutnv/src/gamefalloutnv.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/games/falloutnv/src/gamefalloutnv.cpp b/src/games/falloutnv/src/gamefalloutnv.cpp index af841dac..393bc7c5 100644 --- a/src/games/falloutnv/src/gamefalloutnv.cpp +++ b/src/games/falloutnv/src/gamefalloutnv.cpp @@ -63,7 +63,7 @@ QList GameFalloutNV::executables() const QString GameFalloutNV::name() const { - return "FalloutNV Support Plugin"; + return "Fallout NV Support Plugin"; } QString GameFalloutNV::author() const From 3cd49ba67a66a932f53bae6708c795700a3d4873 Mon Sep 17 00:00:00 2001 From: Al12rs Date: Fri, 30 Nov 2018 13:06:09 +0100 Subject: [PATCH 0651/1544] [game_falloutnv] Added support for GECK ini files. --- src/games/falloutnv/src/gamefalloutnv.cpp | 9 ++++++--- 1 file changed, 6 insertions(+), 3 deletions(-) diff --git a/src/games/falloutnv/src/gamefalloutnv.cpp b/src/games/falloutnv/src/gamefalloutnv.cpp index 393bc7c5..85ffd4b2 100644 --- a/src/games/falloutnv/src/gamefalloutnv.cpp +++ b/src/games/falloutnv/src/gamefalloutnv.cpp @@ -107,8 +107,11 @@ void GameFalloutNV::initializeProfile(const QDir &path, ProfileSettings settings } copyToProfile(myGamesPath(), path, "falloutprefs.ini"); - copyToProfile(myGamesPath(), path, "falloutcustom.ini"); - copyToProfile(myGamesPath(), path, "custom.ini"); + copyToProfile(myGamesPath(), path, "falloutcustom.ini"); + copyToProfile(myGamesPath(), path, "custom.ini"); + copyToProfile(myGamesPath(), path, "GECKCustom.ini"); + copyToProfile(myGamesPath(), path, "GECKPrefs.ini"); + } } @@ -144,7 +147,7 @@ QString GameFalloutNV::gameNexusName() const QStringList GameFalloutNV::iniFiles() const { - return { "fallout.ini", "falloutprefs.ini", "falloutcustom.ini", "custom.ini"}; + return { "fallout.ini", "falloutprefs.ini", "falloutcustom.ini", "custom.ini", "GECKCustom.ini", "GECKPrefs.ini"}; } QStringList GameFalloutNV::DLCPlugins() const From d32b7773908f50a2891802e758bb0627ced4d9e8 Mon Sep 17 00:00:00 2001 From: Al12rs Date: Fri, 30 Nov 2018 13:12:15 +0100 Subject: [PATCH 0652/1544] [game_fallout3] Added support for GECK ini files. --- src/games/fallout3/src/gamefallout3.cpp | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/src/games/fallout3/src/gamefallout3.cpp b/src/games/fallout3/src/gamefallout3.cpp index 78cca4d0..9eb68bc6 100644 --- a/src/games/fallout3/src/gamefallout3.cpp +++ b/src/games/fallout3/src/gamefallout3.cpp @@ -107,7 +107,9 @@ void GameFallout3::initializeProfile(const QDir &path, ProfileSettings settings) } copyToProfile(myGamesPath(), path, "falloutprefs.ini"); - copyToProfile(myGamesPath(), path, "custom.ini"); + copyToProfile(myGamesPath(), path, "custom.ini"); + copyToProfile(myGamesPath(), path, "GECKCustom.ini"); + copyToProfile(myGamesPath(), path, "GECKPrefs.ini"); } } @@ -154,7 +156,7 @@ QString GameFallout3::gameNexusName() const QStringList GameFallout3::iniFiles() const { - return { "fallout.ini", "falloutprefs.ini", "custom.ini" }; + return { "fallout.ini", "falloutprefs.ini", "custom.ini", "GECKCustom.ini", "GECKPrefs.ini" }; } QStringList GameFallout3::DLCPlugins() const From 8d5416eca40825a5b8f47b16277a074cb7cfaec6 Mon Sep 17 00:00:00 2001 From: Al12rs Date: Fri, 30 Nov 2018 13:13:35 +0100 Subject: [PATCH 0653/1544] [game_ttw] Added GECK ini files support --- src/games/ttw/src/gamefalloutttw.cpp | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/src/games/ttw/src/gamefalloutttw.cpp b/src/games/ttw/src/gamefalloutttw.cpp index 3709186d..564a8240 100644 --- a/src/games/ttw/src/gamefalloutttw.cpp +++ b/src/games/ttw/src/gamefalloutttw.cpp @@ -111,6 +111,8 @@ void GameFalloutTTW::initializeProfile(const QDir &path, ProfileSettings setting copyToProfile(myGamesPath(), path, "falloutprefs.ini"); copyToProfile(myGamesPath(), path, "falloutcustom.ini"); copyToProfile(myGamesPath(), path, "custom.ini"); + copyToProfile(myGamesPath(), path, "GECKCustom.ini"); + copyToProfile(myGamesPath(), path, "GECKPrefs.ini"); } } @@ -177,7 +179,7 @@ QString GameFalloutTTW::gameNexusName() const QStringList GameFalloutTTW::iniFiles() const { - return { "fallout.ini", "falloutprefs.ini", "falloutcustom.ini", "custom.ini" }; + return { "fallout.ini", "falloutprefs.ini", "falloutcustom.ini", "custom.ini", "GECKCustom.ini", "GECKPrefs.ini" }; } QStringList GameFalloutTTW::DLCPlugins() const From 50a78f7c3a1facc81436522af719a9f72b1ee253 Mon Sep 17 00:00:00 2001 From: LostDragonist Date: Wed, 5 Dec 2018 00:02:07 -0600 Subject: [PATCH 0654/1544] Rework invalidation to better allow automatic fixing --- src/gamebryo/gamebryobsainvalidation.cpp | 130 ++++++++++++++--------- src/gamebryo/gamebryobsainvalidation.h | 1 + src/gamebryo/gamebryodataarchives.cpp | 2 +- 3 files changed, 83 insertions(+), 50 deletions(-) diff --git a/src/gamebryo/gamebryobsainvalidation.cpp b/src/gamebryo/gamebryobsainvalidation.cpp index 48bf5e07..9c6be33b 100644 --- a/src/gamebryo/gamebryobsainvalidation.cpp +++ b/src/gamebryo/gamebryobsainvalidation.cpp @@ -36,58 +36,90 @@ bool GamebryoBSAInvalidation::isInvalidationBSA(const QString &bsaName) void GamebryoBSAInvalidation::deactivate(MOBase::IProfile *profile) { - QStringList archivesBefore = m_DataArchives->archives(profile); - for (const QString &archive : archivesBefore) { - if (isInvalidationBSA(archive)) { - m_DataArchives->removeArchive(profile, archive); - } - } - - QString bsaFile = m_Game->dataDirectory().absoluteFilePath(invalidationBSAName()); - if (QFile::exists(bsaFile)) { - MOBase::shellDeleteQuiet(bsaFile); - } - - QString iniFile = profile->localSettingsEnabled() ? QDir(profile->absolutePath()).absoluteFilePath(m_IniFileName) : m_Game->documentsDirectory().absoluteFilePath(m_IniFileName); - - ::SetFileAttributesW(iniFile.toStdWString().c_str(), FILE_ATTRIBUTE_NORMAL); - - if (!::WritePrivateProfileStringW(L"Archive", L"bInvalidateOlderFiles", L"0", iniFile.toStdWString().c_str()) || - !::WritePrivateProfileStringW(L"Archive", L"SInvalidationFile", L"ArchiveInvalidation.txt", iniFile.toStdWString().c_str())) { - throw MOBase::MyException(QObject::tr("failed to deactivate BSA invalidation in \"%1\" (errorcode %2)").arg(iniFile, ::GetLastError())); - } + prepareProfile(profile); } void GamebryoBSAInvalidation::activate(MOBase::IProfile *profile) { - // set the invalidation bsa up to be loaded - QStringList archives = m_DataArchives->archives(profile); - bool bsaInstalled = false; - for (const QString &archive : archives) { - if (isInvalidationBSA(archive)) { - bsaInstalled = true; - break; - } - } - if (!bsaInstalled) { - m_DataArchives->addArchive(profile, 0, invalidationBSAName()); - } - - // create the dummy bsa if necessary - QString bsaFile = m_Game->dataDirectory().absoluteFilePath(invalidationBSAName()); - if (!QFile::exists(bsaFile)) { - DummyBSA bsa(bsaVersion()); - bsa.write(bsaFile); - } - - // set the remaining ini settings required - QString iniFile = profile->localSettingsEnabled() ? QDir(profile->absolutePath()).absoluteFilePath(m_IniFileName) : m_Game->documentsDirectory().absoluteFilePath(m_IniFileName); - - ::SetFileAttributesW(iniFile.toStdWString().c_str(), FILE_ATTRIBUTE_NORMAL); - - if (!::WritePrivateProfileStringW(L"Archive", L"bInvalidateOlderFiles", L"1", iniFile.toStdWString().c_str()) || - !::WritePrivateProfileStringW(L"Archive", L"SInvalidationFile", L"", iniFile.toStdWString().c_str())) { - throw MOBase::MyException(QObject::tr("failed to activate BSA invalidation in \"%1\" (errorcode %2)").arg(iniFile, ::GetLastError())); - } + prepareProfile(profile); } +void GamebryoBSAInvalidation::prepareProfile(MOBase::IProfile *profile) +{ + QString basePath + = profile->localSettingsEnabled() + ? profile->absolutePath() + : m_Game->documentsDirectory().absolutePath(); + QString iniFilePath = basePath + "/" + m_IniFileName; + WCHAR setting[MAX_PATH]; + + if (profile->invalidationActive(nullptr)){ + + // add the dummy bsa to the archive string, if needed + QStringList archives = m_DataArchives->archives(profile); + bool bsaInstalled = false; + for (const QString &archive : archives) { + if (isInvalidationBSA(archive)) { + bsaInstalled = true; + break; + } + } + if (!bsaInstalled) { + m_DataArchives->addArchive(profile, 0, invalidationBSAName()); + } + + // create the dummy bsa if necessary + QString bsaFile = m_Game->dataDirectory().absoluteFilePath(invalidationBSAName()); + if (!QFile::exists(bsaFile)) { + DummyBSA bsa(bsaVersion()); + bsa.write(bsaFile); + } + + // write bInvalidateOlderFiles = 1, if needed + if (!::GetPrivateProfileStringW(L"Archive", L"bInvalidateOlderFiles", L"0", setting, MAX_PATH, iniFilePath.toStdWString().c_str()) + || wcstol(setting, nullptr, 10) != 1) { + if (!::WritePrivateProfileStringW(L"Archive", L"bInvalidateOlderFiles", L"1", iniFilePath.toStdWString().c_str())) { + throw MOBase::MyException(QObject::tr("failed to activate BSA invalidation in \"%1\" (errorcode %2)").arg(m_IniFileName, ::GetLastError())); + } + } + + // write SInvalidationFile = "", if needed + if (!::GetPrivateProfileStringW(L"Archive", L"SInvalidationFile", L"ArchiveInvalidation.txt", setting, MAX_PATH, iniFilePath.toStdWString().c_str()) + || wcscmp(setting, L"") != 0) { + if (!::WritePrivateProfileStringW(L"Archive", L"SInvalidationFile", L"", iniFilePath.toStdWString().c_str())) { + throw MOBase::MyException(QObject::tr("failed to activate BSA invalidation in \"%1\" (errorcode %2)").arg(m_IniFileName, ::GetLastError())); + } + } + } else { + + // remove the dummy bsa from the archive string, if needed + QStringList archivesBefore = m_DataArchives->archives(profile); + for (const QString &archive : archivesBefore) { + if (isInvalidationBSA(archive)) { + m_DataArchives->removeArchive(profile, archive); + } + } + + // delete the dummy bsa, if needed + QString bsaFile = m_Game->dataDirectory().absoluteFilePath(invalidationBSAName()); + if (QFile::exists(bsaFile)) { + MOBase::shellDeleteQuiet(bsaFile); + } + + // write bInvalidateOlderFiles = 0, if needed + if (!::GetPrivateProfileStringW(L"Archive", L"bInvalidateOlderFiles", L"1", setting, MAX_PATH, iniFilePath.toStdWString().c_str()) + || wcstol(setting, nullptr, 10) != 0) { + if (!::WritePrivateProfileStringW(L"Archive", L"bInvalidateOlderFiles", L"0", iniFilePath.toStdWString().c_str())) { + throw MOBase::MyException(QObject::tr("failed to deactivate BSA invalidation in \"%1\" (errorcode %2)").arg(m_IniFileName, ::GetLastError())); + } + } + + // write SInvalidationFile = "ArchiveInvalidation.txt", if needed + if (!::GetPrivateProfileStringW(L"Archive", L"SInvalidationFile", L"", setting, MAX_PATH, iniFilePath.toStdWString().c_str()) + || wcscmp(setting, L"ArchiveInvalidation.txt") != 0) { + if (!::WritePrivateProfileStringW(L"Archive", L"SInvalidationFile", L"ArchiveInvalidation.txt", iniFilePath.toStdWString().c_str())) { + throw MOBase::MyException(QObject::tr("failed to activate BSA invalidation in \"%1\" (errorcode %2)").arg(m_IniFileName, ::GetLastError())); + } + } + } +} \ No newline at end of file diff --git a/src/gamebryo/gamebryobsainvalidation.h b/src/gamebryo/gamebryobsainvalidation.h index e73e6837..2ba81cb3 100644 --- a/src/gamebryo/gamebryobsainvalidation.h +++ b/src/gamebryo/gamebryobsainvalidation.h @@ -22,6 +22,7 @@ public: virtual bool isInvalidationBSA(const QString &bsaName) override; virtual void deactivate(MOBase::IProfile *profile) override; virtual void activate(MOBase::IProfile *profile) override; + virtual void prepareProfile(MOBase::IProfile *profile) override; private: diff --git a/src/gamebryo/gamebryodataarchives.cpp b/src/gamebryo/gamebryodataarchives.cpp index 6045db10..2cb8dfbd 100644 --- a/src/gamebryo/gamebryodataarchives.cpp +++ b/src/gamebryo/gamebryodataarchives.cpp @@ -32,7 +32,7 @@ QStringList GamebryoDataArchives::getArchivesFromKey(const QString &iniFile, con void GamebryoDataArchives::setArchivesToKey(const QString &iniFile, const QString &key, const QString &value) { if (!::WritePrivateProfileStringW(L"Archive", key.toStdWString().c_str(), value.toStdWString().c_str(), iniFile.toStdWString().c_str())) { - throw MOBase::MyException(QObject::tr("failed to set archive key (errorcode %1)").arg(errno)); + throw MOBase::MyException(QObject::tr("failed to set archive key in %1 (errorcode %2)").arg(iniFile).arg(errno)); } } From 47d000a9e227457f99dc44fbda0269da9126360a Mon Sep 17 00:00:00 2001 From: LostDragonist Date: Fri, 7 Dec 2018 14:43:07 -0600 Subject: [PATCH 0655/1544] Always set bInvalidateOlderFiles=1 --- src/gamebryo/gamebryobsainvalidation.cpp | 24 ++++++++---------------- 1 file changed, 8 insertions(+), 16 deletions(-) diff --git a/src/gamebryo/gamebryobsainvalidation.cpp b/src/gamebryo/gamebryobsainvalidation.cpp index 9c6be33b..ae1e6a9e 100644 --- a/src/gamebryo/gamebryobsainvalidation.cpp +++ b/src/gamebryo/gamebryobsainvalidation.cpp @@ -53,6 +53,14 @@ void GamebryoBSAInvalidation::prepareProfile(MOBase::IProfile *profile) QString iniFilePath = basePath + "/" + m_IniFileName; WCHAR setting[MAX_PATH]; + // write bInvalidateOlderFiles = 1, if needed + if (!::GetPrivateProfileStringW(L"Archive", L"bInvalidateOlderFiles", L"0", setting, MAX_PATH, iniFilePath.toStdWString().c_str()) + || wcstol(setting, nullptr, 10) != 1) { + if (!::WritePrivateProfileStringW(L"Archive", L"bInvalidateOlderFiles", L"1", iniFilePath.toStdWString().c_str())) { + throw MOBase::MyException(QObject::tr("failed to activate BSA invalidation in \"%1\" (errorcode %2)").arg(m_IniFileName, ::GetLastError())); + } + } + if (profile->invalidationActive(nullptr)){ // add the dummy bsa to the archive string, if needed @@ -75,14 +83,6 @@ void GamebryoBSAInvalidation::prepareProfile(MOBase::IProfile *profile) bsa.write(bsaFile); } - // write bInvalidateOlderFiles = 1, if needed - if (!::GetPrivateProfileStringW(L"Archive", L"bInvalidateOlderFiles", L"0", setting, MAX_PATH, iniFilePath.toStdWString().c_str()) - || wcstol(setting, nullptr, 10) != 1) { - if (!::WritePrivateProfileStringW(L"Archive", L"bInvalidateOlderFiles", L"1", iniFilePath.toStdWString().c_str())) { - throw MOBase::MyException(QObject::tr("failed to activate BSA invalidation in \"%1\" (errorcode %2)").arg(m_IniFileName, ::GetLastError())); - } - } - // write SInvalidationFile = "", if needed if (!::GetPrivateProfileStringW(L"Archive", L"SInvalidationFile", L"ArchiveInvalidation.txt", setting, MAX_PATH, iniFilePath.toStdWString().c_str()) || wcscmp(setting, L"") != 0) { @@ -106,14 +106,6 @@ void GamebryoBSAInvalidation::prepareProfile(MOBase::IProfile *profile) MOBase::shellDeleteQuiet(bsaFile); } - // write bInvalidateOlderFiles = 0, if needed - if (!::GetPrivateProfileStringW(L"Archive", L"bInvalidateOlderFiles", L"1", setting, MAX_PATH, iniFilePath.toStdWString().c_str()) - || wcstol(setting, nullptr, 10) != 0) { - if (!::WritePrivateProfileStringW(L"Archive", L"bInvalidateOlderFiles", L"0", iniFilePath.toStdWString().c_str())) { - throw MOBase::MyException(QObject::tr("failed to deactivate BSA invalidation in \"%1\" (errorcode %2)").arg(m_IniFileName, ::GetLastError())); - } - } - // write SInvalidationFile = "ArchiveInvalidation.txt", if needed if (!::GetPrivateProfileStringW(L"Archive", L"SInvalidationFile", L"", setting, MAX_PATH, iniFilePath.toStdWString().c_str()) || wcscmp(setting, L"ArchiveInvalidation.txt") != 0) { From 8f0c0113a44f09a0ad4194d8a2f033d89ecb044c Mon Sep 17 00:00:00 2001 From: LostDragonist Date: Fri, 7 Dec 2018 21:38:36 -0600 Subject: [PATCH 0656/1544] Improve refresh of data when changing profile settings --- src/gamebryo/gamebryobsainvalidation.cpp | 16 ++++-- src/gamebryo/gamebryobsainvalidation.h | 2 +- src/gamebryo/gamebryolocalsavegames.cpp | 65 ++++++++++++++++++------ src/gamebryo/gamebryolocalsavegames.h | 3 +- 4 files changed, 65 insertions(+), 21 deletions(-) diff --git a/src/gamebryo/gamebryobsainvalidation.cpp b/src/gamebryo/gamebryobsainvalidation.cpp index ae1e6a9e..94d782ab 100644 --- a/src/gamebryo/gamebryobsainvalidation.cpp +++ b/src/gamebryo/gamebryobsainvalidation.cpp @@ -44,8 +44,9 @@ void GamebryoBSAInvalidation::activate(MOBase::IProfile *profile) prepareProfile(profile); } -void GamebryoBSAInvalidation::prepareProfile(MOBase::IProfile *profile) +bool GamebryoBSAInvalidation::prepareProfile(MOBase::IProfile *profile) { + bool dirty = false; QString basePath = profile->localSettingsEnabled() ? profile->absolutePath() @@ -56,6 +57,7 @@ void GamebryoBSAInvalidation::prepareProfile(MOBase::IProfile *profile) // write bInvalidateOlderFiles = 1, if needed if (!::GetPrivateProfileStringW(L"Archive", L"bInvalidateOlderFiles", L"0", setting, MAX_PATH, iniFilePath.toStdWString().c_str()) || wcstol(setting, nullptr, 10) != 1) { + dirty = true; if (!::WritePrivateProfileStringW(L"Archive", L"bInvalidateOlderFiles", L"1", iniFilePath.toStdWString().c_str())) { throw MOBase::MyException(QObject::tr("failed to activate BSA invalidation in \"%1\" (errorcode %2)").arg(m_IniFileName, ::GetLastError())); } @@ -74,6 +76,7 @@ void GamebryoBSAInvalidation::prepareProfile(MOBase::IProfile *profile) } if (!bsaInstalled) { m_DataArchives->addArchive(profile, 0, invalidationBSAName()); + dirty = true; } // create the dummy bsa if necessary @@ -81,11 +84,13 @@ void GamebryoBSAInvalidation::prepareProfile(MOBase::IProfile *profile) if (!QFile::exists(bsaFile)) { DummyBSA bsa(bsaVersion()); bsa.write(bsaFile); + dirty = true; } // write SInvalidationFile = "", if needed - if (!::GetPrivateProfileStringW(L"Archive", L"SInvalidationFile", L"ArchiveInvalidation.txt", setting, MAX_PATH, iniFilePath.toStdWString().c_str()) + if (::GetPrivateProfileStringW(L"Archive", L"SInvalidationFile", L"ArchiveInvalidation.txt", setting, MAX_PATH, iniFilePath.toStdWString().c_str()) || wcscmp(setting, L"") != 0) { + dirty = true; if (!::WritePrivateProfileStringW(L"Archive", L"SInvalidationFile", L"", iniFilePath.toStdWString().c_str())) { throw MOBase::MyException(QObject::tr("failed to activate BSA invalidation in \"%1\" (errorcode %2)").arg(m_IniFileName, ::GetLastError())); } @@ -97,6 +102,7 @@ void GamebryoBSAInvalidation::prepareProfile(MOBase::IProfile *profile) for (const QString &archive : archivesBefore) { if (isInvalidationBSA(archive)) { m_DataArchives->removeArchive(profile, archive); + dirty = true; } } @@ -104,14 +110,18 @@ void GamebryoBSAInvalidation::prepareProfile(MOBase::IProfile *profile) QString bsaFile = m_Game->dataDirectory().absoluteFilePath(invalidationBSAName()); if (QFile::exists(bsaFile)) { MOBase::shellDeleteQuiet(bsaFile); + dirty = true; } // write SInvalidationFile = "ArchiveInvalidation.txt", if needed if (!::GetPrivateProfileStringW(L"Archive", L"SInvalidationFile", L"", setting, MAX_PATH, iniFilePath.toStdWString().c_str()) || wcscmp(setting, L"ArchiveInvalidation.txt") != 0) { + dirty = true; if (!::WritePrivateProfileStringW(L"Archive", L"SInvalidationFile", L"ArchiveInvalidation.txt", iniFilePath.toStdWString().c_str())) { throw MOBase::MyException(QObject::tr("failed to activate BSA invalidation in \"%1\" (errorcode %2)").arg(m_IniFileName, ::GetLastError())); } } } -} \ No newline at end of file + + return dirty; +} diff --git a/src/gamebryo/gamebryobsainvalidation.h b/src/gamebryo/gamebryobsainvalidation.h index 2ba81cb3..7b8e3a35 100644 --- a/src/gamebryo/gamebryobsainvalidation.h +++ b/src/gamebryo/gamebryobsainvalidation.h @@ -22,7 +22,7 @@ public: virtual bool isInvalidationBSA(const QString &bsaName) override; virtual void deactivate(MOBase::IProfile *profile) override; virtual void activate(MOBase::IProfile *profile) override; - virtual void prepareProfile(MOBase::IProfile *profile) override; + virtual bool prepareProfile(MOBase::IProfile *profile) override; private: diff --git a/src/gamebryo/gamebryolocalsavegames.cpp b/src/gamebryo/gamebryolocalsavegames.cpp index 408a39cf..c63e55e0 100644 --- a/src/gamebryo/gamebryolocalsavegames.cpp +++ b/src/gamebryo/gamebryolocalsavegames.cpp @@ -47,8 +47,9 @@ MappingType GamebryoLocalSavegames::mappings(const QDir &profileSaveDir) const } -void GamebryoLocalSavegames::prepareProfile(MOBase::IProfile *profile) +bool GamebryoLocalSavegames::prepareProfile(MOBase::IProfile *profile) { + bool dirty = false; bool enable = profile->localSavesEnabled(); qDebug("enable local saves: %d", enable); QString basePath @@ -61,7 +62,8 @@ void GamebryoLocalSavegames::prepareProfile(MOBase::IProfile *profile) WCHAR oldMyGames[1]; GetPrivateProfileStringW(L"General", L"SLocalSavePath", NULL, oldPath, MAX_PATH, iniFilePath.toStdWString().c_str()); GetPrivateProfileStringW(L"General", L"bUseMyGamesDirectory", NULL, oldMyGames, 1, iniFilePath.toStdWString().c_str()); - if (enable && wcscmp(oldPath, L"") != 0 && wcscmp(oldPath, (LocalSavesDummy + "\\").toStdWString().c_str()) == 0) { + if (enable && wcscmp(oldPath, L"") != 0 && wcscmp(oldPath, (LocalSavesDummy + "\\").toStdWString().c_str()) != 0) { + dirty = true; WritePrivateProfileStringW(L"General", L"SLocalSavePath", oldPath, QString(profile->absolutePath() + "/" + "savepath.ini").toStdWString().c_str()); if (wcscmp(oldMyGames, L"") != 0) { WritePrivateProfileStringW(L"General", L"bUseMyGamesDirectory", oldMyGames, QString(profile->absolutePath() + "/" + "savepath.ini").toStdWString().c_str()); @@ -88,18 +90,51 @@ void GamebryoLocalSavegames::prepareProfile(MOBase::IProfile *profile) } } - WritePrivateProfileStringW(L"General", L"SLocalSavePath", - enable ? (LocalSavesDummy + "\\").toStdWString().c_str() - : (saved ? savedPath : NULL), - iniFilePath.toStdWString().c_str()); + if (enable) { + if (wcscmp(oldPath, (LocalSavesDummy + "\\").toStdWString().c_str()) != 0){ + WritePrivateProfileStringW(L"General", L"SLocalSavePath", + (LocalSavesDummy + "\\").toStdWString().c_str(), + iniFilePath.toStdWString().c_str()); + dirty = true; + } + if (wcscmp(oldMyGames, L"") != 0) { + WritePrivateProfileStringW(L"General", L"bUseMyGamesDirectory", + NULL, + iniFilePath.toStdWString().c_str()); + dirty = true; + } + } else { + if (saved) { + if (wcscmp(oldPath, savedPath) != 0) { + WritePrivateProfileStringW(L"General", L"SLocalSavePath", + savedPath, + iniFilePath.toStdWString().c_str()); + dirty = true; + } + } else { + if (wcscmp(oldPath, L"") != 0) { + WritePrivateProfileStringW(L"General", L"SLocalSavePath", + NULL, + iniFilePath.toStdWString().c_str()); + dirty = true; + } + } + if (savedDir) { + if (wcscmp(oldMyGames, savedMyGames) != 0) { + WritePrivateProfileStringW(L"General", L"bUseMyGamesDirectory", + savedMyGames, + iniFilePath.toStdWString().c_str()); + dirty = true; + } + } else { + if (wcscmp(oldMyGames, L"") != 0) { + WritePrivateProfileStringW(L"General", L"bUseMyGamesDirectory", + NULL, + iniFilePath.toStdWString().c_str()); + dirty = true; + } + } + } - WritePrivateProfileStringW(L"General", L"bUseMyGamesDirectory", - enable ? NULL : (savedDir ? savedMyGames : NULL), - iniFilePath.toStdWString().c_str()); + return dirty; } - - -bool GamebryoLocalSavegames::updateSaveGames(MOBase::IProfile *profile) -{ - return false; -} \ No newline at end of file diff --git a/src/gamebryo/gamebryolocalsavegames.h b/src/gamebryo/gamebryolocalsavegames.h index 550ba242..e2f0bb48 100644 --- a/src/gamebryo/gamebryolocalsavegames.h +++ b/src/gamebryo/gamebryolocalsavegames.h @@ -33,8 +33,7 @@ public: GamebryoLocalSavegames(const QDir &myGamesDir, const QString &iniFileName); virtual MappingType mappings(const QDir &profileSaveDir) const override; - virtual void prepareProfile(MOBase::IProfile *profile) override; - virtual bool updateSaveGames(MOBase::IProfile *profile) override; + virtual bool prepareProfile(MOBase::IProfile *profile) override; private: From 90d42d4c1c61f55924506389631cdd38adbb5475 Mon Sep 17 00:00:00 2001 From: LostDragonist Date: Fri, 7 Dec 2018 23:44:12 -0600 Subject: [PATCH 0657/1544] [game_morrowind] Improve refresh of data when changing profile settings --- src/games/morrowind/src/game_morrowind_en.ts | 15 +++++----- .../morrowind/src/morrowindlocalsavegames.cpp | 30 ++++++++----------- .../morrowind/src/morrowindlocalsavegames.h | 3 +- 3 files changed, 21 insertions(+), 27 deletions(-) diff --git a/src/games/morrowind/src/game_morrowind_en.ts b/src/games/morrowind/src/game_morrowind_en.ts index 1ba6d733..bb070a2d 100644 --- a/src/games/morrowind/src/game_morrowind_en.ts +++ b/src/games/morrowind/src/game_morrowind_en.ts @@ -105,17 +105,13 @@ Splash by %1 QObject - - failed to deactivate BSA invalidation in "%1" (errorcode %2) - - - - + + + failed to activate BSA invalidation in "%1" (errorcode %2) - failed to set archive key (errorcode %1) @@ -151,5 +147,10 @@ Splash by %1 failed to set game file key (errorcode %1) + + + failed to set archive key in %1 (errorcode %2) + + diff --git a/src/games/morrowind/src/morrowindlocalsavegames.cpp b/src/games/morrowind/src/morrowindlocalsavegames.cpp index 056db597..157ed299 100644 --- a/src/games/morrowind/src/morrowindlocalsavegames.cpp +++ b/src/games/morrowind/src/morrowindlocalsavegames.cpp @@ -29,24 +29,7 @@ MorrowindLocalSavegames::MorrowindLocalSavegames(const QDir &gameInstallDir) : m_GameInstallDir(gameInstallDir.absolutePath()) {} -void MorrowindLocalSavegames::prepareProfile(MOBase::IProfile *profile) -{ - updateSaveGames(profile); -} - - -MappingType MorrowindLocalSavegames::mappings(const QDir &profileSaveDir) const -{ - return {{ - profileSaveDir.absolutePath(), - m_GameInstallDir.absolutePath() + "/Saves", - true, - true - }}; -} - - -bool MorrowindLocalSavegames::updateSaveGames(MOBase::IProfile *profile) +bool MorrowindLocalSavegames::prepareProfile(MOBase::IProfile *profile) { bool dirty = false; @@ -68,3 +51,14 @@ bool MorrowindLocalSavegames::updateSaveGames(MOBase::IProfile *profile) return dirty; } + + +MappingType MorrowindLocalSavegames::mappings(const QDir &profileSaveDir) const +{ + return {{ + profileSaveDir.absolutePath(), + m_GameInstallDir.absolutePath() + "/Saves", + true, + true + }}; +} \ No newline at end of file diff --git a/src/games/morrowind/src/morrowindlocalsavegames.h b/src/games/morrowind/src/morrowindlocalsavegames.h index cd1e8e8e..c2164b1d 100644 --- a/src/games/morrowind/src/morrowindlocalsavegames.h +++ b/src/games/morrowind/src/morrowindlocalsavegames.h @@ -33,8 +33,7 @@ public: MorrowindLocalSavegames(const QDir &m_GameInstallDir); virtual MappingType mappings(const QDir &profileSaveDir) const override; - virtual void prepareProfile(MOBase::IProfile *profile) override; - virtual bool updateSaveGames(MOBase::IProfile *profile) override; + virtual bool prepareProfile(MOBase::IProfile *profile) override; private: From 4e35089fefb29f34013cc7635c738e6efd6add2a Mon Sep 17 00:00:00 2001 From: LostDragonist Date: Tue, 11 Dec 2018 15:44:34 -0600 Subject: [PATCH 0658/1544] Remove the requirement for a game launcher to be present --- src/gamebryo/gamegamebryo.cpp | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/src/gamebryo/gamegamebryo.cpp b/src/gamebryo/gamegamebryo.cpp index ae0cd2bf..c5ad673b 100644 --- a/src/gamebryo/gamegamebryo.cpp +++ b/src/gamebryo/gamegamebryo.cpp @@ -114,8 +114,8 @@ MOBase::IPluginGame::SortMechanism GameGamebryo::sortMechanism() const bool GameGamebryo::looksValid(QDir const &path) const { - //Check for .exe and Launcher.exe for now. - return path.exists(binaryName()) && path.exists(getLauncherName()); + //Check for .exe for now. + return path.exists(binaryName()); } QString GameGamebryo::gameVersion() const @@ -350,4 +350,4 @@ QString GameGamebryo::determineMyGamesPath(const QString &gameName) } return result + "/My Games/" + gameName; -} \ No newline at end of file +} From 1f657c4ad3b80a0e5126b7af48f384037098bae7 Mon Sep 17 00:00:00 2001 From: LostDragonist Date: Wed, 12 Dec 2018 02:06:11 -0600 Subject: [PATCH 0659/1544] [game_fallout3] Update version to 1.3.0.0 --- src/games/fallout3/src/gamefallout3.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/games/fallout3/src/gamefallout3.cpp b/src/games/fallout3/src/gamefallout3.cpp index 9eb68bc6..b25f9aed 100644 --- a/src/games/fallout3/src/gamefallout3.cpp +++ b/src/games/fallout3/src/gamefallout3.cpp @@ -78,7 +78,7 @@ QString GameFallout3::description() const MOBase::VersionInfo GameFallout3::version() const { - return VersionInfo(1, 0, 0, VersionInfo::RELEASE_FINAL); + return VersionInfo(1, 3, 0, VersionInfo::RELEASE_FINAL); } bool GameFallout3::isActive() const From 32a791edb78f94d7ffd34d6f870eaa3ba4187a17 Mon Sep 17 00:00:00 2001 From: LostDragonist Date: Wed, 12 Dec 2018 02:10:15 -0600 Subject: [PATCH 0660/1544] [game_fallout76] Update version to 1.3.0.0 --- src/games/fallout76/src/gamefallout4.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/games/fallout76/src/gamefallout4.cpp b/src/games/fallout76/src/gamefallout4.cpp index 97f3417d..ad4a4f02 100644 --- a/src/games/fallout76/src/gamefallout4.cpp +++ b/src/games/fallout76/src/gamefallout4.cpp @@ -79,7 +79,7 @@ QString GameFallout4::description() const MOBase::VersionInfo GameFallout4::version() const { - return VersionInfo(0, 3, 1, VersionInfo::RELEASE_FINAL); + return VersionInfo(1, 3, 0, VersionInfo::RELEASE_FINAL); } bool GameFallout4::isActive() const From 0936257d86212152ce505618a2bbf0b4bcd4a609 Mon Sep 17 00:00:00 2001 From: LostDragonist Date: Wed, 12 Dec 2018 02:10:15 -0600 Subject: [PATCH 0661/1544] [game_fallout4] Update version to 1.3.0.0 --- src/games/fallout4/src/gamefallout4.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/games/fallout4/src/gamefallout4.cpp b/src/games/fallout4/src/gamefallout4.cpp index 97f3417d..ad4a4f02 100644 --- a/src/games/fallout4/src/gamefallout4.cpp +++ b/src/games/fallout4/src/gamefallout4.cpp @@ -79,7 +79,7 @@ QString GameFallout4::description() const MOBase::VersionInfo GameFallout4::version() const { - return VersionInfo(0, 3, 1, VersionInfo::RELEASE_FINAL); + return VersionInfo(1, 3, 0, VersionInfo::RELEASE_FINAL); } bool GameFallout4::isActive() const From 2d8927a8060623a2c968aca1ea36c4cc60def0b8 Mon Sep 17 00:00:00 2001 From: LostDragonist Date: Wed, 12 Dec 2018 02:10:24 -0600 Subject: [PATCH 0662/1544] [game_fallout4vr] Update version to 1.3.0.0 --- src/games/fallout4vr/src/gamefallout4vr.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/games/fallout4vr/src/gamefallout4vr.cpp b/src/games/fallout4vr/src/gamefallout4vr.cpp index d59ba51d..3e457d28 100644 --- a/src/games/fallout4vr/src/gamefallout4vr.cpp +++ b/src/games/fallout4vr/src/gamefallout4vr.cpp @@ -77,7 +77,7 @@ QString GameFallout4VR::description() const MOBase::VersionInfo GameFallout4VR::version() const { - return VersionInfo(0, 4, 0, VersionInfo::RELEASE_CANDIDATE); + return VersionInfo(1, 3, 0, VersionInfo::RELEASE_FINAL); } bool GameFallout4VR::isActive() const From 49a31b4e64549ba2b4e88b39d24202801403f161 Mon Sep 17 00:00:00 2001 From: LostDragonist Date: Wed, 12 Dec 2018 02:10:32 -0600 Subject: [PATCH 0663/1544] [game_falloutnv] Update version to 1.3.0.0 --- src/games/falloutnv/src/gamefalloutnv.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/games/falloutnv/src/gamefalloutnv.cpp b/src/games/falloutnv/src/gamefalloutnv.cpp index 85ffd4b2..e4e5d913 100644 --- a/src/games/falloutnv/src/gamefalloutnv.cpp +++ b/src/games/falloutnv/src/gamefalloutnv.cpp @@ -78,7 +78,7 @@ QString GameFalloutNV::description() const MOBase::VersionInfo GameFalloutNV::version() const { - return VersionInfo(1, 0, 0, VersionInfo::RELEASE_FINAL); + return VersionInfo(1, 3, 0, VersionInfo::RELEASE_FINAL); } bool GameFalloutNV::isActive() const From 844f337391a751c9850ba35a21d28d9fa2d64737 Mon Sep 17 00:00:00 2001 From: LostDragonist Date: Wed, 12 Dec 2018 02:10:45 -0600 Subject: [PATCH 0664/1544] [game_morrowind] Update version to 1.3.0.0 --- src/games/morrowind/src/gamemorrowind.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/games/morrowind/src/gamemorrowind.cpp b/src/games/morrowind/src/gamemorrowind.cpp index eafa7e8c..2de09b29 100644 --- a/src/games/morrowind/src/gamemorrowind.cpp +++ b/src/games/morrowind/src/gamemorrowind.cpp @@ -100,7 +100,7 @@ QString GameMorrowind::description() const MOBase::VersionInfo GameMorrowind::version() const { - return VersionInfo(0, 2, 2, VersionInfo::RELEASE_FINAL); + return VersionInfo(1, 3, 0, VersionInfo::RELEASE_FINAL); } bool GameMorrowind::isActive() const From d736b6268bd7dbd86451480a0805d8648c12226a Mon Sep 17 00:00:00 2001 From: LostDragonist Date: Wed, 12 Dec 2018 02:10:57 -0600 Subject: [PATCH 0665/1544] [game_oblivion] Update version to 1.3.0.0 --- src/games/oblivion/src/gameoblivion.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/games/oblivion/src/gameoblivion.cpp b/src/games/oblivion/src/gameoblivion.cpp index 091c5bc2..22d2b9ca 100644 --- a/src/games/oblivion/src/gameoblivion.cpp +++ b/src/games/oblivion/src/gameoblivion.cpp @@ -73,7 +73,7 @@ QString GameOblivion::description() const MOBase::VersionInfo GameOblivion::version() const { - return VersionInfo(1, 0, 0, VersionInfo::RELEASE_FINAL); + return VersionInfo(1, 3, 0, VersionInfo::RELEASE_FINAL); } bool GameOblivion::isActive() const From 26c892caee6abfb1f200c0aaef504376f9827bd7 Mon Sep 17 00:00:00 2001 From: LostDragonist Date: Wed, 12 Dec 2018 02:11:05 -0600 Subject: [PATCH 0666/1544] [game_skyrim] Update version to 1.3.0.0 --- src/games/skyrim/src/gameskyrim.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/games/skyrim/src/gameskyrim.cpp b/src/games/skyrim/src/gameskyrim.cpp index f1b06e1a..68f49cf5 100644 --- a/src/games/skyrim/src/gameskyrim.cpp +++ b/src/games/skyrim/src/gameskyrim.cpp @@ -84,7 +84,7 @@ QString GameSkyrim::description() const MOBase::VersionInfo GameSkyrim::version() const { - return VersionInfo(1, 0, 0, VersionInfo::RELEASE_FINAL); + return VersionInfo(1, 3, 0, VersionInfo::RELEASE_FINAL); } bool GameSkyrim::isActive() const From 791d36bc6fd9467e239158e30192fd20f2a9a635 Mon Sep 17 00:00:00 2001 From: LostDragonist Date: Wed, 12 Dec 2018 02:11:14 -0600 Subject: [PATCH 0667/1544] [game_skyrimse] Update version to 1.3.0.0 --- src/games/skyrimse/src/gameskyrimse.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/games/skyrimse/src/gameskyrimse.cpp b/src/games/skyrimse/src/gameskyrimse.cpp index a4f245f9..323562ef 100644 --- a/src/games/skyrimse/src/gameskyrimse.cpp +++ b/src/games/skyrimse/src/gameskyrimse.cpp @@ -118,7 +118,7 @@ QString GameSkyrimSE::description() const MOBase::VersionInfo GameSkyrimSE::version() const { - return VersionInfo(0, 1, 5, VersionInfo::RELEASE_ALPHA); + return VersionInfo(1, 3, 0, VersionInfo::RELEASE_FINAL); } bool GameSkyrimSE::isActive() const From 4a08f9198d7d49c218fc40076f1456ed00ab1167 Mon Sep 17 00:00:00 2001 From: LostDragonist Date: Wed, 12 Dec 2018 02:11:22 -0600 Subject: [PATCH 0668/1544] [game_skyrimvr] Update version to 1.3.0.0 --- src/games/skyrimvr/src/gameskyrimvr.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/games/skyrimvr/src/gameskyrimvr.cpp b/src/games/skyrimvr/src/gameskyrimvr.cpp index 3c213b26..4f5b2fe7 100644 --- a/src/games/skyrimvr/src/gameskyrimvr.cpp +++ b/src/games/skyrimvr/src/gameskyrimvr.cpp @@ -117,7 +117,7 @@ QString GameSkyrimVR::description() const MOBase::VersionInfo GameSkyrimVR::version() const { - return VersionInfo(0, 2, 0, VersionInfo::RELEASE_CANDIDATE); + return VersionInfo(1, 3, 0, VersionInfo::RELEASE_FINAL); } bool GameSkyrimVR::isActive() const From 478992e90f919485d9216126e5b80f62de1d3616 Mon Sep 17 00:00:00 2001 From: LostDragonist Date: Wed, 12 Dec 2018 02:11:29 -0600 Subject: [PATCH 0669/1544] [game_ttw] Update version to 1.3.0.0 --- src/games/ttw/src/gamefalloutttw.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/games/ttw/src/gamefalloutttw.cpp b/src/games/ttw/src/gamefalloutttw.cpp index 564a8240..39b71e0c 100644 --- a/src/games/ttw/src/gamefalloutttw.cpp +++ b/src/games/ttw/src/gamefalloutttw.cpp @@ -80,7 +80,7 @@ QString GameFalloutTTW::description() const MOBase::VersionInfo GameFalloutTTW::version() const { - return VersionInfo(1, 2, 0, VersionInfo::RELEASE_FINAL); + return VersionInfo(1, 3, 0, VersionInfo::RELEASE_FINAL); } bool GameFalloutTTW::isActive() const From ec110201a0c96b6cf424276a58116b6b24d009e6 Mon Sep 17 00:00:00 2001 From: LostDragonist Date: Wed, 12 Dec 2018 02:46:42 -0600 Subject: [PATCH 0670/1544] [game_fallout76] Update translation file --- src/games/fallout76/src/game_fallout4_en.ts | 19 ++++++++----------- 1 file changed, 8 insertions(+), 11 deletions(-) diff --git a/src/games/fallout76/src/game_fallout4_en.ts b/src/games/fallout76/src/game_fallout4_en.ts index 636a61b9..2aaf516f 100644 --- a/src/games/fallout76/src/game_fallout4_en.ts +++ b/src/games/fallout76/src/game_fallout4_en.ts @@ -68,20 +68,12 @@ Splash by %1 - - failed to deactivate BSA invalidation in "%1" (errorcode %2) - - - - + + + failed to activate BSA invalidation in "%1" (errorcode %2) - - - failed to set archive key (errorcode %1) - - failed to open %1 @@ -102,5 +94,10 @@ Splash by %1 failed to query registry path (read): %1 + + + failed to set archive key in %1 (errorcode %2) + + From d9ba719f18bd2c5648e38366245fc001dccc4b18 Mon Sep 17 00:00:00 2001 From: LostDragonist Date: Wed, 12 Dec 2018 02:46:42 -0600 Subject: [PATCH 0671/1544] [game_fallout3] Update translation file --- src/games/fallout3/src/game_fallout3_en.ts | 19 ++++++++----------- 1 file changed, 8 insertions(+), 11 deletions(-) diff --git a/src/games/fallout3/src/game_fallout3_en.ts b/src/games/fallout3/src/game_fallout3_en.ts index 4b045a69..f4775642 100644 --- a/src/games/fallout3/src/game_fallout3_en.ts +++ b/src/games/fallout3/src/game_fallout3_en.ts @@ -61,20 +61,12 @@ QObject - - failed to deactivate BSA invalidation in "%1" (errorcode %2) - - - - + + + failed to activate BSA invalidation in "%1" (errorcode %2) - - - failed to set archive key (errorcode %1) - - Some of your plugins have invalid names! These plugins can not be loaded by the game. Please see mo_interface.log for a list of affected plugins and rename them. @@ -100,5 +92,10 @@ failed to query registry path (read): %1 + + + failed to set archive key in %1 (errorcode %2) + + From 35c9337780d3fcb2c40ff5acf3a9922f7716241b Mon Sep 17 00:00:00 2001 From: LostDragonist Date: Wed, 12 Dec 2018 02:46:42 -0600 Subject: [PATCH 0672/1544] [game_fallout4] Update translation file --- src/games/fallout4/src/game_fallout4_en.ts | 19 ++++++++----------- 1 file changed, 8 insertions(+), 11 deletions(-) diff --git a/src/games/fallout4/src/game_fallout4_en.ts b/src/games/fallout4/src/game_fallout4_en.ts index 636a61b9..2aaf516f 100644 --- a/src/games/fallout4/src/game_fallout4_en.ts +++ b/src/games/fallout4/src/game_fallout4_en.ts @@ -68,20 +68,12 @@ Splash by %1 - - failed to deactivate BSA invalidation in "%1" (errorcode %2) - - - - + + + failed to activate BSA invalidation in "%1" (errorcode %2) - - - failed to set archive key (errorcode %1) - - failed to open %1 @@ -102,5 +94,10 @@ Splash by %1 failed to query registry path (read): %1 + + + failed to set archive key in %1 (errorcode %2) + + From 9cd8dd96c31543824372720c5a50f0839ab836fa Mon Sep 17 00:00:00 2001 From: LostDragonist Date: Wed, 12 Dec 2018 02:46:43 -0600 Subject: [PATCH 0673/1544] [game_fallout4vr] Update translation file --- .../fallout4vr/src/game_fallout4vr_en.ts | 19 ++++++++----------- 1 file changed, 8 insertions(+), 11 deletions(-) diff --git a/src/games/fallout4vr/src/game_fallout4vr_en.ts b/src/games/fallout4vr/src/game_fallout4vr_en.ts index a994c825..2384c194 100644 --- a/src/games/fallout4vr/src/game_fallout4vr_en.ts +++ b/src/games/fallout4vr/src/game_fallout4vr_en.ts @@ -78,20 +78,12 @@ Splash by %1 - - failed to deactivate BSA invalidation in "%1" (errorcode %2) - - - - + + + failed to activate BSA invalidation in "%1" (errorcode %2) - - - failed to set archive key (errorcode %1) - - failed to open %1 @@ -102,5 +94,10 @@ Splash by %1 wrong file format - expected %1 got %2 + + + failed to set archive key in %1 (errorcode %2) + + From b824dd0bdcb7c40e37069f16583e3721165c281d Mon Sep 17 00:00:00 2001 From: LostDragonist Date: Wed, 12 Dec 2018 02:46:43 -0600 Subject: [PATCH 0674/1544] [game_falloutnv] Update translation file --- src/games/falloutnv/src/game_falloutNV_en.ts | 19 ++++++++----------- 1 file changed, 8 insertions(+), 11 deletions(-) diff --git a/src/games/falloutnv/src/game_falloutNV_en.ts b/src/games/falloutnv/src/game_falloutNV_en.ts index c2df0978..421fe779 100644 --- a/src/games/falloutnv/src/game_falloutNV_en.ts +++ b/src/games/falloutnv/src/game_falloutNV_en.ts @@ -61,20 +61,12 @@ QObject - - failed to deactivate BSA invalidation in "%1" (errorcode %2) - - - - + + + failed to activate BSA invalidation in "%1" (errorcode %2) - - - failed to set archive key (errorcode %1) - - Some of your plugins have invalid names! These plugins can not be loaded by the game. Please see mo_interface.log for a list of affected plugins and rename them. @@ -100,5 +92,10 @@ failed to query registry path (read): %1 + + + failed to set archive key in %1 (errorcode %2) + + From ee149888e0966de63530461d6a4a5a9718b2d747 Mon Sep 17 00:00:00 2001 From: LostDragonist Date: Wed, 12 Dec 2018 02:46:45 -0600 Subject: [PATCH 0675/1544] [game_oblivion] Update translation file --- src/games/oblivion/src/game_oblivion_en.ts | 19 ++++++++----------- 1 file changed, 8 insertions(+), 11 deletions(-) diff --git a/src/games/oblivion/src/game_oblivion_en.ts b/src/games/oblivion/src/game_oblivion_en.ts index 32d44e8f..db1588a9 100644 --- a/src/games/oblivion/src/game_oblivion_en.ts +++ b/src/games/oblivion/src/game_oblivion_en.ts @@ -61,20 +61,12 @@ QObject - - failed to deactivate BSA invalidation in "%1" (errorcode %2) - - - - + + + failed to activate BSA invalidation in "%1" (errorcode %2) - - - failed to set archive key (errorcode %1) - - Some of your plugins have invalid names! These plugins can not be loaded by the game. Please see mo_interface.log for a list of affected plugins and rename them. @@ -100,5 +92,10 @@ failed to query registry path (read): %1 + + + failed to set archive key in %1 (errorcode %2) + + From 4efe09389d4ab4177756bfe89edbbbc3a0442e24 Mon Sep 17 00:00:00 2001 From: LostDragonist Date: Wed, 12 Dec 2018 02:46:46 -0600 Subject: [PATCH 0676/1544] [game_skyrimse] Update translation file --- src/games/skyrimse/src/game_skyrimse_en.ts | 19 ++++++++----------- 1 file changed, 8 insertions(+), 11 deletions(-) diff --git a/src/games/skyrimse/src/game_skyrimse_en.ts b/src/games/skyrimse/src/game_skyrimse_en.ts index 53ae2864..6406d09f 100644 --- a/src/games/skyrimse/src/game_skyrimse_en.ts +++ b/src/games/skyrimse/src/game_skyrimse_en.ts @@ -77,20 +77,12 @@ - - failed to deactivate BSA invalidation in "%1" (errorcode %2) - - - - + + + failed to activate BSA invalidation in "%1" (errorcode %2) - - - failed to set archive key (errorcode %1) - - failed to open %1 @@ -101,5 +93,10 @@ wrong file format - expected %1 got %2 + + + failed to set archive key in %1 (errorcode %2) + + From 2812fcdb2488d54b395f01ff992a1aea91eb7179 Mon Sep 17 00:00:00 2001 From: LostDragonist Date: Wed, 12 Dec 2018 02:46:46 -0600 Subject: [PATCH 0677/1544] [game_skyrim] Update translation file --- src/games/skyrim/src/game_skyrim_en.ts | 19 ++++++++----------- 1 file changed, 8 insertions(+), 11 deletions(-) diff --git a/src/games/skyrim/src/game_skyrim_en.ts b/src/games/skyrim/src/game_skyrim_en.ts index a83e9525..4b6c5146 100644 --- a/src/games/skyrim/src/game_skyrim_en.ts +++ b/src/games/skyrim/src/game_skyrim_en.ts @@ -61,20 +61,12 @@ QObject - - failed to deactivate BSA invalidation in "%1" (errorcode %2) - - - - + + + failed to activate BSA invalidation in "%1" (errorcode %2) - - - failed to set archive key (errorcode %1) - - Some of your plugins have invalid names! These plugins can not be loaded by the game. Please see mo_interface.log for a list of affected plugins and rename them. @@ -100,5 +92,10 @@ failed to query registry path (read): %1 + + + failed to set archive key in %1 (errorcode %2) + + From 9796883f897683fe58d9fd2eb6486245c20fa160 Mon Sep 17 00:00:00 2001 From: LostDragonist Date: Wed, 12 Dec 2018 02:46:47 -0600 Subject: [PATCH 0678/1544] [game_skyrimvr] Update translation file --- src/games/skyrimvr/src/game_skyrimvr_en.ts | 19 ++++++++----------- 1 file changed, 8 insertions(+), 11 deletions(-) diff --git a/src/games/skyrimvr/src/game_skyrimvr_en.ts b/src/games/skyrimvr/src/game_skyrimvr_en.ts index 5c1f7ad8..ae573fa5 100644 --- a/src/games/skyrimvr/src/game_skyrimvr_en.ts +++ b/src/games/skyrimvr/src/game_skyrimvr_en.ts @@ -77,20 +77,12 @@ - - failed to deactivate BSA invalidation in "%1" (errorcode %2) - - - - + + + failed to activate BSA invalidation in "%1" (errorcode %2) - - - failed to set archive key (errorcode %1) - - failed to open %1 @@ -101,5 +93,10 @@ wrong file format - expected %1 got %2 + + + failed to set archive key in %1 (errorcode %2) + + From ffd043bd4f42105b177ee20686f7ed2bc0049483 Mon Sep 17 00:00:00 2001 From: LostDragonist Date: Wed, 12 Dec 2018 02:46:47 -0600 Subject: [PATCH 0679/1544] [game_ttw] Update translation file --- src/games/ttw/src/game_ttw_en.ts | 19 ++++++++----------- 1 file changed, 8 insertions(+), 11 deletions(-) diff --git a/src/games/ttw/src/game_ttw_en.ts b/src/games/ttw/src/game_ttw_en.ts index 70bdb785..cff8d84b 100644 --- a/src/games/ttw/src/game_ttw_en.ts +++ b/src/games/ttw/src/game_ttw_en.ts @@ -61,20 +61,12 @@ QObject - - failed to deactivate BSA invalidation in "%1" (errorcode %2) - - - - + + + failed to activate BSA invalidation in "%1" (errorcode %2) - - - failed to set archive key (errorcode %1) - - Some of your plugins have invalid names! These plugins can not be loaded by the game. Please see mo_interface.log for a list of affected plugins and rename them. @@ -100,5 +92,10 @@ failed to query registry path (read): %1 + + + failed to set archive key in %1 (errorcode %2) + + From 6019d45326f088c4313a940c0583be0072e8bb32 Mon Sep 17 00:00:00 2001 From: EntranceJew Date: Fri, 21 Dec 2018 15:53:50 -0500 Subject: [PATCH 0680/1544] [game_fallout76] Rename fallout4.qrc to fallout76.qrc --- src/games/fallout76/src/{fallout4.qrc => fallout76.qrc} | 0 1 file changed, 0 insertions(+), 0 deletions(-) rename src/games/fallout76/src/{fallout4.qrc => fallout76.qrc} (100%) diff --git a/src/games/fallout76/src/fallout4.qrc b/src/games/fallout76/src/fallout76.qrc similarity index 100% rename from src/games/fallout76/src/fallout4.qrc rename to src/games/fallout76/src/fallout76.qrc From d5de007d4dc9ac8f32f4551190e4d0a7a5c6300c Mon Sep 17 00:00:00 2001 From: EntranceJew Date: Sat, 22 Dec 2018 19:55:59 -0500 Subject: [PATCH 0681/1544] [game_fallout76] basic changes for fallout 76 to exist --- src/games/fallout76/CMakeLists.txt | 2 +- src/games/fallout76/src/CMakeLists.txt | 2 +- src/games/fallout76/src/SConscript | 4 +- .../fallout76/src/fallout4dataarchives.cpp | 57 ----- .../fallout76/src/fallout4dataarchives.h | 29 --- src/games/fallout76/src/fallout4savegame.h | 14 -- .../fallout76/src/fallout4savegameinfo.cpp | 19 -- .../fallout76/src/fallout4savegameinfo.h | 17 -- .../fallout76/src/fallout4scriptextender.cpp | 24 -- .../fallout76/src/fallout4unmanagedmods.cpp | 64 ------ src/games/fallout76/src/fallout76.qrc | 2 +- .../fallout76/src/fallout76dataarchives.cpp | 114 ++++++++++ .../fallout76/src/fallout76dataarchives.h | 35 +++ ...out4savegame.cpp => fallout76savegame.cpp} | 6 +- src/games/fallout76/src/fallout76savegame.h | 14 ++ .../fallout76/src/fallout76savegameinfo.cpp | 19 ++ .../fallout76/src/fallout76savegameinfo.h | 17 ++ .../fallout76/src/fallout76scriptextender.cpp | 24 ++ ...ptextender.h => fallout76scriptextender.h} | 10 +- .../fallout76/src/fallout76unmanagedmods.cpp | 46 ++++ ...managedmods.h => fallout76unmanagedmods.h} | 12 +- .../{gameFallout4.pro => gameFallout76.pro} | 28 +-- ...me_fallout4_en.ts => game_fallout76_en.ts} | 6 +- src/games/fallout76/src/gamefallout4.cpp | 205 ------------------ src/games/fallout76/src/gamefallout76.cpp | 203 +++++++++++++++++ .../src/{gamefallout4.h => gamefallout76.h} | 12 +- .../{gamefallout4.json => gamefallout76.json} | 0 27 files changed, 514 insertions(+), 471 deletions(-) delete mode 100644 src/games/fallout76/src/fallout4dataarchives.cpp delete mode 100644 src/games/fallout76/src/fallout4dataarchives.h delete mode 100644 src/games/fallout76/src/fallout4savegame.h delete mode 100644 src/games/fallout76/src/fallout4savegameinfo.cpp delete mode 100644 src/games/fallout76/src/fallout4savegameinfo.h delete mode 100644 src/games/fallout76/src/fallout4scriptextender.cpp delete mode 100644 src/games/fallout76/src/fallout4unmanagedmods.cpp create mode 100644 src/games/fallout76/src/fallout76dataarchives.cpp create mode 100644 src/games/fallout76/src/fallout76dataarchives.h rename src/games/fallout76/src/{fallout4savegame.cpp => fallout76savegame.cpp} (85%) create mode 100644 src/games/fallout76/src/fallout76savegame.h create mode 100644 src/games/fallout76/src/fallout76savegameinfo.cpp create mode 100644 src/games/fallout76/src/fallout76savegameinfo.h create mode 100644 src/games/fallout76/src/fallout76scriptextender.cpp rename src/games/fallout76/src/{fallout4scriptextender.h => fallout76scriptextender.h} (52%) create mode 100644 src/games/fallout76/src/fallout76unmanagedmods.cpp rename src/games/fallout76/src/{fallout4unmanagedmods.h => fallout76unmanagedmods.h} (54%) rename src/games/fallout76/src/{gameFallout4.pro => gameFallout76.pro} (63%) rename src/games/fallout76/src/{game_fallout4_en.ts => game_fallout76_en.ts} (96%) delete mode 100644 src/games/fallout76/src/gamefallout4.cpp create mode 100644 src/games/fallout76/src/gamefallout76.cpp rename src/games/fallout76/src/{gamefallout4.h => gamefallout76.h} (86%) rename src/games/fallout76/src/{gamefallout4.json => gamefallout76.json} (100%) diff --git a/src/games/fallout76/CMakeLists.txt b/src/games/fallout76/CMakeLists.txt index 40f51534..77aa297e 100644 --- a/src/games/fallout76/CMakeLists.txt +++ b/src/games/fallout76/CMakeLists.txt @@ -2,7 +2,7 @@ CMAKE_MINIMUM_REQUIRED(VERSION 2.8.12) ADD_COMPILE_OPTIONS($<$:/MP>) -SET(PROJ_NAME game_fallout4) +SET(PROJ_NAME game_fallout76) PROJECT(${PROJ_NAME}) diff --git a/src/games/fallout76/src/CMakeLists.txt b/src/games/fallout76/src/CMakeLists.txt index b5897bb7..3bf8c0a1 100644 --- a/src/games/fallout76/src/CMakeLists.txt +++ b/src/games/fallout76/src/CMakeLists.txt @@ -7,7 +7,7 @@ FILE(GLOB ${PROJ_NAME}_HDRS *.h) FILE(GLOB ${PROJ_NAME}_FORMS *.ui) SET(${PROJ_NAME}_QRCS - fallout4.qrc + fallout76.qrc ) SET(CMAKE_INCLUDE_CURRENT_DIR ON) diff --git a/src/games/fallout76/src/SConscript b/src/games/fallout76/src/SConscript index ebd2e920..23370aa0 100644 --- a/src/games/fallout76/src/SConscript +++ b/src/games/fallout76/src/SConscript @@ -3,11 +3,11 @@ Import('qt_env') env = qt_env.Clone() # Shouldn't this be GAMEFALLOUT3_LIBRARY -env.AppendUnique(CPPDEFINES = [ 'GAMEFALLOUT4_LIBRARY' ]) +env.AppendUnique(CPPDEFINES = [ 'GAMEFALLOUT76_LIBRARY' ]) env.RequiresGamebryo() -lib = env.SharedLibrary('gameFallout4', env.Glob('*.cpp')) +lib = env.SharedLibrary('gameFallout76', env.Glob('*.cpp')) env.InstallModule(lib) res = env['QT_USED_MODULES'] diff --git a/src/games/fallout76/src/fallout4dataarchives.cpp b/src/games/fallout76/src/fallout4dataarchives.cpp deleted file mode 100644 index 3cad8c96..00000000 --- a/src/games/fallout76/src/fallout4dataarchives.cpp +++ /dev/null @@ -1,57 +0,0 @@ -#include "fallout4dataarchives.h" - -#include "iprofile.h" -#include - -Fallout4DataArchives::Fallout4DataArchives(const QDir &myGamesDir) : - GamebryoDataArchives(myGamesDir) -{} - -QStringList Fallout4DataArchives::vanillaArchives() const -{ - return { "Fallout4 - Textures1.ba2" - , "Fallout4 - Textures2.ba2" - , "Fallout4 - Textures3.ba2" - , "Fallout4 - Textures4.ba2" - , "Fallout4 - Textures5.ba2" - , "Fallout4 - Textures6.ba2" - , "Fallout4 - Textures7.ba2" - , "Fallout4 - Textures8.ba2" - , "Fallout4 - Textures9.ba2" - , "Fallout4 - Meshes.ba2" - , "Fallout4 - MeshesExtra.ba2" - , "Fallout4 - Voices.ba2" - , "Fallout4 - Sounds.ba2" - , "Fallout4 - Interface.ba2" - , "Fallout4 - Animations.ba2" - , "Fallout4 - Materials.ba2" - , "Fallout4 - Shaders.ba2" - , "Fallout4 - Startup.ba2" - , "Fallout4 - Misc.ba2" }; -} - - -QStringList Fallout4DataArchives::archives(const MOBase::IProfile *profile) const -{ - QStringList result; - - QString iniFile = profile->localSettingsEnabled() ? QDir(profile->absolutePath()).absoluteFilePath("fallout4.ini") : m_LocalGameDir.absoluteFilePath("fallout4.ini"); - result.append(getArchivesFromKey(iniFile, "SResourceArchiveList")); - result.append(getArchivesFromKey(iniFile, "SResourceArchiveList2")); - - return result; -} - -void Fallout4DataArchives::writeArchiveList(MOBase::IProfile *profile, const QStringList &before) -{ - QString list = before.join(", "); - - QString iniFile = profile->localSettingsEnabled() ? QDir(profile->absolutePath()).absoluteFilePath("fallout4.ini") : m_LocalGameDir.absoluteFilePath("fallout4.ini"); - if (list.length() > 255) { - int splitIdx = list.lastIndexOf(",", 256); - setArchivesToKey(iniFile, "SResourceArchiveList", list.mid(0, splitIdx)); - setArchivesToKey(iniFile, "SResourceArchiveList2", list.mid(splitIdx + 2)); - } else { - setArchivesToKey(iniFile, "SResourceArchiveList", list); - } -} diff --git a/src/games/fallout76/src/fallout4dataarchives.h b/src/games/fallout76/src/fallout4dataarchives.h deleted file mode 100644 index b6abd173..00000000 --- a/src/games/fallout76/src/fallout4dataarchives.h +++ /dev/null @@ -1,29 +0,0 @@ -#ifndef FALLOUT4DATAARCHIVES_H -#define FALLOUT4DATAARCHIVES_H - -#include "gamebryodataarchives.h" - -namespace MOBase { class IProfile; } - -#include -#include - -class Fallout4DataArchives : public GamebryoDataArchives -{ - -public: - - Fallout4DataArchives(const QDir &myGamesDir); - -public: - - 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 // FALLOUT4DATAARCHIVES_H diff --git a/src/games/fallout76/src/fallout4savegame.h b/src/games/fallout76/src/fallout4savegame.h deleted file mode 100644 index 98dffc9f..00000000 --- a/src/games/fallout76/src/fallout4savegame.h +++ /dev/null @@ -1,14 +0,0 @@ -#ifndef FALLOUT4SAVEGAME_H -#define FALLOUT4SAVEGAME_H - -#include "gamebryosavegame.h" - -namespace MOBase { class IPluginGame; } - -class Fallout4SaveGame : public GamebryoSaveGame -{ -public: - Fallout4SaveGame(QString const &fileName, MOBase::IPluginGame const *game, bool const lightEnabled = true); -}; - -#endif // FALLOUT4SAVEGAME_H diff --git a/src/games/fallout76/src/fallout4savegameinfo.cpp b/src/games/fallout76/src/fallout4savegameinfo.cpp deleted file mode 100644 index 22856d86..00000000 --- a/src/games/fallout76/src/fallout4savegameinfo.cpp +++ /dev/null @@ -1,19 +0,0 @@ -#include "fallout4savegameinfo.h" - -#include "fallout4savegame.h" -#include "gamegamebryo.h" - -Fallout4SaveGameInfo::Fallout4SaveGameInfo(GameGamebryo const *game) : - GamebryoSaveGameInfo(game) -{ -} - -Fallout4SaveGameInfo::~Fallout4SaveGameInfo() -{ -} - -const MOBase::ISaveGame *Fallout4SaveGameInfo::getSaveGameInfo(const QString &file) const -{ - return new Fallout4SaveGame(file, m_Game); -} - diff --git a/src/games/fallout76/src/fallout4savegameinfo.h b/src/games/fallout76/src/fallout4savegameinfo.h deleted file mode 100644 index c36ec6f4..00000000 --- a/src/games/fallout76/src/fallout4savegameinfo.h +++ /dev/null @@ -1,17 +0,0 @@ -#ifndef SKYRIMSAVEGAMEINFO_H -#define SKYRIMSAVEGAMEINFO_H - -#include "gamebryosavegameinfo.h" - -class GameGamebryo; - -class Fallout4SaveGameInfo : public GamebryoSaveGameInfo -{ -public: - Fallout4SaveGameInfo(GameGamebryo const *game); - ~Fallout4SaveGameInfo(); - - virtual MOBase::ISaveGame const *getSaveGameInfo(QString const &file) const override; -}; - -#endif // SKYRIMSAVEGAMEINFO_H diff --git a/src/games/fallout76/src/fallout4scriptextender.cpp b/src/games/fallout76/src/fallout4scriptextender.cpp deleted file mode 100644 index 21c930c9..00000000 --- a/src/games/fallout76/src/fallout4scriptextender.cpp +++ /dev/null @@ -1,24 +0,0 @@ -#include "fallout4scriptextender.h" - -#include -#include - -Fallout4ScriptExtender::Fallout4ScriptExtender(GameGamebryo const *game) : - GamebryoScriptExtender(game) -{ -} - -QString Fallout4ScriptExtender::BinaryName() const -{ - return "f4se_loader.exe"; -} - -QString Fallout4ScriptExtender::PluginPath() const -{ - return "f4se/plugins"; -} - -QStringList Fallout4ScriptExtender::saveGameAttachmentExtensions() const -{ - return { }; -} diff --git a/src/games/fallout76/src/fallout4unmanagedmods.cpp b/src/games/fallout76/src/fallout4unmanagedmods.cpp deleted file mode 100644 index 5007c4f7..00000000 --- a/src/games/fallout76/src/fallout4unmanagedmods.cpp +++ /dev/null @@ -1,64 +0,0 @@ -#include "fallout4unmanagedmods.h" - - -Fallout4UnmangedMods::Fallout4UnmangedMods(const GameGamebryo *game) - : GamebryoUnmangedMods(game) -{} - -Fallout4UnmangedMods::~Fallout4UnmangedMods() -{} - -QStringList Fallout4UnmangedMods::mods(bool onlyOfficial) const { - QStringList result; - - QStringList pluginList = game()->primaryPlugins(); - QStringList otherPlugins = game()->DLCPlugins(); - otherPlugins.append(game()->CCPlugins()); - for (QString plugin : otherPlugins) { - pluginList.removeAll(plugin); - } - QDir dataDir(game()->dataDirectory()); - for (const QString &fileName : dataDir.entryList({ "*.esp", "*.esl", "*.esm" })) { - if (!pluginList.contains(fileName, Qt::CaseInsensitive)) { - if (!onlyOfficial || pluginList.contains(fileName, Qt::CaseInsensitive)) { - QFileInfo file(fileName); - result.append(file.baseName()); - } - } - } - - return result; -} - -QStringList Fallout4UnmangedMods::secondaryFiles(const QString &modName) const { - // file extension in FO4 is .ba2 instead of bsa - QStringList archives; - QDir dataDir = game()->dataDirectory(); - for (const QString &archiveName : dataDir.entryList({modName + "*.ba2"})) { - archives.append(dataDir.absoluteFilePath(archiveName)); - } - return archives; -} - -QString Fallout4UnmangedMods::displayName(const QString &modName) const -{ - // unlike in earlier games, in fallout 4 the file name doesn't correspond to - // the public name - if (modName.compare("dlcrobot", Qt::CaseInsensitive) == 0) { - return "Automatron"; - } else if (modName.compare("dlcworkshop01", Qt::CaseInsensitive) == 0) { - return "Wasteland Workshop"; - } else if (modName.compare("dlccoast", Qt::CaseInsensitive) == 0) { - return "Far Harbor"; - } else if (modName.compare("dlcworkshop02", Qt::CaseInsensitive) == 0) { - return "Contraptions Workshop"; - } else if (modName.compare("dlcworkshop03", Qt::CaseInsensitive) == 0) { - return "Vault-Tec Workshop"; - } else if (modName.compare("dlcnukaworld", Qt::CaseInsensitive) == 0) { - return "Nuka-World"; - } else if (modName.compare("dlcultrahighresolution", Qt::CaseInsensitive) == 0) { - return "Ultra High Resolution Texture Pack"; - } else { - return modName; - } -} diff --git a/src/games/fallout76/src/fallout76.qrc b/src/games/fallout76/src/fallout76.qrc index c8e52145..de54646e 100644 --- a/src/games/fallout76/src/fallout76.qrc +++ b/src/games/fallout76/src/fallout76.qrc @@ -1,5 +1,5 @@ - + splash.png diff --git a/src/games/fallout76/src/fallout76dataarchives.cpp b/src/games/fallout76/src/fallout76dataarchives.cpp new file mode 100644 index 00000000..03c4c88b --- /dev/null +++ b/src/games/fallout76/src/fallout76dataarchives.cpp @@ -0,0 +1,114 @@ +#include "fallout76dataarchives.h" + +#include "iprofile.h" +#include + +Fallout76DataArchives::Fallout76DataArchives(const QDir &myGamesDir) : + GamebryoDataArchives(myGamesDir) +{} + +QStringList Fallout76DataArchives::vanillaArchives() const +{ + return { "SeventySix - Animations.ba2" + , "SeventySix - ATX_Main.ba2" + , "SeventySix - ATX_Textures.ba2" + , "SeventySix - EnlightenExteriors01.ba2" + , "SeventySix - EnlightenExteriors02.ba2" + , "SeventySix - EnlightenInteriors.ba2" + , "SeventySix - GeneratedMeshes.ba2" + , "SeventySix - GeneratedTextures.ba2" + , "SeventySix - Interface.ba2" + , "SeventySix - Localization.ba2" + , "SeventySix - Materials.ba2" + , "SeventySix - Meshes01.ba2" + , "SeventySix - Meshes02.ba2" + , "SeventySix - MeshesExtra.ba2" + , "SeventySix - MiscClient.ba2" + , "SeventySix - Shaders.ba2" + , "SeventySix - Sounds01.ba2" + , "SeventySix - Sounds02.ba2" + , "SeventySix - Startup.ba2" + , "SeventySix - Textures01.ba2" + , "SeventySix - Textures02.ba2" + , "SeventySix - Textures03.ba2" + , "SeventySix - Textures04.ba2" + , "SeventySix - Textures05.ba2" + , "SeventySix - Textures06.ba2" + , "SeventySix - Voices.ba2" }; +} + +QStringList Fallout76DataArchives::sResourceIndexFileList() const +{ + return { "SeventySix - Textures01.ba2" + , "SeventySix - Textures02.ba2" + , "SeventySix - Textures03.ba2" + , "SeventySix - Textures04.ba2" + , "SeventySix - Textures05.ba2" + , "SeventySix - Textures06.ba2" }; +} + +QStringList Fallout76DataArchives::sResourceStartUpArchiveList() const +{ + return { "SeventySix - Interface.ba2" + , "SeventySix - Localization.ba2" + , "SeventySix - Shaders.ba2" + , "SeventySix - Startup.ba2" }; +} + +QStringList Fallout76DataArchives::SResourceArchiveList() const { + return { "SeventySix - GeneratedMeshes.ba2" + , "SeventySix - Materials.ba2" + , "SeventySix - Meshes01.ba2" + , "SeventySix - Meshes02.ba2" + , "SeventySix - MeshesExtra.ba2" + , "SeventySix - MiscClient.ba2" + , "SeventySix - Sounds01.ba2" + , "SeventySix - Sounds02.ba2" + , "SeventySix - Startup.ba2" + , "SeventySix - Voices.ba2" }; +} + +QStringList Fallout76DataArchives::SResourceArchiveList2() const { + return { "SeventySix - Animations.ba2" + , "SeventySix - EnlightenInteriors.ba2" + , "SeventySix - GeneratedTextures.ba2" + , "SeventySix - EnlightenExteriors01.ba2" + , "SeventySix - EnlightenExteriors02.ba2" }; +} + +QStringList Fallout76DataArchives::SResourceArchiveMemoryCacheList() const { + return { "SeventySix - Interface.ba2" + , "SeventySix - Materials.ba2" + , "SeventySix - MiscClient.ba2" + , "SeventySix - Shaders.ba2" }; +} + +QStringList Fallout76DataArchives::sResourceArchive2List() const { + return { "SeventySix - ATX_Main.ba2" + , "SeventySix - ATX_Textures.ba2" }; +} + +QStringList Fallout76DataArchives::archives(const MOBase::IProfile *profile) const +{ + QStringList result; + + QString iniFile = profile->localSettingsEnabled() ? QDir(profile->absolutePath()).absoluteFilePath("Fallout76.ini") : m_LocalGameDir.absoluteFilePath("Fallout76.ini"); + result.append(getArchivesFromKey(iniFile, "SResourceArchiveList")); + result.append(getArchivesFromKey(iniFile, "SResourceArchiveList2")); + + return result; +} + +void Fallout76DataArchives::writeArchiveList(MOBase::IProfile *profile, const QStringList &before) +{ + QString list = before.join(", "); + + QString iniFile = profile->localSettingsEnabled() ? QDir(profile->absolutePath()).absoluteFilePath("Fallout76.ini") : m_LocalGameDir.absoluteFilePath("Fallout76.ini"); +// if (list.length() > 255) { +// int splitIdx = list.lastIndexOf(",", 256); +// setArchivesToKey(iniFile, "SResourceArchiveList", list.mid(0, splitIdx)); +// setArchivesToKey(iniFile, "SResourceArchiveList2", list.mid(splitIdx + 2)); +// } else { + setArchivesToKey(iniFile, "sResourceArchive2List", list); +// } +} diff --git a/src/games/fallout76/src/fallout76dataarchives.h b/src/games/fallout76/src/fallout76dataarchives.h new file mode 100644 index 00000000..df7c49b4 --- /dev/null +++ b/src/games/fallout76/src/fallout76dataarchives.h @@ -0,0 +1,35 @@ +#ifndef FALLOUT76DATAARCHIVES_H +#define FALLOUT76DATAARCHIVES_H + +#include "gamebryodataarchives.h" + +namespace MOBase { class IProfile; } + +#include +#include + +class Fallout76DataArchives : public GamebryoDataArchives +{ + +public: + + Fallout76DataArchives(const QDir &myGamesDir); + +public: + + virtual QStringList vanillaArchives() const override; + virtual QStringList Fallout76DataArchives::sResourceIndexFileList() const; + virtual QStringList Fallout76DataArchives::sResourceStartUpArchiveList() const; + virtual QStringList Fallout76DataArchives::SResourceArchiveList() const; + virtual QStringList Fallout76DataArchives::SResourceArchiveList2() const; + virtual QStringList Fallout76DataArchives::SResourceArchiveMemoryCacheList() const; + virtual QStringList Fallout76DataArchives::sResourceArchive2List() const; + virtual QStringList archives(const MOBase::IProfile *profile) const override; + +private: + + virtual void writeArchiveList(MOBase::IProfile *profile, const QStringList &before) override; + +}; + +#endif // FALLOUT76DATAARCHIVES_H diff --git a/src/games/fallout76/src/fallout4savegame.cpp b/src/games/fallout76/src/fallout76savegame.cpp similarity index 85% rename from src/games/fallout76/src/fallout4savegame.cpp rename to src/games/fallout76/src/fallout76savegame.cpp index 429cf1cc..99141164 100644 --- a/src/games/fallout76/src/fallout4savegame.cpp +++ b/src/games/fallout76/src/fallout76savegame.cpp @@ -1,11 +1,11 @@ -#include "fallout4savegame.h" +#include "fallout76savegame.h" #include -Fallout4SaveGame::Fallout4SaveGame(QString const &fileName, MOBase::IPluginGame const *game, bool const lightEnabled) : +Fallout76SaveGame::Fallout76SaveGame(QString const &fileName, MOBase::IPluginGame const *game, bool const lightEnabled) : GamebryoSaveGame(fileName, game, lightEnabled) { - FileWrapper file(this, "FO4_SAVEGAME"); + FileWrapper file(this, "FO76_SAVEGAME"); file.skip(); // header size file.skip(); // header version file.read(m_SaveNumber); diff --git a/src/games/fallout76/src/fallout76savegame.h b/src/games/fallout76/src/fallout76savegame.h new file mode 100644 index 00000000..e015f18c --- /dev/null +++ b/src/games/fallout76/src/fallout76savegame.h @@ -0,0 +1,14 @@ +#ifndef FALLOUT76SAVEGAME_H +#define FALLOUT76SAVEGAME_H + +#include "gamebryosavegame.h" + +namespace MOBase { class IPluginGame; } + +class Fallout76SaveGame : public GamebryoSaveGame +{ +public: + Fallout76SaveGame(QString const &fileName, MOBase::IPluginGame const *game, bool const lightEnabled = true); +}; + +#endif // FALLOUT76SAVEGAME_H diff --git a/src/games/fallout76/src/fallout76savegameinfo.cpp b/src/games/fallout76/src/fallout76savegameinfo.cpp new file mode 100644 index 00000000..e0417e84 --- /dev/null +++ b/src/games/fallout76/src/fallout76savegameinfo.cpp @@ -0,0 +1,19 @@ +#include "fallout76savegameinfo.h" + +#include "fallout76savegame.h" +#include "gamegamebryo.h" + +Fallout76SaveGameInfo::Fallout76SaveGameInfo(GameGamebryo const *game) : + GamebryoSaveGameInfo(game) +{ +} + +Fallout76SaveGameInfo::~Fallout76SaveGameInfo() +{ +} + +const MOBase::ISaveGame *Fallout76SaveGameInfo::getSaveGameInfo(const QString &file) const +{ + return new Fallout76SaveGame(file, m_Game); +} + diff --git a/src/games/fallout76/src/fallout76savegameinfo.h b/src/games/fallout76/src/fallout76savegameinfo.h new file mode 100644 index 00000000..9922b1de --- /dev/null +++ b/src/games/fallout76/src/fallout76savegameinfo.h @@ -0,0 +1,17 @@ +#ifndef FALLOUT76SAVEGAMEINFO_H +#define FALLOUT76SAVEGAMEINFO_H + +#include "gamebryosavegameinfo.h" + +class GameGamebryo; + +class Fallout76SaveGameInfo : public GamebryoSaveGameInfo +{ +public: + Fallout76SaveGameInfo(GameGamebryo const *game); + ~Fallout76SaveGameInfo(); + + virtual MOBase::ISaveGame const *getSaveGameInfo(QString const &file) const override; +}; + +#endif // FALLOUT76SAVEGAMEINFO_H diff --git a/src/games/fallout76/src/fallout76scriptextender.cpp b/src/games/fallout76/src/fallout76scriptextender.cpp new file mode 100644 index 00000000..90f0855a --- /dev/null +++ b/src/games/fallout76/src/fallout76scriptextender.cpp @@ -0,0 +1,24 @@ +#include "fallout76scriptextender.h" + +#include +#include + +Fallout76ScriptExtender::Fallout76ScriptExtender(GameGamebryo const *game) : + GamebryoScriptExtender(game) +{ +} + +QString Fallout76ScriptExtender::BinaryName() const +{ + return "f76se_loader.exe"; +} + +QString Fallout76ScriptExtender::PluginPath() const +{ + return "f76se/plugins"; +} + +QStringList Fallout76ScriptExtender::saveGameAttachmentExtensions() const +{ + return { }; +} diff --git a/src/games/fallout76/src/fallout4scriptextender.h b/src/games/fallout76/src/fallout76scriptextender.h similarity index 52% rename from src/games/fallout76/src/fallout4scriptextender.h rename to src/games/fallout76/src/fallout76scriptextender.h index 4c134276..1a0e7c6d 100644 --- a/src/games/fallout76/src/fallout4scriptextender.h +++ b/src/games/fallout76/src/fallout76scriptextender.h @@ -1,14 +1,14 @@ -#ifndef FALLOUT4SCRIPTEXTENDER_H -#define FALLOUT4SCRIPTEXTENDER_H +#ifndef FALLOUT76SCRIPTEXTENDER_H +#define FALLOUT76SCRIPTEXTENDER_H #include "gamebryoscriptextender.h" class GameGamebryo; -class Fallout4ScriptExtender : public GamebryoScriptExtender +class Fallout76ScriptExtender : public GamebryoScriptExtender { public: - Fallout4ScriptExtender(GameGamebryo const *game); + Fallout76ScriptExtender(GameGamebryo const *game); virtual QString BinaryName() const override; virtual QString PluginPath() const override; @@ -17,4 +17,4 @@ public: }; -#endif // FALLOUT4SCRIPTEXTENDER_H +#endif // FALLOUT76SCRIPTEXTENDER_H diff --git a/src/games/fallout76/src/fallout76unmanagedmods.cpp b/src/games/fallout76/src/fallout76unmanagedmods.cpp new file mode 100644 index 00000000..3eb4f450 --- /dev/null +++ b/src/games/fallout76/src/fallout76unmanagedmods.cpp @@ -0,0 +1,46 @@ +#include "fallout76unmanagedmods.h" + + +Fallout76UnmangedMods::Fallout76UnmangedMods(const GameGamebryo *game) + : GamebryoUnmangedMods(game) +{} + +Fallout76UnmangedMods::~Fallout76UnmangedMods() +{} + +QStringList Fallout76UnmangedMods::mods(bool onlyOfficial) const { + QStringList result; + + QStringList pluginList = game()->primaryPlugins(); + QStringList otherPlugins = game()->DLCPlugins(); + otherPlugins.append(game()->CCPlugins()); + for (QString plugin : otherPlugins) { + pluginList.removeAll(plugin); + } + QDir dataDir(game()->dataDirectory()); + for (const QString &fileName : dataDir.entryList({ "*.esp", "*.esl", "*.esm" })) { + if (!pluginList.contains(fileName, Qt::CaseInsensitive)) { + if (!onlyOfficial || pluginList.contains(fileName, Qt::CaseInsensitive)) { + QFileInfo file(fileName); + result.append(file.baseName()); + } + } + } + + return result; +} + +QStringList Fallout76UnmangedMods::secondaryFiles(const QString &modName) const { + // file extension in FO76 is .ba2 instead of bsa + QStringList archives; + QDir dataDir = game()->dataDirectory(); + for (const QString &archiveName : dataDir.entryList({modName + "*.ba2"})) { + archives.append(dataDir.absoluteFilePath(archiveName)); + } + return archives; +} + +QString Fallout76UnmangedMods::displayName(const QString &modName) const +{ + return modName; +} diff --git a/src/games/fallout76/src/fallout4unmanagedmods.h b/src/games/fallout76/src/fallout76unmanagedmods.h similarity index 54% rename from src/games/fallout76/src/fallout4unmanagedmods.h rename to src/games/fallout76/src/fallout76unmanagedmods.h index aaa97e56..f0d6f947 100644 --- a/src/games/fallout76/src/fallout4unmanagedmods.h +++ b/src/games/fallout76/src/fallout76unmanagedmods.h @@ -1,15 +1,15 @@ -#ifndef FALLOUT4UNMANAGEDMODS_H -#define FALLOUT4UNMANAGEDMODS_H +#ifndef FALLOUT76UNMANAGEDMODS_H +#define FALLOUT76UNMANAGEDMODS_H #include "gamebryounmanagedmods.h" #include -class Fallout4UnmangedMods : public GamebryoUnmangedMods { +class Fallout76UnmangedMods : public GamebryoUnmangedMods { public: - Fallout4UnmangedMods(const GameGamebryo *game); - ~Fallout4UnmangedMods(); + Fallout76UnmangedMods(const GameGamebryo *game); + ~Fallout76UnmangedMods(); virtual QStringList mods(bool onlyOfficial) const override; virtual QStringList secondaryFiles(const QString &modName) const override; @@ -18,4 +18,4 @@ public: -#endif // FALLOUT4UNMANAGEDMODS_H +#endif // FALLOUT76UNMANAGEDMODS_H diff --git a/src/games/fallout76/src/gameFallout4.pro b/src/games/fallout76/src/gameFallout76.pro similarity index 63% rename from src/games/fallout76/src/gameFallout4.pro rename to src/games/fallout76/src/gameFallout76.pro index f78bc45f..674f4073 100644 --- a/src/games/fallout76/src/gameFallout4.pro +++ b/src/games/fallout76/src/gameFallout76.pro @@ -11,21 +11,21 @@ TEMPLATE = lib CONFIG += plugins CONFIG += dll -DEFINES += GAMEFALLOUT4_LIBRARY +DEFINES += GAMEFALLOUT76_LIBRARY -SOURCES += gamefallout4.cpp \ - fallout4bsainvalidation.cpp \ - fallout4scriptextender.cpp \ - fallout4dataarchives.cpp \ - fallout4savegame.cpp \ - fallout4savegameinfo.cpp +SOURCES += gamefallout76.cpp \ + fallout76bsainvalidation.cpp \ + fallout76scriptextender.cpp \ + fallout76dataarchives.cpp \ + fallout76savegame.cpp \ + fallout76savegameinfo.cpp -HEADERS += gamefallout4.h \ - fallout4bsainvalidation.h \ - fallout4scriptextender.h \ - fallout4dataarchives.h \ - fallout4savegame.h \ - fallout4savegameinfo.h +HEADERS += gamefallout76.h \ + fallout76bsainvalidation.h \ + fallout76scriptextender.h \ + fallout76dataarchives.h \ + fallout76savegame.h \ + fallout76savegameinfo.h CONFIG(debug, debug|release) { LIBS += -L"$${OUT_PWD}/../gameGamebryo/debug" @@ -44,7 +44,7 @@ INCLUDEPATH += "$${BOOSTPATH}" "$${PWD}/../gamefeatures" "$${PWD}/../gamegamebry LIBS += -ladvapi32 -lole32 -lgameGamebryo OTHER_FILES += \ - gamefallout4.json\ + gamefallout76.json\ SConscript \ CMakeLists.txt diff --git a/src/games/fallout76/src/game_fallout4_en.ts b/src/games/fallout76/src/game_fallout76_en.ts similarity index 96% rename from src/games/fallout76/src/game_fallout4_en.ts rename to src/games/fallout76/src/game_fallout76_en.ts index 2aaf516f..de99c8d5 100644 --- a/src/games/fallout76/src/game_fallout4_en.ts +++ b/src/games/fallout76/src/game_fallout76_en.ts @@ -2,10 +2,10 @@ - GameFallout4 + GameFallout76 - - Adds support for the game Fallout 4. + + Adds support for the game Fallout 76. Splash by %1 diff --git a/src/games/fallout76/src/gamefallout4.cpp b/src/games/fallout76/src/gamefallout4.cpp deleted file mode 100644 index ad4a4f02..00000000 --- a/src/games/fallout76/src/gamefallout4.cpp +++ /dev/null @@ -1,205 +0,0 @@ -#include "gameFallout4.h" - -#include "fallout4dataarchives.h" -#include "fallout4scriptextender.h" -#include "fallout4savegameinfo.h" -#include "fallout4unmanagedmods.h" - -#include -#include -#include -#include -#include "versioninfo.h" - -#include -#include -#include -#include -#include -#include -#include - -#include - -#include "scopeguard.h" - -using namespace MOBase; - -GameFallout4::GameFallout4() -{ -} - -bool GameFallout4::init(IOrganizer *moInfo) -{ - if (!GameGamebryo::init(moInfo)) { - return false; - } - - registerFeature(new Fallout4ScriptExtender(this)); - registerFeature(new Fallout4DataArchives(myGamesPath())); - registerFeature(new GamebryoLocalSavegames(myGamesPath(), "Fallout4.ini")); - registerFeature(new Fallout4SaveGameInfo(this)); - registerFeature(new CreationGamePlugins(moInfo)); - registerFeature(new Fallout4UnmangedMods(this)); - - return true; -} - -QString GameFallout4::gameName() const -{ - return "Fallout 4"; -} - -QList GameFallout4::executables() const -{ - return QList() - << ExecutableInfo("F4SE", findInGameFolder(feature()->loaderName())) - << ExecutableInfo("Fallout 4", findInGameFolder(binaryName())) - << ExecutableInfo("Fallout Launcher", findInGameFolder(getLauncherName())) - << ExecutableInfo("Creation Kit", findInGameFolder("CreationKit.exe")) - << ExecutableInfo("LOOT", getLootPath()).withArgument("--game=\"Fallout4\"") - ; -} - -QString GameFallout4::name() const -{ - return "Fallout 4 Support Plugin"; -} - -QString GameFallout4::author() const -{ - return "Tannin"; -} - -QString GameFallout4::description() const -{ - return tr("Adds support for the game Fallout 4.\n" - "Splash by %1").arg("nekoyoubi"); -} - -MOBase::VersionInfo GameFallout4::version() const -{ - return VersionInfo(1, 3, 0, VersionInfo::RELEASE_FINAL); -} - -bool GameFallout4::isActive() const -{ - return qApp->property("managed_game").value() == this; -} - -QList GameFallout4::settings() const -{ - return QList(); -} - -void GameFallout4::initializeProfile(const QDir &path, ProfileSettings settings) const -{ - if (settings.testFlag(IPluginGame::MODS)) { - copyToProfile(localAppFolder() + "/Fallout4", path, "plugins.txt"); - copyToProfile(localAppFolder() + "/Fallout4", path, "loadorder.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 GameFallout4::savegameExtension() const -{ - return "fos"; -} - -QString GameFallout4::savegameSEExtension() const -{ - return "f4se"; -} - -QString GameFallout4::steamAPPId() const -{ - return "377160"; -} - -QStringList GameFallout4::primaryPlugins() const { - QStringList plugins = {"fallout4.esm", "dlcrobot.esm", "dlcworkshop01.esm", "dlccoast.esm", "dlcworkshop02.esm", - "dlcworkshop03.esm", "dlcnukaworld.esm", "dlcultrahighresolution.esm"}; - - plugins.append(CCPlugins()); - - return plugins; -} - -QStringList GameFallout4::gameVariants() const -{ - return { "Regular" }; -} - -QString GameFallout4::gameShortName() const -{ - return "Fallout4"; -} - -QString GameFallout4::gameNexusName() const -{ - return "Fallout4"; -} - -QStringList GameFallout4::iniFiles() const -{ - return { "fallout4.ini", "fallout4prefs.ini", "fallout4custom.ini" }; -} - -QStringList GameFallout4::DLCPlugins() const -{ - return {"dlcrobot.esm", "dlcworkshop01.esm", "dlccoast.esm", "dlcworkshop02.esm", "dlcworkshop03.esm", - "dlcnukaworld.esm", "dlcultrahighresolution.esm"}; -} - -QStringList GameFallout4::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::LoadOrderMechanism GameFallout4::loadOrderMechanism() const -{ - return IPluginGame::LoadOrderMechanism::PluginsTxt; -} - -int GameFallout4::nexusModOrganizerID() const -{ - return 28715; -} - -int GameFallout4::nexusGameID() const -{ - return 1151; -} diff --git a/src/games/fallout76/src/gamefallout76.cpp b/src/games/fallout76/src/gamefallout76.cpp new file mode 100644 index 00000000..a41164a0 --- /dev/null +++ b/src/games/fallout76/src/gamefallout76.cpp @@ -0,0 +1,203 @@ +#include "gameFallout76.h" + +#include "fallout76dataarchives.h" +#include "fallout76scriptextender.h" +#include "fallout76savegameinfo.h" +#include "fallout76unmanagedmods.h" + +#include +#include +#include +#include +#include "versioninfo.h" + +#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(new Fallout76ScriptExtender(this)); + registerFeature(new Fallout76DataArchives(myGamesPath())); + registerFeature(new GamebryoLocalSavegames(myGamesPath(), "Fallout76.ini")); + registerFeature(new Fallout76SaveGameInfo(this)); + registerFeature(new CreationGamePlugins(moInfo)); + registerFeature(new Fallout76UnmangedMods(this)); + + return true; +} + +QString GameFallout76::gameName() const +{ + return "Fallout 76"; +} + +QList GameFallout76::executables() const +{ + return QList() + << ExecutableInfo("F76SE", findInGameFolder(feature()->loaderName())) + << ExecutableInfo("Fallout 76", findInGameFolder(binaryName())) + << ExecutableInfo("Fallout Launcher", findInGameFolder(getLauncherName())) + << ExecutableInfo("Creation Kit", findInGameFolder("CreationKit.exe")) + << ExecutableInfo("LOOT", getLootPath()).withArgument("--game=\"Fallout76\"") + ; +} + +QString GameFallout76::name() const +{ + return "Fallout 76 Support Plugin"; +} + +QString GameFallout76::author() const +{ + return "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, 3, 0, VersionInfo::RELEASE_FINAL); +} + +bool GameFallout76::isActive() const +{ + return qApp->property("managed_game").value() == this; +} + +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 "bgs"; +} + +QString GameFallout76::savegameSEExtension() const +{ + return "f76se"; +} + +QString GameFallout76::steamAPPId() const +{ + return "n/a"; +} + +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::LoadOrderMechanism GameFallout76::loadOrderMechanism() const +{ + return IPluginGame::LoadOrderMechanism::PluginsTxt; +} + +int GameFallout76::nexusModOrganizerID() const +{ + return -1; +} + +int GameFallout76::nexusGameID() const +{ + return 2590; +} diff --git a/src/games/fallout76/src/gamefallout4.h b/src/games/fallout76/src/gamefallout76.h similarity index 86% rename from src/games/fallout76/src/gamefallout4.h rename to src/games/fallout76/src/gamefallout76.h index 60cbf083..45359932 100644 --- a/src/games/fallout76/src/gamefallout4.h +++ b/src/games/fallout76/src/gamefallout76.h @@ -1,5 +1,5 @@ -#ifndef GAMEFALLOUT4_H -#define GAMEFALLOUT4_H +#ifndef GAMEFALLOUT76_H +#define GAMEFALLOUT76_H #include "gamegamebryo.h" @@ -7,15 +7,15 @@ #include #include -class GameFallout4 : public GameGamebryo +class GameFallout76 : public GameGamebryo { Q_OBJECT - Q_PLUGIN_METADATA(IID "org.tannin.GameFallout4" FILE "gamefallout4.json") + Q_PLUGIN_METADATA(IID "in.ejew.GameFallout76" FILE "gamefallout76.json") public: - GameFallout4(); + GameFallout76(); virtual bool init(MOBase::IOrganizer *moInfo) override; @@ -49,4 +49,4 @@ public: // IPlugin interface }; -#endif // GAMEFallout4_H +#endif // GAMEFallout76_H diff --git a/src/games/fallout76/src/gamefallout4.json b/src/games/fallout76/src/gamefallout76.json similarity index 100% rename from src/games/fallout76/src/gamefallout4.json rename to src/games/fallout76/src/gamefallout76.json From f7c69fcf4cfa17a673e15f31d4f8d6180b11467d Mon Sep 17 00:00:00 2001 From: EntranceJew Date: Sun, 23 Dec 2018 12:00:15 -0500 Subject: [PATCH 0682/1544] [game_fallout76] potentially implements intelligent sorting of files based on ba2 keywords --- .../fallout76/src/fallout76dataarchives.cpp | 63 ++++++++++++++----- .../fallout76/src/fallout76dataarchives.h | 2 +- src/games/fallout76/src/gamefallout76.cpp | 12 ++-- 3 files changed, 54 insertions(+), 23 deletions(-) diff --git a/src/games/fallout76/src/fallout76dataarchives.cpp b/src/games/fallout76/src/fallout76dataarchives.cpp index 03c4c88b..e00bce76 100644 --- a/src/games/fallout76/src/fallout76dataarchives.cpp +++ b/src/games/fallout76/src/fallout76dataarchives.cpp @@ -55,6 +55,13 @@ QStringList Fallout76DataArchives::sResourceStartUpArchiveList() const , "SeventySix - Startup.ba2" }; } +QStringList Fallout76DataArchives::SResourceArchiveMemoryCacheList() const { + return { "SeventySix - Interface.ba2" + , "SeventySix - Materials.ba2" + , "SeventySix - MiscClient.ba2" + , "SeventySix - Shaders.ba2" }; +} + QStringList Fallout76DataArchives::SResourceArchiveList() const { return { "SeventySix - GeneratedMeshes.ba2" , "SeventySix - Materials.ba2" @@ -76,13 +83,6 @@ QStringList Fallout76DataArchives::SResourceArchiveList2() const { , "SeventySix - EnlightenExteriors02.ba2" }; } -QStringList Fallout76DataArchives::SResourceArchiveMemoryCacheList() const { - return { "SeventySix - Interface.ba2" - , "SeventySix - Materials.ba2" - , "SeventySix - MiscClient.ba2" - , "SeventySix - Shaders.ba2" }; -} - QStringList Fallout76DataArchives::sResourceArchive2List() const { return { "SeventySix - ATX_Main.ba2" , "SeventySix - ATX_Textures.ba2" }; @@ -93,22 +93,53 @@ QStringList Fallout76DataArchives::archives(const MOBase::IProfile *profile) con QStringList result; QString iniFile = profile->localSettingsEnabled() ? QDir(profile->absolutePath()).absoluteFilePath("Fallout76.ini") : m_LocalGameDir.absoluteFilePath("Fallout76.ini"); + + result.append(getArchivesFromKey(iniFile, "sResourceIndexFileList")); + result.append(getArchivesFromKey(iniFile, "sResourceStartUpArchiveList")); + result.append(getArchivesFromKey(iniFile, "SResourceArchiveMemoryCacheList")); result.append(getArchivesFromKey(iniFile, "SResourceArchiveList")); result.append(getArchivesFromKey(iniFile, "SResourceArchiveList2")); + result.append(getArchivesFromKey(iniFile, "sResourceArchive2List")); return result; } void Fallout76DataArchives::writeArchiveList(MOBase::IProfile *profile, const QStringList &before) { - QString list = before.join(", "); - QString iniFile = profile->localSettingsEnabled() ? QDir(profile->absolutePath()).absoluteFilePath("Fallout76.ini") : m_LocalGameDir.absoluteFilePath("Fallout76.ini"); -// if (list.length() > 255) { -// int splitIdx = list.lastIndexOf(",", 256); -// setArchivesToKey(iniFile, "SResourceArchiveList", list.mid(0, splitIdx)); -// setArchivesToKey(iniFile, "SResourceArchiveList2", list.mid(splitIdx + 2)); -// } else { - setArchivesToKey(iniFile, "sResourceArchive2List", list); -// } + + QStringList sResourceIndexFileList = {}; + QStringList sResourceStartUpArchiveList = {}; + QStringList SResourceArchiveMemoryCacheList = {}; + QStringList SResourceArchiveList = {}; + QStringList SResourceArchiveList2 = {}; + QStringList sResourceArchive2List = {}; + + for (int i = 0; i < before.size(); ++i) { + QString archive = before[i]; + if (archive.contains(QRegExp(" - Textures(\\d{2})\\.ba2$"))) { + sResourceIndexFileList.append(archive); + } else if (archive.contains(QRegExp(" - (Interface|Localization|Shaders|Startup)\\.ba2$"))) { + sResourceStartUpArchiveList.append(archive); + } else if (archive.contains(QRegExp(" - (Interface|Materials|MiscClient|Shaders)\\.ba2$"))) { + SResourceArchiveMemoryCacheList.append(archive); + } else if (archive.contains(QRegExp(" - (GeneratedMeshes|Materials|Meshes(\\d{2}|\\w+)?|MiscClient|Sounds\\d{2}|Startup|Voices)\\.ba2$"))) { + SResourceArchiveList.append(archive); + } else if (archive.contains(QRegExp(" - (Animations|Enlighten(Interiors|Exteriors\\d{2})|GeneratedTextures)\\.ba2$"))) { + SResourceArchiveList2.append(archive); + } else if (archive.contains(QRegExp(" - ATX_.*\\.ba2$"))) { + // if it is named after DLC, it has to go here + sResourceArchive2List.append(archive); + } else { + // if it did not fit any description above, it gets tacked on at the end + sResourceArchive2List.append(archive); + } + } + + setArchivesToKey(iniFile, "sResourceIndexFileList", sResourceIndexFileList.join(", ")); + setArchivesToKey(iniFile, "sResourceStartUpArchiveList", sResourceStartUpArchiveList.join(", ")); + setArchivesToKey(iniFile, "SResourceArchiveMemoryCacheList", SResourceArchiveMemoryCacheList.join(", ")); + setArchivesToKey(iniFile, "SResourceArchiveList", SResourceArchiveList.join(", ")); + setArchivesToKey(iniFile, "SResourceArchiveList2", SResourceArchiveList2.join(", ")); + setArchivesToKey(iniFile, "sResourceArchive2List", sResourceArchive2List.join(", ")); } diff --git a/src/games/fallout76/src/fallout76dataarchives.h b/src/games/fallout76/src/fallout76dataarchives.h index df7c49b4..9248c088 100644 --- a/src/games/fallout76/src/fallout76dataarchives.h +++ b/src/games/fallout76/src/fallout76dataarchives.h @@ -20,9 +20,9 @@ public: virtual QStringList vanillaArchives() const override; virtual QStringList Fallout76DataArchives::sResourceIndexFileList() const; virtual QStringList Fallout76DataArchives::sResourceStartUpArchiveList() const; + virtual QStringList Fallout76DataArchives::SResourceArchiveMemoryCacheList() const; virtual QStringList Fallout76DataArchives::SResourceArchiveList() const; virtual QStringList Fallout76DataArchives::SResourceArchiveList2() const; - virtual QStringList Fallout76DataArchives::SResourceArchiveMemoryCacheList() const; virtual QStringList Fallout76DataArchives::sResourceArchive2List() const; virtual QStringList archives(const MOBase::IProfile *profile) const override; diff --git a/src/games/fallout76/src/gamefallout76.cpp b/src/games/fallout76/src/gamefallout76.cpp index a41164a0..59062ca8 100644 --- a/src/games/fallout76/src/gamefallout76.cpp +++ b/src/games/fallout76/src/gamefallout76.cpp @@ -79,7 +79,7 @@ QString GameFallout76::description() const MOBase::VersionInfo GameFallout76::version() const { - return VersionInfo(1, 3, 0, VersionInfo::RELEASE_FINAL); + return VersionInfo(1, 0, 1, VersionInfo::RELEASE_FINAL); } bool GameFallout76::isActive() const @@ -101,14 +101,14 @@ void GameFallout76::initializeProfile(const QDir &path, ProfileSettings settings 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"); + || !QFileInfo(myGamesPath() + "/Fallout76.ini").exists()) { + copyToProfile(gameDirectory().absolutePath(), path, "Fallout76_default.ini", "Fallout76.ini"); } else { - copyToProfile(myGamesPath(), path, "fallout76.ini"); + copyToProfile(myGamesPath(), path, "Fallout76.ini"); } - copyToProfile(myGamesPath(), path, "fallout76prefs.ini"); - copyToProfile(myGamesPath(), path, "fallout76custom.ini"); + copyToProfile(myGamesPath(), path, "Fallout76Prefs.ini"); + copyToProfile(myGamesPath(), path, "Fallout76Custom.ini"); } } From 73b9c5a03a3892362b270da43b8d5901652a9a52 Mon Sep 17 00:00:00 2001 From: Al12rs Date: Sun, 23 Dec 2018 19:47:46 +0100 Subject: [PATCH 0683/1544] [game_skyrimse] Added skyrimcustom.ini support for SSE --- src/games/skyrimse/src/gameskyrimse.cpp | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/src/games/skyrimse/src/gameskyrimse.cpp b/src/games/skyrimse/src/gameskyrimse.cpp index 323562ef..6f464c0e 100644 --- a/src/games/skyrimse/src/gameskyrimse.cpp +++ b/src/games/skyrimse/src/gameskyrimse.cpp @@ -148,6 +148,7 @@ void GameSkyrimSE::initializeProfile(const QDir &path, ProfileSettings settings) } copyToProfile(myGamesPath(), path, "skyrimprefs.ini"); + copyToProfile(myGamesPath(), path, "skyrimcustom.ini"); } } @@ -196,7 +197,7 @@ QString GameSkyrimSE::gameNexusName() const QStringList GameSkyrimSE::iniFiles() const { - return{ "skyrim.ini", "skyrimprefs.ini" }; + return{ "skyrim.ini", "skyrimprefs.ini", "skyrimcustom.ini" }; } QStringList GameSkyrimSE::DLCPlugins() const From a3fa0faaa0b78c0eccb6d87371ed9e23809d6a28 Mon Sep 17 00:00:00 2001 From: LostDragonist Date: Wed, 26 Dec 2018 16:18:46 -0600 Subject: [PATCH 0684/1544] Use WriteRegistryValue function to handle read-only files --- src/gamebryo/gamebryobsainvalidation.cpp | 7 ++++--- src/gamebryo/gamebryodataarchives.cpp | 5 +++-- src/gamebryo/gamebryolocalsavegames.cpp | 17 +++++++++-------- 3 files changed, 16 insertions(+), 13 deletions(-) diff --git a/src/gamebryo/gamebryobsainvalidation.cpp b/src/gamebryo/gamebryobsainvalidation.cpp index 94d782ab..d1284ef3 100644 --- a/src/gamebryo/gamebryobsainvalidation.cpp +++ b/src/gamebryo/gamebryobsainvalidation.cpp @@ -6,6 +6,7 @@ #include #include #include +#include "registry.h" #include #include @@ -58,7 +59,7 @@ bool GamebryoBSAInvalidation::prepareProfile(MOBase::IProfile *profile) if (!::GetPrivateProfileStringW(L"Archive", L"bInvalidateOlderFiles", L"0", setting, MAX_PATH, iniFilePath.toStdWString().c_str()) || wcstol(setting, nullptr, 10) != 1) { dirty = true; - if (!::WritePrivateProfileStringW(L"Archive", L"bInvalidateOlderFiles", L"1", iniFilePath.toStdWString().c_str())) { + if (!MOBase::WriteRegistryValue(L"Archive", L"bInvalidateOlderFiles", L"1", iniFilePath.toStdWString().c_str())) { throw MOBase::MyException(QObject::tr("failed to activate BSA invalidation in \"%1\" (errorcode %2)").arg(m_IniFileName, ::GetLastError())); } } @@ -91,7 +92,7 @@ bool GamebryoBSAInvalidation::prepareProfile(MOBase::IProfile *profile) if (::GetPrivateProfileStringW(L"Archive", L"SInvalidationFile", L"ArchiveInvalidation.txt", setting, MAX_PATH, iniFilePath.toStdWString().c_str()) || wcscmp(setting, L"") != 0) { dirty = true; - if (!::WritePrivateProfileStringW(L"Archive", L"SInvalidationFile", L"", iniFilePath.toStdWString().c_str())) { + if (!MOBase::WriteRegistryValue(L"Archive", L"SInvalidationFile", L"", iniFilePath.toStdWString().c_str())) { throw MOBase::MyException(QObject::tr("failed to activate BSA invalidation in \"%1\" (errorcode %2)").arg(m_IniFileName, ::GetLastError())); } } @@ -117,7 +118,7 @@ bool GamebryoBSAInvalidation::prepareProfile(MOBase::IProfile *profile) if (!::GetPrivateProfileStringW(L"Archive", L"SInvalidationFile", L"", setting, MAX_PATH, iniFilePath.toStdWString().c_str()) || wcscmp(setting, L"ArchiveInvalidation.txt") != 0) { dirty = true; - if (!::WritePrivateProfileStringW(L"Archive", L"SInvalidationFile", L"ArchiveInvalidation.txt", iniFilePath.toStdWString().c_str())) { + if (!MOBase::WriteRegistryValue(L"Archive", L"SInvalidationFile", L"ArchiveInvalidation.txt", iniFilePath.toStdWString().c_str())) { throw MOBase::MyException(QObject::tr("failed to activate BSA invalidation in \"%1\" (errorcode %2)").arg(m_IniFileName, ::GetLastError())); } } diff --git a/src/gamebryo/gamebryodataarchives.cpp b/src/gamebryo/gamebryodataarchives.cpp index 2cb8dfbd..2b4370e8 100644 --- a/src/gamebryo/gamebryodataarchives.cpp +++ b/src/gamebryo/gamebryodataarchives.cpp @@ -1,4 +1,5 @@ #include "gamebryodataarchives.h" +#include "registry.h" #include #include @@ -31,7 +32,7 @@ QStringList GamebryoDataArchives::getArchivesFromKey(const QString &iniFile, con void GamebryoDataArchives::setArchivesToKey(const QString &iniFile, const QString &key, const QString &value) { - if (!::WritePrivateProfileStringW(L"Archive", key.toStdWString().c_str(), value.toStdWString().c_str(), iniFile.toStdWString().c_str())) { + if (!MOBase::WriteRegistryValue(L"Archive", key.toStdWString().c_str(), value.toStdWString().c_str(), iniFile.toStdWString().c_str())) { throw MOBase::MyException(QObject::tr("failed to set archive key in %1 (errorcode %2)").arg(iniFile).arg(errno)); } } @@ -57,4 +58,4 @@ void GamebryoDataArchives::removeArchive(MOBase::IProfile *profile, const QStrin current.removeAll(archiveName); writeArchiveList(profile, current); -} \ No newline at end of file +} diff --git a/src/gamebryo/gamebryolocalsavegames.cpp b/src/gamebryo/gamebryolocalsavegames.cpp index c63e55e0..5d8cadf7 100644 --- a/src/gamebryo/gamebryolocalsavegames.cpp +++ b/src/gamebryo/gamebryolocalsavegames.cpp @@ -18,6 +18,7 @@ Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA #include "gamebryolocalsavegames.h" +#include "registry.h" #include #include #include @@ -64,9 +65,9 @@ bool GamebryoLocalSavegames::prepareProfile(MOBase::IProfile *profile) GetPrivateProfileStringW(L"General", L"bUseMyGamesDirectory", NULL, oldMyGames, 1, iniFilePath.toStdWString().c_str()); if (enable && wcscmp(oldPath, L"") != 0 && wcscmp(oldPath, (LocalSavesDummy + "\\").toStdWString().c_str()) != 0) { dirty = true; - WritePrivateProfileStringW(L"General", L"SLocalSavePath", oldPath, QString(profile->absolutePath() + "/" + "savepath.ini").toStdWString().c_str()); + MOBase::WriteRegistryValue(L"General", L"SLocalSavePath", oldPath, QString(profile->absolutePath() + "/" + "savepath.ini").toStdWString().c_str()); if (wcscmp(oldMyGames, L"") != 0) { - WritePrivateProfileStringW(L"General", L"bUseMyGamesDirectory", oldMyGames, QString(profile->absolutePath() + "/" + "savepath.ini").toStdWString().c_str()); + MOBase::WriteRegistryValue(L"General", L"bUseMyGamesDirectory", oldMyGames, QString(profile->absolutePath() + "/" + "savepath.ini").toStdWString().c_str()); } } bool saved = false; @@ -92,13 +93,13 @@ bool GamebryoLocalSavegames::prepareProfile(MOBase::IProfile *profile) if (enable) { if (wcscmp(oldPath, (LocalSavesDummy + "\\").toStdWString().c_str()) != 0){ - WritePrivateProfileStringW(L"General", L"SLocalSavePath", + MOBase::WriteRegistryValue(L"General", L"SLocalSavePath", (LocalSavesDummy + "\\").toStdWString().c_str(), iniFilePath.toStdWString().c_str()); dirty = true; } if (wcscmp(oldMyGames, L"") != 0) { - WritePrivateProfileStringW(L"General", L"bUseMyGamesDirectory", + MOBase::WriteRegistryValue(L"General", L"bUseMyGamesDirectory", NULL, iniFilePath.toStdWString().c_str()); dirty = true; @@ -106,14 +107,14 @@ bool GamebryoLocalSavegames::prepareProfile(MOBase::IProfile *profile) } else { if (saved) { if (wcscmp(oldPath, savedPath) != 0) { - WritePrivateProfileStringW(L"General", L"SLocalSavePath", + MOBase::WriteRegistryValue(L"General", L"SLocalSavePath", savedPath, iniFilePath.toStdWString().c_str()); dirty = true; } } else { if (wcscmp(oldPath, L"") != 0) { - WritePrivateProfileStringW(L"General", L"SLocalSavePath", + MOBase::WriteRegistryValue(L"General", L"SLocalSavePath", NULL, iniFilePath.toStdWString().c_str()); dirty = true; @@ -121,14 +122,14 @@ bool GamebryoLocalSavegames::prepareProfile(MOBase::IProfile *profile) } if (savedDir) { if (wcscmp(oldMyGames, savedMyGames) != 0) { - WritePrivateProfileStringW(L"General", L"bUseMyGamesDirectory", + MOBase::WriteRegistryValue(L"General", L"bUseMyGamesDirectory", savedMyGames, iniFilePath.toStdWString().c_str()); dirty = true; } } else { if (wcscmp(oldMyGames, L"") != 0) { - WritePrivateProfileStringW(L"General", L"bUseMyGamesDirectory", + MOBase::WriteRegistryValue(L"General", L"bUseMyGamesDirectory", NULL, iniFilePath.toStdWString().c_str()); dirty = true; From 2c356fdb11d57d8c0bcc9484110aedfb567505f9 Mon Sep 17 00:00:00 2001 From: LostDragonist Date: Wed, 26 Dec 2018 16:18:46 -0600 Subject: [PATCH 0685/1544] [game_morrowind] Use WriteRegistryValue function to handle read-only files --- .../morrowind/src/morrowinddataarchives.cpp | 5 ++-- .../morrowind/src/morrowindgameplugins.cpp | 23 ++++++++++--------- 2 files changed, 15 insertions(+), 13 deletions(-) diff --git a/src/games/morrowind/src/morrowinddataarchives.cpp b/src/games/morrowind/src/morrowinddataarchives.cpp index aafde61a..a52b59c1 100644 --- a/src/games/morrowind/src/morrowinddataarchives.cpp +++ b/src/games/morrowind/src/morrowinddataarchives.cpp @@ -1,5 +1,6 @@ #include "morrowinddataarchives.h" #include +#include "registry.h" MorrowindDataArchives::MorrowindDataArchives(const QDir &myGamesDir) : GamebryoDataArchives(myGamesDir) @@ -33,11 +34,11 @@ QStringList MorrowindDataArchives::getArchives(const QString &iniFile) const void MorrowindDataArchives::setArchives(const QString &iniFile, const QStringList &list) { ::WritePrivateProfileSectionW(L"Archives", NULL, iniFile.toStdWString().c_str()); - + QString key = "Archive "; int writtenCount = 0; foreach(const QString &value, list) { - if (!::WritePrivateProfileStringW(L"Archives", (key+QString::number(writtenCount)).toStdWString().c_str(), value.toStdWString().c_str(), iniFile.toStdWString().c_str())) { + if (!MOBase::WriteRegistryValue(L"Archives", (key+QString::number(writtenCount)).toStdWString().c_str(), value.toStdWString().c_str(), iniFile.toStdWString().c_str())) { throw MOBase::MyException(QObject::tr("failed to set archive key (errorcode %1)").arg(errno)); } ++writtenCount; diff --git a/src/games/morrowind/src/morrowindgameplugins.cpp b/src/games/morrowind/src/morrowindgameplugins.cpp index d4236bbe..d91fdb90 100644 --- a/src/games/morrowind/src/morrowindgameplugins.cpp +++ b/src/games/morrowind/src/morrowindgameplugins.cpp @@ -6,6 +6,7 @@ #include #include #include +#include "registry.h" #include #include @@ -30,16 +31,16 @@ void MorrowindGamePlugins::writePluginLists(const IPluginList *pluginList) { if (organizer()->profile()->localSettingsEnabled()) { writePluginList( - pluginList, + pluginList, organizer()->profile()->absolutePath() + "/Morrowind.ini" - ); + ); } else { writePluginList( - pluginList, + pluginList, organizer()->managedGame()->gameDirectory().absolutePath() + "/Morrowind.ini" ); } - + writeLoadOrderList(pluginList, organizer()->profile()->absolutePath() + "/loadorder.txt"); @@ -83,12 +84,12 @@ void MorrowindGamePlugins::writePluginList(const MOBase::IPluginList *pluginList void MorrowindGamePlugins::writeList(const IPluginList *pluginList, const QString &filePath, bool loadOrder) { QTextCodec *textCodec = loadOrder ? utf8Codec() : localCodec(); - + ::WritePrivateProfileSectionW(L"Game Files", NULL, filePath.toStdWString().c_str()); - + bool invalidFileNames = false; int writtenCount = 0; - + QStringList plugins = pluginList->pluginNames(); std::sort(plugins.begin(), plugins.end(), [pluginList](const QString &lhs, const QString &rhs) { @@ -102,21 +103,21 @@ void MorrowindGamePlugins::writeList(const IPluginList *pluginList, invalidFileNames = true; qCritical("invalid plugin name %s", qPrintable(pluginName)); } else { - if (!::WritePrivateProfileStringW(L"Game Files", (key+QString::number(writtenCount)).toStdWString().c_str(), pluginName.toStdWString().c_str(), filePath.toStdWString().c_str())) { + if (!MOBase::WriteRegistryValue(L"Game Files", (key+QString::number(writtenCount)).toStdWString().c_str(), pluginName.toStdWString().c_str(), filePath.toStdWString().c_str())) { throw MOBase::MyException(QObject::tr("failed to set game file key (errorcode %1)").arg(errno)); } } ++writtenCount; } } - + if (invalidFileNames) { reportError(QObject::tr("Some of your plugins have invalid names! These " "plugins can not be loaded by the game. Please see " "mo_interface.log for a list of affected plugins " "and rename them.")); } - + if (writtenCount == 0) { qWarning("plugin list would be empty, this is almost certainly wrong. Not " "saving."); @@ -185,4 +186,4 @@ QStringList MorrowindGamePlugins::readPluginList(MOBase::IPluginList *pluginList pluginList->setState(pluginName, IPluginList::STATE_INACTIVE); return primary + plugins; -} \ No newline at end of file +} From d8aae1da44819bdbe783fd51679bc76072ab9543 Mon Sep 17 00:00:00 2001 From: LostDragonist Date: Wed, 26 Dec 2018 17:21:22 -0600 Subject: [PATCH 0686/1544] [game_fallout3] Update plugin version --- src/games/fallout3/src/game_fallout3_en.ts | 8 ++++---- src/games/fallout3/src/gamefallout3.cpp | 2 +- 2 files changed, 5 insertions(+), 5 deletions(-) diff --git a/src/games/fallout3/src/game_fallout3_en.ts b/src/games/fallout3/src/game_fallout3_en.ts index f4775642..2c4ba1f4 100644 --- a/src/games/fallout3/src/game_fallout3_en.ts +++ b/src/games/fallout3/src/game_fallout3_en.ts @@ -61,9 +61,9 @@ QObject - - - + + + failed to activate BSA invalidation in "%1" (errorcode %2) @@ -93,7 +93,7 @@ - + failed to set archive key in %1 (errorcode %2) diff --git a/src/games/fallout3/src/gamefallout3.cpp b/src/games/fallout3/src/gamefallout3.cpp index b25f9aed..70ac48a1 100644 --- a/src/games/fallout3/src/gamefallout3.cpp +++ b/src/games/fallout3/src/gamefallout3.cpp @@ -78,7 +78,7 @@ QString GameFallout3::description() const MOBase::VersionInfo GameFallout3::version() const { - return VersionInfo(1, 3, 0, VersionInfo::RELEASE_FINAL); + return VersionInfo(1, 3, 1, VersionInfo::RELEASE_FINAL); } bool GameFallout3::isActive() const From f4440da81e15b38a654ca2560f129cc91bf23a8e Mon Sep 17 00:00:00 2001 From: LostDragonist Date: Wed, 26 Dec 2018 17:21:23 -0600 Subject: [PATCH 0687/1544] [game_fallout4] Update plugin version --- src/games/fallout4/src/game_fallout4_en.ts | 8 ++++---- src/games/fallout4/src/gamefallout4.cpp | 2 +- 2 files changed, 5 insertions(+), 5 deletions(-) diff --git a/src/games/fallout4/src/game_fallout4_en.ts b/src/games/fallout4/src/game_fallout4_en.ts index 2aaf516f..1765f9ec 100644 --- a/src/games/fallout4/src/game_fallout4_en.ts +++ b/src/games/fallout4/src/game_fallout4_en.ts @@ -68,9 +68,9 @@ Splash by %1 - - - + + + failed to activate BSA invalidation in "%1" (errorcode %2) @@ -95,7 +95,7 @@ Splash by %1 - + failed to set archive key in %1 (errorcode %2) diff --git a/src/games/fallout4/src/gamefallout4.cpp b/src/games/fallout4/src/gamefallout4.cpp index ad4a4f02..6976fa0f 100644 --- a/src/games/fallout4/src/gamefallout4.cpp +++ b/src/games/fallout4/src/gamefallout4.cpp @@ -79,7 +79,7 @@ QString GameFallout4::description() const MOBase::VersionInfo GameFallout4::version() const { - return VersionInfo(1, 3, 0, VersionInfo::RELEASE_FINAL); + return VersionInfo(1, 3, 1, VersionInfo::RELEASE_FINAL); } bool GameFallout4::isActive() const From e510d1411ceba02f9d04b78902d7ae242305c201 Mon Sep 17 00:00:00 2001 From: LostDragonist Date: Wed, 26 Dec 2018 17:21:23 -0600 Subject: [PATCH 0688/1544] [game_fallout4vr] Update plugin version --- src/games/fallout4vr/src/game_fallout4vr_en.ts | 8 ++++---- src/games/fallout4vr/src/gamefallout4vr.cpp | 2 +- 2 files changed, 5 insertions(+), 5 deletions(-) diff --git a/src/games/fallout4vr/src/game_fallout4vr_en.ts b/src/games/fallout4vr/src/game_fallout4vr_en.ts index 2384c194..6894f053 100644 --- a/src/games/fallout4vr/src/game_fallout4vr_en.ts +++ b/src/games/fallout4vr/src/game_fallout4vr_en.ts @@ -78,9 +78,9 @@ Splash by %1 - - - + + + failed to activate BSA invalidation in "%1" (errorcode %2) @@ -95,7 +95,7 @@ Splash by %1 - + failed to set archive key in %1 (errorcode %2) diff --git a/src/games/fallout4vr/src/gamefallout4vr.cpp b/src/games/fallout4vr/src/gamefallout4vr.cpp index 3e457d28..3454da52 100644 --- a/src/games/fallout4vr/src/gamefallout4vr.cpp +++ b/src/games/fallout4vr/src/gamefallout4vr.cpp @@ -77,7 +77,7 @@ QString GameFallout4VR::description() const MOBase::VersionInfo GameFallout4VR::version() const { - return VersionInfo(1, 3, 0, VersionInfo::RELEASE_FINAL); + return VersionInfo(1, 3, 1, VersionInfo::RELEASE_FINAL); } bool GameFallout4VR::isActive() const From ac2191b48dc3b5a1f0954bccce4c504a5e164350 Mon Sep 17 00:00:00 2001 From: LostDragonist Date: Wed, 26 Dec 2018 17:21:24 -0600 Subject: [PATCH 0689/1544] [game_falloutnv] Update plugin version --- src/games/falloutnv/src/game_falloutNV_en.ts | 8 ++++---- src/games/falloutnv/src/gamefalloutnv.cpp | 2 +- 2 files changed, 5 insertions(+), 5 deletions(-) diff --git a/src/games/falloutnv/src/game_falloutNV_en.ts b/src/games/falloutnv/src/game_falloutNV_en.ts index 421fe779..f940d821 100644 --- a/src/games/falloutnv/src/game_falloutNV_en.ts +++ b/src/games/falloutnv/src/game_falloutNV_en.ts @@ -61,9 +61,9 @@ QObject - - - + + + failed to activate BSA invalidation in "%1" (errorcode %2) @@ -93,7 +93,7 @@ - + failed to set archive key in %1 (errorcode %2) diff --git a/src/games/falloutnv/src/gamefalloutnv.cpp b/src/games/falloutnv/src/gamefalloutnv.cpp index e4e5d913..168857b4 100644 --- a/src/games/falloutnv/src/gamefalloutnv.cpp +++ b/src/games/falloutnv/src/gamefalloutnv.cpp @@ -78,7 +78,7 @@ QString GameFalloutNV::description() const MOBase::VersionInfo GameFalloutNV::version() const { - return VersionInfo(1, 3, 0, VersionInfo::RELEASE_FINAL); + return VersionInfo(1, 3, 1, VersionInfo::RELEASE_FINAL); } bool GameFalloutNV::isActive() const From 6c90815df5542bfa2c7ce505ec2f568ed5fbe7b8 Mon Sep 17 00:00:00 2001 From: LostDragonist Date: Wed, 26 Dec 2018 17:21:25 -0600 Subject: [PATCH 0690/1544] [game_morrowind] Update plugin version --- src/games/morrowind/src/game_morrowind_en.ts | 14 +++++++------- src/games/morrowind/src/gamemorrowind.cpp | 2 +- 2 files changed, 8 insertions(+), 8 deletions(-) diff --git a/src/games/morrowind/src/game_morrowind_en.ts b/src/games/morrowind/src/game_morrowind_en.ts index bb070a2d..1d4b7979 100644 --- a/src/games/morrowind/src/game_morrowind_en.ts +++ b/src/games/morrowind/src/game_morrowind_en.ts @@ -105,20 +105,20 @@ Splash by %1 QObject - - - + + + failed to activate BSA invalidation in "%1" (errorcode %2) - + failed to set archive key (errorcode %1) - + Some of your plugins have invalid names! These plugins can not be loaded by the game. Please see mo_interface.log for a list of affected plugins and rename them. @@ -143,12 +143,12 @@ Splash by %1 - + failed to set game file key (errorcode %1) - + failed to set archive key in %1 (errorcode %2) diff --git a/src/games/morrowind/src/gamemorrowind.cpp b/src/games/morrowind/src/gamemorrowind.cpp index 2de09b29..e28cb197 100644 --- a/src/games/morrowind/src/gamemorrowind.cpp +++ b/src/games/morrowind/src/gamemorrowind.cpp @@ -100,7 +100,7 @@ QString GameMorrowind::description() const MOBase::VersionInfo GameMorrowind::version() const { - return VersionInfo(1, 3, 0, VersionInfo::RELEASE_FINAL); + return VersionInfo(1, 3, 1, VersionInfo::RELEASE_FINAL); } bool GameMorrowind::isActive() const From 2ffd1f615d148db769be9226ffeecaccb6d0fc5c Mon Sep 17 00:00:00 2001 From: LostDragonist Date: Wed, 26 Dec 2018 17:21:25 -0600 Subject: [PATCH 0691/1544] [game_oblivion] Update plugin version --- src/games/oblivion/src/game_oblivion_en.ts | 8 ++++---- src/games/oblivion/src/gameoblivion.cpp | 2 +- 2 files changed, 5 insertions(+), 5 deletions(-) diff --git a/src/games/oblivion/src/game_oblivion_en.ts b/src/games/oblivion/src/game_oblivion_en.ts index db1588a9..4bd0708c 100644 --- a/src/games/oblivion/src/game_oblivion_en.ts +++ b/src/games/oblivion/src/game_oblivion_en.ts @@ -61,9 +61,9 @@ QObject - - - + + + failed to activate BSA invalidation in "%1" (errorcode %2) @@ -93,7 +93,7 @@ - + failed to set archive key in %1 (errorcode %2) diff --git a/src/games/oblivion/src/gameoblivion.cpp b/src/games/oblivion/src/gameoblivion.cpp index 22d2b9ca..7388b67b 100644 --- a/src/games/oblivion/src/gameoblivion.cpp +++ b/src/games/oblivion/src/gameoblivion.cpp @@ -73,7 +73,7 @@ QString GameOblivion::description() const MOBase::VersionInfo GameOblivion::version() const { - return VersionInfo(1, 3, 0, VersionInfo::RELEASE_FINAL); + return VersionInfo(1, 3, 1, VersionInfo::RELEASE_FINAL); } bool GameOblivion::isActive() const From e4ef2d1b9657c793c99a1c764cab4e1f4bccf23e Mon Sep 17 00:00:00 2001 From: LostDragonist Date: Wed, 26 Dec 2018 17:21:26 -0600 Subject: [PATCH 0692/1544] [game_skyrim] Update plugin version --- src/games/skyrim/src/game_skyrim_en.ts | 8 ++++---- src/games/skyrim/src/gameskyrim.cpp | 2 +- 2 files changed, 5 insertions(+), 5 deletions(-) diff --git a/src/games/skyrim/src/game_skyrim_en.ts b/src/games/skyrim/src/game_skyrim_en.ts index 4b6c5146..49bfb9d1 100644 --- a/src/games/skyrim/src/game_skyrim_en.ts +++ b/src/games/skyrim/src/game_skyrim_en.ts @@ -61,9 +61,9 @@ QObject - - - + + + failed to activate BSA invalidation in "%1" (errorcode %2) @@ -93,7 +93,7 @@ - + failed to set archive key in %1 (errorcode %2) diff --git a/src/games/skyrim/src/gameskyrim.cpp b/src/games/skyrim/src/gameskyrim.cpp index 68f49cf5..73a5be8e 100644 --- a/src/games/skyrim/src/gameskyrim.cpp +++ b/src/games/skyrim/src/gameskyrim.cpp @@ -84,7 +84,7 @@ QString GameSkyrim::description() const MOBase::VersionInfo GameSkyrim::version() const { - return VersionInfo(1, 3, 0, VersionInfo::RELEASE_FINAL); + return VersionInfo(1, 3, 1, VersionInfo::RELEASE_FINAL); } bool GameSkyrim::isActive() const From b263511c332a49dfe271b756d21ff504390744f1 Mon Sep 17 00:00:00 2001 From: LostDragonist Date: Wed, 26 Dec 2018 17:21:26 -0600 Subject: [PATCH 0693/1544] [game_skyrimse] Update plugin version --- src/games/skyrimse/src/game_skyrimse_en.ts | 8 ++++---- src/games/skyrimse/src/gameskyrimse.cpp | 2 +- 2 files changed, 5 insertions(+), 5 deletions(-) diff --git a/src/games/skyrimse/src/game_skyrimse_en.ts b/src/games/skyrimse/src/game_skyrimse_en.ts index 6406d09f..1e11c68d 100644 --- a/src/games/skyrimse/src/game_skyrimse_en.ts +++ b/src/games/skyrimse/src/game_skyrimse_en.ts @@ -77,9 +77,9 @@ - - - + + + failed to activate BSA invalidation in "%1" (errorcode %2) @@ -94,7 +94,7 @@ - + failed to set archive key in %1 (errorcode %2) diff --git a/src/games/skyrimse/src/gameskyrimse.cpp b/src/games/skyrimse/src/gameskyrimse.cpp index 6f464c0e..ea8d95cd 100644 --- a/src/games/skyrimse/src/gameskyrimse.cpp +++ b/src/games/skyrimse/src/gameskyrimse.cpp @@ -118,7 +118,7 @@ QString GameSkyrimSE::description() const MOBase::VersionInfo GameSkyrimSE::version() const { - return VersionInfo(1, 3, 0, VersionInfo::RELEASE_FINAL); + return VersionInfo(1, 3, 1, VersionInfo::RELEASE_FINAL); } bool GameSkyrimSE::isActive() const From 63c25a96d2d46aa4a3a7ffb2b12f8254051549b3 Mon Sep 17 00:00:00 2001 From: LostDragonist Date: Wed, 26 Dec 2018 17:21:27 -0600 Subject: [PATCH 0694/1544] [game_skyrimvr] Update plugin version --- src/games/skyrimvr/src/game_skyrimvr_en.ts | 8 ++++---- src/games/skyrimvr/src/gameskyrimvr.cpp | 2 +- 2 files changed, 5 insertions(+), 5 deletions(-) diff --git a/src/games/skyrimvr/src/game_skyrimvr_en.ts b/src/games/skyrimvr/src/game_skyrimvr_en.ts index ae573fa5..a83a05f4 100644 --- a/src/games/skyrimvr/src/game_skyrimvr_en.ts +++ b/src/games/skyrimvr/src/game_skyrimvr_en.ts @@ -77,9 +77,9 @@ - - - + + + failed to activate BSA invalidation in "%1" (errorcode %2) @@ -94,7 +94,7 @@ - + failed to set archive key in %1 (errorcode %2) diff --git a/src/games/skyrimvr/src/gameskyrimvr.cpp b/src/games/skyrimvr/src/gameskyrimvr.cpp index 4f5b2fe7..f8f14fd1 100644 --- a/src/games/skyrimvr/src/gameskyrimvr.cpp +++ b/src/games/skyrimvr/src/gameskyrimvr.cpp @@ -117,7 +117,7 @@ QString GameSkyrimVR::description() const MOBase::VersionInfo GameSkyrimVR::version() const { - return VersionInfo(1, 3, 0, VersionInfo::RELEASE_FINAL); + return VersionInfo(1, 3, 1, VersionInfo::RELEASE_FINAL); } bool GameSkyrimVR::isActive() const From 47afffa423ef4c00688dff1c7714f9fde697583a Mon Sep 17 00:00:00 2001 From: LostDragonist Date: Wed, 26 Dec 2018 17:21:27 -0600 Subject: [PATCH 0695/1544] [game_ttw] Update plugin version --- src/games/ttw/src/game_ttw_en.ts | 8 ++++---- src/games/ttw/src/gamefalloutttw.cpp | 2 +- 2 files changed, 5 insertions(+), 5 deletions(-) diff --git a/src/games/ttw/src/game_ttw_en.ts b/src/games/ttw/src/game_ttw_en.ts index cff8d84b..de7efaba 100644 --- a/src/games/ttw/src/game_ttw_en.ts +++ b/src/games/ttw/src/game_ttw_en.ts @@ -61,9 +61,9 @@ QObject - - - + + + failed to activate BSA invalidation in "%1" (errorcode %2) @@ -93,7 +93,7 @@ - + failed to set archive key in %1 (errorcode %2) diff --git a/src/games/ttw/src/gamefalloutttw.cpp b/src/games/ttw/src/gamefalloutttw.cpp index 39b71e0c..568bddf3 100644 --- a/src/games/ttw/src/gamefalloutttw.cpp +++ b/src/games/ttw/src/gamefalloutttw.cpp @@ -80,7 +80,7 @@ QString GameFalloutTTW::description() const MOBase::VersionInfo GameFalloutTTW::version() const { - return VersionInfo(1, 3, 0, VersionInfo::RELEASE_FINAL); + return VersionInfo(1, 3, 1, VersionInfo::RELEASE_FINAL); } bool GameFalloutTTW::isActive() const From 92eebc54d7adfa8dd8415f36200a786a7c823ab3 Mon Sep 17 00:00:00 2001 From: LostDragonist Date: Sat, 29 Dec 2018 13:53:24 -0600 Subject: [PATCH 0696/1544] [game_skyrim] Remove disabledPlugins to fix the plugin list --- src/games/skyrim/src/skyrimgameplugins.cpp | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/src/games/skyrim/src/skyrimgameplugins.cpp b/src/games/skyrim/src/skyrimgameplugins.cpp index 91a446e5..6699f6cb 100644 --- a/src/games/skyrim/src/skyrimgameplugins.cpp +++ b/src/games/skyrim/src/skyrimgameplugins.cpp @@ -83,7 +83,6 @@ QStringList SkyrimGamePlugins::readPluginList(MOBase::IPluginList *pluginList) pluginsTxtExists = false; } - QStringList disabledPlugins; if (pluginsTxtExists) { while (!file.atEnd()) { QByteArray line = file.readLine(); @@ -94,7 +93,6 @@ QStringList SkyrimGamePlugins::readPluginList(MOBase::IPluginList *pluginList) if (pluginName.size() > 0) { pluginList->setState(pluginName, IPluginList::STATE_ACTIVE); plugins.removeAll(pluginName); - disabledPlugins.append(pluginName); loadOrder.append(pluginName); } } @@ -111,5 +109,5 @@ QStringList SkyrimGamePlugins::readPluginList(MOBase::IPluginList *pluginList) } } - return loadOrder + disabledPlugins; + return loadOrder; } From 74df095b24f81a562b533b0edd9a02ed873f4d10 Mon Sep 17 00:00:00 2001 From: Al Date: Mon, 31 Dec 2018 03:21:45 +0100 Subject: [PATCH 0697/1544] [game_skyrim] Fixed disabled plugins loosing priority after they are deleted from plugins.txt Warning: plugins.txt order changes are for now ignored. --- src/games/skyrim/src/skyrimgameplugins.cpp | 17 +++++++++++++---- 1 file changed, 13 insertions(+), 4 deletions(-) diff --git a/src/games/skyrim/src/skyrimgameplugins.cpp b/src/games/skyrim/src/skyrimgameplugins.cpp index 6699f6cb..a8b427fe 100644 --- a/src/games/skyrim/src/skyrimgameplugins.cpp +++ b/src/games/skyrim/src/skyrimgameplugins.cpp @@ -35,8 +35,15 @@ void SkyrimGamePlugins::readPluginLists(MOBase::IPluginList *pluginList) { if (pluginsIsNew && !loadOrderIsNew) { // If the plugins is new but not loadorder, we must reparse the load order from the plugin files - QStringList loadOrder = readPluginList(pluginList); + + //removed because returned loadorder was incorrect and did not account for plugins that were already disabled before. + /*QStringList loadOrder = readPluginList(pluginList); + pluginList->setLoadOrder(loadOrder);*/ + + //Fix me: we are ignoring order changes in plugins.txt favouring loadorder.txt in all cases (plugins.txt shuld have precedence) + QStringList loadOrder = readLoadOrderList(pluginList, loadOrderPath); pluginList->setLoadOrder(loadOrder); + readPluginList(pluginList); } else { // read both files if they are both new or both older than the last read QStringList loadOrder = readLoadOrderList(pluginList, loadOrderPath); @@ -47,13 +54,14 @@ void SkyrimGamePlugins::readPluginLists(MOBase::IPluginList *pluginList) { m_LastRead = QDateTime::currentDateTime(); } +//TODO: return value is incorrect and should be ignored (it's not currently used QStringList SkyrimGamePlugins::readPluginList(MOBase::IPluginList *pluginList) { QStringList plugins = pluginList->pluginNames(); QStringList primaryPlugins = organizer()->managedGame()->primaryPlugins(); - QStringList loadOrder(primaryPlugins); + QStringList loadOrder(plugins); - for (const QString &pluginName : loadOrder) { + for (const QString &pluginName : primaryPlugins) { if (pluginList->state(pluginName) != IPluginList::STATE_MISSING) { pluginList->setState(pluginName, IPluginList::STATE_ACTIVE); } @@ -93,7 +101,8 @@ QStringList SkyrimGamePlugins::readPluginList(MOBase::IPluginList *pluginList) if (pluginName.size() > 0) { pluginList->setState(pluginName, IPluginList::STATE_ACTIVE); plugins.removeAll(pluginName); - loadOrder.append(pluginName); + //we already have the old loadorder and we ignore the positions in plugins.txt (needs fix) + //loadOrder.append(pluginName); } } From 5b410cf930d1eff2db083d393baa71651c2c6b2d Mon Sep 17 00:00:00 2001 From: LostDragonist Date: Sat, 5 Jan 2019 16:34:01 -0600 Subject: [PATCH 0698/1544] Change qPrintable to qUtf8Printable to better support non-ASCII text --- src/creation/creationgameplugins.cpp | 12 ++++++------ src/gamebryo/gamebryogameplugins.cpp | 6 +++--- 2 files changed, 9 insertions(+), 9 deletions(-) diff --git a/src/creation/creationgameplugins.cpp b/src/creation/creationgameplugins.cpp index 9dbd38a6..adb0b44b 100644 --- a/src/creation/creationgameplugins.cpp +++ b/src/creation/creationgameplugins.cpp @@ -70,7 +70,7 @@ void CreationGamePlugins::writePluginList(const IPluginList *pluginList, if (pluginList->state(pluginName) == IPluginList::STATE_ACTIVE) { if (!textCodec->canEncode(pluginName)) { invalidFileNames = true; - qCritical("invalid plugin name %s", qPrintable(pluginName)); + qCritical("invalid plugin name %s", qUtf8Printable(pluginName)); } else { @@ -85,7 +85,7 @@ void CreationGamePlugins::writePluginList(const IPluginList *pluginList, { if (!textCodec->canEncode(pluginName)) { invalidFileNames = true; - qCritical("invalid plugin name %s", qPrintable(pluginName)); + qCritical("invalid plugin name %s", qUtf8Printable(pluginName)); } else { @@ -105,7 +105,7 @@ void CreationGamePlugins::writePluginList(const IPluginList *pluginList, } if (file.commitIfDifferent(m_LastSaveHash[filePath])) { - qDebug("%s saved", qPrintable(QDir::toNativeSeparators(filePath))); + qDebug("%s saved", qUtf8Printable(QDir::toNativeSeparators(filePath))); } } @@ -124,7 +124,7 @@ QStringList CreationGamePlugins::readPluginList(MOBase::IPluginList *pluginList) QString filePath = organizer()->profile()->absolutePath() + "/plugins.txt"; QFile file(filePath); if (!file.open(QIODevice::ReadOnly)) { - qWarning("%s not found", qPrintable(filePath)); + qWarning("%s not found", qUtf8Printable(filePath)); return loadOrder; } ON_BLOCK_EXIT([&]() { file.close(); }); @@ -132,7 +132,7 @@ QStringList CreationGamePlugins::readPluginList(MOBase::IPluginList *pluginList) if (file.size() == 0) { // MO stores at least a header in the file. if it's completely empty the // file is broken - qWarning("%s empty", qPrintable(filePath)); + qWarning("%s empty", qUtf8Printable(filePath)); return loadOrder; } @@ -179,4 +179,4 @@ QStringList CreationGamePlugins::readPluginList(MOBase::IPluginList *pluginList) } return loadOrder; -} \ No newline at end of file +} diff --git a/src/gamebryo/gamebryogameplugins.cpp b/src/gamebryo/gamebryogameplugins.cpp index 6b2c51d4..51cf2075 100644 --- a/src/gamebryo/gamebryogameplugins.cpp +++ b/src/gamebryo/gamebryogameplugins.cpp @@ -115,7 +115,7 @@ void GamebryoGamePlugins::writeList(const IPluginList *pluginList, (pluginList->state(pluginName) == IPluginList::STATE_ACTIVE)) { if (!textCodec->canEncode(pluginName)) { invalidFileNames = true; - qCritical("invalid plugin name %s", qPrintable(pluginName)); + qCritical("invalid plugin name %s", qUtf8Printable(pluginName)); } else { file->write(textCodec->fromUnicode(pluginName)); } @@ -136,7 +136,7 @@ void GamebryoGamePlugins::writeList(const IPluginList *pluginList, "saving."); } else { if (file.commitIfDifferent(m_LastSaveHash[filePath])) { - qDebug("%s saved", qPrintable(QDir::toNativeSeparators(filePath))); + qDebug("%s saved", qUtf8Printable(QDir::toNativeSeparators(filePath))); } } } @@ -211,7 +211,7 @@ QStringList GamebryoGamePlugins::readPluginList(MOBase::IPluginList *pluginList) pluginsTxtExists = false; } ON_BLOCK_EXIT([&]() { - qDebug("close %s", qPrintable(filePath)); + qDebug("close %s", qUtf8Printable(filePath)); file.close(); }); From d1a651533ab0947da01db8c2a2b5a236a8b3b1e2 Mon Sep 17 00:00:00 2001 From: LostDragonist Date: Sat, 5 Jan 2019 16:34:02 -0600 Subject: [PATCH 0699/1544] [game_morrowind] Change qPrintable to qUtf8Printable to better support non-ASCII text --- src/games/morrowind/src/morrowindgameplugins.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/games/morrowind/src/morrowindgameplugins.cpp b/src/games/morrowind/src/morrowindgameplugins.cpp index d91fdb90..0fa7910b 100644 --- a/src/games/morrowind/src/morrowindgameplugins.cpp +++ b/src/games/morrowind/src/morrowindgameplugins.cpp @@ -101,7 +101,7 @@ void MorrowindGamePlugins::writeList(const IPluginList *pluginList, (pluginList->state(pluginName) == IPluginList::STATE_ACTIVE)) { if (!textCodec->canEncode(pluginName)) { invalidFileNames = true; - qCritical("invalid plugin name %s", qPrintable(pluginName)); + qCritical("invalid plugin name %s", qUtf8Printable(pluginName)); } else { if (!MOBase::WriteRegistryValue(L"Game Files", (key+QString::number(writtenCount)).toStdWString().c_str(), pluginName.toStdWString().c_str(), filePath.toStdWString().c_str())) { throw MOBase::MyException(QObject::tr("failed to set game file key (errorcode %1)").arg(errno)); From 1a98103e1258180248aea71ea836480b304b32c0 Mon Sep 17 00:00:00 2001 From: LostDragonist Date: Sat, 5 Jan 2019 16:34:03 -0600 Subject: [PATCH 0700/1544] [game_skyrim] Change qPrintable to qUtf8Printable to better support non-ASCII text --- src/games/skyrim/src/skyrimgameplugins.cpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/games/skyrim/src/skyrimgameplugins.cpp b/src/games/skyrim/src/skyrimgameplugins.cpp index a8b427fe..4c4ab6c5 100644 --- a/src/games/skyrim/src/skyrimgameplugins.cpp +++ b/src/games/skyrim/src/skyrimgameplugins.cpp @@ -35,7 +35,7 @@ void SkyrimGamePlugins::readPluginLists(MOBase::IPluginList *pluginList) { if (pluginsIsNew && !loadOrderIsNew) { // If the plugins is new but not loadorder, we must reparse the load order from the plugin files - + //removed because returned loadorder was incorrect and did not account for plugins that were already disabled before. /*QStringList loadOrder = readPluginList(pluginList); pluginList->setLoadOrder(loadOrder);*/ @@ -81,7 +81,7 @@ QStringList SkyrimGamePlugins::readPluginList(MOBase::IPluginList *pluginList) pluginsTxtExists = false; } ON_BLOCK_EXIT([&]() { - qDebug("close %s", qPrintable(filePath)); + qDebug("close %s", qUtf8Printable(filePath)); file.close(); }); From b0c31feec19178a1a810cc824449a603b2f6f0a5 Mon Sep 17 00:00:00 2001 From: LostDragonist Date: Fri, 11 Jan 2019 01:39:03 -0600 Subject: [PATCH 0701/1544] [game_fallout3] Support for force loading libraries --- src/games/fallout3/src/gamefallout3.cpp | 5 +++++ src/games/fallout3/src/gamefallout3.h | 1 + 2 files changed, 6 insertions(+) diff --git a/src/games/fallout3/src/gamefallout3.cpp b/src/games/fallout3/src/gamefallout3.cpp index 70ac48a1..71ab6ce8 100644 --- a/src/games/fallout3/src/gamefallout3.cpp +++ b/src/games/fallout3/src/gamefallout3.cpp @@ -61,6 +61,11 @@ QList GameFallout3::executables() const ; } +QList GameFallout3::executableForcedLoads() const +{ + return QList(); +} + QString GameFallout3::name() const { return "Fallout 3 Support Plugin"; diff --git a/src/games/fallout3/src/gamefallout3.h b/src/games/fallout3/src/gamefallout3.h index 8283d159..d7417bdf 100644 --- a/src/games/fallout3/src/gamefallout3.h +++ b/src/games/fallout3/src/gamefallout3.h @@ -21,6 +21,7 @@ public: // IPluginGame interface virtual QString gameName() const override; virtual QList executables() const override; + virtual QList executableForcedLoads() const override; virtual void initializeProfile(const QDir &path, ProfileSettings settings) const override; virtual QString savegameExtension() const override; virtual QString savegameSEExtension() const override; From ada1110b5b3845830f1b616aa449ba637277b216 Mon Sep 17 00:00:00 2001 From: LostDragonist Date: Fri, 11 Jan 2019 01:39:03 -0600 Subject: [PATCH 0702/1544] [game_fallout4] Support for force loading libraries --- src/games/fallout4/src/gamefallout4.cpp | 5 +++++ src/games/fallout4/src/gamefallout4.h | 1 + 2 files changed, 6 insertions(+) diff --git a/src/games/fallout4/src/gamefallout4.cpp b/src/games/fallout4/src/gamefallout4.cpp index 6976fa0f..7d1f7b5b 100644 --- a/src/games/fallout4/src/gamefallout4.cpp +++ b/src/games/fallout4/src/gamefallout4.cpp @@ -61,6 +61,11 @@ QList GameFallout4::executables() const ; } +QList GameFallout4::executableForcedLoads() const +{ + return QList(); +} + QString GameFallout4::name() const { return "Fallout 4 Support Plugin"; diff --git a/src/games/fallout4/src/gamefallout4.h b/src/games/fallout4/src/gamefallout4.h index 60cbf083..e901eeaa 100644 --- a/src/games/fallout4/src/gamefallout4.h +++ b/src/games/fallout4/src/gamefallout4.h @@ -23,6 +23,7 @@ public: // IPluginGame interface virtual QString gameName() const override; virtual QList executables() const override; + virtual QList executableForcedLoads() const override; virtual void initializeProfile(const QDir &path, ProfileSettings settings) const override; virtual QString savegameExtension() const override; virtual QString savegameSEExtension() const override; From 7b65b3f1ed041bb7ac76c84a09fbc221c762b83d Mon Sep 17 00:00:00 2001 From: LostDragonist Date: Fri, 11 Jan 2019 01:39:03 -0600 Subject: [PATCH 0703/1544] [game_fallout4vr] Support for force loading libraries --- src/games/fallout4vr/src/gamefallout4vr.cpp | 5 +++++ src/games/fallout4vr/src/gamefallout4vr.h | 1 + 2 files changed, 6 insertions(+) diff --git a/src/games/fallout4vr/src/gamefallout4vr.cpp b/src/games/fallout4vr/src/gamefallout4vr.cpp index 3454da52..0a5ea919 100644 --- a/src/games/fallout4vr/src/gamefallout4vr.cpp +++ b/src/games/fallout4vr/src/gamefallout4vr.cpp @@ -59,6 +59,11 @@ QList GameFallout4VR::executables() const ; } +QList GameFallout4VR::executableForcedLoads() const +{ + return QList(); +} + QString GameFallout4VR::name() const { return "Fallout 4 VR Support Plugin"; diff --git a/src/games/fallout4vr/src/gamefallout4vr.h b/src/games/fallout4vr/src/gamefallout4vr.h index 1d99b711..87ae4e3a 100644 --- a/src/games/fallout4vr/src/gamefallout4vr.h +++ b/src/games/fallout4vr/src/gamefallout4vr.h @@ -23,6 +23,7 @@ public: // IPluginGame interface virtual QString gameName() const override; virtual QList executables() const override; + virtual QList executableForcedLoads() const override; virtual void initializeProfile(const QDir &path, ProfileSettings settings) const override; virtual QString savegameExtension() const override; virtual QString savegameSEExtension() const override; From 67b7f75edad27b2319cd2d6ace3d8bf42a8b5e29 Mon Sep 17 00:00:00 2001 From: LostDragonist Date: Fri, 11 Jan 2019 01:39:03 -0600 Subject: [PATCH 0704/1544] [game_falloutnv] Support for force loading libraries --- src/games/falloutnv/src/gamefalloutnv.cpp | 5 +++++ src/games/falloutnv/src/gamefalloutnv.h | 1 + 2 files changed, 6 insertions(+) diff --git a/src/games/falloutnv/src/gamefalloutnv.cpp b/src/games/falloutnv/src/gamefalloutnv.cpp index 168857b4..fddc7a5a 100644 --- a/src/games/falloutnv/src/gamefalloutnv.cpp +++ b/src/games/falloutnv/src/gamefalloutnv.cpp @@ -61,6 +61,11 @@ QList GameFalloutNV::executables() const ; } +QList GameFalloutNV::executableForcedLoads() const +{ + return QList(); +} + QString GameFalloutNV::name() const { return "Fallout NV Support Plugin"; diff --git a/src/games/falloutnv/src/gamefalloutnv.h b/src/games/falloutnv/src/gamefalloutnv.h index e4609629..1a4d38c7 100644 --- a/src/games/falloutnv/src/gamefalloutnv.h +++ b/src/games/falloutnv/src/gamefalloutnv.h @@ -23,6 +23,7 @@ public: // IPluginGame interface virtual QString gameName() const override; virtual QList executables() const override; + virtual QList executableForcedLoads() const override; virtual void initializeProfile(const QDir &path, ProfileSettings settings) const override; virtual QString savegameExtension() const override; virtual QString savegameSEExtension() const override; From bf78360b2ef27ae02b5f794a06bac4697d94918b Mon Sep 17 00:00:00 2001 From: LostDragonist Date: Fri, 11 Jan 2019 01:39:03 -0600 Subject: [PATCH 0705/1544] [game_morrowind] Support for force loading libraries --- src/games/morrowind/src/gamemorrowind.cpp | 5 +++++ src/games/morrowind/src/gamemorrowind.h | 1 + 2 files changed, 6 insertions(+) diff --git a/src/games/morrowind/src/gamemorrowind.cpp b/src/games/morrowind/src/gamemorrowind.cpp index e28cb197..c1f00e07 100644 --- a/src/games/morrowind/src/gamemorrowind.cpp +++ b/src/games/morrowind/src/gamemorrowind.cpp @@ -82,6 +82,11 @@ QList GameMorrowind::executables() const ; } +QList GameMorrowind::executableForcedLoads() const +{ + return QList(); +} + QString GameMorrowind::name() const { return "Morrowind Support Plugin"; diff --git a/src/games/morrowind/src/gamemorrowind.h b/src/games/morrowind/src/gamemorrowind.h index 72fe2595..5fbe9dd5 100644 --- a/src/games/morrowind/src/gamemorrowind.h +++ b/src/games/morrowind/src/gamemorrowind.h @@ -30,6 +30,7 @@ public: // IPluginGame interface virtual QDir savesDirectory() const override; virtual QDir documentsDirectory() const override; virtual QList executables() const override; + virtual QList executableForcedLoads() const override; virtual void initializeProfile(const QDir &path, ProfileSettings settings) const override; virtual QString savegameExtension() const override; virtual QString savegameSEExtension() const override; From 8c8248a3a9c3d1fd38f25743d76bb517e44d0baf Mon Sep 17 00:00:00 2001 From: LostDragonist Date: Fri, 11 Jan 2019 01:39:03 -0600 Subject: [PATCH 0706/1544] [game_oblivion] Support for force loading libraries --- src/games/oblivion/src/gameoblivion.cpp | 9 +++++++++ src/games/oblivion/src/gameoblivion.h | 1 + 2 files changed, 10 insertions(+) diff --git a/src/games/oblivion/src/gameoblivion.cpp b/src/games/oblivion/src/gameoblivion.cpp index 7388b67b..b37f300c 100644 --- a/src/games/oblivion/src/gameoblivion.cpp +++ b/src/games/oblivion/src/gameoblivion.cpp @@ -56,6 +56,15 @@ QList GameOblivion::executables() const ; } +QList GameOblivion::executableForcedLoads() const +{ + //TODO Search game directory for OBSE DLLs + return QList() + << ExecutableForcedLoadSetting("Oblivion.exe", "obse_1_2_416.dll").withForced() + << ExecutableForcedLoadSetting("TESConstructionSet.exe", "obse_editor_1_2.dll").withForced() + ; +} + QString GameOblivion::name() const { return "Oblivion Support Plugin"; diff --git a/src/games/oblivion/src/gameoblivion.h b/src/games/oblivion/src/gameoblivion.h index bea187a3..e2a88a21 100644 --- a/src/games/oblivion/src/gameoblivion.h +++ b/src/games/oblivion/src/gameoblivion.h @@ -21,6 +21,7 @@ public: // IPluginGame interface virtual QString gameName() const override; virtual QList executables() const override; + virtual QList executableForcedLoads() const override; virtual void initializeProfile(const QDir &path, ProfileSettings settings) const override; virtual QString savegameExtension() const override; virtual QString savegameSEExtension() const override; From 7bd7d523a2987c2e809c2f462ed621ce9ae1960f Mon Sep 17 00:00:00 2001 From: LostDragonist Date: Fri, 11 Jan 2019 01:39:03 -0600 Subject: [PATCH 0707/1544] [game_skyrim] Support for force loading libraries --- src/games/skyrim/src/gameskyrim.cpp | 5 +++++ src/games/skyrim/src/gameskyrim.h | 1 + 2 files changed, 6 insertions(+) diff --git a/src/games/skyrim/src/gameskyrim.cpp b/src/games/skyrim/src/gameskyrim.cpp index 73a5be8e..4f561a01 100644 --- a/src/games/skyrim/src/gameskyrim.cpp +++ b/src/games/skyrim/src/gameskyrim.cpp @@ -67,6 +67,11 @@ QList GameSkyrim::executables() const ; } +QList GameSkyrim::executableForcedLoads() const +{ + return QList(); +} + QString GameSkyrim::name() const { return "Skyrim Support Plugin"; diff --git a/src/games/skyrim/src/gameskyrim.h b/src/games/skyrim/src/gameskyrim.h index fcc90193..9e7daca5 100644 --- a/src/games/skyrim/src/gameskyrim.h +++ b/src/games/skyrim/src/gameskyrim.h @@ -23,6 +23,7 @@ public: // IPluginGame interface virtual QString gameName() const override; virtual QList executables() const override; + virtual QList executableForcedLoads() const override; virtual void initializeProfile(const QDir &path, ProfileSettings settings) const override; virtual QString savegameExtension() const override; virtual QString savegameSEExtension() const override; From 470a948dc7249eb8c7b907ae02969a6a6937d520 Mon Sep 17 00:00:00 2001 From: LostDragonist Date: Fri, 11 Jan 2019 01:39:04 -0600 Subject: [PATCH 0708/1544] [game_skyrimse] Support for force loading libraries --- src/games/skyrimse/src/gameskyrimse.cpp | 5 +++++ src/games/skyrimse/src/gameskyrimse.h | 3 ++- 2 files changed, 7 insertions(+), 1 deletion(-) diff --git a/src/games/skyrimse/src/gameskyrimse.cpp b/src/games/skyrimse/src/gameskyrimse.cpp index ea8d95cd..4888bb69 100644 --- a/src/games/skyrimse/src/gameskyrimse.cpp +++ b/src/games/skyrimse/src/gameskyrimse.cpp @@ -96,6 +96,11 @@ QList GameSkyrimSE::executables() const ; } +QList GameSkyrimSE::executableForcedLoads() const +{ + return QList(); +} + QFileInfo GameSkyrimSE::findInGameFolder(const QString &relativePath) const { return QFileInfo(m_GamePath + "/" + relativePath); diff --git a/src/games/skyrimse/src/gameskyrimse.h b/src/games/skyrimse/src/gameskyrimse.h index 5caaeb7d..437d2c55 100644 --- a/src/games/skyrimse/src/gameskyrimse.h +++ b/src/games/skyrimse/src/gameskyrimse.h @@ -24,6 +24,7 @@ public: // IPluginGame interface virtual QString gameName() const override; virtual QList executables() const override; + virtual QList executableForcedLoads() const override; virtual void initializeProfile(const QDir &path, ProfileSettings settings) const override; virtual QString savegameExtension() const override; virtual QString savegameSEExtension() const override; @@ -62,7 +63,7 @@ protected: QString myGamesPath() const; virtual QString identifyGamePath() const override; - + }; #endif // _GAMESKYRIMSE_H From 7a34c5d83a61fa44d2cc942d609b4e9eb9d3c028 Mon Sep 17 00:00:00 2001 From: LostDragonist Date: Fri, 11 Jan 2019 01:39:04 -0600 Subject: [PATCH 0709/1544] [game_skyrimvr] Support for force loading libraries --- src/games/skyrimvr/src/gameskyrimvr.cpp | 5 +++++ src/games/skyrimvr/src/gameskyrimvr.h | 1 + 2 files changed, 6 insertions(+) diff --git a/src/games/skyrimvr/src/gameskyrimvr.cpp b/src/games/skyrimvr/src/gameskyrimvr.cpp index f8f14fd1..4b557f23 100644 --- a/src/games/skyrimvr/src/gameskyrimvr.cpp +++ b/src/games/skyrimvr/src/gameskyrimvr.cpp @@ -95,6 +95,11 @@ QList GameSkyrimVR::executables() const ; } +QList GameSkyrimVR::executableForcedLoads() const +{ + return QList(); +} + QFileInfo GameSkyrimVR::findInGameFolder(const QString &relativePath) const { return QFileInfo(m_GamePath + "/" + relativePath); diff --git a/src/games/skyrimvr/src/gameskyrimvr.h b/src/games/skyrimvr/src/gameskyrimvr.h index 84322847..0987c1c5 100644 --- a/src/games/skyrimvr/src/gameskyrimvr.h +++ b/src/games/skyrimvr/src/gameskyrimvr.h @@ -20,6 +20,7 @@ public: // IPluginGame interface virtual QString gameName() const override; virtual QList executables() const override; + virtual QList executableForcedLoads() const override; virtual void initializeProfile(const QDir &path, ProfileSettings settings) const override; virtual QString savegameExtension() const override; virtual QString savegameSEExtension() const override; From 88e22940695a283e3a383fd94c939d81d246ddf9 Mon Sep 17 00:00:00 2001 From: LostDragonist Date: Fri, 11 Jan 2019 01:39:04 -0600 Subject: [PATCH 0710/1544] [game_ttw] Support for force loading libraries --- src/games/ttw/src/gamefalloutttw.cpp | 5 +++++ src/games/ttw/src/gamefalloutttw.h | 1 + 2 files changed, 6 insertions(+) diff --git a/src/games/ttw/src/gamefalloutttw.cpp b/src/games/ttw/src/gamefalloutttw.cpp index 568bddf3..1832b7cc 100644 --- a/src/games/ttw/src/gamefalloutttw.cpp +++ b/src/games/ttw/src/gamefalloutttw.cpp @@ -63,6 +63,11 @@ QList GameFalloutTTW::executables() const ; } +QList GameFalloutTTW::executableForcedLoads() const +{ + return QList(); +} + QString GameFalloutTTW::name() const { return "Fallout TTW Support Plugin"; diff --git a/src/games/ttw/src/gamefalloutttw.h b/src/games/ttw/src/gamefalloutttw.h index 93bdaceb..2f1bda41 100644 --- a/src/games/ttw/src/gamefalloutttw.h +++ b/src/games/ttw/src/gamefalloutttw.h @@ -23,6 +23,7 @@ public: // IPluginGame interface virtual QString gameName() const override; virtual QList executables() const override; + virtual QList executableForcedLoads() const override; virtual void initializeProfile(const QDir &path, ProfileSettings settings) const override; virtual QString savegameExtension() const override; virtual QString savegameSEExtension() const override; From 437ba42f622dc964719c22cdc5f38b6b43571e44 Mon Sep 17 00:00:00 2001 From: LostDragonist Date: Fri, 11 Jan 2019 09:02:04 -0600 Subject: [PATCH 0711/1544] [game_fallout3] Update translation file --- src/games/fallout3/src/game_fallout3_en.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/games/fallout3/src/game_fallout3_en.ts b/src/games/fallout3/src/game_fallout3_en.ts index 2c4ba1f4..aa4005d7 100644 --- a/src/games/fallout3/src/game_fallout3_en.ts +++ b/src/games/fallout3/src/game_fallout3_en.ts @@ -4,7 +4,7 @@ GameFallout3 - + Adds support for the game Fallout 3s From 7fa9e3934be93621d398fc9f45b79673bd13c78b Mon Sep 17 00:00:00 2001 From: LostDragonist Date: Fri, 11 Jan 2019 09:02:04 -0600 Subject: [PATCH 0712/1544] [game_fallout4] Update translation file --- src/games/fallout4/src/game_fallout4_en.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/games/fallout4/src/game_fallout4_en.ts b/src/games/fallout4/src/game_fallout4_en.ts index 1765f9ec..c306181a 100644 --- a/src/games/fallout4/src/game_fallout4_en.ts +++ b/src/games/fallout4/src/game_fallout4_en.ts @@ -4,7 +4,7 @@ GameFallout4 - + Adds support for the game Fallout 4. Splash by %1 From d6f7cfeebe4eb7b6412d5c71feb76690041c16f7 Mon Sep 17 00:00:00 2001 From: LostDragonist Date: Fri, 11 Jan 2019 09:02:04 -0600 Subject: [PATCH 0713/1544] [game_morrowind] Update translation file --- src/games/morrowind/src/game_morrowind_en.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/games/morrowind/src/game_morrowind_en.ts b/src/games/morrowind/src/game_morrowind_en.ts index 1d4b7979..e65b0543 100644 --- a/src/games/morrowind/src/game_morrowind_en.ts +++ b/src/games/morrowind/src/game_morrowind_en.ts @@ -4,7 +4,7 @@ GameMorrowind - + Adds support for the game Morrowind. Splash by %1 From d978e8f01e31a4630821de233287e958851ec10b Mon Sep 17 00:00:00 2001 From: LostDragonist Date: Fri, 11 Jan 2019 09:02:04 -0600 Subject: [PATCH 0714/1544] [game_fallout4vr] Update translation file --- src/games/fallout4vr/src/game_fallout4vr_en.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/games/fallout4vr/src/game_fallout4vr_en.ts b/src/games/fallout4vr/src/game_fallout4vr_en.ts index 6894f053..600a34ed 100644 --- a/src/games/fallout4vr/src/game_fallout4vr_en.ts +++ b/src/games/fallout4vr/src/game_fallout4vr_en.ts @@ -4,7 +4,7 @@ GameFallout4VR - + Adds support for the game Fallout 4 VR. Splash by %1 From 2dafa2f23bbc5111efa1660e7a0550379a3b21d8 Mon Sep 17 00:00:00 2001 From: LostDragonist Date: Fri, 11 Jan 2019 09:02:04 -0600 Subject: [PATCH 0715/1544] [game_oblivion] Update translation file --- src/games/oblivion/src/game_oblivion_en.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/games/oblivion/src/game_oblivion_en.ts b/src/games/oblivion/src/game_oblivion_en.ts index 4bd0708c..34653c86 100644 --- a/src/games/oblivion/src/game_oblivion_en.ts +++ b/src/games/oblivion/src/game_oblivion_en.ts @@ -4,7 +4,7 @@ GameOblivion - + Adds support for the game Oblivion From 8d5b52d31cb817580d8de79ebf20bc17807d8a86 Mon Sep 17 00:00:00 2001 From: LostDragonist Date: Fri, 11 Jan 2019 09:02:04 -0600 Subject: [PATCH 0716/1544] [game_falloutnv] Update translation file --- src/games/falloutnv/src/game_falloutNV_en.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/games/falloutnv/src/game_falloutNV_en.ts b/src/games/falloutnv/src/game_falloutNV_en.ts index f940d821..2d26f67a 100644 --- a/src/games/falloutnv/src/game_falloutNV_en.ts +++ b/src/games/falloutnv/src/game_falloutNV_en.ts @@ -4,7 +4,7 @@ GameFalloutNV - + Adds support for the game Fallout New Vegas From 003fa812dfc2758cc86a3964754572c9c65b121a Mon Sep 17 00:00:00 2001 From: LostDragonist Date: Fri, 11 Jan 2019 09:02:05 -0600 Subject: [PATCH 0717/1544] [game_skyrimse] Update translation file --- src/games/skyrimse/src/game_skyrimse_en.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/games/skyrimse/src/game_skyrimse_en.ts b/src/games/skyrimse/src/game_skyrimse_en.ts index 1e11c68d..13007e99 100644 --- a/src/games/skyrimse/src/game_skyrimse_en.ts +++ b/src/games/skyrimse/src/game_skyrimse_en.ts @@ -4,7 +4,7 @@ GameSkyrimSE - + Adds support for the game Skyrim Special Edition. From 22c6573a34dbeabef46617ca5af116fda5ba8955 Mon Sep 17 00:00:00 2001 From: LostDragonist Date: Fri, 11 Jan 2019 09:02:05 -0600 Subject: [PATCH 0718/1544] [game_skyrimvr] Update translation file --- src/games/skyrimvr/src/game_skyrimvr_en.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/games/skyrimvr/src/game_skyrimvr_en.ts b/src/games/skyrimvr/src/game_skyrimvr_en.ts index a83a05f4..b2fec422 100644 --- a/src/games/skyrimvr/src/game_skyrimvr_en.ts +++ b/src/games/skyrimvr/src/game_skyrimvr_en.ts @@ -4,7 +4,7 @@ GameSkyrimVR - + Adds support for the game Skyrim VR. From 15bb48f187c772d077794398a411b3f718a50e01 Mon Sep 17 00:00:00 2001 From: LostDragonist Date: Fri, 11 Jan 2019 09:02:05 -0600 Subject: [PATCH 0719/1544] [game_ttw] Update translation file --- src/games/ttw/src/game_ttw_en.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/games/ttw/src/game_ttw_en.ts b/src/games/ttw/src/game_ttw_en.ts index de7efaba..a86566c6 100644 --- a/src/games/ttw/src/game_ttw_en.ts +++ b/src/games/ttw/src/game_ttw_en.ts @@ -4,7 +4,7 @@ GameFalloutTTW - + Adds support for the game Fallout TTW From ea336256b226d371f709705a938e4bd31ebbb45e Mon Sep 17 00:00:00 2001 From: LostDragonist Date: Fri, 11 Jan 2019 09:02:05 -0600 Subject: [PATCH 0720/1544] [game_skyrim] Update translation file --- src/games/skyrim/src/game_skyrim_en.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/games/skyrim/src/game_skyrim_en.ts b/src/games/skyrim/src/game_skyrim_en.ts index 49bfb9d1..7b2d227d 100644 --- a/src/games/skyrim/src/game_skyrim_en.ts +++ b/src/games/skyrim/src/game_skyrim_en.ts @@ -4,7 +4,7 @@ GameSkyrim - + Adds support for the game Skyrim From 80815245e221d166363c8ce732baeef94aec8841 Mon Sep 17 00:00:00 2001 From: LostDragonist Date: Tue, 29 Jan 2019 22:48:42 -0600 Subject: [PATCH 0721/1544] [game_skyrimse] Change case of shortName to match executable case This really shouldn't matter but some mods appear to care for some reason. Doing this is technically more correct for the default case so... oh well. --- src/games/skyrimse/src/gameskyrimse.cpp | 4 ++-- src/games/skyrimse/src/gameskyrimse.h | 4 ++-- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/src/games/skyrimse/src/gameskyrimse.cpp b/src/games/skyrimse/src/gameskyrimse.cpp index 4888bb69..304a9057 100644 --- a/src/games/skyrimse/src/gameskyrimse.cpp +++ b/src/games/skyrimse/src/gameskyrimse.cpp @@ -187,12 +187,12 @@ QStringList GameSkyrimSE::gameVariants() const QString GameSkyrimSE::gameShortName() const { - return "skyrimse"; + return "SkyrimSE"; } QStringList GameSkyrimSE::validShortNames() const { - return { "skyrim" }; + return { "Skyrim" }; } QString GameSkyrimSE::gameNexusName() const diff --git a/src/games/skyrimse/src/gameskyrimse.h b/src/games/skyrimse/src/gameskyrimse.h index 437d2c55..1f5d6618 100644 --- a/src/games/skyrimse/src/gameskyrimse.h +++ b/src/games/skyrimse/src/gameskyrimse.h @@ -11,7 +11,7 @@ class GameSkyrimSE : public GameGamebryo { Q_OBJECT - Q_PLUGIN_METADATA(IID "com.soundcontactstudio.GameSkyrimSE" FILE "gameskyrimse.json") + Q_PLUGIN_METADATA(IID "com.soundcontactstudio.GameSkyrimSE" FILE "gameskyrimse.json") public: @@ -32,7 +32,7 @@ public: // IPluginGame interface virtual QStringList primaryPlugins() const override; virtual QStringList gameVariants() const override; virtual QString gameShortName() const override; - virtual QString gameNexusName() const override; + virtual QString gameNexusName() const override; virtual QStringList validShortNames() const override; virtual QStringList iniFiles() const override; virtual QStringList DLCPlugins() const override; From af14e6ba55414bb3a1c9753185158ad5b5cada9d Mon Sep 17 00:00:00 2001 From: Silarn Date: Tue, 29 Jan 2019 23:01:21 -0600 Subject: [PATCH 0722/1544] [game_fallout3] Correct the Nexus id (though it appears to be case-insensitive) --- src/games/fallout3/src/gamefallout3.cpp | 370 ++++++++++++------------ 1 file changed, 185 insertions(+), 185 deletions(-) diff --git a/src/games/fallout3/src/gamefallout3.cpp b/src/games/fallout3/src/gamefallout3.cpp index 71ab6ce8..9970ebf5 100644 --- a/src/games/fallout3/src/gamefallout3.cpp +++ b/src/games/fallout3/src/gamefallout3.cpp @@ -1,185 +1,185 @@ -#include "gamefallout3.h" - -#include "fallout3bsainvalidation.h" -#include "fallout3scriptextender.h" -#include "fallout3dataarchives.h" -#include "fallout3savegameinfo.h" - -#include "executableinfo.h" -#include "pluginsetting.h" -#include "versioninfo.h" -#include -#include -#include - -#include -#include -#include -#include -#include -#include -#include - -#include - -using namespace MOBase; - -GameFallout3::GameFallout3() -{ -} - -bool GameFallout3::init(IOrganizer *moInfo) -{ - if (!GameGamebryo::init(moInfo)) { - return false; - } - registerFeature(new Fallout3ScriptExtender(this)); - registerFeature(new Fallout3DataArchives(myGamesPath())); - registerFeature(new Fallout3BSAInvalidation(feature(), this)); - registerFeature(new Fallout3SaveGameInfo(this)); - registerFeature(new GamebryoLocalSavegames(myGamesPath(), "fallout.ini")); - registerFeature(new GamebryoGamePlugins(moInfo)); - registerFeature(new GamebryoUnmangedMods(this)); - return true; -} - -QString GameFallout3::gameName() const -{ - return "Fallout 3"; -} - -QList GameFallout3::executables() const -{ - return QList() - << ExecutableInfo("FOSE", findInGameFolder(feature()->loaderName())) - << ExecutableInfo("Fallout 3", findInGameFolder(binaryName())) - << ExecutableInfo("Fallout Mod Manager", findInGameFolder("fomm/fomm.exe")) - << ExecutableInfo("Construction Kit", findInGameFolder("geck.exe")) - << ExecutableInfo("Fallout Launcher", findInGameFolder(getLauncherName())) - << ExecutableInfo("BOSS", findInGameFolder("BOSS/BOSS.exe")) - << ExecutableInfo("LOOT", getLootPath()).withArgument("--game=\"Fallout3\"") - ; -} - -QList GameFallout3::executableForcedLoads() const -{ - return QList(); -} - -QString GameFallout3::name() const -{ - return "Fallout 3 Support Plugin"; -} - -QString GameFallout3::author() const -{ - return "Tannin"; -} - -QString GameFallout3::description() const -{ - return tr("Adds support for the game Fallout 3s"); -} - -MOBase::VersionInfo GameFallout3::version() const -{ - return VersionInfo(1, 3, 1, VersionInfo::RELEASE_FINAL); -} - -bool GameFallout3::isActive() const -{ - return qApp->property("managed_game").value() == this; -} - -QList GameFallout3::settings() const -{ - return QList(); -} - -void GameFallout3::initializeProfile(const QDir &path, ProfileSettings settings) const -{ - if (settings.testFlag(IPluginGame::MODS)) { - copyToProfile(localAppFolder() + "/Fallout3", path, "plugins.txt"); - copyToProfile(localAppFolder() + "/Fallout3", path, "loadorder.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, "custom.ini"); - copyToProfile(myGamesPath(), path, "GECKCustom.ini"); - copyToProfile(myGamesPath(), path, "GECKPrefs.ini"); - } -} - -QString GameFallout3::savegameExtension() const -{ - return "fos"; -} - -QString GameFallout3::savegameSEExtension() const -{ - return ""; -} - -QString GameFallout3::steamAPPId() const -{ - if (selectedVariant() == "Game Of The Year") { - return "22370"; - } else { - return "22300"; - } -} - -QStringList GameFallout3::primaryPlugins() const -{ - return { "fallout3.esm" }; -} - - -QStringList GameFallout3::gameVariants() const -{ - return { "Regular", "Game Of The Year" }; -} - -QString GameFallout3::gameShortName() const -{ - return "Fallout3"; -} - -QString GameFallout3::gameNexusName() const -{ - return "Fallout3"; -} - - -QStringList GameFallout3::iniFiles() const -{ - return { "fallout.ini", "falloutprefs.ini", "custom.ini", "GECKCustom.ini", "GECKPrefs.ini" }; -} - -QStringList GameFallout3::DLCPlugins() const -{ - return { "ThePitt.esm", "Anchorage.esm", "BrokenSteel.esm", "PointLookout.esm", "Zeta.esm" }; -} - -int GameFallout3::nexusModOrganizerID() const -{ - return 16348; -} - -int GameFallout3::nexusGameID() const -{ - return 120; -} - -QString GameFallout3::getLauncherName() const -{ - return "FalloutLauncher.exe"; -} +#include "gamefallout3.h" + +#include "fallout3bsainvalidation.h" +#include "fallout3scriptextender.h" +#include "fallout3dataarchives.h" +#include "fallout3savegameinfo.h" + +#include "executableinfo.h" +#include "pluginsetting.h" +#include "versioninfo.h" +#include +#include +#include + +#include +#include +#include +#include +#include +#include +#include + +#include + +using namespace MOBase; + +GameFallout3::GameFallout3() +{ +} + +bool GameFallout3::init(IOrganizer *moInfo) +{ + if (!GameGamebryo::init(moInfo)) { + return false; + } + registerFeature(new Fallout3ScriptExtender(this)); + registerFeature(new Fallout3DataArchives(myGamesPath())); + registerFeature(new Fallout3BSAInvalidation(feature(), this)); + registerFeature(new Fallout3SaveGameInfo(this)); + registerFeature(new GamebryoLocalSavegames(myGamesPath(), "fallout.ini")); + registerFeature(new GamebryoGamePlugins(moInfo)); + registerFeature(new GamebryoUnmangedMods(this)); + return true; +} + +QString GameFallout3::gameName() const +{ + return "Fallout 3"; +} + +QList GameFallout3::executables() const +{ + return QList() + << ExecutableInfo("FOSE", findInGameFolder(feature()->loaderName())) + << ExecutableInfo("Fallout 3", findInGameFolder(binaryName())) + << ExecutableInfo("Fallout Mod Manager", findInGameFolder("fomm/fomm.exe")) + << ExecutableInfo("Construction Kit", findInGameFolder("geck.exe")) + << ExecutableInfo("Fallout Launcher", findInGameFolder(getLauncherName())) + << ExecutableInfo("BOSS", findInGameFolder("BOSS/BOSS.exe")) + << ExecutableInfo("LOOT", getLootPath()).withArgument("--game=\"Fallout3\"") + ; +} + +QList GameFallout3::executableForcedLoads() const +{ + return QList(); +} + +QString GameFallout3::name() const +{ + return "Fallout 3 Support Plugin"; +} + +QString GameFallout3::author() const +{ + return "Tannin"; +} + +QString GameFallout3::description() const +{ + return tr("Adds support for the game Fallout 3s"); +} + +MOBase::VersionInfo GameFallout3::version() const +{ + return VersionInfo(1, 3, 1, VersionInfo::RELEASE_FINAL); +} + +bool GameFallout3::isActive() const +{ + return qApp->property("managed_game").value() == this; +} + +QList GameFallout3::settings() const +{ + return QList(); +} + +void GameFallout3::initializeProfile(const QDir &path, ProfileSettings settings) const +{ + if (settings.testFlag(IPluginGame::MODS)) { + copyToProfile(localAppFolder() + "/Fallout3", path, "plugins.txt"); + copyToProfile(localAppFolder() + "/Fallout3", path, "loadorder.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, "custom.ini"); + copyToProfile(myGamesPath(), path, "GECKCustom.ini"); + copyToProfile(myGamesPath(), path, "GECKPrefs.ini"); + } +} + +QString GameFallout3::savegameExtension() const +{ + return "fos"; +} + +QString GameFallout3::savegameSEExtension() const +{ + return ""; +} + +QString GameFallout3::steamAPPId() const +{ + if (selectedVariant() == "Game Of The Year") { + return "22370"; + } else { + return "22300"; + } +} + +QStringList GameFallout3::primaryPlugins() const +{ + return { "fallout3.esm" }; +} + + +QStringList GameFallout3::gameVariants() const +{ + return { "Regular", "Game Of The Year" }; +} + +QString GameFallout3::gameShortName() const +{ + return "Fallout3"; +} + +QString GameFallout3::gameNexusName() const +{ + return "fallout3"; +} + + +QStringList GameFallout3::iniFiles() const +{ + return { "fallout.ini", "falloutprefs.ini", "custom.ini", "GECKCustom.ini", "GECKPrefs.ini" }; +} + +QStringList GameFallout3::DLCPlugins() const +{ + return { "ThePitt.esm", "Anchorage.esm", "BrokenSteel.esm", "PointLookout.esm", "Zeta.esm" }; +} + +int GameFallout3::nexusModOrganizerID() const +{ + return 16348; +} + +int GameFallout3::nexusGameID() const +{ + return 120; +} + +QString GameFallout3::getLauncherName() const +{ + return "FalloutLauncher.exe"; +} From 4ef43dd30d9cc0a587525617c41861c2aa02ea35 Mon Sep 17 00:00:00 2001 From: Silarn Date: Tue, 29 Jan 2019 23:01:22 -0600 Subject: [PATCH 0723/1544] [game_fallout4] Correct the Nexus id (though it appears to be case-insensitive) --- src/games/fallout4/src/gamefallout4.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/games/fallout4/src/gamefallout4.cpp b/src/games/fallout4/src/gamefallout4.cpp index 7d1f7b5b..b98567c3 100644 --- a/src/games/fallout4/src/gamefallout4.cpp +++ b/src/games/fallout4/src/gamefallout4.cpp @@ -153,7 +153,7 @@ QString GameFallout4::gameShortName() const QString GameFallout4::gameNexusName() const { - return "Fallout4"; + return "fallout4"; } QStringList GameFallout4::iniFiles() const From 03078ec16236c64ba2f81cad6e835ce0a4fe2a67 Mon Sep 17 00:00:00 2001 From: LostDragonist Date: Sat, 2 Feb 2019 17:26:56 -0600 Subject: [PATCH 0724/1544] [game_morrowind] Do not store game directory for local save games --- src/games/morrowind/src/game_morrowind_en.ts | 14 +++++++------- src/games/morrowind/src/gamemorrowind.cpp | 2 +- .../morrowind/src/morrowindlocalsavegames.cpp | 14 +++++++------- src/games/morrowind/src/morrowindlocalsavegames.h | 5 +++-- 4 files changed, 18 insertions(+), 17 deletions(-) diff --git a/src/games/morrowind/src/game_morrowind_en.ts b/src/games/morrowind/src/game_morrowind_en.ts index e65b0543..8db66a31 100644 --- a/src/games/morrowind/src/game_morrowind_en.ts +++ b/src/games/morrowind/src/game_morrowind_en.ts @@ -112,8 +112,8 @@ Splash by %1 - - failed to set archive key (errorcode %1) + + failed to set archive key in %1 (errorcode %2) @@ -142,15 +142,15 @@ Splash by %1 failed to query registry path (read): %1 + + + failed to set archive key (errorcode %1) + + failed to set game file key (errorcode %1) - - - failed to set archive key in %1 (errorcode %2) - - diff --git a/src/games/morrowind/src/gamemorrowind.cpp b/src/games/morrowind/src/gamemorrowind.cpp index c1f00e07..70731e50 100644 --- a/src/games/morrowind/src/gamemorrowind.cpp +++ b/src/games/morrowind/src/gamemorrowind.cpp @@ -40,7 +40,7 @@ bool GameMorrowind::init(IOrganizer *moInfo) registerFeature(new MorrowindDataArchives(gameDirectory().absolutePath())); registerFeature(new MorrowindBSAInvalidation(feature(), this)); registerFeature(new MorrowindSaveGameInfo(this)); - registerFeature(new MorrowindLocalSavegames(gameDirectory().absolutePath())); + registerFeature(new MorrowindLocalSavegames(this)); registerFeature(new MorrowindGamePlugins(moInfo)); registerFeature(new GamebryoUnmangedMods(this)); m_Organizer = moInfo; diff --git a/src/games/morrowind/src/morrowindlocalsavegames.cpp b/src/games/morrowind/src/morrowindlocalsavegames.cpp index 157ed299..e4f2ce83 100644 --- a/src/games/morrowind/src/morrowindlocalsavegames.cpp +++ b/src/games/morrowind/src/morrowindlocalsavegames.cpp @@ -25,8 +25,8 @@ Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA #include -MorrowindLocalSavegames::MorrowindLocalSavegames(const QDir &gameInstallDir) - : m_GameInstallDir(gameInstallDir.absolutePath()) +MorrowindLocalSavegames::MorrowindLocalSavegames(const MOBase::IPluginGame *game) + : m_GamePlugin(game) {} bool MorrowindLocalSavegames::prepareProfile(MOBase::IProfile *profile) @@ -34,15 +34,15 @@ bool MorrowindLocalSavegames::prepareProfile(MOBase::IProfile *profile) bool dirty = false; if (profile->localSavesEnabled()) { - if (m_GameInstallDir.exists("Saves")) { - if (!m_GameInstallDir.rename("Saves", "_Saves")) { + if (m_GamePlugin->gameDirectory().exists("Saves")) { + if (!m_GamePlugin->gameDirectory().rename("Saves", "_Saves")) { qCritical("Unable to enable Morrowind local save games!"); } dirty = true; } } else { - if (m_GameInstallDir.exists("_Saves")) { - if (!m_GameInstallDir.rename("_Saves", "Saves")) { + if (m_GamePlugin->gameDirectory().exists("_Saves")) { + if (!m_GamePlugin->gameDirectory().rename("_Saves", "Saves")) { qCritical("Unable to disable Morrowind local save games!"); } dirty = true; @@ -57,7 +57,7 @@ MappingType MorrowindLocalSavegames::mappings(const QDir &profileSaveDir) const { return {{ profileSaveDir.absolutePath(), - m_GameInstallDir.absolutePath() + "/Saves", + m_GamePlugin->gameDirectory().absoluteFilePath("Saves"), true, true }}; diff --git a/src/games/morrowind/src/morrowindlocalsavegames.h b/src/games/morrowind/src/morrowindlocalsavegames.h index c2164b1d..b70f212c 100644 --- a/src/games/morrowind/src/morrowindlocalsavegames.h +++ b/src/games/morrowind/src/morrowindlocalsavegames.h @@ -25,19 +25,20 @@ Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA #include #include +#include "iplugingame.h" class MorrowindLocalSavegames : public LocalSavegames { public: - MorrowindLocalSavegames(const QDir &m_GameInstallDir); + MorrowindLocalSavegames(const MOBase::IPluginGame *game); virtual MappingType mappings(const QDir &profileSaveDir) const override; virtual bool prepareProfile(MOBase::IProfile *profile) override; private: - QDir m_GameInstallDir; + const MOBase::IPluginGame *m_GamePlugin; }; From dadfe99815ecfb7b319239ded43e0ed93a8cd2e6 Mon Sep 17 00:00:00 2001 From: LostDragonist Date: Sat, 2 Feb 2019 17:34:23 -0600 Subject: [PATCH 0725/1544] [game_morrowind] Do not store game directory for data archives --- src/games/morrowind/src/gamemorrowind.cpp | 2 +- src/games/morrowind/src/morrowinddataarchives.cpp | 9 +++++---- src/games/morrowind/src/morrowinddataarchives.h | 5 ++++- 3 files changed, 10 insertions(+), 6 deletions(-) diff --git a/src/games/morrowind/src/gamemorrowind.cpp b/src/games/morrowind/src/gamemorrowind.cpp index 70731e50..f0129350 100644 --- a/src/games/morrowind/src/gamemorrowind.cpp +++ b/src/games/morrowind/src/gamemorrowind.cpp @@ -37,7 +37,7 @@ bool GameMorrowind::init(IOrganizer *moInfo) if (!GameGamebryo::init(moInfo)) { return false; } - registerFeature(new MorrowindDataArchives(gameDirectory().absolutePath())); + registerFeature(new MorrowindDataArchives(this)); registerFeature(new MorrowindBSAInvalidation(feature(), this)); registerFeature(new MorrowindSaveGameInfo(this)); registerFeature(new MorrowindLocalSavegames(this)); diff --git a/src/games/morrowind/src/morrowinddataarchives.cpp b/src/games/morrowind/src/morrowinddataarchives.cpp index a52b59c1..ecbc5abd 100644 --- a/src/games/morrowind/src/morrowinddataarchives.cpp +++ b/src/games/morrowind/src/morrowinddataarchives.cpp @@ -2,8 +2,9 @@ #include #include "registry.h" -MorrowindDataArchives::MorrowindDataArchives(const QDir &myGamesDir) : - GamebryoDataArchives(myGamesDir) +MorrowindDataArchives::MorrowindDataArchives(const MOBase::IPluginGame *game) + : GamebryoDataArchives(QDir()) // m_LocalGameDir is not used as it's determined too soon + , m_GamePlugin(game) { } @@ -49,7 +50,7 @@ QStringList MorrowindDataArchives::archives(const MOBase::IProfile *profile) con { QStringList result; - QString iniFile = profile->localSettingsEnabled() ? QDir(profile->absolutePath()).absoluteFilePath("morrowind.ini") : m_LocalGameDir.absoluteFilePath("morrowind.ini"); + QString iniFile = profile->localSettingsEnabled() ? QDir(profile->absolutePath()).absoluteFilePath("morrowind.ini") : m_GamePlugin->gameDirectory().absoluteFilePath("morrowind.ini"); result.append(getArchives(iniFile)); return result; @@ -57,6 +58,6 @@ QStringList MorrowindDataArchives::archives(const MOBase::IProfile *profile) con void MorrowindDataArchives::writeArchiveList(MOBase::IProfile *profile, const QStringList &before) { - QString iniFile = profile->localSettingsEnabled() ? QDir(profile->absolutePath()).absoluteFilePath("morrowind.ini") : m_LocalGameDir.absoluteFilePath("morrowind.ini"); + QString iniFile = profile->localSettingsEnabled() ? QDir(profile->absolutePath()).absoluteFilePath("morrowind.ini") : m_GamePlugin->gameDirectory().absoluteFilePath("morrowind.ini"); setArchives(iniFile, before); } diff --git a/src/games/morrowind/src/morrowinddataarchives.h b/src/games/morrowind/src/morrowinddataarchives.h index 8264c676..d132ce17 100644 --- a/src/games/morrowind/src/morrowinddataarchives.h +++ b/src/games/morrowind/src/morrowinddataarchives.h @@ -4,6 +4,7 @@ #include #include +#include #include #include #include @@ -12,7 +13,7 @@ class MorrowindDataArchives : public GamebryoDataArchives { public: - MorrowindDataArchives(const QDir &myGamesDir); + MorrowindDataArchives(const MOBase::IPluginGame *game); public: @@ -28,6 +29,8 @@ private: virtual void writeArchiveList(MOBase::IProfile *profile, const QStringList &before) override; + const MOBase::IPluginGame *m_GamePlugin; + }; #endif // MORROWINDDATAARCHIVES_H From 890a55cda712fb2cc8b61ea6d33fed4142346450 Mon Sep 17 00:00:00 2001 From: LostDragonist Date: Wed, 13 Feb 2019 21:04:11 -0600 Subject: [PATCH 0726/1544] [game_morrowind] Search Steam libraries if registry key is not found --- src/games/morrowind/src/gamemorrowind.cpp | 10 +++++++++- src/games/morrowind/src/gamemorrowind.h | 1 + 2 files changed, 10 insertions(+), 1 deletion(-) diff --git a/src/games/morrowind/src/gamemorrowind.cpp b/src/games/morrowind/src/gamemorrowind.cpp index f0129350..d3238bcc 100644 --- a/src/games/morrowind/src/gamemorrowind.cpp +++ b/src/games/morrowind/src/gamemorrowind.cpp @@ -8,6 +8,7 @@ #include "executableinfo.h" #include "pluginsetting.h" +#include "steamutility.h" #include @@ -211,7 +212,6 @@ VS_FIXEDFILEINFO GetFileVersion(const std::wstring &fileName) } - int GameMorrowind::nexusModOrganizerID() const { return 1334; @@ -221,3 +221,11 @@ int GameMorrowind::nexusGameID() const { return 100; } + +QString GameMorrowind::identifyGamePath() const +{ + QString path = GameGamebryo::identifyGamePath(); + if (path.isEmpty()) + path = MOBase::findSteamGame("Morrowind", "Data Files\\Morrowind.esm"); + return path; +} diff --git a/src/games/morrowind/src/gamemorrowind.h b/src/games/morrowind/src/gamemorrowind.h index 5fbe9dd5..1ce652ae 100644 --- a/src/games/morrowind/src/gamemorrowind.h +++ b/src/games/morrowind/src/gamemorrowind.h @@ -44,6 +44,7 @@ public: // IPluginGame interface virtual SortMechanism sortMechanism() const override; virtual int nexusModOrganizerID() const override; virtual int nexusGameID() const override; + virtual QString identifyGamePath() const; public: // IPlugin interface From ec7194b85d6f73ac099f762e875cd9c5bb688362 Mon Sep 17 00:00:00 2001 From: LostDragonist Date: Wed, 13 Feb 2019 21:16:29 -0600 Subject: [PATCH 0727/1544] [game_morrowind] Update translation file --- src/games/morrowind/src/game_morrowind_en.ts | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/games/morrowind/src/game_morrowind_en.ts b/src/games/morrowind/src/game_morrowind_en.ts index 8db66a31..8baf04b4 100644 --- a/src/games/morrowind/src/game_morrowind_en.ts +++ b/src/games/morrowind/src/game_morrowind_en.ts @@ -4,7 +4,7 @@ GameMorrowind - + Adds support for the game Morrowind. Splash by %1 @@ -143,7 +143,7 @@ Splash by %1 - + failed to set archive key (errorcode %1) From f6243f08f8a3e9905807f656c059fb76922c1e5b Mon Sep 17 00:00:00 2001 From: LostDragonist Date: Thu, 14 Feb 2019 16:44:16 -0600 Subject: [PATCH 0728/1544] Fix logic to save and restore INI settings when changing local saves setting --- src/gamebryo/gamebryolocalsavegames.cpp | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/src/gamebryo/gamebryolocalsavegames.cpp b/src/gamebryo/gamebryolocalsavegames.cpp index 5d8cadf7..78801936 100644 --- a/src/gamebryo/gamebryolocalsavegames.cpp +++ b/src/gamebryo/gamebryolocalsavegames.cpp @@ -77,8 +77,8 @@ bool GamebryoLocalSavegames::prepareProfile(MOBase::IProfile *profile) if (!enable) { if (QFile::exists(QString(profile->absolutePath() + "/" + "savepath.ini"))) { saved = true; - GetPrivateProfileStringW(L"General", L"SLocalSavePath", NULL, savedPath, MAX_PATH, iniFilePath.toStdWString().c_str()); - GetPrivateProfileStringW(L"General", L"bUseMyGamesDirectory", NULL, savedMyGames, 1, iniFilePath.toStdWString().c_str()); + GetPrivateProfileStringW(L"General", L"SLocalSavePath", NULL, savedPath, MAX_PATH, QString(profile->absolutePath() + "/" + "savepath.ini").toStdWString().c_str()); + GetPrivateProfileStringW(L"General", L"bUseMyGamesDirectory", NULL, savedMyGames, 1, QString(profile->absolutePath() + "/" + "savepath.ini").toStdWString().c_str()); if (wcscmp(oldMyGames, L"") != 0) { savedDir = true; } @@ -113,7 +113,7 @@ bool GamebryoLocalSavegames::prepareProfile(MOBase::IProfile *profile) dirty = true; } } else { - if (wcscmp(oldPath, L"") != 0) { + if (wcscmp(oldPath, L"") == 0) { MOBase::WriteRegistryValue(L"General", L"SLocalSavePath", NULL, iniFilePath.toStdWString().c_str()); @@ -128,7 +128,7 @@ bool GamebryoLocalSavegames::prepareProfile(MOBase::IProfile *profile) dirty = true; } } else { - if (wcscmp(oldMyGames, L"") != 0) { + if (wcscmp(oldMyGames, L"") == 0) { MOBase::WriteRegistryValue(L"General", L"bUseMyGamesDirectory", NULL, iniFilePath.toStdWString().c_str()); From 82f0697f7a7616d04ab59d96f92fe43ed3de2204 Mon Sep 17 00:00:00 2001 From: LostDragonist Date: Thu, 14 Feb 2019 16:48:28 -0600 Subject: [PATCH 0729/1544] Fix one more --- src/gamebryo/gamebryolocalsavegames.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/gamebryo/gamebryolocalsavegames.cpp b/src/gamebryo/gamebryolocalsavegames.cpp index 78801936..5cdb6bc1 100644 --- a/src/gamebryo/gamebryolocalsavegames.cpp +++ b/src/gamebryo/gamebryolocalsavegames.cpp @@ -79,7 +79,7 @@ bool GamebryoLocalSavegames::prepareProfile(MOBase::IProfile *profile) saved = true; GetPrivateProfileStringW(L"General", L"SLocalSavePath", NULL, savedPath, MAX_PATH, QString(profile->absolutePath() + "/" + "savepath.ini").toStdWString().c_str()); GetPrivateProfileStringW(L"General", L"bUseMyGamesDirectory", NULL, savedMyGames, 1, QString(profile->absolutePath() + "/" + "savepath.ini").toStdWString().c_str()); - if (wcscmp(oldMyGames, L"") != 0) { + if (wcscmp(savedMyGames, L"") != 0) { savedDir = true; } QFile::remove(QString(profile->absolutePath() + "/" + "savepath.ini")); From 7c55f42371334b6489c008bb9ebfcd252f5ca50a Mon Sep 17 00:00:00 2001 From: Silarn Date: Sat, 16 Feb 2019 02:33:51 -0600 Subject: [PATCH 0730/1544] [game_skyrimse] Unify whitespace --- src/games/skyrimse/src/gameskyrimse.cpp | 62 ++++++++++++------------- 1 file changed, 31 insertions(+), 31 deletions(-) diff --git a/src/games/skyrimse/src/gameskyrimse.cpp b/src/games/skyrimse/src/gameskyrimse.cpp index 304a9057..b7188543 100644 --- a/src/games/skyrimse/src/gameskyrimse.cpp +++ b/src/games/skyrimse/src/gameskyrimse.cpp @@ -87,18 +87,18 @@ QString GameSkyrimSE::gameName() const QList GameSkyrimSE::executables() const { - return QList() - << ExecutableInfo("SKSE", findInGameFolder(feature()->loaderName())) - << ExecutableInfo("Skyrim Special Edition", findInGameFolder(binaryName())) - << ExecutableInfo("Skyrim Special Edition Launcher", findInGameFolder(getLauncherName())) - << ExecutableInfo("Creation Kit", findInGameFolder("CreationKit.exe")) - << ExecutableInfo("LOOT", getLootPath()).withArgument("--game=\"Skyrim Special Edition\"") - ; + return QList() + << ExecutableInfo("SKSE", findInGameFolder(feature()->loaderName())) + << ExecutableInfo("Skyrim Special Edition", findInGameFolder(binaryName())) + << ExecutableInfo("Skyrim Special Edition Launcher", findInGameFolder(getLauncherName())) + << ExecutableInfo("Creation Kit", findInGameFolder("CreationKit.exe")) + << ExecutableInfo("LOOT", getLootPath()).withArgument("--game=\"Skyrim Special Edition\"") + ; } QList GameSkyrimSE::executableForcedLoads() const { - return QList(); + return QList(); } QFileInfo GameSkyrimSE::findInGameFolder(const QString &relativePath) const @@ -173,11 +173,11 @@ QString GameSkyrimSE::steamAPPId() const } QStringList GameSkyrimSE::primaryPlugins() const { - QStringList plugins = { "skyrim.esm", "update.esm", "dawnguard.esm", "hearthfires.esm", "dragonborn.esm" }; + QStringList plugins = { "skyrim.esm", "update.esm", "dawnguard.esm", "hearthfires.esm", "dragonborn.esm" }; - plugins.append(CCPlugins()); + plugins.append(CCPlugins()); - return plugins; + return plugins; } QStringList GameSkyrimSE::gameVariants() const @@ -192,7 +192,7 @@ QString GameSkyrimSE::gameShortName() const QStringList GameSkyrimSE::validShortNames() const { - return { "Skyrim" }; + return { "Skyrim" }; } QString GameSkyrimSE::gameNexusName() const @@ -212,29 +212,29 @@ QStringList GameSkyrimSE::DLCPlugins() const QStringList GameSkyrimSE::CCPlugins() const { - QStringList plugins = {}; - QFile file(gameDirectory().filePath("Skyrim.ccc")); - if (file.open(QIODevice::ReadOnly)) { - ON_BLOCK_EXIT([&file]() { file.close(); }); + QStringList plugins = {}; + QFile file(gameDirectory().filePath("Skyrim.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 (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); + if (modName.size() > 0) { + if (!plugins.contains(modName, Qt::CaseInsensitive)) { + plugins.append(modName); + } + } } - } } - } - return plugins; + return plugins; } IPluginGame::LoadOrderMechanism GameSkyrimSE::loadOrderMechanism() const From b09ebb96827144805b31c5a3dfa6e006a54a388c Mon Sep 17 00:00:00 2001 From: Silarn Date: Sat, 16 Feb 2019 18:26:20 -0600 Subject: [PATCH 0731/1544] [game_fallout4vr] Remove "gamenexusname" and other incorrect Nexus refs from derived games - Fixes issues with incorrect plugin identification for downloads - Alternative Reg search for Enderal location --- src/games/fallout4vr/src/gamefallout4vr.cpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/games/fallout4vr/src/gamefallout4vr.cpp b/src/games/fallout4vr/src/gamefallout4vr.cpp index 0a5ea919..96ae2a26 100644 --- a/src/games/fallout4vr/src/gamefallout4vr.cpp +++ b/src/games/fallout4vr/src/gamefallout4vr.cpp @@ -155,7 +155,7 @@ QStringList GameFallout4VR::validShortNames() const QString GameFallout4VR::gameNexusName() const { - return "Fallout4"; + return QString(); } QStringList GameFallout4VR::iniFiles() const @@ -208,7 +208,7 @@ int GameFallout4VR::nexusModOrganizerID() const int GameFallout4VR::nexusGameID() const { - return 1151; + return 0; } QString GameFallout4VR::getLauncherName() const From 11161651029466dc5769fb4fdac8765e42076e5c Mon Sep 17 00:00:00 2001 From: Silarn Date: Sat, 16 Feb 2019 18:26:21 -0600 Subject: [PATCH 0732/1544] [game_skyrimvr] Remove "gamenexusname" and other incorrect Nexus refs from derived games - Fixes issues with incorrect plugin identification for downloads - Alternative Reg search for Enderal location --- src/games/skyrimvr/src/gameskyrimvr.cpp | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/src/games/skyrimvr/src/gameskyrimvr.cpp b/src/games/skyrimvr/src/gameskyrimvr.cpp index 4b557f23..4e867a9f 100644 --- a/src/games/skyrimvr/src/gameskyrimvr.cpp +++ b/src/games/skyrimvr/src/gameskyrimvr.cpp @@ -199,7 +199,7 @@ QStringList GameSkyrimVR::validShortNames() const QString GameSkyrimVR::gameNexusName() const { - return "skyrimspecialedition"; + return QString(); } @@ -252,12 +252,12 @@ MOBase::IPluginGame::SortMechanism GameSkyrimVR::sortMechanism() const int GameSkyrimVR::nexusModOrganizerID() const { - return 6194; + return 0; } int GameSkyrimVR::nexusGameID() const { - return 1704; + return 0; } QString GameSkyrimVR::getLauncherName() const From e31f9af4a66504fc06852dacc70b16153f1132ff Mon Sep 17 00:00:00 2001 From: Silarn Date: Sat, 16 Feb 2019 18:26:22 -0600 Subject: [PATCH 0733/1544] [game_ttw] Remove "gamenexusname" and other incorrect Nexus refs from derived games - Fixes issues with incorrect plugin identification for downloads - Alternative Reg search for Enderal location --- src/games/ttw/src/gamefalloutttw.cpp | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/src/games/ttw/src/gamefalloutttw.cpp b/src/games/ttw/src/gamefalloutttw.cpp index 1832b7cc..d488b3cb 100644 --- a/src/games/ttw/src/gamefalloutttw.cpp +++ b/src/games/ttw/src/gamefalloutttw.cpp @@ -179,7 +179,7 @@ QStringList GameFalloutTTW::validShortNames() const QString GameFalloutTTW::gameNexusName() const { - return "newvegas"; + return QString(); } QStringList GameFalloutTTW::iniFiles() const @@ -199,12 +199,12 @@ MOBase::IPluginGame::SortMechanism GameFalloutTTW::sortMechanism() const int GameFalloutTTW::nexusModOrganizerID() const { - return 42572; + return 0; } int GameFalloutTTW::nexusGameID() const { - return 130; + return 0; } QString GameFalloutTTW::getLauncherName() const From 6bc3924a8bbe3f7f0028a831590446bf8b0d1646 Mon Sep 17 00:00:00 2001 From: Silarn Date: Sat, 16 Feb 2019 18:27:34 -0600 Subject: [PATCH 0734/1544] [game_skyrim] Fix nexus name, which is not capitalized --- src/games/skyrim/src/gameskyrim.cpp | 450 ++++++++++++++-------------- 1 file changed, 225 insertions(+), 225 deletions(-) diff --git a/src/games/skyrim/src/gameskyrim.cpp b/src/games/skyrim/src/gameskyrim.cpp index 4f561a01..2c14adb3 100644 --- a/src/games/skyrim/src/gameskyrim.cpp +++ b/src/games/skyrim/src/gameskyrim.cpp @@ -1,225 +1,225 @@ -#include "gameskyrim.h" - -#include "skyrimbsainvalidation.h" -#include "skyrimscriptextender.h" -#include "skyrimdataarchives.h" -#include "skyrimsavegameinfo.h" -#include "skyrimgameplugins.h" - -#include "executableinfo.h" -#include "pluginsetting.h" - -#include -#include -#include - -#include -#include -#include - -#include - -#include -#include - -#include -#include -#include -#include -#include - -using namespace MOBase; - -GameSkyrim::GameSkyrim() -{ -} - -bool GameSkyrim::init(IOrganizer *moInfo) -{ - if (!GameGamebryo::init(moInfo)) { - return false; - } - registerFeature(new SkyrimScriptExtender(this)); - registerFeature(new SkyrimDataArchives(myGamesPath())); - registerFeature(new SkyrimBSAInvalidation(feature(), this)); - registerFeature(new SkyrimSaveGameInfo(this)); - registerFeature(new GamebryoLocalSavegames(myGamesPath(), "skyrim.ini")); - registerFeature(new SkyrimGamePlugins(moInfo)); - registerFeature(new GamebryoUnmangedMods(this)); - return true; -} - -QString GameSkyrim::gameName() const -{ - return "Skyrim"; -} - -QList GameSkyrim::executables() const -{ - return QList() - << ExecutableInfo("SKSE", findInGameFolder(feature()->loaderName())) - << ExecutableInfo("SBW", findInGameFolder("SBW.exe")) - << ExecutableInfo("Skyrim", findInGameFolder(binaryName())) - << ExecutableInfo("Skyrim Launcher", findInGameFolder(getLauncherName())) - << ExecutableInfo("BOSS", findInGameFolder("BOSS/BOSS.exe")) - << ExecutableInfo("LOOT", getLootPath()).withArgument("--game=\"Skyrim\"") - << ExecutableInfo("Creation Kit", findInGameFolder("CreationKit.exe")).withSteamAppId("202480") - ; -} - -QList GameSkyrim::executableForcedLoads() const -{ - return QList(); -} - -QString GameSkyrim::name() const -{ - return "Skyrim Support Plugin"; -} - -QString GameSkyrim::author() const -{ - return "Tannin"; -} - -QString GameSkyrim::description() const -{ - return tr("Adds support for the game Skyrim"); -} - -MOBase::VersionInfo GameSkyrim::version() const -{ - return VersionInfo(1, 3, 1, VersionInfo::RELEASE_FINAL); -} - -bool GameSkyrim::isActive() const -{ - return qApp->property("managed_game").value() == this; -} - -QList GameSkyrim::settings() const -{ - return QList(); -} - -void GameSkyrim::initializeProfile(const QDir &path, ProfileSettings settings) const -{ - if (settings.testFlag(IPluginGame::MODS)) { - copyToProfile(localAppFolder() + "/Skyrim", path, "plugins.txt"); - copyToProfile(localAppFolder() + "/Skyrim", path, "loadorder.txt"); - } - - if (settings.testFlag(IPluginGame::CONFIGURATION)) { - if (settings.testFlag(IPluginGame::PREFER_DEFAULTS) - || !QFileInfo(myGamesPath() + "/skyrim.ini").exists()) { - copyToProfile(gameDirectory().absolutePath(), path, "skyrim_default.ini", "skyrim.ini"); - } else { - copyToProfile(myGamesPath(), path, "skyrim.ini"); - } - - copyToProfile(myGamesPath(), path, "skyrimprefs.ini"); - } -} - -QString GameSkyrim::savegameExtension() const -{ - return "ess"; -} - -QString GameSkyrim::savegameSEExtension() const -{ - return "skse"; -} - -QString GameSkyrim::steamAPPId() const -{ - return "72850"; -} - -QStringList GameSkyrim::primaryPlugins() const -{ - return { "skyrim.esm", "update.esm" }; -} - -QString GameSkyrim::binaryName() const -{ - return "TESV.exe"; -} - -QString GameSkyrim::gameShortName() const -{ - return "Skyrim"; -} - -QString GameSkyrim::gameNexusName() const -{ - return "Skyrim"; -} - - -QStringList GameSkyrim::iniFiles() const -{ - return { "skyrim.ini", "skyrimprefs.ini" }; -} - -QStringList GameSkyrim::DLCPlugins() const -{ - return { "Dawnguard.esm", "Dragonborn.esm", "HearthFires.esm", - "HighResTexturePack01.esp", "HighResTexturePack02.esp", "HighResTexturePack03.esp" }; -} - -namespace { -//Note: This is ripped off from shared/util. And in an upcoming move, the fomod -//installer requires something similar. I suspect I should abstract this out -//into gamebryo (or lower level) - -VS_FIXEDFILEINFO GetFileVersion(const std::wstring &fileName) -{ - DWORD handle = 0UL; - DWORD size = ::GetFileVersionInfoSizeW(fileName.c_str(), &handle); - if (size == 0) { - throw std::runtime_error("failed to determine file version info size"); - } - - std::vector buffer(size); - handle = 0UL; - if (!::GetFileVersionInfoW(fileName.c_str(), handle, size, buffer.data())) { - throw std::runtime_error("failed to determine file version info"); - } - - void *versionInfoPtr = nullptr; - UINT versionInfoLength = 0; - if (!::VerQueryValue(buffer.data(), L"\\", &versionInfoPtr, &versionInfoLength)) { - throw std::runtime_error("failed to determine file version"); - } - - return *static_cast(versionInfoPtr); -} - -} - -IPluginGame::LoadOrderMechanism GameSkyrim::loadOrderMechanism() const -{ - try { - std::wstring fileName = gameDirectory().absoluteFilePath(binaryName()).toStdWString().c_str(); - VS_FIXEDFILEINFO versionInfo = ::GetFileVersion(fileName); - if ((versionInfo.dwFileVersionMS > 0x10004) || // version >= 1.5.x? - ((versionInfo.dwFileVersionMS == 0x10004) && (versionInfo.dwFileVersionLS >= 0x1A0000))) { // version >= ?.4.26 - return LoadOrderMechanism::PluginsTxt; - } - } catch (const std::exception &e) { - qCritical() << "TESV.exe is invalid: " << e.what(); - } - return LoadOrderMechanism::FileTime; -} - - -int GameSkyrim::nexusModOrganizerID() const -{ - return 1334; -} - -int GameSkyrim::nexusGameID() const -{ - return 110; -} +#include "gameskyrim.h" + +#include "skyrimbsainvalidation.h" +#include "skyrimscriptextender.h" +#include "skyrimdataarchives.h" +#include "skyrimsavegameinfo.h" +#include "skyrimgameplugins.h" + +#include "executableinfo.h" +#include "pluginsetting.h" + +#include +#include +#include + +#include +#include +#include + +#include + +#include +#include + +#include +#include +#include +#include +#include + +using namespace MOBase; + +GameSkyrim::GameSkyrim() +{ +} + +bool GameSkyrim::init(IOrganizer *moInfo) +{ + if (!GameGamebryo::init(moInfo)) { + return false; + } + registerFeature(new SkyrimScriptExtender(this)); + registerFeature(new SkyrimDataArchives(myGamesPath())); + registerFeature(new SkyrimBSAInvalidation(feature(), this)); + registerFeature(new SkyrimSaveGameInfo(this)); + registerFeature(new GamebryoLocalSavegames(myGamesPath(), "skyrim.ini")); + registerFeature(new SkyrimGamePlugins(moInfo)); + registerFeature(new GamebryoUnmangedMods(this)); + return true; +} + +QString GameSkyrim::gameName() const +{ + return "Skyrim"; +} + +QList GameSkyrim::executables() const +{ + return QList() + << ExecutableInfo("SKSE", findInGameFolder(feature()->loaderName())) + << ExecutableInfo("SBW", findInGameFolder("SBW.exe")) + << ExecutableInfo("Skyrim", findInGameFolder(binaryName())) + << ExecutableInfo("Skyrim Launcher", findInGameFolder(getLauncherName())) + << ExecutableInfo("BOSS", findInGameFolder("BOSS/BOSS.exe")) + << ExecutableInfo("LOOT", getLootPath()).withArgument("--game=\"Skyrim\"") + << ExecutableInfo("Creation Kit", findInGameFolder("CreationKit.exe")).withSteamAppId("202480") + ; +} + +QList GameSkyrim::executableForcedLoads() const +{ + return QList(); +} + +QString GameSkyrim::name() const +{ + return "Skyrim Support Plugin"; +} + +QString GameSkyrim::author() const +{ + return "Tannin"; +} + +QString GameSkyrim::description() const +{ + return tr("Adds support for the game Skyrim"); +} + +MOBase::VersionInfo GameSkyrim::version() const +{ + return VersionInfo(1, 3, 1, VersionInfo::RELEASE_FINAL); +} + +bool GameSkyrim::isActive() const +{ + return qApp->property("managed_game").value() == this; +} + +QList GameSkyrim::settings() const +{ + return QList(); +} + +void GameSkyrim::initializeProfile(const QDir &path, ProfileSettings settings) const +{ + if (settings.testFlag(IPluginGame::MODS)) { + copyToProfile(localAppFolder() + "/Skyrim", path, "plugins.txt"); + copyToProfile(localAppFolder() + "/Skyrim", path, "loadorder.txt"); + } + + if (settings.testFlag(IPluginGame::CONFIGURATION)) { + if (settings.testFlag(IPluginGame::PREFER_DEFAULTS) + || !QFileInfo(myGamesPath() + "/skyrim.ini").exists()) { + copyToProfile(gameDirectory().absolutePath(), path, "skyrim_default.ini", "skyrim.ini"); + } else { + copyToProfile(myGamesPath(), path, "skyrim.ini"); + } + + copyToProfile(myGamesPath(), path, "skyrimprefs.ini"); + } +} + +QString GameSkyrim::savegameExtension() const +{ + return "ess"; +} + +QString GameSkyrim::savegameSEExtension() const +{ + return "skse"; +} + +QString GameSkyrim::steamAPPId() const +{ + return "72850"; +} + +QStringList GameSkyrim::primaryPlugins() const +{ + return { "skyrim.esm", "update.esm" }; +} + +QString GameSkyrim::binaryName() const +{ + return "TESV.exe"; +} + +QString GameSkyrim::gameShortName() const +{ + return "Skyrim"; +} + +QString GameSkyrim::gameNexusName() const +{ + return "skyrim"; +} + + +QStringList GameSkyrim::iniFiles() const +{ + return { "skyrim.ini", "skyrimprefs.ini" }; +} + +QStringList GameSkyrim::DLCPlugins() const +{ + return { "Dawnguard.esm", "Dragonborn.esm", "HearthFires.esm", + "HighResTexturePack01.esp", "HighResTexturePack02.esp", "HighResTexturePack03.esp" }; +} + +namespace { +//Note: This is ripped off from shared/util. And in an upcoming move, the fomod +//installer requires something similar. I suspect I should abstract this out +//into gamebryo (or lower level) + +VS_FIXEDFILEINFO GetFileVersion(const std::wstring &fileName) +{ + DWORD handle = 0UL; + DWORD size = ::GetFileVersionInfoSizeW(fileName.c_str(), &handle); + if (size == 0) { + throw std::runtime_error("failed to determine file version info size"); + } + + std::vector buffer(size); + handle = 0UL; + if (!::GetFileVersionInfoW(fileName.c_str(), handle, size, buffer.data())) { + throw std::runtime_error("failed to determine file version info"); + } + + void *versionInfoPtr = nullptr; + UINT versionInfoLength = 0; + if (!::VerQueryValue(buffer.data(), L"\\", &versionInfoPtr, &versionInfoLength)) { + throw std::runtime_error("failed to determine file version"); + } + + return *static_cast(versionInfoPtr); +} + +} + +IPluginGame::LoadOrderMechanism GameSkyrim::loadOrderMechanism() const +{ + try { + std::wstring fileName = gameDirectory().absoluteFilePath(binaryName()).toStdWString().c_str(); + VS_FIXEDFILEINFO versionInfo = ::GetFileVersion(fileName); + if ((versionInfo.dwFileVersionMS > 0x10004) || // version >= 1.5.x? + ((versionInfo.dwFileVersionMS == 0x10004) && (versionInfo.dwFileVersionLS >= 0x1A0000))) { // version >= ?.4.26 + return LoadOrderMechanism::PluginsTxt; + } + } catch (const std::exception &e) { + qCritical() << "TESV.exe is invalid: " << e.what(); + } + return LoadOrderMechanism::FileTime; +} + + +int GameSkyrim::nexusModOrganizerID() const +{ + return 0; +} + +int GameSkyrim::nexusGameID() const +{ + return 110; +} From 38ddb4967c67ec49c863a25e5f5abf45488cecd6 Mon Sep 17 00:00:00 2001 From: LostDragonist Date: Sun, 17 Feb 2019 21:16:34 -0600 Subject: [PATCH 0735/1544] [game_skyrim] Fix issue with deleting save games The .skse save game extension is handled by savegameSEExtension. Defining it for saveGameAttachmentExtensions is double-dipping and causing errors. --- src/games/skyrim/src/skyrimscriptextender.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/games/skyrim/src/skyrimscriptextender.cpp b/src/games/skyrim/src/skyrimscriptextender.cpp index 6c56dbe1..352bd01e 100644 --- a/src/games/skyrim/src/skyrimscriptextender.cpp +++ b/src/games/skyrim/src/skyrimscriptextender.cpp @@ -20,5 +20,5 @@ QString SkyrimScriptExtender::PluginPath() const QStringList SkyrimScriptExtender::saveGameAttachmentExtensions() const { - return { "skse" }; + return { }; } From 60600304a9eb75048f33d6023e86933e1cb50c0f Mon Sep 17 00:00:00 2001 From: LostDragonist Date: Sun, 17 Mar 2019 17:54:54 -0500 Subject: [PATCH 0736/1544] [game_oblivion] Fix reading and writing archive list This was using SResourceArchiveList when it should have been using SArchiveList --- src/games/oblivion/src/obliviondataarchives.cpp | 11 ++--------- 1 file changed, 2 insertions(+), 9 deletions(-) diff --git a/src/games/oblivion/src/obliviondataarchives.cpp b/src/games/oblivion/src/obliviondataarchives.cpp index e94dbdc5..51d35e18 100644 --- a/src/games/oblivion/src/obliviondataarchives.cpp +++ b/src/games/oblivion/src/obliviondataarchives.cpp @@ -22,8 +22,7 @@ QStringList OblivionDataArchives::archives(const MOBase::IProfile *profile) cons QStringList result; QString iniFile = profile->localSettingsEnabled() ? QDir(profile->absolutePath()).absoluteFilePath("oblivion.ini") : m_LocalGameDir.absoluteFilePath("oblivion.ini"); - result.append(getArchivesFromKey(iniFile, "SResourceArchiveList")); - result.append(getArchivesFromKey(iniFile, "SResourceArchiveList2")); + result.append(getArchivesFromKey(iniFile, "SArchiveList")); return result; } @@ -33,11 +32,5 @@ void OblivionDataArchives::writeArchiveList(MOBase::IProfile *profile, const QSt QString list = before.join(", "); QString iniFile = profile->localSettingsEnabled() ? QDir(profile->absolutePath()).absoluteFilePath("oblivion.ini") : m_LocalGameDir.absoluteFilePath("oblivion.ini"); - if (list.length() > 255) { - int splitIdx = list.lastIndexOf(",", 256); - setArchivesToKey(iniFile, "SResourceArchiveList", list.mid(0, splitIdx)); - setArchivesToKey(iniFile, "SResourceArchiveList2", list.mid(splitIdx + 2)); - } else { - setArchivesToKey(iniFile, "SResourceArchiveList", list); - } + setArchivesToKey(iniFile, "SArchiveList", list); } From e3ec5f617cdb7a86900a329a58cdf6e4abac162b Mon Sep 17 00:00:00 2001 From: Lepresidente Date: Fri, 26 Apr 2019 15:01:10 +0200 Subject: [PATCH 0737/1544] [game_fallout4vr] support appveyor. --- src/games/fallout4vr/appveyor.yml | 30 ++++++++++++++++++++++++++++++ 1 file changed, 30 insertions(+) create mode 100644 src/games/fallout4vr/appveyor.yml diff --git a/src/games/fallout4vr/appveyor.yml b/src/games/fallout4vr/appveyor.yml new file mode 100644 index 00000000..9b92260f --- /dev/null +++ b/src/games/fallout4vr/appveyor.yml @@ -0,0 +1,30 @@ +version: 1.0.{build} +skip_branch_with_pr: true +image: Visual Studio 2017 +environment: + WEBHOOK_URL: + secure: gOKbXaZM9ImtMD5XrYITvdyZUW/az082G9OIN1EC1Vbg57wBaeLhi49uGjxPw5GVujHku6kxN6ab89zhbS5GVeluR76GM83IbKV4Sh7udXzoYZZdg6YudtYHzdhCgUeiedpswbuczTq9ceIkkfSEWZuh/lMAAVVwvcGsJAnoPFw= +build_script: +- cmd: >- + git clone --depth=1 --branch=%APPVEYOR_REPO_BRANCH% https://github.com/ModOrganizer2/modorganizer-umbrella.git c:\projects\modorganizer-umbrella 2> $null + + mkdir c:\projects\modorganizer-build -type directory + + cd c:\projects\modorganizer-umbrella + + C:\Python37-x64\python.exe unimake.py -d c:\projects\modorganizer-build -s Appveyor_Build=True %APPVEYOR_PROJECT_NAME% +artifacts: +- path: vsbuild\src\RelWithDebInfo\game_fallout4vr.dll + name: game_fallout4vr_dll +- path: vsbuild\src\RelWithDebInfo\game_fallout4vr.pdb + name: game_fallout4vr_pdb +- path: vsbuild\src\RelWithDebInfo\game_fallout4vr.lib + name: game_fallout4vr_lib +on_success: + - ps: Set-Location -Path $env:APPVEYOR_BUILD_FOLDER + - ps: Invoke-RestMethod https://raw.githubusercontent.com/DiscordHooks/appveyor-discord-webhook/master/send.ps1 -o send.ps1 + - ps: ./send.ps1 success $env:WEBHOOK_URL +on_failure: + - ps: Set-Location -Path $env:APPVEYOR_BUILD_FOLDER + - ps: Invoke-RestMethod https://raw.githubusercontent.com/DiscordHooks/appveyor-discord-webhook/master/send.ps1 -o send.ps1 + - ps: ./send.ps1 failure $env:WEBHOOK_URL \ No newline at end of file From c5f6c138ba92f0f306c9aa5677cd84c2598793fe Mon Sep 17 00:00:00 2001 From: LePresidente Date: Fri, 26 Apr 2019 19:21:48 +0200 Subject: [PATCH 0738/1544] [game_oblivion] Support Appveyor. --- src/games/oblivion/appveyor.yml | 30 +++++++++++++++++++++++++++ src/games/oblivion/src/CMakeLists.txt | 3 ++- 2 files changed, 32 insertions(+), 1 deletion(-) create mode 100644 src/games/oblivion/appveyor.yml diff --git a/src/games/oblivion/appveyor.yml b/src/games/oblivion/appveyor.yml new file mode 100644 index 00000000..84facb2b --- /dev/null +++ b/src/games/oblivion/appveyor.yml @@ -0,0 +1,30 @@ +version: 1.0.{build} +skip_branch_with_pr: true +image: Visual Studio 2017 +environment: + WEBHOOK_URL: + secure: gOKbXaZM9ImtMD5XrYITvdyZUW/az082G9OIN1EC1Vbg57wBaeLhi49uGjxPw5GVujHku6kxN6ab89zhbS5GVeluR76GM83IbKV4Sh7udXzoYZZdg6YudtYHzdhCgUeiedpswbuczTq9ceIkkfSEWZuh/lMAAVVwvcGsJAnoPFw= +build_script: +- cmd: >- + git clone --depth=1 --branch=%APPVEYOR_REPO_BRANCH% https://github.com/ModOrganizer2/modorganizer-umbrella.git c:\projects\modorganizer-umbrella 2> $null + + mkdir c:\projects\modorganizer-build -type directory + + cd c:\projects\modorganizer-umbrella + + C:\Python37-x64\python.exe unimake.py -d c:\projects\modorganizer-build -s Appveyor_Build=True %APPVEYOR_PROJECT_NAME% +artifacts: +- path: vsbuild\src\RelWithDebInfo\game_oblivion.dll + name: game_oblivion_dll +- path: vsbuild\src\RelWithDebInfo\game_oblivion.pdb + name: game_oblivion_pdb +- path: vsbuild\src\RelWithDebInfo\game_oblivion.lib + name: game_oblivion_lib +on_success: + - ps: Set-Location -Path $env:APPVEYOR_BUILD_FOLDER + - ps: Invoke-RestMethod https://raw.githubusercontent.com/DiscordHooks/appveyor-discord-webhook/master/send.ps1 -o send.ps1 + - ps: ./send.ps1 success $env:WEBHOOK_URL +on_failure: + - ps: Set-Location -Path $env:APPVEYOR_BUILD_FOLDER + - ps: Invoke-RestMethod https://raw.githubusercontent.com/DiscordHooks/appveyor-discord-webhook/master/send.ps1 -o send.ps1 + - ps: ./send.ps1 failure $env:WEBHOOK_URL \ No newline at end of file diff --git a/src/games/oblivion/src/CMakeLists.txt b/src/games/oblivion/src/CMakeLists.txt index dbeec13c..c4e00ffa 100644 --- a/src/games/oblivion/src/CMakeLists.txt +++ b/src/games/oblivion/src/CMakeLists.txt @@ -13,7 +13,8 @@ SET(CMAKE_AUTOUIC ON) FIND_PACKAGE(Qt5Widgets REQUIRED) QT5_WRAP_UI(${PROJ_NAME}_UIHDRS ${${PROJ_NAME}_FORMS}) -SET(default_project_path "${CMAKE_SOURCE_DIR}/..") +# MO projects +SET(default_project_path "${DEPENDENCIES_DIR}/modorganizer_super") GET_FILENAME_COMPONENT(${default_project_path} ${default_project_path} REALPATH) SET(project_path "${default_project_path}" CACHE PATH "path to the other mo projects") From 5ec56763232d36b1fde388c3194542aa9f5f96fd Mon Sep 17 00:00:00 2001 From: LePresidente Date: Fri, 26 Apr 2019 19:36:23 +0200 Subject: [PATCH 0739/1544] [game_morrowind] Support Appveyor. --- src/games/morrowind/appveyor.yml | 30 ++++++++++++++++++++++++++ src/games/morrowind/src/CMakeLists.txt | 2 +- 2 files changed, 31 insertions(+), 1 deletion(-) create mode 100644 src/games/morrowind/appveyor.yml diff --git a/src/games/morrowind/appveyor.yml b/src/games/morrowind/appveyor.yml new file mode 100644 index 00000000..3d3dfb0e --- /dev/null +++ b/src/games/morrowind/appveyor.yml @@ -0,0 +1,30 @@ +version: 1.0.{build} +skip_branch_with_pr: true +image: Visual Studio 2017 +environment: + WEBHOOK_URL: + secure: gOKbXaZM9ImtMD5XrYITvdyZUW/az082G9OIN1EC1Vbg57wBaeLhi49uGjxPw5GVujHku6kxN6ab89zhbS5GVeluR76GM83IbKV4Sh7udXzoYZZdg6YudtYHzdhCgUeiedpswbuczTq9ceIkkfSEWZuh/lMAAVVwvcGsJAnoPFw= +build_script: +- cmd: >- + git clone --depth=1 --branch=%APPVEYOR_REPO_BRANCH% https://github.com/ModOrganizer2/modorganizer-umbrella.git c:\projects\modorganizer-umbrella 2> $null + + mkdir c:\projects\modorganizer-build -type directory + + cd c:\projects\modorganizer-umbrella + + C:\Python37-x64\python.exe unimake.py -d c:\projects\modorganizer-build -s Appveyor_Build=True %APPVEYOR_PROJECT_NAME% +artifacts: +- path: vsbuild\src\RelWithDebInfo\game_morrowind.dll + name: game_morrowind_dll +- path: vsbuild\src\RelWithDebInfo\game_morrowind.pdb + name: game_morrowind_pdb +- path: vsbuild\src\RelWithDebInfo\game_morrowind.lib + name: game_morrowind_lib +on_success: + - ps: Set-Location -Path $env:APPVEYOR_BUILD_FOLDER + - ps: Invoke-RestMethod https://raw.githubusercontent.com/DiscordHooks/appveyor-discord-webhook/master/send.ps1 -o send.ps1 + - ps: ./send.ps1 success $env:WEBHOOK_URL +on_failure: + - ps: Set-Location -Path $env:APPVEYOR_BUILD_FOLDER + - ps: Invoke-RestMethod https://raw.githubusercontent.com/DiscordHooks/appveyor-discord-webhook/master/send.ps1 -o send.ps1 + - ps: ./send.ps1 failure $env:WEBHOOK_URL \ No newline at end of file diff --git a/src/games/morrowind/src/CMakeLists.txt b/src/games/morrowind/src/CMakeLists.txt index b85a3aa9..858502b8 100644 --- a/src/games/morrowind/src/CMakeLists.txt +++ b/src/games/morrowind/src/CMakeLists.txt @@ -17,7 +17,7 @@ FIND_PACKAGE(Qt5Widgets REQUIRED) QT5_WRAP_UI(${PROJ_NAME}_UIHDRS ${${PROJ_NAME}_FORMS}) QT5_ADD_RESOURCES(${PROJ_NAME}_RCCPPS ${${PROJ_NAME}_QRCS}) -SET(default_project_path "${CMAKE_SOURCE_DIR}/..") +SET(default_project_path "${DEPENDENCIES_DIR}/modorganizer_super") GET_FILENAME_COMPONENT(${default_project_path} ${default_project_path} REALPATH) SET(project_path "${default_project_path}" CACHE PATH "path to the other mo projects") From 20a18bc9c9325600c6427e090c69daabd5ca4045 Mon Sep 17 00:00:00 2001 From: LePresidente Date: Sun, 28 Apr 2019 09:11:07 +0200 Subject: [PATCH 0740/1544] [game_fallout3] Support Appveyor --- src/games/fallout3/appveyor.yml | 30 +++++++++++++++++++++++++++ src/games/fallout3/src/CMakeLists.txt | 2 +- 2 files changed, 31 insertions(+), 1 deletion(-) create mode 100644 src/games/fallout3/appveyor.yml diff --git a/src/games/fallout3/appveyor.yml b/src/games/fallout3/appveyor.yml new file mode 100644 index 00000000..c4a4e799 --- /dev/null +++ b/src/games/fallout3/appveyor.yml @@ -0,0 +1,30 @@ +version: 1.0.{build} +skip_branch_with_pr: true +image: Visual Studio 2017 +environment: + WEBHOOK_URL: + secure: gOKbXaZM9ImtMD5XrYITvdyZUW/az082G9OIN1EC1Vbg57wBaeLhi49uGjxPw5GVujHku6kxN6ab89zhbS5GVeluR76GM83IbKV4Sh7udXzoYZZdg6YudtYHzdhCgUeiedpswbuczTq9ceIkkfSEWZuh/lMAAVVwvcGsJAnoPFw= +build_script: +- cmd: >- + git clone --depth=1 --branch=%APPVEYOR_REPO_BRANCH% https://github.com/ModOrganizer2/modorganizer-umbrella.git c:\projects\modorganizer-umbrella 2> $null + + mkdir c:\projects\modorganizer-build -type directory + + cd c:\projects\modorganizer-umbrella + + C:\Python37-x64\python.exe unimake.py -d c:\projects\modorganizer-build -s Appveyor_Build=True %APPVEYOR_PROJECT_NAME% +artifacts: +- path: vsbuild\src\RelWithDebInfo\game_fallout3.dll + name: game_fallout3_dll +- path: vsbuild\src\RelWithDebInfo\game_fallout3.pdb + name: game_fallout3_pdb +- path: vsbuild\src\RelWithDebInfo\game_fallout3.lib + name: game_fallout3_lib +on_success: + - ps: Set-Location -Path $env:APPVEYOR_BUILD_FOLDER + - ps: Invoke-RestMethod https://raw.githubusercontent.com/DiscordHooks/appveyor-discord-webhook/master/send.ps1 -o send.ps1 + - ps: ./send.ps1 success $env:WEBHOOK_URL +on_failure: + - ps: Set-Location -Path $env:APPVEYOR_BUILD_FOLDER + - ps: Invoke-RestMethod https://raw.githubusercontent.com/DiscordHooks/appveyor-discord-webhook/master/send.ps1 -o send.ps1 + - ps: ./send.ps1 failure $env:WEBHOOK_URL \ No newline at end of file diff --git a/src/games/fallout3/src/CMakeLists.txt b/src/games/fallout3/src/CMakeLists.txt index de7f7d7b..1edcce5c 100644 --- a/src/games/fallout3/src/CMakeLists.txt +++ b/src/games/fallout3/src/CMakeLists.txt @@ -13,7 +13,7 @@ SET(CMAKE_AUTOUIC ON) FIND_PACKAGE(Qt5Widgets REQUIRED) QT5_WRAP_UI(${PROJ_NAME}_UIHDRS ${${PROJ_NAME}_FORMS}) -SET(default_project_path "${CMAKE_SOURCE_DIR}/..") +SET(default_project_path "${DEPENDENCIES_DIR}/modorganizer_super") GET_FILENAME_COMPONENT(${default_project_path} ${default_project_path} REALPATH) SET(project_path "${default_project_path}" CACHE PATH "path to the other mo projects") From 47d79c806f77e1386f3621fbfda17b7a5f451725 Mon Sep 17 00:00:00 2001 From: LePresidente Date: Sun, 28 Apr 2019 09:14:54 +0200 Subject: [PATCH 0741/1544] [game_fallout4] Support Appveyor. --- src/games/fallout4/appveyor.yml | 30 +++++++++++++++++++++++++++ src/games/fallout4/src/CMakeLists.txt | 2 +- 2 files changed, 31 insertions(+), 1 deletion(-) create mode 100644 src/games/fallout4/appveyor.yml diff --git a/src/games/fallout4/appveyor.yml b/src/games/fallout4/appveyor.yml new file mode 100644 index 00000000..9e2b4685 --- /dev/null +++ b/src/games/fallout4/appveyor.yml @@ -0,0 +1,30 @@ +version: 1.0.{build} +skip_branch_with_pr: true +image: Visual Studio 2017 +environment: + WEBHOOK_URL: + secure: gOKbXaZM9ImtMD5XrYITvdyZUW/az082G9OIN1EC1Vbg57wBaeLhi49uGjxPw5GVujHku6kxN6ab89zhbS5GVeluR76GM83IbKV4Sh7udXzoYZZdg6YudtYHzdhCgUeiedpswbuczTq9ceIkkfSEWZuh/lMAAVVwvcGsJAnoPFw= +build_script: +- cmd: >- + git clone --depth=1 --branch=%APPVEYOR_REPO_BRANCH% https://github.com/ModOrganizer2/modorganizer-umbrella.git c:\projects\modorganizer-umbrella 2> $null + + mkdir c:\projects\modorganizer-build -type directory + + cd c:\projects\modorganizer-umbrella + + C:\Python37-x64\python.exe unimake.py -d c:\projects\modorganizer-build -s Appveyor_Build=True %APPVEYOR_PROJECT_NAME% +artifacts: +- path: vsbuild\src\RelWithDebInfo\game_fallout4.dll + name: game_fallout4_dll +- path: vsbuild\src\RelWithDebInfo\game_fallout4.pdb + name: game_fallout4_pdb +- path: vsbuild\src\RelWithDebInfo\game_fallout4.lib + name: game_fallout4_lib +on_success: + - ps: Set-Location -Path $env:APPVEYOR_BUILD_FOLDER + - ps: Invoke-RestMethod https://raw.githubusercontent.com/DiscordHooks/appveyor-discord-webhook/master/send.ps1 -o send.ps1 + - ps: ./send.ps1 success $env:WEBHOOK_URL +on_failure: + - ps: Set-Location -Path $env:APPVEYOR_BUILD_FOLDER + - ps: Invoke-RestMethod https://raw.githubusercontent.com/DiscordHooks/appveyor-discord-webhook/master/send.ps1 -o send.ps1 + - ps: ./send.ps1 failure $env:WEBHOOK_URL \ No newline at end of file diff --git a/src/games/fallout4/src/CMakeLists.txt b/src/games/fallout4/src/CMakeLists.txt index b5897bb7..944a7ae0 100644 --- a/src/games/fallout4/src/CMakeLists.txt +++ b/src/games/fallout4/src/CMakeLists.txt @@ -17,7 +17,7 @@ FIND_PACKAGE(Qt5Widgets REQUIRED) QT5_WRAP_UI(${PROJ_NAME}_UIHDRS ${${PROJ_NAME}_FORMS}) QT5_ADD_RESOURCES(${PROJ_NAME}_RCCPPS ${${PROJ_NAME}_QRCS}) -SET(default_project_path "${CMAKE_SOURCE_DIR}/..") +SET(default_project_path "${DEPENDENCIES_DIR}/modorganizer_super") GET_FILENAME_COMPONENT(${default_project_path} ${default_project_path} REALPATH) SET(project_path "${default_project_path}" CACHE PATH "path to the other mo projects") From 20dc6ecb7338f3312bfad26e16ea4ca0e515ac4f Mon Sep 17 00:00:00 2001 From: LePresidente Date: Sun, 28 Apr 2019 09:17:00 +0200 Subject: [PATCH 0742/1544] [game_fallout4vr] Use DEPENDENCIES_DIR variable to find modorganizer_super folder. --- src/games/fallout4vr/src/CMakeLists.txt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/games/fallout4vr/src/CMakeLists.txt b/src/games/fallout4vr/src/CMakeLists.txt index d0a23423..186dab28 100644 --- a/src/games/fallout4vr/src/CMakeLists.txt +++ b/src/games/fallout4vr/src/CMakeLists.txt @@ -17,7 +17,7 @@ FIND_PACKAGE(Qt5Widgets REQUIRED) QT5_WRAP_UI(${PROJ_NAME}_UIHDRS ${${PROJ_NAME}_FORMS}) QT5_ADD_RESOURCES(${PROJ_NAME}_RCCPPS ${${PROJ_NAME}_QRCS}) -SET(default_project_path "${CMAKE_SOURCE_DIR}/..") +SET(default_project_path "${DEPENDENCIES_DIR}/modorganizer_super") GET_FILENAME_COMPONENT(${default_project_path} ${default_project_path} REALPATH) SET(project_path "${default_project_path}" CACHE PATH "path to the other mo projects") From 41266264b19b79a74f49ef59c3f8cc5e6668bdd1 Mon Sep 17 00:00:00 2001 From: LePresidente Date: Sun, 28 Apr 2019 09:22:02 +0200 Subject: [PATCH 0743/1544] [game_falloutnv] Support Appveyor --- src/games/falloutnv/appveyor.yml | 30 ++++++++++++++++++++++++++ src/games/falloutnv/src/CMakeLists.txt | 2 +- 2 files changed, 31 insertions(+), 1 deletion(-) create mode 100644 src/games/falloutnv/appveyor.yml diff --git a/src/games/falloutnv/appveyor.yml b/src/games/falloutnv/appveyor.yml new file mode 100644 index 00000000..5f45e9b8 --- /dev/null +++ b/src/games/falloutnv/appveyor.yml @@ -0,0 +1,30 @@ +version: 1.0.{build} +skip_branch_with_pr: true +image: Visual Studio 2017 +environment: + WEBHOOK_URL: + secure: gOKbXaZM9ImtMD5XrYITvdyZUW/az082G9OIN1EC1Vbg57wBaeLhi49uGjxPw5GVujHku6kxN6ab89zhbS5GVeluR76GM83IbKV4Sh7udXzoYZZdg6YudtYHzdhCgUeiedpswbuczTq9ceIkkfSEWZuh/lMAAVVwvcGsJAnoPFw= +build_script: +- cmd: >- + git clone --depth=1 --branch=%APPVEYOR_REPO_BRANCH% https://github.com/ModOrganizer2/modorganizer-umbrella.git c:\projects\modorganizer-umbrella 2> $null + + mkdir c:\projects\modorganizer-build -type directory + + cd c:\projects\modorganizer-umbrella + + C:\Python37-x64\python.exe unimake.py -d c:\projects\modorganizer-build -s Appveyor_Build=True %APPVEYOR_PROJECT_NAME% +artifacts: +- path: vsbuild\src\RelWithDebInfo\game_falloutNV.dll + name: game_falloutNV_dll +- path: vsbuild\src\RelWithDebInfo\game_falloutNV.pdb + name: game_falloutNV_pdb +- path: vsbuild\src\RelWithDebInfo\game_falloutNV.lib + name: game_falloutNVe_lib +on_success: + - ps: Set-Location -Path $env:APPVEYOR_BUILD_FOLDER + - ps: Invoke-RestMethod https://raw.githubusercontent.com/DiscordHooks/appveyor-discord-webhook/master/send.ps1 -o send.ps1 + - ps: ./send.ps1 success $env:WEBHOOK_URL +on_failure: + - ps: Set-Location -Path $env:APPVEYOR_BUILD_FOLDER + - ps: Invoke-RestMethod https://raw.githubusercontent.com/DiscordHooks/appveyor-discord-webhook/master/send.ps1 -o send.ps1 + - ps: ./send.ps1 failure $env:WEBHOOK_URL \ No newline at end of file diff --git a/src/games/falloutnv/src/CMakeLists.txt b/src/games/falloutnv/src/CMakeLists.txt index de7f7d7b..1edcce5c 100644 --- a/src/games/falloutnv/src/CMakeLists.txt +++ b/src/games/falloutnv/src/CMakeLists.txt @@ -13,7 +13,7 @@ SET(CMAKE_AUTOUIC ON) FIND_PACKAGE(Qt5Widgets REQUIRED) QT5_WRAP_UI(${PROJ_NAME}_UIHDRS ${${PROJ_NAME}_FORMS}) -SET(default_project_path "${CMAKE_SOURCE_DIR}/..") +SET(default_project_path "${DEPENDENCIES_DIR}/modorganizer_super") GET_FILENAME_COMPONENT(${default_project_path} ${default_project_path} REALPATH) SET(project_path "${default_project_path}" CACHE PATH "path to the other mo projects") From 0464c8bf19a3f62586785939ced263efd956d5df Mon Sep 17 00:00:00 2001 From: LePresidente Date: Sun, 28 Apr 2019 09:25:00 +0200 Subject: [PATCH 0744/1544] Support Appveyor. --- appveyor.yml | 28 ++++++++++++++++++++++++++++ src/creation/CMakeLists.txt | 2 +- src/gamebryo/CMakeLists.txt | 2 +- 3 files changed, 30 insertions(+), 2 deletions(-) create mode 100644 appveyor.yml diff --git a/appveyor.yml b/appveyor.yml new file mode 100644 index 00000000..320ef7bd --- /dev/null +++ b/appveyor.yml @@ -0,0 +1,28 @@ +version: 1.0.{build} +skip_branch_with_pr: true +image: Visual Studio 2017 +environment: + WEBHOOK_URL: + secure: gOKbXaZM9ImtMD5XrYITvdyZUW/az082G9OIN1EC1Vbg57wBaeLhi49uGjxPw5GVujHku6kxN6ab89zhbS5GVeluR76GM83IbKV4Sh7udXzoYZZdg6YudtYHzdhCgUeiedpswbuczTq9ceIkkfSEWZuh/lMAAVVwvcGsJAnoPFw= +build_script: +- cmd: >- + git clone --depth=1 --branch=%APPVEYOR_REPO_BRANCH% https://github.com/ModOrganizer2/modorganizer-umbrella.git c:\projects\modorganizer-umbrella 2> $null + + mkdir c:\projects\modorganizer-build -type directory + + cd c:\projects\modorganizer-umbrella + + C:\Python37-x64\python.exe unimake.py -d c:\projects\modorganizer-build -s Appveyor_Build=True %APPVEYOR_PROJECT_NAME% +artifacts: +- path: vsbuild\src\gamebryo\RelWithDebInfo\game_gamebryo.lib + name: game_gamebryo_lib +- path: vsbuild\src\creation\RelWithDebInfo\game_creation.lib + name: game_creation_lib +on_success: + - ps: Set-Location -Path $env:APPVEYOR_BUILD_FOLDER + - ps: Invoke-RestMethod https://raw.githubusercontent.com/DiscordHooks/appveyor-discord-webhook/master/send.ps1 -o send.ps1 + - ps: ./send.ps1 success $env:WEBHOOK_URL +on_failure: + - ps: Set-Location -Path $env:APPVEYOR_BUILD_FOLDER + - ps: Invoke-RestMethod https://raw.githubusercontent.com/DiscordHooks/appveyor-discord-webhook/master/send.ps1 -o send.ps1 + - ps: ./send.ps1 failure $env:WEBHOOK_URL \ No newline at end of file diff --git a/src/creation/CMakeLists.txt b/src/creation/CMakeLists.txt index bff1180f..0e72f905 100644 --- a/src/creation/CMakeLists.txt +++ b/src/creation/CMakeLists.txt @@ -24,7 +24,7 @@ IF (Boost_FOUND) INCLUDE_DIRECTORIES(${Boost_INCLUDE_DIRS}) ENDIF (Boost_FOUND) -SET(default_project_path "${CMAKE_SOURCE_DIR}/..") +SET(default_project_path "${DEPENDENCIES_DIR}/modorganizer_super") GET_FILENAME_COMPONENT(${default_project_path} ${default_project_path} REALPATH) SET(project_path "${default_project_path}" CACHE PATH "path to the other mo projects") diff --git a/src/gamebryo/CMakeLists.txt b/src/gamebryo/CMakeLists.txt index 84c4dd42..9a604b81 100644 --- a/src/gamebryo/CMakeLists.txt +++ b/src/gamebryo/CMakeLists.txt @@ -21,7 +21,7 @@ IF (Boost_FOUND) INCLUDE_DIRECTORIES(${Boost_INCLUDE_DIRS}) ENDIF (Boost_FOUND) -SET(default_project_path "${CMAKE_SOURCE_DIR}/..") +SET(default_project_path "${DEPENDENCIES_DIR}/modorganizer_super") GET_FILENAME_COMPONENT(${default_project_path} ${default_project_path} REALPATH) SET(project_path "${default_project_path}" CACHE PATH "path to the other mo projects") From 40a666dcf6cc685083ee41a6c515cf413a7ea922 Mon Sep 17 00:00:00 2001 From: LePresidente Date: Sun, 28 Apr 2019 09:58:03 +0200 Subject: [PATCH 0745/1544] [game_ttw] Support Appveyor. --- src/games/ttw/appveyor.yml | 30 ++++++++++++++++++++++++++++++ src/games/ttw/src/CMakeLists.txt | 2 +- 2 files changed, 31 insertions(+), 1 deletion(-) create mode 100644 src/games/ttw/appveyor.yml diff --git a/src/games/ttw/appveyor.yml b/src/games/ttw/appveyor.yml new file mode 100644 index 00000000..04c6be15 --- /dev/null +++ b/src/games/ttw/appveyor.yml @@ -0,0 +1,30 @@ +version: 1.0.{build} +skip_branch_with_pr: true +image: Visual Studio 2017 +environment: + WEBHOOK_URL: + secure: gOKbXaZM9ImtMD5XrYITvdyZUW/az082G9OIN1EC1Vbg57wBaeLhi49uGjxPw5GVujHku6kxN6ab89zhbS5GVeluR76GM83IbKV4Sh7udXzoYZZdg6YudtYHzdhCgUeiedpswbuczTq9ceIkkfSEWZuh/lMAAVVwvcGsJAnoPFw= +build_script: +- cmd: >- + git clone --depth=1 --branch=%APPVEYOR_REPO_BRANCH% https://github.com/ModOrganizer2/modorganizer-umbrella.git c:\projects\modorganizer-umbrella 2> $null + + mkdir c:\projects\modorganizer-build -type directory + + cd c:\projects\modorganizer-umbrella + + C:\Python37-x64\python.exe unimake.py -d c:\projects\modorganizer-build -s Appveyor_Build=True %APPVEYOR_PROJECT_NAME% +artifacts: +- path: vsbuild\src\RelWithDebInfo\game_ttw.dll + name: game_ttw_dll +- path: vsbuild\src\RelWithDebInfo\game_ttw.pdb + name: game_ttw_pdb +- path: vsbuild\src\RelWithDebInfo\game_ttw.lib + name: game_ttw_lib +on_success: + - ps: Set-Location -Path $env:APPVEYOR_BUILD_FOLDER + - ps: Invoke-RestMethod https://raw.githubusercontent.com/DiscordHooks/appveyor-discord-webhook/master/send.ps1 -o send.ps1 + - ps: ./send.ps1 success $env:WEBHOOK_URL +on_failure: + - ps: Set-Location -Path $env:APPVEYOR_BUILD_FOLDER + - ps: Invoke-RestMethod https://raw.githubusercontent.com/DiscordHooks/appveyor-discord-webhook/master/send.ps1 -o send.ps1 + - ps: ./send.ps1 failure $env:WEBHOOK_URL \ No newline at end of file diff --git a/src/games/ttw/src/CMakeLists.txt b/src/games/ttw/src/CMakeLists.txt index de7f7d7b..1edcce5c 100644 --- a/src/games/ttw/src/CMakeLists.txt +++ b/src/games/ttw/src/CMakeLists.txt @@ -13,7 +13,7 @@ SET(CMAKE_AUTOUIC ON) FIND_PACKAGE(Qt5Widgets REQUIRED) QT5_WRAP_UI(${PROJ_NAME}_UIHDRS ${${PROJ_NAME}_FORMS}) -SET(default_project_path "${CMAKE_SOURCE_DIR}/..") +SET(default_project_path "${DEPENDENCIES_DIR}/modorganizer_super") GET_FILENAME_COMPONENT(${default_project_path} ${default_project_path} REALPATH) SET(project_path "${default_project_path}" CACHE PATH "path to the other mo projects") From 8a5f8451b6ab00067aae29daae049ee0662d2397 Mon Sep 17 00:00:00 2001 From: LePresidente Date: Sun, 28 Apr 2019 10:01:09 +0200 Subject: [PATCH 0746/1544] [game_skyrim] Support Appveyor. --- src/games/skyrim/appveyor.yml | 30 +++++++++++++++++++++++++++++ src/games/skyrim/src/CMakeLists.txt | 2 +- 2 files changed, 31 insertions(+), 1 deletion(-) create mode 100644 src/games/skyrim/appveyor.yml diff --git a/src/games/skyrim/appveyor.yml b/src/games/skyrim/appveyor.yml new file mode 100644 index 00000000..4bd3f9a2 --- /dev/null +++ b/src/games/skyrim/appveyor.yml @@ -0,0 +1,30 @@ +version: 1.0.{build} +skip_branch_with_pr: true +image: Visual Studio 2017 +environment: + WEBHOOK_URL: + secure: gOKbXaZM9ImtMD5XrYITvdyZUW/az082G9OIN1EC1Vbg57wBaeLhi49uGjxPw5GVujHku6kxN6ab89zhbS5GVeluR76GM83IbKV4Sh7udXzoYZZdg6YudtYHzdhCgUeiedpswbuczTq9ceIkkfSEWZuh/lMAAVVwvcGsJAnoPFw= +build_script: +- cmd: >- + git clone --depth=1 --branch=%APPVEYOR_REPO_BRANCH% https://github.com/ModOrganizer2/modorganizer-umbrella.git c:\projects\modorganizer-umbrella 2> $null + + mkdir c:\projects\modorganizer-build -type directory + + cd c:\projects\modorganizer-umbrella + + C:\Python37-x64\python.exe unimake.py -d c:\projects\modorganizer-build -s Appveyor_Build=True %APPVEYOR_PROJECT_NAME% +artifacts: +- path: vsbuild\src\RelWithDebInfo\game_skyrim.dll + name: game_skyrim_dll +- path: vsbuild\src\RelWithDebInfo\game_skyrim.pdb + name: game_skyrim_pdb +- path: vsbuild\src\RelWithDebInfo\game_skyrim.lib + name: game_skyrim_lib +on_success: + - ps: Set-Location -Path $env:APPVEYOR_BUILD_FOLDER + - ps: Invoke-RestMethod https://raw.githubusercontent.com/DiscordHooks/appveyor-discord-webhook/master/send.ps1 -o send.ps1 + - ps: ./send.ps1 success $env:WEBHOOK_URL +on_failure: + - ps: Set-Location -Path $env:APPVEYOR_BUILD_FOLDER + - ps: Invoke-RestMethod https://raw.githubusercontent.com/DiscordHooks/appveyor-discord-webhook/master/send.ps1 -o send.ps1 + - ps: ./send.ps1 failure $env:WEBHOOK_URL \ No newline at end of file diff --git a/src/games/skyrim/src/CMakeLists.txt b/src/games/skyrim/src/CMakeLists.txt index b4228951..52334248 100644 --- a/src/games/skyrim/src/CMakeLists.txt +++ b/src/games/skyrim/src/CMakeLists.txt @@ -13,7 +13,7 @@ SET(CMAKE_AUTOUIC ON) FIND_PACKAGE(Qt5Widgets REQUIRED) QT5_WRAP_UI(${PROJ_NAME}_UIHDRS ${${PROJ_NAME}_FORMS}) -SET(default_project_path "${CMAKE_SOURCE_DIR}/..") +SET(default_project_path "${DEPENDENCIES_DIR}/modorganizer_super") GET_FILENAME_COMPONENT(${default_project_path} ${default_project_path} REALPATH) SET(project_path "${default_project_path}" CACHE PATH "path to the other mo projects") From efa562858b84b094996ae9d09dba980156fc059f Mon Sep 17 00:00:00 2001 From: LePresidente Date: Mon, 29 Apr 2019 07:05:07 +0200 Subject: [PATCH 0747/1544] [game_skyrimse] Support Appveyor. --- src/games/skyrimse/appveyor.yml | 30 +++++++++++++++++++++++++++ src/games/skyrimse/src/CMakeLists.txt | 2 +- 2 files changed, 31 insertions(+), 1 deletion(-) create mode 100644 src/games/skyrimse/appveyor.yml diff --git a/src/games/skyrimse/appveyor.yml b/src/games/skyrimse/appveyor.yml new file mode 100644 index 00000000..5ac0b2e8 --- /dev/null +++ b/src/games/skyrimse/appveyor.yml @@ -0,0 +1,30 @@ +version: 1.0.{build} +skip_branch_with_pr: true +image: Visual Studio 2017 +environment: + WEBHOOK_URL: + secure: gOKbXaZM9ImtMD5XrYITvdyZUW/az082G9OIN1EC1Vbg57wBaeLhi49uGjxPw5GVujHku6kxN6ab89zhbS5GVeluR76GM83IbKV4Sh7udXzoYZZdg6YudtYHzdhCgUeiedpswbuczTq9ceIkkfSEWZuh/lMAAVVwvcGsJAnoPFw= +build_script: +- cmd: >- + git clone --depth=1 --branch=%APPVEYOR_REPO_BRANCH% https://github.com/ModOrganizer2/modorganizer-umbrella.git c:\projects\modorganizer-umbrella 2> $null + + mkdir c:\projects\modorganizer-build -type directory + + cd c:\projects\modorganizer-umbrella + + C:\Python37-x64\python.exe unimake.py -d c:\projects\modorganizer-build -s Appveyor_Build=True %APPVEYOR_PROJECT_NAME% +artifacts: +- path: vsbuild\src\RelWithDebInfo\game_skyrimse.dll + name: game_skyrimse_dll +- path: vsbuild\src\RelWithDebInfo\game_skyrimse.pdb + name: game_skyrimse_pdb +- path: vsbuild\src\RelWithDebInfo\game_skyrimse.lib + name: game_skyrimse_lib +on_success: + - ps: Set-Location -Path $env:APPVEYOR_BUILD_FOLDER + - ps: Invoke-RestMethod https://raw.githubusercontent.com/DiscordHooks/appveyor-discord-webhook/master/send.ps1 -o send.ps1 + - ps: ./send.ps1 success $env:WEBHOOK_URL +on_failure: + - ps: Set-Location -Path $env:APPVEYOR_BUILD_FOLDER + - ps: Invoke-RestMethod https://raw.githubusercontent.com/DiscordHooks/appveyor-discord-webhook/master/send.ps1 -o send.ps1 + - ps: ./send.ps1 failure $env:WEBHOOK_URL \ No newline at end of file diff --git a/src/games/skyrimse/src/CMakeLists.txt b/src/games/skyrimse/src/CMakeLists.txt index 6281cdb9..229b1708 100644 --- a/src/games/skyrimse/src/CMakeLists.txt +++ b/src/games/skyrimse/src/CMakeLists.txt @@ -13,7 +13,7 @@ SET(CMAKE_AUTOUIC ON) FIND_PACKAGE(Qt5Widgets REQUIRED) QT5_WRAP_UI(${PROJ_NAME}_UIHDRS ${${PROJ_NAME}_FORMS}) -SET(default_project_path "${CMAKE_SOURCE_DIR}/..") +SET(default_project_path "${DEPENDENCIES_DIR}/modorganizer_super") GET_FILENAME_COMPONENT(${default_project_path} ${default_project_path} REALPATH) SET(project_path "${default_project_path}" CACHE PATH "path to the other mo projects") From d1d12a5948436c4e4cb8b1516b877b14987d5ce0 Mon Sep 17 00:00:00 2001 From: LePresidente Date: Mon, 29 Apr 2019 10:02:27 +0200 Subject: [PATCH 0748/1544] [game_skyrimvr] Support Appveyor. --- src/games/skyrimvr/appveyor.yml | 30 +++++++++++++++++++++++++++ src/games/skyrimvr/src/CMakeLists.txt | 2 +- 2 files changed, 31 insertions(+), 1 deletion(-) create mode 100644 src/games/skyrimvr/appveyor.yml diff --git a/src/games/skyrimvr/appveyor.yml b/src/games/skyrimvr/appveyor.yml new file mode 100644 index 00000000..a1c916fa --- /dev/null +++ b/src/games/skyrimvr/appveyor.yml @@ -0,0 +1,30 @@ +version: 1.0.{build} +skip_branch_with_pr: true +image: Visual Studio 2017 +environment: + WEBHOOK_URL: + secure: gOKbXaZM9ImtMD5XrYITvdyZUW/az082G9OIN1EC1Vbg57wBaeLhi49uGjxPw5GVujHku6kxN6ab89zhbS5GVeluR76GM83IbKV4Sh7udXzoYZZdg6YudtYHzdhCgUeiedpswbuczTq9ceIkkfSEWZuh/lMAAVVwvcGsJAnoPFw= +build_script: +- cmd: >- + git clone --depth=1 --branch=%APPVEYOR_REPO_BRANCH% https://github.com/ModOrganizer2/modorganizer-umbrella.git c:\projects\modorganizer-umbrella 2> $null + + mkdir c:\projects\modorganizer-build -type directory + + cd c:\projects\modorganizer-umbrella + + C:\Python37-x64\python.exe unimake.py -d c:\projects\modorganizer-build -s Appveyor_Build=True %APPVEYOR_PROJECT_NAME% +artifacts: +- path: vsbuild\src\RelWithDebInfo\game_skyrimvr.dll + name: game_skyrimvr_dll +- path: vsbuild\src\RelWithDebInfo\game_skyrimvr.pdb + name: game_skyrimvr_pdb +- path: vsbuild\src\RelWithDebInfo\game_skyrimvr.lib + name: game_skyrimvr_lib +on_success: + - ps: Set-Location -Path $env:APPVEYOR_BUILD_FOLDER + - ps: Invoke-RestMethod https://raw.githubusercontent.com/DiscordHooks/appveyor-discord-webhook/master/send.ps1 -o send.ps1 + - ps: ./send.ps1 success $env:WEBHOOK_URL +on_failure: + - ps: Set-Location -Path $env:APPVEYOR_BUILD_FOLDER + - ps: Invoke-RestMethod https://raw.githubusercontent.com/DiscordHooks/appveyor-discord-webhook/master/send.ps1 -o send.ps1 + - ps: ./send.ps1 failure $env:WEBHOOK_URL \ No newline at end of file diff --git a/src/games/skyrimvr/src/CMakeLists.txt b/src/games/skyrimvr/src/CMakeLists.txt index 6281cdb9..229b1708 100644 --- a/src/games/skyrimvr/src/CMakeLists.txt +++ b/src/games/skyrimvr/src/CMakeLists.txt @@ -13,7 +13,7 @@ SET(CMAKE_AUTOUIC ON) FIND_PACKAGE(Qt5Widgets REQUIRED) QT5_WRAP_UI(${PROJ_NAME}_UIHDRS ${${PROJ_NAME}_FORMS}) -SET(default_project_path "${CMAKE_SOURCE_DIR}/..") +SET(default_project_path "${DEPENDENCIES_DIR}/modorganizer_super") GET_FILENAME_COMPONENT(${default_project_path} ${default_project_path} REALPATH) SET(project_path "${default_project_path}" CACHE PATH "path to the other mo projects") From f92ba507110977d2b4a20b06e942ec31a97bbf11 Mon Sep 17 00:00:00 2001 From: Silarn Date: Wed, 8 May 2019 23:02:44 -0500 Subject: [PATCH 0749/1544] [game_fallout4vr] Modify LZ4 paths to support building from source --- src/games/fallout4vr/src/CMakeLists.txt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/games/fallout4vr/src/CMakeLists.txt b/src/games/fallout4vr/src/CMakeLists.txt index 186dab28..59e9f9d1 100644 --- a/src/games/fallout4vr/src/CMakeLists.txt +++ b/src/games/fallout4vr/src/CMakeLists.txt @@ -43,7 +43,7 @@ INCLUDE_DIRECTORIES(${project_path}/uibase/src ${project_path}/game_gamebryo/src/creation) LINK_DIRECTORIES(${project_path}/uibase/build/src ${lib_path} - ${LZ4_ROOT}/dll) + ${LZ4_ROOT}/bin) ADD_LIBRARY(${PROJ_NAME} SHARED ${${PROJ_NAME}_HDRS} ${${PROJ_NAME}_SRCS} ${${PROJ_NAME}_UIHDRS} ${${PROJ_NAME}_RCCPPS} ${${PROJ_NAME}_translations_qm}) From 06ab86897c45697536bbece8579870506529cfc5 Mon Sep 17 00:00:00 2001 From: Silarn Date: Wed, 8 May 2019 23:02:45 -0500 Subject: [PATCH 0750/1544] [game_morrowind] Modify LZ4 paths to support building from source --- src/games/morrowind/src/CMakeLists.txt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/games/morrowind/src/CMakeLists.txt b/src/games/morrowind/src/CMakeLists.txt index 858502b8..46ad05b3 100644 --- a/src/games/morrowind/src/CMakeLists.txt +++ b/src/games/morrowind/src/CMakeLists.txt @@ -42,7 +42,7 @@ INCLUDE_DIRECTORIES(${project_path}/uibase/src ${project_path}/game_gamebryo/src/gamebryo) LINK_DIRECTORIES(${project_path}/uibase/build/src ${lib_path} - ${LZ4_ROOT}/dll) + ${LZ4_ROOT}/bin) ADD_DEFINITIONS(-DUNICODE -D_UNICODE) From 51d79aa15423842f37a8a1d9948d50ba261b817b Mon Sep 17 00:00:00 2001 From: Silarn Date: Wed, 8 May 2019 23:02:46 -0500 Subject: [PATCH 0751/1544] [game_falloutnv] Modify LZ4 paths to support building from source --- src/games/falloutnv/src/CMakeLists.txt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/games/falloutnv/src/CMakeLists.txt b/src/games/falloutnv/src/CMakeLists.txt index 1edcce5c..4c3f4d45 100644 --- a/src/games/falloutnv/src/CMakeLists.txt +++ b/src/games/falloutnv/src/CMakeLists.txt @@ -38,7 +38,7 @@ INCLUDE_DIRECTORIES(${project_path}/uibase/src ${project_path}/game_gamebryo/src/gamebryo) LINK_DIRECTORIES(${project_path}/uibase/build/src ${lib_path} - ${LZ4_ROOT}/dll) + ${LZ4_ROOT}/bin) ADD_LIBRARY(${PROJ_NAME} SHARED ${${PROJ_NAME}_HDRS} ${${PROJ_NAME}_SRCS} ${${PROJ_NAME}_UIHDRS} ${${PROJ_NAME}_translations_qm}) From 996e0d6a63958bb5fd1c9ff12a564020bf9dd071 Mon Sep 17 00:00:00 2001 From: Silarn Date: Wed, 8 May 2019 23:02:47 -0500 Subject: [PATCH 0752/1544] [game_oblivion] Modify LZ4 paths to support building from source --- src/games/oblivion/src/CMakeLists.txt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/games/oblivion/src/CMakeLists.txt b/src/games/oblivion/src/CMakeLists.txt index c4e00ffa..5d15b3bc 100644 --- a/src/games/oblivion/src/CMakeLists.txt +++ b/src/games/oblivion/src/CMakeLists.txt @@ -39,7 +39,7 @@ INCLUDE_DIRECTORIES(${project_path}/uibase/src ${project_path}/game_gamebryo/src/gamebryo) LINK_DIRECTORIES(${project_path}/uibase/build/src ${lib_path} - ${LZ4_ROOT}/dll) + ${LZ4_ROOT}/bin) ADD_LIBRARY(${PROJ_NAME} SHARED ${${PROJ_NAME}_HDRS} ${${PROJ_NAME}_SRCS} ${${PROJ_NAME}_UIHDRS} ${${PROJ_NAME}_translations_qm}) From 2c10cdd56d35f5390dd0e5430e9ab052034baef2 Mon Sep 17 00:00:00 2001 From: Silarn Date: Wed, 8 May 2019 23:02:47 -0500 Subject: [PATCH 0753/1544] Modify LZ4 paths to support building from source --- src/creation/CMakeLists.txt | 4 ++-- src/gamebryo/CMakeLists.txt | 4 ++-- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/src/creation/CMakeLists.txt b/src/creation/CMakeLists.txt index 0e72f905..f046fb3f 100644 --- a/src/creation/CMakeLists.txt +++ b/src/creation/CMakeLists.txt @@ -35,9 +35,9 @@ SET(plugin_path "${project_path}") INCLUDE_DIRECTORIES(../gamebryo ${project_path}/uibase/src ${project_path}/game_features/src - ${LZ4_ROOT}/include) + ${LZ4_ROOT}/lib) LINK_DIRECTORIES(${lib_path} - ${LZ4_ROOT}/dll) + ${LZ4_ROOT}/bin) ADD_LIBRARY(${PROJ_NAME} STATIC ${${PROJ_NAME}_HDRS} ${${PROJ_NAME}_SRCS} ${${PROJ_NAME}_UIHDRS}) TARGET_LINK_LIBRARIES(${PROJ_NAME} diff --git a/src/gamebryo/CMakeLists.txt b/src/gamebryo/CMakeLists.txt index 9a604b81..f01a69d4 100644 --- a/src/gamebryo/CMakeLists.txt +++ b/src/gamebryo/CMakeLists.txt @@ -31,10 +31,10 @@ SET(plugin_path "${project_path}") INCLUDE_DIRECTORIES(${project_path}/uibase/src ${project_path}/game_features/src - ${LZ4_ROOT}/include) + ${LZ4_ROOT}/lib) LINK_DIRECTORIES(${lib_path} - ${LZ4_ROOT}/dll) + ${LZ4_ROOT}/bin) ADD_LIBRARY(${PROJ_NAME} STATIC ${${PROJ_NAME}_HDRS} ${${PROJ_NAME}_SRCS} ${${PROJ_NAME}_UIHDRS}) TARGET_LINK_LIBRARIES(${PROJ_NAME} From 378d081b2b55091423386ce0eed196230f790fda Mon Sep 17 00:00:00 2001 From: Silarn Date: Wed, 8 May 2019 23:02:48 -0500 Subject: [PATCH 0754/1544] [game_fallout3] Modify LZ4 paths to support building from source --- src/games/fallout3/src/CMakeLists.txt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/games/fallout3/src/CMakeLists.txt b/src/games/fallout3/src/CMakeLists.txt index 1edcce5c..4c3f4d45 100644 --- a/src/games/fallout3/src/CMakeLists.txt +++ b/src/games/fallout3/src/CMakeLists.txt @@ -38,7 +38,7 @@ INCLUDE_DIRECTORIES(${project_path}/uibase/src ${project_path}/game_gamebryo/src/gamebryo) LINK_DIRECTORIES(${project_path}/uibase/build/src ${lib_path} - ${LZ4_ROOT}/dll) + ${LZ4_ROOT}/bin) ADD_LIBRARY(${PROJ_NAME} SHARED ${${PROJ_NAME}_HDRS} ${${PROJ_NAME}_SRCS} ${${PROJ_NAME}_UIHDRS} ${${PROJ_NAME}_translations_qm}) From 1061b75c51a04b8f8b533d1ff0878d3c34a68cde Mon Sep 17 00:00:00 2001 From: Silarn Date: Wed, 8 May 2019 23:02:49 -0500 Subject: [PATCH 0755/1544] [game_fallout4] Modify LZ4 paths to support building from source --- src/games/fallout4/src/CMakeLists.txt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/games/fallout4/src/CMakeLists.txt b/src/games/fallout4/src/CMakeLists.txt index 944a7ae0..79f44159 100644 --- a/src/games/fallout4/src/CMakeLists.txt +++ b/src/games/fallout4/src/CMakeLists.txt @@ -43,7 +43,7 @@ INCLUDE_DIRECTORIES(${project_path}/uibase/src ${project_path}/game_gamebryo/src/creation) LINK_DIRECTORIES(${project_path}/uibase/build/src ${lib_path} - ${LZ4_ROOT}/dll) + ${LZ4_ROOT}/bin) ADD_LIBRARY(${PROJ_NAME} SHARED ${${PROJ_NAME}_HDRS} ${${PROJ_NAME}_SRCS} ${${PROJ_NAME}_UIHDRS} ${${PROJ_NAME}_RCCPPS} ${${PROJ_NAME}_translations_qm}) From 3227852b29b9ce6d5ee49b070d08a24842b5ca19 Mon Sep 17 00:00:00 2001 From: Silarn Date: Wed, 8 May 2019 23:02:49 -0500 Subject: [PATCH 0756/1544] [game_skyrimvr] Modify LZ4 paths to support building from source --- src/games/skyrimvr/src/CMakeLists.txt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/games/skyrimvr/src/CMakeLists.txt b/src/games/skyrimvr/src/CMakeLists.txt index 229b1708..9145cb06 100644 --- a/src/games/skyrimvr/src/CMakeLists.txt +++ b/src/games/skyrimvr/src/CMakeLists.txt @@ -39,7 +39,7 @@ INCLUDE_DIRECTORIES(${project_path}/uibase/src ${project_path}/game_gamebryo/src/creation) LINK_DIRECTORIES(${project_path}/uibase/build/src ${lib_path} - ${LZ4_ROOT}/dll) + ${LZ4_ROOT}/bin) ADD_DEFINITIONS(-DUNICODE -D_UNICODE) From f2d4b1a725fcc1822e4269ce909b65f088829dc9 Mon Sep 17 00:00:00 2001 From: Silarn Date: Wed, 8 May 2019 23:02:50 -0500 Subject: [PATCH 0757/1544] [game_skyrimse] Modify LZ4 paths to support building from source --- src/games/skyrimse/src/CMakeLists.txt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/games/skyrimse/src/CMakeLists.txt b/src/games/skyrimse/src/CMakeLists.txt index 229b1708..9145cb06 100644 --- a/src/games/skyrimse/src/CMakeLists.txt +++ b/src/games/skyrimse/src/CMakeLists.txt @@ -39,7 +39,7 @@ INCLUDE_DIRECTORIES(${project_path}/uibase/src ${project_path}/game_gamebryo/src/creation) LINK_DIRECTORIES(${project_path}/uibase/build/src ${lib_path} - ${LZ4_ROOT}/dll) + ${LZ4_ROOT}/bin) ADD_DEFINITIONS(-DUNICODE -D_UNICODE) From caede60c2c45c9971150163cf4929bdfdfdd173a Mon Sep 17 00:00:00 2001 From: Silarn Date: Wed, 8 May 2019 23:02:52 -0500 Subject: [PATCH 0758/1544] [game_skyrim] Modify LZ4 paths to support building from source --- src/games/skyrim/src/CMakeLists.txt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/games/skyrim/src/CMakeLists.txt b/src/games/skyrim/src/CMakeLists.txt index 52334248..b2916ad6 100644 --- a/src/games/skyrim/src/CMakeLists.txt +++ b/src/games/skyrim/src/CMakeLists.txt @@ -38,7 +38,7 @@ INCLUDE_DIRECTORIES(${project_path}/uibase/src ${project_path}/game_gamebryo/src/gamebryo) LINK_DIRECTORIES(${project_path}/uibase/build/src ${lib_path} - ${LZ4_ROOT}/dll) + ${LZ4_ROOT}/bin) ADD_DEFINITIONS(-DUNICODE -D_UNICODE) From d2ca9cd1c989bf523eb38deda16c0d236dec82ed Mon Sep 17 00:00:00 2001 From: Silarn Date: Wed, 8 May 2019 23:02:53 -0500 Subject: [PATCH 0759/1544] [game_ttw] Modify LZ4 paths to support building from source --- src/games/ttw/src/CMakeLists.txt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/games/ttw/src/CMakeLists.txt b/src/games/ttw/src/CMakeLists.txt index 1edcce5c..4c3f4d45 100644 --- a/src/games/ttw/src/CMakeLists.txt +++ b/src/games/ttw/src/CMakeLists.txt @@ -38,7 +38,7 @@ INCLUDE_DIRECTORIES(${project_path}/uibase/src ${project_path}/game_gamebryo/src/gamebryo) LINK_DIRECTORIES(${project_path}/uibase/build/src ${lib_path} - ${LZ4_ROOT}/dll) + ${LZ4_ROOT}/bin) ADD_LIBRARY(${PROJ_NAME} SHARED ${${PROJ_NAME}_HDRS} ${${PROJ_NAME}_SRCS} ${${PROJ_NAME}_UIHDRS} ${${PROJ_NAME}_translations_qm}) From a09a4a9a262c750cede6accd3f433ff10c50570f Mon Sep 17 00:00:00 2001 From: Silarn Date: Wed, 8 May 2019 23:10:30 -0500 Subject: [PATCH 0760/1544] [game_fallout4vr] Set appveyor image to VS 2019 Preview --- src/games/fallout4vr/appveyor.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/games/fallout4vr/appveyor.yml b/src/games/fallout4vr/appveyor.yml index 9b92260f..06b4a902 100644 --- a/src/games/fallout4vr/appveyor.yml +++ b/src/games/fallout4vr/appveyor.yml @@ -1,6 +1,6 @@ version: 1.0.{build} skip_branch_with_pr: true -image: Visual Studio 2017 +image: Visual Studio 2019 Preview environment: WEBHOOK_URL: secure: gOKbXaZM9ImtMD5XrYITvdyZUW/az082G9OIN1EC1Vbg57wBaeLhi49uGjxPw5GVujHku6kxN6ab89zhbS5GVeluR76GM83IbKV4Sh7udXzoYZZdg6YudtYHzdhCgUeiedpswbuczTq9ceIkkfSEWZuh/lMAAVVwvcGsJAnoPFw= From 60de0b67d89ff7527f972abde553d3a379ccfe5a Mon Sep 17 00:00:00 2001 From: Silarn Date: Wed, 8 May 2019 23:10:31 -0500 Subject: [PATCH 0761/1544] [game_morrowind] Set appveyor image to VS 2019 Preview --- src/games/morrowind/appveyor.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/games/morrowind/appveyor.yml b/src/games/morrowind/appveyor.yml index 3d3dfb0e..970fcfca 100644 --- a/src/games/morrowind/appveyor.yml +++ b/src/games/morrowind/appveyor.yml @@ -1,6 +1,6 @@ version: 1.0.{build} skip_branch_with_pr: true -image: Visual Studio 2017 +image: Visual Studio 2019 Preview environment: WEBHOOK_URL: secure: gOKbXaZM9ImtMD5XrYITvdyZUW/az082G9OIN1EC1Vbg57wBaeLhi49uGjxPw5GVujHku6kxN6ab89zhbS5GVeluR76GM83IbKV4Sh7udXzoYZZdg6YudtYHzdhCgUeiedpswbuczTq9ceIkkfSEWZuh/lMAAVVwvcGsJAnoPFw= From 86058ab5284a106431304e4bf4dfcda999ac3203 Mon Sep 17 00:00:00 2001 From: Silarn Date: Wed, 8 May 2019 23:10:33 -0500 Subject: [PATCH 0762/1544] [game_falloutnv] Set appveyor image to VS 2019 Preview --- src/games/falloutnv/appveyor.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/games/falloutnv/appveyor.yml b/src/games/falloutnv/appveyor.yml index 5f45e9b8..e903c0e9 100644 --- a/src/games/falloutnv/appveyor.yml +++ b/src/games/falloutnv/appveyor.yml @@ -1,6 +1,6 @@ version: 1.0.{build} skip_branch_with_pr: true -image: Visual Studio 2017 +image: Visual Studio 2019 Preview environment: WEBHOOK_URL: secure: gOKbXaZM9ImtMD5XrYITvdyZUW/az082G9OIN1EC1Vbg57wBaeLhi49uGjxPw5GVujHku6kxN6ab89zhbS5GVeluR76GM83IbKV4Sh7udXzoYZZdg6YudtYHzdhCgUeiedpswbuczTq9ceIkkfSEWZuh/lMAAVVwvcGsJAnoPFw= From 3e97c7782433531d4e755ac8f6475f6412da958b Mon Sep 17 00:00:00 2001 From: Silarn Date: Wed, 8 May 2019 23:10:34 -0500 Subject: [PATCH 0763/1544] [game_skyrimse] Set appveyor image to VS 2019 Preview --- src/games/skyrimse/appveyor.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/games/skyrimse/appveyor.yml b/src/games/skyrimse/appveyor.yml index 5ac0b2e8..63da474d 100644 --- a/src/games/skyrimse/appveyor.yml +++ b/src/games/skyrimse/appveyor.yml @@ -1,6 +1,6 @@ version: 1.0.{build} skip_branch_with_pr: true -image: Visual Studio 2017 +image: Visual Studio 2019 Preview environment: WEBHOOK_URL: secure: gOKbXaZM9ImtMD5XrYITvdyZUW/az082G9OIN1EC1Vbg57wBaeLhi49uGjxPw5GVujHku6kxN6ab89zhbS5GVeluR76GM83IbKV4Sh7udXzoYZZdg6YudtYHzdhCgUeiedpswbuczTq9ceIkkfSEWZuh/lMAAVVwvcGsJAnoPFw= From 60d0a2ee5c10458a68cb0cadcc8f1960dea67754 Mon Sep 17 00:00:00 2001 From: Silarn Date: Wed, 8 May 2019 23:10:35 -0500 Subject: [PATCH 0764/1544] [game_oblivion] Set appveyor image to VS 2019 Preview --- src/games/oblivion/appveyor.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/games/oblivion/appveyor.yml b/src/games/oblivion/appveyor.yml index 84facb2b..4416bebe 100644 --- a/src/games/oblivion/appveyor.yml +++ b/src/games/oblivion/appveyor.yml @@ -1,6 +1,6 @@ version: 1.0.{build} skip_branch_with_pr: true -image: Visual Studio 2017 +image: Visual Studio 2019 Preview environment: WEBHOOK_URL: secure: gOKbXaZM9ImtMD5XrYITvdyZUW/az082G9OIN1EC1Vbg57wBaeLhi49uGjxPw5GVujHku6kxN6ab89zhbS5GVeluR76GM83IbKV4Sh7udXzoYZZdg6YudtYHzdhCgUeiedpswbuczTq9ceIkkfSEWZuh/lMAAVVwvcGsJAnoPFw= From 119ee3a7d1b7948cebc2a8b72477f91b68cb6d73 Mon Sep 17 00:00:00 2001 From: Silarn Date: Wed, 8 May 2019 23:10:36 -0500 Subject: [PATCH 0765/1544] Set appveyor image to VS 2019 Preview --- appveyor.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/appveyor.yml b/appveyor.yml index 320ef7bd..62b1d262 100644 --- a/appveyor.yml +++ b/appveyor.yml @@ -1,6 +1,6 @@ version: 1.0.{build} skip_branch_with_pr: true -image: Visual Studio 2017 +image: Visual Studio 2019 Preview environment: WEBHOOK_URL: secure: gOKbXaZM9ImtMD5XrYITvdyZUW/az082G9OIN1EC1Vbg57wBaeLhi49uGjxPw5GVujHku6kxN6ab89zhbS5GVeluR76GM83IbKV4Sh7udXzoYZZdg6YudtYHzdhCgUeiedpswbuczTq9ceIkkfSEWZuh/lMAAVVwvcGsJAnoPFw= From 1566d5c4d5661b9bc7192dea96e00b6209c2fd25 Mon Sep 17 00:00:00 2001 From: Silarn Date: Wed, 8 May 2019 23:10:36 -0500 Subject: [PATCH 0766/1544] [game_fallout3] Set appveyor image to VS 2019 Preview --- src/games/fallout3/appveyor.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/games/fallout3/appveyor.yml b/src/games/fallout3/appveyor.yml index c4a4e799..4941d681 100644 --- a/src/games/fallout3/appveyor.yml +++ b/src/games/fallout3/appveyor.yml @@ -1,6 +1,6 @@ version: 1.0.{build} skip_branch_with_pr: true -image: Visual Studio 2017 +image: Visual Studio 2019 Preview environment: WEBHOOK_URL: secure: gOKbXaZM9ImtMD5XrYITvdyZUW/az082G9OIN1EC1Vbg57wBaeLhi49uGjxPw5GVujHku6kxN6ab89zhbS5GVeluR76GM83IbKV4Sh7udXzoYZZdg6YudtYHzdhCgUeiedpswbuczTq9ceIkkfSEWZuh/lMAAVVwvcGsJAnoPFw= From 3089a3beb229b6bc3435853a0680978e8144ab60 Mon Sep 17 00:00:00 2001 From: Silarn Date: Wed, 8 May 2019 23:10:37 -0500 Subject: [PATCH 0767/1544] [game_fallout4] Set appveyor image to VS 2019 Preview --- src/games/fallout4/appveyor.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/games/fallout4/appveyor.yml b/src/games/fallout4/appveyor.yml index 9e2b4685..3c05999c 100644 --- a/src/games/fallout4/appveyor.yml +++ b/src/games/fallout4/appveyor.yml @@ -1,6 +1,6 @@ version: 1.0.{build} skip_branch_with_pr: true -image: Visual Studio 2017 +image: Visual Studio 2019 Preview environment: WEBHOOK_URL: secure: gOKbXaZM9ImtMD5XrYITvdyZUW/az082G9OIN1EC1Vbg57wBaeLhi49uGjxPw5GVujHku6kxN6ab89zhbS5GVeluR76GM83IbKV4Sh7udXzoYZZdg6YudtYHzdhCgUeiedpswbuczTq9ceIkkfSEWZuh/lMAAVVwvcGsJAnoPFw= From f6dd4a64388510154cb0e999f31af9f57032520b Mon Sep 17 00:00:00 2001 From: Silarn Date: Wed, 8 May 2019 23:10:37 -0500 Subject: [PATCH 0768/1544] [game_skyrimvr] Set appveyor image to VS 2019 Preview --- src/games/skyrimvr/appveyor.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/games/skyrimvr/appveyor.yml b/src/games/skyrimvr/appveyor.yml index a1c916fa..6e34f2f9 100644 --- a/src/games/skyrimvr/appveyor.yml +++ b/src/games/skyrimvr/appveyor.yml @@ -1,6 +1,6 @@ version: 1.0.{build} skip_branch_with_pr: true -image: Visual Studio 2017 +image: Visual Studio 2019 Preview environment: WEBHOOK_URL: secure: gOKbXaZM9ImtMD5XrYITvdyZUW/az082G9OIN1EC1Vbg57wBaeLhi49uGjxPw5GVujHku6kxN6ab89zhbS5GVeluR76GM83IbKV4Sh7udXzoYZZdg6YudtYHzdhCgUeiedpswbuczTq9ceIkkfSEWZuh/lMAAVVwvcGsJAnoPFw= From bf8818fdb9400da1f3bcbf6ea89c6374f13a7b05 Mon Sep 17 00:00:00 2001 From: Silarn Date: Wed, 8 May 2019 23:10:39 -0500 Subject: [PATCH 0769/1544] [game_skyrim] Set appveyor image to VS 2019 Preview --- src/games/skyrim/appveyor.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/games/skyrim/appveyor.yml b/src/games/skyrim/appveyor.yml index 4bd3f9a2..e7d7866e 100644 --- a/src/games/skyrim/appveyor.yml +++ b/src/games/skyrim/appveyor.yml @@ -1,6 +1,6 @@ version: 1.0.{build} skip_branch_with_pr: true -image: Visual Studio 2017 +image: Visual Studio 2019 Preview environment: WEBHOOK_URL: secure: gOKbXaZM9ImtMD5XrYITvdyZUW/az082G9OIN1EC1Vbg57wBaeLhi49uGjxPw5GVujHku6kxN6ab89zhbS5GVeluR76GM83IbKV4Sh7udXzoYZZdg6YudtYHzdhCgUeiedpswbuczTq9ceIkkfSEWZuh/lMAAVVwvcGsJAnoPFw= From 49f1d222d2a9ab1efb6e454c2a623f174e71ceec Mon Sep 17 00:00:00 2001 From: Silarn Date: Wed, 8 May 2019 23:10:42 -0500 Subject: [PATCH 0770/1544] [game_ttw] Set appveyor image to VS 2019 Preview --- src/games/ttw/appveyor.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/games/ttw/appveyor.yml b/src/games/ttw/appveyor.yml index 04c6be15..371bc170 100644 --- a/src/games/ttw/appveyor.yml +++ b/src/games/ttw/appveyor.yml @@ -1,6 +1,6 @@ version: 1.0.{build} skip_branch_with_pr: true -image: Visual Studio 2017 +image: Visual Studio 2019 Preview environment: WEBHOOK_URL: secure: gOKbXaZM9ImtMD5XrYITvdyZUW/az082G9OIN1EC1Vbg57wBaeLhi49uGjxPw5GVujHku6kxN6ab89zhbS5GVeluR76GM83IbKV4Sh7udXzoYZZdg6YudtYHzdhCgUeiedpswbuczTq9ceIkkfSEWZuh/lMAAVVwvcGsJAnoPFw= From e095a763f14fb6f2d58266f6ba9fe3f205f1a68a Mon Sep 17 00:00:00 2001 From: Silarn Date: Thu, 9 May 2019 14:39:11 -0500 Subject: [PATCH 0771/1544] [game_morrowind] Update sort mechanism to support LOOT --- src/games/morrowind/src/gamemorrowind.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/games/morrowind/src/gamemorrowind.cpp b/src/games/morrowind/src/gamemorrowind.cpp index d3238bcc..abc7fcbb 100644 --- a/src/games/morrowind/src/gamemorrowind.cpp +++ b/src/games/morrowind/src/gamemorrowind.cpp @@ -179,7 +179,7 @@ QStringList GameMorrowind::DLCPlugins() const MOBase::IPluginGame::SortMechanism GameMorrowind::sortMechanism() const { - return SortMechanism::NONE; + return SortMechanism::LOOT; } namespace { From a674ae3ad5977222703cecf3d1f321876b074448 Mon Sep 17 00:00:00 2001 From: Silarn Date: Tue, 21 May 2019 01:37:14 -0500 Subject: [PATCH 0772/1544] [game_fallout4vr] Unify artifacts source path to install path --- src/games/fallout4vr/appveyor.yml | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/src/games/fallout4vr/appveyor.yml b/src/games/fallout4vr/appveyor.yml index 06b4a902..8bac78e3 100644 --- a/src/games/fallout4vr/appveyor.yml +++ b/src/games/fallout4vr/appveyor.yml @@ -14,11 +14,11 @@ build_script: C:\Python37-x64\python.exe unimake.py -d c:\projects\modorganizer-build -s Appveyor_Build=True %APPVEYOR_PROJECT_NAME% artifacts: -- path: vsbuild\src\RelWithDebInfo\game_fallout4vr.dll +- path: ..\..\..\install\bin\plugins\game_fallout4vr.dll name: game_fallout4vr_dll -- path: vsbuild\src\RelWithDebInfo\game_fallout4vr.pdb +- path: ..\..\..\install\pdb\game_fallout4vr.pdb name: game_fallout4vr_pdb -- path: vsbuild\src\RelWithDebInfo\game_fallout4vr.lib +- path: ..\..\..\install\libs\game_fallout4vr.lib name: game_fallout4vr_lib on_success: - ps: Set-Location -Path $env:APPVEYOR_BUILD_FOLDER From e3e35f683b6d3afdc73d1be4d485ff47dbc1df1f Mon Sep 17 00:00:00 2001 From: Silarn Date: Tue, 21 May 2019 01:37:15 -0500 Subject: [PATCH 0773/1544] [game_morrowind] Unify artifacts source path to install path --- src/games/morrowind/appveyor.yml | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/src/games/morrowind/appveyor.yml b/src/games/morrowind/appveyor.yml index 970fcfca..4f022e91 100644 --- a/src/games/morrowind/appveyor.yml +++ b/src/games/morrowind/appveyor.yml @@ -14,11 +14,11 @@ build_script: C:\Python37-x64\python.exe unimake.py -d c:\projects\modorganizer-build -s Appveyor_Build=True %APPVEYOR_PROJECT_NAME% artifacts: -- path: vsbuild\src\RelWithDebInfo\game_morrowind.dll +- path: ..\..\..\install\bin\plugins\game_morrowind.dll name: game_morrowind_dll -- path: vsbuild\src\RelWithDebInfo\game_morrowind.pdb +- path: ..\..\..\install\pdb\game_morrowind.pdb name: game_morrowind_pdb -- path: vsbuild\src\RelWithDebInfo\game_morrowind.lib +- path: ..\..\..\install\libs\game_morrowind.lib name: game_morrowind_lib on_success: - ps: Set-Location -Path $env:APPVEYOR_BUILD_FOLDER From 122f616b3f7f04d5d4294a51bfdfca5c2226f00d Mon Sep 17 00:00:00 2001 From: Silarn Date: Tue, 21 May 2019 01:37:17 -0500 Subject: [PATCH 0774/1544] [game_falloutnv] Unify artifacts source path to install path --- src/games/falloutnv/appveyor.yml | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/src/games/falloutnv/appveyor.yml b/src/games/falloutnv/appveyor.yml index e903c0e9..f36ec70e 100644 --- a/src/games/falloutnv/appveyor.yml +++ b/src/games/falloutnv/appveyor.yml @@ -14,11 +14,11 @@ build_script: C:\Python37-x64\python.exe unimake.py -d c:\projects\modorganizer-build -s Appveyor_Build=True %APPVEYOR_PROJECT_NAME% artifacts: -- path: vsbuild\src\RelWithDebInfo\game_falloutNV.dll +- path: ..\..\..\install\bin\plugins\game_falloutNV.dll name: game_falloutNV_dll -- path: vsbuild\src\RelWithDebInfo\game_falloutNV.pdb +- path: ..\..\..\install\pdb\game_falloutNV.pdb name: game_falloutNV_pdb -- path: vsbuild\src\RelWithDebInfo\game_falloutNV.lib +- path: ..\..\..\install\libs\game_falloutNV.lib name: game_falloutNVe_lib on_success: - ps: Set-Location -Path $env:APPVEYOR_BUILD_FOLDER From afc45301ce94e6ac04275ac6867489d8697a1ba7 Mon Sep 17 00:00:00 2001 From: Silarn Date: Tue, 21 May 2019 01:37:19 -0500 Subject: [PATCH 0775/1544] [game_skyrimse] Unify artifacts source path to install path --- src/games/skyrimse/appveyor.yml | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/src/games/skyrimse/appveyor.yml b/src/games/skyrimse/appveyor.yml index 63da474d..023e0aa2 100644 --- a/src/games/skyrimse/appveyor.yml +++ b/src/games/skyrimse/appveyor.yml @@ -14,11 +14,11 @@ build_script: C:\Python37-x64\python.exe unimake.py -d c:\projects\modorganizer-build -s Appveyor_Build=True %APPVEYOR_PROJECT_NAME% artifacts: -- path: vsbuild\src\RelWithDebInfo\game_skyrimse.dll +- path: ..\..\..\install\bin\plugins\game_skyrimse.dll name: game_skyrimse_dll -- path: vsbuild\src\RelWithDebInfo\game_skyrimse.pdb +- path: ..\..\..\install\pdb\game_skyrimse.pdb name: game_skyrimse_pdb -- path: vsbuild\src\RelWithDebInfo\game_skyrimse.lib +- path: ..\..\..\install\libs\game_skyrimse.lib name: game_skyrimse_lib on_success: - ps: Set-Location -Path $env:APPVEYOR_BUILD_FOLDER From db4444c1e42d2594a8a67307bcf513db453eb6e8 Mon Sep 17 00:00:00 2001 From: Silarn Date: Tue, 21 May 2019 01:37:20 -0500 Subject: [PATCH 0776/1544] [game_oblivion] Unify artifacts source path to install path --- src/games/oblivion/appveyor.yml | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/src/games/oblivion/appveyor.yml b/src/games/oblivion/appveyor.yml index 4416bebe..a0a0dddd 100644 --- a/src/games/oblivion/appveyor.yml +++ b/src/games/oblivion/appveyor.yml @@ -14,11 +14,11 @@ build_script: C:\Python37-x64\python.exe unimake.py -d c:\projects\modorganizer-build -s Appveyor_Build=True %APPVEYOR_PROJECT_NAME% artifacts: -- path: vsbuild\src\RelWithDebInfo\game_oblivion.dll +- path: ..\..\..\install\bin\plugins\game_oblivion.dll name: game_oblivion_dll -- path: vsbuild\src\RelWithDebInfo\game_oblivion.pdb +- path: ..\..\..\install\pdb\game_oblivion.pdb name: game_oblivion_pdb -- path: vsbuild\src\RelWithDebInfo\game_oblivion.lib +- path: ..\..\..\install\libs\game_oblivion.lib name: game_oblivion_lib on_success: - ps: Set-Location -Path $env:APPVEYOR_BUILD_FOLDER From fbdd7aaf52305ce78601c34debca0a3b5142ed73 Mon Sep 17 00:00:00 2001 From: Silarn Date: Tue, 21 May 2019 01:37:21 -0500 Subject: [PATCH 0777/1544] Unify artifacts source path to install path --- appveyor.yml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/appveyor.yml b/appveyor.yml index 62b1d262..faaf5936 100644 --- a/appveyor.yml +++ b/appveyor.yml @@ -14,9 +14,9 @@ build_script: C:\Python37-x64\python.exe unimake.py -d c:\projects\modorganizer-build -s Appveyor_Build=True %APPVEYOR_PROJECT_NAME% artifacts: -- path: vsbuild\src\gamebryo\RelWithDebInfo\game_gamebryo.lib +- path: ..\..\..\install\libs\game_gamebryo.lib name: game_gamebryo_lib -- path: vsbuild\src\creation\RelWithDebInfo\game_creation.lib +- path: ..\..\..\install\libs\game_creation.lib name: game_creation_lib on_success: - ps: Set-Location -Path $env:APPVEYOR_BUILD_FOLDER From 8b93f97666b1bc5edbf36757d612180b2297472e Mon Sep 17 00:00:00 2001 From: Silarn Date: Tue, 21 May 2019 01:37:22 -0500 Subject: [PATCH 0778/1544] [game_fallout3] Unify artifacts source path to install path --- src/games/fallout3/appveyor.yml | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/src/games/fallout3/appveyor.yml b/src/games/fallout3/appveyor.yml index 4941d681..a222e17c 100644 --- a/src/games/fallout3/appveyor.yml +++ b/src/games/fallout3/appveyor.yml @@ -14,11 +14,11 @@ build_script: C:\Python37-x64\python.exe unimake.py -d c:\projects\modorganizer-build -s Appveyor_Build=True %APPVEYOR_PROJECT_NAME% artifacts: -- path: vsbuild\src\RelWithDebInfo\game_fallout3.dll +- path: ..\..\..\install\bin\plugins\game_fallout3.dll name: game_fallout3_dll -- path: vsbuild\src\RelWithDebInfo\game_fallout3.pdb +- path: ..\..\..\install\pdb\game_fallout3.pdb name: game_fallout3_pdb -- path: vsbuild\src\RelWithDebInfo\game_fallout3.lib +- path: ..\..\..\install\libs\game_fallout3.lib name: game_fallout3_lib on_success: - ps: Set-Location -Path $env:APPVEYOR_BUILD_FOLDER From 746ab1d2625e42412ea397a6b2ce96564b2a69df Mon Sep 17 00:00:00 2001 From: Silarn Date: Tue, 21 May 2019 01:37:23 -0500 Subject: [PATCH 0779/1544] [game_fallout4] Unify artifacts source path to install path --- src/games/fallout4/appveyor.yml | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/src/games/fallout4/appveyor.yml b/src/games/fallout4/appveyor.yml index 3c05999c..612c15d2 100644 --- a/src/games/fallout4/appveyor.yml +++ b/src/games/fallout4/appveyor.yml @@ -14,11 +14,11 @@ build_script: C:\Python37-x64\python.exe unimake.py -d c:\projects\modorganizer-build -s Appveyor_Build=True %APPVEYOR_PROJECT_NAME% artifacts: -- path: vsbuild\src\RelWithDebInfo\game_fallout4.dll +- path: ..\..\..\install\bin\plugins\game_fallout4.dll name: game_fallout4_dll -- path: vsbuild\src\RelWithDebInfo\game_fallout4.pdb +- path: ..\..\..\install\pdb\game_fallout4.pdb name: game_fallout4_pdb -- path: vsbuild\src\RelWithDebInfo\game_fallout4.lib +- path: ..\..\..\install\libs\game_fallout4.lib name: game_fallout4_lib on_success: - ps: Set-Location -Path $env:APPVEYOR_BUILD_FOLDER From c4f06ad86e41095795e12cb2f87b64d7dca079af Mon Sep 17 00:00:00 2001 From: Silarn Date: Tue, 21 May 2019 01:37:24 -0500 Subject: [PATCH 0780/1544] [game_skyrimvr] Unify artifacts source path to install path --- src/games/skyrimvr/appveyor.yml | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/src/games/skyrimvr/appveyor.yml b/src/games/skyrimvr/appveyor.yml index 6e34f2f9..bb9a77d5 100644 --- a/src/games/skyrimvr/appveyor.yml +++ b/src/games/skyrimvr/appveyor.yml @@ -14,11 +14,11 @@ build_script: C:\Python37-x64\python.exe unimake.py -d c:\projects\modorganizer-build -s Appveyor_Build=True %APPVEYOR_PROJECT_NAME% artifacts: -- path: vsbuild\src\RelWithDebInfo\game_skyrimvr.dll +- path: ..\..\..\install\bin\plugins\game_skyrimvr.dll name: game_skyrimvr_dll -- path: vsbuild\src\RelWithDebInfo\game_skyrimvr.pdb +- path: ..\..\..\install\pdb\game_skyrimvr.pdb name: game_skyrimvr_pdb -- path: vsbuild\src\RelWithDebInfo\game_skyrimvr.lib +- path: ..\..\..\install\libs\game_skyrimvr.lib name: game_skyrimvr_lib on_success: - ps: Set-Location -Path $env:APPVEYOR_BUILD_FOLDER From dcb602121653aede911f5f237cd563873ed6453d Mon Sep 17 00:00:00 2001 From: Silarn Date: Tue, 21 May 2019 01:37:27 -0500 Subject: [PATCH 0781/1544] [game_skyrim] Unify artifacts source path to install path --- src/games/skyrim/appveyor.yml | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/src/games/skyrim/appveyor.yml b/src/games/skyrim/appveyor.yml index e7d7866e..fc2693c7 100644 --- a/src/games/skyrim/appveyor.yml +++ b/src/games/skyrim/appveyor.yml @@ -14,11 +14,11 @@ build_script: C:\Python37-x64\python.exe unimake.py -d c:\projects\modorganizer-build -s Appveyor_Build=True %APPVEYOR_PROJECT_NAME% artifacts: -- path: vsbuild\src\RelWithDebInfo\game_skyrim.dll +- path: ..\..\..\install\bin\plugins\game_skyrim.dll name: game_skyrim_dll -- path: vsbuild\src\RelWithDebInfo\game_skyrim.pdb +- path: ..\..\..\install\pdb\game_skyrim.pdb name: game_skyrim_pdb -- path: vsbuild\src\RelWithDebInfo\game_skyrim.lib +- path: ..\..\..\install\libs\game_skyrim.lib name: game_skyrim_lib on_success: - ps: Set-Location -Path $env:APPVEYOR_BUILD_FOLDER From fcbb976c5e60281b1f82118f7343d7a6e70d9246 Mon Sep 17 00:00:00 2001 From: Silarn Date: Tue, 21 May 2019 01:37:30 -0500 Subject: [PATCH 0782/1544] [game_ttw] Unify artifacts source path to install path --- src/games/ttw/appveyor.yml | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/src/games/ttw/appveyor.yml b/src/games/ttw/appveyor.yml index 371bc170..aacf00ac 100644 --- a/src/games/ttw/appveyor.yml +++ b/src/games/ttw/appveyor.yml @@ -14,11 +14,11 @@ build_script: C:\Python37-x64\python.exe unimake.py -d c:\projects\modorganizer-build -s Appveyor_Build=True %APPVEYOR_PROJECT_NAME% artifacts: -- path: vsbuild\src\RelWithDebInfo\game_ttw.dll +- path: ..\..\..\install\bin\plugins\game_ttw.dll name: game_ttw_dll -- path: vsbuild\src\RelWithDebInfo\game_ttw.pdb +- path: ..\..\..\install\pdb\game_ttw.pdb name: game_ttw_pdb -- path: vsbuild\src\RelWithDebInfo\game_ttw.lib +- path: ..\..\..\install\libs\game_ttw.lib name: game_ttw_lib on_success: - ps: Set-Location -Path $env:APPVEYOR_BUILD_FOLDER From a278fb330ca4b1a76565ec0bbedb7c62913bc39e Mon Sep 17 00:00:00 2001 From: Silarn Date: Tue, 21 May 2019 02:27:53 -0500 Subject: [PATCH 0783/1544] [game_fallout4vr] Switch to local build files as appveyor can't use installed files --- src/games/fallout4vr/appveyor.yml | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/src/games/fallout4vr/appveyor.yml b/src/games/fallout4vr/appveyor.yml index 8bac78e3..306cfb0e 100644 --- a/src/games/fallout4vr/appveyor.yml +++ b/src/games/fallout4vr/appveyor.yml @@ -14,11 +14,11 @@ build_script: C:\Python37-x64\python.exe unimake.py -d c:\projects\modorganizer-build -s Appveyor_Build=True %APPVEYOR_PROJECT_NAME% artifacts: -- path: ..\..\..\install\bin\plugins\game_fallout4vr.dll +- path: build\src\game_fallout4vr.dll name: game_fallout4vr_dll -- path: ..\..\..\install\pdb\game_fallout4vr.pdb +- path: build\src\game_fallout4vr.pdb name: game_fallout4vr_pdb -- path: ..\..\..\install\libs\game_fallout4vr.lib +- path: build\src\game_fallout4vr.lib name: game_fallout4vr_lib on_success: - ps: Set-Location -Path $env:APPVEYOR_BUILD_FOLDER From fa41d17ebc55c8ee8a33e3d4d6a2d9a24e22ca35 Mon Sep 17 00:00:00 2001 From: Silarn Date: Tue, 21 May 2019 02:27:55 -0500 Subject: [PATCH 0784/1544] [game_morrowind] Switch to local build files as appveyor can't use installed files --- src/games/morrowind/appveyor.yml | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/src/games/morrowind/appveyor.yml b/src/games/morrowind/appveyor.yml index 4f022e91..b17d6e02 100644 --- a/src/games/morrowind/appveyor.yml +++ b/src/games/morrowind/appveyor.yml @@ -14,11 +14,11 @@ build_script: C:\Python37-x64\python.exe unimake.py -d c:\projects\modorganizer-build -s Appveyor_Build=True %APPVEYOR_PROJECT_NAME% artifacts: -- path: ..\..\..\install\bin\plugins\game_morrowind.dll +- path: build\src\game_morrowind.dll name: game_morrowind_dll -- path: ..\..\..\install\pdb\game_morrowind.pdb +- path: build\src\game_morrowind.pdb name: game_morrowind_pdb -- path: ..\..\..\install\libs\game_morrowind.lib +- path: build\src\game_morrowind.lib name: game_morrowind_lib on_success: - ps: Set-Location -Path $env:APPVEYOR_BUILD_FOLDER From d1d10714e3db98648694fe0d95984f07dcdabbfe Mon Sep 17 00:00:00 2001 From: Silarn Date: Tue, 21 May 2019 02:27:57 -0500 Subject: [PATCH 0785/1544] [game_falloutnv] Switch to local build files as appveyor can't use installed files --- src/games/falloutnv/appveyor.yml | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/src/games/falloutnv/appveyor.yml b/src/games/falloutnv/appveyor.yml index f36ec70e..1d218033 100644 --- a/src/games/falloutnv/appveyor.yml +++ b/src/games/falloutnv/appveyor.yml @@ -14,11 +14,11 @@ build_script: C:\Python37-x64\python.exe unimake.py -d c:\projects\modorganizer-build -s Appveyor_Build=True %APPVEYOR_PROJECT_NAME% artifacts: -- path: ..\..\..\install\bin\plugins\game_falloutNV.dll +- path: build\src\game_falloutNV.dll name: game_falloutNV_dll -- path: ..\..\..\install\pdb\game_falloutNV.pdb +- path: build\src\game_falloutNV.pdb name: game_falloutNV_pdb -- path: ..\..\..\install\libs\game_falloutNV.lib +- path: build\src\game_falloutNV.lib name: game_falloutNVe_lib on_success: - ps: Set-Location -Path $env:APPVEYOR_BUILD_FOLDER From 72b9ca7ba4dc7643ffba9b6d3846d519ad2d849e Mon Sep 17 00:00:00 2001 From: Silarn Date: Tue, 21 May 2019 02:27:58 -0500 Subject: [PATCH 0786/1544] [game_skyrimse] Switch to local build files as appveyor can't use installed files --- src/games/skyrimse/appveyor.yml | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/src/games/skyrimse/appveyor.yml b/src/games/skyrimse/appveyor.yml index 023e0aa2..c5dbcf14 100644 --- a/src/games/skyrimse/appveyor.yml +++ b/src/games/skyrimse/appveyor.yml @@ -14,11 +14,11 @@ build_script: C:\Python37-x64\python.exe unimake.py -d c:\projects\modorganizer-build -s Appveyor_Build=True %APPVEYOR_PROJECT_NAME% artifacts: -- path: ..\..\..\install\bin\plugins\game_skyrimse.dll +- path: build\src\game_skyrimse.dll name: game_skyrimse_dll -- path: ..\..\..\install\pdb\game_skyrimse.pdb +- path: build\src\game_skyrimse.pdb name: game_skyrimse_pdb -- path: ..\..\..\install\libs\game_skyrimse.lib +- path: build\src\game_skyrimse.lib name: game_skyrimse_lib on_success: - ps: Set-Location -Path $env:APPVEYOR_BUILD_FOLDER From 39f7eef0bae0e46db8b5b83f683facfeb08a3b64 Mon Sep 17 00:00:00 2001 From: Silarn Date: Tue, 21 May 2019 02:28:00 -0500 Subject: [PATCH 0787/1544] [game_oblivion] Switch to local build files as appveyor can't use installed files --- src/games/oblivion/appveyor.yml | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/src/games/oblivion/appveyor.yml b/src/games/oblivion/appveyor.yml index a0a0dddd..ffcb8d00 100644 --- a/src/games/oblivion/appveyor.yml +++ b/src/games/oblivion/appveyor.yml @@ -14,11 +14,11 @@ build_script: C:\Python37-x64\python.exe unimake.py -d c:\projects\modorganizer-build -s Appveyor_Build=True %APPVEYOR_PROJECT_NAME% artifacts: -- path: ..\..\..\install\bin\plugins\game_oblivion.dll +- path: build\src\game_oblivion.dll name: game_oblivion_dll -- path: ..\..\..\install\pdb\game_oblivion.pdb +- path: build\src\game_oblivion.pdb name: game_oblivion_pdb -- path: ..\..\..\install\libs\game_oblivion.lib +- path: build\src\game_oblivion.lib name: game_oblivion_lib on_success: - ps: Set-Location -Path $env:APPVEYOR_BUILD_FOLDER From d2fdcc6b2813d541ab6386841d1ae80ad9c9086b Mon Sep 17 00:00:00 2001 From: Silarn Date: Tue, 21 May 2019 02:28:01 -0500 Subject: [PATCH 0788/1544] Switch to local build files as appveyor can't use installed files --- appveyor.yml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/appveyor.yml b/appveyor.yml index faaf5936..9f663dd1 100644 --- a/appveyor.yml +++ b/appveyor.yml @@ -14,9 +14,9 @@ build_script: C:\Python37-x64\python.exe unimake.py -d c:\projects\modorganizer-build -s Appveyor_Build=True %APPVEYOR_PROJECT_NAME% artifacts: -- path: ..\..\..\install\libs\game_gamebryo.lib +- path: build\src\game_gamebryo.lib name: game_gamebryo_lib -- path: ..\..\..\install\libs\game_creation.lib +- path: build\src\game_creation.lib name: game_creation_lib on_success: - ps: Set-Location -Path $env:APPVEYOR_BUILD_FOLDER From 292b4ef4ac223ad1497370da2f529d8d03482032 Mon Sep 17 00:00:00 2001 From: Silarn Date: Tue, 21 May 2019 02:28:01 -0500 Subject: [PATCH 0789/1544] [game_fallout3] Switch to local build files as appveyor can't use installed files --- src/games/fallout3/appveyor.yml | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/src/games/fallout3/appveyor.yml b/src/games/fallout3/appveyor.yml index a222e17c..d0440986 100644 --- a/src/games/fallout3/appveyor.yml +++ b/src/games/fallout3/appveyor.yml @@ -14,11 +14,11 @@ build_script: C:\Python37-x64\python.exe unimake.py -d c:\projects\modorganizer-build -s Appveyor_Build=True %APPVEYOR_PROJECT_NAME% artifacts: -- path: ..\..\..\install\bin\plugins\game_fallout3.dll +- path: build\src\game_fallout3.dll name: game_fallout3_dll -- path: ..\..\..\install\pdb\game_fallout3.pdb +- path: build\src\game_fallout3.pdb name: game_fallout3_pdb -- path: ..\..\..\install\libs\game_fallout3.lib +- path: build\src\game_fallout3.lib name: game_fallout3_lib on_success: - ps: Set-Location -Path $env:APPVEYOR_BUILD_FOLDER From 4d12a023e6beeb71a868773a229cc4c5d49e70c9 Mon Sep 17 00:00:00 2001 From: Silarn Date: Tue, 21 May 2019 02:28:02 -0500 Subject: [PATCH 0790/1544] [game_fallout4] Switch to local build files as appveyor can't use installed files --- src/games/fallout4/appveyor.yml | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/src/games/fallout4/appveyor.yml b/src/games/fallout4/appveyor.yml index 612c15d2..68932c3a 100644 --- a/src/games/fallout4/appveyor.yml +++ b/src/games/fallout4/appveyor.yml @@ -14,11 +14,11 @@ build_script: C:\Python37-x64\python.exe unimake.py -d c:\projects\modorganizer-build -s Appveyor_Build=True %APPVEYOR_PROJECT_NAME% artifacts: -- path: ..\..\..\install\bin\plugins\game_fallout4.dll +- path: build\src\game_fallout4.dll name: game_fallout4_dll -- path: ..\..\..\install\pdb\game_fallout4.pdb +- path: build\src\game_fallout4.pdb name: game_fallout4_pdb -- path: ..\..\..\install\libs\game_fallout4.lib +- path: build\src\game_fallout4.lib name: game_fallout4_lib on_success: - ps: Set-Location -Path $env:APPVEYOR_BUILD_FOLDER From 4ee5e7782cc985d9c777a94644b6639ac342095e Mon Sep 17 00:00:00 2001 From: Silarn Date: Tue, 21 May 2019 02:28:03 -0500 Subject: [PATCH 0791/1544] [game_skyrimvr] Switch to local build files as appveyor can't use installed files --- src/games/skyrimvr/appveyor.yml | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/src/games/skyrimvr/appveyor.yml b/src/games/skyrimvr/appveyor.yml index bb9a77d5..47ddf6e5 100644 --- a/src/games/skyrimvr/appveyor.yml +++ b/src/games/skyrimvr/appveyor.yml @@ -14,11 +14,11 @@ build_script: C:\Python37-x64\python.exe unimake.py -d c:\projects\modorganizer-build -s Appveyor_Build=True %APPVEYOR_PROJECT_NAME% artifacts: -- path: ..\..\..\install\bin\plugins\game_skyrimvr.dll +- path: build\src\game_skyrimvr.dll name: game_skyrimvr_dll -- path: ..\..\..\install\pdb\game_skyrimvr.pdb +- path: build\src\game_skyrimvr.pdb name: game_skyrimvr_pdb -- path: ..\..\..\install\libs\game_skyrimvr.lib +- path: build\src\game_skyrimvr.lib name: game_skyrimvr_lib on_success: - ps: Set-Location -Path $env:APPVEYOR_BUILD_FOLDER From ff2987174d2e1b0d42681350fab9d37cf443a562 Mon Sep 17 00:00:00 2001 From: Silarn Date: Tue, 21 May 2019 02:28:06 -0500 Subject: [PATCH 0792/1544] [game_skyrim] Switch to local build files as appveyor can't use installed files --- src/games/skyrim/appveyor.yml | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/src/games/skyrim/appveyor.yml b/src/games/skyrim/appveyor.yml index fc2693c7..9fa06de0 100644 --- a/src/games/skyrim/appveyor.yml +++ b/src/games/skyrim/appveyor.yml @@ -14,11 +14,11 @@ build_script: C:\Python37-x64\python.exe unimake.py -d c:\projects\modorganizer-build -s Appveyor_Build=True %APPVEYOR_PROJECT_NAME% artifacts: -- path: ..\..\..\install\bin\plugins\game_skyrim.dll +- path: build\src\game_skyrim.dll name: game_skyrim_dll -- path: ..\..\..\install\pdb\game_skyrim.pdb +- path: build\src\game_skyrim.pdb name: game_skyrim_pdb -- path: ..\..\..\install\libs\game_skyrim.lib +- path: build\src\game_skyrim.lib name: game_skyrim_lib on_success: - ps: Set-Location -Path $env:APPVEYOR_BUILD_FOLDER From 2acd6e60f6e958916fe9cc423f828d6512f84692 Mon Sep 17 00:00:00 2001 From: Silarn Date: Tue, 21 May 2019 02:28:08 -0500 Subject: [PATCH 0793/1544] [game_ttw] Switch to local build files as appveyor can't use installed files --- src/games/ttw/appveyor.yml | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/src/games/ttw/appveyor.yml b/src/games/ttw/appveyor.yml index aacf00ac..e65a0dee 100644 --- a/src/games/ttw/appveyor.yml +++ b/src/games/ttw/appveyor.yml @@ -14,11 +14,11 @@ build_script: C:\Python37-x64\python.exe unimake.py -d c:\projects\modorganizer-build -s Appveyor_Build=True %APPVEYOR_PROJECT_NAME% artifacts: -- path: ..\..\..\install\bin\plugins\game_ttw.dll +- path: build\src\game_ttw.dll name: game_ttw_dll -- path: ..\..\..\install\pdb\game_ttw.pdb +- path: build\src\game_ttw.pdb name: game_ttw_pdb -- path: ..\..\..\install\libs\game_ttw.lib +- path: build\src\game_ttw.lib name: game_ttw_lib on_success: - ps: Set-Location -Path $env:APPVEYOR_BUILD_FOLDER From 93890eb5f8cb64abb2a54c3e68cb7e4026a03a8f Mon Sep 17 00:00:00 2001 From: Silarn Date: Tue, 21 May 2019 23:46:03 -0500 Subject: [PATCH 0794/1544] [game_fallout4vr] Add logs to build artifacts on CI fail, commit translation changes --- src/games/fallout4vr/appveyor.yml | 2 ++ 1 file changed, 2 insertions(+) diff --git a/src/games/fallout4vr/appveyor.yml b/src/games/fallout4vr/appveyor.yml index 306cfb0e..fb43eb11 100644 --- a/src/games/fallout4vr/appveyor.yml +++ b/src/games/fallout4vr/appveyor.yml @@ -26,5 +26,7 @@ on_success: - ps: ./send.ps1 success $env:WEBHOOK_URL on_failure: - ps: Set-Location -Path $env:APPVEYOR_BUILD_FOLDER + - ps: Push-AppveyorArtifact ${env:APPVEYOR_BUILD_FOLDER}\stdout.log + - ps: Push-AppveyorArtifact ${env:APPVEYOR_BUILD_FOLDER}\stderr.log - ps: Invoke-RestMethod https://raw.githubusercontent.com/DiscordHooks/appveyor-discord-webhook/master/send.ps1 -o send.ps1 - ps: ./send.ps1 failure $env:WEBHOOK_URL \ No newline at end of file From 34c073e2a09c176d79335168ef4c8652e94b63f5 Mon Sep 17 00:00:00 2001 From: Silarn Date: Tue, 21 May 2019 23:46:04 -0500 Subject: [PATCH 0795/1544] [game_morrowind] Add logs to build artifacts on CI fail, commit translation changes --- src/games/morrowind/appveyor.yml | 2 ++ 1 file changed, 2 insertions(+) diff --git a/src/games/morrowind/appveyor.yml b/src/games/morrowind/appveyor.yml index b17d6e02..6dbc0add 100644 --- a/src/games/morrowind/appveyor.yml +++ b/src/games/morrowind/appveyor.yml @@ -26,5 +26,7 @@ on_success: - ps: ./send.ps1 success $env:WEBHOOK_URL on_failure: - ps: Set-Location -Path $env:APPVEYOR_BUILD_FOLDER + - ps: Push-AppveyorArtifact ${env:APPVEYOR_BUILD_FOLDER}\stdout.log + - ps: Push-AppveyorArtifact ${env:APPVEYOR_BUILD_FOLDER}\stderr.log - ps: Invoke-RestMethod https://raw.githubusercontent.com/DiscordHooks/appveyor-discord-webhook/master/send.ps1 -o send.ps1 - ps: ./send.ps1 failure $env:WEBHOOK_URL \ No newline at end of file From 1da93f16cb4dc55c939777eba592733abbd4a230 Mon Sep 17 00:00:00 2001 From: Silarn Date: Tue, 21 May 2019 23:46:06 -0500 Subject: [PATCH 0796/1544] [game_falloutnv] Add logs to build artifacts on CI fail, commit translation changes --- src/games/falloutnv/appveyor.yml | 2 ++ 1 file changed, 2 insertions(+) diff --git a/src/games/falloutnv/appveyor.yml b/src/games/falloutnv/appveyor.yml index 1d218033..8e92aa15 100644 --- a/src/games/falloutnv/appveyor.yml +++ b/src/games/falloutnv/appveyor.yml @@ -26,5 +26,7 @@ on_success: - ps: ./send.ps1 success $env:WEBHOOK_URL on_failure: - ps: Set-Location -Path $env:APPVEYOR_BUILD_FOLDER + - ps: Push-AppveyorArtifact ${env:APPVEYOR_BUILD_FOLDER}\stdout.log + - ps: Push-AppveyorArtifact ${env:APPVEYOR_BUILD_FOLDER}\stderr.log - ps: Invoke-RestMethod https://raw.githubusercontent.com/DiscordHooks/appveyor-discord-webhook/master/send.ps1 -o send.ps1 - ps: ./send.ps1 failure $env:WEBHOOK_URL \ No newline at end of file From e35f7b2956db3b5dbdcd567a6add5d6ae80686a7 Mon Sep 17 00:00:00 2001 From: Silarn Date: Tue, 21 May 2019 23:46:07 -0500 Subject: [PATCH 0797/1544] [game_skyrimse] Add logs to build artifacts on CI fail, commit translation changes --- src/games/skyrimse/appveyor.yml | 2 ++ 1 file changed, 2 insertions(+) diff --git a/src/games/skyrimse/appveyor.yml b/src/games/skyrimse/appveyor.yml index c5dbcf14..ddc0f0f4 100644 --- a/src/games/skyrimse/appveyor.yml +++ b/src/games/skyrimse/appveyor.yml @@ -26,5 +26,7 @@ on_success: - ps: ./send.ps1 success $env:WEBHOOK_URL on_failure: - ps: Set-Location -Path $env:APPVEYOR_BUILD_FOLDER + - ps: Push-AppveyorArtifact ${env:APPVEYOR_BUILD_FOLDER}\stdout.log + - ps: Push-AppveyorArtifact ${env:APPVEYOR_BUILD_FOLDER}\stderr.log - ps: Invoke-RestMethod https://raw.githubusercontent.com/DiscordHooks/appveyor-discord-webhook/master/send.ps1 -o send.ps1 - ps: ./send.ps1 failure $env:WEBHOOK_URL \ No newline at end of file From f0650a2ca8e4c1f933e95b88e335a3da921e4c02 Mon Sep 17 00:00:00 2001 From: Silarn Date: Tue, 21 May 2019 23:46:08 -0500 Subject: [PATCH 0798/1544] [game_oblivion] Add logs to build artifacts on CI fail, commit translation changes --- src/games/oblivion/appveyor.yml | 2 ++ 1 file changed, 2 insertions(+) diff --git a/src/games/oblivion/appveyor.yml b/src/games/oblivion/appveyor.yml index ffcb8d00..1436d8a0 100644 --- a/src/games/oblivion/appveyor.yml +++ b/src/games/oblivion/appveyor.yml @@ -26,5 +26,7 @@ on_success: - ps: ./send.ps1 success $env:WEBHOOK_URL on_failure: - ps: Set-Location -Path $env:APPVEYOR_BUILD_FOLDER + - ps: Push-AppveyorArtifact ${env:APPVEYOR_BUILD_FOLDER}\stdout.log + - ps: Push-AppveyorArtifact ${env:APPVEYOR_BUILD_FOLDER}\stderr.log - ps: Invoke-RestMethod https://raw.githubusercontent.com/DiscordHooks/appveyor-discord-webhook/master/send.ps1 -o send.ps1 - ps: ./send.ps1 failure $env:WEBHOOK_URL \ No newline at end of file From 643875875558c4f4c8940fee4fb1f24596ddfb7a Mon Sep 17 00:00:00 2001 From: Silarn Date: Tue, 21 May 2019 23:46:08 -0500 Subject: [PATCH 0799/1544] Add logs to build artifacts on CI fail, commit translation changes --- appveyor.yml | 2 ++ 1 file changed, 2 insertions(+) diff --git a/appveyor.yml b/appveyor.yml index 9f663dd1..b6103ccc 100644 --- a/appveyor.yml +++ b/appveyor.yml @@ -24,5 +24,7 @@ on_success: - ps: ./send.ps1 success $env:WEBHOOK_URL on_failure: - ps: Set-Location -Path $env:APPVEYOR_BUILD_FOLDER + - ps: Push-AppveyorArtifact ${env:APPVEYOR_BUILD_FOLDER}\stdout.log + - ps: Push-AppveyorArtifact ${env:APPVEYOR_BUILD_FOLDER}\stderr.log - ps: Invoke-RestMethod https://raw.githubusercontent.com/DiscordHooks/appveyor-discord-webhook/master/send.ps1 -o send.ps1 - ps: ./send.ps1 failure $env:WEBHOOK_URL \ No newline at end of file From f0360731cf438de6cd8436259086d1bb4a86c17d Mon Sep 17 00:00:00 2001 From: Silarn Date: Tue, 21 May 2019 23:46:09 -0500 Subject: [PATCH 0800/1544] [game_fallout3] Add logs to build artifacts on CI fail, commit translation changes --- src/games/fallout3/appveyor.yml | 2 ++ 1 file changed, 2 insertions(+) diff --git a/src/games/fallout3/appveyor.yml b/src/games/fallout3/appveyor.yml index d0440986..c09a3a56 100644 --- a/src/games/fallout3/appveyor.yml +++ b/src/games/fallout3/appveyor.yml @@ -26,5 +26,7 @@ on_success: - ps: ./send.ps1 success $env:WEBHOOK_URL on_failure: - ps: Set-Location -Path $env:APPVEYOR_BUILD_FOLDER + - ps: Push-AppveyorArtifact ${env:APPVEYOR_BUILD_FOLDER}\stdout.log + - ps: Push-AppveyorArtifact ${env:APPVEYOR_BUILD_FOLDER}\stderr.log - ps: Invoke-RestMethod https://raw.githubusercontent.com/DiscordHooks/appveyor-discord-webhook/master/send.ps1 -o send.ps1 - ps: ./send.ps1 failure $env:WEBHOOK_URL \ No newline at end of file From 6cfa43dff42a3f0884c2aa28520a5a04aa0e0af9 Mon Sep 17 00:00:00 2001 From: Silarn Date: Tue, 21 May 2019 23:46:09 -0500 Subject: [PATCH 0801/1544] [game_fallout4] Add logs to build artifacts on CI fail, commit translation changes --- src/games/fallout4/appveyor.yml | 2 ++ 1 file changed, 2 insertions(+) diff --git a/src/games/fallout4/appveyor.yml b/src/games/fallout4/appveyor.yml index 68932c3a..6b0ead4a 100644 --- a/src/games/fallout4/appveyor.yml +++ b/src/games/fallout4/appveyor.yml @@ -26,5 +26,7 @@ on_success: - ps: ./send.ps1 success $env:WEBHOOK_URL on_failure: - ps: Set-Location -Path $env:APPVEYOR_BUILD_FOLDER + - ps: Push-AppveyorArtifact ${env:APPVEYOR_BUILD_FOLDER}\stdout.log + - ps: Push-AppveyorArtifact ${env:APPVEYOR_BUILD_FOLDER}\stderr.log - ps: Invoke-RestMethod https://raw.githubusercontent.com/DiscordHooks/appveyor-discord-webhook/master/send.ps1 -o send.ps1 - ps: ./send.ps1 failure $env:WEBHOOK_URL \ No newline at end of file From fe812d20007a3e08bb9974bc687df8735dadff0a Mon Sep 17 00:00:00 2001 From: Silarn Date: Tue, 21 May 2019 23:46:10 -0500 Subject: [PATCH 0802/1544] [game_skyrimvr] Add logs to build artifacts on CI fail, commit translation changes --- src/games/skyrimvr/appveyor.yml | 2 ++ 1 file changed, 2 insertions(+) diff --git a/src/games/skyrimvr/appveyor.yml b/src/games/skyrimvr/appveyor.yml index 47ddf6e5..1a20f07f 100644 --- a/src/games/skyrimvr/appveyor.yml +++ b/src/games/skyrimvr/appveyor.yml @@ -26,5 +26,7 @@ on_success: - ps: ./send.ps1 success $env:WEBHOOK_URL on_failure: - ps: Set-Location -Path $env:APPVEYOR_BUILD_FOLDER + - ps: Push-AppveyorArtifact ${env:APPVEYOR_BUILD_FOLDER}\stdout.log + - ps: Push-AppveyorArtifact ${env:APPVEYOR_BUILD_FOLDER}\stderr.log - ps: Invoke-RestMethod https://raw.githubusercontent.com/DiscordHooks/appveyor-discord-webhook/master/send.ps1 -o send.ps1 - ps: ./send.ps1 failure $env:WEBHOOK_URL \ No newline at end of file From 8083224f512265e3b5e5183909576b82372540fb Mon Sep 17 00:00:00 2001 From: Silarn Date: Tue, 21 May 2019 23:46:12 -0500 Subject: [PATCH 0803/1544] [game_skyrim] Add logs to build artifacts on CI fail, commit translation changes --- src/games/skyrim/appveyor.yml | 2 ++ 1 file changed, 2 insertions(+) diff --git a/src/games/skyrim/appveyor.yml b/src/games/skyrim/appveyor.yml index 9fa06de0..62789332 100644 --- a/src/games/skyrim/appveyor.yml +++ b/src/games/skyrim/appveyor.yml @@ -26,5 +26,7 @@ on_success: - ps: ./send.ps1 success $env:WEBHOOK_URL on_failure: - ps: Set-Location -Path $env:APPVEYOR_BUILD_FOLDER + - ps: Push-AppveyorArtifact ${env:APPVEYOR_BUILD_FOLDER}\stdout.log + - ps: Push-AppveyorArtifact ${env:APPVEYOR_BUILD_FOLDER}\stderr.log - ps: Invoke-RestMethod https://raw.githubusercontent.com/DiscordHooks/appveyor-discord-webhook/master/send.ps1 -o send.ps1 - ps: ./send.ps1 failure $env:WEBHOOK_URL \ No newline at end of file From 7b57e594f1517ebfb3017845def2426788c08e4a Mon Sep 17 00:00:00 2001 From: Silarn Date: Tue, 21 May 2019 23:46:15 -0500 Subject: [PATCH 0804/1544] [game_ttw] Add logs to build artifacts on CI fail, commit translation changes --- src/games/ttw/appveyor.yml | 2 ++ 1 file changed, 2 insertions(+) diff --git a/src/games/ttw/appveyor.yml b/src/games/ttw/appveyor.yml index e65a0dee..aac65ea8 100644 --- a/src/games/ttw/appveyor.yml +++ b/src/games/ttw/appveyor.yml @@ -26,5 +26,7 @@ on_success: - ps: ./send.ps1 success $env:WEBHOOK_URL on_failure: - ps: Set-Location -Path $env:APPVEYOR_BUILD_FOLDER + - ps: Push-AppveyorArtifact ${env:APPVEYOR_BUILD_FOLDER}\stdout.log + - ps: Push-AppveyorArtifact ${env:APPVEYOR_BUILD_FOLDER}\stderr.log - ps: Invoke-RestMethod https://raw.githubusercontent.com/DiscordHooks/appveyor-discord-webhook/master/send.ps1 -o send.ps1 - ps: ./send.ps1 failure $env:WEBHOOK_URL \ No newline at end of file From 1a2303c7929d74727ef25eef2105b6d28dcaf5b8 Mon Sep 17 00:00:00 2001 From: Silarn Date: Wed, 22 May 2019 02:04:16 -0500 Subject: [PATCH 0805/1544] [game_fallout4vr] Set optimization for release builds --- src/games/fallout4vr/CMakeLists.txt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/games/fallout4vr/CMakeLists.txt b/src/games/fallout4vr/CMakeLists.txt index 8288c438..d61a4016 100644 --- a/src/games/fallout4vr/CMakeLists.txt +++ b/src/games/fallout4vr/CMakeLists.txt @@ -1,6 +1,6 @@ CMAKE_MINIMUM_REQUIRED(VERSION 2.8.12) -ADD_COMPILE_OPTIONS($<$:/MP>) +ADD_COMPILE_OPTIONS($<$:/MP> $<$:$<$:/O2>> $<$:$<$:/O2>>) SET(PROJ_NAME game_fallout4vr) From 66090f5c6d5712c6876e3e19a41539ce00a4b9bc Mon Sep 17 00:00:00 2001 From: Silarn Date: Wed, 22 May 2019 02:04:18 -0500 Subject: [PATCH 0806/1544] [game_morrowind] Set optimization for release builds --- src/games/morrowind/CMakeLists.txt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/games/morrowind/CMakeLists.txt b/src/games/morrowind/CMakeLists.txt index 5e4f1635..0a591eef 100644 --- a/src/games/morrowind/CMakeLists.txt +++ b/src/games/morrowind/CMakeLists.txt @@ -1,6 +1,6 @@ CMAKE_MINIMUM_REQUIRED(VERSION 2.8.12) -ADD_COMPILE_OPTIONS($<$:/MP>) +ADD_COMPILE_OPTIONS($<$:/MP> $<$:$<$:/O2>> $<$:$<$:/O2>>) SET(PROJ_NAME game_morrowind) From a796a7b115fd3ccb7d8e1fc3de180db2c96151ae Mon Sep 17 00:00:00 2001 From: Silarn Date: Wed, 22 May 2019 02:04:21 -0500 Subject: [PATCH 0807/1544] [game_falloutnv] Set optimization for release builds --- src/games/falloutnv/CMakeLists.txt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/games/falloutnv/CMakeLists.txt b/src/games/falloutnv/CMakeLists.txt index 414d3cc7..39dd6e76 100644 --- a/src/games/falloutnv/CMakeLists.txt +++ b/src/games/falloutnv/CMakeLists.txt @@ -1,6 +1,6 @@ CMAKE_MINIMUM_REQUIRED(VERSION 2.8.12) -ADD_COMPILE_OPTIONS($<$:/MP>) +ADD_COMPILE_OPTIONS($<$:/MP> $<$:$<$:/O2>> $<$:$<$:/O2>>) SET(PROJ_NAME game_falloutNV) From 845b13050b2ced442f3fb67b9ac751f0814ecf2a Mon Sep 17 00:00:00 2001 From: Silarn Date: Wed, 22 May 2019 02:04:23 -0500 Subject: [PATCH 0808/1544] [game_skyrimse] Set optimization for release builds --- src/games/skyrimse/CMakeLists.txt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/games/skyrimse/CMakeLists.txt b/src/games/skyrimse/CMakeLists.txt index 41613096..3e0ea718 100644 --- a/src/games/skyrimse/CMakeLists.txt +++ b/src/games/skyrimse/CMakeLists.txt @@ -1,6 +1,6 @@ CMAKE_MINIMUM_REQUIRED(VERSION 2.8.12) -ADD_COMPILE_OPTIONS($<$:/MP>) +ADD_COMPILE_OPTIONS($<$:/MP> $<$:$<$:/O2>> $<$:$<$:/O2>>) SET(PROJ_NAME game_skyrimse) From d772343a01a07445f1371f8fea91450e5b263cf1 Mon Sep 17 00:00:00 2001 From: Silarn Date: Wed, 22 May 2019 02:04:25 -0500 Subject: [PATCH 0809/1544] [game_oblivion] Set optimization for release builds --- src/games/oblivion/CMakeLists.txt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/games/oblivion/CMakeLists.txt b/src/games/oblivion/CMakeLists.txt index f0e6b4bb..9e30f4cc 100644 --- a/src/games/oblivion/CMakeLists.txt +++ b/src/games/oblivion/CMakeLists.txt @@ -1,6 +1,6 @@ CMAKE_MINIMUM_REQUIRED(VERSION 2.8.12) -ADD_COMPILE_OPTIONS($<$:/MP>) +ADD_COMPILE_OPTIONS($<$:/MP> $<$:$<$:/O2>> $<$:$<$:/O2>>) SET(PROJ_NAME game_oblivion) From 6588e70ec3895a929095fe8e04ac084d7a9638fa Mon Sep 17 00:00:00 2001 From: Silarn Date: Wed, 22 May 2019 02:04:26 -0500 Subject: [PATCH 0810/1544] Set optimization for release builds --- CMakeLists.txt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/CMakeLists.txt b/CMakeLists.txt index 05b2f29d..0c7189e0 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -1,6 +1,6 @@ CMAKE_MINIMUM_REQUIRED(VERSION 2.8.12) -ADD_COMPILE_OPTIONS($<$:/MP>) +ADD_COMPILE_OPTIONS($<$:/MP> $<$:$<$:/O2>> $<$:$<$:/O2>>) SET(PROJ_NAME game_gamebryo) PROJECT(${PROJ_NAME}) From 2fc307a553bf35f0941658b773fbad64862dd5e1 Mon Sep 17 00:00:00 2001 From: Silarn Date: Wed, 22 May 2019 02:04:27 -0500 Subject: [PATCH 0811/1544] [game_fallout3] Set optimization for release builds --- src/games/fallout3/CMakeLists.txt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/games/fallout3/CMakeLists.txt b/src/games/fallout3/CMakeLists.txt index bc4627d8..a6f19354 100644 --- a/src/games/fallout3/CMakeLists.txt +++ b/src/games/fallout3/CMakeLists.txt @@ -1,6 +1,6 @@ CMAKE_MINIMUM_REQUIRED(VERSION 2.8.12) -ADD_COMPILE_OPTIONS($<$:/MP>) +ADD_COMPILE_OPTIONS($<$:/MP> $<$:$<$:/O2>> $<$:$<$:/O2>>) SET(PROJ_NAME game_fallout3) From 01ce7769091010e863d54fb0922d627ccb2f85a9 Mon Sep 17 00:00:00 2001 From: Silarn Date: Wed, 22 May 2019 02:04:27 -0500 Subject: [PATCH 0812/1544] [game_fallout4] Set optimization for release builds --- src/games/fallout4/CMakeLists.txt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/games/fallout4/CMakeLists.txt b/src/games/fallout4/CMakeLists.txt index 40f51534..cab5836e 100644 --- a/src/games/fallout4/CMakeLists.txt +++ b/src/games/fallout4/CMakeLists.txt @@ -1,6 +1,6 @@ CMAKE_MINIMUM_REQUIRED(VERSION 2.8.12) -ADD_COMPILE_OPTIONS($<$:/MP>) +ADD_COMPILE_OPTIONS($<$:/MP> $<$:$<$:/O2>> $<$:$<$:/O2>>) SET(PROJ_NAME game_fallout4) From 7c02cdce8bf41dbebd0402a8b4d1c84278907a17 Mon Sep 17 00:00:00 2001 From: Silarn Date: Wed, 22 May 2019 02:04:29 -0500 Subject: [PATCH 0813/1544] [game_skyrimvr] Set optimization for release builds --- src/games/skyrimvr/CMakeLists.txt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/games/skyrimvr/CMakeLists.txt b/src/games/skyrimvr/CMakeLists.txt index 7a72d215..52a4323d 100644 --- a/src/games/skyrimvr/CMakeLists.txt +++ b/src/games/skyrimvr/CMakeLists.txt @@ -1,6 +1,6 @@ CMAKE_MINIMUM_REQUIRED(VERSION 2.8.12) -ADD_COMPILE_OPTIONS($<$:/MP>) +ADD_COMPILE_OPTIONS($<$:/MP> $<$:$<$:/O2>> $<$:$<$:/O2>>) SET(PROJ_NAME game_skyrimvr) From 6a02b34b402c39e9957ecc3c7e2a58e211a78f23 Mon Sep 17 00:00:00 2001 From: Silarn Date: Wed, 22 May 2019 02:04:33 -0500 Subject: [PATCH 0814/1544] [game_skyrim] Set optimization for release builds --- src/games/skyrim/CMakeLists.txt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/games/skyrim/CMakeLists.txt b/src/games/skyrim/CMakeLists.txt index 41920872..a8aa9fb9 100644 --- a/src/games/skyrim/CMakeLists.txt +++ b/src/games/skyrim/CMakeLists.txt @@ -1,6 +1,6 @@ CMAKE_MINIMUM_REQUIRED(VERSION 2.8.12) -ADD_COMPILE_OPTIONS($<$:/MP>) +ADD_COMPILE_OPTIONS($<$:/MP> $<$:$<$:/O2>> $<$:$<$:/O2>>) SET(PROJ_NAME game_skyrim) From 12fe2a06b4b5c85e934a507bb40cbbcb440c946f Mon Sep 17 00:00:00 2001 From: Silarn Date: Wed, 22 May 2019 02:04:36 -0500 Subject: [PATCH 0815/1544] [game_ttw] Set optimization for release builds --- src/games/ttw/CMakeLists.txt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/games/ttw/CMakeLists.txt b/src/games/ttw/CMakeLists.txt index eefc4cc3..991c7a29 100644 --- a/src/games/ttw/CMakeLists.txt +++ b/src/games/ttw/CMakeLists.txt @@ -1,6 +1,6 @@ CMAKE_MINIMUM_REQUIRED(VERSION 2.8.12) -ADD_COMPILE_OPTIONS($<$:/MP>) +ADD_COMPILE_OPTIONS($<$:/MP> $<$:$<$:/O2>> $<$:$<$:/O2>>) SET(PROJ_NAME game_ttw) From 154f59ba712c822509041b776eb78bffdafb6153 Mon Sep 17 00:00:00 2001 From: LostDragonist Date: Mon, 27 May 2019 19:03:50 -0500 Subject: [PATCH 0816/1544] [game_oblivion] Fix issue with deleting save games The .obse save game extension is handled by savegameSEExtension. Defining it for saveGameAttachmentExtensions is double-dipping and causing errors. --- src/games/oblivion/src/oblivionscriptextender.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/games/oblivion/src/oblivionscriptextender.cpp b/src/games/oblivion/src/oblivionscriptextender.cpp index 6c6ef557..ecbd95ef 100644 --- a/src/games/oblivion/src/oblivionscriptextender.cpp +++ b/src/games/oblivion/src/oblivionscriptextender.cpp @@ -24,5 +24,5 @@ QString OblivionScriptExtender::PluginPath() const QStringList OblivionScriptExtender::saveGameAttachmentExtensions() const { - return { "obse" }; + return {}; } From f64d8b453b349d635681f0c8a0cdd2a4700a6c12 Mon Sep 17 00:00:00 2001 From: isanae <14251494+isanae@users.noreply.github.com> Date: Wed, 3 Jul 2019 18:24:35 -0400 Subject: [PATCH 0817/1544] [game_skyrimse] don't read compression and don't use alpha for LE --- src/games/skyrimse/src/skyrimsesavegame.cpp | 15 ++++++++++++--- 1 file changed, 12 insertions(+), 3 deletions(-) diff --git a/src/games/skyrimse/src/skyrimsesavegame.cpp b/src/games/skyrimse/src/skyrimsesavegame.cpp index 6c209043..ce613a00 100644 --- a/src/games/skyrimse/src/skyrimsesavegame.cpp +++ b/src/games/skyrimse/src/skyrimsesavegame.cpp @@ -8,7 +8,8 @@ SkyrimSESaveGame::SkyrimSESaveGame(QString const &fileName, MOBase::IPluginGame FileWrapper file(this, "TESV_SAVEGAME"); //10bytes unsigned long headerSize; file.read(headerSize); // header size "TESV_SAVEGAME" - file.skip(); // header version 74. Original Skyrim is 79 + unsigned long version = 0; + file.read(version); file.read(m_SaveNumber); file.read(m_PCName); @@ -53,9 +54,17 @@ SkyrimSESaveGame::SkyrimSESaveGame(QString const &fileName, MOBase::IPluginGame file.read(width); file.read(height); - file.read(m_CompressionType); + bool alpha = false; - file.readImage(width, height, 320, true); + // compatibility between LE and SE: + // SE has an additional uin16_t for compression + // SE uses an alpha channel, whereas LE does not + if (static_cast(version) == GameVersions::SpecialEdition) { + file.read(m_CompressionType); + alpha = true; + } + + file.readImage(width, height, 320, alpha); file.openCompressedData(); From bcd3a1df75da46881237dd935b2c4b599d2a9283 Mon Sep 17 00:00:00 2001 From: isanae <14251494+isanae@users.noreply.github.com> Date: Wed, 3 Jul 2019 18:29:05 -0400 Subject: [PATCH 0818/1544] [game_skyrimse] just use the version number directly --- src/games/skyrimse/src/skyrimsesavegame.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/games/skyrimse/src/skyrimsesavegame.cpp b/src/games/skyrimse/src/skyrimsesavegame.cpp index ce613a00..c4a807e9 100644 --- a/src/games/skyrimse/src/skyrimsesavegame.cpp +++ b/src/games/skyrimse/src/skyrimsesavegame.cpp @@ -59,7 +59,7 @@ SkyrimSESaveGame::SkyrimSESaveGame(QString const &fileName, MOBase::IPluginGame // compatibility between LE and SE: // SE has an additional uin16_t for compression // SE uses an alpha channel, whereas LE does not - if (static_cast(version) == GameVersions::SpecialEdition) { + if (version == 12) { file.read(m_CompressionType); alpha = true; } From f392f3f6627acf41ff9d2d52dfec2456a5065563 Mon Sep 17 00:00:00 2001 From: isanae <14251494+isanae@users.noreply.github.com> Date: Fri, 19 Jul 2019 06:14:12 -0400 Subject: [PATCH 0819/1544] useless logging --- src/gamebryo/gamebryolocalsavegames.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/gamebryo/gamebryolocalsavegames.cpp b/src/gamebryo/gamebryolocalsavegames.cpp index 5cdb6bc1..97fca7cb 100644 --- a/src/gamebryo/gamebryolocalsavegames.cpp +++ b/src/gamebryo/gamebryolocalsavegames.cpp @@ -52,7 +52,7 @@ bool GamebryoLocalSavegames::prepareProfile(MOBase::IProfile *profile) { bool dirty = false; bool enable = profile->localSavesEnabled(); - qDebug("enable local saves: %d", enable); + QString basePath = profile->localSettingsEnabled() ? profile->absolutePath() From 77a1a18f0fcb8a67aace3055948af2f5c82b027f Mon Sep 17 00:00:00 2001 From: isanae <14251494+isanae@users.noreply.github.com> Date: Fri, 19 Jul 2019 06:50:56 -0400 Subject: [PATCH 0820/1544] enabled install project in build removed useless message --- CMakeLists.txt | 8 +++++--- 1 file changed, 5 insertions(+), 3 deletions(-) diff --git a/CMakeLists.txt b/CMakeLists.txt index 0c7189e0..a9a4a8e7 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -1,17 +1,19 @@ CMAKE_MINIMUM_REQUIRED(VERSION 2.8.12) -ADD_COMPILE_OPTIONS($<$:/MP> $<$:$<$:/O2>> $<$:$<$:/O2>>) +ADD_COMPILE_OPTIONS( + $<$:/MP> + $<$:$<$:/O2>> + $<$:$<$:/O2>>) SET(PROJ_NAME game_gamebryo) PROJECT(${PROJ_NAME}) +set(CMAKE_VS_INCLUDE_INSTALL_TO_DEFAULT_BUILD 1) SET(DEPENDENCIES_DIR CACHE PATH "") # hint to find qt in dependencies path LIST(APPEND CMAKE_PREFIX_PATH ${QT_ROOT}/lib/cmake) - LIST(APPEND CMAKE_PREFIX_PATH ${LZ4_ROOT}/dll) -message(${LZ4_ROOT}) ADD_SUBDIRECTORY(src/gamebryo) ADD_SUBDIRECTORY(src/creation) From 786ac99da256582515fad2719a6ba9146e50d3f5 Mon Sep 17 00:00:00 2001 From: Al Date: Thu, 29 Aug 2019 16:41:44 +0200 Subject: [PATCH 0821/1544] [game_fallout3] Added support for FalloutCustom.ini to FO3 --- src/games/fallout3/src/gamefallout3.cpp | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/src/games/fallout3/src/gamefallout3.cpp b/src/games/fallout3/src/gamefallout3.cpp index 9970ebf5..b74619d8 100644 --- a/src/games/fallout3/src/gamefallout3.cpp +++ b/src/games/fallout3/src/gamefallout3.cpp @@ -112,7 +112,8 @@ void GameFallout3::initializeProfile(const QDir &path, ProfileSettings settings) } copyToProfile(myGamesPath(), path, "falloutprefs.ini"); - copyToProfile(myGamesPath(), path, "custom.ini"); + copyToProfile(myGamesPath(), path, "FalloutCustom.ini"); + copyToProfile(myGamesPath(), path, "custom.ini"); copyToProfile(myGamesPath(), path, "GECKCustom.ini"); copyToProfile(myGamesPath(), path, "GECKPrefs.ini"); } @@ -161,7 +162,7 @@ QString GameFallout3::gameNexusName() const QStringList GameFallout3::iniFiles() const { - return { "fallout.ini", "falloutprefs.ini", "custom.ini", "GECKCustom.ini", "GECKPrefs.ini" }; + return { "fallout.ini", "falloutprefs.ini", "custom.ini", "FalloutCustom.ini", "GECKCustom.ini", "GECKPrefs.ini" }; } QStringList GameFallout3::DLCPlugins() const From 10f3f4d6b72f5230b8b422e02221e9beb52d6c08 Mon Sep 17 00:00:00 2001 From: LostDragonist Date: Wed, 25 Sep 2019 17:45:07 -0500 Subject: [PATCH 0822/1544] [game_falloutnv] Add the ability to download and manage Fallout 3 mods --- src/games/falloutnv/src/gamefalloutnv.cpp | 7 ++++++- src/games/falloutnv/src/gamefalloutnv.h | 1 + 2 files changed, 7 insertions(+), 1 deletion(-) diff --git a/src/games/falloutnv/src/gamefalloutnv.cpp b/src/games/falloutnv/src/gamefalloutnv.cpp index fddc7a5a..b7f03d35 100644 --- a/src/games/falloutnv/src/gamefalloutnv.cpp +++ b/src/games/falloutnv/src/gamefalloutnv.cpp @@ -83,7 +83,7 @@ QString GameFalloutNV::description() const MOBase::VersionInfo GameFalloutNV::version() const { - return VersionInfo(1, 3, 1, VersionInfo::RELEASE_FINAL); + return VersionInfo(1, 4, 0, VersionInfo::RELEASE_FINAL); } bool GameFalloutNV::isActive() const @@ -145,6 +145,11 @@ QString GameFalloutNV::gameShortName() const return "FalloutNV"; } +QStringList GameFalloutNV::validShortNames() const +{ + return { "Fallout3" }; +} + QString GameFalloutNV::gameNexusName() const { return "newvegas"; diff --git a/src/games/falloutnv/src/gamefalloutnv.h b/src/games/falloutnv/src/gamefalloutnv.h index 1a4d38c7..5efee187 100644 --- a/src/games/falloutnv/src/gamefalloutnv.h +++ b/src/games/falloutnv/src/gamefalloutnv.h @@ -30,6 +30,7 @@ public: // IPluginGame interface virtual QString steamAPPId() const override; virtual QStringList primaryPlugins() 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; From 8508fc225387bbb32d223435f4aabd56a0097d15 Mon Sep 17 00:00:00 2001 From: LostDragonist Date: Wed, 25 Sep 2019 18:13:19 -0500 Subject: [PATCH 0823/1544] [game_fallout3] Add the ability to download and manage Fallout NV mods --- src/games/fallout3/src/gamefallout3.cpp | 9 ++++++--- src/games/fallout3/src/gamefallout3.h | 1 + 2 files changed, 7 insertions(+), 3 deletions(-) diff --git a/src/games/fallout3/src/gamefallout3.cpp b/src/games/fallout3/src/gamefallout3.cpp index b74619d8..ac0adf65 100644 --- a/src/games/fallout3/src/gamefallout3.cpp +++ b/src/games/fallout3/src/gamefallout3.cpp @@ -83,7 +83,7 @@ QString GameFallout3::description() const MOBase::VersionInfo GameFallout3::version() const { - return VersionInfo(1, 3, 1, VersionInfo::RELEASE_FINAL); + return VersionInfo(1, 4, 0, VersionInfo::RELEASE_FINAL); } bool GameFallout3::isActive() const @@ -143,7 +143,6 @@ QStringList GameFallout3::primaryPlugins() const return { "fallout3.esm" }; } - QStringList GameFallout3::gameVariants() const { return { "Regular", "Game Of The Year" }; @@ -154,12 +153,16 @@ QString GameFallout3::gameShortName() const return "Fallout3"; } +QStringList GameFallout3::validShortNames() const +{ + return { "FalloutNV" }; +} + QString GameFallout3::gameNexusName() const { return "fallout3"; } - QStringList GameFallout3::iniFiles() const { return { "fallout.ini", "falloutprefs.ini", "custom.ini", "FalloutCustom.ini", "GECKCustom.ini", "GECKPrefs.ini" }; diff --git a/src/games/fallout3/src/gamefallout3.h b/src/games/fallout3/src/gamefallout3.h index d7417bdf..787bc301 100644 --- a/src/games/fallout3/src/gamefallout3.h +++ b/src/games/fallout3/src/gamefallout3.h @@ -29,6 +29,7 @@ public: // IPluginGame interface virtual QStringList primaryPlugins() const override; virtual QStringList gameVariants() const; virtual QString gameShortName() const override; + virtual QStringList validShortNames() const override; virtual QString gameNexusName() const override; virtual QString getLauncherName() const override; virtual QStringList iniFiles() const override; From d3a3a5ffb3b6a27356838f5e9d6e4463b6922911 Mon Sep 17 00:00:00 2001 From: Silarn Date: Fri, 27 Sep 2019 23:48:47 -0500 Subject: [PATCH 0824/1544] [game_morrowind] Compatibility update --- src/games/morrowind/src/morrowindsavegame.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/games/morrowind/src/morrowindsavegame.cpp b/src/games/morrowind/src/morrowindsavegame.cpp index 39d7623c..fb216fa8 100644 --- a/src/games/morrowind/src/morrowindsavegame.cpp +++ b/src/games/morrowind/src/morrowindsavegame.cpp @@ -103,7 +103,7 @@ MorrowindSaveGame::MorrowindSaveGame(QString const &fileName, MOBase::IPluginGam } } - std::experimental::filesystem::path realFile(fileName.toStdWString()); + std::filesystem::path realFile(fileName.toStdWString()); QString realFileName = QString::fromStdWString(realFile.filename().wstring()); m_SaveNumber = realFileName.mid(4, 5).remove(QRegExp("0+$")).toInt(); } From db19efd71dfddc6d35b72dae56a640a7501e78d8 Mon Sep 17 00:00:00 2001 From: Silarn Date: Sat, 28 Sep 2019 00:41:37 -0500 Subject: [PATCH 0825/1544] [game_fallout4vr] Update Appveyor to official VS 2019 image --- src/games/fallout4vr/appveyor.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/games/fallout4vr/appveyor.yml b/src/games/fallout4vr/appveyor.yml index fb43eb11..8158a4e5 100644 --- a/src/games/fallout4vr/appveyor.yml +++ b/src/games/fallout4vr/appveyor.yml @@ -1,6 +1,6 @@ version: 1.0.{build} skip_branch_with_pr: true -image: Visual Studio 2019 Preview +image: Visual Studio 2019 environment: WEBHOOK_URL: secure: gOKbXaZM9ImtMD5XrYITvdyZUW/az082G9OIN1EC1Vbg57wBaeLhi49uGjxPw5GVujHku6kxN6ab89zhbS5GVeluR76GM83IbKV4Sh7udXzoYZZdg6YudtYHzdhCgUeiedpswbuczTq9ceIkkfSEWZuh/lMAAVVwvcGsJAnoPFw= From b9667c068a777d29d412be08e5c67034bf1f9380 Mon Sep 17 00:00:00 2001 From: Silarn Date: Sat, 28 Sep 2019 00:41:38 -0500 Subject: [PATCH 0826/1544] [game_morrowind] Update Appveyor to official VS 2019 image --- src/games/morrowind/appveyor.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/games/morrowind/appveyor.yml b/src/games/morrowind/appveyor.yml index 6dbc0add..90353113 100644 --- a/src/games/morrowind/appveyor.yml +++ b/src/games/morrowind/appveyor.yml @@ -1,6 +1,6 @@ version: 1.0.{build} skip_branch_with_pr: true -image: Visual Studio 2019 Preview +image: Visual Studio 2019 environment: WEBHOOK_URL: secure: gOKbXaZM9ImtMD5XrYITvdyZUW/az082G9OIN1EC1Vbg57wBaeLhi49uGjxPw5GVujHku6kxN6ab89zhbS5GVeluR76GM83IbKV4Sh7udXzoYZZdg6YudtYHzdhCgUeiedpswbuczTq9ceIkkfSEWZuh/lMAAVVwvcGsJAnoPFw= From debbe3a2ce190472537b5aa2bee68e684f9bcb85 Mon Sep 17 00:00:00 2001 From: Silarn Date: Sat, 28 Sep 2019 00:41:40 -0500 Subject: [PATCH 0827/1544] [game_falloutnv] Update Appveyor to official VS 2019 image --- src/games/falloutnv/appveyor.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/games/falloutnv/appveyor.yml b/src/games/falloutnv/appveyor.yml index 8e92aa15..c9d0630b 100644 --- a/src/games/falloutnv/appveyor.yml +++ b/src/games/falloutnv/appveyor.yml @@ -1,6 +1,6 @@ version: 1.0.{build} skip_branch_with_pr: true -image: Visual Studio 2019 Preview +image: Visual Studio 2019 environment: WEBHOOK_URL: secure: gOKbXaZM9ImtMD5XrYITvdyZUW/az082G9OIN1EC1Vbg57wBaeLhi49uGjxPw5GVujHku6kxN6ab89zhbS5GVeluR76GM83IbKV4Sh7udXzoYZZdg6YudtYHzdhCgUeiedpswbuczTq9ceIkkfSEWZuh/lMAAVVwvcGsJAnoPFw= From 4486034c663ae63245f8c3bf1a4b534be9c23a25 Mon Sep 17 00:00:00 2001 From: Silarn Date: Sat, 28 Sep 2019 00:41:42 -0500 Subject: [PATCH 0828/1544] [game_skyrimvr] Update Appveyor to official VS 2019 image --- src/games/skyrimvr/appveyor.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/games/skyrimvr/appveyor.yml b/src/games/skyrimvr/appveyor.yml index 1a20f07f..f149e8e1 100644 --- a/src/games/skyrimvr/appveyor.yml +++ b/src/games/skyrimvr/appveyor.yml @@ -1,6 +1,6 @@ version: 1.0.{build} skip_branch_with_pr: true -image: Visual Studio 2019 Preview +image: Visual Studio 2019 environment: WEBHOOK_URL: secure: gOKbXaZM9ImtMD5XrYITvdyZUW/az082G9OIN1EC1Vbg57wBaeLhi49uGjxPw5GVujHku6kxN6ab89zhbS5GVeluR76GM83IbKV4Sh7udXzoYZZdg6YudtYHzdhCgUeiedpswbuczTq9ceIkkfSEWZuh/lMAAVVwvcGsJAnoPFw= From 518e5abd3ad214e4f2301d12ebbff02d4be5feeb Mon Sep 17 00:00:00 2001 From: Silarn Date: Sat, 28 Sep 2019 00:41:43 -0500 Subject: [PATCH 0829/1544] Update Appveyor to official VS 2019 image --- appveyor.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/appveyor.yml b/appveyor.yml index b6103ccc..7932ecda 100644 --- a/appveyor.yml +++ b/appveyor.yml @@ -1,6 +1,6 @@ version: 1.0.{build} skip_branch_with_pr: true -image: Visual Studio 2019 Preview +image: Visual Studio 2019 environment: WEBHOOK_URL: secure: gOKbXaZM9ImtMD5XrYITvdyZUW/az082G9OIN1EC1Vbg57wBaeLhi49uGjxPw5GVujHku6kxN6ab89zhbS5GVeluR76GM83IbKV4Sh7udXzoYZZdg6YudtYHzdhCgUeiedpswbuczTq9ceIkkfSEWZuh/lMAAVVwvcGsJAnoPFw= From 70049caa80b38a1b8db2f31b71bfc52ea64bbf80 Mon Sep 17 00:00:00 2001 From: Silarn Date: Sat, 28 Sep 2019 00:41:44 -0500 Subject: [PATCH 0830/1544] [game_fallout4] Update Appveyor to official VS 2019 image --- src/games/fallout4/appveyor.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/games/fallout4/appveyor.yml b/src/games/fallout4/appveyor.yml index 6b0ead4a..5ef81b21 100644 --- a/src/games/fallout4/appveyor.yml +++ b/src/games/fallout4/appveyor.yml @@ -1,6 +1,6 @@ version: 1.0.{build} skip_branch_with_pr: true -image: Visual Studio 2019 Preview +image: Visual Studio 2019 environment: WEBHOOK_URL: secure: gOKbXaZM9ImtMD5XrYITvdyZUW/az082G9OIN1EC1Vbg57wBaeLhi49uGjxPw5GVujHku6kxN6ab89zhbS5GVeluR76GM83IbKV4Sh7udXzoYZZdg6YudtYHzdhCgUeiedpswbuczTq9ceIkkfSEWZuh/lMAAVVwvcGsJAnoPFw= From 5fdd18c07d69894e68d9dcd57c10e20bce56f4fc Mon Sep 17 00:00:00 2001 From: Silarn Date: Sat, 28 Sep 2019 00:41:44 -0500 Subject: [PATCH 0831/1544] [game_fallout3] Update Appveyor to official VS 2019 image --- src/games/fallout3/appveyor.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/games/fallout3/appveyor.yml b/src/games/fallout3/appveyor.yml index c09a3a56..e776e806 100644 --- a/src/games/fallout3/appveyor.yml +++ b/src/games/fallout3/appveyor.yml @@ -1,6 +1,6 @@ version: 1.0.{build} skip_branch_with_pr: true -image: Visual Studio 2019 Preview +image: Visual Studio 2019 environment: WEBHOOK_URL: secure: gOKbXaZM9ImtMD5XrYITvdyZUW/az082G9OIN1EC1Vbg57wBaeLhi49uGjxPw5GVujHku6kxN6ab89zhbS5GVeluR76GM83IbKV4Sh7udXzoYZZdg6YudtYHzdhCgUeiedpswbuczTq9ceIkkfSEWZuh/lMAAVVwvcGsJAnoPFw= From cd44fdd6a460a64271d06713501c55d641e83e13 Mon Sep 17 00:00:00 2001 From: Silarn Date: Sat, 28 Sep 2019 00:41:46 -0500 Subject: [PATCH 0832/1544] [game_skyrimse] Update Appveyor to official VS 2019 image --- src/games/skyrimse/appveyor.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/games/skyrimse/appveyor.yml b/src/games/skyrimse/appveyor.yml index ddc0f0f4..ce9d17eb 100644 --- a/src/games/skyrimse/appveyor.yml +++ b/src/games/skyrimse/appveyor.yml @@ -1,6 +1,6 @@ version: 1.0.{build} skip_branch_with_pr: true -image: Visual Studio 2019 Preview +image: Visual Studio 2019 environment: WEBHOOK_URL: secure: gOKbXaZM9ImtMD5XrYITvdyZUW/az082G9OIN1EC1Vbg57wBaeLhi49uGjxPw5GVujHku6kxN6ab89zhbS5GVeluR76GM83IbKV4Sh7udXzoYZZdg6YudtYHzdhCgUeiedpswbuczTq9ceIkkfSEWZuh/lMAAVVwvcGsJAnoPFw= From 24893a15dd2a30d93a280803ecde84bf481a240f Mon Sep 17 00:00:00 2001 From: Silarn Date: Sat, 28 Sep 2019 00:41:47 -0500 Subject: [PATCH 0833/1544] [game_oblivion] Update Appveyor to official VS 2019 image --- src/games/oblivion/appveyor.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/games/oblivion/appveyor.yml b/src/games/oblivion/appveyor.yml index 1436d8a0..4abade28 100644 --- a/src/games/oblivion/appveyor.yml +++ b/src/games/oblivion/appveyor.yml @@ -1,6 +1,6 @@ version: 1.0.{build} skip_branch_with_pr: true -image: Visual Studio 2019 Preview +image: Visual Studio 2019 environment: WEBHOOK_URL: secure: gOKbXaZM9ImtMD5XrYITvdyZUW/az082G9OIN1EC1Vbg57wBaeLhi49uGjxPw5GVujHku6kxN6ab89zhbS5GVeluR76GM83IbKV4Sh7udXzoYZZdg6YudtYHzdhCgUeiedpswbuczTq9ceIkkfSEWZuh/lMAAVVwvcGsJAnoPFw= From c8bd2f403630e3940b842fafe839fb3e232b47c5 Mon Sep 17 00:00:00 2001 From: Silarn Date: Sat, 28 Sep 2019 00:41:49 -0500 Subject: [PATCH 0834/1544] [game_skyrim] Update Appveyor to official VS 2019 image --- src/games/skyrim/appveyor.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/games/skyrim/appveyor.yml b/src/games/skyrim/appveyor.yml index 62789332..5938d9ed 100644 --- a/src/games/skyrim/appveyor.yml +++ b/src/games/skyrim/appveyor.yml @@ -1,6 +1,6 @@ version: 1.0.{build} skip_branch_with_pr: true -image: Visual Studio 2019 Preview +image: Visual Studio 2019 environment: WEBHOOK_URL: secure: gOKbXaZM9ImtMD5XrYITvdyZUW/az082G9OIN1EC1Vbg57wBaeLhi49uGjxPw5GVujHku6kxN6ab89zhbS5GVeluR76GM83IbKV4Sh7udXzoYZZdg6YudtYHzdhCgUeiedpswbuczTq9ceIkkfSEWZuh/lMAAVVwvcGsJAnoPFw= From 8f30368f1485f403530482a85b19ead730cba7e2 Mon Sep 17 00:00:00 2001 From: Silarn Date: Sat, 28 Sep 2019 00:41:51 -0500 Subject: [PATCH 0835/1544] [game_ttw] Update Appveyor to official VS 2019 image --- src/games/ttw/appveyor.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/games/ttw/appveyor.yml b/src/games/ttw/appveyor.yml index aac65ea8..87eccb06 100644 --- a/src/games/ttw/appveyor.yml +++ b/src/games/ttw/appveyor.yml @@ -1,6 +1,6 @@ version: 1.0.{build} skip_branch_with_pr: true -image: Visual Studio 2019 Preview +image: Visual Studio 2019 environment: WEBHOOK_URL: secure: gOKbXaZM9ImtMD5XrYITvdyZUW/az082G9OIN1EC1Vbg57wBaeLhi49uGjxPw5GVujHku6kxN6ab89zhbS5GVeluR76GM83IbKV4Sh7udXzoYZZdg6YudtYHzdhCgUeiedpswbuczTq9ceIkkfSEWZuh/lMAAVVwvcGsJAnoPFw= From 86560d2133183f6af9d9a7a20e429d7ed0185a8f Mon Sep 17 00:00:00 2001 From: LostDragonist Date: Wed, 2 Oct 2019 09:00:45 -0500 Subject: [PATCH 0836/1544] Fix issue when disabling profile-specific game saves --- src/gamebryo/gamebryolocalsavegames.cpp | 57 ++++++++++++++----------- 1 file changed, 31 insertions(+), 26 deletions(-) diff --git a/src/gamebryo/gamebryolocalsavegames.cpp b/src/gamebryo/gamebryolocalsavegames.cpp index 97fca7cb..db4529d0 100644 --- a/src/gamebryo/gamebryolocalsavegames.cpp +++ b/src/gamebryo/gamebryolocalsavegames.cpp @@ -29,35 +29,36 @@ Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA static const QString LocalSavesDummy = "__MO_Saves"; -GamebryoLocalSavegames::GamebryoLocalSavegames(const QDir &myGamesDir, - const QString &iniFileName) +GamebryoLocalSavegames::GamebryoLocalSavegames(const QDir& myGamesDir, + const QString& iniFileName) : m_LocalSavesDir(myGamesDir.absoluteFilePath(LocalSavesDummy)) , m_LocalGameDir(myGamesDir.absolutePath()) , m_IniFileName(iniFileName) {} -MappingType GamebryoLocalSavegames::mappings(const QDir &profileSaveDir) const +MappingType GamebryoLocalSavegames::mappings(const QDir& profileSaveDir) const { - return {{ + return { { profileSaveDir.absolutePath(), m_LocalSavesDir.absolutePath(), true, true - }}; + } }; } -bool GamebryoLocalSavegames::prepareProfile(MOBase::IProfile *profile) +bool GamebryoLocalSavegames::prepareProfile(MOBase::IProfile* profile) { bool dirty = false; bool enable = profile->localSavesEnabled(); QString basePath - = profile->localSettingsEnabled() - ? profile->absolutePath() - : m_LocalGameDir.absolutePath(); + = profile->localSettingsEnabled() + ? profile->absolutePath() + : m_LocalGameDir.absolutePath(); QString iniFilePath = basePath + "/" + m_IniFileName; + QString savepathFilePath = profile->absolutePath() + "/" + "savepath.ini"; WCHAR oldPath[MAX_PATH]; WCHAR oldMyGames[1]; @@ -65,9 +66,9 @@ bool GamebryoLocalSavegames::prepareProfile(MOBase::IProfile *profile) GetPrivateProfileStringW(L"General", L"bUseMyGamesDirectory", NULL, oldMyGames, 1, iniFilePath.toStdWString().c_str()); if (enable && wcscmp(oldPath, L"") != 0 && wcscmp(oldPath, (LocalSavesDummy + "\\").toStdWString().c_str()) != 0) { dirty = true; - MOBase::WriteRegistryValue(L"General", L"SLocalSavePath", oldPath, QString(profile->absolutePath() + "/" + "savepath.ini").toStdWString().c_str()); + MOBase::WriteRegistryValue(L"General", L"SLocalSavePath", oldPath, savepathFilePath.toStdWString().c_str()); if (wcscmp(oldMyGames, L"") != 0) { - MOBase::WriteRegistryValue(L"General", L"bUseMyGamesDirectory", oldMyGames, QString(profile->absolutePath() + "/" + "savepath.ini").toStdWString().c_str()); + MOBase::WriteRegistryValue(L"General", L"bUseMyGamesDirectory", oldMyGames, savepathFilePath.toStdWString().c_str()); } } bool saved = false; @@ -75,16 +76,17 @@ bool GamebryoLocalSavegames::prepareProfile(MOBase::IProfile *profile) WCHAR savedPath[MAX_PATH]; WCHAR savedMyGames[1]; if (!enable) { - if (QFile::exists(QString(profile->absolutePath() + "/" + "savepath.ini"))) { + if (QFile::exists(savepathFilePath)) { saved = true; - GetPrivateProfileStringW(L"General", L"SLocalSavePath", NULL, savedPath, MAX_PATH, QString(profile->absolutePath() + "/" + "savepath.ini").toStdWString().c_str()); - GetPrivateProfileStringW(L"General", L"bUseMyGamesDirectory", NULL, savedMyGames, 1, QString(profile->absolutePath() + "/" + "savepath.ini").toStdWString().c_str()); + GetPrivateProfileStringW(L"General", L"SLocalSavePath", NULL, savedPath, MAX_PATH, savepathFilePath.toStdWString().c_str()); + GetPrivateProfileStringW(L"General", L"bUseMyGamesDirectory", NULL, savedMyGames, 1, savepathFilePath.toStdWString().c_str()); if (wcscmp(savedMyGames, L"") != 0) { savedDir = true; } - QFile::remove(QString(profile->absolutePath() + "/" + "savepath.ini")); + QFile::remove(savepathFilePath); } - } else { + } + else { QDir saves = QDir(m_LocalGameDir.absolutePath() + "/" + LocalSavesDummy); if (!saves.exists()) { saves.mkdir("."); @@ -92,19 +94,20 @@ bool GamebryoLocalSavegames::prepareProfile(MOBase::IProfile *profile) } if (enable) { - if (wcscmp(oldPath, (LocalSavesDummy + "\\").toStdWString().c_str()) != 0){ + if (wcscmp(oldPath, (LocalSavesDummy + "\\").toStdWString().c_str()) != 0) { MOBase::WriteRegistryValue(L"General", L"SLocalSavePath", - (LocalSavesDummy + "\\").toStdWString().c_str(), - iniFilePath.toStdWString().c_str()); + (LocalSavesDummy + "\\").toStdWString().c_str(), + iniFilePath.toStdWString().c_str()); dirty = true; } if (wcscmp(oldMyGames, L"") != 0) { MOBase::WriteRegistryValue(L"General", L"bUseMyGamesDirectory", - NULL, - iniFilePath.toStdWString().c_str()); + NULL, + iniFilePath.toStdWString().c_str()); dirty = true; } - } else { + } + else { if (saved) { if (wcscmp(oldPath, savedPath) != 0) { MOBase::WriteRegistryValue(L"General", L"SLocalSavePath", @@ -112,8 +115,9 @@ bool GamebryoLocalSavegames::prepareProfile(MOBase::IProfile *profile) iniFilePath.toStdWString().c_str()); dirty = true; } - } else { - if (wcscmp(oldPath, L"") == 0) { + } + else { + if (wcscmp(oldPath, L"") != 0) { MOBase::WriteRegistryValue(L"General", L"SLocalSavePath", NULL, iniFilePath.toStdWString().c_str()); @@ -127,8 +131,9 @@ bool GamebryoLocalSavegames::prepareProfile(MOBase::IProfile *profile) iniFilePath.toStdWString().c_str()); dirty = true; } - } else { - if (wcscmp(oldMyGames, L"") == 0) { + } + else { + if (wcscmp(oldMyGames, L"") != 0) { MOBase::WriteRegistryValue(L"General", L"bUseMyGamesDirectory", NULL, iniFilePath.toStdWString().c_str()); From 4e550f5da04538de22f37c811e4a69ee443c9a86 Mon Sep 17 00:00:00 2001 From: LostDragonist Date: Sun, 6 Oct 2019 12:21:32 -0500 Subject: [PATCH 0837/1544] Downgrade failures to set archives and archive invalidation to warnings Some users value the ability to keep INI files as read-only and do not want to be constantly nagged to clear the read-only status. This allows them to mostly ignore the nags. --- src/gamebryo/gamebryobsainvalidation.cpp | 6 +++--- src/gamebryo/gamebryodataarchives.cpp | 2 +- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/src/gamebryo/gamebryobsainvalidation.cpp b/src/gamebryo/gamebryobsainvalidation.cpp index d1284ef3..9db2b857 100644 --- a/src/gamebryo/gamebryobsainvalidation.cpp +++ b/src/gamebryo/gamebryobsainvalidation.cpp @@ -60,7 +60,7 @@ bool GamebryoBSAInvalidation::prepareProfile(MOBase::IProfile *profile) || wcstol(setting, nullptr, 10) != 1) { dirty = true; if (!MOBase::WriteRegistryValue(L"Archive", L"bInvalidateOlderFiles", L"1", iniFilePath.toStdWString().c_str())) { - throw MOBase::MyException(QObject::tr("failed to activate BSA invalidation in \"%1\" (errorcode %2)").arg(m_IniFileName, ::GetLastError())); + qWarning("failed to activate BSA invalidation in \"%s\"", qUtf8Printable(m_IniFileName)); } } @@ -93,7 +93,7 @@ bool GamebryoBSAInvalidation::prepareProfile(MOBase::IProfile *profile) || wcscmp(setting, L"") != 0) { dirty = true; if (!MOBase::WriteRegistryValue(L"Archive", L"SInvalidationFile", L"", iniFilePath.toStdWString().c_str())) { - throw MOBase::MyException(QObject::tr("failed to activate BSA invalidation in \"%1\" (errorcode %2)").arg(m_IniFileName, ::GetLastError())); + qWarning("failed to activate BSA invalidation in \"%s\"", qUtf8Printable(m_IniFileName)); } } } else { @@ -119,7 +119,7 @@ bool GamebryoBSAInvalidation::prepareProfile(MOBase::IProfile *profile) || wcscmp(setting, L"ArchiveInvalidation.txt") != 0) { dirty = true; if (!MOBase::WriteRegistryValue(L"Archive", L"SInvalidationFile", L"ArchiveInvalidation.txt", iniFilePath.toStdWString().c_str())) { - throw MOBase::MyException(QObject::tr("failed to activate BSA invalidation in \"%1\" (errorcode %2)").arg(m_IniFileName, ::GetLastError())); + qWarning("failed to activate BSA invalidation in \"%s\"", qUtf8Printable(m_IniFileName)); } } } diff --git a/src/gamebryo/gamebryodataarchives.cpp b/src/gamebryo/gamebryodataarchives.cpp index 2b4370e8..cdeb4ea5 100644 --- a/src/gamebryo/gamebryodataarchives.cpp +++ b/src/gamebryo/gamebryodataarchives.cpp @@ -33,7 +33,7 @@ QStringList GamebryoDataArchives::getArchivesFromKey(const QString &iniFile, con void GamebryoDataArchives::setArchivesToKey(const QString &iniFile, const QString &key, const QString &value) { if (!MOBase::WriteRegistryValue(L"Archive", key.toStdWString().c_str(), value.toStdWString().c_str(), iniFile.toStdWString().c_str())) { - throw MOBase::MyException(QObject::tr("failed to set archive key in %1 (errorcode %2)").arg(iniFile).arg(errno)); + qWarning("failed to set archives in \"%s\"", qUtf8Printable(iniFile)); } } From 3d4bf90bf5e70bfffff21406e27d723a8c957164 Mon Sep 17 00:00:00 2001 From: LostDragonist Date: Sun, 6 Oct 2019 12:22:57 -0500 Subject: [PATCH 0838/1544] [game_morrowind] Downgrade failures to set archives and archive invalidation to warnings Some users value the ability to keep INI files as read-only and do not want to be constantly nagged to clear the read-only status. This allows them to mostly ignore the nags. --- src/games/morrowind/src/gamemorrowind.cpp | 2 +- src/games/morrowind/src/morrowinddataarchives.cpp | 2 +- src/games/morrowind/src/morrowindgameplugins.cpp | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) diff --git a/src/games/morrowind/src/gamemorrowind.cpp b/src/games/morrowind/src/gamemorrowind.cpp index abc7fcbb..3f947a01 100644 --- a/src/games/morrowind/src/gamemorrowind.cpp +++ b/src/games/morrowind/src/gamemorrowind.cpp @@ -106,7 +106,7 @@ QString GameMorrowind::description() const MOBase::VersionInfo GameMorrowind::version() const { - return VersionInfo(1, 3, 1, VersionInfo::RELEASE_FINAL); + return VersionInfo(1, 4, 0, VersionInfo::RELEASE_FINAL); } bool GameMorrowind::isActive() const diff --git a/src/games/morrowind/src/morrowinddataarchives.cpp b/src/games/morrowind/src/morrowinddataarchives.cpp index ecbc5abd..c35c8481 100644 --- a/src/games/morrowind/src/morrowinddataarchives.cpp +++ b/src/games/morrowind/src/morrowinddataarchives.cpp @@ -40,7 +40,7 @@ void MorrowindDataArchives::setArchives(const QString &iniFile, const QStringLis int writtenCount = 0; foreach(const QString &value, list) { if (!MOBase::WriteRegistryValue(L"Archives", (key+QString::number(writtenCount)).toStdWString().c_str(), value.toStdWString().c_str(), iniFile.toStdWString().c_str())) { - throw MOBase::MyException(QObject::tr("failed to set archive key (errorcode %1)").arg(errno)); + qWarning("failed to set archives in \"%s\"", qUtf8Printable(iniFile)); } ++writtenCount; } diff --git a/src/games/morrowind/src/morrowindgameplugins.cpp b/src/games/morrowind/src/morrowindgameplugins.cpp index 0fa7910b..9550bb8d 100644 --- a/src/games/morrowind/src/morrowindgameplugins.cpp +++ b/src/games/morrowind/src/morrowindgameplugins.cpp @@ -104,7 +104,7 @@ void MorrowindGamePlugins::writeList(const IPluginList *pluginList, qCritical("invalid plugin name %s", qUtf8Printable(pluginName)); } else { if (!MOBase::WriteRegistryValue(L"Game Files", (key+QString::number(writtenCount)).toStdWString().c_str(), pluginName.toStdWString().c_str(), filePath.toStdWString().c_str())) { - throw MOBase::MyException(QObject::tr("failed to set game file key (errorcode %1)").arg(errno)); + qWarning("failed to set game files in \"%s\"", qUtf8Printable(filePath)); } } ++writtenCount; From 914cd89fe5f8d3d99b7ffe66be0db80dc4d2e22b Mon Sep 17 00:00:00 2001 From: LostDragonist Date: Tue, 15 Oct 2019 11:43:52 -0500 Subject: [PATCH 0839/1544] Report light plugins are supported for Creation games and not supported for Gamebryo games --- src/creation/creationgameplugins.cpp | 5 +++++ src/creation/creationgameplugins.h | 1 + src/gamebryo/gamebryogameplugins.cpp | 5 +++++ src/gamebryo/gamebryogameplugins.h | 1 + 4 files changed, 12 insertions(+) diff --git a/src/creation/creationgameplugins.cpp b/src/creation/creationgameplugins.cpp index adb0b44b..1d22e545 100644 --- a/src/creation/creationgameplugins.cpp +++ b/src/creation/creationgameplugins.cpp @@ -180,3 +180,8 @@ QStringList CreationGamePlugins::readPluginList(MOBase::IPluginList *pluginList) return loadOrder; } + +bool CreationGamePlugins::lightPluginsAreSupported() +{ + return true; +} \ No newline at end of file diff --git a/src/creation/creationgameplugins.h b/src/creation/creationgameplugins.h index 23e3c33b..635d67a1 100644 --- a/src/creation/creationgameplugins.h +++ b/src/creation/creationgameplugins.h @@ -16,6 +16,7 @@ protected: const QString &filePath) override; virtual QStringList readPluginList(MOBase::IPluginList *pluginList) override; virtual void getLoadOrder(QStringList &loadOrder) override; + virtual bool lightPluginsAreSupported() override; private: std::map m_LastSaveHash; diff --git a/src/gamebryo/gamebryogameplugins.cpp b/src/gamebryo/gamebryogameplugins.cpp index 51cf2075..df6e6338 100644 --- a/src/gamebryo/gamebryogameplugins.cpp +++ b/src/gamebryo/gamebryogameplugins.cpp @@ -250,3 +250,8 @@ QStringList GamebryoGamePlugins::readPluginList(MOBase::IPluginList *pluginList) return primary + plugins; } + +bool GamebryoGamePlugins::lightPluginsAreSupported() +{ + return false; +} \ No newline at end of file diff --git a/src/gamebryo/gamebryogameplugins.h b/src/gamebryo/gamebryogameplugins.h index 7fff3c9c..5e9f6a16 100644 --- a/src/gamebryo/gamebryogameplugins.h +++ b/src/gamebryo/gamebryogameplugins.h @@ -15,6 +15,7 @@ public: virtual void writePluginLists(const MOBase::IPluginList *pluginList) override; virtual void readPluginLists(MOBase::IPluginList *pluginList) override; virtual void getLoadOrder(QStringList &loadOrder) override; + virtual bool lightPluginsAreSupported() override; protected: QTextCodec *utf8Codec() const { return m_Utf8Codec; } From 2fade883c69bea674651c9d5ec232d8c0ab0b2c6 Mon Sep 17 00:00:00 2001 From: Silarn Date: Sat, 19 Oct 2019 03:44:26 -0500 Subject: [PATCH 0840/1544] [game_morrowind] Add LOOT to startup executables --- src/games/morrowind/src/gamemorrowind.cpp | 1 + 1 file changed, 1 insertion(+) diff --git a/src/games/morrowind/src/gamemorrowind.cpp b/src/games/morrowind/src/gamemorrowind.cpp index 3f947a01..d2c1a684 100644 --- a/src/games/morrowind/src/gamemorrowind.cpp +++ b/src/games/morrowind/src/gamemorrowind.cpp @@ -80,6 +80,7 @@ QList GameMorrowind::executables() const << ExecutableInfo("Morrowind", findInGameFolder(binaryName())) << ExecutableInfo("Morrowind Launcher", findInGameFolder(getLauncherName())) << ExecutableInfo("MGE XE", findInGameFolder("MGEXEgui.exe")) + << ExecutableInfo("LOOT", getLootPath()).withArgument("--game=\"Morrowind\"") ; } From e0e37c38ebd74923275a6cdc7e1b7deef9f782f5 Mon Sep 17 00:00:00 2001 From: LostDragonist Date: Sat, 7 Dec 2019 01:28:21 -0700 Subject: [PATCH 0841/1544] [game_fallout4] Update translations --- src/games/fallout4/src/game_fallout4_en.ts | 12 ------------ 1 file changed, 12 deletions(-) diff --git a/src/games/fallout4/src/game_fallout4_en.ts b/src/games/fallout4/src/game_fallout4_en.ts index c306181a..81bc0496 100644 --- a/src/games/fallout4/src/game_fallout4_en.ts +++ b/src/games/fallout4/src/game_fallout4_en.ts @@ -67,13 +67,6 @@ Splash by %1 Some of your plugins have invalid names! These plugins can not be loaded by the game. Please see mo_interface.log for a list of affected plugins and rename them. - - - - - failed to activate BSA invalidation in "%1" (errorcode %2) - - failed to open %1 @@ -94,10 +87,5 @@ Splash by %1 failed to query registry path (read): %1 - - - failed to set archive key in %1 (errorcode %2) - - From c6becee091cb78cace1a60a2ba69a42044ea6bcd Mon Sep 17 00:00:00 2001 From: LostDragonist Date: Sat, 7 Dec 2019 01:28:21 -0700 Subject: [PATCH 0842/1544] [game_fallout4vr] Update translations --- src/games/fallout4vr/src/game_fallout4vr_en.ts | 12 ------------ 1 file changed, 12 deletions(-) diff --git a/src/games/fallout4vr/src/game_fallout4vr_en.ts b/src/games/fallout4vr/src/game_fallout4vr_en.ts index 600a34ed..97dfecee 100644 --- a/src/games/fallout4vr/src/game_fallout4vr_en.ts +++ b/src/games/fallout4vr/src/game_fallout4vr_en.ts @@ -77,13 +77,6 @@ Splash by %1 failed to query registry path (read): %1 - - - - - failed to activate BSA invalidation in "%1" (errorcode %2) - - failed to open %1 @@ -94,10 +87,5 @@ Splash by %1 wrong file format - expected %1 got %2 - - - failed to set archive key in %1 (errorcode %2) - - From 9441979c3f69fd6e4b1d409916d157fd61e17f92 Mon Sep 17 00:00:00 2001 From: LostDragonist Date: Sat, 7 Dec 2019 01:28:21 -0700 Subject: [PATCH 0843/1544] [game_oblivion] Update translations --- src/games/oblivion/src/game_oblivion_en.ts | 12 ------------ 1 file changed, 12 deletions(-) diff --git a/src/games/oblivion/src/game_oblivion_en.ts b/src/games/oblivion/src/game_oblivion_en.ts index 34653c86..75dda7e2 100644 --- a/src/games/oblivion/src/game_oblivion_en.ts +++ b/src/games/oblivion/src/game_oblivion_en.ts @@ -60,13 +60,6 @@ QObject - - - - - failed to activate BSA invalidation in "%1" (errorcode %2) - - Some of your plugins have invalid names! These plugins can not be loaded by the game. Please see mo_interface.log for a list of affected plugins and rename them. @@ -92,10 +85,5 @@ failed to query registry path (read): %1 - - - failed to set archive key in %1 (errorcode %2) - - From 744dccc1aae13d182a20bc60fb98755b57b45a97 Mon Sep 17 00:00:00 2001 From: LostDragonist Date: Sat, 7 Dec 2019 01:28:21 -0700 Subject: [PATCH 0844/1544] [game_skyrim] Update translations --- src/games/skyrim/src/game_skyrim_en.ts | 12 ------------ 1 file changed, 12 deletions(-) diff --git a/src/games/skyrim/src/game_skyrim_en.ts b/src/games/skyrim/src/game_skyrim_en.ts index 7b2d227d..72f08d7f 100644 --- a/src/games/skyrim/src/game_skyrim_en.ts +++ b/src/games/skyrim/src/game_skyrim_en.ts @@ -60,13 +60,6 @@ QObject - - - - - failed to activate BSA invalidation in "%1" (errorcode %2) - - Some of your plugins have invalid names! These plugins can not be loaded by the game. Please see mo_interface.log for a list of affected plugins and rename them. @@ -92,10 +85,5 @@ failed to query registry path (read): %1 - - - failed to set archive key in %1 (errorcode %2) - - From b0ad2562e3561514562b4fd8470a2dc6394c3e53 Mon Sep 17 00:00:00 2001 From: LostDragonist Date: Sat, 7 Dec 2019 01:28:21 -0700 Subject: [PATCH 0845/1544] [game_skyrimse] Update translations --- src/games/skyrimse/src/game_skyrimse_en.ts | 12 ------------ 1 file changed, 12 deletions(-) diff --git a/src/games/skyrimse/src/game_skyrimse_en.ts b/src/games/skyrimse/src/game_skyrimse_en.ts index 13007e99..615c27d1 100644 --- a/src/games/skyrimse/src/game_skyrimse_en.ts +++ b/src/games/skyrimse/src/game_skyrimse_en.ts @@ -76,13 +76,6 @@ Some of your plugins have invalid names! These plugins can not be loaded by the game. Please see mo_interface.log for a list of affected plugins and rename them. - - - - - failed to activate BSA invalidation in "%1" (errorcode %2) - - failed to open %1 @@ -93,10 +86,5 @@ wrong file format - expected %1 got %2 - - - failed to set archive key in %1 (errorcode %2) - - From fa1e9cdbf7339914af540918404d7378d6af6064 Mon Sep 17 00:00:00 2001 From: LostDragonist Date: Sat, 7 Dec 2019 01:28:21 -0700 Subject: [PATCH 0846/1544] [game_skyrimvr] Update translations --- src/games/skyrimvr/src/game_skyrimvr_en.ts | 12 ------------ 1 file changed, 12 deletions(-) diff --git a/src/games/skyrimvr/src/game_skyrimvr_en.ts b/src/games/skyrimvr/src/game_skyrimvr_en.ts index b2fec422..d1c07d1a 100644 --- a/src/games/skyrimvr/src/game_skyrimvr_en.ts +++ b/src/games/skyrimvr/src/game_skyrimvr_en.ts @@ -76,13 +76,6 @@ Some of your plugins have invalid names! These plugins can not be loaded by the game. Please see mo_interface.log for a list of affected plugins and rename them. - - - - - failed to activate BSA invalidation in "%1" (errorcode %2) - - failed to open %1 @@ -93,10 +86,5 @@ wrong file format - expected %1 got %2 - - - failed to set archive key in %1 (errorcode %2) - - From f85acd1cbf63b706382928ac372a9bdc475f9e59 Mon Sep 17 00:00:00 2001 From: LostDragonist Date: Sat, 7 Dec 2019 01:28:21 -0700 Subject: [PATCH 0847/1544] [game_morrowind] Update translations --- src/games/morrowind/src/game_morrowind_en.ts | 24 +------------------- 1 file changed, 1 insertion(+), 23 deletions(-) diff --git a/src/games/morrowind/src/game_morrowind_en.ts b/src/games/morrowind/src/game_morrowind_en.ts index 8baf04b4..cd24c464 100644 --- a/src/games/morrowind/src/game_morrowind_en.ts +++ b/src/games/morrowind/src/game_morrowind_en.ts @@ -4,7 +4,7 @@ GameMorrowind - + Adds support for the game Morrowind. Splash by %1 @@ -104,18 +104,6 @@ Splash by %1 QObject - - - - - failed to activate BSA invalidation in "%1" (errorcode %2) - - - - - failed to set archive key in %1 (errorcode %2) - - @@ -142,15 +130,5 @@ Splash by %1 failed to query registry path (read): %1 - - - failed to set archive key (errorcode %1) - - - - - failed to set game file key (errorcode %1) - - From 09bca1b4c7fe39bd657be1a5694076af3efec42e Mon Sep 17 00:00:00 2001 From: LostDragonist Date: Sat, 7 Dec 2019 01:28:21 -0700 Subject: [PATCH 0848/1544] [game_fallout3] Update translations --- src/games/fallout3/src/game_fallout3_en.ts | 12 ------------ 1 file changed, 12 deletions(-) diff --git a/src/games/fallout3/src/game_fallout3_en.ts b/src/games/fallout3/src/game_fallout3_en.ts index aa4005d7..334bc0be 100644 --- a/src/games/fallout3/src/game_fallout3_en.ts +++ b/src/games/fallout3/src/game_fallout3_en.ts @@ -60,13 +60,6 @@ QObject - - - - - failed to activate BSA invalidation in "%1" (errorcode %2) - - Some of your plugins have invalid names! These plugins can not be loaded by the game. Please see mo_interface.log for a list of affected plugins and rename them. @@ -92,10 +85,5 @@ failed to query registry path (read): %1 - - - failed to set archive key in %1 (errorcode %2) - - From f6961739cb7f1fb90a2c36b9a06a016bd84c2125 Mon Sep 17 00:00:00 2001 From: LostDragonist Date: Sat, 7 Dec 2019 01:28:21 -0700 Subject: [PATCH 0849/1544] [game_falloutnv] Update translations --- src/games/falloutnv/src/game_falloutNV_en.ts | 12 ------------ 1 file changed, 12 deletions(-) diff --git a/src/games/falloutnv/src/game_falloutNV_en.ts b/src/games/falloutnv/src/game_falloutNV_en.ts index 2d26f67a..033df8e1 100644 --- a/src/games/falloutnv/src/game_falloutNV_en.ts +++ b/src/games/falloutnv/src/game_falloutNV_en.ts @@ -60,13 +60,6 @@ QObject - - - - - failed to activate BSA invalidation in "%1" (errorcode %2) - - Some of your plugins have invalid names! These plugins can not be loaded by the game. Please see mo_interface.log for a list of affected plugins and rename them. @@ -92,10 +85,5 @@ failed to query registry path (read): %1 - - - failed to set archive key in %1 (errorcode %2) - - From ff5b1f704820e22a9961dedd7d5b32daf35e60d3 Mon Sep 17 00:00:00 2001 From: LostDragonist Date: Sat, 7 Dec 2019 01:28:22 -0700 Subject: [PATCH 0850/1544] [game_ttw] Update translations --- src/games/ttw/src/game_ttw_en.ts | 12 ------------ 1 file changed, 12 deletions(-) diff --git a/src/games/ttw/src/game_ttw_en.ts b/src/games/ttw/src/game_ttw_en.ts index a86566c6..2beca918 100644 --- a/src/games/ttw/src/game_ttw_en.ts +++ b/src/games/ttw/src/game_ttw_en.ts @@ -60,13 +60,6 @@ QObject - - - - - failed to activate BSA invalidation in "%1" (errorcode %2) - - Some of your plugins have invalid names! These plugins can not be loaded by the game. Please see mo_interface.log for a list of affected plugins and rename them. @@ -92,10 +85,5 @@ failed to query registry path (read): %1 - - - failed to set archive key in %1 (errorcode %2) - - From 4e53af361f7b0ed898e88ac25e3c1ad924258001 Mon Sep 17 00:00:00 2001 From: LostDragonist Date: Sat, 7 Dec 2019 01:45:23 -0700 Subject: [PATCH 0851/1544] [game_fallout4] Update version to 1.4.0.0 --- src/games/fallout4/src/gamefallout4.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/games/fallout4/src/gamefallout4.cpp b/src/games/fallout4/src/gamefallout4.cpp index b98567c3..9aa9d8fa 100644 --- a/src/games/fallout4/src/gamefallout4.cpp +++ b/src/games/fallout4/src/gamefallout4.cpp @@ -84,7 +84,7 @@ QString GameFallout4::description() const MOBase::VersionInfo GameFallout4::version() const { - return VersionInfo(1, 3, 1, VersionInfo::RELEASE_FINAL); + return VersionInfo(1, 4, 0, VersionInfo::RELEASE_FINAL); } bool GameFallout4::isActive() const From 91c3245f20a527ba43d1a98ffe9dd874311194ef Mon Sep 17 00:00:00 2001 From: LostDragonist Date: Sat, 7 Dec 2019 01:45:56 -0700 Subject: [PATCH 0852/1544] [game_fallout4vr] Update version to 1.4.0.0 --- src/games/fallout4vr/src/gamefallout4vr.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/games/fallout4vr/src/gamefallout4vr.cpp b/src/games/fallout4vr/src/gamefallout4vr.cpp index 96ae2a26..46ca1fd6 100644 --- a/src/games/fallout4vr/src/gamefallout4vr.cpp +++ b/src/games/fallout4vr/src/gamefallout4vr.cpp @@ -82,7 +82,7 @@ QString GameFallout4VR::description() const MOBase::VersionInfo GameFallout4VR::version() const { - return VersionInfo(1, 3, 1, VersionInfo::RELEASE_FINAL); + return VersionInfo(1, 4, 0, VersionInfo::RELEASE_FINAL); } bool GameFallout4VR::isActive() const From fe3a699d4cebb0ddd427ad98fabae01de760b440 Mon Sep 17 00:00:00 2001 From: LostDragonist Date: Sat, 7 Dec 2019 01:46:37 -0700 Subject: [PATCH 0853/1544] [game_oblivion] Update version to 1.4.0.0 --- src/games/oblivion/src/gameoblivion.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/games/oblivion/src/gameoblivion.cpp b/src/games/oblivion/src/gameoblivion.cpp index b37f300c..8cffa3f0 100644 --- a/src/games/oblivion/src/gameoblivion.cpp +++ b/src/games/oblivion/src/gameoblivion.cpp @@ -82,7 +82,7 @@ QString GameOblivion::description() const MOBase::VersionInfo GameOblivion::version() const { - return VersionInfo(1, 3, 1, VersionInfo::RELEASE_FINAL); + return VersionInfo(1, 4, 0, VersionInfo::RELEASE_FINAL); } bool GameOblivion::isActive() const From 551747be69a5f41f3f4a3b8876c1bad69d727613 Mon Sep 17 00:00:00 2001 From: LostDragonist Date: Sat, 7 Dec 2019 01:47:17 -0700 Subject: [PATCH 0854/1544] [game_skyrim] Update version to 1.4.0.0 --- src/games/skyrim/src/gameskyrim.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/games/skyrim/src/gameskyrim.cpp b/src/games/skyrim/src/gameskyrim.cpp index 2c14adb3..98003e59 100644 --- a/src/games/skyrim/src/gameskyrim.cpp +++ b/src/games/skyrim/src/gameskyrim.cpp @@ -89,7 +89,7 @@ QString GameSkyrim::description() const MOBase::VersionInfo GameSkyrim::version() const { - return VersionInfo(1, 3, 1, VersionInfo::RELEASE_FINAL); + return VersionInfo(1, 4, 0, VersionInfo::RELEASE_FINAL); } bool GameSkyrim::isActive() const From 0f4e3379d966712b15ab93e374c297dcba7f6ec9 Mon Sep 17 00:00:00 2001 From: LostDragonist Date: Sat, 7 Dec 2019 01:47:50 -0700 Subject: [PATCH 0855/1544] [game_skyrimse] Update version to 1.4.0.0 --- src/games/skyrimse/src/gameskyrimse.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/games/skyrimse/src/gameskyrimse.cpp b/src/games/skyrimse/src/gameskyrimse.cpp index b7188543..52cae4ed 100644 --- a/src/games/skyrimse/src/gameskyrimse.cpp +++ b/src/games/skyrimse/src/gameskyrimse.cpp @@ -123,7 +123,7 @@ QString GameSkyrimSE::description() const MOBase::VersionInfo GameSkyrimSE::version() const { - return VersionInfo(1, 3, 1, VersionInfo::RELEASE_FINAL); + return VersionInfo(1, 4, 0, VersionInfo::RELEASE_FINAL); } bool GameSkyrimSE::isActive() const From cecf1444f2098c88f830636b53285c292030ab79 Mon Sep 17 00:00:00 2001 From: LostDragonist Date: Sat, 7 Dec 2019 01:48:30 -0700 Subject: [PATCH 0856/1544] [game_skyrimvr] Update version to 1.4.0.0 --- src/games/skyrimvr/src/gameskyrimvr.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/games/skyrimvr/src/gameskyrimvr.cpp b/src/games/skyrimvr/src/gameskyrimvr.cpp index 4e867a9f..4d08de60 100644 --- a/src/games/skyrimvr/src/gameskyrimvr.cpp +++ b/src/games/skyrimvr/src/gameskyrimvr.cpp @@ -122,7 +122,7 @@ QString GameSkyrimVR::description() const MOBase::VersionInfo GameSkyrimVR::version() const { - return VersionInfo(1, 3, 1, VersionInfo::RELEASE_FINAL); + return VersionInfo(1, 4, 0, VersionInfo::RELEASE_FINAL); } bool GameSkyrimVR::isActive() const From a441d21e436163f6880a074643c306f3bd0841e2 Mon Sep 17 00:00:00 2001 From: LostDragonist Date: Sat, 7 Dec 2019 01:49:09 -0700 Subject: [PATCH 0857/1544] [game_ttw] Update version to 1.4.0.0 --- src/games/ttw/src/gamefalloutttw.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/games/ttw/src/gamefalloutttw.cpp b/src/games/ttw/src/gamefalloutttw.cpp index d488b3cb..d0a92b89 100644 --- a/src/games/ttw/src/gamefalloutttw.cpp +++ b/src/games/ttw/src/gamefalloutttw.cpp @@ -85,7 +85,7 @@ QString GameFalloutTTW::description() const MOBase::VersionInfo GameFalloutTTW::version() const { - return VersionInfo(1, 3, 1, VersionInfo::RELEASE_FINAL); + return VersionInfo(1, 4, 0, VersionInfo::RELEASE_FINAL); } bool GameFalloutTTW::isActive() const From a3e7c66cf7b3f750de11f79023bfa737e0ea1e7f Mon Sep 17 00:00:00 2001 From: Chris Bessent Date: Thu, 9 Jan 2020 18:12:05 -0700 Subject: [PATCH 0858/1544] Don't delete existing save game path when making a new profile --- src/gamebryo/gamebryolocalsavegames.cpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/gamebryo/gamebryolocalsavegames.cpp b/src/gamebryo/gamebryolocalsavegames.cpp index db4529d0..e390d76d 100644 --- a/src/gamebryo/gamebryolocalsavegames.cpp +++ b/src/gamebryo/gamebryolocalsavegames.cpp @@ -116,7 +116,7 @@ bool GamebryoLocalSavegames::prepareProfile(MOBase::IProfile* profile) dirty = true; } } - else { + else if (dirty) { if (wcscmp(oldPath, L"") != 0) { MOBase::WriteRegistryValue(L"General", L"SLocalSavePath", NULL, @@ -132,7 +132,7 @@ bool GamebryoLocalSavegames::prepareProfile(MOBase::IProfile* profile) dirty = true; } } - else { + else if (dirty) { if (wcscmp(oldMyGames, L"") != 0) { MOBase::WriteRegistryValue(L"General", L"bUseMyGamesDirectory", NULL, From d70b300d0f222b8ace5d37d9942d74395db9d8ba Mon Sep 17 00:00:00 2001 From: Chris Bessent Date: Thu, 9 Jan 2020 18:25:10 -0700 Subject: [PATCH 0859/1544] [game_fallout3] Update version --- src/games/fallout3/src/gamefallout3.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/games/fallout3/src/gamefallout3.cpp b/src/games/fallout3/src/gamefallout3.cpp index ac0adf65..670c62df 100644 --- a/src/games/fallout3/src/gamefallout3.cpp +++ b/src/games/fallout3/src/gamefallout3.cpp @@ -83,7 +83,7 @@ QString GameFallout3::description() const MOBase::VersionInfo GameFallout3::version() const { - return VersionInfo(1, 4, 0, VersionInfo::RELEASE_FINAL); + return VersionInfo(1, 4, 1, VersionInfo::RELEASE_FINAL); } bool GameFallout3::isActive() const From 299192a13db71d0ac4315d55bb5e4de99c5a6675 Mon Sep 17 00:00:00 2001 From: Chris Bessent Date: Thu, 9 Jan 2020 18:25:10 -0700 Subject: [PATCH 0860/1544] [game_fallout4] Update version --- src/games/fallout4/src/gamefallout4.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/games/fallout4/src/gamefallout4.cpp b/src/games/fallout4/src/gamefallout4.cpp index 9aa9d8fa..29e7d20e 100644 --- a/src/games/fallout4/src/gamefallout4.cpp +++ b/src/games/fallout4/src/gamefallout4.cpp @@ -84,7 +84,7 @@ QString GameFallout4::description() const MOBase::VersionInfo GameFallout4::version() const { - return VersionInfo(1, 4, 0, VersionInfo::RELEASE_FINAL); + return VersionInfo(1, 4, 1, VersionInfo::RELEASE_FINAL); } bool GameFallout4::isActive() const From 4f147766d12b95270389d78a1e4013cb793156b6 Mon Sep 17 00:00:00 2001 From: Chris Bessent Date: Thu, 9 Jan 2020 18:25:10 -0700 Subject: [PATCH 0861/1544] [game_fallout4vr] Update version --- src/games/fallout4vr/src/gamefallout4vr.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/games/fallout4vr/src/gamefallout4vr.cpp b/src/games/fallout4vr/src/gamefallout4vr.cpp index 46ca1fd6..9a257fef 100644 --- a/src/games/fallout4vr/src/gamefallout4vr.cpp +++ b/src/games/fallout4vr/src/gamefallout4vr.cpp @@ -82,7 +82,7 @@ QString GameFallout4VR::description() const MOBase::VersionInfo GameFallout4VR::version() const { - return VersionInfo(1, 4, 0, VersionInfo::RELEASE_FINAL); + return VersionInfo(1, 4, 1, VersionInfo::RELEASE_FINAL); } bool GameFallout4VR::isActive() const From b4f7808ad6634037c4c00f91b50cc585f70a9737 Mon Sep 17 00:00:00 2001 From: Chris Bessent Date: Thu, 9 Jan 2020 18:25:10 -0700 Subject: [PATCH 0862/1544] [game_falloutnv] Update version --- src/games/falloutnv/src/gamefalloutnv.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/games/falloutnv/src/gamefalloutnv.cpp b/src/games/falloutnv/src/gamefalloutnv.cpp index b7f03d35..ee22b76c 100644 --- a/src/games/falloutnv/src/gamefalloutnv.cpp +++ b/src/games/falloutnv/src/gamefalloutnv.cpp @@ -83,7 +83,7 @@ QString GameFalloutNV::description() const MOBase::VersionInfo GameFalloutNV::version() const { - return VersionInfo(1, 4, 0, VersionInfo::RELEASE_FINAL); + return VersionInfo(1, 4, 1, VersionInfo::RELEASE_FINAL); } bool GameFalloutNV::isActive() const From dcd4d0969daa30d51b137e8ff409af10a528c885 Mon Sep 17 00:00:00 2001 From: Chris Bessent Date: Thu, 9 Jan 2020 18:25:10 -0700 Subject: [PATCH 0863/1544] [game_oblivion] Update version --- src/games/oblivion/src/gameoblivion.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/games/oblivion/src/gameoblivion.cpp b/src/games/oblivion/src/gameoblivion.cpp index 8cffa3f0..b73a8d7a 100644 --- a/src/games/oblivion/src/gameoblivion.cpp +++ b/src/games/oblivion/src/gameoblivion.cpp @@ -82,7 +82,7 @@ QString GameOblivion::description() const MOBase::VersionInfo GameOblivion::version() const { - return VersionInfo(1, 4, 0, VersionInfo::RELEASE_FINAL); + return VersionInfo(1, 4, 1, VersionInfo::RELEASE_FINAL); } bool GameOblivion::isActive() const From e5e1f71da905809c32619b8cf3954b08bed69c8b Mon Sep 17 00:00:00 2001 From: Chris Bessent Date: Thu, 9 Jan 2020 18:25:10 -0700 Subject: [PATCH 0864/1544] [game_skyrim] Update version --- src/games/skyrim/src/gameskyrim.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/games/skyrim/src/gameskyrim.cpp b/src/games/skyrim/src/gameskyrim.cpp index 98003e59..326d2c97 100644 --- a/src/games/skyrim/src/gameskyrim.cpp +++ b/src/games/skyrim/src/gameskyrim.cpp @@ -89,7 +89,7 @@ QString GameSkyrim::description() const MOBase::VersionInfo GameSkyrim::version() const { - return VersionInfo(1, 4, 0, VersionInfo::RELEASE_FINAL); + return VersionInfo(1, 4, 1, VersionInfo::RELEASE_FINAL); } bool GameSkyrim::isActive() const From 77fbc5b406af51a7596e8c6a9360f0a07c145177 Mon Sep 17 00:00:00 2001 From: Chris Bessent Date: Thu, 9 Jan 2020 18:25:10 -0700 Subject: [PATCH 0865/1544] [game_skyrimse] Update version --- src/games/skyrimse/src/gameskyrimse.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/games/skyrimse/src/gameskyrimse.cpp b/src/games/skyrimse/src/gameskyrimse.cpp index 52cae4ed..1d63c1e0 100644 --- a/src/games/skyrimse/src/gameskyrimse.cpp +++ b/src/games/skyrimse/src/gameskyrimse.cpp @@ -123,7 +123,7 @@ QString GameSkyrimSE::description() const MOBase::VersionInfo GameSkyrimSE::version() const { - return VersionInfo(1, 4, 0, VersionInfo::RELEASE_FINAL); + return VersionInfo(1, 4, 1, VersionInfo::RELEASE_FINAL); } bool GameSkyrimSE::isActive() const From 67f65e8528c5f6386d9d0dffed1ed73de138e008 Mon Sep 17 00:00:00 2001 From: Chris Bessent Date: Thu, 9 Jan 2020 18:25:10 -0700 Subject: [PATCH 0866/1544] [game_skyrimvr] Update version --- src/games/skyrimvr/src/gameskyrimvr.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/games/skyrimvr/src/gameskyrimvr.cpp b/src/games/skyrimvr/src/gameskyrimvr.cpp index 4d08de60..b8aa9652 100644 --- a/src/games/skyrimvr/src/gameskyrimvr.cpp +++ b/src/games/skyrimvr/src/gameskyrimvr.cpp @@ -122,7 +122,7 @@ QString GameSkyrimVR::description() const MOBase::VersionInfo GameSkyrimVR::version() const { - return VersionInfo(1, 4, 0, VersionInfo::RELEASE_FINAL); + return VersionInfo(1, 4, 1, VersionInfo::RELEASE_FINAL); } bool GameSkyrimVR::isActive() const From bcd5a7ebde635377e009aecdf81259c0a3ff6e46 Mon Sep 17 00:00:00 2001 From: Chris Bessent Date: Thu, 9 Jan 2020 18:25:10 -0700 Subject: [PATCH 0867/1544] [game_ttw] Update version --- src/games/ttw/src/gamefalloutttw.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/games/ttw/src/gamefalloutttw.cpp b/src/games/ttw/src/gamefalloutttw.cpp index d0a92b89..17f3449d 100644 --- a/src/games/ttw/src/gamefalloutttw.cpp +++ b/src/games/ttw/src/gamefalloutttw.cpp @@ -85,7 +85,7 @@ QString GameFalloutTTW::description() const MOBase::VersionInfo GameFalloutTTW::version() const { - return VersionInfo(1, 4, 0, VersionInfo::RELEASE_FINAL); + return VersionInfo(1, 4, 1, VersionInfo::RELEASE_FINAL); } bool GameFalloutTTW::isActive() const From 65801a24d9b73e71d49bd42368fb98afcb6c3380 Mon Sep 17 00:00:00 2001 From: isanae <14251494+isanae@users.noreply.github.com> Date: Sun, 16 Feb 2020 18:10:21 -0500 Subject: [PATCH 0868/1544] removed "{} saved" logs optimized readLoadOrderList() --- src/creation/creationgameplugins.cpp | 4 +- src/gamebryo/gamebryogameplugins.cpp | 94 +++++++++++++++++++--------- 2 files changed, 67 insertions(+), 31 deletions(-) diff --git a/src/creation/creationgameplugins.cpp b/src/creation/creationgameplugins.cpp index 1d22e545..138ea3bc 100644 --- a/src/creation/creationgameplugins.cpp +++ b/src/creation/creationgameplugins.cpp @@ -104,9 +104,7 @@ void CreationGamePlugins::writePluginList(const IPluginList *pluginList, "and rename them.")); } - if (file.commitIfDifferent(m_LastSaveHash[filePath])) { - qDebug("%s saved", qUtf8Printable(QDir::toNativeSeparators(filePath))); - } + file.commitIfDifferent(m_LastSaveHash[filePath]); } QStringList CreationGamePlugins::readPluginList(MOBase::IPluginList *pluginList) diff --git a/src/gamebryo/gamebryogameplugins.cpp b/src/gamebryo/gamebryogameplugins.cpp index df6e6338..94a3f5d3 100644 --- a/src/gamebryo/gamebryogameplugins.cpp +++ b/src/gamebryo/gamebryogameplugins.cpp @@ -135,41 +135,80 @@ void GamebryoGamePlugins::writeList(const IPluginList *pluginList, qWarning("plugin list would be empty, this is almost certainly wrong. Not " "saving."); } else { - if (file.commitIfDifferent(m_LastSaveHash[filePath])) { - qDebug("%s saved", qUtf8Printable(QDir::toNativeSeparators(filePath))); - } + file.commitIfDifferent(m_LastSaveHash[filePath]); } } -QStringList GamebryoGamePlugins::readLoadOrderList(MOBase::IPluginList *pluginList, - const QString &filePath) { - QFile file(filePath); - if (!file.open(QIODevice::ReadOnly)) { - return readPluginList(pluginList); - } else { - QStringList pluginNames = organizer()->managedGame()->primaryPlugins(); +QStringList GamebryoGamePlugins::readLoadOrderList( + MOBase::IPluginList *pluginList, const QString &filePath) +{ + HANDLE h = ::CreateFileW( + reinterpret_cast(filePath.utf16()), GENERIC_READ, + FILE_SHARE_READ, nullptr, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, 0); - ON_BLOCK_EXIT([&file]() { file.close(); }); + if (h == INVALID_HANDLE_VALUE) { + return readPluginList(pluginList); + } - if (file.size() == 0) { - return readPluginList(pluginList); - } - while (!file.atEnd()) { - QByteArray line = file.readLine().trimmed(); - QString modName; - if ((line.size() > 0) && (line.at(0) != '#')) { - modName = QString::fromUtf8(line.constData()).toLower(); - } + MOBase::Guard g([&]{ ::CloseHandle(h); }); - if (modName.size() > 0) { - if (!pluginNames.contains(modName, Qt::CaseInsensitive)) { - pluginNames.append(modName); - } - } - } + LARGE_INTEGER fileSize; + if (!GetFileSizeEx(h, &fileSize)) { + return readPluginList(pluginList); + } - return pluginNames; + auto buffer = std::make_unique(fileSize.QuadPart); + DWORD byteCount = static_cast(fileSize.QuadPart); + if (!::ReadFile(h, buffer.get(), byteCount, &byteCount, nullptr)) { + return readPluginList(pluginList); + } + + QStringList pluginNames = organizer()->managedGame()->primaryPlugins(); + + std::set pluginLookup; + for (auto&& name : pluginNames) { + pluginLookup.insert(name.toLower()); + } + + const char* lineStart = buffer.get(); + const char* p = lineStart; + + while (*p) { + // skip all newline characters + while (*p && (*p == '\n' || *p == '\r')) { + ++p; } + + // line starts here + lineStart = p; + + // find end of line + while (*p && *p != '\n' && *p != '\r') { + ++p; + } + + if (p != lineStart && *lineStart != '#') { + // skip whitespace at beginning of line + while (std::isspace(*lineStart)) { + ++lineStart; + } + + // skip white at end of line + const char* lineEnd = p - 1; + while (std::isspace(*lineEnd) && lineEnd > lineStart) { + --lineEnd; + } + ++lineEnd; + + QString s = QString::fromUtf8(lineStart, lineEnd - lineStart).toLower(); + + if (!pluginLookup.contains(s)) { + pluginNames.push_back(std::move(s)); + } + } + } + + return pluginNames; } QStringList GamebryoGamePlugins::readPluginList(MOBase::IPluginList *pluginList) { @@ -211,7 +250,6 @@ QStringList GamebryoGamePlugins::readPluginList(MOBase::IPluginList *pluginList) pluginsTxtExists = false; } ON_BLOCK_EXIT([&]() { - qDebug("close %s", qUtf8Printable(filePath)); file.close(); }); From ee0db5f3a2ea57d34eba29e640405baa926a5017 Mon Sep 17 00:00:00 2001 From: isanae <14251494+isanae@users.noreply.github.com> Date: Sun, 16 Feb 2020 18:44:41 -0500 Subject: [PATCH 0869/1544] moved read file to uibase --- src/gamebryo/gamebryogameplugins.cpp | 65 ++++------------------------ 1 file changed, 9 insertions(+), 56 deletions(-) diff --git a/src/gamebryo/gamebryogameplugins.cpp b/src/gamebryo/gamebryogameplugins.cpp index 94a3f5d3..0e99bdb6 100644 --- a/src/gamebryo/gamebryogameplugins.cpp +++ b/src/gamebryo/gamebryogameplugins.cpp @@ -5,6 +5,7 @@ #include #include #include +#include #include #include @@ -142,70 +143,22 @@ void GamebryoGamePlugins::writeList(const IPluginList *pluginList, QStringList GamebryoGamePlugins::readLoadOrderList( MOBase::IPluginList *pluginList, const QString &filePath) { - HANDLE h = ::CreateFileW( - reinterpret_cast(filePath.utf16()), GENERIC_READ, - FILE_SHARE_READ, nullptr, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, 0); - - if (h == INVALID_HANDLE_VALUE) { - return readPluginList(pluginList); - } - - MOBase::Guard g([&]{ ::CloseHandle(h); }); - - LARGE_INTEGER fileSize; - if (!GetFileSizeEx(h, &fileSize)) { - return readPluginList(pluginList); - } - - auto buffer = std::make_unique(fileSize.QuadPart); - DWORD byteCount = static_cast(fileSize.QuadPart); - if (!::ReadFile(h, buffer.get(), byteCount, &byteCount, nullptr)) { - return readPluginList(pluginList); - } - QStringList pluginNames = organizer()->managedGame()->primaryPlugins(); std::set pluginLookup; for (auto&& name : pluginNames) { - pluginLookup.insert(name.toLower()); + pluginLookup.insert(name); } - const char* lineStart = buffer.get(); - const char* p = lineStart; - - while (*p) { - // skip all newline characters - while (*p && (*p == '\n' || *p == '\r')) { - ++p; + const auto b = MOBase::forEachLineInFile(filePath, [&](QString s) { + if (!pluginLookup.contains(s)) { + pluginLookup.insert(s); + pluginNames.push_back(std::move(s)); } + }); - // line starts here - lineStart = p; - - // find end of line - while (*p && *p != '\n' && *p != '\r') { - ++p; - } - - if (p != lineStart && *lineStart != '#') { - // skip whitespace at beginning of line - while (std::isspace(*lineStart)) { - ++lineStart; - } - - // skip white at end of line - const char* lineEnd = p - 1; - while (std::isspace(*lineEnd) && lineEnd > lineStart) { - --lineEnd; - } - ++lineEnd; - - QString s = QString::fromUtf8(lineStart, lineEnd - lineStart).toLower(); - - if (!pluginLookup.contains(s)) { - pluginNames.push_back(std::move(s)); - } - } + if (!b) { + return readPluginList(pluginList); } return pluginNames; From 4b8c1cd899bea95a99ef6451e23204ab829f9a50 Mon Sep 17 00:00:00 2001 From: isanae <14251494+isanae@users.noreply.github.com> Date: Sun, 16 Feb 2020 18:47:58 -0500 Subject: [PATCH 0870/1544] [game_skyrimse] faster CCPlugins() --- src/games/skyrimse/src/gameskyrimse.cpp | 42 ++++++++++++------------- 1 file changed, 20 insertions(+), 22 deletions(-) diff --git a/src/games/skyrimse/src/gameskyrimse.cpp b/src/games/skyrimse/src/gameskyrimse.cpp index 1d63c1e0..6e575e51 100644 --- a/src/games/skyrimse/src/gameskyrimse.cpp +++ b/src/games/skyrimse/src/gameskyrimse.cpp @@ -10,6 +10,7 @@ #include #include #include "versioninfo.h" +#include #include #include @@ -172,8 +173,15 @@ QString GameSkyrimSE::steamAPPId() const return "489830"; } -QStringList GameSkyrimSE::primaryPlugins() const { - QStringList plugins = { "skyrim.esm", "update.esm", "dawnguard.esm", "hearthfires.esm", "dragonborn.esm" }; +QStringList GameSkyrimSE::primaryPlugins() const +{ + QStringList plugins = { + "skyrim.esm", + "update.esm", + "dawnguard.esm", + "hearthfires.esm", + "dragonborn.esm" + }; plugins.append(CCPlugins()); @@ -212,29 +220,19 @@ QStringList GameSkyrimSE::DLCPlugins() const QStringList GameSkyrimSE::CCPlugins() const { - QStringList plugins = {}; - QFile file(gameDirectory().filePath("Skyrim.ccc")); - if (file.open(QIODevice::ReadOnly)) { - ON_BLOCK_EXIT([&file]() { file.close(); }); + QStringList plugins; + std::set pluginsLookup; - 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(); - } + const QString path = gameDirectory().filePath("Skyrim.ccc"); - if (modName.size() > 0) { - if (!plugins.contains(modName, Qt::CaseInsensitive)) { - plugins.append(modName); - } - } - } + MOBase::forEachLineInFile(path, [&](QString s) { + if (!pluginsLookup.contains(s)) { + pluginsLookup.insert(s); + plugins.append(std::move(s)); } - return plugins; + }); + + return plugins; } IPluginGame::LoadOrderMechanism GameSkyrimSE::loadOrderMechanism() const From 8fc2cb6a86fc8580011c054fcb96a965670b8276 Mon Sep 17 00:00:00 2001 From: Chris Bessent Date: Tue, 10 Mar 2020 20:50:23 -0700 Subject: [PATCH 0871/1544] [game_skyrimse] Use SkyrimCustom.ini for local save games An increasing number of users are using BethINI to put everything in SkyrimCustom.ini instead of Skyrim.ini. This causes local save games to break. This should resolve the issue. --- src/games/skyrimse/src/gameskyrimse.cpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/games/skyrimse/src/gameskyrimse.cpp b/src/games/skyrimse/src/gameskyrimse.cpp index 6e575e51..32bfe578 100644 --- a/src/games/skyrimse/src/gameskyrimse.cpp +++ b/src/games/skyrimse/src/gameskyrimse.cpp @@ -71,7 +71,7 @@ bool GameSkyrimSE::init(IOrganizer *moInfo) registerFeature(new SkyrimSEScriptExtender(this)); registerFeature(new SkyrimSEDataArchives(myGamesPath())); - registerFeature(new GamebryoLocalSavegames(myGamesPath(), "Skyrim.ini")); + registerFeature(new GamebryoLocalSavegames(myGamesPath(), "Skyrimcustom.ini")); registerFeature(new SkyrimSESaveGameInfo(this)); registerFeature(new CreationGamePlugins(moInfo)); registerFeature(new SkyrimSEUnmangedMods(this)); @@ -124,7 +124,7 @@ QString GameSkyrimSE::description() const MOBase::VersionInfo GameSkyrimSE::version() const { - return VersionInfo(1, 4, 1, VersionInfo::RELEASE_FINAL); + return VersionInfo(1, 5, 0, VersionInfo::RELEASE_FINAL); } bool GameSkyrimSE::isActive() const From 3b99e223838ab26c4aca9546d0ddfcee71a4f15a Mon Sep 17 00:00:00 2001 From: Chris Bessent Date: Tue, 10 Mar 2020 21:03:49 -0700 Subject: [PATCH 0872/1544] [game_fallout4] Use Fallout4Custom.ini for local save games An increasing number of users are using BethINI to put everything in Fallout4Custom.ini instead of Fallout4.ini. This causes local save games to break. This should resolve the issue. --- src/games/fallout4/src/gamefallout4.cpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/games/fallout4/src/gamefallout4.cpp b/src/games/fallout4/src/gamefallout4.cpp index 29e7d20e..0777f1d4 100644 --- a/src/games/fallout4/src/gamefallout4.cpp +++ b/src/games/fallout4/src/gamefallout4.cpp @@ -37,7 +37,7 @@ bool GameFallout4::init(IOrganizer *moInfo) registerFeature(new Fallout4ScriptExtender(this)); registerFeature(new Fallout4DataArchives(myGamesPath())); - registerFeature(new GamebryoLocalSavegames(myGamesPath(), "Fallout4.ini")); + registerFeature(new GamebryoLocalSavegames(myGamesPath(), "fallout4custom.ini")); registerFeature(new Fallout4SaveGameInfo(this)); registerFeature(new CreationGamePlugins(moInfo)); registerFeature(new Fallout4UnmangedMods(this)); @@ -84,7 +84,7 @@ QString GameFallout4::description() const MOBase::VersionInfo GameFallout4::version() const { - return VersionInfo(1, 4, 1, VersionInfo::RELEASE_FINAL); + return VersionInfo(1, 5, 0, VersionInfo::RELEASE_FINAL); } bool GameFallout4::isActive() const From a351dd141d612545e306b636480662b9382cc982 Mon Sep 17 00:00:00 2001 From: Chris Bessent Date: Tue, 10 Mar 2020 22:22:40 -0700 Subject: [PATCH 0873/1544] Fix local save games for the "final" time. --- src/gamebryo/gamebryolocalsavegames.cpp | 120 ++++++++++-------------- 1 file changed, 48 insertions(+), 72 deletions(-) diff --git a/src/gamebryo/gamebryolocalsavegames.cpp b/src/gamebryo/gamebryolocalsavegames.cpp index e390d76d..90ad93f1 100644 --- a/src/gamebryo/gamebryolocalsavegames.cpp +++ b/src/gamebryo/gamebryolocalsavegames.cpp @@ -26,7 +26,7 @@ Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA #include -static const QString LocalSavesDummy = "__MO_Saves"; +static const QString LocalSavesDummy = "__MO_Saves\\"; GamebryoLocalSavegames::GamebryoLocalSavegames(const QDir& myGamesDir, @@ -50,7 +50,6 @@ MappingType GamebryoLocalSavegames::mappings(const QDir& profileSaveDir) const bool GamebryoLocalSavegames::prepareProfile(MOBase::IProfile* profile) { - bool dirty = false; bool enable = profile->localSavesEnabled(); QString basePath @@ -58,89 +57,66 @@ bool GamebryoLocalSavegames::prepareProfile(MOBase::IProfile* profile) ? profile->absolutePath() : m_LocalGameDir.absolutePath(); QString iniFilePath = basePath + "/" + m_IniFileName; - QString savepathFilePath = profile->absolutePath() + "/" + "savepath.ini"; + QString saveIni = profile->absolutePath() + "/" + "savepath.ini"; - WCHAR oldPath[MAX_PATH]; - WCHAR oldMyGames[1]; - GetPrivateProfileStringW(L"General", L"SLocalSavePath", NULL, oldPath, MAX_PATH, iniFilePath.toStdWString().c_str()); - GetPrivateProfileStringW(L"General", L"bUseMyGamesDirectory", NULL, oldMyGames, 1, iniFilePath.toStdWString().c_str()); - if (enable && wcscmp(oldPath, L"") != 0 && wcscmp(oldPath, (LocalSavesDummy + "\\").toStdWString().c_str()) != 0) { - dirty = true; - MOBase::WriteRegistryValue(L"General", L"SLocalSavePath", oldPath, savepathFilePath.toStdWString().c_str()); - if (wcscmp(oldMyGames, L"") != 0) { - MOBase::WriteRegistryValue(L"General", L"bUseMyGamesDirectory", oldMyGames, savepathFilePath.toStdWString().c_str()); - } - } - bool saved = false; - bool savedDir = false; - WCHAR savedPath[MAX_PATH]; - WCHAR savedMyGames[1]; - if (!enable) { - if (QFile::exists(savepathFilePath)) { - saved = true; - GetPrivateProfileStringW(L"General", L"SLocalSavePath", NULL, savedPath, MAX_PATH, savepathFilePath.toStdWString().c_str()); - GetPrivateProfileStringW(L"General", L"bUseMyGamesDirectory", NULL, savedMyGames, 1, savepathFilePath.toStdWString().c_str()); - if (wcscmp(savedMyGames, L"") != 0) { - savedDir = true; - } - QFile::remove(savepathFilePath); - } - } - else { + // Get the current sLocalSavePath + WCHAR currentPath[MAX_PATH]; + GetPrivateProfileStringW(L"General", L"sLocalSavePath", L"SKIP_ME", currentPath, MAX_PATH, iniFilePath.toStdWString().c_str()); + bool alreadyEnabled = wcscmp(currentPath, LocalSavesDummy.toStdWString().c_str()) == 0; + + // Get the current bUseMyGamesDirectory + WCHAR currentMyGames[MAX_PATH]; + GetPrivateProfileStringW(L"General", L"bUseMyGamesDirectory", L"SKIP_ME", currentMyGames, MAX_PATH, iniFilePath.toStdWString().c_str()); + + // Create the __MO_Saves directory if local saves are enabled and it doesn't exist + if (enable) { QDir saves = QDir(m_LocalGameDir.absolutePath() + "/" + LocalSavesDummy); if (!saves.exists()) { saves.mkdir("."); } } - if (enable) { - if (wcscmp(oldPath, (LocalSavesDummy + "\\").toStdWString().c_str()) != 0) { - MOBase::WriteRegistryValue(L"General", L"SLocalSavePath", - (LocalSavesDummy + "\\").toStdWString().c_str(), - iniFilePath.toStdWString().c_str()); - dirty = true; + // Set the path to __MO_Saves if it's not already + if (enable && !alreadyEnabled) { + // If the path is not blank, save it to savepath.ini + if (wcscmp(currentPath, L"SKIP_ME") != 0) { + MOBase::WriteRegistryValue(L"General", L"sLocalSavePath", currentPath, saveIni.toStdWString().c_str()); } - if (wcscmp(oldMyGames, L"") != 0) { - MOBase::WriteRegistryValue(L"General", L"bUseMyGamesDirectory", - NULL, - iniFilePath.toStdWString().c_str()); - dirty = true; + if (wcscmp(currentMyGames, L"SKIP_ME") != 0) { + MOBase::WriteRegistryValue(L"General", L"bUseMyGamesDirectory", currentMyGames, saveIni.toStdWString().c_str()); } + MOBase::WriteRegistryValue(L"General", L"sLocalSavePath", LocalSavesDummy.toStdWString().c_str(), iniFilePath.toStdWString().c_str()); + MOBase::WriteRegistryValue(L"General", L"bUseMyGamesDirectory", L"1", iniFilePath.toStdWString().c_str()); } - else { - if (saved) { - if (wcscmp(oldPath, savedPath) != 0) { - MOBase::WriteRegistryValue(L"General", L"SLocalSavePath", - savedPath, - iniFilePath.toStdWString().c_str()); - dirty = true; + + // Get rid of the local saves setting if it's still there + if (!enable && alreadyEnabled) { + // If savepath.ini exists, use it and delete it + if (QFile::exists(saveIni)) { + WCHAR savedPath[MAX_PATH]; + WCHAR savedMyGames[MAX_PATH]; + GetPrivateProfileStringW(L"General", L"sLocalSavePath", L"DELETE_ME", savedPath, MAX_PATH, saveIni.toStdWString().c_str()); + GetPrivateProfileStringW(L"General", L"bUseMyGamesDirectory", L"DELETE_ME", savedMyGames, MAX_PATH, saveIni.toStdWString().c_str()); + if (wcscmp(savedPath, L"DELETE_ME") != 0) { + MOBase::WriteRegistryValue(L"General", L"sLocalSavePath", savedPath, iniFilePath.toStdWString().c_str()); } + else { + MOBase::WriteRegistryValue(L"General", L"sLocalSavePath", NULL, iniFilePath.toStdWString().c_str()); + } + if (wcscmp(savedMyGames, L"DELETE_ME") != 0) { + MOBase::WriteRegistryValue(L"General", L"bUseMyGamesDirectory", savedMyGames, iniFilePath.toStdWString().c_str()); + } + else { + MOBase::WriteRegistryValue(L"General", L"bUseMyGamesDirectory", NULL, iniFilePath.toStdWString().c_str()); + } + QFile::remove(saveIni); } - else if (dirty) { - if (wcscmp(oldPath, L"") != 0) { - MOBase::WriteRegistryValue(L"General", L"SLocalSavePath", - NULL, - iniFilePath.toStdWString().c_str()); - dirty = true; - } - } - if (savedDir) { - if (wcscmp(oldMyGames, savedMyGames) != 0) { - MOBase::WriteRegistryValue(L"General", L"bUseMyGamesDirectory", - savedMyGames, - iniFilePath.toStdWString().c_str()); - dirty = true; - } - } - else if (dirty) { - if (wcscmp(oldMyGames, L"") != 0) { - MOBase::WriteRegistryValue(L"General", L"bUseMyGamesDirectory", - NULL, - iniFilePath.toStdWString().c_str()); - dirty = true; - } + // Otherwise just delete the setting + else { + MOBase::WriteRegistryValue(L"General", L"sLocalSavePath", NULL, iniFilePath.toStdWString().c_str()); + MOBase::WriteRegistryValue(L"General", L"bUseMyGamesDirectory", NULL, iniFilePath.toStdWString().c_str()); } } - return dirty; + return enable != alreadyEnabled; } From 1342facc1407dc8978040880b68e6600837fa779 Mon Sep 17 00:00:00 2001 From: isanae <14251494+isanae@users.noreply.github.com> Date: Fri, 24 Apr 2020 22:15:13 -0400 Subject: [PATCH 0874/1544] [game_fallout3] now using new cmakefiles --- src/games/fallout3/CMakeLists.txt | 19 +++---- src/games/fallout3/src/CMakeLists.txt | 77 ++------------------------- 2 files changed, 9 insertions(+), 87 deletions(-) diff --git a/src/games/fallout3/CMakeLists.txt b/src/games/fallout3/CMakeLists.txt index a6f19354..b241c568 100644 --- a/src/games/fallout3/CMakeLists.txt +++ b/src/games/fallout3/CMakeLists.txt @@ -1,15 +1,8 @@ -CMAKE_MINIMUM_REQUIRED(VERSION 2.8.12) +cmake_minimum_required(VERSION 3.16) -ADD_COMPILE_OPTIONS($<$:/MP> $<$:$<$:/O2>> $<$:$<$:/O2>>) +project(game_fallout3) +set(project_type plugin) +set(enable_warnings OFF) -SET(PROJ_NAME game_fallout3) - -PROJECT(${PROJ_NAME}) - -SET(DEPENDENCIES_DIR CACHE PATH "") - -# hint to find qt in dependencies path -LIST(APPEND CMAKE_PREFIX_PATH ${QT_ROOT}/lib/cmake) -LIST(APPEND CMAKE_PREFIX_PATH ${LZ4_ROOT}/dll) - -ADD_SUBDIRECTORY(src) +include(../cmake_common/project.cmake) +add_subdirectory(src) diff --git a/src/games/fallout3/src/CMakeLists.txt b/src/games/fallout3/src/CMakeLists.txt index 4c3f4d45..1a3a3af2 100644 --- a/src/games/fallout3/src/CMakeLists.txt +++ b/src/games/fallout3/src/CMakeLists.txt @@ -1,75 +1,4 @@ -CMAKE_MINIMUM_REQUIRED (VERSION 2.8.11) +cmake_minimum_required(VERSION 3.16) +include(../../cmake_common/src.cmake) -CMAKE_POLICY(SET CMP0020 NEW) - -FILE(GLOB ${PROJ_NAME}_SRCS *.cpp) -FILE(GLOB ${PROJ_NAME}_HDRS *.h) -FILE(GLOB ${PROJ_NAME}_FORMS *.ui) - - -SET(CMAKE_INCLUDE_CURRENT_DIR ON) -SET(CMAKE_AUTOMOC ON) -SET(CMAKE_AUTOUIC ON) -FIND_PACKAGE(Qt5Widgets REQUIRED) -QT5_WRAP_UI(${PROJ_NAME}_UIHDRS ${${PROJ_NAME}_FORMS}) - -SET(default_project_path "${DEPENDENCIES_DIR}/modorganizer_super") -GET_FILENAME_COMPONENT(${default_project_path} ${default_project_path} REALPATH) - -SET(project_path "${default_project_path}" CACHE PATH "path to the other mo projects") - -FIND_PACKAGE(Qt5LinguistTools) -SET(translation_sources ${CMAKE_SOURCE_DIR}/src ${project_path}/game_gamebryo/src/gamebryo) -QT5_CREATE_TRANSLATION(${PROJ_NAME}_translations_qm ${translation_sources} ${CMAKE_SOURCE_DIR}/src/${PROJ_NAME}_en.ts) - -SET(Boost_USE_STATIC_LIBS ON) -SET(Boost_USE_MULTITHREADED ON) -SET(Boost_USE_STATIC_RUNTIME OFF) -FIND_PACKAGE(Boost) - -IF (Boost_FOUND) - INCLUDE_DIRECTORIES(${Boost_INCLUDE_DIRS}) -ENDIF () - -SET(lib_path "${project_path}/../../install/libs") - -INCLUDE_DIRECTORIES(${project_path}/uibase/src - ${project_path}/game_features/src - ${project_path}/game_gamebryo/src/gamebryo) -LINK_DIRECTORIES(${project_path}/uibase/build/src - ${lib_path} - ${LZ4_ROOT}/bin) - - -ADD_LIBRARY(${PROJ_NAME} SHARED ${${PROJ_NAME}_HDRS} ${${PROJ_NAME}_SRCS} ${${PROJ_NAME}_UIHDRS} ${${PROJ_NAME}_translations_qm}) -TARGET_LINK_LIBRARIES(${PROJ_NAME} - Qt5::Widgets - ${Boost_LIBRARIES} - DbgHelp - uibase - game_gamebryo - liblz4 - Version) - -IF (MSVC) - SET_TARGET_PROPERTIES(${PROJ_NAME} PROPERTIES COMPILE_FLAGS "/std:c++latest") -ENDIF() -IF (MSVC AND CMAKE_SIZEOF_VOID_P EQUAL 4) - # 32 bits - SET_TARGET_PROPERTIES(${PROJ_NAME} PROPERTIES LINK_FLAGS "/LARGEADDRESSAWARE") -ENDIF() - -IF (NOT "${OPTIMIZE_COMPILE_FLAGS}" STREQUAL "") - SET_TARGET_PROPERTIES(${PROJ_NAME} PROPERTIES COMPILE_FLAGS_RELWITHDEBINFO ${OPTIMIZE_COMPILE_FLAGS}) -ENDIF() -IF (NOT "${OPTIMIZE_LINK_FLAGS}" STREQUAL "") - SET_TARGET_PROPERTIES(${PROJ_NAME} PROPERTIES LINK_FLAGS_RELWITHDEBINFO ${OPTIMIZE_LINK_FLAGS}) -ENDIF() - -############### -## Installation - -INSTALL(TARGETS ${PROJ_NAME} - RUNTIME DESTINATION bin/plugins) -INSTALL(FILES $ - DESTINATION pdb) +requires_project(game_features game_gamebryo) From 2ee5f0caa099b89dcdc39808096273bab11715f6 Mon Sep 17 00:00:00 2001 From: isanae <14251494+isanae@users.noreply.github.com> Date: Fri, 24 Apr 2020 22:22:58 -0400 Subject: [PATCH 0875/1544] [game_fallout4] now using new cmakefiles --- src/games/fallout4/CMakeLists.txt | 19 ++---- src/games/fallout4/src/CMakeLists.txt | 84 +-------------------------- 2 files changed, 9 insertions(+), 94 deletions(-) diff --git a/src/games/fallout4/CMakeLists.txt b/src/games/fallout4/CMakeLists.txt index cab5836e..f7ef8b24 100644 --- a/src/games/fallout4/CMakeLists.txt +++ b/src/games/fallout4/CMakeLists.txt @@ -1,15 +1,8 @@ -CMAKE_MINIMUM_REQUIRED(VERSION 2.8.12) +cmake_minimum_required(VERSION 3.16) -ADD_COMPILE_OPTIONS($<$:/MP> $<$:$<$:/O2>> $<$:$<$:/O2>>) +project(game_fallout4) +set(project_type plugin) +set(enable_warnings OFF) -SET(PROJ_NAME game_fallout4) - -PROJECT(${PROJ_NAME}) - -SET(DEPENDENCIES_DIR CACHE PATH "") - -# hint to find qt in dependencies path -LIST(APPEND CMAKE_PREFIX_PATH ${QT_ROOT}/lib/cmake) -LIST(APPEND CMAKE_PREFIX_PATH ${LZ4_ROOT}/dll) - -ADD_SUBDIRECTORY(src) +include(../cmake_common/project.cmake) +add_subdirectory(src) diff --git a/src/games/fallout4/src/CMakeLists.txt b/src/games/fallout4/src/CMakeLists.txt index 79f44159..1a3a3af2 100644 --- a/src/games/fallout4/src/CMakeLists.txt +++ b/src/games/fallout4/src/CMakeLists.txt @@ -1,82 +1,4 @@ -CMAKE_MINIMUM_REQUIRED (VERSION 2.8.11) +cmake_minimum_required(VERSION 3.16) +include(../../cmake_common/src.cmake) -CMAKE_POLICY(SET CMP0020 NEW) - -FILE(GLOB ${PROJ_NAME}_SRCS *.cpp) -FILE(GLOB ${PROJ_NAME}_HDRS *.h) -FILE(GLOB ${PROJ_NAME}_FORMS *.ui) - -SET(${PROJ_NAME}_QRCS - fallout4.qrc - ) - -SET(CMAKE_INCLUDE_CURRENT_DIR ON) -SET(CMAKE_AUTOMOC ON) -SET(CMAKE_AUTOUIC ON) -FIND_PACKAGE(Qt5Widgets REQUIRED) -QT5_WRAP_UI(${PROJ_NAME}_UIHDRS ${${PROJ_NAME}_FORMS}) -QT5_ADD_RESOURCES(${PROJ_NAME}_RCCPPS ${${PROJ_NAME}_QRCS}) - -SET(default_project_path "${DEPENDENCIES_DIR}/modorganizer_super") -GET_FILENAME_COMPONENT(${default_project_path} ${default_project_path} REALPATH) - -SET(project_path "${default_project_path}" CACHE PATH "path to the other mo projects") - -FIND_PACKAGE(Qt5LinguistTools) -SET(translation_sources ${CMAKE_SOURCE_DIR}/src ${project_path}/game_gamebryo/src/gamebryo ${project_path}/game_gamebryo/src/creation) -QT5_CREATE_TRANSLATION(${PROJ_NAME}_translations_qm ${translation_sources} ${CMAKE_SOURCE_DIR}/src/${PROJ_NAME}_en.ts) - -SET(Boost_USE_STATIC_LIBS ON) -SET(Boost_USE_MULTITHREADED ON) -SET(Boost_USE_STATIC_RUNTIME OFF) -FIND_PACKAGE(Boost) - -IF (Boost_FOUND) - INCLUDE_DIRECTORIES(${Boost_INCLUDE_DIRS}) -ENDIF () - -SET(lib_path "${project_path}/../../install/libs") - -INCLUDE_DIRECTORIES(${project_path}/uibase/src - ${project_path}/game_features/src - ${project_path}/game_gamebryo/src/gamebryo - ${project_path}/game_gamebryo/src/creation) -LINK_DIRECTORIES(${project_path}/uibase/build/src - ${lib_path} - ${LZ4_ROOT}/bin) - - -ADD_LIBRARY(${PROJ_NAME} SHARED ${${PROJ_NAME}_HDRS} ${${PROJ_NAME}_SRCS} ${${PROJ_NAME}_UIHDRS} ${${PROJ_NAME}_RCCPPS} ${${PROJ_NAME}_translations_qm}) -TARGET_LINK_LIBRARIES(${PROJ_NAME} - Qt5::Widgets - ${Boost_LIBRARIES} - DbgHelp - uibase - Version - liblz4 - game_gamebryo - game_creation) - -IF (MSVC) - SET_TARGET_PROPERTIES(${PROJ_NAME} PROPERTIES COMPILE_FLAGS "/std:c++latest") -ENDIF() -IF (MSVC AND CMAKE_SIZEOF_VOID_P EQUAL 4) - # 32 bits - SET_TARGET_PROPERTIES(${PROJ_NAME} PROPERTIES LINK_FLAGS "/LARGEADDRESSAWARE") -ENDIF() - -IF (NOT "${OPTIMIZE_COMPILE_FLAGS}" STREQUAL "") - SET_TARGET_PROPERTIES(${PROJ_NAME} PROPERTIES COMPILE_FLAGS_RELWITHDEBINFO ${OPTIMIZE_COMPILE_FLAGS}) -ENDIF() -IF (NOT "${OPTIMIZE_LINK_FLAGS}" STREQUAL "") - SET_TARGET_PROPERTIES(${PROJ_NAME} PROPERTIES LINK_FLAGS_RELWITHDEBINFO ${OPTIMIZE_LINK_FLAGS}) -ENDIF() - - -############### -## Installation - -INSTALL(TARGETS ${PROJ_NAME} - RUNTIME DESTINATION bin/plugins) -INSTALL(FILES $ - DESTINATION pdb) +requires_project(game_features game_gamebryo) From fbeae138a12cbf1526444c1b0fe0fcf2536e0822 Mon Sep 17 00:00:00 2001 From: isanae <14251494+isanae@users.noreply.github.com> Date: Fri, 24 Apr 2020 22:24:58 -0400 Subject: [PATCH 0876/1544] [game_fallout4vr] now using new cmakefiles --- src/games/fallout4vr/CMakeLists.txt | 19 ++---- src/games/fallout4vr/src/CMakeLists.txt | 84 +------------------------ 2 files changed, 9 insertions(+), 94 deletions(-) diff --git a/src/games/fallout4vr/CMakeLists.txt b/src/games/fallout4vr/CMakeLists.txt index d61a4016..073d9efb 100644 --- a/src/games/fallout4vr/CMakeLists.txt +++ b/src/games/fallout4vr/CMakeLists.txt @@ -1,15 +1,8 @@ -CMAKE_MINIMUM_REQUIRED(VERSION 2.8.12) +cmake_minimum_required(VERSION 3.16) -ADD_COMPILE_OPTIONS($<$:/MP> $<$:$<$:/O2>> $<$:$<$:/O2>>) +project(game_fallout4vr) +set(project_type plugin) +set(enable_warnings OFF) -SET(PROJ_NAME game_fallout4vr) - -PROJECT(${PROJ_NAME}) - -SET(DEPENDENCIES_DIR CACHE PATH "") - -# hint to find qt in dependencies path -LIST(APPEND CMAKE_PREFIX_PATH ${QT_ROOT}/lib/cmake) -LIST(APPEND CMAKE_PREFIX_PATH ${LZ4_ROOT}/dll) - -ADD_SUBDIRECTORY(src) +include(../cmake_common/project.cmake) +add_subdirectory(src) diff --git a/src/games/fallout4vr/src/CMakeLists.txt b/src/games/fallout4vr/src/CMakeLists.txt index 59e9f9d1..1a3a3af2 100644 --- a/src/games/fallout4vr/src/CMakeLists.txt +++ b/src/games/fallout4vr/src/CMakeLists.txt @@ -1,82 +1,4 @@ -CMAKE_MINIMUM_REQUIRED (VERSION 2.8.11) +cmake_minimum_required(VERSION 3.16) +include(../../cmake_common/src.cmake) -CMAKE_POLICY(SET CMP0020 NEW) - -FILE(GLOB ${PROJ_NAME}_SRCS *.cpp) -FILE(GLOB ${PROJ_NAME}_HDRS *.h) -FILE(GLOB ${PROJ_NAME}_FORMS *.ui) - -SET(${PROJ_NAME}_QRCS - fallout4vr.qrc - ) - -SET(CMAKE_INCLUDE_CURRENT_DIR ON) -SET(CMAKE_AUTOMOC ON) -SET(CMAKE_AUTOUIC ON) -FIND_PACKAGE(Qt5Widgets REQUIRED) -QT5_WRAP_UI(${PROJ_NAME}_UIHDRS ${${PROJ_NAME}_FORMS}) -QT5_ADD_RESOURCES(${PROJ_NAME}_RCCPPS ${${PROJ_NAME}_QRCS}) - -SET(default_project_path "${DEPENDENCIES_DIR}/modorganizer_super") -GET_FILENAME_COMPONENT(${default_project_path} ${default_project_path} REALPATH) - -SET(project_path "${default_project_path}" CACHE PATH "path to the other mo projects") - -FIND_PACKAGE(Qt5LinguistTools) -SET(translation_sources ${CMAKE_SOURCE_DIR}/src ${project_path}/game_gamebryo/src/gamebryo ${project_path}/game_gamebryo/src/creation) -QT5_CREATE_TRANSLATION(${PROJ_NAME}_translations_qm ${translation_sources} ${CMAKE_SOURCE_DIR}/src/${PROJ_NAME}_en.ts) - -SET(Boost_USE_STATIC_LIBS ON) -SET(Boost_USE_MULTITHREADED ON) -SET(Boost_USE_STATIC_RUNTIME OFF) -FIND_PACKAGE(Boost) - -IF (Boost_FOUND) - INCLUDE_DIRECTORIES(${Boost_INCLUDE_DIRS}) -ENDIF () - -SET(lib_path "${project_path}/../../install/libs") - -INCLUDE_DIRECTORIES(${project_path}/uibase/src - ${project_path}/game_features/src - ${project_path}/game_gamebryo/src/gamebryo - ${project_path}/game_gamebryo/src/creation) -LINK_DIRECTORIES(${project_path}/uibase/build/src - ${lib_path} - ${LZ4_ROOT}/bin) - - -ADD_LIBRARY(${PROJ_NAME} SHARED ${${PROJ_NAME}_HDRS} ${${PROJ_NAME}_SRCS} ${${PROJ_NAME}_UIHDRS} ${${PROJ_NAME}_RCCPPS} ${${PROJ_NAME}_translations_qm}) -TARGET_LINK_LIBRARIES(${PROJ_NAME} - Qt5::Widgets - ${Boost_LIBRARIES} - DbgHelp - uibase - Version - liblz4 - game_gamebryo - game_creation) - -IF (MSVC) - SET_TARGET_PROPERTIES(${PROJ_NAME} PROPERTIES COMPILE_FLAGS "/std:c++latest") -ENDIF() -IF (MSVC AND CMAKE_SIZEOF_VOID_P EQUAL 4) - # 32 bits - SET_TARGET_PROPERTIES(${PROJ_NAME} PROPERTIES LINK_FLAGS "/LARGEADDRESSAWARE") -ENDIF() - -IF (NOT "${OPTIMIZE_COMPILE_FLAGS}" STREQUAL "") - SET_TARGET_PROPERTIES(${PROJ_NAME} PROPERTIES COMPILE_FLAGS_RELWITHDEBINFO ${OPTIMIZE_COMPILE_FLAGS}) -ENDIF() -IF (NOT "${OPTIMIZE_LINK_FLAGS}" STREQUAL "") - SET_TARGET_PROPERTIES(${PROJ_NAME} PROPERTIES LINK_FLAGS_RELWITHDEBINFO ${OPTIMIZE_LINK_FLAGS}) -ENDIF() - - -############### -## Installation - -INSTALL(TARGETS ${PROJ_NAME} - RUNTIME DESTINATION bin/plugins) -INSTALL(FILES $ - DESTINATION pdb) +requires_project(game_features game_gamebryo) From 975d1865eb3b42b3f5af511d81c16e9d228171ed Mon Sep 17 00:00:00 2001 From: isanae <14251494+isanae@users.noreply.github.com> Date: Fri, 24 Apr 2020 22:26:53 -0400 Subject: [PATCH 0877/1544] [game_falloutnv] now using new cmakefiles --- src/games/falloutnv/CMakeLists.txt | 20 ++----- src/games/falloutnv/src/CMakeLists.txt | 77 +------------------------- 2 files changed, 9 insertions(+), 88 deletions(-) diff --git a/src/games/falloutnv/CMakeLists.txt b/src/games/falloutnv/CMakeLists.txt index 39dd6e76..cd1f4b23 100644 --- a/src/games/falloutnv/CMakeLists.txt +++ b/src/games/falloutnv/CMakeLists.txt @@ -1,16 +1,8 @@ -CMAKE_MINIMUM_REQUIRED(VERSION 2.8.12) +cmake_minimum_required(VERSION 3.16) -ADD_COMPILE_OPTIONS($<$:/MP> $<$:$<$:/O2>> $<$:$<$:/O2>>) +project(game_falloutNV) +set(project_type plugin) +set(enable_warnings OFF) -SET(PROJ_NAME game_falloutNV) - -PROJECT(${PROJ_NAME}) - -SET(DEPENDENCIES_DIR CACHE PATH "") - -# hint to find qt in dependencies path -LIST(APPEND CMAKE_PREFIX_PATH ${QT_ROOT}/lib/cmake) - -LIST(APPEND CMAKE_PREFIX_PATH ${LZ4_ROOT}/dll) - -ADD_SUBDIRECTORY(src) +include(../cmake_common/project.cmake) +add_subdirectory(src) diff --git a/src/games/falloutnv/src/CMakeLists.txt b/src/games/falloutnv/src/CMakeLists.txt index 4c3f4d45..1a3a3af2 100644 --- a/src/games/falloutnv/src/CMakeLists.txt +++ b/src/games/falloutnv/src/CMakeLists.txt @@ -1,75 +1,4 @@ -CMAKE_MINIMUM_REQUIRED (VERSION 2.8.11) +cmake_minimum_required(VERSION 3.16) +include(../../cmake_common/src.cmake) -CMAKE_POLICY(SET CMP0020 NEW) - -FILE(GLOB ${PROJ_NAME}_SRCS *.cpp) -FILE(GLOB ${PROJ_NAME}_HDRS *.h) -FILE(GLOB ${PROJ_NAME}_FORMS *.ui) - - -SET(CMAKE_INCLUDE_CURRENT_DIR ON) -SET(CMAKE_AUTOMOC ON) -SET(CMAKE_AUTOUIC ON) -FIND_PACKAGE(Qt5Widgets REQUIRED) -QT5_WRAP_UI(${PROJ_NAME}_UIHDRS ${${PROJ_NAME}_FORMS}) - -SET(default_project_path "${DEPENDENCIES_DIR}/modorganizer_super") -GET_FILENAME_COMPONENT(${default_project_path} ${default_project_path} REALPATH) - -SET(project_path "${default_project_path}" CACHE PATH "path to the other mo projects") - -FIND_PACKAGE(Qt5LinguistTools) -SET(translation_sources ${CMAKE_SOURCE_DIR}/src ${project_path}/game_gamebryo/src/gamebryo) -QT5_CREATE_TRANSLATION(${PROJ_NAME}_translations_qm ${translation_sources} ${CMAKE_SOURCE_DIR}/src/${PROJ_NAME}_en.ts) - -SET(Boost_USE_STATIC_LIBS ON) -SET(Boost_USE_MULTITHREADED ON) -SET(Boost_USE_STATIC_RUNTIME OFF) -FIND_PACKAGE(Boost) - -IF (Boost_FOUND) - INCLUDE_DIRECTORIES(${Boost_INCLUDE_DIRS}) -ENDIF () - -SET(lib_path "${project_path}/../../install/libs") - -INCLUDE_DIRECTORIES(${project_path}/uibase/src - ${project_path}/game_features/src - ${project_path}/game_gamebryo/src/gamebryo) -LINK_DIRECTORIES(${project_path}/uibase/build/src - ${lib_path} - ${LZ4_ROOT}/bin) - - -ADD_LIBRARY(${PROJ_NAME} SHARED ${${PROJ_NAME}_HDRS} ${${PROJ_NAME}_SRCS} ${${PROJ_NAME}_UIHDRS} ${${PROJ_NAME}_translations_qm}) -TARGET_LINK_LIBRARIES(${PROJ_NAME} - Qt5::Widgets - ${Boost_LIBRARIES} - DbgHelp - uibase - game_gamebryo - liblz4 - Version) - -IF (MSVC) - SET_TARGET_PROPERTIES(${PROJ_NAME} PROPERTIES COMPILE_FLAGS "/std:c++latest") -ENDIF() -IF (MSVC AND CMAKE_SIZEOF_VOID_P EQUAL 4) - # 32 bits - SET_TARGET_PROPERTIES(${PROJ_NAME} PROPERTIES LINK_FLAGS "/LARGEADDRESSAWARE") -ENDIF() - -IF (NOT "${OPTIMIZE_COMPILE_FLAGS}" STREQUAL "") - SET_TARGET_PROPERTIES(${PROJ_NAME} PROPERTIES COMPILE_FLAGS_RELWITHDEBINFO ${OPTIMIZE_COMPILE_FLAGS}) -ENDIF() -IF (NOT "${OPTIMIZE_LINK_FLAGS}" STREQUAL "") - SET_TARGET_PROPERTIES(${PROJ_NAME} PROPERTIES LINK_FLAGS_RELWITHDEBINFO ${OPTIMIZE_LINK_FLAGS}) -ENDIF() - -############### -## Installation - -INSTALL(TARGETS ${PROJ_NAME} - RUNTIME DESTINATION bin/plugins) -INSTALL(FILES $ - DESTINATION pdb) +requires_project(game_features game_gamebryo) From c11ae927d1a47cf9399256b78b88cd584f2f0e76 Mon Sep 17 00:00:00 2001 From: isanae <14251494+isanae@users.noreply.github.com> Date: Fri, 24 Apr 2020 22:58:17 -0400 Subject: [PATCH 0878/1544] now using new cmakefiles --- CMakeLists.txt | 24 ++++-------- src/creation/CMakeLists.txt | 74 ++++--------------------------------- 2 files changed, 15 insertions(+), 83 deletions(-) diff --git a/CMakeLists.txt b/CMakeLists.txt index a9a4a8e7..79a95210 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -1,19 +1,11 @@ -CMAKE_MINIMUM_REQUIRED(VERSION 2.8.12) +cmake_minimum_required(VERSION 3.16) -ADD_COMPILE_OPTIONS( - $<$:/MP> - $<$:$<$:/O2>> - $<$:$<$:/O2>>) +project(game_gamebryo) +set(project_type lib) +set(enable_warnings OFF) -SET(PROJ_NAME game_gamebryo) -PROJECT(${PROJ_NAME}) +include(../cmake_common/project.cmake) +add_subdirectory(src/gamebryo) -set(CMAKE_VS_INCLUDE_INSTALL_TO_DEFAULT_BUILD 1) -SET(DEPENDENCIES_DIR CACHE PATH "") - -# hint to find qt in dependencies path -LIST(APPEND CMAKE_PREFIX_PATH ${QT_ROOT}/lib/cmake) -LIST(APPEND CMAKE_PREFIX_PATH ${LZ4_ROOT}/dll) - -ADD_SUBDIRECTORY(src/gamebryo) -ADD_SUBDIRECTORY(src/creation) +# note that this also creates a project +add_subdirectory(src/creation) diff --git a/src/creation/CMakeLists.txt b/src/creation/CMakeLists.txt index f046fb3f..29a68a33 100644 --- a/src/creation/CMakeLists.txt +++ b/src/creation/CMakeLists.txt @@ -1,70 +1,10 @@ -CMAKE_MINIMUM_REQUIRED (VERSION 2.8.11) +cmake_minimum_required(VERSION 3.16) -CMAKE_POLICY(SET CMP0020 NEW) +project(game_creation) +set(project_type lib) +set(enable_warnings OFF) -SET(PROJ_NAME game_creation) -PROJECT(${PROJ_NAME}) +include(../../../cmake_common/project.cmake) +include(../../../cmake_common/src.cmake) -FILE(GLOB ${PROJ_NAME}_SRCS *.cpp) -FILE(GLOB ${PROJ_NAME}_HDRS *.h) -FILE(GLOB ${PROJ_NAME}_FORMS *.ui) - -SET(CMAKE_INCLUDE_CURRENT_DIR ON) -SET(CMAKE_AUTOMOC ON) -SET(CMAKE_AUTOUIC ON) -FIND_PACKAGE(Qt5Widgets REQUIRED) -QT5_WRAP_UI(${PROJ_NAME}_UIHDRS ${${PROJ_NAME}_FORMS}) - -SET(Boost_USE_STATIC_LIBS ON) -SET(Boost_USE_MULTITHREADED ON) -SET(Boost_USE_STATIC_RUNTIME OFF) -FIND_PACKAGE(Boost) - -IF (Boost_FOUND) - INCLUDE_DIRECTORIES(${Boost_INCLUDE_DIRS}) -ENDIF (Boost_FOUND) - -SET(default_project_path "${DEPENDENCIES_DIR}/modorganizer_super") -GET_FILENAME_COMPONENT(${default_project_path} ${default_project_path} REALPATH) - -SET(project_path "${default_project_path}" CACHE PATH "path to the other mo projects") -SET(lib_path "${project_path}/../../install/libs") -SET(plugin_path "${project_path}") - - -INCLUDE_DIRECTORIES(../gamebryo - ${project_path}/uibase/src - ${project_path}/game_features/src - ${LZ4_ROOT}/lib) -LINK_DIRECTORIES(${lib_path} - ${LZ4_ROOT}/bin) - -ADD_LIBRARY(${PROJ_NAME} STATIC ${${PROJ_NAME}_HDRS} ${${PROJ_NAME}_SRCS} ${${PROJ_NAME}_UIHDRS}) -TARGET_LINK_LIBRARIES(${PROJ_NAME} - Qt5::Widgets - ${Boost_LIBRARIES} - uibase - liblz4 - Version - game_gamebryo) - -IF (MSVC) - SET_TARGET_PROPERTIES(${PROJ_NAME} PROPERTIES COMPILE_FLAGS "/std:c++latest") -ENDIF() -IF (MSVC AND CMAKE_SIZEOF_VOID_P EQUAL 4) - # 32 bits - SET_TARGET_PROPERTIES(${PROJ_NAME} PROPERTIES LINK_FLAGS "/LARGEADDRESSAWARE") -ENDIF() - -IF (NOT "${OPTIMIZE_COMPILE_FLAGS}" STREQUAL "") - SET_TARGET_PROPERTIES(${PROJ_NAME} PROPERTIES COMPILE_FLAGS_RELWITHDEBINFO ${OPTIMIZE_COMPILE_FLAGS}) -ENDIF() -IF (NOT "${OPTIMIZE_LINK_FLAGS}" STREQUAL "") - SET_TARGET_PROPERTIES(${PROJ_NAME} PROPERTIES LINK_FLAGS_RELWITHDEBINFO ${OPTIMIZE_LINK_FLAGS}) -ENDIF() - -############### -## Installation - -INSTALL(TARGETS ${PROJ_NAME} - ARCHIVE DESTINATION libs) +requires_project(game_gamebryo game_features) From c3f6695d8dba31569ecd8dbbe44114da9c82cc7e Mon Sep 17 00:00:00 2001 From: isanae <14251494+isanae@users.noreply.github.com> Date: Fri, 24 Apr 2020 22:58:35 -0400 Subject: [PATCH 0879/1544] now using new cmakefiles --- src/gamebryo/CMakeLists.txt | 68 ++----------------------------------- 1 file changed, 3 insertions(+), 65 deletions(-) diff --git a/src/gamebryo/CMakeLists.txt b/src/gamebryo/CMakeLists.txt index f01a69d4..00203ddb 100644 --- a/src/gamebryo/CMakeLists.txt +++ b/src/gamebryo/CMakeLists.txt @@ -1,66 +1,4 @@ -CMAKE_MINIMUM_REQUIRED (VERSION 2.8.11) +cmake_minimum_required(VERSION 3.16) +include(../../../cmake_common/src.cmake) -CMAKE_POLICY(SET CMP0020 NEW) - -FILE(GLOB ${PROJ_NAME}_SRCS *.cpp) -FILE(GLOB ${PROJ_NAME}_HDRS *.h) -FILE(GLOB ${PROJ_NAME}_FORMS *.ui) - -SET(CMAKE_INCLUDE_CURRENT_DIR ON) -SET(CMAKE_AUTOMOC ON) -SET(CMAKE_AUTOUIC ON) -FIND_PACKAGE(Qt5Widgets REQUIRED) -QT5_WRAP_UI(${PROJ_NAME}_UIHDRS ${${PROJ_NAME}_FORMS}) - -SET(Boost_USE_STATIC_LIBS ON) -SET(Boost_USE_MULTITHREADED ON) -SET(Boost_USE_STATIC_RUNTIME OFF) -FIND_PACKAGE(Boost) - -IF (Boost_FOUND) - INCLUDE_DIRECTORIES(${Boost_INCLUDE_DIRS}) -ENDIF (Boost_FOUND) - -SET(default_project_path "${DEPENDENCIES_DIR}/modorganizer_super") -GET_FILENAME_COMPONENT(${default_project_path} ${default_project_path} REALPATH) - -SET(project_path "${default_project_path}" CACHE PATH "path to the other mo projects") -SET(lib_path "${project_path}/../../install/libs") -SET(plugin_path "${project_path}") - - -INCLUDE_DIRECTORIES(${project_path}/uibase/src - ${project_path}/game_features/src - ${LZ4_ROOT}/lib) - -LINK_DIRECTORIES(${lib_path} - ${LZ4_ROOT}/bin) - -ADD_LIBRARY(${PROJ_NAME} STATIC ${${PROJ_NAME}_HDRS} ${${PROJ_NAME}_SRCS} ${${PROJ_NAME}_UIHDRS}) -TARGET_LINK_LIBRARIES(${PROJ_NAME} - Qt5::Widgets - ${Boost_LIBRARIES} - uibase - liblz4 - Version) - -IF (MSVC) - SET_TARGET_PROPERTIES(${PROJ_NAME} PROPERTIES COMPILE_FLAGS "/std:c++latest") -ENDIF() -IF (MSVC AND CMAKE_SIZEOF_VOID_P EQUAL 4) - # 32 bits - SET_TARGET_PROPERTIES(${PROJ_NAME} PROPERTIES LINK_FLAGS "/LARGEADDRESSAWARE") -ENDIF() - -IF (NOT "${OPTIMIZE_COMPILE_FLAGS}" STREQUAL "") - SET_TARGET_PROPERTIES(${PROJ_NAME} PROPERTIES COMPILE_FLAGS_RELWITHDEBINFO ${OPTIMIZE_COMPILE_FLAGS}) -ENDIF() -IF (NOT "${OPTIMIZE_LINK_FLAGS}" STREQUAL "") - SET_TARGET_PROPERTIES(${PROJ_NAME} PROPERTIES LINK_FLAGS_RELWITHDEBINFO ${OPTIMIZE_LINK_FLAGS}) -ENDIF() - -############### -## Installation - -INSTALL(TARGETS ${PROJ_NAME} - ARCHIVE DESTINATION libs) +requires_project(game_features) From 0b5e73400a796b80507b14b5dbd2320983f2dfaf Mon Sep 17 00:00:00 2001 From: isanae <14251494+isanae@users.noreply.github.com> Date: Fri, 24 Apr 2020 22:58:55 -0400 Subject: [PATCH 0880/1544] fixes for unicode --- src/gamebryo/gamegamebryo.cpp | 21 +++++++++++++-------- 1 file changed, 13 insertions(+), 8 deletions(-) diff --git a/src/gamebryo/gamegamebryo.cpp b/src/gamebryo/gamegamebryo.cpp index c5ad673b..35199ac2 100644 --- a/src/gamebryo/gamegamebryo.cpp +++ b/src/gamebryo/gamegamebryo.cpp @@ -162,25 +162,30 @@ WORD GameGamebryo::getArch(QString const &program) const { WORD arch = 0; //This *really* needs to be factored out - LPCSTR app_name = ("\\\\?\\" + - QDir::toNativeSeparators(this->gameDirectory().absoluteFilePath(program)).toStdString()).c_str(); + std::wstring app_name = + L"\\\\?\\" + QDir::toNativeSeparators(this->gameDirectory().absoluteFilePath(program)).toStdWString(); - WIN32_FIND_DATA FindFileData; - HANDLE hFind = ::FindFirstFile(app_name, &FindFileData); + WIN32_FIND_DATAW FindFileData; + HANDLE hFind = ::FindFirstFileW(app_name.c_str(), &FindFileData); //exit if the binary was not found if (hFind == INVALID_HANDLE_VALUE) return arch; - HANDLE hFile = CreateFile(app_name, GENERIC_READ, FILE_SHARE_READ, NULL, OPEN_EXISTING, FILE_ATTRIBUTE_READONLY, NULL); + HANDLE hFile = INVALID_HANDLE_VALUE; + HANDLE hMapping = INVALID_HANDLE_VALUE; + LPVOID addrHeader = nullptr; + PIMAGE_NT_HEADERS peHdr = nullptr; + + hFile = CreateFileW(app_name.c_str(), GENERIC_READ, FILE_SHARE_READ, NULL, OPEN_EXISTING, FILE_ATTRIBUTE_READONLY, NULL); if (hFile == INVALID_HANDLE_VALUE) goto cleanup; - HANDLE hMapping = CreateFileMapping(hFile, NULL, PAGE_READONLY | SEC_IMAGE, 0, 0, program.toStdString().c_str()); + hMapping = CreateFileMappingW(hFile, NULL, PAGE_READONLY | SEC_IMAGE, 0, 0, program.toStdWString().c_str()); if (hMapping == INVALID_HANDLE_VALUE) goto cleanup; - LPVOID addrHeader = MapViewOfFile(hMapping, FILE_MAP_READ, 0, 0, 0); + addrHeader = MapViewOfFile(hMapping, FILE_MAP_READ, 0, 0, 0); if (addrHeader == NULL) goto cleanup; //couldn't memory map the file - PIMAGE_NT_HEADERS peHdr = ImageNtHeader(addrHeader); + peHdr = ImageNtHeader(addrHeader); if (peHdr == NULL) goto cleanup; //couldn't read the header arch = peHdr->FileHeader.Machine; From cd48ef2d685e5cfc2eca6e924744d534235dd9c9 Mon Sep 17 00:00:00 2001 From: isanae <14251494+isanae@users.noreply.github.com> Date: Fri, 24 Apr 2020 23:01:07 -0400 Subject: [PATCH 0881/1544] [game_morrowind] now using new cmakefiles --- src/games/morrowind/CMakeLists.txt | 19 ++---- src/games/morrowind/src/CMakeLists.txt | 83 +------------------------- 2 files changed, 9 insertions(+), 93 deletions(-) diff --git a/src/games/morrowind/CMakeLists.txt b/src/games/morrowind/CMakeLists.txt index 0a591eef..2cd216fe 100644 --- a/src/games/morrowind/CMakeLists.txt +++ b/src/games/morrowind/CMakeLists.txt @@ -1,15 +1,8 @@ -CMAKE_MINIMUM_REQUIRED(VERSION 2.8.12) +cmake_minimum_required(VERSION 3.16) -ADD_COMPILE_OPTIONS($<$:/MP> $<$:$<$:/O2>> $<$:$<$:/O2>>) +project(game_morrowind) +set(project_type plugin) +set(enable_warnings OFF) -SET(PROJ_NAME game_morrowind) - -PROJECT(${PROJ_NAME}) - -SET(DEPENDENCIES_DIR CACHE PATH "") - -# hint to find qt in dependencies path -LIST(APPEND CMAKE_PREFIX_PATH ${QT_ROOT}/lib/cmake) -LIST(APPEND CMAKE_PREFIX_PATH ${LZ4_ROOT}/dll) - -ADD_SUBDIRECTORY(src) +include(../cmake_common/project.cmake) +add_subdirectory(src) diff --git a/src/games/morrowind/src/CMakeLists.txt b/src/games/morrowind/src/CMakeLists.txt index 46ad05b3..de337c03 100644 --- a/src/games/morrowind/src/CMakeLists.txt +++ b/src/games/morrowind/src/CMakeLists.txt @@ -1,81 +1,4 @@ -CMAKE_MINIMUM_REQUIRED (VERSION 1.8) +cmake_minimum_required(VERSION 3.16) +include(../../cmake_common/src.cmake) -CMAKE_POLICY(SET CMP0020 NEW) - -FILE(GLOB ${PROJ_NAME}_SRCS *.cpp) -FILE(GLOB ${PROJ_NAME}_HDRS *.h) -FILE(GLOB ${PROJ_NAME}_FORMS *.ui) - -SET(${PROJ_NAME}_QRCS - morrowind.qrc - ) - -SET(CMAKE_INCLUDE_CURRENT_DIR ON) -SET(CMAKE_AUTOMOC ON) -SET(CMAKE_AUTOUIC ON) -FIND_PACKAGE(Qt5Widgets REQUIRED) -QT5_WRAP_UI(${PROJ_NAME}_UIHDRS ${${PROJ_NAME}_FORMS}) -QT5_ADD_RESOURCES(${PROJ_NAME}_RCCPPS ${${PROJ_NAME}_QRCS}) - -SET(default_project_path "${DEPENDENCIES_DIR}/modorganizer_super") -GET_FILENAME_COMPONENT(${default_project_path} ${default_project_path} REALPATH) - -SET(project_path "${default_project_path}" CACHE PATH "path to the other mo projects") - -FIND_PACKAGE(Qt5LinguistTools) -SET(translation_sources ${CMAKE_SOURCE_DIR}/src ${project_path}/game_gamebryo/src/gamebryo) -QT5_CREATE_TRANSLATION(${PROJ_NAME}_translations_qm ${translation_sources} ${CMAKE_SOURCE_DIR}/src/${PROJ_NAME}_en.ts) - -SET(Boost_USE_STATIC_LIBS ON) -SET(Boost_USE_MULTITHREADED ON) -SET(Boost_USE_STATIC_RUNTIME OFF) -FIND_PACKAGE(Boost) - -IF (Boost_FOUND) - INCLUDE_DIRECTORIES(${Boost_INCLUDE_DIRS}) -ENDIF () - -SET(lib_path "${project_path}/../../install/libs") - -INCLUDE_DIRECTORIES(${project_path}/uibase/src - ${project_path}/game_features/src - ${project_path}/game_gamebryo/src/gamebryo) -LINK_DIRECTORIES(${project_path}/uibase/build/src - ${lib_path} - ${LZ4_ROOT}/bin) - -ADD_DEFINITIONS(-DUNICODE -D_UNICODE) - -ADD_LIBRARY(${PROJ_NAME} SHARED ${${PROJ_NAME}_HDRS} ${${PROJ_NAME}_SRCS} ${${PROJ_NAME}_UIHDRS} ${${PROJ_NAME}_RCCPPS} ${${PROJ_NAME}_translations_qm}) -TARGET_LINK_LIBRARIES(${PROJ_NAME} - Qt5::Widgets - ${Boost_LIBRARIES} - DbgHelp - uibase - game_gamebryo - liblz4 - version) - -IF (MSVC) - SET_TARGET_PROPERTIES(${PROJ_NAME} PROPERTIES COMPILE_FLAGS "/std:c++latest") -ENDIF() -IF (MSVC AND CMAKE_SIZEOF_VOID_P EQUAL 4) - # 32 bits - SET_TARGET_PROPERTIES(${PROJ_NAME} PROPERTIES LINK_FLAGS "/LARGEADDRESSAWARE") -ENDIF() - -IF (NOT "${OPTIMIZE_COMPILE_FLAGS}" STREQUAL "") - SET_TARGET_PROPERTIES(${PROJ_NAME} PROPERTIES COMPILE_FLAGS_RELWITHDEBINFO ${OPTIMIZE_COMPILE_FLAGS}) -ENDIF() -IF (NOT "${OPTIMIZE_LINK_FLAGS}" STREQUAL "") - SET_TARGET_PROPERTIES(${PROJ_NAME} PROPERTIES LINK_FLAGS_RELWITHDEBINFO ${OPTIMIZE_LINK_FLAGS}) -ENDIF() - - -############### -## Installation - -INSTALL(TARGETS ${PROJ_NAME} - RUNTIME DESTINATION bin/plugins) -INSTALL(FILES $ - DESTINATION pdb) +requires_project(game_gamebryo game_features) From 27d9154127c74b1a6e4918a097a0fc2a0b45f3c6 Mon Sep 17 00:00:00 2001 From: isanae <14251494+isanae@users.noreply.github.com> Date: Fri, 24 Apr 2020 23:02:32 -0400 Subject: [PATCH 0882/1544] [game_oblivion] now using new cmakefiles --- src/games/oblivion/CMakeLists.txt | 19 +++---- src/games/oblivion/src/CMakeLists.txt | 78 ++------------------------- 2 files changed, 9 insertions(+), 88 deletions(-) diff --git a/src/games/oblivion/CMakeLists.txt b/src/games/oblivion/CMakeLists.txt index 9e30f4cc..ba1d0771 100644 --- a/src/games/oblivion/CMakeLists.txt +++ b/src/games/oblivion/CMakeLists.txt @@ -1,15 +1,8 @@ -CMAKE_MINIMUM_REQUIRED(VERSION 2.8.12) +cmake_minimum_required(VERSION 3.16) -ADD_COMPILE_OPTIONS($<$:/MP> $<$:$<$:/O2>> $<$:$<$:/O2>>) +project(game_oblivion) +set(project_type plugin) +set(enable_warnings OFF) -SET(PROJ_NAME game_oblivion) - -PROJECT(${PROJ_NAME}) - -SET(DEPENDENCIES_DIR CACHE PATH "") - -# hint to find qt in dependencies path -LIST(APPEND CMAKE_PREFIX_PATH ${QT_ROOT}/lib/cmake) -LIST(APPEND CMAKE_PREFIX_PATH ${LZ4_ROOT}/dll) - -ADD_SUBDIRECTORY(src) +include(../cmake_common/project.cmake) +add_subdirectory(src) diff --git a/src/games/oblivion/src/CMakeLists.txt b/src/games/oblivion/src/CMakeLists.txt index 5d15b3bc..de337c03 100644 --- a/src/games/oblivion/src/CMakeLists.txt +++ b/src/games/oblivion/src/CMakeLists.txt @@ -1,76 +1,4 @@ -CMAKE_MINIMUM_REQUIRED (VERSION 2.8.11) +cmake_minimum_required(VERSION 3.16) +include(../../cmake_common/src.cmake) -CMAKE_POLICY(SET CMP0020 NEW) - -FILE(GLOB ${PROJ_NAME}_SRCS *.cpp) -FILE(GLOB ${PROJ_NAME}_HDRS *.h) -FILE(GLOB ${PROJ_NAME}_FORMS *.ui) - - -SET(CMAKE_INCLUDE_CURRENT_DIR ON) -SET(CMAKE_AUTOMOC ON) -SET(CMAKE_AUTOUIC ON) -FIND_PACKAGE(Qt5Widgets REQUIRED) -QT5_WRAP_UI(${PROJ_NAME}_UIHDRS ${${PROJ_NAME}_FORMS}) - -# MO projects -SET(default_project_path "${DEPENDENCIES_DIR}/modorganizer_super") -GET_FILENAME_COMPONENT(${default_project_path} ${default_project_path} REALPATH) - -SET(project_path "${default_project_path}" CACHE PATH "path to the other mo projects") - -FIND_PACKAGE(Qt5LinguistTools) -SET(translation_sources ${CMAKE_SOURCE_DIR}/src ${project_path}/game_gamebryo/src/gamebryo) -QT5_CREATE_TRANSLATION(${PROJ_NAME}_translations_qm ${translation_sources} ${CMAKE_SOURCE_DIR}/src/${PROJ_NAME}_en.ts) - -SET(Boost_USE_STATIC_LIBS ON) -SET(Boost_USE_MULTITHREADED ON) -SET(Boost_USE_STATIC_RUNTIME OFF) -FIND_PACKAGE(Boost) - -IF (Boost_FOUND) - INCLUDE_DIRECTORIES(${Boost_INCLUDE_DIRS}) -ENDIF () - -SET(lib_path "${project_path}/../../install/libs") - -INCLUDE_DIRECTORIES(${project_path}/uibase/src - ${project_path}/game_features/src - ${project_path}/game_gamebryo/src/gamebryo) -LINK_DIRECTORIES(${project_path}/uibase/build/src - ${lib_path} - ${LZ4_ROOT}/bin) - - -ADD_LIBRARY(${PROJ_NAME} SHARED ${${PROJ_NAME}_HDRS} ${${PROJ_NAME}_SRCS} ${${PROJ_NAME}_UIHDRS} ${${PROJ_NAME}_translations_qm}) -TARGET_LINK_LIBRARIES(${PROJ_NAME} - Qt5::Widgets - ${Boost_LIBRARIES} - DbgHelp - uibase - game_gamebryo - liblz4 - version) - -IF (MSVC) - SET_TARGET_PROPERTIES(${PROJ_NAME} PROPERTIES COMPILE_FLAGS "/std:c++latest") -ENDIF() -IF (MSVC AND CMAKE_SIZEOF_VOID_P EQUAL 4) - # 32 bits - SET_TARGET_PROPERTIES(${PROJ_NAME} PROPERTIES LINK_FLAGS "/LARGEADDRESSAWARE") -ENDIF() - -IF (NOT "${OPTIMIZE_COMPILE_FLAGS}" STREQUAL "") - SET_TARGET_PROPERTIES(${PROJ_NAME} PROPERTIES COMPILE_FLAGS_RELWITHDEBINFO ${OPTIMIZE_COMPILE_FLAGS}) -ENDIF() -IF (NOT "${OPTIMIZE_LINK_FLAGS}" STREQUAL "") - SET_TARGET_PROPERTIES(${PROJ_NAME} PROPERTIES LINK_FLAGS_RELWITHDEBINFO ${OPTIMIZE_LINK_FLAGS}) -ENDIF() - -############### -## Installation - -INSTALL(TARGETS ${PROJ_NAME} - RUNTIME DESTINATION bin/plugins) -INSTALL(FILES $ - DESTINATION pdb) +requires_project(game_gamebryo game_features) From fbaebd28c675277af775c499579f4c2315570acf Mon Sep 17 00:00:00 2001 From: isanae <14251494+isanae@users.noreply.github.com> Date: Fri, 24 Apr 2020 23:03:53 -0400 Subject: [PATCH 0883/1544] [game_skyrim] now using new cmakefiles --- src/games/skyrim/CMakeLists.txt | 19 +++---- src/games/skyrim/src/CMakeLists.txt | 78 ++--------------------------- 2 files changed, 9 insertions(+), 88 deletions(-) diff --git a/src/games/skyrim/CMakeLists.txt b/src/games/skyrim/CMakeLists.txt index a8aa9fb9..a66154e8 100644 --- a/src/games/skyrim/CMakeLists.txt +++ b/src/games/skyrim/CMakeLists.txt @@ -1,15 +1,8 @@ -CMAKE_MINIMUM_REQUIRED(VERSION 2.8.12) +cmake_minimum_required(VERSION 3.16) -ADD_COMPILE_OPTIONS($<$:/MP> $<$:$<$:/O2>> $<$:$<$:/O2>>) +project(game_skyrim) +set(project_type plugin) +set(enable_warnings OFF) -SET(PROJ_NAME game_skyrim) - -PROJECT(${PROJ_NAME}) - -SET(DEPENDENCIES_DIR CACHE PATH "") - -# hint to find qt in dependencies path -LIST(APPEND CMAKE_PREFIX_PATH ${QT_ROOT}/lib/cmake) -LIST(APPEND CMAKE_PREFIX_PATH ${LZ4_ROOT}/dll) - -ADD_SUBDIRECTORY(src) +include(../cmake_common/project.cmake) +add_subdirectory(src) diff --git a/src/games/skyrim/src/CMakeLists.txt b/src/games/skyrim/src/CMakeLists.txt index b2916ad6..de337c03 100644 --- a/src/games/skyrim/src/CMakeLists.txt +++ b/src/games/skyrim/src/CMakeLists.txt @@ -1,76 +1,4 @@ -CMAKE_MINIMUM_REQUIRED (VERSION 1.8) +cmake_minimum_required(VERSION 3.16) +include(../../cmake_common/src.cmake) -CMAKE_POLICY(SET CMP0020 NEW) - -FILE(GLOB ${PROJ_NAME}_SRCS *.cpp) -FILE(GLOB ${PROJ_NAME}_HDRS *.h) -FILE(GLOB ${PROJ_NAME}_FORMS *.ui) - - -SET(CMAKE_INCLUDE_CURRENT_DIR ON) -SET(CMAKE_AUTOMOC ON) -SET(CMAKE_AUTOUIC ON) -FIND_PACKAGE(Qt5Widgets REQUIRED) -QT5_WRAP_UI(${PROJ_NAME}_UIHDRS ${${PROJ_NAME}_FORMS}) - -SET(default_project_path "${DEPENDENCIES_DIR}/modorganizer_super") -GET_FILENAME_COMPONENT(${default_project_path} ${default_project_path} REALPATH) - -SET(project_path "${default_project_path}" CACHE PATH "path to the other mo projects") - -FIND_PACKAGE(Qt5LinguistTools) -SET(translation_sources ${CMAKE_SOURCE_DIR}/src ${project_path}/game_gamebryo/src/gamebryo) -QT5_CREATE_TRANSLATION(${PROJ_NAME}_translations_qm ${translation_sources} ${CMAKE_SOURCE_DIR}/src/${PROJ_NAME}_en.ts) - -SET(Boost_USE_STATIC_LIBS ON) -SET(Boost_USE_MULTITHREADED ON) -SET(Boost_USE_STATIC_RUNTIME OFF) -FIND_PACKAGE(Boost) - -IF (Boost_FOUND) - INCLUDE_DIRECTORIES(${Boost_INCLUDE_DIRS}) -ENDIF () - -SET(lib_path "${project_path}/../../install/libs") - -INCLUDE_DIRECTORIES(${project_path}/uibase/src - ${project_path}/game_features/src - ${project_path}/game_gamebryo/src/gamebryo) -LINK_DIRECTORIES(${project_path}/uibase/build/src - ${lib_path} - ${LZ4_ROOT}/bin) - -ADD_DEFINITIONS(-DUNICODE -D_UNICODE) - -ADD_LIBRARY(${PROJ_NAME} SHARED ${${PROJ_NAME}_HDRS} ${${PROJ_NAME}_SRCS} ${${PROJ_NAME}_UIHDRS} ${${PROJ_NAME}_translations_qm}) -TARGET_LINK_LIBRARIES(${PROJ_NAME} - Qt5::Widgets - ${Boost_LIBRARIES} - DbgHelp - uibase - game_gamebryo - liblz4 - version) - -IF (MSVC) - SET_TARGET_PROPERTIES(${PROJ_NAME} PROPERTIES COMPILE_FLAGS "/std:c++latest") -ENDIF() -IF (MSVC AND CMAKE_SIZEOF_VOID_P EQUAL 4) - # 32 bits - SET_TARGET_PROPERTIES(${PROJ_NAME} PROPERTIES LINK_FLAGS "/LARGEADDRESSAWARE") -ENDIF() - -IF (NOT "${OPTIMIZE_COMPILE_FLAGS}" STREQUAL "") - SET_TARGET_PROPERTIES(${PROJ_NAME} PROPERTIES COMPILE_FLAGS_RELWITHDEBINFO ${OPTIMIZE_COMPILE_FLAGS}) -ENDIF() -IF (NOT "${OPTIMIZE_LINK_FLAGS}" STREQUAL "") - SET_TARGET_PROPERTIES(${PROJ_NAME} PROPERTIES LINK_FLAGS_RELWITHDEBINFO ${OPTIMIZE_LINK_FLAGS}) -ENDIF() - -############### -## Installation - -INSTALL(TARGETS ${PROJ_NAME} - RUNTIME DESTINATION bin/plugins) -INSTALL(FILES $ - DESTINATION pdb) +requires_project(game_gamebryo game_features) From 67eccf185837ff9e34a664eba877fe3befa90191 Mon Sep 17 00:00:00 2001 From: isanae <14251494+isanae@users.noreply.github.com> Date: Fri, 24 Apr 2020 23:05:18 -0400 Subject: [PATCH 0884/1544] [game_skyrimse] now using new cmakefiles --- src/games/skyrimse/CMakeLists.txt | 19 ++----- src/games/skyrimse/src/CMakeLists.txt | 80 +-------------------------- 2 files changed, 9 insertions(+), 90 deletions(-) diff --git a/src/games/skyrimse/CMakeLists.txt b/src/games/skyrimse/CMakeLists.txt index 3e0ea718..cb8d90ee 100644 --- a/src/games/skyrimse/CMakeLists.txt +++ b/src/games/skyrimse/CMakeLists.txt @@ -1,15 +1,8 @@ -CMAKE_MINIMUM_REQUIRED(VERSION 2.8.12) +cmake_minimum_required(VERSION 3.16) -ADD_COMPILE_OPTIONS($<$:/MP> $<$:$<$:/O2>> $<$:$<$:/O2>>) +project(game_skyrimse) +set(project_type plugin) +set(enable_warnings OFF) -SET(PROJ_NAME game_skyrimse) - -PROJECT(${PROJ_NAME}) - -SET(DEPENDENCIES_DIR CACHE PATH "") - -# hint to find qt in dependencies path -LIST(APPEND CMAKE_PREFIX_PATH ${QT_ROOT}/lib/cmake) -LIST(APPEND CMAKE_PREFIX_PATH ${LZ4_ROOT}/dll) - -ADD_SUBDIRECTORY(src) +include(../cmake_common/project.cmake) +add_subdirectory(src) diff --git a/src/games/skyrimse/src/CMakeLists.txt b/src/games/skyrimse/src/CMakeLists.txt index 9145cb06..de337c03 100644 --- a/src/games/skyrimse/src/CMakeLists.txt +++ b/src/games/skyrimse/src/CMakeLists.txt @@ -1,78 +1,4 @@ -CMAKE_MINIMUM_REQUIRED (VERSION 2.8.11) +cmake_minimum_required(VERSION 3.16) +include(../../cmake_common/src.cmake) -CMAKE_POLICY(SET CMP0020 NEW) - -FILE(GLOB ${PROJ_NAME}_SRCS *.cpp) -FILE(GLOB ${PROJ_NAME}_HDRS *.h) -FILE(GLOB ${PROJ_NAME}_FORMS *.ui) - - -SET(CMAKE_INCLUDE_CURRENT_DIR ON) -SET(CMAKE_AUTOMOC ON) -SET(CMAKE_AUTOUIC ON) -FIND_PACKAGE(Qt5Widgets REQUIRED) -QT5_WRAP_UI(${PROJ_NAME}_UIHDRS ${${PROJ_NAME}_FORMS}) - -SET(default_project_path "${DEPENDENCIES_DIR}/modorganizer_super") -GET_FILENAME_COMPONENT(${default_project_path} ${default_project_path} REALPATH) - -SET(project_path "${default_project_path}" CACHE PATH "path to the other mo projects") - -FIND_PACKAGE(Qt5LinguistTools) -SET(translation_sources ${CMAKE_SOURCE_DIR}/src ${project_path}/game_gamebryo/src/gamebryo ${project_path}/game_gamebryo/src/creation) -QT5_CREATE_TRANSLATION(${PROJ_NAME}_translations_qm ${translation_sources} ${CMAKE_SOURCE_DIR}/src/${PROJ_NAME}_en.ts) - -SET(Boost_USE_STATIC_LIBS ON) -SET(Boost_USE_MULTITHREADED ON) -SET(Boost_USE_STATIC_RUNTIME OFF) -FIND_PACKAGE(Boost) - -IF (Boost_FOUND) - INCLUDE_DIRECTORIES(${Boost_INCLUDE_DIRS}) -ENDIF () - -SET(lib_path "${project_path}/../../install/libs") - -INCLUDE_DIRECTORIES(${project_path}/uibase/src - ${project_path}/game_features/src - ${project_path}/game_gamebryo/src/gamebryo - ${project_path}/game_gamebryo/src/creation) -LINK_DIRECTORIES(${project_path}/uibase/build/src - ${lib_path} - ${LZ4_ROOT}/bin) - -ADD_DEFINITIONS(-DUNICODE -D_UNICODE) - -ADD_LIBRARY(${PROJ_NAME} SHARED ${${PROJ_NAME}_HDRS} ${${PROJ_NAME}_SRCS} ${${PROJ_NAME}_UIHDRS} ${${PROJ_NAME}_translations_qm}) -TARGET_LINK_LIBRARIES(${PROJ_NAME} - Qt5::Widgets - ${Boost_LIBRARIES} - DbgHelp - uibase - game_gamebryo - game_creation - liblz4 - version) - -IF (MSVC) - SET_TARGET_PROPERTIES(${PROJ_NAME} PROPERTIES COMPILE_FLAGS "/std:c++latest") -ENDIF() -IF (MSVC AND CMAKE_SIZEOF_VOID_P EQUAL 4) - # 32 bits - SET_TARGET_PROPERTIES(${PROJ_NAME} PROPERTIES LINK_FLAGS "/LARGEADDRESSAWARE") -ENDIF() - -IF (NOT "${OPTIMIZE_COMPILE_FLAGS}" STREQUAL "") - SET_TARGET_PROPERTIES(${PROJ_NAME} PROPERTIES COMPILE_FLAGS_RELWITHDEBINFO ${OPTIMIZE_COMPILE_FLAGS}) -ENDIF() -IF (NOT "${OPTIMIZE_LINK_FLAGS}" STREQUAL "") - SET_TARGET_PROPERTIES(${PROJ_NAME} PROPERTIES LINK_FLAGS_RELWITHDEBINFO ${OPTIMIZE_LINK_FLAGS}) -ENDIF() - -############### -## Installation - -INSTALL(TARGETS ${PROJ_NAME} - RUNTIME DESTINATION bin/plugins) -INSTALL(FILES $ - DESTINATION pdb) +requires_project(game_gamebryo game_features) From 53101a92f3aaae4a86ab5de19e6cb2803977c7e9 Mon Sep 17 00:00:00 2001 From: isanae <14251494+isanae@users.noreply.github.com> Date: Fri, 24 Apr 2020 23:06:38 -0400 Subject: [PATCH 0885/1544] [game_skyrimvr] now using new cmakefiles --- src/games/skyrimvr/CMakeLists.txt | 19 ++----- src/games/skyrimvr/src/CMakeLists.txt | 80 +-------------------------- 2 files changed, 9 insertions(+), 90 deletions(-) diff --git a/src/games/skyrimvr/CMakeLists.txt b/src/games/skyrimvr/CMakeLists.txt index 52a4323d..5e7ef7c4 100644 --- a/src/games/skyrimvr/CMakeLists.txt +++ b/src/games/skyrimvr/CMakeLists.txt @@ -1,15 +1,8 @@ -CMAKE_MINIMUM_REQUIRED(VERSION 2.8.12) +cmake_minimum_required(VERSION 3.16) -ADD_COMPILE_OPTIONS($<$:/MP> $<$:$<$:/O2>> $<$:$<$:/O2>>) +project(game_skyrimvr) +set(project_type plugin) +set(enable_warnings OFF) -SET(PROJ_NAME game_skyrimvr) - -PROJECT(${PROJ_NAME}) - -SET(DEPENDENCIES_DIR CACHE PATH "") - -# hint to find qt in dependencies path -LIST(APPEND CMAKE_PREFIX_PATH ${QT_ROOT}/lib/cmake) -LIST(APPEND CMAKE_PREFIX_PATH ${LZ4_ROOT}/dll) - -ADD_SUBDIRECTORY(src) +include(../cmake_common/project.cmake) +add_subdirectory(src) diff --git a/src/games/skyrimvr/src/CMakeLists.txt b/src/games/skyrimvr/src/CMakeLists.txt index 9145cb06..de337c03 100644 --- a/src/games/skyrimvr/src/CMakeLists.txt +++ b/src/games/skyrimvr/src/CMakeLists.txt @@ -1,78 +1,4 @@ -CMAKE_MINIMUM_REQUIRED (VERSION 2.8.11) +cmake_minimum_required(VERSION 3.16) +include(../../cmake_common/src.cmake) -CMAKE_POLICY(SET CMP0020 NEW) - -FILE(GLOB ${PROJ_NAME}_SRCS *.cpp) -FILE(GLOB ${PROJ_NAME}_HDRS *.h) -FILE(GLOB ${PROJ_NAME}_FORMS *.ui) - - -SET(CMAKE_INCLUDE_CURRENT_DIR ON) -SET(CMAKE_AUTOMOC ON) -SET(CMAKE_AUTOUIC ON) -FIND_PACKAGE(Qt5Widgets REQUIRED) -QT5_WRAP_UI(${PROJ_NAME}_UIHDRS ${${PROJ_NAME}_FORMS}) - -SET(default_project_path "${DEPENDENCIES_DIR}/modorganizer_super") -GET_FILENAME_COMPONENT(${default_project_path} ${default_project_path} REALPATH) - -SET(project_path "${default_project_path}" CACHE PATH "path to the other mo projects") - -FIND_PACKAGE(Qt5LinguistTools) -SET(translation_sources ${CMAKE_SOURCE_DIR}/src ${project_path}/game_gamebryo/src/gamebryo ${project_path}/game_gamebryo/src/creation) -QT5_CREATE_TRANSLATION(${PROJ_NAME}_translations_qm ${translation_sources} ${CMAKE_SOURCE_DIR}/src/${PROJ_NAME}_en.ts) - -SET(Boost_USE_STATIC_LIBS ON) -SET(Boost_USE_MULTITHREADED ON) -SET(Boost_USE_STATIC_RUNTIME OFF) -FIND_PACKAGE(Boost) - -IF (Boost_FOUND) - INCLUDE_DIRECTORIES(${Boost_INCLUDE_DIRS}) -ENDIF () - -SET(lib_path "${project_path}/../../install/libs") - -INCLUDE_DIRECTORIES(${project_path}/uibase/src - ${project_path}/game_features/src - ${project_path}/game_gamebryo/src/gamebryo - ${project_path}/game_gamebryo/src/creation) -LINK_DIRECTORIES(${project_path}/uibase/build/src - ${lib_path} - ${LZ4_ROOT}/bin) - -ADD_DEFINITIONS(-DUNICODE -D_UNICODE) - -ADD_LIBRARY(${PROJ_NAME} SHARED ${${PROJ_NAME}_HDRS} ${${PROJ_NAME}_SRCS} ${${PROJ_NAME}_UIHDRS} ${${PROJ_NAME}_translations_qm}) -TARGET_LINK_LIBRARIES(${PROJ_NAME} - Qt5::Widgets - ${Boost_LIBRARIES} - DbgHelp - uibase - game_gamebryo - game_creation - liblz4 - version) - -IF (MSVC) - SET_TARGET_PROPERTIES(${PROJ_NAME} PROPERTIES COMPILE_FLAGS "/std:c++latest") -ENDIF() -IF (MSVC AND CMAKE_SIZEOF_VOID_P EQUAL 4) - # 32 bits - SET_TARGET_PROPERTIES(${PROJ_NAME} PROPERTIES LINK_FLAGS "/LARGEADDRESSAWARE") -ENDIF() - -IF (NOT "${OPTIMIZE_COMPILE_FLAGS}" STREQUAL "") - SET_TARGET_PROPERTIES(${PROJ_NAME} PROPERTIES COMPILE_FLAGS_RELWITHDEBINFO ${OPTIMIZE_COMPILE_FLAGS}) -ENDIF() -IF (NOT "${OPTIMIZE_LINK_FLAGS}" STREQUAL "") - SET_TARGET_PROPERTIES(${PROJ_NAME} PROPERTIES LINK_FLAGS_RELWITHDEBINFO ${OPTIMIZE_LINK_FLAGS}) -ENDIF() - -############### -## Installation - -INSTALL(TARGETS ${PROJ_NAME} - RUNTIME DESTINATION bin/plugins) -INSTALL(FILES $ - DESTINATION pdb) +requires_project(game_gamebryo game_features) From 1a07f621fe0936db59044cb71a89b78f422a96c4 Mon Sep 17 00:00:00 2001 From: isanae <14251494+isanae@users.noreply.github.com> Date: Fri, 24 Apr 2020 23:07:56 -0400 Subject: [PATCH 0886/1544] [game_ttw] now using new cmakefiles --- src/games/ttw/CMakeLists.txt | 20 +++------ src/games/ttw/src/CMakeLists.txt | 77 ++------------------------------ 2 files changed, 9 insertions(+), 88 deletions(-) diff --git a/src/games/ttw/CMakeLists.txt b/src/games/ttw/CMakeLists.txt index 991c7a29..5f1d087c 100644 --- a/src/games/ttw/CMakeLists.txt +++ b/src/games/ttw/CMakeLists.txt @@ -1,16 +1,8 @@ -CMAKE_MINIMUM_REQUIRED(VERSION 2.8.12) +cmake_minimum_required(VERSION 3.16) -ADD_COMPILE_OPTIONS($<$:/MP> $<$:$<$:/O2>> $<$:$<$:/O2>>) +project(game_ttw) +set(project_type plugin) +set(enable_warnings OFF) -SET(PROJ_NAME game_ttw) - -PROJECT(${PROJ_NAME}) - -SET(DEPENDENCIES_DIR CACHE PATH "") - -# hint to find qt in dependencies path -LIST(APPEND CMAKE_PREFIX_PATH ${QT_ROOT}/lib/cmake) - -LIST(APPEND CMAKE_PREFIX_PATH ${DEPENDENCIES_DIR}/lz4/dll) - -ADD_SUBDIRECTORY(src) +include(../cmake_common/project.cmake) +add_subdirectory(src) diff --git a/src/games/ttw/src/CMakeLists.txt b/src/games/ttw/src/CMakeLists.txt index 4c3f4d45..de337c03 100644 --- a/src/games/ttw/src/CMakeLists.txt +++ b/src/games/ttw/src/CMakeLists.txt @@ -1,75 +1,4 @@ -CMAKE_MINIMUM_REQUIRED (VERSION 2.8.11) +cmake_minimum_required(VERSION 3.16) +include(../../cmake_common/src.cmake) -CMAKE_POLICY(SET CMP0020 NEW) - -FILE(GLOB ${PROJ_NAME}_SRCS *.cpp) -FILE(GLOB ${PROJ_NAME}_HDRS *.h) -FILE(GLOB ${PROJ_NAME}_FORMS *.ui) - - -SET(CMAKE_INCLUDE_CURRENT_DIR ON) -SET(CMAKE_AUTOMOC ON) -SET(CMAKE_AUTOUIC ON) -FIND_PACKAGE(Qt5Widgets REQUIRED) -QT5_WRAP_UI(${PROJ_NAME}_UIHDRS ${${PROJ_NAME}_FORMS}) - -SET(default_project_path "${DEPENDENCIES_DIR}/modorganizer_super") -GET_FILENAME_COMPONENT(${default_project_path} ${default_project_path} REALPATH) - -SET(project_path "${default_project_path}" CACHE PATH "path to the other mo projects") - -FIND_PACKAGE(Qt5LinguistTools) -SET(translation_sources ${CMAKE_SOURCE_DIR}/src ${project_path}/game_gamebryo/src/gamebryo) -QT5_CREATE_TRANSLATION(${PROJ_NAME}_translations_qm ${translation_sources} ${CMAKE_SOURCE_DIR}/src/${PROJ_NAME}_en.ts) - -SET(Boost_USE_STATIC_LIBS ON) -SET(Boost_USE_MULTITHREADED ON) -SET(Boost_USE_STATIC_RUNTIME OFF) -FIND_PACKAGE(Boost) - -IF (Boost_FOUND) - INCLUDE_DIRECTORIES(${Boost_INCLUDE_DIRS}) -ENDIF () - -SET(lib_path "${project_path}/../../install/libs") - -INCLUDE_DIRECTORIES(${project_path}/uibase/src - ${project_path}/game_features/src - ${project_path}/game_gamebryo/src/gamebryo) -LINK_DIRECTORIES(${project_path}/uibase/build/src - ${lib_path} - ${LZ4_ROOT}/bin) - - -ADD_LIBRARY(${PROJ_NAME} SHARED ${${PROJ_NAME}_HDRS} ${${PROJ_NAME}_SRCS} ${${PROJ_NAME}_UIHDRS} ${${PROJ_NAME}_translations_qm}) -TARGET_LINK_LIBRARIES(${PROJ_NAME} - Qt5::Widgets - ${Boost_LIBRARIES} - DbgHelp - uibase - game_gamebryo - liblz4 - Version) - -IF (MSVC) - SET_TARGET_PROPERTIES(${PROJ_NAME} PROPERTIES COMPILE_FLAGS "/std:c++latest") -ENDIF() -IF (MSVC AND CMAKE_SIZEOF_VOID_P EQUAL 4) - # 32 bits - SET_TARGET_PROPERTIES(${PROJ_NAME} PROPERTIES LINK_FLAGS "/LARGEADDRESSAWARE") -ENDIF() - -IF (NOT "${OPTIMIZE_COMPILE_FLAGS}" STREQUAL "") - SET_TARGET_PROPERTIES(${PROJ_NAME} PROPERTIES COMPILE_FLAGS_RELWITHDEBINFO ${OPTIMIZE_COMPILE_FLAGS}) -ENDIF() -IF (NOT "${OPTIMIZE_LINK_FLAGS}" STREQUAL "") - SET_TARGET_PROPERTIES(${PROJ_NAME} PROPERTIES LINK_FLAGS_RELWITHDEBINFO ${OPTIMIZE_LINK_FLAGS}) -ENDIF() - -############### -## Installation - -INSTALL(TARGETS ${PROJ_NAME} - RUNTIME DESTINATION bin/plugins) -INSTALL(FILES $ - DESTINATION pdb) +requires_project(game_gamebryo game_features) From 7a735477f9578937fcc3e99a7984d1499b50321d Mon Sep 17 00:00:00 2001 From: Silarn Date: Fri, 1 May 2020 04:58:56 -0500 Subject: [PATCH 0887/1544] [game_fallout4vr] Appveyor CMAKE fix --- src/games/fallout4vr/CMakeLists.txt | 6 +++++- src/games/fallout4vr/src/CMakeLists.txt | 6 +++++- 2 files changed, 10 insertions(+), 2 deletions(-) diff --git a/src/games/fallout4vr/CMakeLists.txt b/src/games/fallout4vr/CMakeLists.txt index 073d9efb..5a0cd43f 100644 --- a/src/games/fallout4vr/CMakeLists.txt +++ b/src/games/fallout4vr/CMakeLists.txt @@ -4,5 +4,9 @@ project(game_fallout4vr) set(project_type plugin) set(enable_warnings OFF) -include(../cmake_common/project.cmake) +if(DEFINED DEPENDENCIES_DIR) + include(${DEPENDENCIES_DIR}/modorganizer_super/cmake_common/project.cmake) +else() + include(../cmake_common/project.cmake) +endif() add_subdirectory(src) diff --git a/src/games/fallout4vr/src/CMakeLists.txt b/src/games/fallout4vr/src/CMakeLists.txt index 1a3a3af2..3b4e7319 100644 --- a/src/games/fallout4vr/src/CMakeLists.txt +++ b/src/games/fallout4vr/src/CMakeLists.txt @@ -1,4 +1,8 @@ cmake_minimum_required(VERSION 3.16) -include(../../cmake_common/src.cmake) +if(DEFINED DEPENDENCIES_DIR) + include(${DEPENDENCIES_DIR}/modorganizer_super/cmake_common/src.cmake) +else() + include(../../cmake_common/src.cmake) +endif() requires_project(game_features game_gamebryo) From 61eb0e300e3c4c1b18e5dd25830b3e8f85cbe11d Mon Sep 17 00:00:00 2001 From: Silarn Date: Fri, 1 May 2020 04:58:58 -0500 Subject: [PATCH 0888/1544] [game_falloutnv] Appveyor CMAKE fix --- src/games/falloutnv/CMakeLists.txt | 6 +++++- src/games/falloutnv/src/CMakeLists.txt | 7 +++++-- 2 files changed, 10 insertions(+), 3 deletions(-) diff --git a/src/games/falloutnv/CMakeLists.txt b/src/games/falloutnv/CMakeLists.txt index cd1f4b23..693cf34b 100644 --- a/src/games/falloutnv/CMakeLists.txt +++ b/src/games/falloutnv/CMakeLists.txt @@ -4,5 +4,9 @@ project(game_falloutNV) set(project_type plugin) set(enable_warnings OFF) -include(../cmake_common/project.cmake) +if(DEFINED DEPENDENCIES_DIR) + include(${DEPENDENCIES_DIR}/modorganizer_super/cmake_common/project.cmake) +else() + include(../cmake_common/project.cmake) +endif() add_subdirectory(src) diff --git a/src/games/falloutnv/src/CMakeLists.txt b/src/games/falloutnv/src/CMakeLists.txt index 1a3a3af2..e17b5e89 100644 --- a/src/games/falloutnv/src/CMakeLists.txt +++ b/src/games/falloutnv/src/CMakeLists.txt @@ -1,4 +1,7 @@ cmake_minimum_required(VERSION 3.16) -include(../../cmake_common/src.cmake) - +if(DEFINED DEPENDENCIES_DIR) + include(${DEPENDENCIES_DIR}/modorganizer_super/cmake_common/src.cmake) +else() + include(../../cmake_common/src.cmake) +endif() requires_project(game_features game_gamebryo) From 0e2649e8052b07d31a94d35a842afd3c8baad997 Mon Sep 17 00:00:00 2001 From: Silarn Date: Fri, 1 May 2020 04:59:01 -0500 Subject: [PATCH 0889/1544] [game_morrowind] Appveyor CMAKE fix --- src/games/morrowind/CMakeLists.txt | 6 +++++- src/games/morrowind/src/CMakeLists.txt | 7 +++++-- 2 files changed, 10 insertions(+), 3 deletions(-) diff --git a/src/games/morrowind/CMakeLists.txt b/src/games/morrowind/CMakeLists.txt index 2cd216fe..cf3cced3 100644 --- a/src/games/morrowind/CMakeLists.txt +++ b/src/games/morrowind/CMakeLists.txt @@ -4,5 +4,9 @@ project(game_morrowind) set(project_type plugin) set(enable_warnings OFF) -include(../cmake_common/project.cmake) +if(DEFINED DEPENDENCIES_DIR) + include(${DEPENDENCIES_DIR}/modorganizer_super/cmake_common/project.cmake) +else() + include(../cmake_common/project.cmake) +endif() add_subdirectory(src) diff --git a/src/games/morrowind/src/CMakeLists.txt b/src/games/morrowind/src/CMakeLists.txt index de337c03..1f12c529 100644 --- a/src/games/morrowind/src/CMakeLists.txt +++ b/src/games/morrowind/src/CMakeLists.txt @@ -1,4 +1,7 @@ cmake_minimum_required(VERSION 3.16) -include(../../cmake_common/src.cmake) - +if(DEFINED DEPENDENCIES_DIR) + include(${DEPENDENCIES_DIR}/modorganizer_super/cmake_common/src.cmake) +else() + include(../../cmake_common/src.cmake) +endif() requires_project(game_gamebryo game_features) From 7cff99aab73e0881e50eea0abd993578c8ff74c9 Mon Sep 17 00:00:00 2001 From: Silarn Date: Fri, 1 May 2020 04:59:03 -0500 Subject: [PATCH 0890/1544] [game_oblivion] Appveyor CMAKE fix --- src/games/oblivion/CMakeLists.txt | 6 +++++- src/games/oblivion/src/CMakeLists.txt | 7 +++++-- 2 files changed, 10 insertions(+), 3 deletions(-) diff --git a/src/games/oblivion/CMakeLists.txt b/src/games/oblivion/CMakeLists.txt index ba1d0771..c9691dc0 100644 --- a/src/games/oblivion/CMakeLists.txt +++ b/src/games/oblivion/CMakeLists.txt @@ -4,5 +4,9 @@ project(game_oblivion) set(project_type plugin) set(enable_warnings OFF) -include(../cmake_common/project.cmake) +if(DEFINED DEPENDENCIES_DIR) + include(${DEPENDENCIES_DIR}/modorganizer_super/cmake_common/project.cmake) +else() + include(../cmake_common/project.cmake) +endif() add_subdirectory(src) diff --git a/src/games/oblivion/src/CMakeLists.txt b/src/games/oblivion/src/CMakeLists.txt index de337c03..1f12c529 100644 --- a/src/games/oblivion/src/CMakeLists.txt +++ b/src/games/oblivion/src/CMakeLists.txt @@ -1,4 +1,7 @@ cmake_minimum_required(VERSION 3.16) -include(../../cmake_common/src.cmake) - +if(DEFINED DEPENDENCIES_DIR) + include(${DEPENDENCIES_DIR}/modorganizer_super/cmake_common/src.cmake) +else() + include(../../cmake_common/src.cmake) +endif() requires_project(game_gamebryo game_features) From 686cb4ef49e790bfb7e96a5f7a2307581102aa73 Mon Sep 17 00:00:00 2001 From: Silarn Date: Fri, 1 May 2020 04:59:04 -0500 Subject: [PATCH 0891/1544] [game_skyrimse] Appveyor CMAKE fix --- src/games/skyrimse/CMakeLists.txt | 6 +++++- src/games/skyrimse/src/CMakeLists.txt | 7 +++++-- 2 files changed, 10 insertions(+), 3 deletions(-) diff --git a/src/games/skyrimse/CMakeLists.txt b/src/games/skyrimse/CMakeLists.txt index cb8d90ee..c64b65a3 100644 --- a/src/games/skyrimse/CMakeLists.txt +++ b/src/games/skyrimse/CMakeLists.txt @@ -4,5 +4,9 @@ project(game_skyrimse) set(project_type plugin) set(enable_warnings OFF) -include(../cmake_common/project.cmake) +if(DEFINED DEPENDENCIES_DIR) + include(${DEPENDENCIES_DIR}/modorganizer_super/cmake_common/project.cmake) +else() + include(../cmake_common/project.cmake) +endif() add_subdirectory(src) diff --git a/src/games/skyrimse/src/CMakeLists.txt b/src/games/skyrimse/src/CMakeLists.txt index de337c03..1f12c529 100644 --- a/src/games/skyrimse/src/CMakeLists.txt +++ b/src/games/skyrimse/src/CMakeLists.txt @@ -1,4 +1,7 @@ cmake_minimum_required(VERSION 3.16) -include(../../cmake_common/src.cmake) - +if(DEFINED DEPENDENCIES_DIR) + include(${DEPENDENCIES_DIR}/modorganizer_super/cmake_common/src.cmake) +else() + include(../../cmake_common/src.cmake) +endif() requires_project(game_gamebryo game_features) From be7a2fe584119df355513fca2b36f7ec9d67dfc7 Mon Sep 17 00:00:00 2001 From: Silarn Date: Fri, 1 May 2020 04:59:05 -0500 Subject: [PATCH 0892/1544] [game_fallout3] Appveyor CMAKE fix --- src/games/fallout3/CMakeLists.txt | 6 +++++- src/games/fallout3/src/CMakeLists.txt | 6 +++++- 2 files changed, 10 insertions(+), 2 deletions(-) diff --git a/src/games/fallout3/CMakeLists.txt b/src/games/fallout3/CMakeLists.txt index b241c568..dc89ec22 100644 --- a/src/games/fallout3/CMakeLists.txt +++ b/src/games/fallout3/CMakeLists.txt @@ -4,5 +4,9 @@ project(game_fallout3) set(project_type plugin) set(enable_warnings OFF) -include(../cmake_common/project.cmake) +if(DEFINED DEPENDENCIES_DIR) + include(${DEPENDENCIES_DIR}/modorganizer_super/cmake_common/project.cmake) +else() + include(../cmake_common/project.cmake) +endif() add_subdirectory(src) diff --git a/src/games/fallout3/src/CMakeLists.txt b/src/games/fallout3/src/CMakeLists.txt index 1a3a3af2..3b4e7319 100644 --- a/src/games/fallout3/src/CMakeLists.txt +++ b/src/games/fallout3/src/CMakeLists.txt @@ -1,4 +1,8 @@ cmake_minimum_required(VERSION 3.16) -include(../../cmake_common/src.cmake) +if(DEFINED DEPENDENCIES_DIR) + include(${DEPENDENCIES_DIR}/modorganizer_super/cmake_common/src.cmake) +else() + include(../../cmake_common/src.cmake) +endif() requires_project(game_features game_gamebryo) From b839cce007a225e2ee92a40e87ff8bd54ef33f31 Mon Sep 17 00:00:00 2001 From: Silarn Date: Fri, 1 May 2020 04:59:06 -0500 Subject: [PATCH 0893/1544] Appveyor CMAKE fix --- CMakeLists.txt | 6 +++++- src/creation/CMakeLists.txt | 11 +++++++++-- src/gamebryo/CMakeLists.txt | 8 +++++++- 3 files changed, 21 insertions(+), 4 deletions(-) diff --git a/CMakeLists.txt b/CMakeLists.txt index 79a95210..dc380d25 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -4,7 +4,11 @@ project(game_gamebryo) set(project_type lib) set(enable_warnings OFF) -include(../cmake_common/project.cmake) +if(DEFINED DEPENDENCIES_DIR) + include(${DEPENDENCIES_DIR}/modorganizer_super/cmake_common/project.cmake) +else() + include(../cmake_common/project.cmake) +endif() add_subdirectory(src/gamebryo) # note that this also creates a project diff --git a/src/creation/CMakeLists.txt b/src/creation/CMakeLists.txt index 29a68a33..c4f6c921 100644 --- a/src/creation/CMakeLists.txt +++ b/src/creation/CMakeLists.txt @@ -4,7 +4,14 @@ project(game_creation) set(project_type lib) set(enable_warnings OFF) -include(../../../cmake_common/project.cmake) -include(../../../cmake_common/src.cmake) +# appveyor does not build modorganizer in its standard location, so use +# DEPENDENCIES_DIR to find cmake_common +if(DEFINED DEPENDENCIES_DIR) + include(${DEPENDENCIES_DIR}/modorganizer_super/cmake_common/project.cmake) + include(${DEPENDENCIES_DIR}/modorganizer_super/cmake_common/src.cmake) +else() + include(../../../cmake_common/project.cmake) + include(../../../cmake_common/src.cmake) +endif() requires_project(game_gamebryo game_features) diff --git a/src/gamebryo/CMakeLists.txt b/src/gamebryo/CMakeLists.txt index 00203ddb..c5e1b895 100644 --- a/src/gamebryo/CMakeLists.txt +++ b/src/gamebryo/CMakeLists.txt @@ -1,4 +1,10 @@ cmake_minimum_required(VERSION 3.16) -include(../../../cmake_common/src.cmake) +# appveyor does not build modorganizer in its standard location, so use +# DEPENDENCIES_DIR to find cmake_common +if(DEFINED DEPENDENCIES_DIR) + include(${DEPENDENCIES_DIR}/modorganizer_super/cmake_common/src.cmake) +else() + include(../../../cmake_common/src.cmake) +endif() requires_project(game_features) From 073b3f9710fd1ea9845e13a73f6692df43c72d62 Mon Sep 17 00:00:00 2001 From: Silarn Date: Fri, 1 May 2020 04:59:06 -0500 Subject: [PATCH 0894/1544] [game_fallout4] Appveyor CMAKE fix --- src/games/fallout4/CMakeLists.txt | 6 +++++- src/games/fallout4/src/CMakeLists.txt | 6 +++++- 2 files changed, 10 insertions(+), 2 deletions(-) diff --git a/src/games/fallout4/CMakeLists.txt b/src/games/fallout4/CMakeLists.txt index f7ef8b24..15de22e1 100644 --- a/src/games/fallout4/CMakeLists.txt +++ b/src/games/fallout4/CMakeLists.txt @@ -4,5 +4,9 @@ project(game_fallout4) set(project_type plugin) set(enable_warnings OFF) -include(../cmake_common/project.cmake) +if(DEFINED DEPENDENCIES_DIR) + include(${DEPENDENCIES_DIR}/modorganizer_super/cmake_common/project.cmake) +else() + include(../cmake_common/project.cmake) +endif() add_subdirectory(src) diff --git a/src/games/fallout4/src/CMakeLists.txt b/src/games/fallout4/src/CMakeLists.txt index 1a3a3af2..3b4e7319 100644 --- a/src/games/fallout4/src/CMakeLists.txt +++ b/src/games/fallout4/src/CMakeLists.txt @@ -1,4 +1,8 @@ cmake_minimum_required(VERSION 3.16) -include(../../cmake_common/src.cmake) +if(DEFINED DEPENDENCIES_DIR) + include(${DEPENDENCIES_DIR}/modorganizer_super/cmake_common/src.cmake) +else() + include(../../cmake_common/src.cmake) +endif() requires_project(game_features game_gamebryo) From 78d7e37af7a68c1cbe23db53ca56266bfad9d713 Mon Sep 17 00:00:00 2001 From: Silarn Date: Fri, 1 May 2020 04:59:07 -0500 Subject: [PATCH 0895/1544] [game_skyrimvr] Appveyor CMAKE fix --- src/games/skyrimvr/CMakeLists.txt | 6 +++++- src/games/skyrimvr/src/CMakeLists.txt | 7 +++++-- 2 files changed, 10 insertions(+), 3 deletions(-) diff --git a/src/games/skyrimvr/CMakeLists.txt b/src/games/skyrimvr/CMakeLists.txt index 5e7ef7c4..a6883a42 100644 --- a/src/games/skyrimvr/CMakeLists.txt +++ b/src/games/skyrimvr/CMakeLists.txt @@ -4,5 +4,9 @@ project(game_skyrimvr) set(project_type plugin) set(enable_warnings OFF) -include(../cmake_common/project.cmake) +if(DEFINED DEPENDENCIES_DIR) + include(${DEPENDENCIES_DIR}/modorganizer_super/cmake_common/project.cmake) +else() + include(../cmake_common/project.cmake) +endif() add_subdirectory(src) diff --git a/src/games/skyrimvr/src/CMakeLists.txt b/src/games/skyrimvr/src/CMakeLists.txt index de337c03..1f12c529 100644 --- a/src/games/skyrimvr/src/CMakeLists.txt +++ b/src/games/skyrimvr/src/CMakeLists.txt @@ -1,4 +1,7 @@ cmake_minimum_required(VERSION 3.16) -include(../../cmake_common/src.cmake) - +if(DEFINED DEPENDENCIES_DIR) + include(${DEPENDENCIES_DIR}/modorganizer_super/cmake_common/src.cmake) +else() + include(../../cmake_common/src.cmake) +endif() requires_project(game_gamebryo game_features) From 5ca31fc6c1e016ba69f9d6d126d413696242f005 Mon Sep 17 00:00:00 2001 From: Silarn Date: Fri, 1 May 2020 04:59:11 -0500 Subject: [PATCH 0896/1544] [game_skyrim] Appveyor CMAKE fix --- src/games/skyrim/CMakeLists.txt | 6 +++++- src/games/skyrim/src/CMakeLists.txt | 7 +++++-- 2 files changed, 10 insertions(+), 3 deletions(-) diff --git a/src/games/skyrim/CMakeLists.txt b/src/games/skyrim/CMakeLists.txt index a66154e8..b4c1bb55 100644 --- a/src/games/skyrim/CMakeLists.txt +++ b/src/games/skyrim/CMakeLists.txt @@ -4,5 +4,9 @@ project(game_skyrim) set(project_type plugin) set(enable_warnings OFF) -include(../cmake_common/project.cmake) +if(DEFINED DEPENDENCIES_DIR) + include(${DEPENDENCIES_DIR}/modorganizer_super/cmake_common/project.cmake) +else() + include(../cmake_common/project.cmake) +endif() add_subdirectory(src) diff --git a/src/games/skyrim/src/CMakeLists.txt b/src/games/skyrim/src/CMakeLists.txt index de337c03..1f12c529 100644 --- a/src/games/skyrim/src/CMakeLists.txt +++ b/src/games/skyrim/src/CMakeLists.txt @@ -1,4 +1,7 @@ cmake_minimum_required(VERSION 3.16) -include(../../cmake_common/src.cmake) - +if(DEFINED DEPENDENCIES_DIR) + include(${DEPENDENCIES_DIR}/modorganizer_super/cmake_common/src.cmake) +else() + include(../../cmake_common/src.cmake) +endif() requires_project(game_gamebryo game_features) From 9e2ecfdd33eb8ef60656684614ff9016ad64edb9 Mon Sep 17 00:00:00 2001 From: Silarn Date: Fri, 1 May 2020 04:59:13 -0500 Subject: [PATCH 0897/1544] [game_ttw] Appveyor CMAKE fix --- src/games/ttw/CMakeLists.txt | 6 +++++- src/games/ttw/src/CMakeLists.txt | 7 +++++-- 2 files changed, 10 insertions(+), 3 deletions(-) diff --git a/src/games/ttw/CMakeLists.txt b/src/games/ttw/CMakeLists.txt index 5f1d087c..e8bdaaea 100644 --- a/src/games/ttw/CMakeLists.txt +++ b/src/games/ttw/CMakeLists.txt @@ -4,5 +4,9 @@ project(game_ttw) set(project_type plugin) set(enable_warnings OFF) -include(../cmake_common/project.cmake) +if(DEFINED DEPENDENCIES_DIR) + include(${DEPENDENCIES_DIR}/modorganizer_super/cmake_common/project.cmake) +else() + include(../cmake_common/project.cmake) +endif() add_subdirectory(src) diff --git a/src/games/ttw/src/CMakeLists.txt b/src/games/ttw/src/CMakeLists.txt index de337c03..1f12c529 100644 --- a/src/games/ttw/src/CMakeLists.txt +++ b/src/games/ttw/src/CMakeLists.txt @@ -1,4 +1,7 @@ cmake_minimum_required(VERSION 3.16) -include(../../cmake_common/src.cmake) - +if(DEFINED DEPENDENCIES_DIR) + include(${DEPENDENCIES_DIR}/modorganizer_super/cmake_common/src.cmake) +else() + include(../../cmake_common/src.cmake) +endif() requires_project(game_gamebryo game_features) From fd5f9cac0d72c1ddcb49e4abe19de2b15ab28935 Mon Sep 17 00:00:00 2001 From: Silarn Date: Fri, 1 May 2020 16:33:41 -0500 Subject: [PATCH 0898/1544] Fix artifact paths --- appveyor.yml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/appveyor.yml b/appveyor.yml index 7932ecda..8c8aba4d 100644 --- a/appveyor.yml +++ b/appveyor.yml @@ -14,9 +14,9 @@ build_script: C:\Python37-x64\python.exe unimake.py -d c:\projects\modorganizer-build -s Appveyor_Build=True %APPVEYOR_PROJECT_NAME% artifacts: -- path: build\src\game_gamebryo.lib +- path: build\src\RelWithDebInfo\game_gamebryo.lib name: game_gamebryo_lib -- path: build\src\game_creation.lib +- path: build\src\RelWithDebInfo\game_creation.lib name: game_creation_lib on_success: - ps: Set-Location -Path $env:APPVEYOR_BUILD_FOLDER From b2104f9a09d9406f04b4583dcda9fc25b21d3d24 Mon Sep 17 00:00:00 2001 From: Silarn Date: Fri, 1 May 2020 16:43:20 -0500 Subject: [PATCH 0899/1544] Restore artifact paths..? --- appveyor.yml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/appveyor.yml b/appveyor.yml index 8c8aba4d..edd640d3 100644 --- a/appveyor.yml +++ b/appveyor.yml @@ -14,9 +14,9 @@ build_script: C:\Python37-x64\python.exe unimake.py -d c:\projects\modorganizer-build -s Appveyor_Build=True %APPVEYOR_PROJECT_NAME% artifacts: -- path: build\src\RelWithDebInfo\game_gamebryo.lib +- path: build\src\gamebryo\game_gamebryo.lib name: game_gamebryo_lib -- path: build\src\RelWithDebInfo\game_creation.lib +- path: build\src\creation\game_creation.lib name: game_creation_lib on_success: - ps: Set-Location -Path $env:APPVEYOR_BUILD_FOLDER From bb8970284932e2de29ea2be7d9fb6445bf9ab6e1 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Mika=C3=ABl=20Capelle?= Date: Sat, 16 May 2020 18:58:16 +0200 Subject: [PATCH 0900/1544] Add ModDataChecker game feature for GameBryo. --- src/gamebryomoddatachecker.cpp | 39 +++++++++++++++++++++++ src/gamebryomoddatachecker.h | 57 ++++++++++++++++++++++++++++++++++ 2 files changed, 96 insertions(+) create mode 100644 src/gamebryomoddatachecker.cpp create mode 100644 src/gamebryomoddatachecker.h diff --git a/src/gamebryomoddatachecker.cpp b/src/gamebryomoddatachecker.cpp new file mode 100644 index 00000000..3859ec54 --- /dev/null +++ b/src/gamebryomoddatachecker.cpp @@ -0,0 +1,39 @@ +#include + +#include "gamebryomoddatachecker.h" + +const QStringList GamebryoModDataChecker::STANDARD_FOLDERS = { + "fonts", "interface", "menus", "meshes", "music", "scripts", "shaders", + "sound", "strings", "textures", "trees", "video", "facegen", "materials", + "skse", "obse", "mwse", "nvse", "fose", "f4se", "distantlod", "asi", + "SkyProc Patchers", "Tools", "MCM", "icons", "bookart", "distantland", + "mits", "splash", "dllplugins", "CalienteTools", "NetScriptFramework", + "shadersfx" +}; + +const QStringList GamebryoModDataChecker::STANDARD_EXTENSIONS = { + "esp", "esm", "esl", "bsa", "ba2", ".modgroups" +}; + +GamebryoModDataChecker::GamebryoModDataChecker(const GameGamebryo* game, QStringList folders, QStringList extensions) : + m_Game(game), m_FolderNames(folders.begin(), folders.end()), m_FileExtensions(extensions.begin(), extensions.end()) { } + +QString GamebryoModDataChecker::getDataFolderName() const { + return "data"; +} + +bool GamebryoModDataChecker::dataLooksValid(std::shared_ptr fileTree) const { + for (auto entry : *fileTree) { + if (entry->isDir()) { + if (m_FolderNames.count(entry->name()) > 0) { + return true; + } + } + else { + if (m_FileExtensions.count(entry->suffix()) > 0) { + return true; + } + } + } + return false; +} \ No newline at end of file diff --git a/src/gamebryomoddatachecker.h b/src/gamebryomoddatachecker.h new file mode 100644 index 00000000..94ba7b5a --- /dev/null +++ b/src/gamebryomoddatachecker.h @@ -0,0 +1,57 @@ +#ifndef GAMEBRYO_MODATACHECKER_H +#define GAMEBRYO_MODATACHECKER_H + +#include +#include + +class GameGamebryo; + +class GamebryoModDataChecker: public ModDataChecker +{ + /** + * @brief Standard list of folders. + */ + static const QStringList STANDARD_FOLDERS; + + /** + * @brief Standard list of extensions. + */ + static const QStringList STANDARD_EXTENSIONS; + +public: + + + /** + * @brief Construct a new mod-data checker for GameBryo games using the default + * list of possible folders and extensions. + */ + GamebryoModDataChecker(const GameGamebryo* game) : + GamebryoModDataChecker(game, STANDARD_FOLDERS, STANDARD_EXTENSIONS) { } + + + /** + * @brief Construct a new mod-data checker for GameBryo games using the given + * list of possible folders and extensions. + * + * @param folders List of folders that should be found in the data folder. + * @param extensions List of extension of files that should be found in the data folder (without + * the leading dot). + */ + GamebryoModDataChecker(const GameGamebryo* game, QStringList folders, QStringList extensions); + + + virtual QString getDataFolderName() const override; + virtual bool dataLooksValid(std::shared_ptr fileTree) const; + +protected: + const GameGamebryo* game() const { return m_Game; } + +private: + const GameGamebryo* m_Game; + + std::set m_FolderNames; + std::set m_FileExtensions; + +}; + +#endif // GAMEBRYO_MODATACHECKER_H From 623f92bdf1de083f73bf9fc4fe3fbc945732fc4f Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Mika=C3=ABl=20Capelle?= Date: Sat, 16 May 2020 23:25:34 +0200 Subject: [PATCH 0901/1544] [game_fallout3] Add ModDataChecker feeature (generic). --- src/games/fallout3/src/gamefallout3.cpp | 2 ++ 1 file changed, 2 insertions(+) diff --git a/src/games/fallout3/src/gamefallout3.cpp b/src/games/fallout3/src/gamefallout3.cpp index 670c62df..fc547a90 100644 --- a/src/games/fallout3/src/gamefallout3.cpp +++ b/src/games/fallout3/src/gamefallout3.cpp @@ -9,6 +9,7 @@ #include "pluginsetting.h" #include "versioninfo.h" #include +#include #include #include @@ -38,6 +39,7 @@ bool GameFallout3::init(IOrganizer *moInfo) registerFeature(new Fallout3BSAInvalidation(feature(), this)); registerFeature(new Fallout3SaveGameInfo(this)); registerFeature(new GamebryoLocalSavegames(myGamesPath(), "fallout.ini")); + registerFeature(new GamebryoModDataChecker(this)); registerFeature(new GamebryoGamePlugins(moInfo)); registerFeature(new GamebryoUnmangedMods(this)); return true; From d4b01a52acae3d2d694788f7af59b6f7c38c279e Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Mika=C3=ABl=20Capelle?= Date: Sat, 16 May 2020 23:26:04 +0200 Subject: [PATCH 0902/1544] [game_falloutnv] Add ModDataChecker feeature (generic). --- src/games/falloutnv/src/gamefalloutnv.cpp | 2 ++ 1 file changed, 2 insertions(+) diff --git a/src/games/falloutnv/src/gamefalloutnv.cpp b/src/games/falloutnv/src/gamefalloutnv.cpp index ee22b76c..fb839488 100644 --- a/src/games/falloutnv/src/gamefalloutnv.cpp +++ b/src/games/falloutnv/src/gamefalloutnv.cpp @@ -9,6 +9,7 @@ #include "pluginsetting.h" #include "versioninfo.h" #include +#include #include #include @@ -38,6 +39,7 @@ bool GameFalloutNV::init(IOrganizer *moInfo) registerFeature(new FalloutNVBSAInvalidation(feature(), this)); registerFeature(new FalloutNVSaveGameInfo(this)); registerFeature(new GamebryoLocalSavegames(myGamesPath(), "fallout.ini")); + registerFeature(new GamebryoModDataChecker(this)); registerFeature(new GamebryoGamePlugins(moInfo)); registerFeature(new GamebryoUnmangedMods(this)); return true; From d454548d22b4dd0ea1fcadbd96f0027f99b206cf Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Mika=C3=ABl=20Capelle?= Date: Sat, 16 May 2020 23:26:47 +0200 Subject: [PATCH 0903/1544] Move ModDataChecker at the right location. --- src/{ => gamebryo}/gamebryomoddatachecker.cpp | 0 src/{ => gamebryo}/gamebryomoddatachecker.h | 0 2 files changed, 0 insertions(+), 0 deletions(-) rename src/{ => gamebryo}/gamebryomoddatachecker.cpp (100%) rename src/{ => gamebryo}/gamebryomoddatachecker.h (100%) diff --git a/src/gamebryomoddatachecker.cpp b/src/gamebryo/gamebryomoddatachecker.cpp similarity index 100% rename from src/gamebryomoddatachecker.cpp rename to src/gamebryo/gamebryomoddatachecker.cpp diff --git a/src/gamebryomoddatachecker.h b/src/gamebryo/gamebryomoddatachecker.h similarity index 100% rename from src/gamebryomoddatachecker.h rename to src/gamebryo/gamebryomoddatachecker.h From 8cb609771e6b19963d8587dd5903b3a5683aa0bc Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Mika=C3=ABl=20Capelle?= Date: Sat, 16 May 2020 23:27:11 +0200 Subject: [PATCH 0904/1544] [game_morrowind] Add ModDataChecker feeature (generic). --- src/games/morrowind/src/gamemorrowind.cpp | 2 ++ 1 file changed, 2 insertions(+) diff --git a/src/games/morrowind/src/gamemorrowind.cpp b/src/games/morrowind/src/gamemorrowind.cpp index d2c1a684..e9faf729 100644 --- a/src/games/morrowind/src/gamemorrowind.cpp +++ b/src/games/morrowind/src/gamemorrowind.cpp @@ -10,6 +10,7 @@ #include "pluginsetting.h" #include "steamutility.h" +#include #include #include @@ -42,6 +43,7 @@ bool GameMorrowind::init(IOrganizer *moInfo) registerFeature(new MorrowindBSAInvalidation(feature(), this)); registerFeature(new MorrowindSaveGameInfo(this)); registerFeature(new MorrowindLocalSavegames(this)); + registerFeature(new GamebryoModDataChecker(this)); registerFeature(new MorrowindGamePlugins(moInfo)); registerFeature(new GamebryoUnmangedMods(this)); m_Organizer = moInfo; From aaad378079882ccf3470559990f9c01afa6905a4 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Mika=C3=ABl=20Capelle?= Date: Sat, 16 May 2020 23:27:20 +0200 Subject: [PATCH 0905/1544] [game_oblivion] Add ModDataChecker feeature (generic). --- src/games/oblivion/src/gameoblivion.cpp | 2 ++ 1 file changed, 2 insertions(+) diff --git a/src/games/oblivion/src/gameoblivion.cpp b/src/games/oblivion/src/gameoblivion.cpp index b73a8d7a..6e7a3af3 100644 --- a/src/games/oblivion/src/gameoblivion.cpp +++ b/src/games/oblivion/src/gameoblivion.cpp @@ -8,6 +8,7 @@ #include "pluginsetting.h" #include "executableinfo.h" #include +#include #include #include @@ -33,6 +34,7 @@ bool GameOblivion::init(IOrganizer *moInfo) registerFeature(new OblivionBSAInvalidation(feature(), this)); registerFeature(new OblivionSaveGameInfo(this)); registerFeature(new GamebryoLocalSavegames(myGamesPath(), "oblivion.ini")); + registerFeature(new GamebryoModDataChecker(this)); registerFeature(new GamebryoGamePlugins(moInfo)); registerFeature(new GamebryoUnmangedMods(this)); return true; From 721212ccaa5054bb4b1340a9eaa6f87fb5e75b6b Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Mika=C3=ABl=20Capelle?= Date: Sat, 16 May 2020 23:27:29 +0200 Subject: [PATCH 0906/1544] [game_skyrim] Add ModDataChecker feeature (generic). --- src/games/skyrim/src/gameskyrim.cpp | 2 ++ 1 file changed, 2 insertions(+) diff --git a/src/games/skyrim/src/gameskyrim.cpp b/src/games/skyrim/src/gameskyrim.cpp index 326d2c97..0e366ec9 100644 --- a/src/games/skyrim/src/gameskyrim.cpp +++ b/src/games/skyrim/src/gameskyrim.cpp @@ -10,6 +10,7 @@ #include "pluginsetting.h" #include +#include #include #include @@ -44,6 +45,7 @@ bool GameSkyrim::init(IOrganizer *moInfo) registerFeature(new SkyrimBSAInvalidation(feature(), this)); registerFeature(new SkyrimSaveGameInfo(this)); registerFeature(new GamebryoLocalSavegames(myGamesPath(), "skyrim.ini")); + registerFeature(new GamebryoModDataChecker(this)); registerFeature(new SkyrimGamePlugins(moInfo)); registerFeature(new GamebryoUnmangedMods(this)); return true; From a4387e2f07c18c3d0fa19015a267c7e8c4d72a0a Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Mika=C3=ABl=20Capelle?= Date: Sat, 16 May 2020 23:27:36 +0200 Subject: [PATCH 0907/1544] [game_skyrimse] Add ModDataChecker feeature (generic). --- src/games/skyrimse/src/gameskyrimse.cpp | 2 ++ 1 file changed, 2 insertions(+) diff --git a/src/games/skyrimse/src/gameskyrimse.cpp b/src/games/skyrimse/src/gameskyrimse.cpp index 32bfe578..66caf8ad 100644 --- a/src/games/skyrimse/src/gameskyrimse.cpp +++ b/src/games/skyrimse/src/gameskyrimse.cpp @@ -8,6 +8,7 @@ #include #include #include +#include #include #include "versioninfo.h" #include @@ -72,6 +73,7 @@ bool GameSkyrimSE::init(IOrganizer *moInfo) registerFeature(new SkyrimSEScriptExtender(this)); registerFeature(new SkyrimSEDataArchives(myGamesPath())); registerFeature(new GamebryoLocalSavegames(myGamesPath(), "Skyrimcustom.ini")); + registerFeature(new GamebryoModDataChecker(this)); registerFeature(new SkyrimSESaveGameInfo(this)); registerFeature(new CreationGamePlugins(moInfo)); registerFeature(new SkyrimSEUnmangedMods(this)); From 84fd34454766163e050f224a038c3b4a87010bf6 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Mika=C3=ABl=20Capelle?= Date: Sat, 16 May 2020 23:27:45 +0200 Subject: [PATCH 0908/1544] [game_skyrimvr] Add ModDataChecker feeature (generic). --- src/games/skyrimvr/src/gameskyrimvr.cpp | 2 ++ 1 file changed, 2 insertions(+) diff --git a/src/games/skyrimvr/src/gameskyrimvr.cpp b/src/games/skyrimvr/src/gameskyrimvr.cpp index b8aa9652..4c8451e4 100644 --- a/src/games/skyrimvr/src/gameskyrimvr.cpp +++ b/src/games/skyrimvr/src/gameskyrimvr.cpp @@ -8,6 +8,7 @@ #include #include #include +#include #include #include "versioninfo.h" @@ -71,6 +72,7 @@ bool GameSkyrimVR::init(IOrganizer *moInfo) registerFeature(new SkyrimVRScriptExtender(this)); registerFeature(new SkyrimVRDataArchives(myGamesPath())); registerFeature(new GamebryoLocalSavegames(myGamesPath(), "SkyrimVR.ini")); + registerFeature(new GamebryoModDataChecker(this)); registerFeature(new SkyrimVRSaveGameInfo(this)); registerFeature(new CreationGamePlugins(moInfo)); registerFeature(new SkyrimVRUnmangedMods(this)); From a3f46776983f97cf7c74e18a9dac55cf981b5b3c Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Mika=C3=ABl=20Capelle?= Date: Sat, 16 May 2020 23:28:17 +0200 Subject: [PATCH 0909/1544] [game_ttw] Add ModDataChecker feeature (generic). --- src/games/ttw/src/gamefalloutttw.cpp | 2 ++ 1 file changed, 2 insertions(+) diff --git a/src/games/ttw/src/gamefalloutttw.cpp b/src/games/ttw/src/gamefalloutttw.cpp index 17f3449d..64de5245 100644 --- a/src/games/ttw/src/gamefalloutttw.cpp +++ b/src/games/ttw/src/gamefalloutttw.cpp @@ -9,6 +9,7 @@ #include "pluginsetting.h" #include "versioninfo.h" #include +#include #include #include @@ -40,6 +41,7 @@ bool GameFalloutTTW::init(IOrganizer *moInfo) registerFeature(new FalloutTTWBSAInvalidation(feature(), this)); registerFeature(new FalloutTTWSaveGameInfo(this)); registerFeature(new GamebryoLocalSavegames(myGamesPath(), "fallout.ini")); + registerFeature(new GamebryoModDataChecker(this)); registerFeature(new GamebryoGamePlugins(moInfo)); registerFeature(new GamebryoUnmangedMods(this)); return true; From 05ded214497a34c398518d242dfe98605dcae025 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Mika=C3=ABl=20Capelle?= Date: Mon, 18 May 2020 19:36:45 +0200 Subject: [PATCH 0910/1544] Add getProductVersion() method. --- src/gamebryo/gamegamebryo.cpp | 38 +++++++++++++++++++++++++++++++++++ src/gamebryo/gamegamebryo.h | 1 + 2 files changed, 39 insertions(+) diff --git a/src/gamebryo/gamegamebryo.cpp b/src/gamebryo/gamegamebryo.cpp index 35199ac2..fb278c78 100644 --- a/src/gamebryo/gamegamebryo.cpp +++ b/src/gamebryo/gamegamebryo.cpp @@ -25,6 +25,8 @@ #include #include +#include + GameGamebryo::GameGamebryo() { } @@ -158,6 +160,42 @@ QString GameGamebryo::getVersion(QString const &program) const .arg(LOWORD(pFileInfo->dwFileVersionLS)); } +QString GameGamebryo::getProductVersion(QString const& program) const { + //This *really* needs to be factored out + std::wstring app_name = L"\\\\?\\" + + QDir::toNativeSeparators(this->gameDirectory().absoluteFilePath(program)).toStdWString(); + DWORD handle; + DWORD info_len = ::GetFileVersionInfoSizeW(app_name.c_str(), &handle); + if (info_len == 0) { + qDebug("GetFileVersionInfoSizeW Error %d", ::GetLastError()); + return ""; + } + + std::vector buff(info_len); + if (!::GetFileVersionInfoW(app_name.c_str(), handle, info_len, buff.data())) { + qDebug("GetFileVersionInfoW Error %d", ::GetLastError()); + return ""; + } + + // The following is from https://stackoverflow.com/a/12408544/2666289 + + UINT uiSize; + BYTE* lpb; + if (!::VerQueryValueW(buff.data(), TEXT("\\VarFileInfo\\Translation"), (void**)&lpb, &uiSize)) { + qDebug("VerQueryValue Error %d", ::GetLastError()); + return ""; + } + + WORD* lpw = (WORD*)lpb; + auto query = fmt::format(L"\\StringFileInfo\\{:04x}{:04x}\\ProductVersion", lpw[0], lpw[1]); + if (!::VerQueryValueW(buff.data(), query.data(), (void**)&lpb, &uiSize) && uiSize > 0) { + qDebug("VerQueryValue Error %d", ::GetLastError()); + return ""; + } + + return QString::fromWCharArray((LPCWSTR)lpb); +} + WORD GameGamebryo::getArch(QString const &program) const { WORD arch = 0; diff --git a/src/gamebryo/gamegamebryo.h b/src/gamebryo/gamegamebryo.h index 841e7e8a..16fb99b0 100644 --- a/src/gamebryo/gamegamebryo.h +++ b/src/gamebryo/gamegamebryo.h @@ -80,6 +80,7 @@ protected: QString myGamesPath() const; QString selectedVariant() const; QString getVersion(QString const &program) const; + QString getProductVersion(QString const& program) const; WORD getArch(QString const &program) const; static QString localAppFolder(); From 2af98b7ca1c19f978b63aa463951b49bcedf3705 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Mika=C3=ABl=20Capelle?= Date: Fri, 22 May 2020 15:51:21 +0200 Subject: [PATCH 0911/1544] Remove getDataFolderName(). --- src/gamebryo/gamebryomoddatachecker.cpp | 4 ---- src/gamebryo/gamebryomoddatachecker.h | 3 +-- 2 files changed, 1 insertion(+), 6 deletions(-) diff --git a/src/gamebryo/gamebryomoddatachecker.cpp b/src/gamebryo/gamebryomoddatachecker.cpp index 3859ec54..372d5d52 100644 --- a/src/gamebryo/gamebryomoddatachecker.cpp +++ b/src/gamebryo/gamebryomoddatachecker.cpp @@ -18,10 +18,6 @@ const QStringList GamebryoModDataChecker::STANDARD_EXTENSIONS = { GamebryoModDataChecker::GamebryoModDataChecker(const GameGamebryo* game, QStringList folders, QStringList extensions) : m_Game(game), m_FolderNames(folders.begin(), folders.end()), m_FileExtensions(extensions.begin(), extensions.end()) { } -QString GamebryoModDataChecker::getDataFolderName() const { - return "data"; -} - bool GamebryoModDataChecker::dataLooksValid(std::shared_ptr fileTree) const { for (auto entry : *fileTree) { if (entry->isDir()) { diff --git a/src/gamebryo/gamebryomoddatachecker.h b/src/gamebryo/gamebryomoddatachecker.h index 94ba7b5a..dcbcd3ce 100644 --- a/src/gamebryo/gamebryomoddatachecker.h +++ b/src/gamebryo/gamebryomoddatachecker.h @@ -40,8 +40,7 @@ public: GamebryoModDataChecker(const GameGamebryo* game, QStringList folders, QStringList extensions); - virtual QString getDataFolderName() const override; - virtual bool dataLooksValid(std::shared_ptr fileTree) const; + virtual bool dataLooksValid(std::shared_ptr fileTree) const override; protected: const GameGamebryo* game() const { return m_Game; } From 86267b606aa2a5bb0c34f1dbb8c9dca35db899e8 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Mika=C3=ABl=20Capelle?= Date: Fri, 22 May 2020 22:59:58 +0200 Subject: [PATCH 0912/1544] Change the way possible folder names and file extensions are provided to ModDataChecker. --- src/gamebryo/gamebryomoddatachecker.cpp | 45 +++++++++++++------- src/gamebryo/gamebryomoddatachecker.h | 55 +++++++++++-------------- 2 files changed, 54 insertions(+), 46 deletions(-) diff --git a/src/gamebryo/gamebryomoddatachecker.cpp b/src/gamebryo/gamebryomoddatachecker.cpp index 372d5d52..7ef6e13f 100644 --- a/src/gamebryo/gamebryomoddatachecker.cpp +++ b/src/gamebryo/gamebryomoddatachecker.cpp @@ -2,31 +2,46 @@ #include "gamebryomoddatachecker.h" -const QStringList GamebryoModDataChecker::STANDARD_FOLDERS = { - "fonts", "interface", "menus", "meshes", "music", "scripts", "shaders", - "sound", "strings", "textures", "trees", "video", "facegen", "materials", - "skse", "obse", "mwse", "nvse", "fose", "f4se", "distantlod", "asi", - "SkyProc Patchers", "Tools", "MCM", "icons", "bookart", "distantland", - "mits", "splash", "dllplugins", "CalienteTools", "NetScriptFramework", - "shadersfx" -}; -const QStringList GamebryoModDataChecker::STANDARD_EXTENSIONS = { - "esp", "esm", "esl", "bsa", "ba2", ".modgroups" -}; -GamebryoModDataChecker::GamebryoModDataChecker(const GameGamebryo* game, QStringList folders, QStringList extensions) : - m_Game(game), m_FolderNames(folders.begin(), folders.end()), m_FileExtensions(extensions.begin(), extensions.end()) { } +/** + * @return the list of possible folder names in data. + */ +auto GamebryoModDataChecker::possibleFolderNames() const -> const FileNameSet& { + static FileNameSet result{ + "fonts", "interface", "menus", "meshes", "music", "scripts", "shaders", + "sound", "strings", "textures", "trees", "video", "facegen", "materials", + "skse", "obse", "mwse", "nvse", "fose", "f4se", "distantlod", "asi", + "SkyProc Patchers", "Tools", "MCM", "icons", "bookart", "distantland", + "mits", "splash", "dllplugins", "CalienteTools", "NetScriptFramework", + "shadersfx" + }; + return result; +} + +/** + * @return the extensions of possible files in data. + */ +auto GamebryoModDataChecker::possibleFileExtensions() const -> const FileNameSet& { + static FileNameSet result{ + "esp", "esm", "esl", "bsa", "ba2", ".modgroups" + }; + return result; +} + +GamebryoModDataChecker::GamebryoModDataChecker(const GameGamebryo* game) : m_Game(game) { } bool GamebryoModDataChecker::dataLooksValid(std::shared_ptr fileTree) const { + auto& folders = possibleFolderNames(); + auto& suffixes = possibleFileExtensions(); for (auto entry : *fileTree) { if (entry->isDir()) { - if (m_FolderNames.count(entry->name()) > 0) { + if (folders.count(entry->name()) > 0) { return true; } } else { - if (m_FileExtensions.count(entry->suffix()) > 0) { + if (suffixes.count(entry->suffix()) > 0) { return true; } } diff --git a/src/gamebryo/gamebryomoddatachecker.h b/src/gamebryo/gamebryomoddatachecker.h index dcbcd3ce..ec081fa9 100644 --- a/src/gamebryo/gamebryomoddatachecker.h +++ b/src/gamebryo/gamebryomoddatachecker.h @@ -6,51 +6,44 @@ class GameGamebryo; -class GamebryoModDataChecker: public ModDataChecker -{ - /** - * @brief Standard list of folders. - */ - static const QStringList STANDARD_FOLDERS; - - /** - * @brief Standard list of extensions. - */ - static const QStringList STANDARD_EXTENSIONS; - +/** + * @brief ModDataChecker for GameBryo games that look at folder and files in the "data" + * directory. + * + * The default implementation is game-agnostic and uses the list of folders and file extensions + * that were used before the ModDataChecker feature was added. It is possible to inherit the class + * to provide custom list of folders or filenames. + */ +class GamebryoModDataChecker: public ModDataChecker { public: /** - * @brief Construct a new mod-data checker for GameBryo games using the default - * list of possible folders and extensions. + * @brief Construct a new mod-data checker for GameBryo games. */ - GamebryoModDataChecker(const GameGamebryo* game) : - GamebryoModDataChecker(game, STANDARD_FOLDERS, STANDARD_EXTENSIONS) { } - - - /** - * @brief Construct a new mod-data checker for GameBryo games using the given - * list of possible folders and extensions. - * - * @param folders List of folders that should be found in the data folder. - * @param extensions List of extension of files that should be found in the data folder (without - * the leading dot). - */ - GamebryoModDataChecker(const GameGamebryo* game, QStringList folders, QStringList extensions); - + GamebryoModDataChecker(const GameGamebryo* game); virtual bool dataLooksValid(std::shared_ptr fileTree) const override; protected: + + using FileNameSet = std::set; + const GameGamebryo* game() const { return m_Game; } + /** + * @return the list of possible folder names in data. + */ + virtual const FileNameSet& possibleFolderNames() const; + + /** + * @return the extensions of possible files in data. + */ + virtual const FileNameSet& possibleFileExtensions() const; + private: const GameGamebryo* m_Game; - std::set m_FolderNames; - std::set m_FileExtensions; - }; #endif // GAMEBRYO_MODATACHECKER_H From ceea69807abd230f02dec483bb3d74daba734126 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Mika=C3=ABl=20Capelle?= Date: Fri, 22 May 2020 23:25:57 +0200 Subject: [PATCH 0913/1544] Make m_Game protected in ModDataChecker. --- src/gamebryo/gamebryomoddatachecker.h | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/src/gamebryo/gamebryomoddatachecker.h b/src/gamebryo/gamebryomoddatachecker.h index ec081fa9..5925c5bd 100644 --- a/src/gamebryo/gamebryomoddatachecker.h +++ b/src/gamebryo/gamebryomoddatachecker.h @@ -27,6 +27,8 @@ public: protected: + GameGamebryo const * const m_Game; + using FileNameSet = std::set; const GameGamebryo* game() const { return m_Game; } @@ -41,9 +43,6 @@ protected: */ virtual const FileNameSet& possibleFileExtensions() const; -private: - const GameGamebryo* m_Game; - }; #endif // GAMEBRYO_MODATACHECKER_H From 876994526fdfdd86fda459346ac4c9f6d6f4287e Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Mika=C3=ABl=20Capelle?= Date: Fri, 22 May 2020 23:38:08 +0200 Subject: [PATCH 0914/1544] [game_skyrimse] Add specific folders and extensions for Skyrim SE. --- src/games/skyrimse/src/gameskyrimse.cpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/games/skyrimse/src/gameskyrimse.cpp b/src/games/skyrimse/src/gameskyrimse.cpp index 66caf8ad..6f0bd5b6 100644 --- a/src/games/skyrimse/src/gameskyrimse.cpp +++ b/src/games/skyrimse/src/gameskyrimse.cpp @@ -4,11 +4,11 @@ #include "skyrimsescriptextender.h" #include "skyrimsesavegameinfo.h" #include "skyrimseunmanagedmods.h" +#include "skyrimsemoddatachecker.h" #include #include #include -#include #include #include "versioninfo.h" #include @@ -73,7 +73,7 @@ bool GameSkyrimSE::init(IOrganizer *moInfo) registerFeature(new SkyrimSEScriptExtender(this)); registerFeature(new SkyrimSEDataArchives(myGamesPath())); registerFeature(new GamebryoLocalSavegames(myGamesPath(), "Skyrimcustom.ini")); - registerFeature(new GamebryoModDataChecker(this)); + registerFeature(new SkyrimSEModDataChecker(this)); registerFeature(new SkyrimSESaveGameInfo(this)); registerFeature(new CreationGamePlugins(moInfo)); registerFeature(new SkyrimSEUnmangedMods(this)); From 6fca8cc1a723c972475d9f3a02b20feaf11ae8bf Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Mika=C3=ABl=20Capelle?= Date: Sat, 23 May 2020 11:38:33 +0200 Subject: [PATCH 0915/1544] [game_morrowind] Use a dedicated ModDataChecker. --- src/games/morrowind/src/gamemorrowind.cpp | 4 +-- .../morrowind/src/morrowindmoddatachecker.h | 29 +++++++++++++++++++ 2 files changed, 31 insertions(+), 2 deletions(-) create mode 100644 src/games/morrowind/src/morrowindmoddatachecker.h diff --git a/src/games/morrowind/src/gamemorrowind.cpp b/src/games/morrowind/src/gamemorrowind.cpp index e9faf729..75926b22 100644 --- a/src/games/morrowind/src/gamemorrowind.cpp +++ b/src/games/morrowind/src/gamemorrowind.cpp @@ -5,12 +5,12 @@ #include "morrowindgameplugins.h" #include "morrowindlocalsavegames.h" #include "morrowindsavegameinfo.h" +#include "morrowindmoddatachecker.h" #include "executableinfo.h" #include "pluginsetting.h" #include "steamutility.h" -#include #include #include @@ -43,7 +43,7 @@ bool GameMorrowind::init(IOrganizer *moInfo) registerFeature(new MorrowindBSAInvalidation(feature(), this)); registerFeature(new MorrowindSaveGameInfo(this)); registerFeature(new MorrowindLocalSavegames(this)); - registerFeature(new GamebryoModDataChecker(this)); + registerFeature(new MorrowindModDataChecker(this)); registerFeature(new MorrowindGamePlugins(moInfo)); registerFeature(new GamebryoUnmangedMods(this)); m_Organizer = moInfo; diff --git a/src/games/morrowind/src/morrowindmoddatachecker.h b/src/games/morrowind/src/morrowindmoddatachecker.h new file mode 100644 index 00000000..e0b78839 --- /dev/null +++ b/src/games/morrowind/src/morrowindmoddatachecker.h @@ -0,0 +1,29 @@ +#ifndef MORROWIND_MODATACHECKER_H +#define MORROWIND_MODATACHECKER_H + +#include + +class MorrowindModDataChecker : public GamebryoModDataChecker +{ +public: + using GamebryoModDataChecker::GamebryoModDataChecker; + +protected: + virtual const FileNameSet& possibleFolderNames() const override { + static FileNameSet result{ + "fonts", "meshes", "music", "shaders", "sound", "textures", "video", + "mwse", "distantland", "mits", "icons", "bookart", "splash" + }; + return result; + } + virtual const FileNameSet& possibleFileExtensions() const override { + static FileNameSet result{ + "esp", "esm", "bsa", ".modgroups" + }; + return result; + } + + const GameGamebryo* m_Game; +}; + +#endif // MORROWIND_MODATACHECKER_H From b5b45ff55d5194082442b4993227ecf7541ced82 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Mika=C3=ABl=20Capelle?= Date: Sat, 23 May 2020 11:38:55 +0200 Subject: [PATCH 0916/1544] [game_skyrim] Use a dedicated ModDataChecker. --- src/games/skyrim/src/gameskyrim.cpp | 4 +-- src/games/skyrim/src/skyrimmoddatachecker.h | 31 +++++++++++++++++++++ 2 files changed, 33 insertions(+), 2 deletions(-) create mode 100644 src/games/skyrim/src/skyrimmoddatachecker.h diff --git a/src/games/skyrim/src/gameskyrim.cpp b/src/games/skyrim/src/gameskyrim.cpp index 0e366ec9..49c25fd2 100644 --- a/src/games/skyrim/src/gameskyrim.cpp +++ b/src/games/skyrim/src/gameskyrim.cpp @@ -5,12 +5,12 @@ #include "skyrimdataarchives.h" #include "skyrimsavegameinfo.h" #include "skyrimgameplugins.h" +#include "skyrimmoddatachecker.h" #include "executableinfo.h" #include "pluginsetting.h" #include -#include #include #include @@ -45,7 +45,7 @@ bool GameSkyrim::init(IOrganizer *moInfo) registerFeature(new SkyrimBSAInvalidation(feature(), this)); registerFeature(new SkyrimSaveGameInfo(this)); registerFeature(new GamebryoLocalSavegames(myGamesPath(), "skyrim.ini")); - registerFeature(new GamebryoModDataChecker(this)); + registerFeature(new SkyrimModDataChecker(this)); registerFeature(new SkyrimGamePlugins(moInfo)); registerFeature(new GamebryoUnmangedMods(this)); return true; diff --git a/src/games/skyrim/src/skyrimmoddatachecker.h b/src/games/skyrim/src/skyrimmoddatachecker.h new file mode 100644 index 00000000..ad940c55 --- /dev/null +++ b/src/games/skyrim/src/skyrimmoddatachecker.h @@ -0,0 +1,31 @@ +#ifndef SKYRIM_MODATACHECKER_H +#define SKYRIM_MODATACHECKER_H + +#include + +class SkyrimModDataChecker : 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", + "skse", "distantlod", "asi", "Tools", "MCM", "distantland", "mits", + "dllplugins", "SkyProc Patchers", "CalienteTools", "NetScriptFramework", "shadersfx" + }; + return result; + } + virtual const FileNameSet& possibleFileExtensions() const override { + static FileNameSet result{ + "esp", "esm", "bsa", ".modgroups" + }; + return result; + } + + const GameGamebryo* m_Game; +}; + +#endif // SKYRIM_MODATACHECKER_H From 99f4d93be7c5c13c31f5b1c6b4d31f89ad984539 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Mika=C3=ABl=20Capelle?= Date: Sat, 23 May 2020 11:39:02 +0200 Subject: [PATCH 0917/1544] [game_skyrimse] Use a dedicated ModDataChecker. --- .../skyrimse/src/skyrimsemoddatachecker.h | 31 +++++++++++++++++++ 1 file changed, 31 insertions(+) create mode 100644 src/games/skyrimse/src/skyrimsemoddatachecker.h diff --git a/src/games/skyrimse/src/skyrimsemoddatachecker.h b/src/games/skyrimse/src/skyrimsemoddatachecker.h new file mode 100644 index 00000000..52ad0764 --- /dev/null +++ b/src/games/skyrimse/src/skyrimsemoddatachecker.h @@ -0,0 +1,31 @@ +#ifndef SKYRIMSE_MODATACHECKER_H +#define SKYRIMSE_MODATACHECKER_H + +#include + +class SkyrimSEModDataChecker : 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", + "skse", "distantlod", "asi", "Tools", "MCM", "distantland", "mits", + "dllplugins", "CalienteTools", "NetScriptFramework", "shadersfx" + }; + return result; + } + virtual const FileNameSet& possibleFileExtensions() const override { + static FileNameSet result{ + "esp", "esm", "esl", "bsa", ".modgroups" + }; + return result; + } + + const GameGamebryo *m_Game; +}; + +#endif // SKYRIMSE_MODATACHECKER_H From a27d10982cc95f4a37d5de323e381c314e0e38b8 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Mika=C3=ABl=20Capelle?= Date: Sat, 23 May 2020 11:39:27 +0200 Subject: [PATCH 0918/1544] [game_skyrimvr] Use a dedicated ModDataChecker. --- src/games/skyrimvr/src/gameskyrimvr.cpp | 4 +-- .../skyrimvr/src/skyrimvrmoddatachecker.h | 31 +++++++++++++++++++ 2 files changed, 33 insertions(+), 2 deletions(-) create mode 100644 src/games/skyrimvr/src/skyrimvrmoddatachecker.h diff --git a/src/games/skyrimvr/src/gameskyrimvr.cpp b/src/games/skyrimvr/src/gameskyrimvr.cpp index 4c8451e4..2a416f91 100644 --- a/src/games/skyrimvr/src/gameskyrimvr.cpp +++ b/src/games/skyrimvr/src/gameskyrimvr.cpp @@ -4,11 +4,11 @@ #include "skyrimvrscriptextender.h" #include "skyrimvrsavegameinfo.h" #include "skyrimvrunmanagedmods.h" +#include "skyrimvrmoddatachecker.h" #include #include #include -#include #include #include "versioninfo.h" @@ -72,7 +72,7 @@ bool GameSkyrimVR::init(IOrganizer *moInfo) registerFeature(new SkyrimVRScriptExtender(this)); registerFeature(new SkyrimVRDataArchives(myGamesPath())); registerFeature(new GamebryoLocalSavegames(myGamesPath(), "SkyrimVR.ini")); - registerFeature(new GamebryoModDataChecker(this)); + registerFeature(new SkyrimVRModDataChecker(this)); registerFeature(new SkyrimVRSaveGameInfo(this)); registerFeature(new CreationGamePlugins(moInfo)); registerFeature(new SkyrimVRUnmangedMods(this)); diff --git a/src/games/skyrimvr/src/skyrimvrmoddatachecker.h b/src/games/skyrimvr/src/skyrimvrmoddatachecker.h new file mode 100644 index 00000000..0b09db96 --- /dev/null +++ b/src/games/skyrimvr/src/skyrimvrmoddatachecker.h @@ -0,0 +1,31 @@ +#ifndef SKYRIMVR_MODATACHECKER_H +#define SKYRIMVR_MODATACHECKER_H + +#include + +class SkyrimVRModDataChecker : 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", + "skse", "distantlod", "asi", "Tools", "MCM", "distantland", "mits", + "dllplugins", "CalienteTools", "NetScriptFramework", "shadersfx" + }; + return result; + } + virtual const FileNameSet& possibleFileExtensions() const override { + static FileNameSet result{ + "esp", "esm", "bsa", ".modgroups" + }; + return result; + } + + const GameGamebryo* m_Game; +}; + +#endif // SKYRIMVR_MODATACHECKER_H From 0c34ce692cf9ec273578eb61fb8f5b2ddde3a45a Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Mika=C3=ABl=20Capelle?= Date: Sat, 23 May 2020 11:39:34 +0200 Subject: [PATCH 0919/1544] [game_oblivion] Use a dedicated ModDataChecker. --- .../oblivion/src/oblivionmoddatachecker.h | 31 +++++++++++++++++++ 1 file changed, 31 insertions(+) create mode 100644 src/games/oblivion/src/oblivionmoddatachecker.h diff --git a/src/games/oblivion/src/oblivionmoddatachecker.h b/src/games/oblivion/src/oblivionmoddatachecker.h new file mode 100644 index 00000000..277f1551 --- /dev/null +++ b/src/games/oblivion/src/oblivionmoddatachecker.h @@ -0,0 +1,31 @@ +#ifndef OBLIVION_MODATACHECKER_H +#define OBLIVION_MODATACHECKER_H + +#include + +class SkyrimSEModDataChecker : 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", + "obse", "distantlod", "asi", "distantland", "mits", "dllplugins", "CalienteTools", + "NetScriptFramework" + }; + return result; + } + virtual const FileNameSet& possibleFileExtensions() const override { + static FileNameSet result{ + "esp", "esm", "bsa", ".modgroups" + }; + return result; + } + + const GameGamebryo* m_Game; +}; + +#endif // OBLIVION_MODATACHECKER_H From 8a23b1cb8907079225e954ef0954dfe936373c84 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Mika=C3=ABl=20Capelle?= Date: Sat, 23 May 2020 11:58:38 +0200 Subject: [PATCH 0920/1544] [game_oblivion] Remove left-out attribute. --- src/games/oblivion/src/oblivionmoddatachecker.h | 2 -- 1 file changed, 2 deletions(-) diff --git a/src/games/oblivion/src/oblivionmoddatachecker.h b/src/games/oblivion/src/oblivionmoddatachecker.h index 277f1551..622fe912 100644 --- a/src/games/oblivion/src/oblivionmoddatachecker.h +++ b/src/games/oblivion/src/oblivionmoddatachecker.h @@ -24,8 +24,6 @@ protected: }; return result; } - - const GameGamebryo* m_Game; }; #endif // OBLIVION_MODATACHECKER_H From abac3904b5e5c1c8714fa880d6f26bc2a0a68893 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Mika=C3=ABl=20Capelle?= Date: Sat, 23 May 2020 11:58:44 +0200 Subject: [PATCH 0921/1544] [game_morrowind] Remove left-out attribute. --- src/games/morrowind/src/morrowindmoddatachecker.h | 2 -- 1 file changed, 2 deletions(-) diff --git a/src/games/morrowind/src/morrowindmoddatachecker.h b/src/games/morrowind/src/morrowindmoddatachecker.h index e0b78839..63ad8535 100644 --- a/src/games/morrowind/src/morrowindmoddatachecker.h +++ b/src/games/morrowind/src/morrowindmoddatachecker.h @@ -22,8 +22,6 @@ protected: }; return result; } - - const GameGamebryo* m_Game; }; #endif // MORROWIND_MODATACHECKER_H From a6c6e6e2044ea0d1a711300301e04f2ada0d47ea Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Mika=C3=ABl=20Capelle?= Date: Sat, 23 May 2020 11:58:52 +0200 Subject: [PATCH 0922/1544] [game_skyrim] Remove left-out attribute. --- src/games/skyrim/src/skyrimmoddatachecker.h | 2 -- 1 file changed, 2 deletions(-) diff --git a/src/games/skyrim/src/skyrimmoddatachecker.h b/src/games/skyrim/src/skyrimmoddatachecker.h index ad940c55..b452b218 100644 --- a/src/games/skyrim/src/skyrimmoddatachecker.h +++ b/src/games/skyrim/src/skyrimmoddatachecker.h @@ -24,8 +24,6 @@ protected: }; return result; } - - const GameGamebryo* m_Game; }; #endif // SKYRIM_MODATACHECKER_H From afa2a0875453e06aafd4c567008d3f1860a2867c Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Mika=C3=ABl=20Capelle?= Date: Sat, 23 May 2020 11:59:00 +0200 Subject: [PATCH 0923/1544] [game_skyrimse] Remove left-out attribute. --- src/games/skyrimse/src/skyrimsemoddatachecker.h | 2 -- 1 file changed, 2 deletions(-) diff --git a/src/games/skyrimse/src/skyrimsemoddatachecker.h b/src/games/skyrimse/src/skyrimsemoddatachecker.h index 52ad0764..5ceb0d47 100644 --- a/src/games/skyrimse/src/skyrimsemoddatachecker.h +++ b/src/games/skyrimse/src/skyrimsemoddatachecker.h @@ -24,8 +24,6 @@ protected: }; return result; } - - const GameGamebryo *m_Game; }; #endif // SKYRIMSE_MODATACHECKER_H From 11de06edbfdd58a208e0efe4bfbd714745552ee5 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Mika=C3=ABl=20Capelle?= Date: Sat, 23 May 2020 11:59:07 +0200 Subject: [PATCH 0924/1544] [game_skyrimvr] Remove left-out attribute. --- src/games/skyrimvr/src/skyrimvrmoddatachecker.h | 2 -- 1 file changed, 2 deletions(-) diff --git a/src/games/skyrimvr/src/skyrimvrmoddatachecker.h b/src/games/skyrimvr/src/skyrimvrmoddatachecker.h index 0b09db96..3703fbf2 100644 --- a/src/games/skyrimvr/src/skyrimvrmoddatachecker.h +++ b/src/games/skyrimvr/src/skyrimvrmoddatachecker.h @@ -24,8 +24,6 @@ protected: }; return result; } - - const GameGamebryo* m_Game; }; #endif // SKYRIMVR_MODATACHECKER_H From b976326e41d34f01394df06dea6f0437a0e6c8a8 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Mika=C3=ABl=20Capelle?= Date: Sat, 23 May 2020 12:30:50 +0200 Subject: [PATCH 0925/1544] [game_fallout3] Use a dedicated ModDataChecker. --- .../fallout3/src/fallout3moddatachecker.h | 29 +++++++++++++++++++ src/games/fallout3/src/gamefallout3.cpp | 4 +-- 2 files changed, 31 insertions(+), 2 deletions(-) create mode 100644 src/games/fallout3/src/fallout3moddatachecker.h diff --git a/src/games/fallout3/src/fallout3moddatachecker.h b/src/games/fallout3/src/fallout3moddatachecker.h new file mode 100644 index 00000000..9387c06e --- /dev/null +++ b/src/games/fallout3/src/fallout3moddatachecker.h @@ -0,0 +1,29 @@ +#ifndef FALLOUT3_MODATACHECKER_H +#define FALLOUT3_MODATACHECKER_H + +#include + +class Fallout3ModDataChecker : 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", + "fose", "distantlod", "asi", "Tools", "MCM", "distantland", "mits", + "dllplugins", "CalienteTools", "NetScriptFramework", "shadersfx" + }; + return result; + } + virtual const FileNameSet& possibleFileExtensions() const override { + static FileNameSet result{ + "esp", "esm", "bsa", ".modgroups" + }; + return result; + } +}; + +#endif // FALLOUT3_MODATACHECKER_H diff --git a/src/games/fallout3/src/gamefallout3.cpp b/src/games/fallout3/src/gamefallout3.cpp index fc547a90..bfbcc0b5 100644 --- a/src/games/fallout3/src/gamefallout3.cpp +++ b/src/games/fallout3/src/gamefallout3.cpp @@ -4,12 +4,12 @@ #include "fallout3scriptextender.h" #include "fallout3dataarchives.h" #include "fallout3savegameinfo.h" +#include "fallout3moddatachecker.h" #include "executableinfo.h" #include "pluginsetting.h" #include "versioninfo.h" #include -#include #include #include @@ -39,7 +39,7 @@ bool GameFallout3::init(IOrganizer *moInfo) registerFeature(new Fallout3BSAInvalidation(feature(), this)); registerFeature(new Fallout3SaveGameInfo(this)); registerFeature(new GamebryoLocalSavegames(myGamesPath(), "fallout.ini")); - registerFeature(new GamebryoModDataChecker(this)); + registerFeature(new Fallout3ModDataChecker(this)); registerFeature(new GamebryoGamePlugins(moInfo)); registerFeature(new GamebryoUnmangedMods(this)); return true; From 4228985609ceadaad1144a60ed56f9fc0fa45799 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Mika=C3=ABl=20Capelle?= Date: Sat, 23 May 2020 12:30:55 +0200 Subject: [PATCH 0926/1544] [game_falloutnv] Use a dedicated ModDataChecker. --- .../falloutnv/src/falloutnvmoddatachecker.h | 29 +++++++++++++++++++ src/games/falloutnv/src/gamefalloutnv.cpp | 4 +-- 2 files changed, 31 insertions(+), 2 deletions(-) create mode 100644 src/games/falloutnv/src/falloutnvmoddatachecker.h diff --git a/src/games/falloutnv/src/falloutnvmoddatachecker.h b/src/games/falloutnv/src/falloutnvmoddatachecker.h new file mode 100644 index 00000000..d80200ec --- /dev/null +++ b/src/games/falloutnv/src/falloutnvmoddatachecker.h @@ -0,0 +1,29 @@ +#ifndef FALLOUTNV_MODATACHECKER_H +#define FALLOUTNV_MODATACHECKER_H + +#include + +class FalloutNVModDataChecker : 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", "NetScriptFramework", "shadersfx" + }; + return result; + } + virtual const FileNameSet& possibleFileExtensions() const override { + static FileNameSet result{ + "esp", "esm", "bsa", ".modgroups" + }; + return result; + } +}; + +#endif // FALLOUTNV_MODATACHECKER_H diff --git a/src/games/falloutnv/src/gamefalloutnv.cpp b/src/games/falloutnv/src/gamefalloutnv.cpp index fb839488..db46a5ce 100644 --- a/src/games/falloutnv/src/gamefalloutnv.cpp +++ b/src/games/falloutnv/src/gamefalloutnv.cpp @@ -4,12 +4,12 @@ #include "falloutnvdataarchives.h" #include "falloutnvsavegameinfo.h" #include "falloutnvscriptextender.h" +#include "falloutnvmoddatachecker.h" #include "executableinfo.h" #include "pluginsetting.h" #include "versioninfo.h" #include -#include #include #include @@ -39,7 +39,7 @@ bool GameFalloutNV::init(IOrganizer *moInfo) registerFeature(new FalloutNVBSAInvalidation(feature(), this)); registerFeature(new FalloutNVSaveGameInfo(this)); registerFeature(new GamebryoLocalSavegames(myGamesPath(), "fallout.ini")); - registerFeature(new GamebryoModDataChecker(this)); + registerFeature(new FalloutNVModDataChecker(this)); registerFeature(new GamebryoGamePlugins(moInfo)); registerFeature(new GamebryoUnmangedMods(this)); return true; From 1ce1f6a1a036f5042a5d73896cc6e0377ff5508e Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Mika=C3=ABl=20Capelle?= Date: Sat, 23 May 2020 12:31:04 +0200 Subject: [PATCH 0927/1544] [game_ttw] Use a dedicated ModDataChecker. --- src/games/ttw/src/falloutttwmoddatachecker.h | 29 ++++++++++++++++++++ src/games/ttw/src/gamefalloutttw.cpp | 4 +-- 2 files changed, 31 insertions(+), 2 deletions(-) create mode 100644 src/games/ttw/src/falloutttwmoddatachecker.h diff --git a/src/games/ttw/src/falloutttwmoddatachecker.h b/src/games/ttw/src/falloutttwmoddatachecker.h new file mode 100644 index 00000000..723b2454 --- /dev/null +++ b/src/games/ttw/src/falloutttwmoddatachecker.h @@ -0,0 +1,29 @@ +#ifndef FALLOUTTTW_MODATACHECKER_H +#define FALLOUTTTW_MODATACHECKER_H + +#include + +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", "NetScriptFramework", "shadersfx" + }; + return result; + } + virtual const FileNameSet& possibleFileExtensions() const override { + static FileNameSet result{ + "esp", "esm", "bsa", ".modgroups" + }; + return result; + } +}; + +#endif // FALLOUTTTW_MODATACHECKER_H diff --git a/src/games/ttw/src/gamefalloutttw.cpp b/src/games/ttw/src/gamefalloutttw.cpp index 64de5245..f4296c25 100644 --- a/src/games/ttw/src/gamefalloutttw.cpp +++ b/src/games/ttw/src/gamefalloutttw.cpp @@ -4,12 +4,12 @@ #include "falloutttwdataarchives.h" #include "falloutttwsavegameinfo.h" #include "falloutttwscriptextender.h" +#include "falloutttwmoddatachecker.h" #include "executableinfo.h" #include "pluginsetting.h" #include "versioninfo.h" #include -#include #include #include @@ -41,7 +41,7 @@ bool GameFalloutTTW::init(IOrganizer *moInfo) registerFeature(new FalloutTTWBSAInvalidation(feature(), this)); registerFeature(new FalloutTTWSaveGameInfo(this)); registerFeature(new GamebryoLocalSavegames(myGamesPath(), "fallout.ini")); - registerFeature(new GamebryoModDataChecker(this)); + registerFeature(new FalloutTTWModDataChecker(this)); registerFeature(new GamebryoGamePlugins(moInfo)); registerFeature(new GamebryoUnmangedMods(this)); return true; From f70c20c74c20496301544ad4a5e364cccdade2f7 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Mika=C3=ABl=20Capelle?= Date: Sat, 23 May 2020 23:09:29 +0200 Subject: [PATCH 0928/1544] [game_fallout4vr] Custom ModDataChecker for Fallout 4 VR (#13) * Add ModDataChecker feeature (generic). * Use a dedicated ModDataChecker. * Remove ESL as a possible file extension. --- .../fallout4vr/src/fallout4vrmoddatachecker.h | 29 +++++++++++++++++++ src/games/fallout4vr/src/gamefallout4vr.cpp | 2 ++ 2 files changed, 31 insertions(+) create mode 100644 src/games/fallout4vr/src/fallout4vrmoddatachecker.h diff --git a/src/games/fallout4vr/src/fallout4vrmoddatachecker.h b/src/games/fallout4vr/src/fallout4vrmoddatachecker.h new file mode 100644 index 00000000..760f7aa2 --- /dev/null +++ b/src/games/fallout4vr/src/fallout4vrmoddatachecker.h @@ -0,0 +1,29 @@ +#ifndef FALLOUT4VR_MODATACHECKER_H +#define FALLOUT4VR_MODATACHECKER_H + +#include + +class Fallout4VRModDataChecker : public GamebryoModDataChecker +{ +public: + using GamebryoModDataChecker::GamebryoModDataChecker; + +protected: + virtual const FileNameSet& possibleFolderNames() const override { + static FileNameSet result{ + "interface", "meshes", "music", "scripts", "sound", "strings", "textures", + "trees", "video", "materials", "f4se", "distantlod", "asi", "Tools", "MCM", + "distantland", "mits", "dllplugins", "CalienteTools", "NetScriptFramework", + "shadersfx", "aaf" + }; + return result; + } + virtual const FileNameSet& possibleFileExtensions() const override { + static FileNameSet result{ + "esp", "esm", "ba2", ".modgroups" + }; + return result; + } +}; + +#endif // FALLOUT4VR_MODATACHECKER_H diff --git a/src/games/fallout4vr/src/gamefallout4vr.cpp b/src/games/fallout4vr/src/gamefallout4vr.cpp index 9a257fef..b6e023d9 100644 --- a/src/games/fallout4vr/src/gamefallout4vr.cpp +++ b/src/games/fallout4vr/src/gamefallout4vr.cpp @@ -3,6 +3,7 @@ #include "fallout4vrdataarchives.h" #include "fallout4vrsavegameinfo.h" #include "fallout4vrunmanagedmods.h" +#include "fallout4vrmoddatachecker.h" #include #include @@ -38,6 +39,7 @@ bool GameFallout4VR::init(IOrganizer *moInfo) registerFeature(new Fallout4VRDataArchives(myGamesPath())); registerFeature(new GamebryoLocalSavegames(myGamesPath(), "fallout4custom.ini")); + registerFeature(new Fallout4VRModDataChecker(this)); registerFeature(new Fallout4VRSaveGameInfo(this)); registerFeature(new CreationGamePlugins(moInfo)); registerFeature(new Fallout4VRUnmangedMods(this)); From 36583fea9fde4c3480ae6df7c436fb1fd0f84291 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Mika=C3=ABl=20Capelle?= Date: Sat, 23 May 2020 23:09:40 +0200 Subject: [PATCH 0929/1544] [game_fallout4] Custom ModDataChecker for Fallout 4 (#12) * Add ModDataChecker feeature (generic). * Use a dedicated ModDataChecker. --- .../fallout4/src/fallout4moddatachecker.h | 29 +++++++++++++++++++ src/games/fallout4/src/gamefallout4.cpp | 2 ++ 2 files changed, 31 insertions(+) create mode 100644 src/games/fallout4/src/fallout4moddatachecker.h diff --git a/src/games/fallout4/src/fallout4moddatachecker.h b/src/games/fallout4/src/fallout4moddatachecker.h new file mode 100644 index 00000000..7b48c551 --- /dev/null +++ b/src/games/fallout4/src/fallout4moddatachecker.h @@ -0,0 +1,29 @@ +#ifndef FALLOUT4_MODATACHECKER_H +#define FALLOUT4_MODATACHECKER_H + +#include + +class Fallout4ModDataChecker : public GamebryoModDataChecker +{ +public: + using GamebryoModDataChecker::GamebryoModDataChecker; + +protected: + virtual const FileNameSet& possibleFolderNames() const override { + static FileNameSet result{ + "interface", "meshes", "music", "scripts", "sound", "strings", "textures", + "trees", "video", "materials", "f4se", "distantlod", "asi", "Tools", "MCM", + "distantland", "mits", "dllplugins", "CalienteTools", "NetScriptFramework", + "shadersfx", "aaf" + }; + return result; + } + virtual const FileNameSet& possibleFileExtensions() const override { + static FileNameSet result{ + "esp", "esm", "esl", "ba2", ".modgroups" + }; + return result; + } +}; + +#endif // FALLOUT4_MODATACHECKER_H diff --git a/src/games/fallout4/src/gamefallout4.cpp b/src/games/fallout4/src/gamefallout4.cpp index 0777f1d4..deb1248b 100644 --- a/src/games/fallout4/src/gamefallout4.cpp +++ b/src/games/fallout4/src/gamefallout4.cpp @@ -4,6 +4,7 @@ #include "fallout4scriptextender.h" #include "fallout4savegameinfo.h" #include "fallout4unmanagedmods.h" +#include "fallout4moddatachecker.h" #include #include @@ -38,6 +39,7 @@ bool GameFallout4::init(IOrganizer *moInfo) registerFeature(new Fallout4ScriptExtender(this)); registerFeature(new Fallout4DataArchives(myGamesPath())); registerFeature(new GamebryoLocalSavegames(myGamesPath(), "fallout4custom.ini")); + registerFeature(new Fallout4ModDataChecker(this)); registerFeature(new Fallout4SaveGameInfo(this)); registerFeature(new CreationGamePlugins(moInfo)); registerFeature(new Fallout4UnmangedMods(this)); From 326e46de010a1da9c8ff9d3923fe65363f33f3e1 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Mika=C3=ABl=20Capelle?= Date: Mon, 25 May 2020 18:53:25 +0200 Subject: [PATCH 0930/1544] Add ModDataContent feature for GameBryo. --- src/gamebryo/gamebryomoddatacontent.cpp | 75 +++++++++++++++++++++++++ src/gamebryo/gamebryomoddatacontent.h | 58 +++++++++++++++++++ 2 files changed, 133 insertions(+) create mode 100644 src/gamebryo/gamebryomoddatacontent.cpp create mode 100644 src/gamebryo/gamebryomoddatacontent.h diff --git a/src/gamebryo/gamebryomoddatacontent.cpp b/src/gamebryo/gamebryomoddatacontent.cpp new file mode 100644 index 00000000..a071b695 --- /dev/null +++ b/src/gamebryo/gamebryomoddatacontent.cpp @@ -0,0 +1,75 @@ +#include "gamebryomoddatacontent.h" + +#include + +#include "gamegamebryo.h" + +std::vector GamebryoModDataContent::getAllContents() const { + return { + {CONTENT_PLUGIN, ":/MO/gui/content/plugin", QT_TR_NOOP("Game Plugins (ESP/ESM/ESL)")}, + {CONTENT_INTERFACE, ":/MO/gui/content/interface", QT_TR_NOOP("Interface")}, + {CONTENT_MESH, ":/MO/gui/content/mesh", QT_TR_NOOP("Meshes")}, + {CONTENT_BSA, ":/MO/gui/content/bsa", QT_TR_NOOP("Bethesda Archive")}, + {CONTENT_SCRIPT, ":/MO/gui/content/script", QT_TR_NOOP("Scripts (Papyrus)")}, + {CONTENT_SKSE, ":/MO/gui/content/skse", QT_TR_NOOP("Script Extender Plugin")}, + {CONTENT_SKYPROC, ":/MO/gui/content/skyproc", QT_TR_NOOP("SkyProc Patcher")}, + {CONTENT_SOUND, ":/MO/gui/content/sound", QT_TR_NOOP("Sound or Music")}, + {CONTENT_TEXTURE, ":/MO/gui/content/texture", QT_TR_NOOP("Textures")}, + {CONTENT_MCM, ":/MO/gui/content/menu", QT_TR_NOOP("MCM Configuration")}, + {CONTENT_INI, ":/MO/gui/content/inifile", QT_TR_NOOP("INI files")}, + {CONTENT_MODGROUP, ":/MO/gui/content/modgroup", QT_TR_NOOP("ModGroup files")} + }; +} + +std::vector GamebryoModDataContent::getContentsFor(std::shared_ptr fileTree) const { + std::vector contents; + + for (auto e : *fileTree) { + if (e->isFile()) { + auto suffix = e->suffix().toLower(); + if (suffix == "esp" || suffix == "esm" || suffix == "esl") { + contents.push_back(CONTENT_PLUGIN); + } + else if (suffix == "bsa" || suffix == "ba2") { + contents.push_back(CONTENT_BSA); + } + else if (suffix == "ini" && e->compare("meta.ini") != 0) { + contents.push_back(CONTENT_INI); + } + else if (suffix == "modgroups") { + contents.push_back(CONTENT_MODGROUP); + } + } + else { + if (e->compare("textures") == 0 || e->compare("icons") == 0 || e->compare("bookart") == 0) + contents.push_back(CONTENT_TEXTURE); + if (e->compare("meshes") == 0) + contents.push_back(CONTENT_MESH); + if (e->compare("interface") == 0 || e->compare("menus") == 0) + contents.push_back(CONTENT_INTERFACE); + if (e->compare("music") == 0 || e->compare("sound") == 0) + contents.push_back(CONTENT_SOUND); + if (e->compare("scripts") == 0) + contents.push_back(CONTENT_SCRIPT); + if (e->compare("SkyProc Patchers") == 0) + contents.push_back(CONTENT_SKYPROC); + if (e->compare("MCM") == 0) + contents.push_back(CONTENT_MCM); + } + } + + ScriptExtender* extender = m_GamePlugin->feature(); + if (extender != nullptr) { + auto e = fileTree->findDirectory(extender->PluginPath()); + if (e) { + for (auto f : *e) { + if (f->hasSuffix("dll")) { + contents.push_back(CONTENT_SKSE); + break; + } + } + } + } + + return contents; +} \ No newline at end of file diff --git a/src/gamebryo/gamebryomoddatacontent.h b/src/gamebryo/gamebryomoddatacontent.h new file mode 100644 index 00000000..e398e659 --- /dev/null +++ b/src/gamebryo/gamebryomoddatacontent.h @@ -0,0 +1,58 @@ +#ifndef GAMEBRYO_MODDATACONTENT_H +#define GAMEBRYO_MODDATACONTENT_H + +#include +#include + +class GameGamebryo; + +/** + * @brief ModDataContent for GameBryo games. + * + */ +class GamebryoModDataContent : public ModDataContent { +protected: + + enum EContent { + CONTENT_PLUGIN, + CONTENT_TEXTURE, + CONTENT_MESH, + CONTENT_BSA, + CONTENT_INTERFACE, + CONTENT_SOUND, + CONTENT_SCRIPT, + CONTENT_SKSE, + CONTENT_SKYPROC, + CONTENT_MCM, + CONTENT_INI, + CONTENT_MODGROUP + }; + +public: + + /** + * + */ + GamebryoModDataContent(GameGamebryo const* gamePlugin) : m_GamePlugin{gamePlugin} { } + + /** + * @return the list of all possible contents for the corresponding game. + */ + virtual std::vector getAllContents() const override; + + /** + * @brief Retrieve the list of contents in the given tree. + * + * @param fileTree The tree corresponding to the mod to retrieve contents for. + * + * @return the IDs of the content in the given tree. + */ + virtual std::vector getContentsFor(std::shared_ptr fileTree) const override; + +protected: + + GameGamebryo const* const m_GamePlugin; + +}; + +#endif // GAMEBRYO_MODDATACONTENT_H From 6f45df9bb938dbb540e2af7d055f62b89c83c983 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Mika=C3=ABl=20Capelle?= Date: Mon, 25 May 2020 19:45:26 +0200 Subject: [PATCH 0931/1544] Fix order of argument in Content(). --- src/gamebryo/gamebryomoddatacontent.cpp | 24 ++++++++++++------------ 1 file changed, 12 insertions(+), 12 deletions(-) diff --git a/src/gamebryo/gamebryomoddatacontent.cpp b/src/gamebryo/gamebryomoddatacontent.cpp index a071b695..5cc1ec11 100644 --- a/src/gamebryo/gamebryomoddatacontent.cpp +++ b/src/gamebryo/gamebryomoddatacontent.cpp @@ -6,18 +6,18 @@ std::vector GamebryoModDataContent::getAllContents() const { return { - {CONTENT_PLUGIN, ":/MO/gui/content/plugin", QT_TR_NOOP("Game Plugins (ESP/ESM/ESL)")}, - {CONTENT_INTERFACE, ":/MO/gui/content/interface", QT_TR_NOOP("Interface")}, - {CONTENT_MESH, ":/MO/gui/content/mesh", QT_TR_NOOP("Meshes")}, - {CONTENT_BSA, ":/MO/gui/content/bsa", QT_TR_NOOP("Bethesda Archive")}, - {CONTENT_SCRIPT, ":/MO/gui/content/script", QT_TR_NOOP("Scripts (Papyrus)")}, - {CONTENT_SKSE, ":/MO/gui/content/skse", QT_TR_NOOP("Script Extender Plugin")}, - {CONTENT_SKYPROC, ":/MO/gui/content/skyproc", QT_TR_NOOP("SkyProc Patcher")}, - {CONTENT_SOUND, ":/MO/gui/content/sound", QT_TR_NOOP("Sound or Music")}, - {CONTENT_TEXTURE, ":/MO/gui/content/texture", QT_TR_NOOP("Textures")}, - {CONTENT_MCM, ":/MO/gui/content/menu", QT_TR_NOOP("MCM Configuration")}, - {CONTENT_INI, ":/MO/gui/content/inifile", QT_TR_NOOP("INI files")}, - {CONTENT_MODGROUP, ":/MO/gui/content/modgroup", QT_TR_NOOP("ModGroup files")} + {CONTENT_PLUGIN, QT_TR_NOOP("Game Plugins (ESP/ESM/ESL)"), ":/MO/gui/content/plugin"}, + {CONTENT_INTERFACE, QT_TR_NOOP("Interface"), ":/MO/gui/content/interface"}, + {CONTENT_MESH, QT_TR_NOOP("Meshes"), ":/MO/gui/content/mesh"}, + {CONTENT_BSA, QT_TR_NOOP("Bethesda Archive"), ":/MO/gui/content/bsa"}, + {CONTENT_SCRIPT, QT_TR_NOOP("Scripts (Papyrus)"), ":/MO/gui/content/script"}, + {CONTENT_SKSE, QT_TR_NOOP("Script Extender Plugin"), ":/MO/gui/content/skse"}, + {CONTENT_SKYPROC, QT_TR_NOOP("SkyProc Patcher"), ":/MO/gui/content/skyproc"}, + {CONTENT_SOUND, QT_TR_NOOP("Sound or Music"), ":/MO/gui/content/sound"}, + {CONTENT_TEXTURE, QT_TR_NOOP("Textures"), ":/MO/gui/content/texture"}, + {CONTENT_MCM, QT_TR_NOOP("MCM Configuration"), ":/MO/gui/content/menu"}, + {CONTENT_INI, QT_TR_NOOP("INI files"), ":/MO/gui/content/inifile"}, + {CONTENT_MODGROUP, QT_TR_NOOP("ModGroup files"), ":/MO/gui/content/modgroup"} }; } From 8777fe47214c36ebb51749f58914b1d68a8ae8f8 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Mika=C3=ABl=20Capelle?= Date: Tue, 26 May 2020 21:27:13 +0200 Subject: [PATCH 0932/1544] Set GamebryoModDataContent as default and allow child class to disable contents. --- src/gamebryo/gamebryomoddatacontent.cpp | 42 +++++++++++++++++-------- src/gamebryo/gamebryomoddatacontent.h | 9 +++++- src/gamebryo/gamegamebryo.cpp | 2 ++ 3 files changed, 39 insertions(+), 14 deletions(-) diff --git a/src/gamebryo/gamebryomoddatacontent.cpp b/src/gamebryo/gamebryomoddatacontent.cpp index 5cc1ec11..f0947782 100644 --- a/src/gamebryo/gamebryomoddatacontent.cpp +++ b/src/gamebryo/gamebryomoddatacontent.cpp @@ -4,8 +4,11 @@ #include "gamegamebryo.h" +GamebryoModDataContent::GamebryoModDataContent(GameGamebryo const* gamePlugin) : + m_GamePlugin(gamePlugin), m_Enabled(CONTENT_MODGROUP, true) { } + std::vector GamebryoModDataContent::getAllContents() const { - return { + static std::vector GAMEBRYO_CONTENTS{ {CONTENT_PLUGIN, QT_TR_NOOP("Game Plugins (ESP/ESM/ESL)"), ":/MO/gui/content/plugin"}, {CONTENT_INTERFACE, QT_TR_NOOP("Interface"), ":/MO/gui/content/interface"}, {CONTENT_MESH, QT_TR_NOOP("Meshes"), ":/MO/gui/content/mesh"}, @@ -19,6 +22,12 @@ std::vector GamebryoModDataContent::getAllConte {CONTENT_INI, QT_TR_NOOP("INI files"), ":/MO/gui/content/inifile"}, {CONTENT_MODGROUP, QT_TR_NOOP("ModGroup files"), ":/MO/gui/content/modgroup"} }; + + // Copy the list of enabled contents: + std::vector contents; + std::copy_if(std::begin(GAMEBRYO_CONTENTS), std::end(GAMEBRYO_CONTENTS), + std::back_inserter(contents), [this](auto e) { return m_Enabled[e.id()]; }); + return contents; } std::vector GamebryoModDataContent::getContentsFor(std::shared_ptr fileTree) const { @@ -27,39 +36,46 @@ std::vector GamebryoModDataContent::getContentsFor(std::shared_ptrisFile()) { auto suffix = e->suffix().toLower(); - if (suffix == "esp" || suffix == "esm" || suffix == "esl") { + if (m_Enabled[CONTENT_PLUGIN] && (suffix == "esp" || suffix == "esm" || suffix == "esl")) { contents.push_back(CONTENT_PLUGIN); } - else if (suffix == "bsa" || suffix == "ba2") { + else if (m_Enabled[CONTENT_BSA] && (suffix == "bsa" || suffix == "ba2")) { contents.push_back(CONTENT_BSA); } - else if (suffix == "ini" && e->compare("meta.ini") != 0) { + else if (m_Enabled[CONTENT_INI] && suffix == "ini" && e->compare("meta.ini") != 0) { contents.push_back(CONTENT_INI); } - else if (suffix == "modgroups") { + else if (m_Enabled[CONTENT_MODGROUP] && suffix == "modgroups") { contents.push_back(CONTENT_MODGROUP); } } else { - if (e->compare("textures") == 0 || e->compare("icons") == 0 || e->compare("bookart") == 0) + if (m_Enabled[CONTENT_TEXTURE] && (e->compare("textures") == 0 || e->compare("icons") == 0 || e->compare("bookart") == 0)) { contents.push_back(CONTENT_TEXTURE); - if (e->compare("meshes") == 0) + } + else if (m_Enabled[CONTENT_MESH] && e->compare("meshes") == 0) { contents.push_back(CONTENT_MESH); - if (e->compare("interface") == 0 || e->compare("menus") == 0) + } + else if (m_Enabled[CONTENT_INTERFACE] && (e->compare("interface") == 0 || e->compare("menus") == 0)) { contents.push_back(CONTENT_INTERFACE); - if (e->compare("music") == 0 || e->compare("sound") == 0) + } + else if (m_Enabled[CONTENT_SOUND] && e->compare("music") == 0 || e->compare("sound") == 0) { contents.push_back(CONTENT_SOUND); - if (e->compare("scripts") == 0) + } + else if (m_Enabled[CONTENT_SCRIPT] && e->compare("scripts") == 0) { contents.push_back(CONTENT_SCRIPT); - if (e->compare("SkyProc Patchers") == 0) + } + else if (m_Enabled[CONTENT_SKYPROC] && e->compare("SkyProc Patchers") == 0) { contents.push_back(CONTENT_SKYPROC); - if (e->compare("MCM") == 0) + } + else if (m_Enabled[CONTENT_MCM] && e->compare("MCM") == 0) { contents.push_back(CONTENT_MCM); + } } } ScriptExtender* extender = m_GamePlugin->feature(); - if (extender != nullptr) { + if (m_Enabled[CONTENT_SKSE] && extender != nullptr) { auto e = fileTree->findDirectory(extender->PluginPath()); if (e) { for (auto f : *e) { diff --git a/src/gamebryo/gamebryomoddatacontent.h b/src/gamebryo/gamebryomoddatacontent.h index e398e659..f791560a 100644 --- a/src/gamebryo/gamebryomoddatacontent.h +++ b/src/gamebryo/gamebryomoddatacontent.h @@ -13,6 +13,10 @@ class GameGamebryo; class GamebryoModDataContent : public ModDataContent { protected: + /** + * Note: These are used to index m_Contents so should have standard + * enum values, not custom ones. + */ enum EContent { CONTENT_PLUGIN, CONTENT_TEXTURE, @@ -33,7 +37,7 @@ public: /** * */ - GamebryoModDataContent(GameGamebryo const* gamePlugin) : m_GamePlugin{gamePlugin} { } + GamebryoModDataContent(GameGamebryo const* gamePlugin); /** * @return the list of all possible contents for the corresponding game. @@ -53,6 +57,9 @@ protected: GameGamebryo const* const m_GamePlugin; + // List of enabled contents: + std::vector m_Enabled; + }; #endif // GAMEBRYO_MODDATACONTENT_H diff --git a/src/gamebryo/gamegamebryo.cpp b/src/gamebryo/gamegamebryo.cpp index 35199ac2..852a5d83 100644 --- a/src/gamebryo/gamegamebryo.cpp +++ b/src/gamebryo/gamegamebryo.cpp @@ -6,6 +6,7 @@ #include "scriptextender.h" #include "scopeguard.h" #include "utility.h" +#include "gamebryomoddatacontent.h" #include #include @@ -33,6 +34,7 @@ bool GameGamebryo::init(MOBase::IOrganizer *moInfo) { m_GamePath = identifyGamePath(); m_MyGamesPath = determineMyGamesPath(gameShortName()); + registerFeature(new GamebryoModDataContent(this)); m_Organizer = moInfo; return true; } From 4cec11b6c74ec22c414942d7ae10b0882bc94148 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Mika=C3=ABl=20Capelle?= Date: Tue, 26 May 2020 21:27:46 +0200 Subject: [PATCH 0933/1544] [game_morrowind] Custom ModDataContent for Morrowind. --- src/games/morrowind/src/gamemorrowind.cpp | 2 ++ .../morrowind/src/morrowindmoddatacontent.h | 23 +++++++++++++++++++ 2 files changed, 25 insertions(+) create mode 100644 src/games/morrowind/src/morrowindmoddatacontent.h diff --git a/src/games/morrowind/src/gamemorrowind.cpp b/src/games/morrowind/src/gamemorrowind.cpp index 75926b22..841c1968 100644 --- a/src/games/morrowind/src/gamemorrowind.cpp +++ b/src/games/morrowind/src/gamemorrowind.cpp @@ -6,6 +6,7 @@ #include "morrowindlocalsavegames.h" #include "morrowindsavegameinfo.h" #include "morrowindmoddatachecker.h" +#include "morrowindmoddatacontent.h" #include "executableinfo.h" #include "pluginsetting.h" @@ -44,6 +45,7 @@ bool GameMorrowind::init(IOrganizer *moInfo) registerFeature(new MorrowindSaveGameInfo(this)); registerFeature(new MorrowindLocalSavegames(this)); registerFeature(new MorrowindModDataChecker(this)); + registerFeature(new MorrowindModDataContent(this)); registerFeature(new MorrowindGamePlugins(moInfo)); registerFeature(new GamebryoUnmangedMods(this)); m_Organizer = moInfo; diff --git a/src/games/morrowind/src/morrowindmoddatacontent.h b/src/games/morrowind/src/morrowindmoddatacontent.h new file mode 100644 index 00000000..f52ce0a1 --- /dev/null +++ b/src/games/morrowind/src/morrowindmoddatacontent.h @@ -0,0 +1,23 @@ +#ifndef MORROWIND_MODDATACONTENT_H +#define MORROWIND_MODDATACONTENT_H + +#include +#include + +class MorrowindModDataContent : public GamebryoModDataContent { +public: + + /** + * + */ + MorrowindModDataContent(GameGamebryo const* gamePlugin) : GamebryoModDataContent(gamePlugin) { + // Just need to disable some contents: + m_Enabled[CONTENT_MCM] = false; + m_Enabled[CONTENT_SKYPROC] = false; + m_Enabled[CONTENT_INTERFACE] = false; + m_Enabled[CONTENT_SCRIPT] = false; + } + +}; + +#endif // MORROWIND_MODDATACONTENT_H From 53c396d3354b244b880e8b0267010782b7fcaaec Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Mika=C3=ABl=20Capelle?= Date: Tue, 26 May 2020 21:35:15 +0200 Subject: [PATCH 0934/1544] Delete previous game features when new ones are registered. --- src/gamebryo/gamegamebryo.h | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/src/gamebryo/gamegamebryo.h b/src/gamebryo/gamegamebryo.h index 841e7e8a..ccba6ac9 100644 --- a/src/gamebryo/gamegamebryo.h +++ b/src/gamebryo/gamegamebryo.h @@ -112,7 +112,7 @@ protected: protected: - std::map featureList() const; + std::map featureList() const override; //These should be implemented by anything that uses gamebryo (I think) //(and if they don't, it'll be a null pointer and won't look implemented, @@ -128,6 +128,10 @@ protected: template void registerFeature(T *type) { + auto index = std::type_index(typeid(T)); + if (m_FeatureList.find(index) != m_FeatureList.end()) { + delete boost::any_cast(m_FeatureList[index]); + } m_FeatureList[std::type_index(typeid(T))] = type; } From 7d7466aecd059ffdfb64ce30112bf7edf6d4a461 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Mika=C3=ABl=20Capelle?= Date: Tue, 26 May 2020 21:42:04 +0200 Subject: [PATCH 0935/1544] [game_fallout3] Custom ModDataContent. --- .../fallout3/src/fallout3moddatacontent.h | 21 +++++++++++++++++++ src/games/fallout3/src/gamefallout3.cpp | 2 ++ 2 files changed, 23 insertions(+) create mode 100644 src/games/fallout3/src/fallout3moddatacontent.h diff --git a/src/games/fallout3/src/fallout3moddatacontent.h b/src/games/fallout3/src/fallout3moddatacontent.h new file mode 100644 index 00000000..5b99dd05 --- /dev/null +++ b/src/games/fallout3/src/fallout3moddatacontent.h @@ -0,0 +1,21 @@ +#ifndef FALLOUT3_MODDATACONTENT_H +#define FALLOUT3_MODDATACONTENT_H + +#include +#include + +class Fallout3ModDataContent : public GamebryoModDataContent { +public: + + /** + * + */ + Fallout3ModDataContent(GameGamebryo const* gamePlugin) : GamebryoModDataContent(gamePlugin) { + // Just need to disable some contents: + m_Enabled[CONTENT_MCM] = false; + m_Enabled[CONTENT_SKYPROC] = false; + } + +}; + +#endif // FALLOUT3_MODDATACONTENT_H diff --git a/src/games/fallout3/src/gamefallout3.cpp b/src/games/fallout3/src/gamefallout3.cpp index bfbcc0b5..33125d70 100644 --- a/src/games/fallout3/src/gamefallout3.cpp +++ b/src/games/fallout3/src/gamefallout3.cpp @@ -5,6 +5,7 @@ #include "fallout3dataarchives.h" #include "fallout3savegameinfo.h" #include "fallout3moddatachecker.h" +#include "fallout3moddatacontent.h" #include "executableinfo.h" #include "pluginsetting.h" @@ -40,6 +41,7 @@ bool GameFallout3::init(IOrganizer *moInfo) registerFeature(new Fallout3SaveGameInfo(this)); registerFeature(new GamebryoLocalSavegames(myGamesPath(), "fallout.ini")); registerFeature(new Fallout3ModDataChecker(this)); + registerFeature(new Fallout3ModDataContent(this)); registerFeature(new GamebryoGamePlugins(moInfo)); registerFeature(new GamebryoUnmangedMods(this)); return true; From b8a482d5a58fb1a15509c251138c867f500d87ae Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Mika=C3=ABl=20Capelle?= Date: Tue, 26 May 2020 21:43:01 +0200 Subject: [PATCH 0936/1544] [game_falloutnv] Custom ModDataContent. --- .../falloutnv/src/falloutnvmoddatacontent.h | 21 +++++++++++++++++++ src/games/falloutnv/src/gamefalloutnv.cpp | 2 ++ 2 files changed, 23 insertions(+) create mode 100644 src/games/falloutnv/src/falloutnvmoddatacontent.h diff --git a/src/games/falloutnv/src/falloutnvmoddatacontent.h b/src/games/falloutnv/src/falloutnvmoddatacontent.h new file mode 100644 index 00000000..6d66bf8e --- /dev/null +++ b/src/games/falloutnv/src/falloutnvmoddatacontent.h @@ -0,0 +1,21 @@ +#ifndef FALLOUTNV_MODDATACONTENT_H +#define FALLOUTNV_MODDATACONTENT_H + +#include +#include + +class FalloutNVModDataContent : public GamebryoModDataContent { +public: + + /** + * + */ + FalloutNVModDataContent(GameGamebryo const* gamePlugin) : GamebryoModDataContent(gamePlugin) { + // Just need to disable some contents: + m_Enabled[CONTENT_MCM] = false; + m_Enabled[CONTENT_SKYPROC] = false; + } + +}; + +#endif // FALLOUTNV_MODDATACONTENT_H diff --git a/src/games/falloutnv/src/gamefalloutnv.cpp b/src/games/falloutnv/src/gamefalloutnv.cpp index db46a5ce..da5026ef 100644 --- a/src/games/falloutnv/src/gamefalloutnv.cpp +++ b/src/games/falloutnv/src/gamefalloutnv.cpp @@ -5,6 +5,7 @@ #include "falloutnvsavegameinfo.h" #include "falloutnvscriptextender.h" #include "falloutnvmoddatachecker.h" +#include "falloutnvmoddatacontent.h" #include "executableinfo.h" #include "pluginsetting.h" @@ -40,6 +41,7 @@ bool GameFalloutNV::init(IOrganizer *moInfo) registerFeature(new FalloutNVSaveGameInfo(this)); registerFeature(new GamebryoLocalSavegames(myGamesPath(), "fallout.ini")); registerFeature(new FalloutNVModDataChecker(this)); + registerFeature(new FalloutNVModDataContent(this)); registerFeature(new GamebryoGamePlugins(moInfo)); registerFeature(new GamebryoUnmangedMods(this)); return true; From 15f393f2e0b73bd90d3d3cd33727e5d7e4d2ee9d Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Mika=C3=ABl=20Capelle?= Date: Tue, 26 May 2020 21:43:30 +0200 Subject: [PATCH 0937/1544] [game_ttw] Custom ModDataContent. --- src/games/ttw/src/falloutttwmoddatacontent.h | 21 ++++++++++++++++++++ src/games/ttw/src/gamefalloutttw.cpp | 2 ++ 2 files changed, 23 insertions(+) create mode 100644 src/games/ttw/src/falloutttwmoddatacontent.h diff --git a/src/games/ttw/src/falloutttwmoddatacontent.h b/src/games/ttw/src/falloutttwmoddatacontent.h new file mode 100644 index 00000000..4c85d899 --- /dev/null +++ b/src/games/ttw/src/falloutttwmoddatacontent.h @@ -0,0 +1,21 @@ +#ifndef FALLOUTTTW_MODDATACONTENT_H +#define FALLOUTTTW_MODDATACONTENT_H + +#include +#include + +class FalloutTTWModDataContent : public GamebryoModDataContent { +public: + + /** + * + */ + FalloutTTWModDataContent(GameGamebryo const* gamePlugin) : GamebryoModDataContent(gamePlugin) { + // Just need to disable some contents: + m_Enabled[CONTENT_MCM] = false; + m_Enabled[CONTENT_SKYPROC] = false; + } + +}; + +#endif // FALLOUTTTW_MODDATACONTENT_H diff --git a/src/games/ttw/src/gamefalloutttw.cpp b/src/games/ttw/src/gamefalloutttw.cpp index f4296c25..f3cc1d9c 100644 --- a/src/games/ttw/src/gamefalloutttw.cpp +++ b/src/games/ttw/src/gamefalloutttw.cpp @@ -5,6 +5,7 @@ #include "falloutttwsavegameinfo.h" #include "falloutttwscriptextender.h" #include "falloutttwmoddatachecker.h" +#include "falloutttwmoddatacontent.h" #include "executableinfo.h" #include "pluginsetting.h" @@ -42,6 +43,7 @@ bool GameFalloutTTW::init(IOrganizer *moInfo) registerFeature(new FalloutTTWSaveGameInfo(this)); registerFeature(new GamebryoLocalSavegames(myGamesPath(), "fallout.ini")); registerFeature(new FalloutTTWModDataChecker(this)); + registerFeature(new FalloutTTWModDataContent(this)); registerFeature(new GamebryoGamePlugins(moInfo)); registerFeature(new GamebryoUnmangedMods(this)); return true; From 3ff313dd7416adf8f495048d84da6f1fb9ca292f Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Mika=C3=ABl=20Capelle?= Date: Tue, 26 May 2020 21:54:38 +0200 Subject: [PATCH 0938/1544] [game_oblivion] Fix incorrect ModDataChecker usage. --- src/games/oblivion/src/gameoblivion.cpp | 4 ++-- src/games/oblivion/src/oblivionmoddatachecker.h | 2 +- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/src/games/oblivion/src/gameoblivion.cpp b/src/games/oblivion/src/gameoblivion.cpp index 6e7a3af3..dfc77aa4 100644 --- a/src/games/oblivion/src/gameoblivion.cpp +++ b/src/games/oblivion/src/gameoblivion.cpp @@ -4,11 +4,11 @@ #include "obliviondataarchives.h" #include "oblivionsavegameinfo.h" #include "oblivionscriptextender.h" +#include "oblivionmoddatachecker.h" #include "pluginsetting.h" #include "executableinfo.h" #include -#include #include #include @@ -34,7 +34,7 @@ bool GameOblivion::init(IOrganizer *moInfo) registerFeature(new OblivionBSAInvalidation(feature(), this)); registerFeature(new OblivionSaveGameInfo(this)); registerFeature(new GamebryoLocalSavegames(myGamesPath(), "oblivion.ini")); - registerFeature(new GamebryoModDataChecker(this)); + registerFeature(new OblivionModDataChecker(this)); registerFeature(new GamebryoGamePlugins(moInfo)); registerFeature(new GamebryoUnmangedMods(this)); return true; diff --git a/src/games/oblivion/src/oblivionmoddatachecker.h b/src/games/oblivion/src/oblivionmoddatachecker.h index 622fe912..baa703a1 100644 --- a/src/games/oblivion/src/oblivionmoddatachecker.h +++ b/src/games/oblivion/src/oblivionmoddatachecker.h @@ -3,7 +3,7 @@ #include -class SkyrimSEModDataChecker : public GamebryoModDataChecker +class OblivionModDataChecker : public GamebryoModDataChecker { public: using GamebryoModDataChecker::GamebryoModDataChecker; From 6ed8cdc4a65c829d4e85fd3d8f96db6f5bfe043c Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Mika=C3=ABl=20Capelle?= Date: Tue, 26 May 2020 21:54:53 +0200 Subject: [PATCH 0939/1544] [game_oblivion] Custom ModDataContent for Oblivion. --- src/games/oblivion/src/gameoblivion.cpp | 2 ++ .../oblivion/src/oblivionmoddatacontent.h | 21 +++++++++++++++++++ 2 files changed, 23 insertions(+) create mode 100644 src/games/oblivion/src/oblivionmoddatacontent.h diff --git a/src/games/oblivion/src/gameoblivion.cpp b/src/games/oblivion/src/gameoblivion.cpp index dfc77aa4..72663ca5 100644 --- a/src/games/oblivion/src/gameoblivion.cpp +++ b/src/games/oblivion/src/gameoblivion.cpp @@ -5,6 +5,7 @@ #include "oblivionsavegameinfo.h" #include "oblivionscriptextender.h" #include "oblivionmoddatachecker.h" +#include "oblivionmoddatacontent.h" #include "pluginsetting.h" #include "executableinfo.h" @@ -35,6 +36,7 @@ bool GameOblivion::init(IOrganizer *moInfo) registerFeature(new OblivionSaveGameInfo(this)); registerFeature(new GamebryoLocalSavegames(myGamesPath(), "oblivion.ini")); registerFeature(new OblivionModDataChecker(this)); + registerFeature(new OblivionModDataContent(this)); registerFeature(new GamebryoGamePlugins(moInfo)); registerFeature(new GamebryoUnmangedMods(this)); return true; diff --git a/src/games/oblivion/src/oblivionmoddatacontent.h b/src/games/oblivion/src/oblivionmoddatacontent.h new file mode 100644 index 00000000..2e79a87f --- /dev/null +++ b/src/games/oblivion/src/oblivionmoddatacontent.h @@ -0,0 +1,21 @@ +#ifndef OBLIVION_MODDATACONTENT_H +#define OBLIVION_MODDATACONTENT_H + +#include +#include + +class OblivionModDataContent : public GamebryoModDataContent { +public: + + /** + * + */ + OblivionModDataContent(GameGamebryo const* gamePlugin) : GamebryoModDataContent(gamePlugin) { + // Just need to disable some contents: + m_Enabled[CONTENT_MCM] = false; + m_Enabled[CONTENT_SKYPROC] = false; + } + +}; + +#endif // OBLIVION_MODDATACONTENT_H From 9374f5330ab95ba470e1aef529c4f9c4a7077311 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Mika=C3=ABl=20Capelle?= Date: Wed, 27 May 2020 14:41:49 +0200 Subject: [PATCH 0940/1544] [game_skyrim] Add custom ModDataContent. --- src/games/skyrim/src/gameskyrim.cpp | 2 ++ src/games/skyrim/src/skyrimmoddatacontent.h | 15 +++++++++++++++ 2 files changed, 17 insertions(+) create mode 100644 src/games/skyrim/src/skyrimmoddatacontent.h diff --git a/src/games/skyrim/src/gameskyrim.cpp b/src/games/skyrim/src/gameskyrim.cpp index 49c25fd2..52382897 100644 --- a/src/games/skyrim/src/gameskyrim.cpp +++ b/src/games/skyrim/src/gameskyrim.cpp @@ -6,6 +6,7 @@ #include "skyrimsavegameinfo.h" #include "skyrimgameplugins.h" #include "skyrimmoddatachecker.h" +#include "skyrimmoddatacontent.h" #include "executableinfo.h" #include "pluginsetting.h" @@ -46,6 +47,7 @@ bool GameSkyrim::init(IOrganizer *moInfo) registerFeature(new SkyrimSaveGameInfo(this)); registerFeature(new GamebryoLocalSavegames(myGamesPath(), "skyrim.ini")); registerFeature(new SkyrimModDataChecker(this)); + registerFeature(new SkyrimModDataContent(this)); registerFeature(new SkyrimGamePlugins(moInfo)); registerFeature(new GamebryoUnmangedMods(this)); return true; diff --git a/src/games/skyrim/src/skyrimmoddatacontent.h b/src/games/skyrim/src/skyrimmoddatacontent.h new file mode 100644 index 00000000..2a8948d4 --- /dev/null +++ b/src/games/skyrim/src/skyrimmoddatacontent.h @@ -0,0 +1,15 @@ +#ifndef SKYRIM_MODDATACONTENT_H +#define SKYRIM_MODDATACONTENT_H + +#include +#include + +// Skyrim does not need any change from the default feature: +class SkyrimModDataContent : public GamebryoModDataContent { +public: + + using GamebryoModDataContent::GamebryoModDataContent; + +}; + +#endif // SKYRIM_MODDATACONTENT_H From 229d4584bff672b2bd0803fb952b2073d5035af7 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Mika=C3=ABl=20Capelle?= Date: Wed, 27 May 2020 14:42:00 +0200 Subject: [PATCH 0941/1544] [game_skyrimse] Add custom ModDataContent. --- src/games/skyrimse/src/gameskyrimse.cpp | 2 ++ .../skyrimse/src/skyrimsemoddatacontent.h | 20 +++++++++++++++++++ 2 files changed, 22 insertions(+) create mode 100644 src/games/skyrimse/src/skyrimsemoddatacontent.h diff --git a/src/games/skyrimse/src/gameskyrimse.cpp b/src/games/skyrimse/src/gameskyrimse.cpp index 6f0bd5b6..6b2f4104 100644 --- a/src/games/skyrimse/src/gameskyrimse.cpp +++ b/src/games/skyrimse/src/gameskyrimse.cpp @@ -5,6 +5,7 @@ #include "skyrimsesavegameinfo.h" #include "skyrimseunmanagedmods.h" #include "skyrimsemoddatachecker.h" +#include "skyrimsemoddatacontent.h" #include #include @@ -74,6 +75,7 @@ bool GameSkyrimSE::init(IOrganizer *moInfo) registerFeature(new SkyrimSEDataArchives(myGamesPath())); registerFeature(new GamebryoLocalSavegames(myGamesPath(), "Skyrimcustom.ini")); registerFeature(new SkyrimSEModDataChecker(this)); + registerFeature(new SkyrimSEModDataContent(this)); registerFeature(new SkyrimSESaveGameInfo(this)); registerFeature(new CreationGamePlugins(moInfo)); registerFeature(new SkyrimSEUnmangedMods(this)); diff --git a/src/games/skyrimse/src/skyrimsemoddatacontent.h b/src/games/skyrimse/src/skyrimsemoddatacontent.h new file mode 100644 index 00000000..deb34653 --- /dev/null +++ b/src/games/skyrimse/src/skyrimsemoddatacontent.h @@ -0,0 +1,20 @@ +#ifndef SKYRIMSE_MODDATACONTENT_H +#define SKYRIMSE_MODDATACONTENT_H + +#include +#include + +class SkyrimSEModDataContent : public GamebryoModDataContent { +public: + + /** + * + */ + SkyrimSEModDataContent(GameGamebryo const* gamePlugin) : GamebryoModDataContent(gamePlugin) { + // Just need to disable some contents: + m_Enabled[CONTENT_SKYPROC] = false; + } + +}; + +#endif // SKYRIMSE_MODDATACONTENT_H From e9c8cf71c1097fa03d4b64f6720b9b7ebd04ea9d Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Mika=C3=ABl=20Capelle?= Date: Wed, 27 May 2020 14:42:11 +0200 Subject: [PATCH 0942/1544] [game_skyrimvr] Add custom ModDataContent. --- src/games/skyrimvr/src/gameskyrimvr.cpp | 2 ++ .../skyrimvr/src/skyrimvrmoddatacontent.h | 20 +++++++++++++++++++ 2 files changed, 22 insertions(+) create mode 100644 src/games/skyrimvr/src/skyrimvrmoddatacontent.h diff --git a/src/games/skyrimvr/src/gameskyrimvr.cpp b/src/games/skyrimvr/src/gameskyrimvr.cpp index b8aa9652..82fbc26b 100644 --- a/src/games/skyrimvr/src/gameskyrimvr.cpp +++ b/src/games/skyrimvr/src/gameskyrimvr.cpp @@ -4,6 +4,7 @@ #include "skyrimvrscriptextender.h" #include "skyrimvrsavegameinfo.h" #include "skyrimvrunmanagedmods.h" +#include "skyrimvrmoddatacontent.h" #include #include @@ -72,6 +73,7 @@ bool GameSkyrimVR::init(IOrganizer *moInfo) registerFeature(new SkyrimVRDataArchives(myGamesPath())); registerFeature(new GamebryoLocalSavegames(myGamesPath(), "SkyrimVR.ini")); registerFeature(new SkyrimVRSaveGameInfo(this)); + registerFeature(new SkyrimVRModDataContent(this)); registerFeature(new CreationGamePlugins(moInfo)); registerFeature(new SkyrimVRUnmangedMods(this)); diff --git a/src/games/skyrimvr/src/skyrimvrmoddatacontent.h b/src/games/skyrimvr/src/skyrimvrmoddatacontent.h new file mode 100644 index 00000000..940cdda9 --- /dev/null +++ b/src/games/skyrimvr/src/skyrimvrmoddatacontent.h @@ -0,0 +1,20 @@ +#ifndef SKYRIMVR_MODDATACONTENT_H +#define SKYRIMVR_MODDATACONTENT_H + +#include +#include + +class SkyrimVRModDataContent : public GamebryoModDataContent { +public: + + /** + * + */ + SkyrimVRModDataContent(GameGamebryo const* gamePlugin) : GamebryoModDataContent(gamePlugin) { + // Just need to disable some contents: + m_Enabled[CONTENT_SKYPROC] = false; + } + +}; + +#endif // SKYRIMVR_MODDATACONTENT_H From 4c1304dc7115c9928db987a61de4a14661f98f81 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Mika=C3=ABl=20Capelle?= Date: Wed, 27 May 2020 14:42:49 +0200 Subject: [PATCH 0943/1544] [game_fallout4] Add custom ModDataContent. --- .../fallout4/src/fallout4moddatacontent.h | 41 +++++++++++++++++++ src/games/fallout4/src/gamefallout4.cpp | 2 + 2 files changed, 43 insertions(+) create mode 100644 src/games/fallout4/src/fallout4moddatacontent.h diff --git a/src/games/fallout4/src/fallout4moddatacontent.h b/src/games/fallout4/src/fallout4moddatacontent.h new file mode 100644 index 00000000..cc65ebe0 --- /dev/null +++ b/src/games/fallout4/src/fallout4moddatacontent.h @@ -0,0 +1,41 @@ +#ifndef FALLOUT4_MODDATACONTENT_H +#define FALLOUT4_MODDATACONTENT_H + +#include +#include + +class Fallout4ModDataContent : public GamebryoModDataContent { +protected: + enum Fallout4Content { + CONTENT_MATERIAL = CONTENT_NEXT_VALUE + }; + +public: + Fallout4ModDataContent(GameGamebryo const* gamePlugin) : + GamebryoModDataContent(gamePlugin) + { + m_Enabled[CONTENT_SKYPROC] = false; + } + + std::vector getAllContents() const override + { + auto contents = GamebryoModDataContent::getAllContents(); + contents.push_back(Content(CONTENT_MATERIAL, "Materials", ":/MO/gui/content/material")); + return contents; + } + + std::vector getContentsFor( + std::shared_ptr fileTree) const override + { + auto contents = GamebryoModDataContent::getContentsFor(fileTree); + for (auto e : *fileTree) { + if (e->compare("materials") == 0) { + contents.push_back(CONTENT_MATERIAL); + break; // Early break if you have nothing else to check. + } + } + return contents; + } +}; + +#endif // FALLOUT4_MODDATACONTENT_H \ No newline at end of file diff --git a/src/games/fallout4/src/gamefallout4.cpp b/src/games/fallout4/src/gamefallout4.cpp index deb1248b..f5a2d220 100644 --- a/src/games/fallout4/src/gamefallout4.cpp +++ b/src/games/fallout4/src/gamefallout4.cpp @@ -5,6 +5,7 @@ #include "fallout4savegameinfo.h" #include "fallout4unmanagedmods.h" #include "fallout4moddatachecker.h" +#include "fallout4moddatacontent.h" #include #include @@ -40,6 +41,7 @@ bool GameFallout4::init(IOrganizer *moInfo) registerFeature(new Fallout4DataArchives(myGamesPath())); registerFeature(new GamebryoLocalSavegames(myGamesPath(), "fallout4custom.ini")); registerFeature(new Fallout4ModDataChecker(this)); + registerFeature(new Fallout4ModDataContent(this)); registerFeature(new Fallout4SaveGameInfo(this)); registerFeature(new CreationGamePlugins(moInfo)); registerFeature(new Fallout4UnmangedMods(this)); From 1aca2f48157ee62e3cf2c833ce3553be64bcac4e Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Mika=C3=ABl=20Capelle?= Date: Wed, 27 May 2020 14:43:02 +0200 Subject: [PATCH 0944/1544] [game_fallout4vr] Add custom ModDataContent. --- .../fallout4vr/src/fallout4vrmoddatacontent.h | 41 +++++++++++++++++++ src/games/fallout4vr/src/gamefallout4vr.cpp | 2 + 2 files changed, 43 insertions(+) create mode 100644 src/games/fallout4vr/src/fallout4vrmoddatacontent.h diff --git a/src/games/fallout4vr/src/fallout4vrmoddatacontent.h b/src/games/fallout4vr/src/fallout4vrmoddatacontent.h new file mode 100644 index 00000000..5ce3c2dd --- /dev/null +++ b/src/games/fallout4vr/src/fallout4vrmoddatacontent.h @@ -0,0 +1,41 @@ +#ifndef FALLOUT4VR_MODDATACONTENT_H +#define FALLOUT4VR_MODDATACONTENT_H + +#include +#include + +class Fallout4VRModDataContent : public GamebryoModDataContent { +protected: + enum Fallout4Content { + CONTENT_MATERIAL = CONTENT_NEXT_VALUE + }; + +public: + Fallout4VRModDataContent(GameGamebryo const* gamePlugin) : + GamebryoModDataContent(gamePlugin) + { + m_Enabled[CONTENT_SKYPROC] = false; + } + + std::vector getAllContents() const override + { + auto contents = GamebryoModDataContent::getAllContents(); + contents.push_back(Content(CONTENT_MATERIAL, "Materials", ":/MO/gui/content/material")); + return contents; + } + + std::vector getContentsFor( + std::shared_ptr fileTree) const override + { + auto contents = GamebryoModDataContent::getContentsFor(fileTree); + for (auto e : *fileTree) { + if (e->compare("materials") == 0) { + contents.push_back(CONTENT_MATERIAL); + break; // Early break if you have nothing else to check. + } + } + return contents; + } +}; + +#endif // FALLOUT4VR_MODDATACONTENT_H \ No newline at end of file diff --git a/src/games/fallout4vr/src/gamefallout4vr.cpp b/src/games/fallout4vr/src/gamefallout4vr.cpp index b6e023d9..eec13e5b 100644 --- a/src/games/fallout4vr/src/gamefallout4vr.cpp +++ b/src/games/fallout4vr/src/gamefallout4vr.cpp @@ -4,6 +4,7 @@ #include "fallout4vrsavegameinfo.h" #include "fallout4vrunmanagedmods.h" #include "fallout4vrmoddatachecker.h" +#include "fallout4vrmoddatacontent.h" #include #include @@ -40,6 +41,7 @@ bool GameFallout4VR::init(IOrganizer *moInfo) registerFeature(new Fallout4VRDataArchives(myGamesPath())); registerFeature(new GamebryoLocalSavegames(myGamesPath(), "fallout4custom.ini")); registerFeature(new Fallout4VRModDataChecker(this)); + registerFeature(new Fallout4VRModDataContent(this)); registerFeature(new Fallout4VRSaveGameInfo(this)); registerFeature(new CreationGamePlugins(moInfo)); registerFeature(new Fallout4VRUnmangedMods(this)); From 2386b1c627be1896ff11799033cf5167789135fe Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Mika=C3=ABl=20Capelle?= Date: Wed, 27 May 2020 14:43:41 +0200 Subject: [PATCH 0945/1544] Fix issue with m_Enabled. --- src/gamebryo/gamebryomoddatacontent.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/gamebryo/gamebryomoddatacontent.cpp b/src/gamebryo/gamebryomoddatacontent.cpp index f0947782..ca4b1733 100644 --- a/src/gamebryo/gamebryomoddatacontent.cpp +++ b/src/gamebryo/gamebryomoddatacontent.cpp @@ -5,7 +5,7 @@ #include "gamegamebryo.h" GamebryoModDataContent::GamebryoModDataContent(GameGamebryo const* gamePlugin) : - m_GamePlugin(gamePlugin), m_Enabled(CONTENT_MODGROUP, true) { } + m_GamePlugin(gamePlugin), m_Enabled(CONTENT_MODGROUP + 1, true) { } std::vector GamebryoModDataContent::getAllContents() const { static std::vector GAMEBRYO_CONTENTS{ From bad71bbbce2c46cd4343ade383ae15033e535988 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Mika=C3=ABl=20Capelle?= Date: Wed, 27 May 2020 14:43:57 +0200 Subject: [PATCH 0946/1544] Add custom variable to specify the first available Content game can replace. --- src/gamebryo/gamebryomoddatacontent.h | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/src/gamebryo/gamebryomoddatacontent.h b/src/gamebryo/gamebryomoddatacontent.h index f791560a..5b9aeb4a 100644 --- a/src/gamebryo/gamebryomoddatacontent.h +++ b/src/gamebryo/gamebryomoddatacontent.h @@ -32,6 +32,11 @@ protected: CONTENT_MODGROUP }; + /** + * This is the first value that can be used for game-specific contents. + */ + constexpr static auto CONTENT_NEXT_VALUE = CONTENT_MODGROUP + 1; + public: /** From adf3d8c27d670f8d5849d59b7894be3442b3b4ca Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Mika=C3=ABl=20Capelle?= Date: Wed, 27 May 2020 14:44:10 +0200 Subject: [PATCH 0947/1544] Do not register the feature here by default. --- src/gamebryo/gamegamebryo.cpp | 1 - 1 file changed, 1 deletion(-) diff --git a/src/gamebryo/gamegamebryo.cpp b/src/gamebryo/gamegamebryo.cpp index 852a5d83..6e0578b6 100644 --- a/src/gamebryo/gamegamebryo.cpp +++ b/src/gamebryo/gamegamebryo.cpp @@ -34,7 +34,6 @@ bool GameGamebryo::init(MOBase::IOrganizer *moInfo) { m_GamePath = identifyGamePath(); m_MyGamesPath = determineMyGamesPath(gameShortName()); - registerFeature(new GamebryoModDataContent(this)); m_Organizer = moInfo; return true; } From 3d32dc8a279879e8840ef5ac92415c7920c55f91 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Mika=C3=ABl=20Capelle?= Date: Wed, 27 May 2020 21:34:43 +0200 Subject: [PATCH 0948/1544] Rename 'Game Plugins (...)' to 'Plugins (...)'. --- src/gamebryo/gamebryomoddatacontent.cpp | 24 ++++++++++++------------ 1 file changed, 12 insertions(+), 12 deletions(-) diff --git a/src/gamebryo/gamebryomoddatacontent.cpp b/src/gamebryo/gamebryomoddatacontent.cpp index ca4b1733..bd6e769f 100644 --- a/src/gamebryo/gamebryomoddatacontent.cpp +++ b/src/gamebryo/gamebryomoddatacontent.cpp @@ -9,18 +9,18 @@ GamebryoModDataContent::GamebryoModDataContent(GameGamebryo const* gamePlugin) : std::vector GamebryoModDataContent::getAllContents() const { static std::vector GAMEBRYO_CONTENTS{ - {CONTENT_PLUGIN, QT_TR_NOOP("Game Plugins (ESP/ESM/ESL)"), ":/MO/gui/content/plugin"}, - {CONTENT_INTERFACE, QT_TR_NOOP("Interface"), ":/MO/gui/content/interface"}, - {CONTENT_MESH, QT_TR_NOOP("Meshes"), ":/MO/gui/content/mesh"}, - {CONTENT_BSA, QT_TR_NOOP("Bethesda Archive"), ":/MO/gui/content/bsa"}, - {CONTENT_SCRIPT, QT_TR_NOOP("Scripts (Papyrus)"), ":/MO/gui/content/script"}, - {CONTENT_SKSE, QT_TR_NOOP("Script Extender Plugin"), ":/MO/gui/content/skse"}, - {CONTENT_SKYPROC, QT_TR_NOOP("SkyProc Patcher"), ":/MO/gui/content/skyproc"}, - {CONTENT_SOUND, QT_TR_NOOP("Sound or Music"), ":/MO/gui/content/sound"}, - {CONTENT_TEXTURE, QT_TR_NOOP("Textures"), ":/MO/gui/content/texture"}, - {CONTENT_MCM, QT_TR_NOOP("MCM Configuration"), ":/MO/gui/content/menu"}, - {CONTENT_INI, QT_TR_NOOP("INI files"), ":/MO/gui/content/inifile"}, - {CONTENT_MODGROUP, QT_TR_NOOP("ModGroup files"), ":/MO/gui/content/modgroup"} + {CONTENT_PLUGIN, QT_TR_NOOP("Plugins (ESP/ESM/ESL)"), ":/MO/gui/content/plugin"}, + {CONTENT_INTERFACE, QT_TR_NOOP("Interface"), ":/MO/gui/content/interface"}, + {CONTENT_MESH, QT_TR_NOOP("Meshes"), ":/MO/gui/content/mesh"}, + {CONTENT_BSA, QT_TR_NOOP("Bethesda Archive"), ":/MO/gui/content/bsa"}, + {CONTENT_SCRIPT, QT_TR_NOOP("Scripts (Papyrus)"), ":/MO/gui/content/script"}, + {CONTENT_SKSE, QT_TR_NOOP("Script Extender Plugin"), ":/MO/gui/content/skse"}, + {CONTENT_SKYPROC, QT_TR_NOOP("SkyProc Patcher"), ":/MO/gui/content/skyproc"}, + {CONTENT_SOUND, QT_TR_NOOP("Sound or Music"), ":/MO/gui/content/sound"}, + {CONTENT_TEXTURE, QT_TR_NOOP("Textures"), ":/MO/gui/content/texture"}, + {CONTENT_MCM, QT_TR_NOOP("MCM Configuration"), ":/MO/gui/content/menu"}, + {CONTENT_INI, QT_TR_NOOP("INI files"), ":/MO/gui/content/inifile"}, + {CONTENT_MODGROUP, QT_TR_NOOP("ModGroup files"), ":/MO/gui/content/modgroup"} }; // Copy the list of enabled contents: From 2be85db6719f775c6ddd1b0fdbb85a08d7949dfc Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Mika=C3=ABl=20Capelle?= Date: Wed, 27 May 2020 22:01:00 +0200 Subject: [PATCH 0949/1544] Add CONTENT_SKSE_FILES as filter-only Content. --- src/gamebryo/gamebryomoddatacontent.cpp | 40 ++++++++++++++----------- src/gamebryo/gamebryomoddatacontent.h | 1 + 2 files changed, 24 insertions(+), 17 deletions(-) diff --git a/src/gamebryo/gamebryomoddatacontent.cpp b/src/gamebryo/gamebryomoddatacontent.cpp index bd6e769f..415729f9 100644 --- a/src/gamebryo/gamebryomoddatacontent.cpp +++ b/src/gamebryo/gamebryomoddatacontent.cpp @@ -9,18 +9,19 @@ GamebryoModDataContent::GamebryoModDataContent(GameGamebryo const* gamePlugin) : std::vector GamebryoModDataContent::getAllContents() const { static std::vector GAMEBRYO_CONTENTS{ - {CONTENT_PLUGIN, QT_TR_NOOP("Plugins (ESP/ESM/ESL)"), ":/MO/gui/content/plugin"}, - {CONTENT_INTERFACE, QT_TR_NOOP("Interface"), ":/MO/gui/content/interface"}, - {CONTENT_MESH, QT_TR_NOOP("Meshes"), ":/MO/gui/content/mesh"}, - {CONTENT_BSA, QT_TR_NOOP("Bethesda Archive"), ":/MO/gui/content/bsa"}, - {CONTENT_SCRIPT, QT_TR_NOOP("Scripts (Papyrus)"), ":/MO/gui/content/script"}, - {CONTENT_SKSE, QT_TR_NOOP("Script Extender Plugin"), ":/MO/gui/content/skse"}, - {CONTENT_SKYPROC, QT_TR_NOOP("SkyProc Patcher"), ":/MO/gui/content/skyproc"}, - {CONTENT_SOUND, QT_TR_NOOP("Sound or Music"), ":/MO/gui/content/sound"}, - {CONTENT_TEXTURE, QT_TR_NOOP("Textures"), ":/MO/gui/content/texture"}, - {CONTENT_MCM, QT_TR_NOOP("MCM Configuration"), ":/MO/gui/content/menu"}, - {CONTENT_INI, QT_TR_NOOP("INI files"), ":/MO/gui/content/inifile"}, - {CONTENT_MODGROUP, QT_TR_NOOP("ModGroup files"), ":/MO/gui/content/modgroup"} + {CONTENT_PLUGIN, QT_TR_NOOP("Plugins (ESP/ESM/ESL)"), ":/MO/gui/content/plugin"}, + {CONTENT_INTERFACE, QT_TR_NOOP("Interface"), ":/MO/gui/content/interface"}, + {CONTENT_MESH, QT_TR_NOOP("Meshes"), ":/MO/gui/content/mesh"}, + {CONTENT_BSA, QT_TR_NOOP("Bethesda Archive"), ":/MO/gui/content/bsa"}, + {CONTENT_SCRIPT, QT_TR_NOOP("Scripts (Papyrus)"), ":/MO/gui/content/script"}, + {CONTENT_SKSE, QT_TR_NOOP("Script Extender Plugin"), ":/MO/gui/content/skse"}, + {CONTENT_SKSE_FILES, QT_TR_NOOP("Script Extender Files"), "", true}, + {CONTENT_SKYPROC, QT_TR_NOOP("SkyProc Patcher"), ":/MO/gui/content/skyproc"}, + {CONTENT_SOUND, QT_TR_NOOP("Sound or Music"), ":/MO/gui/content/sound"}, + {CONTENT_TEXTURE, QT_TR_NOOP("Textures"), ":/MO/gui/content/texture"}, + {CONTENT_MCM, QT_TR_NOOP("MCM Configuration"), ":/MO/gui/content/menu"}, + {CONTENT_INI, QT_TR_NOOP("INI Files"), ":/MO/gui/content/inifile"}, + {CONTENT_MODGROUP, QT_TR_NOOP("ModGroup Files"), ":/MO/gui/content/modgroup"} }; // Copy the list of enabled contents: @@ -75,13 +76,18 @@ std::vector GamebryoModDataContent::getContentsFor(std::shared_ptrfeature(); - if (m_Enabled[CONTENT_SKSE] && extender != nullptr) { + if (extender != nullptr) { auto e = fileTree->findDirectory(extender->PluginPath()); if (e) { - for (auto f : *e) { - if (f->hasSuffix("dll")) { - contents.push_back(CONTENT_SKSE); - break; + if (m_Enabled[CONTENT_SKSE_FILES]) { + contents.push_back(CONTENT_SKSE_FILES); + } + if (m_Enabled[CONTENT_SKSE]) { + for (auto f : *e) { + if (f->hasSuffix("dll")) { + contents.push_back(CONTENT_SKSE); + break; + } } } } diff --git a/src/gamebryo/gamebryomoddatacontent.h b/src/gamebryo/gamebryomoddatacontent.h index 5b9aeb4a..3e13e36f 100644 --- a/src/gamebryo/gamebryomoddatacontent.h +++ b/src/gamebryo/gamebryomoddatacontent.h @@ -26,6 +26,7 @@ protected: CONTENT_SOUND, CONTENT_SCRIPT, CONTENT_SKSE, + CONTENT_SKSE_FILES, CONTENT_SKYPROC, CONTENT_MCM, CONTENT_INI, From b5f795043d8ef36224d15e1eb24293c2c0c38d49 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Mika=C3=ABl=20Capelle?= Date: Thu, 28 May 2020 19:23:00 +0200 Subject: [PATCH 0950/1544] Fix old comment. --- src/gamebryo/gamebryomoddatacontent.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/gamebryo/gamebryomoddatacontent.h b/src/gamebryo/gamebryomoddatacontent.h index 3e13e36f..8b8f4cde 100644 --- a/src/gamebryo/gamebryomoddatacontent.h +++ b/src/gamebryo/gamebryomoddatacontent.h @@ -14,7 +14,7 @@ class GamebryoModDataContent : public ModDataContent { protected: /** - * Note: These are used to index m_Contents so should have standard + * Note: These are used to index m_Enabled so should have standard * enum values, not custom ones. */ enum EContent { From 821f89abf305a1c54ea8f00f21c54da02ee04a41 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Mika=C3=ABl=20Capelle?= Date: Thu, 28 May 2020 19:23:30 +0200 Subject: [PATCH 0951/1544] Remove index variable in registerFeature. --- src/gamebryo/gamegamebryo.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/gamebryo/gamegamebryo.h b/src/gamebryo/gamegamebryo.h index ccba6ac9..82ed1b28 100644 --- a/src/gamebryo/gamegamebryo.h +++ b/src/gamebryo/gamegamebryo.h @@ -132,7 +132,7 @@ protected: if (m_FeatureList.find(index) != m_FeatureList.end()) { delete boost::any_cast(m_FeatureList[index]); } - m_FeatureList[std::type_index(typeid(T))] = type; + m_FeatureList[index] = type; } protected: From ca125cb9a2c05a53d08dd70196ec8c7917b98333 Mon Sep 17 00:00:00 2001 From: AL <26797547+Al12rs@users.noreply.github.com> Date: Mon, 8 Jun 2020 17:31:43 +0200 Subject: [PATCH 0952/1544] Added Contains Optional Plugins filter. --- src/gamebryo/gamebryomoddatacontent.cpp | 4 ++++ src/gamebryo/gamebryomoddatacontent.h | 1 + 2 files changed, 5 insertions(+) diff --git a/src/gamebryo/gamebryomoddatacontent.cpp b/src/gamebryo/gamebryomoddatacontent.cpp index 415729f9..620ae5ba 100644 --- a/src/gamebryo/gamebryomoddatacontent.cpp +++ b/src/gamebryo/gamebryomoddatacontent.cpp @@ -10,6 +10,7 @@ GamebryoModDataContent::GamebryoModDataContent(GameGamebryo const* gamePlugin) : std::vector GamebryoModDataContent::getAllContents() const { static std::vector GAMEBRYO_CONTENTS{ {CONTENT_PLUGIN, QT_TR_NOOP("Plugins (ESP/ESM/ESL)"), ":/MO/gui/content/plugin"}, + {CONTENT_OPTIONAL, QT_TR_NOOP("Optional Plugins"), "", true}, {CONTENT_INTERFACE, QT_TR_NOOP("Interface"), ":/MO/gui/content/interface"}, {CONTENT_MESH, QT_TR_NOOP("Meshes"), ":/MO/gui/content/mesh"}, {CONTENT_BSA, QT_TR_NOOP("Bethesda Archive"), ":/MO/gui/content/bsa"}, @@ -72,6 +73,9 @@ std::vector GamebryoModDataContent::getContentsFor(std::shared_ptrcompare("MCM") == 0) { contents.push_back(CONTENT_MCM); } + else if (m_Enabled[CONTENT_OPTIONAL] && e->compare("Optional") == 0 && e->astree()->size() > 0) { + contents.push_back(CONTENT_OPTIONAL); + } } } diff --git a/src/gamebryo/gamebryomoddatacontent.h b/src/gamebryo/gamebryomoddatacontent.h index 8b8f4cde..17e6a0b7 100644 --- a/src/gamebryo/gamebryomoddatacontent.h +++ b/src/gamebryo/gamebryomoddatacontent.h @@ -19,6 +19,7 @@ protected: */ enum EContent { CONTENT_PLUGIN, + CONTENT_OPTIONAL, CONTENT_TEXTURE, CONTENT_MESH, CONTENT_BSA, From c27c4d59fb43cfbf6741fd8f57742f922e983c3d Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Mika=C3=ABl=20Capelle?= Date: Mon, 8 Jun 2020 21:55:18 +0200 Subject: [PATCH 0953/1544] Use product version instead of file version when file version looks invalid. --- src/gamebryo/gamegamebryo.cpp | 12 +++++++++++- src/gamebryo/gamegamebryo.h | 7 +++++++ 2 files changed, 18 insertions(+), 1 deletion(-) diff --git a/src/gamebryo/gamegamebryo.cpp b/src/gamebryo/gamegamebryo.cpp index fb278c78..52dc092c 100644 --- a/src/gamebryo/gamegamebryo.cpp +++ b/src/gamebryo/gamegamebryo.cpp @@ -122,7 +122,17 @@ bool GameGamebryo::looksValid(QDir const &path) const QString GameGamebryo::gameVersion() const { - return getVersion(binaryName()); + // We try the file version, but if it looks invalid (starts with the fallback + // version), we look the product version instead. If the product version is + // not empty, we use it. + QString version = getVersion(binaryName()); + if (version.startsWith(FALLBACK_GAME_VERSION)) { + QString pversion = getProductVersion(binaryName()); + if (!pversion.isEmpty()) { + version = pversion; + } + } + return version; } QString GameGamebryo::getLauncherName() const diff --git a/src/gamebryo/gamegamebryo.h b/src/gamebryo/gamegamebryo.h index 16fb99b0..f917d385 100644 --- a/src/gamebryo/gamegamebryo.h +++ b/src/gamebryo/gamegamebryo.h @@ -31,6 +31,13 @@ class GameGamebryo : public MOBase::IPluginGame, friend class GamebryoSaveGameInfo; friend class GamebryoSaveGameInfoWidget; + /** + * Some Bethesda games do not have a valid file version but a valid product + * version. If the file version starts with FALLBACK_GAME_VERSION, the product + * version will be tried. + */ + static constexpr const char* FALLBACK_GAME_VERSION = "1.0.0"; + public: GameGamebryo(); From 6a56e2e00c0c1930b6c32f698690289428da2890 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Mika=C3=ABl=20Capelle?= Date: Tue, 9 Jun 2020 23:38:07 +0200 Subject: [PATCH 0954/1544] Use getFileVersion() and getProductVersion() from uibase. --- src/gamebryo/gamebryoscriptextender.cpp | 4 +- src/gamebryo/gamegamebryo.cpp | 71 ++----------------------- src/gamebryo/gamegamebryo.h | 2 - 3 files changed, 6 insertions(+), 71 deletions(-) diff --git a/src/gamebryo/gamebryoscriptextender.cpp b/src/gamebryo/gamebryoscriptextender.cpp index 7b19f15f..fe743968 100644 --- a/src/gamebryo/gamebryoscriptextender.cpp +++ b/src/gamebryo/gamebryoscriptextender.cpp @@ -2,6 +2,8 @@ #include "gamegamebryo.h" +#include "utility.h" + #include #include @@ -35,7 +37,7 @@ bool GamebryoScriptExtender::isInstalled() const QString GamebryoScriptExtender::getExtenderVersion() const { - return m_Game->getVersion(loaderName()); + return MOBase::getFileVersion(m_Game->gameDirectory().absoluteFilePath(loaderName())); } WORD GamebryoScriptExtender::getArch() const diff --git a/src/gamebryo/gamegamebryo.cpp b/src/gamebryo/gamegamebryo.cpp index b110af0e..57cf574a 100644 --- a/src/gamebryo/gamegamebryo.cpp +++ b/src/gamebryo/gamegamebryo.cpp @@ -126,9 +126,10 @@ QString GameGamebryo::gameVersion() const // We try the file version, but if it looks invalid (starts with the fallback // version), we look the product version instead. If the product version is // not empty, we use it. - QString version = getVersion(binaryName()); + QString binaryAbsPath = gameDirectory().absoluteFilePath(binaryName()); + QString version = MOBase::getFileVersion(binaryAbsPath); if (version.startsWith(FALLBACK_GAME_VERSION)) { - QString pversion = getProductVersion(binaryName()); + QString pversion = MOBase::getProductVersion(binaryAbsPath); if (!pversion.isEmpty()) { version = pversion; } @@ -141,72 +142,6 @@ QString GameGamebryo::getLauncherName() const return gameShortName() + "Launcher.exe"; } -QString GameGamebryo::getVersion(QString const &program) const -{ - //This *really* needs to be factored out - std::wstring app_name = L"\\\\?\\" + - QDir::toNativeSeparators(this->gameDirectory().absoluteFilePath(program)).toStdWString(); - DWORD handle; - DWORD info_len = ::GetFileVersionInfoSizeW(app_name.c_str(), &handle); - if (info_len == 0) { - qDebug("GetFileVersionInfoSizeW Error %d", ::GetLastError()); - return ""; - } - - std::vector buff(info_len); - if( ! ::GetFileVersionInfoW(app_name.c_str(), handle, info_len, buff.data())) { - qDebug("GetFileVersionInfoW Error %d", ::GetLastError()); - return ""; - } - - VS_FIXEDFILEINFO *pFileInfo; - UINT buf_len; - if ( ! ::VerQueryValueW(buff.data(), L"\\", reinterpret_cast(&pFileInfo), &buf_len)) { - qDebug("VerQueryValueW Error %d", ::GetLastError()); - return ""; - } - return QString("%1.%2.%3.%4").arg(HIWORD(pFileInfo->dwFileVersionMS)) - .arg(LOWORD(pFileInfo->dwFileVersionMS)) - .arg(HIWORD(pFileInfo->dwFileVersionLS)) - .arg(LOWORD(pFileInfo->dwFileVersionLS)); -} - -QString GameGamebryo::getProductVersion(QString const& program) const { - //This *really* needs to be factored out - std::wstring app_name = L"\\\\?\\" + - QDir::toNativeSeparators(this->gameDirectory().absoluteFilePath(program)).toStdWString(); - DWORD handle; - DWORD info_len = ::GetFileVersionInfoSizeW(app_name.c_str(), &handle); - if (info_len == 0) { - qDebug("GetFileVersionInfoSizeW Error %d", ::GetLastError()); - return ""; - } - - std::vector buff(info_len); - if (!::GetFileVersionInfoW(app_name.c_str(), handle, info_len, buff.data())) { - qDebug("GetFileVersionInfoW Error %d", ::GetLastError()); - return ""; - } - - // The following is from https://stackoverflow.com/a/12408544/2666289 - - UINT uiSize; - BYTE* lpb; - if (!::VerQueryValueW(buff.data(), TEXT("\\VarFileInfo\\Translation"), (void**)&lpb, &uiSize)) { - qDebug("VerQueryValue Error %d", ::GetLastError()); - return ""; - } - - WORD* lpw = (WORD*)lpb; - auto query = fmt::format(L"\\StringFileInfo\\{:04x}{:04x}\\ProductVersion", lpw[0], lpw[1]); - if (!::VerQueryValueW(buff.data(), query.data(), (void**)&lpb, &uiSize) && uiSize > 0) { - qDebug("VerQueryValue Error %d", ::GetLastError()); - return ""; - } - - return QString::fromWCharArray((LPCWSTR)lpb); -} - WORD GameGamebryo::getArch(QString const &program) const { WORD arch = 0; diff --git a/src/gamebryo/gamegamebryo.h b/src/gamebryo/gamegamebryo.h index d5fad5af..b58ea931 100644 --- a/src/gamebryo/gamegamebryo.h +++ b/src/gamebryo/gamegamebryo.h @@ -86,8 +86,6 @@ protected: QFileInfo findInGameFolder(const QString &relativePath) const; QString myGamesPath() const; QString selectedVariant() const; - QString getVersion(QString const &program) const; - QString getProductVersion(QString const& program) const; WORD getArch(QString const &program) const; static QString localAppFolder(); From afa76ed675ba95d22502191e2d6524699fec6ffc Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Mika=C3=ABl=20Capelle?= Date: Sat, 13 Jun 2020 23:53:54 +0200 Subject: [PATCH 0955/1544] Update following ModDataChecker change. --- src/gamebryo/gamebryomoddatachecker.cpp | 8 ++++---- src/gamebryo/gamebryomoddatachecker.h | 2 +- 2 files changed, 5 insertions(+), 5 deletions(-) diff --git a/src/gamebryo/gamebryomoddatachecker.cpp b/src/gamebryo/gamebryomoddatachecker.cpp index 7ef6e13f..6238c518 100644 --- a/src/gamebryo/gamebryomoddatachecker.cpp +++ b/src/gamebryo/gamebryomoddatachecker.cpp @@ -31,20 +31,20 @@ auto GamebryoModDataChecker::possibleFileExtensions() const -> const FileNameSet GamebryoModDataChecker::GamebryoModDataChecker(const GameGamebryo* game) : m_Game(game) { } -bool GamebryoModDataChecker::dataLooksValid(std::shared_ptr fileTree) const { +GamebryoModDataChecker::CheckReturn GamebryoModDataChecker::dataLooksValid(std::shared_ptr fileTree) const { auto& folders = possibleFolderNames(); auto& suffixes = possibleFileExtensions(); for (auto entry : *fileTree) { if (entry->isDir()) { if (folders.count(entry->name()) > 0) { - return true; + return CheckReturn::VALID; } } else { if (suffixes.count(entry->suffix()) > 0) { - return true; + return CheckReturn::VALID; } } } - return false; + return CheckReturn::INVALID; } \ No newline at end of file diff --git a/src/gamebryo/gamebryomoddatachecker.h b/src/gamebryo/gamebryomoddatachecker.h index 5925c5bd..56a54e35 100644 --- a/src/gamebryo/gamebryomoddatachecker.h +++ b/src/gamebryo/gamebryomoddatachecker.h @@ -23,7 +23,7 @@ public: */ GamebryoModDataChecker(const GameGamebryo* game); - virtual bool dataLooksValid(std::shared_ptr fileTree) const override; + virtual CheckReturn dataLooksValid(std::shared_ptr fileTree) const override; protected: From c85440fd4b6841f74fdd04ad03573ab151142c7e Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Mika=C3=ABl=20Capelle?= Date: Sun, 14 Jun 2020 15:38:33 +0200 Subject: [PATCH 0956/1544] Update following change to getLoadOrder() in game_features. --- src/creation/creationgameplugins.cpp | 6 +++--- src/creation/creationgameplugins.h | 2 +- src/gamebryo/gamebryogameplugins.cpp | 6 +++--- src/gamebryo/gamebryogameplugins.h | 2 +- 4 files changed, 8 insertions(+), 8 deletions(-) diff --git a/src/creation/creationgameplugins.cpp b/src/creation/creationgameplugins.cpp index 138ea3bc..6753606e 100644 --- a/src/creation/creationgameplugins.cpp +++ b/src/creation/creationgameplugins.cpp @@ -21,7 +21,7 @@ CreationGamePlugins::CreationGamePlugins(IOrganizer *organizer) { } -void CreationGamePlugins::getLoadOrder(QStringList &loadOrder) { +QStringList CreationGamePlugins::getLoadOrder() { QString loadOrderPath = organizer()->profile()->absolutePath() + "/loadorder.txt"; QString pluginsPath = organizer()->profile()->absolutePath() + "/plugins.txt"; @@ -33,10 +33,10 @@ void CreationGamePlugins::getLoadOrder(QStringList &loadOrder) { QFileInfo(pluginsPath).lastModified() > m_LastRead; if (loadOrderIsNew || !pluginsIsNew) { - loadOrder = readLoadOrderList(m_Organizer->pluginList(), loadOrderPath); + return readLoadOrderList(m_Organizer->pluginList(), loadOrderPath); } else { - loadOrder = readPluginList(m_Organizer->pluginList()); + return readPluginList(m_Organizer->pluginList()); } } diff --git a/src/creation/creationgameplugins.h b/src/creation/creationgameplugins.h index 635d67a1..47a7d176 100644 --- a/src/creation/creationgameplugins.h +++ b/src/creation/creationgameplugins.h @@ -15,7 +15,7 @@ protected: virtual void writePluginList(const MOBase::IPluginList *pluginList, const QString &filePath) override; virtual QStringList readPluginList(MOBase::IPluginList *pluginList) override; - virtual void getLoadOrder(QStringList &loadOrder) override; + virtual QStringList getLoadOrder() override; virtual bool lightPluginsAreSupported() override; private: diff --git a/src/gamebryo/gamebryogameplugins.cpp b/src/gamebryo/gamebryogameplugins.cpp index 0e99bdb6..ffec3427 100644 --- a/src/gamebryo/gamebryogameplugins.cpp +++ b/src/gamebryo/gamebryogameplugins.cpp @@ -63,7 +63,7 @@ void GamebryoGamePlugins::readPluginLists(MOBase::IPluginList *pluginList) { m_LastRead = QDateTime::currentDateTime(); } -void GamebryoGamePlugins::getLoadOrder(QStringList &loadOrder) { +QStringList GamebryoGamePlugins::getLoadOrder() { QString loadOrderPath = organizer()->profile()->absolutePath() + "/loadorder.txt"; QString pluginsPath = organizer()->profile()->absolutePath() + "/plugins.txt"; @@ -75,9 +75,9 @@ void GamebryoGamePlugins::getLoadOrder(QStringList &loadOrder) { QFileInfo(pluginsPath).lastModified() > m_LastRead; if (loadOrderIsNew || !pluginsIsNew) { - loadOrder = readLoadOrderList(m_Organizer->pluginList(), loadOrderPath); + return readLoadOrderList(m_Organizer->pluginList(), loadOrderPath); } else { - loadOrder = readPluginList(m_Organizer->pluginList()); + return readPluginList(m_Organizer->pluginList()); } } diff --git a/src/gamebryo/gamebryogameplugins.h b/src/gamebryo/gamebryogameplugins.h index 5e9f6a16..b97c5e00 100644 --- a/src/gamebryo/gamebryogameplugins.h +++ b/src/gamebryo/gamebryogameplugins.h @@ -14,7 +14,7 @@ public: virtual void writePluginLists(const MOBase::IPluginList *pluginList) override; virtual void readPluginLists(MOBase::IPluginList *pluginList) override; - virtual void getLoadOrder(QStringList &loadOrder) override; + virtual QStringList getLoadOrder() override; virtual bool lightPluginsAreSupported() override; protected: From ee52cdf18a16bd663817f56d7662a3558d559e94 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Mika=C3=ABl=20Capelle?= Date: Sun, 28 Jun 2020 11:52:14 +0200 Subject: [PATCH 0957/1544] [game_fallout4vr] Fix modgroups extension in ModDataChecker. --- src/games/fallout4vr/src/fallout4vrmoddatachecker.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/games/fallout4vr/src/fallout4vrmoddatachecker.h b/src/games/fallout4vr/src/fallout4vrmoddatachecker.h index 760f7aa2..1fc75e73 100644 --- a/src/games/fallout4vr/src/fallout4vrmoddatachecker.h +++ b/src/games/fallout4vr/src/fallout4vrmoddatachecker.h @@ -20,7 +20,7 @@ protected: } virtual const FileNameSet& possibleFileExtensions() const override { static FileNameSet result{ - "esp", "esm", "ba2", ".modgroups" + "esp", "esm", "ba2", "modgroups" }; return result; } From 074098c1c0ac4484c818a2f301fd600ec1263f18 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Mika=C3=ABl=20Capelle?= Date: Sun, 28 Jun 2020 11:52:14 +0200 Subject: [PATCH 0958/1544] [game_fallout4] Fix modgroups extension in ModDataChecker. --- src/games/fallout4/src/fallout4moddatachecker.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/games/fallout4/src/fallout4moddatachecker.h b/src/games/fallout4/src/fallout4moddatachecker.h index 7b48c551..0482ac1a 100644 --- a/src/games/fallout4/src/fallout4moddatachecker.h +++ b/src/games/fallout4/src/fallout4moddatachecker.h @@ -20,7 +20,7 @@ protected: } virtual const FileNameSet& possibleFileExtensions() const override { static FileNameSet result{ - "esp", "esm", "esl", "ba2", ".modgroups" + "esp", "esm", "esl", "ba2", "modgroups" }; return result; } From 261f0ea10f55a69a63c7e32dfb93567da2b11c4a Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Mika=C3=ABl=20Capelle?= Date: Sun, 28 Jun 2020 11:52:14 +0200 Subject: [PATCH 0959/1544] [game_fallout3] Fix modgroups extension in ModDataChecker. --- src/games/fallout3/src/fallout3moddatachecker.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/games/fallout3/src/fallout3moddatachecker.h b/src/games/fallout3/src/fallout3moddatachecker.h index 9387c06e..8bdb824f 100644 --- a/src/games/fallout3/src/fallout3moddatachecker.h +++ b/src/games/fallout3/src/fallout3moddatachecker.h @@ -20,7 +20,7 @@ protected: } virtual const FileNameSet& possibleFileExtensions() const override { static FileNameSet result{ - "esp", "esm", "bsa", ".modgroups" + "esp", "esm", "bsa", "modgroups" }; return result; } From 8edf3e401395de4e3a4a7d71226f7f2de23f8416 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Mika=C3=ABl=20Capelle?= Date: Sun, 28 Jun 2020 11:52:15 +0200 Subject: [PATCH 0960/1544] [game_ttw] Fix modgroups extension in ModDataChecker. --- src/games/ttw/src/falloutttwmoddatachecker.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/games/ttw/src/falloutttwmoddatachecker.h b/src/games/ttw/src/falloutttwmoddatachecker.h index 723b2454..7499da31 100644 --- a/src/games/ttw/src/falloutttwmoddatachecker.h +++ b/src/games/ttw/src/falloutttwmoddatachecker.h @@ -20,7 +20,7 @@ protected: } virtual const FileNameSet& possibleFileExtensions() const override { static FileNameSet result{ - "esp", "esm", "bsa", ".modgroups" + "esp", "esm", "bsa", "modgroups" }; return result; } From 20ca00f243ca061ef0f0a8ca796f0e682ab05856 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Mika=C3=ABl=20Capelle?= Date: Sun, 28 Jun 2020 11:52:15 +0200 Subject: [PATCH 0961/1544] [game_skyrimse] Fix modgroups extension in ModDataChecker. --- src/games/skyrimse/src/skyrimsemoddatachecker.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/games/skyrimse/src/skyrimsemoddatachecker.h b/src/games/skyrimse/src/skyrimsemoddatachecker.h index 5ceb0d47..7d4ab8c3 100644 --- a/src/games/skyrimse/src/skyrimsemoddatachecker.h +++ b/src/games/skyrimse/src/skyrimsemoddatachecker.h @@ -20,7 +20,7 @@ protected: } virtual const FileNameSet& possibleFileExtensions() const override { static FileNameSet result{ - "esp", "esm", "esl", "bsa", ".modgroups" + "esp", "esm", "esl", "bsa", "modgroups" }; return result; } From 3534585849aa8774392a73e1f83d50ffb68124d5 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Mika=C3=ABl=20Capelle?= Date: Sun, 28 Jun 2020 11:52:15 +0200 Subject: [PATCH 0962/1544] [game_skyrim] Fix modgroups extension in ModDataChecker. --- src/games/skyrim/src/skyrimmoddatachecker.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/games/skyrim/src/skyrimmoddatachecker.h b/src/games/skyrim/src/skyrimmoddatachecker.h index b452b218..f9264a09 100644 --- a/src/games/skyrim/src/skyrimmoddatachecker.h +++ b/src/games/skyrim/src/skyrimmoddatachecker.h @@ -20,7 +20,7 @@ protected: } virtual const FileNameSet& possibleFileExtensions() const override { static FileNameSet result{ - "esp", "esm", "bsa", ".modgroups" + "esp", "esm", "bsa", "modgroups" }; return result; } From 528e35bc12c2609e5f3bac553dea96fe69bb58b6 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Mika=C3=ABl=20Capelle?= Date: Sun, 28 Jun 2020 11:52:15 +0200 Subject: [PATCH 0963/1544] [game_oblivion] Fix modgroups extension in ModDataChecker. --- src/games/oblivion/src/oblivionmoddatachecker.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/games/oblivion/src/oblivionmoddatachecker.h b/src/games/oblivion/src/oblivionmoddatachecker.h index baa703a1..50a88b65 100644 --- a/src/games/oblivion/src/oblivionmoddatachecker.h +++ b/src/games/oblivion/src/oblivionmoddatachecker.h @@ -20,7 +20,7 @@ protected: } virtual const FileNameSet& possibleFileExtensions() const override { static FileNameSet result{ - "esp", "esm", "bsa", ".modgroups" + "esp", "esm", "bsa", "modgroups" }; return result; } From a3a891aaa0c17084d7a9f6fd6eb206e94b424612 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Mika=C3=ABl=20Capelle?= Date: Sun, 28 Jun 2020 11:52:15 +0200 Subject: [PATCH 0964/1544] [game_morrowind] Fix modgroups extension in ModDataChecker. --- src/games/morrowind/src/morrowindmoddatachecker.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/games/morrowind/src/morrowindmoddatachecker.h b/src/games/morrowind/src/morrowindmoddatachecker.h index 63ad8535..68b5e066 100644 --- a/src/games/morrowind/src/morrowindmoddatachecker.h +++ b/src/games/morrowind/src/morrowindmoddatachecker.h @@ -18,7 +18,7 @@ protected: } virtual const FileNameSet& possibleFileExtensions() const override { static FileNameSet result{ - "esp", "esm", "bsa", ".modgroups" + "esp", "esm", "bsa", "modgroups" }; return result; } From 22246964e9f960e3483095c009cdcd8f83d2140d Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Mika=C3=ABl=20Capelle?= Date: Sun, 28 Jun 2020 11:52:15 +0200 Subject: [PATCH 0965/1544] [game_falloutnv] Fix modgroups extension in ModDataChecker. --- src/games/falloutnv/src/falloutnvmoddatachecker.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/games/falloutnv/src/falloutnvmoddatachecker.h b/src/games/falloutnv/src/falloutnvmoddatachecker.h index d80200ec..9a43c3e7 100644 --- a/src/games/falloutnv/src/falloutnvmoddatachecker.h +++ b/src/games/falloutnv/src/falloutnvmoddatachecker.h @@ -20,7 +20,7 @@ protected: } virtual const FileNameSet& possibleFileExtensions() const override { static FileNameSet result{ - "esp", "esm", "bsa", ".modgroups" + "esp", "esm", "bsa", "modgroups" }; return result; } From c6d5a0ba0826acb9fffb0b3c70683e2e17bc56fb Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Mika=C3=ABl=20Capelle?= Date: Sun, 28 Jun 2020 11:52:30 +0200 Subject: [PATCH 0966/1544] Fix modgroups extension in ModDataChecker. --- src/gamebryo/gamebryomoddatachecker.cpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/gamebryo/gamebryomoddatachecker.cpp b/src/gamebryo/gamebryomoddatachecker.cpp index 6238c518..ccda8eb9 100644 --- a/src/gamebryo/gamebryomoddatachecker.cpp +++ b/src/gamebryo/gamebryomoddatachecker.cpp @@ -24,7 +24,7 @@ auto GamebryoModDataChecker::possibleFolderNames() const -> const FileNameSet& { */ auto GamebryoModDataChecker::possibleFileExtensions() const -> const FileNameSet& { static FileNameSet result{ - "esp", "esm", "esl", "bsa", "ba2", ".modgroups" + "esp", "esm", "esl", "bsa", "ba2", "modgroups" }; return result; } @@ -47,4 +47,4 @@ GamebryoModDataChecker::CheckReturn GamebryoModDataChecker::dataLooksValid(std:: } } return CheckReturn::INVALID; -} \ No newline at end of file +} From 8892cfe5f485e4456cd35db920a5a49757f68756 Mon Sep 17 00:00:00 2001 From: isanae <14251494+isanae@users.noreply.github.com> Date: Fri, 10 Jul 2020 11:35:55 -0400 Subject: [PATCH 0967/1544] added the gamebryo translation file turned off translations for the creation project, they're the same as gamebryo --- src/creation/CMakeLists.txt | 1 + src/game_gamebryo_en.ts | 155 ++++++++++++++++++++++++++++++++++++ 2 files changed, 156 insertions(+) create mode 100644 src/game_gamebryo_en.ts diff --git a/src/creation/CMakeLists.txt b/src/creation/CMakeLists.txt index c4f6c921..d1d094d8 100644 --- a/src/creation/CMakeLists.txt +++ b/src/creation/CMakeLists.txt @@ -3,6 +3,7 @@ cmake_minimum_required(VERSION 3.16) project(game_creation) set(project_type lib) set(enable_warnings OFF) +set(create_translations OFF) # appveyor does not build modorganizer in its standard location, so use # DEPENDENCIES_DIR to find cmake_common diff --git a/src/game_gamebryo_en.ts b/src/game_gamebryo_en.ts new file mode 100644 index 00000000..a5cbfcd0 --- /dev/null +++ b/src/game_gamebryo_en.ts @@ -0,0 +1,155 @@ + + + + + GamebryoModDataContent + + + Plugins (ESP/ESM/ESL) + + + + + Optional Plugins + + + + + Interface + + + + + Meshes + + + + + Bethesda Archive + + + + + Scripts (Papyrus) + + + + + Script Extender Plugin + + + + + Script Extender Files + + + + + SkyProc Patcher + + + + + Sound or Music + + + + + Textures + + + + + MCM Configuration + + + + + INI Files + + + + + ModGroup Files + + + + + GamebryoSaveGameInfoWidget + + + Save # + + + + + Character + + + + + Level + + + + + Location + + + + + Date + + + + + Has Script Extender Data + + + + + Missing ESPs + + + + + + None + + + + + Missing ESLs + + + + + QObject + + + + Some of your plugins have invalid names! These plugins can not be loaded by the game. Please see mo_interface.log for a list of affected plugins and rename them. + + + + + failed to open %1 + + + + + wrong file format - expected %1 got %2 + + + + + failed to query registry path (preflight): %1 + + + + + failed to query registry path (read): %1 + + + + From 4fbcbc68381e30cd0a71569bdb1c77e5a857dde3 Mon Sep 17 00:00:00 2001 From: isanae <14251494+isanae@users.noreply.github.com> Date: Fri, 10 Jul 2020 12:02:06 -0400 Subject: [PATCH 0968/1544] [game_fallout3] updated translations --- src/games/fallout3/src/game_fallout3_en.ts | 79 +--------------------- 1 file changed, 1 insertion(+), 78 deletions(-) diff --git a/src/games/fallout3/src/game_fallout3_en.ts b/src/games/fallout3/src/game_fallout3_en.ts index 334bc0be..a6f77373 100644 --- a/src/games/fallout3/src/game_fallout3_en.ts +++ b/src/games/fallout3/src/game_fallout3_en.ts @@ -4,86 +4,9 @@ GameFallout3 - + Adds support for the game Fallout 3s - - GamebryoSaveGameInfoWidget - - - Save # - - - - - Character - - - - - Level - - - - - Location - - - - - Date - - - - - Has Script Extender Data - - - - - Missing ESPs - - - - - - None - - - - - Missing ESLs - - - - - QObject - - - Some of your plugins have invalid names! These plugins can not be loaded by the game. Please see mo_interface.log for a list of affected plugins and rename them. - - - - - failed to open %1 - - - - - wrong file format - expected %1 got %2 - - - - - failed to query registry path (preflight): %1 - - - - - failed to query registry path (read): %1 - - - From e42cd4358265317381021200a3095b80e10b0c6a Mon Sep 17 00:00:00 2001 From: isanae <14251494+isanae@users.noreply.github.com> Date: Fri, 10 Jul 2020 12:02:45 -0400 Subject: [PATCH 0969/1544] [game_fallout4] updated translations --- src/games/fallout4/src/game_fallout4_en.ts | 80 +--------------------- 1 file changed, 1 insertion(+), 79 deletions(-) diff --git a/src/games/fallout4/src/game_fallout4_en.ts b/src/games/fallout4/src/game_fallout4_en.ts index 81bc0496..b80846b9 100644 --- a/src/games/fallout4/src/game_fallout4_en.ts +++ b/src/games/fallout4/src/game_fallout4_en.ts @@ -4,88 +4,10 @@ GameFallout4 - + Adds support for the game Fallout 4. Splash by %1 - - GamebryoSaveGameInfoWidget - - - Save # - - - - - Character - - - - - Level - - - - - Location - - - - - Date - - - - - Has Script Extender Data - - - - - Missing ESPs - - - - - - None - - - - - Missing ESLs - - - - - QObject - - - - Some of your plugins have invalid names! These plugins can not be loaded by the game. Please see mo_interface.log for a list of affected plugins and rename them. - - - - - failed to open %1 - - - - - wrong file format - expected %1 got %2 - - - - - failed to query registry path (preflight): %1 - - - - - failed to query registry path (read): %1 - - - From 9d0bc93237a5acadd0abf5ffec480ef498e55546 Mon Sep 17 00:00:00 2001 From: isanae <14251494+isanae@users.noreply.github.com> Date: Fri, 10 Jul 2020 12:03:23 -0400 Subject: [PATCH 0970/1544] [game_fallout4vr] updated translations --- .../fallout4vr/src/game_fallout4vr_en.ts | 80 +------------------ 1 file changed, 1 insertion(+), 79 deletions(-) diff --git a/src/games/fallout4vr/src/game_fallout4vr_en.ts b/src/games/fallout4vr/src/game_fallout4vr_en.ts index 97dfecee..916a4158 100644 --- a/src/games/fallout4vr/src/game_fallout4vr_en.ts +++ b/src/games/fallout4vr/src/game_fallout4vr_en.ts @@ -4,88 +4,10 @@ GameFallout4VR - + Adds support for the game Fallout 4 VR. Splash by %1 - - GamebryoSaveGameInfoWidget - - - Save # - - - - - Character - - - - - Level - - - - - Location - - - - - Date - - - - - Has Script Extender Data - - - - - Missing ESPs - - - - - - None - - - - - Missing ESLs - - - - - QObject - - - - Some of your plugins have invalid names! These plugins can not be loaded by the game. Please see mo_interface.log for a list of affected plugins and rename them. - - - - - failed to query registry path (preflight): %1 - - - - - failed to query registry path (read): %1 - - - - - failed to open %1 - - - - - wrong file format - expected %1 got %2 - - - From 86738151edcafedd337e821be9139d3bf34bd597 Mon Sep 17 00:00:00 2001 From: isanae <14251494+isanae@users.noreply.github.com> Date: Fri, 10 Jul 2020 12:04:32 -0400 Subject: [PATCH 0971/1544] [game_falloutnv] updated translations --- src/games/falloutnv/src/game_falloutNV_en.ts | 79 +------------------- 1 file changed, 1 insertion(+), 78 deletions(-) diff --git a/src/games/falloutnv/src/game_falloutNV_en.ts b/src/games/falloutnv/src/game_falloutNV_en.ts index 033df8e1..a44dd734 100644 --- a/src/games/falloutnv/src/game_falloutNV_en.ts +++ b/src/games/falloutnv/src/game_falloutNV_en.ts @@ -4,86 +4,9 @@ GameFalloutNV - + Adds support for the game Fallout New Vegas - - GamebryoSaveGameInfoWidget - - - Save # - - - - - Character - - - - - Level - - - - - Location - - - - - Date - - - - - Has Script Extender Data - - - - - Missing ESPs - - - - - - None - - - - - Missing ESLs - - - - - QObject - - - Some of your plugins have invalid names! These plugins can not be loaded by the game. Please see mo_interface.log for a list of affected plugins and rename them. - - - - - failed to open %1 - - - - - wrong file format - expected %1 got %2 - - - - - failed to query registry path (preflight): %1 - - - - - failed to query registry path (read): %1 - - - From e5aaad0ebc0000cbc1f0a331a7157077337734fd Mon Sep 17 00:00:00 2001 From: isanae <14251494+isanae@users.noreply.github.com> Date: Fri, 10 Jul 2020 12:05:33 -0400 Subject: [PATCH 0972/1544] [game_morrowind] updated translations --- src/games/morrowind/src/game_morrowind_en.ts | 72 +------------------- 1 file changed, 1 insertion(+), 71 deletions(-) diff --git a/src/games/morrowind/src/game_morrowind_en.ts b/src/games/morrowind/src/game_morrowind_en.ts index cd24c464..226f1bdf 100644 --- a/src/games/morrowind/src/game_morrowind_en.ts +++ b/src/games/morrowind/src/game_morrowind_en.ts @@ -4,61 +4,12 @@ GameMorrowind - + Adds support for the game Morrowind. Splash by %1 - - GamebryoSaveGameInfoWidget - - - Save # - - - - - Character - - - - - Level - - - - - Location - - - - - Date - - - - - Has Script Extender Data - - - - - Missing ESPs - - - - - - None - - - - - Missing ESLs - - - MorrowindSaveGameInfoWidget @@ -105,30 +56,9 @@ Splash by %1 QObject - Some of your plugins have invalid names! These plugins can not be loaded by the game. Please see mo_interface.log for a list of affected plugins and rename them. - - - failed to open %1 - - - - - wrong file format - expected %1 got %2 - - - - - failed to query registry path (preflight): %1 - - - - - failed to query registry path (read): %1 - - From 52f9632c36cedfc1067c0543a6328f18d5d50eeb Mon Sep 17 00:00:00 2001 From: isanae <14251494+isanae@users.noreply.github.com> Date: Fri, 10 Jul 2020 12:06:08 -0400 Subject: [PATCH 0973/1544] [game_oblivion] updated translations --- src/games/oblivion/src/game_oblivion_en.ts | 79 +--------------------- 1 file changed, 1 insertion(+), 78 deletions(-) diff --git a/src/games/oblivion/src/game_oblivion_en.ts b/src/games/oblivion/src/game_oblivion_en.ts index 75dda7e2..16dffce9 100644 --- a/src/games/oblivion/src/game_oblivion_en.ts +++ b/src/games/oblivion/src/game_oblivion_en.ts @@ -4,86 +4,9 @@ GameOblivion - + Adds support for the game Oblivion - - GamebryoSaveGameInfoWidget - - - Save # - - - - - Character - - - - - Level - - - - - Location - - - - - Date - - - - - Has Script Extender Data - - - - - Missing ESPs - - - - - - None - - - - - Missing ESLs - - - - - QObject - - - Some of your plugins have invalid names! These plugins can not be loaded by the game. Please see mo_interface.log for a list of affected plugins and rename them. - - - - - failed to open %1 - - - - - wrong file format - expected %1 got %2 - - - - - failed to query registry path (preflight): %1 - - - - - failed to query registry path (read): %1 - - - From 15ac58c82d61b357ea6831f187dfb7f246d6cc81 Mon Sep 17 00:00:00 2001 From: isanae <14251494+isanae@users.noreply.github.com> Date: Fri, 10 Jul 2020 12:06:40 -0400 Subject: [PATCH 0974/1544] [game_skyrim] updated translations --- src/games/skyrim/src/game_skyrim_en.ts | 79 +------------------------- 1 file changed, 1 insertion(+), 78 deletions(-) diff --git a/src/games/skyrim/src/game_skyrim_en.ts b/src/games/skyrim/src/game_skyrim_en.ts index 72f08d7f..4cf9d8ce 100644 --- a/src/games/skyrim/src/game_skyrim_en.ts +++ b/src/games/skyrim/src/game_skyrim_en.ts @@ -4,86 +4,9 @@ GameSkyrim - + Adds support for the game Skyrim - - GamebryoSaveGameInfoWidget - - - Save # - - - - - Character - - - - - Level - - - - - Location - - - - - Date - - - - - Has Script Extender Data - - - - - Missing ESPs - - - - - - None - - - - - Missing ESLs - - - - - QObject - - - Some of your plugins have invalid names! These plugins can not be loaded by the game. Please see mo_interface.log for a list of affected plugins and rename them. - - - - - failed to open %1 - - - - - wrong file format - expected %1 got %2 - - - - - failed to query registry path (preflight): %1 - - - - - failed to query registry path (read): %1 - - - From e19ad0d4848e63ef4d4d1c905664691c38be2125 Mon Sep 17 00:00:00 2001 From: isanae <14251494+isanae@users.noreply.github.com> Date: Fri, 10 Jul 2020 12:07:06 -0400 Subject: [PATCH 0975/1544] [game_skyrimse] updated translations --- src/games/skyrimse/src/game_skyrimse_en.ts | 80 +--------------------- 1 file changed, 1 insertion(+), 79 deletions(-) diff --git a/src/games/skyrimse/src/game_skyrimse_en.ts b/src/games/skyrimse/src/game_skyrimse_en.ts index 615c27d1..30758a37 100644 --- a/src/games/skyrimse/src/game_skyrimse_en.ts +++ b/src/games/skyrimse/src/game_skyrimse_en.ts @@ -4,87 +4,9 @@ GameSkyrimSE - + Adds support for the game Skyrim Special Edition. - - GamebryoSaveGameInfoWidget - - - Save # - - - - - Character - - - - - Level - - - - - Location - - - - - Date - - - - - Has Script Extender Data - - - - - Missing ESPs - - - - - - None - - - - - Missing ESLs - - - - - QObject - - - failed to query registry path (preflight): %1 - - - - - failed to query registry path (read): %1 - - - - - - Some of your plugins have invalid names! These plugins can not be loaded by the game. Please see mo_interface.log for a list of affected plugins and rename them. - - - - - failed to open %1 - - - - - wrong file format - expected %1 got %2 - - - From 11e937b164900c9672cb3ad7eb0af492566f775b Mon Sep 17 00:00:00 2001 From: isanae <14251494+isanae@users.noreply.github.com> Date: Fri, 10 Jul 2020 12:07:43 -0400 Subject: [PATCH 0976/1544] [game_skyrimvr] updated translations --- src/games/skyrimvr/src/game_skyrimvr_en.ts | 80 +--------------------- 1 file changed, 1 insertion(+), 79 deletions(-) diff --git a/src/games/skyrimvr/src/game_skyrimvr_en.ts b/src/games/skyrimvr/src/game_skyrimvr_en.ts index d1c07d1a..398fc857 100644 --- a/src/games/skyrimvr/src/game_skyrimvr_en.ts +++ b/src/games/skyrimvr/src/game_skyrimvr_en.ts @@ -4,87 +4,9 @@ GameSkyrimVR - + Adds support for the game Skyrim VR. - - GamebryoSaveGameInfoWidget - - - Save # - - - - - Character - - - - - Level - - - - - Location - - - - - Date - - - - - Has Script Extender Data - - - - - Missing ESPs - - - - - - None - - - - - Missing ESLs - - - - - QObject - - - failed to query registry path (preflight): %1 - - - - - failed to query registry path (read): %1 - - - - - - Some of your plugins have invalid names! These plugins can not be loaded by the game. Please see mo_interface.log for a list of affected plugins and rename them. - - - - - failed to open %1 - - - - - wrong file format - expected %1 got %2 - - - From 21ba583fb00c9188cb2b359f25509ba42f558890 Mon Sep 17 00:00:00 2001 From: isanae <14251494+isanae@users.noreply.github.com> Date: Fri, 10 Jul 2020 12:08:09 -0400 Subject: [PATCH 0977/1544] [game_ttw] updated translations --- src/games/ttw/src/game_ttw_en.ts | 79 +------------------------------- 1 file changed, 1 insertion(+), 78 deletions(-) diff --git a/src/games/ttw/src/game_ttw_en.ts b/src/games/ttw/src/game_ttw_en.ts index 2beca918..18ee55e7 100644 --- a/src/games/ttw/src/game_ttw_en.ts +++ b/src/games/ttw/src/game_ttw_en.ts @@ -4,86 +4,9 @@ GameFalloutTTW - + Adds support for the game Fallout TTW - - GamebryoSaveGameInfoWidget - - - Save # - - - - - Character - - - - - Level - - - - - Location - - - - - Date - - - - - Has Script Extender Data - - - - - Missing ESPs - - - - - - None - - - - - Missing ESLs - - - - - QObject - - - Some of your plugins have invalid names! These plugins can not be loaded by the game. Please see mo_interface.log for a list of affected plugins and rename them. - - - - - failed to open %1 - - - - - wrong file format - expected %1 got %2 - - - - - failed to query registry path (preflight): %1 - - - - - failed to query registry path (read): %1 - - - From c020b58734772c6d93ef008e227145f3ab886a71 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Mika=C3=ABl=20Capelle?= Date: Sat, 1 Aug 2020 19:09:32 +0200 Subject: [PATCH 0978/1544] [game_skyrimvr] Fix modgroups. --- src/games/skyrimvr/src/skyrimvrmoddatachecker.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/games/skyrimvr/src/skyrimvrmoddatachecker.h b/src/games/skyrimvr/src/skyrimvrmoddatachecker.h index 3703fbf2..c0ce9fa8 100644 --- a/src/games/skyrimvr/src/skyrimvrmoddatachecker.h +++ b/src/games/skyrimvr/src/skyrimvrmoddatachecker.h @@ -20,7 +20,7 @@ protected: } virtual const FileNameSet& possibleFileExtensions() const override { static FileNameSet result{ - "esp", "esm", "bsa", ".modgroups" + "esp", "esm", "bsa", "modgroups" }; return result; } From f014a2f9c09c08fe40dbf427d193291cc114480f Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Mika=C3=ABl=20Capelle?= Date: Sat, 1 Aug 2020 19:41:08 +0200 Subject: [PATCH 0979/1544] [game_fallout76] Create README.md --- src/games/fallout76/README.md | 4 ++++ 1 file changed, 4 insertions(+) create mode 100644 src/games/fallout76/README.md diff --git a/src/games/fallout76/README.md b/src/games/fallout76/README.md new file mode 100644 index 00000000..ae62be76 --- /dev/null +++ b/src/games/fallout76/README.md @@ -0,0 +1,4 @@ +# MO2 Plugin to support Fallout 76 + +This is the continuation of https://github.com/EntranceJew/modorganizer-game_fallout76 +This is not a Fork because the former is already a fork of the Fallout 4 game plugin which is making things messy. From 6607dba8c0402f232d2406c704ead6e391531c13 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Mika=C3=ABl=20Capelle?= Date: Sat, 1 Aug 2020 19:53:14 +0200 Subject: [PATCH 0980/1544] [game_fallout76] Update to use cmake_common. --- src/games/fallout76/CMakeLists.txt | 23 +++---- src/games/fallout76/src/CMakeLists.txt | 88 ++------------------------ 2 files changed, 17 insertions(+), 94 deletions(-) diff --git a/src/games/fallout76/CMakeLists.txt b/src/games/fallout76/CMakeLists.txt index 77aa297e..503b6ae0 100644 --- a/src/games/fallout76/CMakeLists.txt +++ b/src/games/fallout76/CMakeLists.txt @@ -1,15 +1,12 @@ -CMAKE_MINIMUM_REQUIRED(VERSION 2.8.12) +cmake_minimum_required(VERSION 3.16) -ADD_COMPILE_OPTIONS($<$:/MP>) +project(game_fallout76) +set(project_type plugin) +set(enable_warnings OFF) -SET(PROJ_NAME game_fallout76) - -PROJECT(${PROJ_NAME}) - -SET(DEPENDENCIES_DIR CACHE PATH "") - -# hint to find qt in dependencies path -LIST(APPEND CMAKE_PREFIX_PATH ${QT_ROOT}/lib/cmake) -LIST(APPEND CMAKE_PREFIX_PATH ${LZ4_ROOT}/dll) - -ADD_SUBDIRECTORY(src) +if(DEFINED DEPENDENCIES_DIR) + include(${DEPENDENCIES_DIR}/modorganizer_super/cmake_common/project.cmake) +else() + include(../cmake_common/project.cmake) +endif() +add_subdirectory(src) diff --git a/src/games/fallout76/src/CMakeLists.txt b/src/games/fallout76/src/CMakeLists.txt index 3bf8c0a1..3b4e7319 100644 --- a/src/games/fallout76/src/CMakeLists.txt +++ b/src/games/fallout76/src/CMakeLists.txt @@ -1,82 +1,8 @@ -CMAKE_MINIMUM_REQUIRED (VERSION 2.8.11) +cmake_minimum_required(VERSION 3.16) +if(DEFINED DEPENDENCIES_DIR) + include(${DEPENDENCIES_DIR}/modorganizer_super/cmake_common/src.cmake) +else() + include(../../cmake_common/src.cmake) +endif() -CMAKE_POLICY(SET CMP0020 NEW) - -FILE(GLOB ${PROJ_NAME}_SRCS *.cpp) -FILE(GLOB ${PROJ_NAME}_HDRS *.h) -FILE(GLOB ${PROJ_NAME}_FORMS *.ui) - -SET(${PROJ_NAME}_QRCS - fallout76.qrc - ) - -SET(CMAKE_INCLUDE_CURRENT_DIR ON) -SET(CMAKE_AUTOMOC ON) -SET(CMAKE_AUTOUIC ON) -FIND_PACKAGE(Qt5Widgets REQUIRED) -QT5_WRAP_UI(${PROJ_NAME}_UIHDRS ${${PROJ_NAME}_FORMS}) -QT5_ADD_RESOURCES(${PROJ_NAME}_RCCPPS ${${PROJ_NAME}_QRCS}) - -SET(default_project_path "${CMAKE_SOURCE_DIR}/..") -GET_FILENAME_COMPONENT(${default_project_path} ${default_project_path} REALPATH) - -SET(project_path "${default_project_path}" CACHE PATH "path to the other mo projects") - -FIND_PACKAGE(Qt5LinguistTools) -SET(translation_sources ${CMAKE_SOURCE_DIR}/src ${project_path}/game_gamebryo/src/gamebryo ${project_path}/game_gamebryo/src/creation) -QT5_CREATE_TRANSLATION(${PROJ_NAME}_translations_qm ${translation_sources} ${CMAKE_SOURCE_DIR}/src/${PROJ_NAME}_en.ts) - -SET(Boost_USE_STATIC_LIBS ON) -SET(Boost_USE_MULTITHREADED ON) -SET(Boost_USE_STATIC_RUNTIME OFF) -FIND_PACKAGE(Boost) - -IF (Boost_FOUND) - INCLUDE_DIRECTORIES(${Boost_INCLUDE_DIRS}) -ENDIF () - -SET(lib_path "${project_path}/../../install/libs") - -INCLUDE_DIRECTORIES(${project_path}/uibase/src - ${project_path}/game_features/src - ${project_path}/game_gamebryo/src/gamebryo - ${project_path}/game_gamebryo/src/creation) -LINK_DIRECTORIES(${project_path}/uibase/build/src - ${lib_path} - ${LZ4_ROOT}/dll) - - -ADD_LIBRARY(${PROJ_NAME} SHARED ${${PROJ_NAME}_HDRS} ${${PROJ_NAME}_SRCS} ${${PROJ_NAME}_UIHDRS} ${${PROJ_NAME}_RCCPPS} ${${PROJ_NAME}_translations_qm}) -TARGET_LINK_LIBRARIES(${PROJ_NAME} - Qt5::Widgets - ${Boost_LIBRARIES} - DbgHelp - uibase - Version - liblz4 - game_gamebryo - game_creation) - -IF (MSVC) - SET_TARGET_PROPERTIES(${PROJ_NAME} PROPERTIES COMPILE_FLAGS "/std:c++latest") -ENDIF() -IF (MSVC AND CMAKE_SIZEOF_VOID_P EQUAL 4) - # 32 bits - SET_TARGET_PROPERTIES(${PROJ_NAME} PROPERTIES LINK_FLAGS "/LARGEADDRESSAWARE") -ENDIF() - -IF (NOT "${OPTIMIZE_COMPILE_FLAGS}" STREQUAL "") - SET_TARGET_PROPERTIES(${PROJ_NAME} PROPERTIES COMPILE_FLAGS_RELWITHDEBINFO ${OPTIMIZE_COMPILE_FLAGS}) -ENDIF() -IF (NOT "${OPTIMIZE_LINK_FLAGS}" STREQUAL "") - SET_TARGET_PROPERTIES(${PROJ_NAME} PROPERTIES LINK_FLAGS_RELWITHDEBINFO ${OPTIMIZE_LINK_FLAGS}) -ENDIF() - - -############### -## Installation - -INSTALL(TARGETS ${PROJ_NAME} - RUNTIME DESTINATION bin/plugins) -INSTALL(FILES $ - DESTINATION pdb) +requires_project(game_features game_gamebryo) From 2ec12e394ba5c7a341c0f438f72fb632bc0d90a4 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Mika=C3=ABl=20Capelle?= Date: Sat, 1 Aug 2020 19:53:34 +0200 Subject: [PATCH 0981/1544] [game_fallout76] Fix DataArchives game feature. --- src/games/fallout76/src/fallout76dataarchives.h | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/src/games/fallout76/src/fallout76dataarchives.h b/src/games/fallout76/src/fallout76dataarchives.h index 9248c088..93fc5a3e 100644 --- a/src/games/fallout76/src/fallout76dataarchives.h +++ b/src/games/fallout76/src/fallout76dataarchives.h @@ -18,12 +18,12 @@ public: public: virtual QStringList vanillaArchives() const override; - virtual QStringList Fallout76DataArchives::sResourceIndexFileList() const; - virtual QStringList Fallout76DataArchives::sResourceStartUpArchiveList() const; - virtual QStringList Fallout76DataArchives::SResourceArchiveMemoryCacheList() const; - virtual QStringList Fallout76DataArchives::SResourceArchiveList() const; - virtual QStringList Fallout76DataArchives::SResourceArchiveList2() const; - virtual QStringList Fallout76DataArchives::sResourceArchive2List() const; + virtual QStringList sResourceIndexFileList() const; + virtual QStringList sResourceStartUpArchiveList() const; + virtual QStringList SResourceArchiveMemoryCacheList() const; + virtual QStringList SResourceArchiveList() const; + virtual QStringList SResourceArchiveList2() const; + virtual QStringList sResourceArchive2List() const; virtual QStringList archives(const MOBase::IProfile *profile) const override; private: From 76531afed43defa0807a546c10313baeef74d10f Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Mika=C3=ABl=20Capelle?= Date: Sat, 1 Aug 2020 19:54:03 +0200 Subject: [PATCH 0982/1544] [game_fallout76] Update game plugin with missing members. --- src/games/fallout76/src/gamefallout76.cpp | 8 ++++++-- src/games/fallout76/src/gamefallout76.h | 1 + 2 files changed, 7 insertions(+), 2 deletions(-) diff --git a/src/games/fallout76/src/gamefallout76.cpp b/src/games/fallout76/src/gamefallout76.cpp index 59062ca8..235c7b34 100644 --- a/src/games/fallout76/src/gamefallout76.cpp +++ b/src/games/fallout76/src/gamefallout76.cpp @@ -61,6 +61,10 @@ QList GameFallout76::executables() const ; } +QList GameFallout76::executableForcedLoads() const { + return {}; +} + QString GameFallout76::name() const { return "Fallout 76 Support Plugin"; @@ -68,7 +72,7 @@ QString GameFallout76::name() const QString GameFallout76::author() const { - return "EntranceJew"; + return "EntranceJew & Holt59"; } QString GameFallout76::description() const @@ -79,7 +83,7 @@ QString GameFallout76::description() const MOBase::VersionInfo GameFallout76::version() const { - return VersionInfo(1, 0, 1, VersionInfo::RELEASE_FINAL); + return VersionInfo(2, 0, 0, VersionInfo::RELEASE_ALPHA); } bool GameFallout76::isActive() const diff --git a/src/games/fallout76/src/gamefallout76.h b/src/games/fallout76/src/gamefallout76.h index 45359932..ce083d42 100644 --- a/src/games/fallout76/src/gamefallout76.h +++ b/src/games/fallout76/src/gamefallout76.h @@ -23,6 +23,7 @@ public: // IPluginGame interface virtual QString gameName() const override; virtual QList executables() const override; + virtual QList executableForcedLoads() const override; virtual void initializeProfile(const QDir &path, ProfileSettings settings) const override; virtual QString savegameExtension() const override; virtual QString savegameSEExtension() const override; From 4a8f6bfabee38cf62b6bc035efe7335ee4f1eef4 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Mika=C3=ABl=20Capelle?= Date: Sat, 1 Aug 2020 19:54:20 +0200 Subject: [PATCH 0983/1544] [game_fallout76] Add ModDataContent and ModDataChecker. --- .../fallout76/src/fallout76moddatachecker.h | 29 ++++++ .../fallout76/src/fallout76moddatacontent.h | 41 +++++++++ src/games/fallout76/src/game_fallout76_en.ts | 92 +------------------ src/games/fallout76/src/gamefallout76.cpp | 4 + 4 files changed, 75 insertions(+), 91 deletions(-) create mode 100644 src/games/fallout76/src/fallout76moddatachecker.h create mode 100644 src/games/fallout76/src/fallout76moddatacontent.h diff --git a/src/games/fallout76/src/fallout76moddatachecker.h b/src/games/fallout76/src/fallout76moddatachecker.h new file mode 100644 index 00000000..3fd1730b --- /dev/null +++ b/src/games/fallout76/src/fallout76moddatachecker.h @@ -0,0 +1,29 @@ +#ifndef FALLOUT4_MODATACHECKER_H +#define FALLOUT4_MODATACHECKER_H + +#include + +class Fallout76ModDataChecker : public GamebryoModDataChecker +{ +public: + using GamebryoModDataChecker::GamebryoModDataChecker; + +protected: + virtual const FileNameSet& possibleFolderNames() const override { + static FileNameSet result{ + "interface", "meshes", "music", "scripts", "sound", "strings", "textures", + "trees", "video", "materials", "f4se", "distantlod", "asi", "Tools", "MCM", + "distantland", "mits", "dllplugins", "CalienteTools", "NetScriptFramework", + "shadersfx", "aaf" + }; + return result; + } + virtual const FileNameSet& possibleFileExtensions() const override { + static FileNameSet result{ + "esp", "esm", "esl", "ba2", "modgroups" + }; + return result; + } +}; + +#endif // FALLOUT4_MODATACHECKER_H diff --git a/src/games/fallout76/src/fallout76moddatacontent.h b/src/games/fallout76/src/fallout76moddatacontent.h new file mode 100644 index 00000000..a38420f6 --- /dev/null +++ b/src/games/fallout76/src/fallout76moddatacontent.h @@ -0,0 +1,41 @@ +#ifndef FALLOUT4_MODDATACONTENT_H +#define FALLOUT4_MODDATACONTENT_H + +#include +#include + +class Fallout76ModDataContent : public GamebryoModDataContent { +protected: + enum Fallout4Content { + CONTENT_MATERIAL = CONTENT_NEXT_VALUE + }; + +public: + Fallout76ModDataContent(GameGamebryo const* gamePlugin) : + GamebryoModDataContent(gamePlugin) + { + m_Enabled[CONTENT_SKYPROC] = false; + } + + std::vector getAllContents() const override + { + auto contents = GamebryoModDataContent::getAllContents(); + contents.push_back(Content(CONTENT_MATERIAL, "Materials", ":/MO/gui/content/material")); + return contents; + } + + std::vector getContentsFor( + std::shared_ptr fileTree) const override + { + auto contents = GamebryoModDataContent::getContentsFor(fileTree); + for (auto e : *fileTree) { + if (e->compare("materials") == 0) { + contents.push_back(CONTENT_MATERIAL); + break; // Early break if you have nothing else to check. + } + } + return contents; + } +}; + +#endif // FALLOUT4_MODDATACONTENT_H \ No newline at end of file diff --git a/src/games/fallout76/src/game_fallout76_en.ts b/src/games/fallout76/src/game_fallout76_en.ts index de99c8d5..397b03f6 100644 --- a/src/games/fallout76/src/game_fallout76_en.ts +++ b/src/games/fallout76/src/game_fallout76_en.ts @@ -4,100 +4,10 @@ GameFallout76 - + Adds support for the game Fallout 76. Splash by %1 - - GamebryoSaveGameInfoWidget - - - Save # - - - - - Character - - - - - Level - - - - - Location - - - - - Date - - - - - Has Script Extender Data - - - - - Missing ESPs - - - - - - None - - - - - Missing ESLs - - - - - QObject - - - - Some of your plugins have invalid names! These plugins can not be loaded by the game. Please see mo_interface.log for a list of affected plugins and rename them. - - - - - - - failed to activate BSA invalidation in "%1" (errorcode %2) - - - - - failed to open %1 - - - - - wrong file format - expected %1 got %2 - - - - - failed to query registry path (preflight): %1 - - - - - failed to query registry path (read): %1 - - - - - failed to set archive key in %1 (errorcode %2) - - - diff --git a/src/games/fallout76/src/gamefallout76.cpp b/src/games/fallout76/src/gamefallout76.cpp index 235c7b34..5727cbdb 100644 --- a/src/games/fallout76/src/gamefallout76.cpp +++ b/src/games/fallout76/src/gamefallout76.cpp @@ -1,6 +1,8 @@ #include "gameFallout76.h" #include "fallout76dataarchives.h" +#include "fallout76moddatachecker.h" +#include "fallout76moddatacontent.h" #include "fallout76scriptextender.h" #include "fallout76savegameinfo.h" #include "fallout76unmanagedmods.h" @@ -38,6 +40,8 @@ bool GameFallout76::init(IOrganizer *moInfo) registerFeature(new Fallout76ScriptExtender(this)); registerFeature(new Fallout76DataArchives(myGamesPath())); registerFeature(new GamebryoLocalSavegames(myGamesPath(), "Fallout76.ini")); + registerFeature(new Fallout76ModDataChecker(this)); + registerFeature(new Fallout76ModDataContent(this)); registerFeature(new Fallout76SaveGameInfo(this)); registerFeature(new CreationGamePlugins(moInfo)); registerFeature(new Fallout76UnmangedMods(this)); From 5213342fbd6a395d55781d82426879a52134af71 Mon Sep 17 00:00:00 2001 From: isanae <14251494+isanae@users.noreply.github.com> Date: Wed, 5 Aug 2020 11:48:25 -0400 Subject: [PATCH 0984/1544] mismatched lower/upper case --- src/gamebryo/gamebryogameplugins.cpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/gamebryo/gamebryogameplugins.cpp b/src/gamebryo/gamebryogameplugins.cpp index ffec3427..301df04b 100644 --- a/src/gamebryo/gamebryogameplugins.cpp +++ b/src/gamebryo/gamebryogameplugins.cpp @@ -147,11 +147,11 @@ QStringList GamebryoGamePlugins::readLoadOrderList( std::set pluginLookup; for (auto&& name : pluginNames) { - pluginLookup.insert(name); + pluginLookup.insert(name.toLower()); } const auto b = MOBase::forEachLineInFile(filePath, [&](QString s) { - if (!pluginLookup.contains(s)) { + if (!pluginLookup.contains(s.toLower())) { pluginLookup.insert(s); pluginNames.push_back(std::move(s)); } From 3ec51e5c8ed1c8d9ad55e182d24cbe95e2a0dca9 Mon Sep 17 00:00:00 2001 From: isanae <14251494+isanae@users.noreply.github.com> Date: Wed, 5 Aug 2020 11:49:15 -0400 Subject: [PATCH 0985/1544] [game_morrowind] removeAll() was called inside a loop over the same list --- src/games/morrowind/src/morrowindgameplugins.cpp | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/src/games/morrowind/src/morrowindgameplugins.cpp b/src/games/morrowind/src/morrowindgameplugins.cpp index 9550bb8d..3c96ba26 100644 --- a/src/games/morrowind/src/morrowindgameplugins.cpp +++ b/src/games/morrowind/src/morrowindgameplugins.cpp @@ -133,7 +133,8 @@ QStringList MorrowindGamePlugins::readPluginList(MOBase::IPluginList *pluginList } QStringList plugins = pluginList->pluginNames(); // Do not sort the primary plugins. Their load order should be locked as defined in "primaryPlugins". - for (QString plugin : plugins) { + const QStringList pluginsClone(plugins); + for (QString plugin : pluginsClone) { if (primary.contains(plugin, Qt::CaseInsensitive)) plugins.removeAll(plugin); } From 2ce6baa466feaa0980f0116cf7ac64a40202f0a6 Mon Sep 17 00:00:00 2001 From: isanae <14251494+isanae@users.noreply.github.com> Date: Wed, 5 Aug 2020 11:50:04 -0400 Subject: [PATCH 0986/1544] [game_skyrimse] mismatched lower/upper case --- src/games/skyrimse/src/gameskyrimse.cpp | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/src/games/skyrimse/src/gameskyrimse.cpp b/src/games/skyrimse/src/gameskyrimse.cpp index 6b2f4104..7e8fe314 100644 --- a/src/games/skyrimse/src/gameskyrimse.cpp +++ b/src/games/skyrimse/src/gameskyrimse.cpp @@ -230,8 +230,9 @@ QStringList GameSkyrimSE::CCPlugins() const const QString path = gameDirectory().filePath("Skyrim.ccc"); MOBase::forEachLineInFile(path, [&](QString s) { - if (!pluginsLookup.contains(s)) { - pluginsLookup.insert(s); + const auto lc = s.toLower(); + if (!pluginsLookup.contains(lc)) { + pluginsLookup.insert(lc); plugins.append(std::move(s)); } }); From f327e306cefa3daeb29218e2b4b77d4e18a3682d Mon Sep 17 00:00:00 2001 From: isanae <14251494+isanae@users.noreply.github.com> Date: Wed, 5 Aug 2020 12:04:35 -0400 Subject: [PATCH 0987/1544] [game_skyrim] removeAll() was called inside a loop over the same list --- src/games/skyrim/src/skyrimgameplugins.cpp | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/src/games/skyrim/src/skyrimgameplugins.cpp b/src/games/skyrim/src/skyrimgameplugins.cpp index 4c4ab6c5..0b9ce583 100644 --- a/src/games/skyrim/src/skyrimgameplugins.cpp +++ b/src/games/skyrim/src/skyrimgameplugins.cpp @@ -68,7 +68,8 @@ QStringList SkyrimGamePlugins::readPluginList(MOBase::IPluginList *pluginList) } // Do not sort the primary plugins. Their load order should be locked as defined in "primaryPlugins". - for (QString plugin : plugins) { + const QStringList pluginsClone(plugins); + for (QString plugin : pluginsClone) { if (primaryPlugins.contains(plugin, Qt::CaseInsensitive)) plugins.removeAll(plugin); } From deced5f84b5297068125cb57649c603ba1062479 Mon Sep 17 00:00:00 2001 From: Chris Bessent Date: Fri, 18 Sep 2020 08:32:13 -0700 Subject: [PATCH 0988/1544] [game_skyrim] Allow Skyrim SE downloads This was requested by some folks as (1) some mod authors are putting Skyrim LE mods on Skyrim SE Nexus for some arcane reason and (2) people are apparently backporting Skyrim LE mods to Skyrim SE. --- src/games/skyrim/src/gameskyrim.cpp | 15 +++++++++++++-- src/games/skyrim/src/gameskyrim.h | 1 + 2 files changed, 14 insertions(+), 2 deletions(-) diff --git a/src/games/skyrim/src/gameskyrim.cpp b/src/games/skyrim/src/gameskyrim.cpp index 52382897..3be28b6b 100644 --- a/src/games/skyrim/src/gameskyrim.cpp +++ b/src/games/skyrim/src/gameskyrim.cpp @@ -93,7 +93,7 @@ QString GameSkyrim::description() const MOBase::VersionInfo GameSkyrim::version() const { - return VersionInfo(1, 4, 1, VersionInfo::RELEASE_FINAL); + return VersionInfo(1, 5, 0, VersionInfo::RELEASE_FINAL); } bool GameSkyrim::isActive() const @@ -103,7 +103,9 @@ bool GameSkyrim::isActive() const QList GameSkyrim::settings() const { - return QList(); + QList results; + results.push_back(PluginSetting("sse_downloads", "allow Skyrim SE downloads", QVariant(false))); + return results; } void GameSkyrim::initializeProfile(const QDir &path, ProfileSettings settings) const @@ -160,6 +162,15 @@ QString GameSkyrim::gameNexusName() const return "skyrim"; } +QStringList GameSkyrim::validShortNames() const +{ + QStringList results; + if (m_Organizer->pluginSetting(name(), "sse_downloads").toBool()) + { + results.push_back( "SkyrimSE" ); + } + return results; +} QStringList GameSkyrim::iniFiles() const { diff --git a/src/games/skyrim/src/gameskyrim.h b/src/games/skyrim/src/gameskyrim.h index 9e7daca5..d89b29a8 100644 --- a/src/games/skyrim/src/gameskyrim.h +++ b/src/games/skyrim/src/gameskyrim.h @@ -32,6 +32,7 @@ public: // IPluginGame interface virtual QString binaryName() const override; virtual QString gameShortName() const override; virtual QString gameNexusName() const override; + virtual QStringList validShortNames() const override; virtual QStringList iniFiles() const override; virtual QStringList DLCPlugins() const override; virtual LoadOrderMechanism loadOrderMechanism() const override; From 4b7a1d0eb16284a61e28e1b5201d98cc51d585fd Mon Sep 17 00:00:00 2001 From: Jeremy Rimpo Date: Sun, 20 Sep 2020 19:02:29 -0500 Subject: [PATCH 0989/1544] [game_fallout4vr] Update to checkout current branch in umbrella if it exists --- src/games/fallout4vr/appveyor.yml | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/src/games/fallout4vr/appveyor.yml b/src/games/fallout4vr/appveyor.yml index 8158a4e5..1fdab3b9 100644 --- a/src/games/fallout4vr/appveyor.yml +++ b/src/games/fallout4vr/appveyor.yml @@ -6,7 +6,8 @@ environment: secure: gOKbXaZM9ImtMD5XrYITvdyZUW/az082G9OIN1EC1Vbg57wBaeLhi49uGjxPw5GVujHku6kxN6ab89zhbS5GVeluR76GM83IbKV4Sh7udXzoYZZdg6YudtYHzdhCgUeiedpswbuczTq9ceIkkfSEWZuh/lMAAVVwvcGsJAnoPFw= build_script: - cmd: >- - git clone --depth=1 --branch=%APPVEYOR_REPO_BRANCH% https://github.com/ModOrganizer2/modorganizer-umbrella.git c:\projects\modorganizer-umbrella 2> $null + git clone --depth=1 https://github.com/ModOrganizer2/modorganizer-umbrella.git c:\projects\modorganizer-umbrella 2> $null + git checkout $(git show-ref --verify --quiet refs/remotes/origin/%APPVEYOR_REPO_BRANCH% || echo '-b') %APPVEYOR_REPO_BRANCH% mkdir c:\projects\modorganizer-build -type directory From e7b0a444fd44616bf43313510a4160a7823d3625 Mon Sep 17 00:00:00 2001 From: Jeremy Rimpo Date: Sun, 20 Sep 2020 19:02:30 -0500 Subject: [PATCH 0990/1544] [game_falloutnv] Update to checkout current branch in umbrella if it exists --- src/games/falloutnv/appveyor.yml | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/src/games/falloutnv/appveyor.yml b/src/games/falloutnv/appveyor.yml index c9d0630b..789d0112 100644 --- a/src/games/falloutnv/appveyor.yml +++ b/src/games/falloutnv/appveyor.yml @@ -6,7 +6,8 @@ environment: secure: gOKbXaZM9ImtMD5XrYITvdyZUW/az082G9OIN1EC1Vbg57wBaeLhi49uGjxPw5GVujHku6kxN6ab89zhbS5GVeluR76GM83IbKV4Sh7udXzoYZZdg6YudtYHzdhCgUeiedpswbuczTq9ceIkkfSEWZuh/lMAAVVwvcGsJAnoPFw= build_script: - cmd: >- - git clone --depth=1 --branch=%APPVEYOR_REPO_BRANCH% https://github.com/ModOrganizer2/modorganizer-umbrella.git c:\projects\modorganizer-umbrella 2> $null + git clone --depth=1 https://github.com/ModOrganizer2/modorganizer-umbrella.git c:\projects\modorganizer-umbrella 2> $null + git checkout $(git show-ref --verify --quiet refs/remotes/origin/%APPVEYOR_REPO_BRANCH% || echo '-b') %APPVEYOR_REPO_BRANCH% mkdir c:\projects\modorganizer-build -type directory From f6be875b07ac620fe41253d257540a164f06e318 Mon Sep 17 00:00:00 2001 From: Jeremy Rimpo Date: Sun, 20 Sep 2020 19:02:31 -0500 Subject: [PATCH 0991/1544] [game_morrowind] Update to checkout current branch in umbrella if it exists --- src/games/morrowind/appveyor.yml | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/src/games/morrowind/appveyor.yml b/src/games/morrowind/appveyor.yml index 90353113..9479a4e2 100644 --- a/src/games/morrowind/appveyor.yml +++ b/src/games/morrowind/appveyor.yml @@ -6,7 +6,8 @@ environment: secure: gOKbXaZM9ImtMD5XrYITvdyZUW/az082G9OIN1EC1Vbg57wBaeLhi49uGjxPw5GVujHku6kxN6ab89zhbS5GVeluR76GM83IbKV4Sh7udXzoYZZdg6YudtYHzdhCgUeiedpswbuczTq9ceIkkfSEWZuh/lMAAVVwvcGsJAnoPFw= build_script: - cmd: >- - git clone --depth=1 --branch=%APPVEYOR_REPO_BRANCH% https://github.com/ModOrganizer2/modorganizer-umbrella.git c:\projects\modorganizer-umbrella 2> $null + git clone --depth=1 https://github.com/ModOrganizer2/modorganizer-umbrella.git c:\projects\modorganizer-umbrella 2> $null + git checkout $(git show-ref --verify --quiet refs/remotes/origin/%APPVEYOR_REPO_BRANCH% || echo '-b') %APPVEYOR_REPO_BRANCH% mkdir c:\projects\modorganizer-build -type directory From c9d8fc2bb609f97f70c17c785cd76b57bad81d1b Mon Sep 17 00:00:00 2001 From: Jeremy Rimpo Date: Sun, 20 Sep 2020 19:02:34 -0500 Subject: [PATCH 0992/1544] [game_skyrimvr] Update to checkout current branch in umbrella if it exists --- src/games/skyrimvr/appveyor.yml | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/src/games/skyrimvr/appveyor.yml b/src/games/skyrimvr/appveyor.yml index f149e8e1..249a3658 100644 --- a/src/games/skyrimvr/appveyor.yml +++ b/src/games/skyrimvr/appveyor.yml @@ -6,7 +6,8 @@ environment: secure: gOKbXaZM9ImtMD5XrYITvdyZUW/az082G9OIN1EC1Vbg57wBaeLhi49uGjxPw5GVujHku6kxN6ab89zhbS5GVeluR76GM83IbKV4Sh7udXzoYZZdg6YudtYHzdhCgUeiedpswbuczTq9ceIkkfSEWZuh/lMAAVVwvcGsJAnoPFw= build_script: - cmd: >- - git clone --depth=1 --branch=%APPVEYOR_REPO_BRANCH% https://github.com/ModOrganizer2/modorganizer-umbrella.git c:\projects\modorganizer-umbrella 2> $null + git clone --depth=1 https://github.com/ModOrganizer2/modorganizer-umbrella.git c:\projects\modorganizer-umbrella 2> $null + git checkout $(git show-ref --verify --quiet refs/remotes/origin/%APPVEYOR_REPO_BRANCH% || echo '-b') %APPVEYOR_REPO_BRANCH% mkdir c:\projects\modorganizer-build -type directory From bbaee40a6140bd541407388ab77cca396c1a0e5a Mon Sep 17 00:00:00 2001 From: Jeremy Rimpo Date: Sun, 20 Sep 2020 19:02:35 -0500 Subject: [PATCH 0993/1544] Update to checkout current branch in umbrella if it exists --- appveyor.yml | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/appveyor.yml b/appveyor.yml index edd640d3..e609ead2 100644 --- a/appveyor.yml +++ b/appveyor.yml @@ -6,7 +6,8 @@ environment: secure: gOKbXaZM9ImtMD5XrYITvdyZUW/az082G9OIN1EC1Vbg57wBaeLhi49uGjxPw5GVujHku6kxN6ab89zhbS5GVeluR76GM83IbKV4Sh7udXzoYZZdg6YudtYHzdhCgUeiedpswbuczTq9ceIkkfSEWZuh/lMAAVVwvcGsJAnoPFw= build_script: - cmd: >- - git clone --depth=1 --branch=%APPVEYOR_REPO_BRANCH% https://github.com/ModOrganizer2/modorganizer-umbrella.git c:\projects\modorganizer-umbrella 2> $null + git clone --depth=1 https://github.com/ModOrganizer2/modorganizer-umbrella.git c:\projects\modorganizer-umbrella 2> $null + git checkout $(git show-ref --verify --quiet refs/remotes/origin/%APPVEYOR_REPO_BRANCH% || echo '-b') %APPVEYOR_REPO_BRANCH% mkdir c:\projects\modorganizer-build -type directory From 2347fe77f8bd997e8700e3bac78c5ee5afd73e25 Mon Sep 17 00:00:00 2001 From: Jeremy Rimpo Date: Sun, 20 Sep 2020 19:02:35 -0500 Subject: [PATCH 0994/1544] [game_fallout4] Update to checkout current branch in umbrella if it exists --- src/games/fallout4/appveyor.yml | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/src/games/fallout4/appveyor.yml b/src/games/fallout4/appveyor.yml index 5ef81b21..39e0504b 100644 --- a/src/games/fallout4/appveyor.yml +++ b/src/games/fallout4/appveyor.yml @@ -6,7 +6,8 @@ environment: secure: gOKbXaZM9ImtMD5XrYITvdyZUW/az082G9OIN1EC1Vbg57wBaeLhi49uGjxPw5GVujHku6kxN6ab89zhbS5GVeluR76GM83IbKV4Sh7udXzoYZZdg6YudtYHzdhCgUeiedpswbuczTq9ceIkkfSEWZuh/lMAAVVwvcGsJAnoPFw= build_script: - cmd: >- - git clone --depth=1 --branch=%APPVEYOR_REPO_BRANCH% https://github.com/ModOrganizer2/modorganizer-umbrella.git c:\projects\modorganizer-umbrella 2> $null + git clone --depth=1 https://github.com/ModOrganizer2/modorganizer-umbrella.git c:\projects\modorganizer-umbrella 2> $null + git checkout $(git show-ref --verify --quiet refs/remotes/origin/%APPVEYOR_REPO_BRANCH% || echo '-b') %APPVEYOR_REPO_BRANCH% mkdir c:\projects\modorganizer-build -type directory From c4e1f8792ce31f16d9d9562f44cf9bb638f969e9 Mon Sep 17 00:00:00 2001 From: Jeremy Rimpo Date: Sun, 20 Sep 2020 19:02:36 -0500 Subject: [PATCH 0995/1544] [game_fallout3] Update to checkout current branch in umbrella if it exists --- src/games/fallout3/appveyor.yml | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/src/games/fallout3/appveyor.yml b/src/games/fallout3/appveyor.yml index e776e806..d5ba1d9e 100644 --- a/src/games/fallout3/appveyor.yml +++ b/src/games/fallout3/appveyor.yml @@ -6,7 +6,8 @@ environment: secure: gOKbXaZM9ImtMD5XrYITvdyZUW/az082G9OIN1EC1Vbg57wBaeLhi49uGjxPw5GVujHku6kxN6ab89zhbS5GVeluR76GM83IbKV4Sh7udXzoYZZdg6YudtYHzdhCgUeiedpswbuczTq9ceIkkfSEWZuh/lMAAVVwvcGsJAnoPFw= build_script: - cmd: >- - git clone --depth=1 --branch=%APPVEYOR_REPO_BRANCH% https://github.com/ModOrganizer2/modorganizer-umbrella.git c:\projects\modorganizer-umbrella 2> $null + git clone --depth=1 https://github.com/ModOrganizer2/modorganizer-umbrella.git c:\projects\modorganizer-umbrella 2> $null + git checkout $(git show-ref --verify --quiet refs/remotes/origin/%APPVEYOR_REPO_BRANCH% || echo '-b') %APPVEYOR_REPO_BRANCH% mkdir c:\projects\modorganizer-build -type directory From f3691728e44bb18fd68341a892ca20bf2ed40e97 Mon Sep 17 00:00:00 2001 From: Jeremy Rimpo Date: Sun, 20 Sep 2020 19:02:37 -0500 Subject: [PATCH 0996/1544] [game_skyrimse] Update to checkout current branch in umbrella if it exists --- src/games/skyrimse/appveyor.yml | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/src/games/skyrimse/appveyor.yml b/src/games/skyrimse/appveyor.yml index ce9d17eb..90df5a2d 100644 --- a/src/games/skyrimse/appveyor.yml +++ b/src/games/skyrimse/appveyor.yml @@ -6,7 +6,8 @@ environment: secure: gOKbXaZM9ImtMD5XrYITvdyZUW/az082G9OIN1EC1Vbg57wBaeLhi49uGjxPw5GVujHku6kxN6ab89zhbS5GVeluR76GM83IbKV4Sh7udXzoYZZdg6YudtYHzdhCgUeiedpswbuczTq9ceIkkfSEWZuh/lMAAVVwvcGsJAnoPFw= build_script: - cmd: >- - git clone --depth=1 --branch=%APPVEYOR_REPO_BRANCH% https://github.com/ModOrganizer2/modorganizer-umbrella.git c:\projects\modorganizer-umbrella 2> $null + git clone --depth=1 https://github.com/ModOrganizer2/modorganizer-umbrella.git c:\projects\modorganizer-umbrella 2> $null + git checkout $(git show-ref --verify --quiet refs/remotes/origin/%APPVEYOR_REPO_BRANCH% || echo '-b') %APPVEYOR_REPO_BRANCH% mkdir c:\projects\modorganizer-build -type directory From 572a7c124307379e4f81bbd706f02e89dc1d2454 Mon Sep 17 00:00:00 2001 From: Jeremy Rimpo Date: Sun, 20 Sep 2020 19:02:38 -0500 Subject: [PATCH 0997/1544] [game_oblivion] Update to checkout current branch in umbrella if it exists --- src/games/oblivion/appveyor.yml | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/src/games/oblivion/appveyor.yml b/src/games/oblivion/appveyor.yml index 4abade28..341a3048 100644 --- a/src/games/oblivion/appveyor.yml +++ b/src/games/oblivion/appveyor.yml @@ -6,7 +6,8 @@ environment: secure: gOKbXaZM9ImtMD5XrYITvdyZUW/az082G9OIN1EC1Vbg57wBaeLhi49uGjxPw5GVujHku6kxN6ab89zhbS5GVeluR76GM83IbKV4Sh7udXzoYZZdg6YudtYHzdhCgUeiedpswbuczTq9ceIkkfSEWZuh/lMAAVVwvcGsJAnoPFw= build_script: - cmd: >- - git clone --depth=1 --branch=%APPVEYOR_REPO_BRANCH% https://github.com/ModOrganizer2/modorganizer-umbrella.git c:\projects\modorganizer-umbrella 2> $null + git clone --depth=1 https://github.com/ModOrganizer2/modorganizer-umbrella.git c:\projects\modorganizer-umbrella 2> $null + git checkout $(git show-ref --verify --quiet refs/remotes/origin/%APPVEYOR_REPO_BRANCH% || echo '-b') %APPVEYOR_REPO_BRANCH% mkdir c:\projects\modorganizer-build -type directory From fce07de20ddbcad4544ffb85a424688a9802f3ac Mon Sep 17 00:00:00 2001 From: Jeremy Rimpo Date: Sun, 20 Sep 2020 19:02:40 -0500 Subject: [PATCH 0998/1544] [game_skyrim] Update to checkout current branch in umbrella if it exists --- src/games/skyrim/appveyor.yml | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/src/games/skyrim/appveyor.yml b/src/games/skyrim/appveyor.yml index 5938d9ed..6def2f88 100644 --- a/src/games/skyrim/appveyor.yml +++ b/src/games/skyrim/appveyor.yml @@ -6,7 +6,8 @@ environment: secure: gOKbXaZM9ImtMD5XrYITvdyZUW/az082G9OIN1EC1Vbg57wBaeLhi49uGjxPw5GVujHku6kxN6ab89zhbS5GVeluR76GM83IbKV4Sh7udXzoYZZdg6YudtYHzdhCgUeiedpswbuczTq9ceIkkfSEWZuh/lMAAVVwvcGsJAnoPFw= build_script: - cmd: >- - git clone --depth=1 --branch=%APPVEYOR_REPO_BRANCH% https://github.com/ModOrganizer2/modorganizer-umbrella.git c:\projects\modorganizer-umbrella 2> $null + git clone --depth=1 https://github.com/ModOrganizer2/modorganizer-umbrella.git c:\projects\modorganizer-umbrella 2> $null + git checkout $(git show-ref --verify --quiet refs/remotes/origin/%APPVEYOR_REPO_BRANCH% || echo '-b') %APPVEYOR_REPO_BRANCH% mkdir c:\projects\modorganizer-build -type directory From cfd862c5f86675d4b74e514dcf626ee55f68df90 Mon Sep 17 00:00:00 2001 From: Jeremy Rimpo Date: Sun, 20 Sep 2020 19:02:43 -0500 Subject: [PATCH 0999/1544] [game_ttw] Update to checkout current branch in umbrella if it exists --- src/games/ttw/appveyor.yml | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/src/games/ttw/appveyor.yml b/src/games/ttw/appveyor.yml index 87eccb06..b1a7f0d4 100644 --- a/src/games/ttw/appveyor.yml +++ b/src/games/ttw/appveyor.yml @@ -6,7 +6,8 @@ environment: secure: gOKbXaZM9ImtMD5XrYITvdyZUW/az082G9OIN1EC1Vbg57wBaeLhi49uGjxPw5GVujHku6kxN6ab89zhbS5GVeluR76GM83IbKV4Sh7udXzoYZZdg6YudtYHzdhCgUeiedpswbuczTq9ceIkkfSEWZuh/lMAAVVwvcGsJAnoPFw= build_script: - cmd: >- - git clone --depth=1 --branch=%APPVEYOR_REPO_BRANCH% https://github.com/ModOrganizer2/modorganizer-umbrella.git c:\projects\modorganizer-umbrella 2> $null + git clone --depth=1 https://github.com/ModOrganizer2/modorganizer-umbrella.git c:\projects\modorganizer-umbrella 2> $null + git checkout $(git show-ref --verify --quiet refs/remotes/origin/%APPVEYOR_REPO_BRANCH% || echo '-b') %APPVEYOR_REPO_BRANCH% mkdir c:\projects\modorganizer-build -type directory From 5cc73276327446ff47f71f4506c65ba750bff4c7 Mon Sep 17 00:00:00 2001 From: Jeremy Rimpo Date: Sun, 20 Sep 2020 19:11:44 -0500 Subject: [PATCH 1000/1544] [game_fallout4vr] Need extra space for second command --- src/games/fallout4vr/appveyor.yml | 1 + 1 file changed, 1 insertion(+) diff --git a/src/games/fallout4vr/appveyor.yml b/src/games/fallout4vr/appveyor.yml index 1fdab3b9..9ca07f9b 100644 --- a/src/games/fallout4vr/appveyor.yml +++ b/src/games/fallout4vr/appveyor.yml @@ -7,6 +7,7 @@ environment: build_script: - cmd: >- git clone --depth=1 https://github.com/ModOrganizer2/modorganizer-umbrella.git c:\projects\modorganizer-umbrella 2> $null + git checkout $(git show-ref --verify --quiet refs/remotes/origin/%APPVEYOR_REPO_BRANCH% || echo '-b') %APPVEYOR_REPO_BRANCH% mkdir c:\projects\modorganizer-build -type directory From 3e51c66c20aebe35b6eb98b7cebffa3d6e41e5cd Mon Sep 17 00:00:00 2001 From: Jeremy Rimpo Date: Sun, 20 Sep 2020 19:11:46 -0500 Subject: [PATCH 1001/1544] [game_falloutnv] Need extra space for second command --- src/games/falloutnv/appveyor.yml | 1 + 1 file changed, 1 insertion(+) diff --git a/src/games/falloutnv/appveyor.yml b/src/games/falloutnv/appveyor.yml index 789d0112..dcf2cc56 100644 --- a/src/games/falloutnv/appveyor.yml +++ b/src/games/falloutnv/appveyor.yml @@ -7,6 +7,7 @@ environment: build_script: - cmd: >- git clone --depth=1 https://github.com/ModOrganizer2/modorganizer-umbrella.git c:\projects\modorganizer-umbrella 2> $null + git checkout $(git show-ref --verify --quiet refs/remotes/origin/%APPVEYOR_REPO_BRANCH% || echo '-b') %APPVEYOR_REPO_BRANCH% mkdir c:\projects\modorganizer-build -type directory From 7cfa384970e7d16ddae8a30debcf0e8aa369cf87 Mon Sep 17 00:00:00 2001 From: Jeremy Rimpo Date: Sun, 20 Sep 2020 19:11:47 -0500 Subject: [PATCH 1002/1544] [game_morrowind] Need extra space for second command --- src/games/morrowind/appveyor.yml | 1 + 1 file changed, 1 insertion(+) diff --git a/src/games/morrowind/appveyor.yml b/src/games/morrowind/appveyor.yml index 9479a4e2..ae9e5555 100644 --- a/src/games/morrowind/appveyor.yml +++ b/src/games/morrowind/appveyor.yml @@ -7,6 +7,7 @@ environment: build_script: - cmd: >- git clone --depth=1 https://github.com/ModOrganizer2/modorganizer-umbrella.git c:\projects\modorganizer-umbrella 2> $null + git checkout $(git show-ref --verify --quiet refs/remotes/origin/%APPVEYOR_REPO_BRANCH% || echo '-b') %APPVEYOR_REPO_BRANCH% mkdir c:\projects\modorganizer-build -type directory From c9c7a79b54184439b6f94150ff3ea9f18771ea26 Mon Sep 17 00:00:00 2001 From: Jeremy Rimpo Date: Sun, 20 Sep 2020 19:11:52 -0500 Subject: [PATCH 1003/1544] [game_skyrimvr] Need extra space for second command --- src/games/skyrimvr/appveyor.yml | 1 + 1 file changed, 1 insertion(+) diff --git a/src/games/skyrimvr/appveyor.yml b/src/games/skyrimvr/appveyor.yml index 249a3658..2ae24c85 100644 --- a/src/games/skyrimvr/appveyor.yml +++ b/src/games/skyrimvr/appveyor.yml @@ -7,6 +7,7 @@ environment: build_script: - cmd: >- git clone --depth=1 https://github.com/ModOrganizer2/modorganizer-umbrella.git c:\projects\modorganizer-umbrella 2> $null + git checkout $(git show-ref --verify --quiet refs/remotes/origin/%APPVEYOR_REPO_BRANCH% || echo '-b') %APPVEYOR_REPO_BRANCH% mkdir c:\projects\modorganizer-build -type directory From fcb7c689bea346b1ee8aab593d260a05dd020332 Mon Sep 17 00:00:00 2001 From: Jeremy Rimpo Date: Sun, 20 Sep 2020 19:11:53 -0500 Subject: [PATCH 1004/1544] Need extra space for second command --- appveyor.yml | 1 + 1 file changed, 1 insertion(+) diff --git a/appveyor.yml b/appveyor.yml index e609ead2..ca81ed2e 100644 --- a/appveyor.yml +++ b/appveyor.yml @@ -7,6 +7,7 @@ environment: build_script: - cmd: >- git clone --depth=1 https://github.com/ModOrganizer2/modorganizer-umbrella.git c:\projects\modorganizer-umbrella 2> $null + git checkout $(git show-ref --verify --quiet refs/remotes/origin/%APPVEYOR_REPO_BRANCH% || echo '-b') %APPVEYOR_REPO_BRANCH% mkdir c:\projects\modorganizer-build -type directory From b66a01042e1099384c0a72d033f83be537a52b64 Mon Sep 17 00:00:00 2001 From: Jeremy Rimpo Date: Sun, 20 Sep 2020 19:11:54 -0500 Subject: [PATCH 1005/1544] [game_fallout4] Need extra space for second command --- src/games/fallout4/appveyor.yml | 1 + 1 file changed, 1 insertion(+) diff --git a/src/games/fallout4/appveyor.yml b/src/games/fallout4/appveyor.yml index 39e0504b..c61c1e26 100644 --- a/src/games/fallout4/appveyor.yml +++ b/src/games/fallout4/appveyor.yml @@ -7,6 +7,7 @@ environment: build_script: - cmd: >- git clone --depth=1 https://github.com/ModOrganizer2/modorganizer-umbrella.git c:\projects\modorganizer-umbrella 2> $null + git checkout $(git show-ref --verify --quiet refs/remotes/origin/%APPVEYOR_REPO_BRANCH% || echo '-b') %APPVEYOR_REPO_BRANCH% mkdir c:\projects\modorganizer-build -type directory From 763761acb386de159bf17ca3a60757a2b2e3ca64 Mon Sep 17 00:00:00 2001 From: Jeremy Rimpo Date: Sun, 20 Sep 2020 19:11:55 -0500 Subject: [PATCH 1006/1544] [game_fallout3] Need extra space for second command --- src/games/fallout3/appveyor.yml | 1 + 1 file changed, 1 insertion(+) diff --git a/src/games/fallout3/appveyor.yml b/src/games/fallout3/appveyor.yml index d5ba1d9e..50326bef 100644 --- a/src/games/fallout3/appveyor.yml +++ b/src/games/fallout3/appveyor.yml @@ -7,6 +7,7 @@ environment: build_script: - cmd: >- git clone --depth=1 https://github.com/ModOrganizer2/modorganizer-umbrella.git c:\projects\modorganizer-umbrella 2> $null + git checkout $(git show-ref --verify --quiet refs/remotes/origin/%APPVEYOR_REPO_BRANCH% || echo '-b') %APPVEYOR_REPO_BRANCH% mkdir c:\projects\modorganizer-build -type directory From eeebc021841f938849028ab25a8c5f7234b270e3 Mon Sep 17 00:00:00 2001 From: Jeremy Rimpo Date: Sun, 20 Sep 2020 19:11:56 -0500 Subject: [PATCH 1007/1544] [game_skyrimse] Need extra space for second command --- src/games/skyrimse/appveyor.yml | 1 + 1 file changed, 1 insertion(+) diff --git a/src/games/skyrimse/appveyor.yml b/src/games/skyrimse/appveyor.yml index 90df5a2d..b1961cf8 100644 --- a/src/games/skyrimse/appveyor.yml +++ b/src/games/skyrimse/appveyor.yml @@ -7,6 +7,7 @@ environment: build_script: - cmd: >- git clone --depth=1 https://github.com/ModOrganizer2/modorganizer-umbrella.git c:\projects\modorganizer-umbrella 2> $null + git checkout $(git show-ref --verify --quiet refs/remotes/origin/%APPVEYOR_REPO_BRANCH% || echo '-b') %APPVEYOR_REPO_BRANCH% mkdir c:\projects\modorganizer-build -type directory From 7976a95ef000080252c93eea394e4698d1ae05e2 Mon Sep 17 00:00:00 2001 From: Jeremy Rimpo Date: Sun, 20 Sep 2020 19:11:57 -0500 Subject: [PATCH 1008/1544] [game_oblivion] Need extra space for second command --- src/games/oblivion/appveyor.yml | 1 + 1 file changed, 1 insertion(+) diff --git a/src/games/oblivion/appveyor.yml b/src/games/oblivion/appveyor.yml index 341a3048..330ac0d7 100644 --- a/src/games/oblivion/appveyor.yml +++ b/src/games/oblivion/appveyor.yml @@ -7,6 +7,7 @@ environment: build_script: - cmd: >- git clone --depth=1 https://github.com/ModOrganizer2/modorganizer-umbrella.git c:\projects\modorganizer-umbrella 2> $null + git checkout $(git show-ref --verify --quiet refs/remotes/origin/%APPVEYOR_REPO_BRANCH% || echo '-b') %APPVEYOR_REPO_BRANCH% mkdir c:\projects\modorganizer-build -type directory From bee56a62b3af1af8f1ba21904777f88fbda1025f Mon Sep 17 00:00:00 2001 From: Jeremy Rimpo Date: Sun, 20 Sep 2020 19:11:58 -0500 Subject: [PATCH 1009/1544] [game_skyrim] Need extra space for second command --- src/games/skyrim/appveyor.yml | 1 + 1 file changed, 1 insertion(+) diff --git a/src/games/skyrim/appveyor.yml b/src/games/skyrim/appveyor.yml index 6def2f88..88aec7cc 100644 --- a/src/games/skyrim/appveyor.yml +++ b/src/games/skyrim/appveyor.yml @@ -7,6 +7,7 @@ environment: build_script: - cmd: >- git clone --depth=1 https://github.com/ModOrganizer2/modorganizer-umbrella.git c:\projects\modorganizer-umbrella 2> $null + git checkout $(git show-ref --verify --quiet refs/remotes/origin/%APPVEYOR_REPO_BRANCH% || echo '-b') %APPVEYOR_REPO_BRANCH% mkdir c:\projects\modorganizer-build -type directory From 08be9d970fb5274456575ded0e9d90a3c6fcfa64 Mon Sep 17 00:00:00 2001 From: Jeremy Rimpo Date: Sun, 20 Sep 2020 19:12:00 -0500 Subject: [PATCH 1010/1544] [game_ttw] Need extra space for second command --- src/games/ttw/appveyor.yml | 1 + 1 file changed, 1 insertion(+) diff --git a/src/games/ttw/appveyor.yml b/src/games/ttw/appveyor.yml index b1a7f0d4..55798880 100644 --- a/src/games/ttw/appveyor.yml +++ b/src/games/ttw/appveyor.yml @@ -7,6 +7,7 @@ environment: build_script: - cmd: >- git clone --depth=1 https://github.com/ModOrganizer2/modorganizer-umbrella.git c:\projects\modorganizer-umbrella 2> $null + git checkout $(git show-ref --verify --quiet refs/remotes/origin/%APPVEYOR_REPO_BRANCH% || echo '-b') %APPVEYOR_REPO_BRANCH% mkdir c:\projects\modorganizer-build -type directory From c2a3d3884dc3184861c407973b131565b9e5c61e Mon Sep 17 00:00:00 2001 From: Jeremy Rimpo Date: Sun, 20 Sep 2020 19:56:31 -0500 Subject: [PATCH 1011/1544] [game_fallout4vr] Convert scripts to PowerShell --- src/games/fallout4vr/appveyor.yml | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/src/games/fallout4vr/appveyor.yml b/src/games/fallout4vr/appveyor.yml index 9ca07f9b..5d1e7efd 100644 --- a/src/games/fallout4vr/appveyor.yml +++ b/src/games/fallout4vr/appveyor.yml @@ -5,16 +5,16 @@ environment: WEBHOOK_URL: secure: gOKbXaZM9ImtMD5XrYITvdyZUW/az082G9OIN1EC1Vbg57wBaeLhi49uGjxPw5GVujHku6kxN6ab89zhbS5GVeluR76GM83IbKV4Sh7udXzoYZZdg6YudtYHzdhCgUeiedpswbuczTq9ceIkkfSEWZuh/lMAAVVwvcGsJAnoPFw= build_script: -- cmd: >- +- ps: >- git clone --depth=1 https://github.com/ModOrganizer2/modorganizer-umbrella.git c:\projects\modorganizer-umbrella 2> $null - git checkout $(git show-ref --verify --quiet refs/remotes/origin/%APPVEYOR_REPO_BRANCH% || echo '-b') %APPVEYOR_REPO_BRANCH% + git checkout $(git show-ref --verify --quiet refs/remotes/origin/${env:APPVEYOR_REPO_BRANCH} || echo '-b') ${env:APPVEYOR_REPO_BRANCH} mkdir c:\projects\modorganizer-build -type directory cd c:\projects\modorganizer-umbrella - C:\Python37-x64\python.exe unimake.py -d c:\projects\modorganizer-build -s Appveyor_Build=True %APPVEYOR_PROJECT_NAME% + C:\Python37-x64\python.exe unimake.py -d c:\projects\modorganizer-build -s Appveyor_Build=True ${env:APPVEYOR_PROJECT_NAME} artifacts: - path: build\src\game_fallout4vr.dll name: game_fallout4vr_dll From 86cfbb41361758f9b0fd1b095be496067d48d965 Mon Sep 17 00:00:00 2001 From: Jeremy Rimpo Date: Sun, 20 Sep 2020 19:56:33 -0500 Subject: [PATCH 1012/1544] [game_falloutnv] Convert scripts to PowerShell --- src/games/falloutnv/appveyor.yml | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/src/games/falloutnv/appveyor.yml b/src/games/falloutnv/appveyor.yml index dcf2cc56..24ed828b 100644 --- a/src/games/falloutnv/appveyor.yml +++ b/src/games/falloutnv/appveyor.yml @@ -5,16 +5,16 @@ environment: WEBHOOK_URL: secure: gOKbXaZM9ImtMD5XrYITvdyZUW/az082G9OIN1EC1Vbg57wBaeLhi49uGjxPw5GVujHku6kxN6ab89zhbS5GVeluR76GM83IbKV4Sh7udXzoYZZdg6YudtYHzdhCgUeiedpswbuczTq9ceIkkfSEWZuh/lMAAVVwvcGsJAnoPFw= build_script: -- cmd: >- +- ps: >- git clone --depth=1 https://github.com/ModOrganizer2/modorganizer-umbrella.git c:\projects\modorganizer-umbrella 2> $null - git checkout $(git show-ref --verify --quiet refs/remotes/origin/%APPVEYOR_REPO_BRANCH% || echo '-b') %APPVEYOR_REPO_BRANCH% + git checkout $(git show-ref --verify --quiet refs/remotes/origin/${env:APPVEYOR_REPO_BRANCH} || echo '-b') ${env:APPVEYOR_REPO_BRANCH} mkdir c:\projects\modorganizer-build -type directory cd c:\projects\modorganizer-umbrella - C:\Python37-x64\python.exe unimake.py -d c:\projects\modorganizer-build -s Appveyor_Build=True %APPVEYOR_PROJECT_NAME% + C:\Python37-x64\python.exe unimake.py -d c:\projects\modorganizer-build -s Appveyor_Build=True ${env:APPVEYOR_PROJECT_NAME} artifacts: - path: build\src\game_falloutNV.dll name: game_falloutNV_dll From 5e5e9e0d920ace43bcf5e656ffcbabb76ab1b0b6 Mon Sep 17 00:00:00 2001 From: Jeremy Rimpo Date: Sun, 20 Sep 2020 19:56:34 -0500 Subject: [PATCH 1013/1544] [game_morrowind] Convert scripts to PowerShell --- src/games/morrowind/appveyor.yml | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/src/games/morrowind/appveyor.yml b/src/games/morrowind/appveyor.yml index ae9e5555..713f1c34 100644 --- a/src/games/morrowind/appveyor.yml +++ b/src/games/morrowind/appveyor.yml @@ -5,16 +5,16 @@ environment: WEBHOOK_URL: secure: gOKbXaZM9ImtMD5XrYITvdyZUW/az082G9OIN1EC1Vbg57wBaeLhi49uGjxPw5GVujHku6kxN6ab89zhbS5GVeluR76GM83IbKV4Sh7udXzoYZZdg6YudtYHzdhCgUeiedpswbuczTq9ceIkkfSEWZuh/lMAAVVwvcGsJAnoPFw= build_script: -- cmd: >- +- ps: >- git clone --depth=1 https://github.com/ModOrganizer2/modorganizer-umbrella.git c:\projects\modorganizer-umbrella 2> $null - git checkout $(git show-ref --verify --quiet refs/remotes/origin/%APPVEYOR_REPO_BRANCH% || echo '-b') %APPVEYOR_REPO_BRANCH% + git checkout $(git show-ref --verify --quiet refs/remotes/origin/${env:APPVEYOR_REPO_BRANCH} || echo '-b') ${env:APPVEYOR_REPO_BRANCH} mkdir c:\projects\modorganizer-build -type directory cd c:\projects\modorganizer-umbrella - C:\Python37-x64\python.exe unimake.py -d c:\projects\modorganizer-build -s Appveyor_Build=True %APPVEYOR_PROJECT_NAME% + C:\Python37-x64\python.exe unimake.py -d c:\projects\modorganizer-build -s Appveyor_Build=True ${env:APPVEYOR_PROJECT_NAME} artifacts: - path: build\src\game_morrowind.dll name: game_morrowind_dll From ff817cfb7a715ca2a54f04a1110fc8cc417b07b0 Mon Sep 17 00:00:00 2001 From: Jeremy Rimpo Date: Sun, 20 Sep 2020 19:56:38 -0500 Subject: [PATCH 1014/1544] [game_skyrimvr] Convert scripts to PowerShell --- src/games/skyrimvr/appveyor.yml | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/src/games/skyrimvr/appveyor.yml b/src/games/skyrimvr/appveyor.yml index 2ae24c85..46ad6e57 100644 --- a/src/games/skyrimvr/appveyor.yml +++ b/src/games/skyrimvr/appveyor.yml @@ -5,16 +5,16 @@ environment: WEBHOOK_URL: secure: gOKbXaZM9ImtMD5XrYITvdyZUW/az082G9OIN1EC1Vbg57wBaeLhi49uGjxPw5GVujHku6kxN6ab89zhbS5GVeluR76GM83IbKV4Sh7udXzoYZZdg6YudtYHzdhCgUeiedpswbuczTq9ceIkkfSEWZuh/lMAAVVwvcGsJAnoPFw= build_script: -- cmd: >- +- ps: >- git clone --depth=1 https://github.com/ModOrganizer2/modorganizer-umbrella.git c:\projects\modorganizer-umbrella 2> $null - git checkout $(git show-ref --verify --quiet refs/remotes/origin/%APPVEYOR_REPO_BRANCH% || echo '-b') %APPVEYOR_REPO_BRANCH% + git checkout $(git show-ref --verify --quiet refs/remotes/origin/${env:APPVEYOR_REPO_BRANCH} || echo '-b') ${env:APPVEYOR_REPO_BRANCH} mkdir c:\projects\modorganizer-build -type directory cd c:\projects\modorganizer-umbrella - C:\Python37-x64\python.exe unimake.py -d c:\projects\modorganizer-build -s Appveyor_Build=True %APPVEYOR_PROJECT_NAME% + C:\Python37-x64\python.exe unimake.py -d c:\projects\modorganizer-build -s Appveyor_Build=True ${env:APPVEYOR_PROJECT_NAME} artifacts: - path: build\src\game_skyrimvr.dll name: game_skyrimvr_dll From 454839938d985bb211716b7c1f8e94d30824d101 Mon Sep 17 00:00:00 2001 From: Jeremy Rimpo Date: Sun, 20 Sep 2020 19:56:39 -0500 Subject: [PATCH 1015/1544] Convert scripts to PowerShell --- appveyor.yml | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/appveyor.yml b/appveyor.yml index ca81ed2e..4da61147 100644 --- a/appveyor.yml +++ b/appveyor.yml @@ -5,16 +5,16 @@ environment: WEBHOOK_URL: secure: gOKbXaZM9ImtMD5XrYITvdyZUW/az082G9OIN1EC1Vbg57wBaeLhi49uGjxPw5GVujHku6kxN6ab89zhbS5GVeluR76GM83IbKV4Sh7udXzoYZZdg6YudtYHzdhCgUeiedpswbuczTq9ceIkkfSEWZuh/lMAAVVwvcGsJAnoPFw= build_script: -- cmd: >- +- ps: >- git clone --depth=1 https://github.com/ModOrganizer2/modorganizer-umbrella.git c:\projects\modorganizer-umbrella 2> $null - git checkout $(git show-ref --verify --quiet refs/remotes/origin/%APPVEYOR_REPO_BRANCH% || echo '-b') %APPVEYOR_REPO_BRANCH% + git checkout $(git show-ref --verify --quiet refs/remotes/origin/${env:APPVEYOR_REPO_BRANCH} || echo '-b') ${env:APPVEYOR_REPO_BRANCH} mkdir c:\projects\modorganizer-build -type directory cd c:\projects\modorganizer-umbrella - C:\Python37-x64\python.exe unimake.py -d c:\projects\modorganizer-build -s Appveyor_Build=True %APPVEYOR_PROJECT_NAME% + C:\Python37-x64\python.exe unimake.py -d c:\projects\modorganizer-build -s Appveyor_Build=True ${env:APPVEYOR_PROJECT_NAME} artifacts: - path: build\src\gamebryo\game_gamebryo.lib name: game_gamebryo_lib From 4db26d5596ab940ccdd2cafac0385f3b8e971a93 Mon Sep 17 00:00:00 2001 From: Jeremy Rimpo Date: Sun, 20 Sep 2020 19:56:40 -0500 Subject: [PATCH 1016/1544] [game_fallout4] Convert scripts to PowerShell --- src/games/fallout4/appveyor.yml | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/src/games/fallout4/appveyor.yml b/src/games/fallout4/appveyor.yml index c61c1e26..9ab1a700 100644 --- a/src/games/fallout4/appveyor.yml +++ b/src/games/fallout4/appveyor.yml @@ -5,16 +5,16 @@ environment: WEBHOOK_URL: secure: gOKbXaZM9ImtMD5XrYITvdyZUW/az082G9OIN1EC1Vbg57wBaeLhi49uGjxPw5GVujHku6kxN6ab89zhbS5GVeluR76GM83IbKV4Sh7udXzoYZZdg6YudtYHzdhCgUeiedpswbuczTq9ceIkkfSEWZuh/lMAAVVwvcGsJAnoPFw= build_script: -- cmd: >- +- ps: >- git clone --depth=1 https://github.com/ModOrganizer2/modorganizer-umbrella.git c:\projects\modorganizer-umbrella 2> $null - git checkout $(git show-ref --verify --quiet refs/remotes/origin/%APPVEYOR_REPO_BRANCH% || echo '-b') %APPVEYOR_REPO_BRANCH% + git checkout $(git show-ref --verify --quiet refs/remotes/origin/${env:APPVEYOR_REPO_BRANCH} || echo '-b') ${env:APPVEYOR_REPO_BRANCH} mkdir c:\projects\modorganizer-build -type directory cd c:\projects\modorganizer-umbrella - C:\Python37-x64\python.exe unimake.py -d c:\projects\modorganizer-build -s Appveyor_Build=True %APPVEYOR_PROJECT_NAME% + C:\Python37-x64\python.exe unimake.py -d c:\projects\modorganizer-build -s Appveyor_Build=True ${env:APPVEYOR_PROJECT_NAME} artifacts: - path: build\src\game_fallout4.dll name: game_fallout4_dll From e78d892c777c985bd9dfdb6d4c35e834272747d9 Mon Sep 17 00:00:00 2001 From: Jeremy Rimpo Date: Sun, 20 Sep 2020 19:56:41 -0500 Subject: [PATCH 1017/1544] [game_fallout3] Convert scripts to PowerShell --- src/games/fallout3/appveyor.yml | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/src/games/fallout3/appveyor.yml b/src/games/fallout3/appveyor.yml index 50326bef..704a93cb 100644 --- a/src/games/fallout3/appveyor.yml +++ b/src/games/fallout3/appveyor.yml @@ -5,16 +5,16 @@ environment: WEBHOOK_URL: secure: gOKbXaZM9ImtMD5XrYITvdyZUW/az082G9OIN1EC1Vbg57wBaeLhi49uGjxPw5GVujHku6kxN6ab89zhbS5GVeluR76GM83IbKV4Sh7udXzoYZZdg6YudtYHzdhCgUeiedpswbuczTq9ceIkkfSEWZuh/lMAAVVwvcGsJAnoPFw= build_script: -- cmd: >- +- ps: >- git clone --depth=1 https://github.com/ModOrganizer2/modorganizer-umbrella.git c:\projects\modorganizer-umbrella 2> $null - git checkout $(git show-ref --verify --quiet refs/remotes/origin/%APPVEYOR_REPO_BRANCH% || echo '-b') %APPVEYOR_REPO_BRANCH% + git checkout $(git show-ref --verify --quiet refs/remotes/origin/${env:APPVEYOR_REPO_BRANCH} || echo '-b') ${env:APPVEYOR_REPO_BRANCH} mkdir c:\projects\modorganizer-build -type directory cd c:\projects\modorganizer-umbrella - C:\Python37-x64\python.exe unimake.py -d c:\projects\modorganizer-build -s Appveyor_Build=True %APPVEYOR_PROJECT_NAME% + C:\Python37-x64\python.exe unimake.py -d c:\projects\modorganizer-build -s Appveyor_Build=True ${env:APPVEYOR_PROJECT_NAME} artifacts: - path: build\src\game_fallout3.dll name: game_fallout3_dll From cd2eacb75c7091c8284611ba37bce5b3f163410a Mon Sep 17 00:00:00 2001 From: Jeremy Rimpo Date: Sun, 20 Sep 2020 19:56:41 -0500 Subject: [PATCH 1018/1544] [game_skyrimse] Convert scripts to PowerShell --- src/games/skyrimse/appveyor.yml | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/src/games/skyrimse/appveyor.yml b/src/games/skyrimse/appveyor.yml index b1961cf8..6b38e040 100644 --- a/src/games/skyrimse/appveyor.yml +++ b/src/games/skyrimse/appveyor.yml @@ -5,16 +5,16 @@ environment: WEBHOOK_URL: secure: gOKbXaZM9ImtMD5XrYITvdyZUW/az082G9OIN1EC1Vbg57wBaeLhi49uGjxPw5GVujHku6kxN6ab89zhbS5GVeluR76GM83IbKV4Sh7udXzoYZZdg6YudtYHzdhCgUeiedpswbuczTq9ceIkkfSEWZuh/lMAAVVwvcGsJAnoPFw= build_script: -- cmd: >- +- ps: >- git clone --depth=1 https://github.com/ModOrganizer2/modorganizer-umbrella.git c:\projects\modorganizer-umbrella 2> $null - git checkout $(git show-ref --verify --quiet refs/remotes/origin/%APPVEYOR_REPO_BRANCH% || echo '-b') %APPVEYOR_REPO_BRANCH% + git checkout $(git show-ref --verify --quiet refs/remotes/origin/${env:APPVEYOR_REPO_BRANCH} || echo '-b') ${env:APPVEYOR_REPO_BRANCH} mkdir c:\projects\modorganizer-build -type directory cd c:\projects\modorganizer-umbrella - C:\Python37-x64\python.exe unimake.py -d c:\projects\modorganizer-build -s Appveyor_Build=True %APPVEYOR_PROJECT_NAME% + C:\Python37-x64\python.exe unimake.py -d c:\projects\modorganizer-build -s Appveyor_Build=True ${env:APPVEYOR_PROJECT_NAME} artifacts: - path: build\src\game_skyrimse.dll name: game_skyrimse_dll From c82a30efd356294bfa1e5b25f96cce81af8bdbcf Mon Sep 17 00:00:00 2001 From: Jeremy Rimpo Date: Sun, 20 Sep 2020 19:56:42 -0500 Subject: [PATCH 1019/1544] [game_oblivion] Convert scripts to PowerShell --- src/games/oblivion/appveyor.yml | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/src/games/oblivion/appveyor.yml b/src/games/oblivion/appveyor.yml index 330ac0d7..5399d664 100644 --- a/src/games/oblivion/appveyor.yml +++ b/src/games/oblivion/appveyor.yml @@ -5,16 +5,16 @@ environment: WEBHOOK_URL: secure: gOKbXaZM9ImtMD5XrYITvdyZUW/az082G9OIN1EC1Vbg57wBaeLhi49uGjxPw5GVujHku6kxN6ab89zhbS5GVeluR76GM83IbKV4Sh7udXzoYZZdg6YudtYHzdhCgUeiedpswbuczTq9ceIkkfSEWZuh/lMAAVVwvcGsJAnoPFw= build_script: -- cmd: >- +- ps: >- git clone --depth=1 https://github.com/ModOrganizer2/modorganizer-umbrella.git c:\projects\modorganizer-umbrella 2> $null - git checkout $(git show-ref --verify --quiet refs/remotes/origin/%APPVEYOR_REPO_BRANCH% || echo '-b') %APPVEYOR_REPO_BRANCH% + git checkout $(git show-ref --verify --quiet refs/remotes/origin/${env:APPVEYOR_REPO_BRANCH} || echo '-b') ${env:APPVEYOR_REPO_BRANCH} mkdir c:\projects\modorganizer-build -type directory cd c:\projects\modorganizer-umbrella - C:\Python37-x64\python.exe unimake.py -d c:\projects\modorganizer-build -s Appveyor_Build=True %APPVEYOR_PROJECT_NAME% + C:\Python37-x64\python.exe unimake.py -d c:\projects\modorganizer-build -s Appveyor_Build=True ${env:APPVEYOR_PROJECT_NAME} artifacts: - path: build\src\game_oblivion.dll name: game_oblivion_dll From d66c618b9b28884eeb80dda29a5fbf7a6c2077c5 Mon Sep 17 00:00:00 2001 From: Jeremy Rimpo Date: Sun, 20 Sep 2020 19:56:44 -0500 Subject: [PATCH 1020/1544] [game_skyrim] Convert scripts to PowerShell --- src/games/skyrim/appveyor.yml | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/src/games/skyrim/appveyor.yml b/src/games/skyrim/appveyor.yml index 88aec7cc..95f2fd69 100644 --- a/src/games/skyrim/appveyor.yml +++ b/src/games/skyrim/appveyor.yml @@ -5,16 +5,16 @@ environment: WEBHOOK_URL: secure: gOKbXaZM9ImtMD5XrYITvdyZUW/az082G9OIN1EC1Vbg57wBaeLhi49uGjxPw5GVujHku6kxN6ab89zhbS5GVeluR76GM83IbKV4Sh7udXzoYZZdg6YudtYHzdhCgUeiedpswbuczTq9ceIkkfSEWZuh/lMAAVVwvcGsJAnoPFw= build_script: -- cmd: >- +- ps: >- git clone --depth=1 https://github.com/ModOrganizer2/modorganizer-umbrella.git c:\projects\modorganizer-umbrella 2> $null - git checkout $(git show-ref --verify --quiet refs/remotes/origin/%APPVEYOR_REPO_BRANCH% || echo '-b') %APPVEYOR_REPO_BRANCH% + git checkout $(git show-ref --verify --quiet refs/remotes/origin/${env:APPVEYOR_REPO_BRANCH} || echo '-b') ${env:APPVEYOR_REPO_BRANCH} mkdir c:\projects\modorganizer-build -type directory cd c:\projects\modorganizer-umbrella - C:\Python37-x64\python.exe unimake.py -d c:\projects\modorganizer-build -s Appveyor_Build=True %APPVEYOR_PROJECT_NAME% + C:\Python37-x64\python.exe unimake.py -d c:\projects\modorganizer-build -s Appveyor_Build=True ${env:APPVEYOR_PROJECT_NAME} artifacts: - path: build\src\game_skyrim.dll name: game_skyrim_dll From 9658769a1e2b99bf782bf41cfb68b9555006d482 Mon Sep 17 00:00:00 2001 From: Jeremy Rimpo Date: Sun, 20 Sep 2020 19:56:46 -0500 Subject: [PATCH 1021/1544] [game_ttw] Convert scripts to PowerShell --- src/games/ttw/appveyor.yml | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/src/games/ttw/appveyor.yml b/src/games/ttw/appveyor.yml index 55798880..1b41b988 100644 --- a/src/games/ttw/appveyor.yml +++ b/src/games/ttw/appveyor.yml @@ -5,16 +5,16 @@ environment: WEBHOOK_URL: secure: gOKbXaZM9ImtMD5XrYITvdyZUW/az082G9OIN1EC1Vbg57wBaeLhi49uGjxPw5GVujHku6kxN6ab89zhbS5GVeluR76GM83IbKV4Sh7udXzoYZZdg6YudtYHzdhCgUeiedpswbuczTq9ceIkkfSEWZuh/lMAAVVwvcGsJAnoPFw= build_script: -- cmd: >- +- ps: >- git clone --depth=1 https://github.com/ModOrganizer2/modorganizer-umbrella.git c:\projects\modorganizer-umbrella 2> $null - git checkout $(git show-ref --verify --quiet refs/remotes/origin/%APPVEYOR_REPO_BRANCH% || echo '-b') %APPVEYOR_REPO_BRANCH% + git checkout $(git show-ref --verify --quiet refs/remotes/origin/${env:APPVEYOR_REPO_BRANCH} || echo '-b') ${env:APPVEYOR_REPO_BRANCH} mkdir c:\projects\modorganizer-build -type directory cd c:\projects\modorganizer-umbrella - C:\Python37-x64\python.exe unimake.py -d c:\projects\modorganizer-build -s Appveyor_Build=True %APPVEYOR_PROJECT_NAME% + C:\Python37-x64\python.exe unimake.py -d c:\projects\modorganizer-build -s Appveyor_Build=True ${env:APPVEYOR_PROJECT_NAME} artifacts: - path: build\src\game_ttw.dll name: game_ttw_dll From 0fa55246eea4594241e30edddec310e6116897bb Mon Sep 17 00:00:00 2001 From: Jeremy Rimpo Date: Sun, 20 Sep 2020 22:34:26 -0500 Subject: [PATCH 1022/1544] [game_fallout4vr] Finalize appveyor script update --- src/games/fallout4vr/appveyor.yml | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/src/games/fallout4vr/appveyor.yml b/src/games/fallout4vr/appveyor.yml index 5d1e7efd..10e33f1a 100644 --- a/src/games/fallout4vr/appveyor.yml +++ b/src/games/fallout4vr/appveyor.yml @@ -5,15 +5,15 @@ environment: WEBHOOK_URL: secure: gOKbXaZM9ImtMD5XrYITvdyZUW/az082G9OIN1EC1Vbg57wBaeLhi49uGjxPw5GVujHku6kxN6ab89zhbS5GVeluR76GM83IbKV4Sh7udXzoYZZdg6YudtYHzdhCgUeiedpswbuczTq9ceIkkfSEWZuh/lMAAVVwvcGsJAnoPFw= build_script: -- ps: >- - git clone --depth=1 https://github.com/ModOrganizer2/modorganizer-umbrella.git c:\projects\modorganizer-umbrella 2> $null +- pwsh: >- + git clone --depth=1 https://github.com/ModOrganizer2/modorganizer-umbrella.git c:\projects\modorganizer-umbrella - git checkout $(git show-ref --verify --quiet refs/remotes/origin/${env:APPVEYOR_REPO_BRANCH} || echo '-b') ${env:APPVEYOR_REPO_BRANCH} - - mkdir c:\projects\modorganizer-build -type directory + New-Item -ItemType Directory -Path c:\projects\modorganizer-build cd c:\projects\modorganizer-umbrella + git checkout $(git show-ref --verify --quiet refs/remotes/origin/${env:APPVEYOR_REPO_BRANCH} || echo '-b') ${env:APPVEYOR_REPO_BRANCH} + C:\Python37-x64\python.exe unimake.py -d c:\projects\modorganizer-build -s Appveyor_Build=True ${env:APPVEYOR_PROJECT_NAME} artifacts: - path: build\src\game_fallout4vr.dll From 0148e5da39cf7d310b4c4e94c41bc7a64f31cc08 Mon Sep 17 00:00:00 2001 From: Jeremy Rimpo Date: Sun, 20 Sep 2020 22:34:28 -0500 Subject: [PATCH 1023/1544] [game_falloutnv] Finalize appveyor script update --- src/games/falloutnv/appveyor.yml | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/src/games/falloutnv/appveyor.yml b/src/games/falloutnv/appveyor.yml index 24ed828b..a5d2fd14 100644 --- a/src/games/falloutnv/appveyor.yml +++ b/src/games/falloutnv/appveyor.yml @@ -5,15 +5,15 @@ environment: WEBHOOK_URL: secure: gOKbXaZM9ImtMD5XrYITvdyZUW/az082G9OIN1EC1Vbg57wBaeLhi49uGjxPw5GVujHku6kxN6ab89zhbS5GVeluR76GM83IbKV4Sh7udXzoYZZdg6YudtYHzdhCgUeiedpswbuczTq9ceIkkfSEWZuh/lMAAVVwvcGsJAnoPFw= build_script: -- ps: >- - git clone --depth=1 https://github.com/ModOrganizer2/modorganizer-umbrella.git c:\projects\modorganizer-umbrella 2> $null +- pwsh: >- + git clone --depth=1 https://github.com/ModOrganizer2/modorganizer-umbrella.git c:\projects\modorganizer-umbrella - git checkout $(git show-ref --verify --quiet refs/remotes/origin/${env:APPVEYOR_REPO_BRANCH} || echo '-b') ${env:APPVEYOR_REPO_BRANCH} - - mkdir c:\projects\modorganizer-build -type directory + New-Item -ItemType Directory -Path c:\projects\modorganizer-build cd c:\projects\modorganizer-umbrella + git checkout $(git show-ref --verify --quiet refs/remotes/origin/${env:APPVEYOR_REPO_BRANCH} || echo '-b') ${env:APPVEYOR_REPO_BRANCH} + C:\Python37-x64\python.exe unimake.py -d c:\projects\modorganizer-build -s Appveyor_Build=True ${env:APPVEYOR_PROJECT_NAME} artifacts: - path: build\src\game_falloutNV.dll From 199fa7a22c5182e832cfd4a3ef65683a8f4d1613 Mon Sep 17 00:00:00 2001 From: Jeremy Rimpo Date: Sun, 20 Sep 2020 22:34:29 -0500 Subject: [PATCH 1024/1544] [game_morrowind] Finalize appveyor script update --- src/games/morrowind/appveyor.yml | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/src/games/morrowind/appveyor.yml b/src/games/morrowind/appveyor.yml index 713f1c34..75d550ba 100644 --- a/src/games/morrowind/appveyor.yml +++ b/src/games/morrowind/appveyor.yml @@ -5,15 +5,15 @@ environment: WEBHOOK_URL: secure: gOKbXaZM9ImtMD5XrYITvdyZUW/az082G9OIN1EC1Vbg57wBaeLhi49uGjxPw5GVujHku6kxN6ab89zhbS5GVeluR76GM83IbKV4Sh7udXzoYZZdg6YudtYHzdhCgUeiedpswbuczTq9ceIkkfSEWZuh/lMAAVVwvcGsJAnoPFw= build_script: -- ps: >- - git clone --depth=1 https://github.com/ModOrganizer2/modorganizer-umbrella.git c:\projects\modorganizer-umbrella 2> $null +- pwsh: >- + git clone --depth=1 https://github.com/ModOrganizer2/modorganizer-umbrella.git c:\projects\modorganizer-umbrella - git checkout $(git show-ref --verify --quiet refs/remotes/origin/${env:APPVEYOR_REPO_BRANCH} || echo '-b') ${env:APPVEYOR_REPO_BRANCH} - - mkdir c:\projects\modorganizer-build -type directory + New-Item -ItemType Directory -Path c:\projects\modorganizer-build cd c:\projects\modorganizer-umbrella + git checkout $(git show-ref --verify --quiet refs/remotes/origin/${env:APPVEYOR_REPO_BRANCH} || echo '-b') ${env:APPVEYOR_REPO_BRANCH} + C:\Python37-x64\python.exe unimake.py -d c:\projects\modorganizer-build -s Appveyor_Build=True ${env:APPVEYOR_PROJECT_NAME} artifacts: - path: build\src\game_morrowind.dll From 73147939a6a046d60844abff48e93b5fb89f37ca Mon Sep 17 00:00:00 2001 From: Jeremy Rimpo Date: Sun, 20 Sep 2020 22:34:33 -0500 Subject: [PATCH 1025/1544] Finalize appveyor script update --- appveyor.yml | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/appveyor.yml b/appveyor.yml index 4da61147..2a38bb46 100644 --- a/appveyor.yml +++ b/appveyor.yml @@ -5,15 +5,15 @@ environment: WEBHOOK_URL: secure: gOKbXaZM9ImtMD5XrYITvdyZUW/az082G9OIN1EC1Vbg57wBaeLhi49uGjxPw5GVujHku6kxN6ab89zhbS5GVeluR76GM83IbKV4Sh7udXzoYZZdg6YudtYHzdhCgUeiedpswbuczTq9ceIkkfSEWZuh/lMAAVVwvcGsJAnoPFw= build_script: -- ps: >- - git clone --depth=1 https://github.com/ModOrganizer2/modorganizer-umbrella.git c:\projects\modorganizer-umbrella 2> $null +- pwsh: >- + git clone --depth=1 https://github.com/ModOrganizer2/modorganizer-umbrella.git c:\projects\modorganizer-umbrella - git checkout $(git show-ref --verify --quiet refs/remotes/origin/${env:APPVEYOR_REPO_BRANCH} || echo '-b') ${env:APPVEYOR_REPO_BRANCH} - - mkdir c:\projects\modorganizer-build -type directory + New-Item -ItemType Directory -Path c:\projects\modorganizer-build cd c:\projects\modorganizer-umbrella + git checkout $(git show-ref --verify --quiet refs/remotes/origin/${env:APPVEYOR_REPO_BRANCH} || echo '-b') ${env:APPVEYOR_REPO_BRANCH} + C:\Python37-x64\python.exe unimake.py -d c:\projects\modorganizer-build -s Appveyor_Build=True ${env:APPVEYOR_PROJECT_NAME} artifacts: - path: build\src\gamebryo\game_gamebryo.lib From df586e3fad9ece36f43d90fe3f28b77b6a339584 Mon Sep 17 00:00:00 2001 From: Jeremy Rimpo Date: Sun, 20 Sep 2020 22:34:33 -0500 Subject: [PATCH 1026/1544] [game_skyrimvr] Finalize appveyor script update --- src/games/skyrimvr/appveyor.yml | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/src/games/skyrimvr/appveyor.yml b/src/games/skyrimvr/appveyor.yml index 46ad6e57..8c11e8d8 100644 --- a/src/games/skyrimvr/appveyor.yml +++ b/src/games/skyrimvr/appveyor.yml @@ -5,15 +5,15 @@ environment: WEBHOOK_URL: secure: gOKbXaZM9ImtMD5XrYITvdyZUW/az082G9OIN1EC1Vbg57wBaeLhi49uGjxPw5GVujHku6kxN6ab89zhbS5GVeluR76GM83IbKV4Sh7udXzoYZZdg6YudtYHzdhCgUeiedpswbuczTq9ceIkkfSEWZuh/lMAAVVwvcGsJAnoPFw= build_script: -- ps: >- - git clone --depth=1 https://github.com/ModOrganizer2/modorganizer-umbrella.git c:\projects\modorganizer-umbrella 2> $null +- pwsh: >- + git clone --depth=1 https://github.com/ModOrganizer2/modorganizer-umbrella.git c:\projects\modorganizer-umbrella - git checkout $(git show-ref --verify --quiet refs/remotes/origin/${env:APPVEYOR_REPO_BRANCH} || echo '-b') ${env:APPVEYOR_REPO_BRANCH} - - mkdir c:\projects\modorganizer-build -type directory + New-Item -ItemType Directory -Path c:\projects\modorganizer-build cd c:\projects\modorganizer-umbrella + git checkout $(git show-ref --verify --quiet refs/remotes/origin/${env:APPVEYOR_REPO_BRANCH} || echo '-b') ${env:APPVEYOR_REPO_BRANCH} + C:\Python37-x64\python.exe unimake.py -d c:\projects\modorganizer-build -s Appveyor_Build=True ${env:APPVEYOR_PROJECT_NAME} artifacts: - path: build\src\game_skyrimvr.dll From ca15da912a3e03c7109b2b0c6d6eb8ba92d52c79 Mon Sep 17 00:00:00 2001 From: Jeremy Rimpo Date: Sun, 20 Sep 2020 22:34:34 -0500 Subject: [PATCH 1027/1544] [game_fallout4] Finalize appveyor script update --- src/games/fallout4/appveyor.yml | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/src/games/fallout4/appveyor.yml b/src/games/fallout4/appveyor.yml index 9ab1a700..ffd2a897 100644 --- a/src/games/fallout4/appveyor.yml +++ b/src/games/fallout4/appveyor.yml @@ -5,15 +5,15 @@ environment: WEBHOOK_URL: secure: gOKbXaZM9ImtMD5XrYITvdyZUW/az082G9OIN1EC1Vbg57wBaeLhi49uGjxPw5GVujHku6kxN6ab89zhbS5GVeluR76GM83IbKV4Sh7udXzoYZZdg6YudtYHzdhCgUeiedpswbuczTq9ceIkkfSEWZuh/lMAAVVwvcGsJAnoPFw= build_script: -- ps: >- - git clone --depth=1 https://github.com/ModOrganizer2/modorganizer-umbrella.git c:\projects\modorganizer-umbrella 2> $null +- pwsh: >- + git clone --depth=1 https://github.com/ModOrganizer2/modorganizer-umbrella.git c:\projects\modorganizer-umbrella - git checkout $(git show-ref --verify --quiet refs/remotes/origin/${env:APPVEYOR_REPO_BRANCH} || echo '-b') ${env:APPVEYOR_REPO_BRANCH} - - mkdir c:\projects\modorganizer-build -type directory + New-Item -ItemType Directory -Path c:\projects\modorganizer-build cd c:\projects\modorganizer-umbrella + git checkout $(git show-ref --verify --quiet refs/remotes/origin/${env:APPVEYOR_REPO_BRANCH} || echo '-b') ${env:APPVEYOR_REPO_BRANCH} + C:\Python37-x64\python.exe unimake.py -d c:\projects\modorganizer-build -s Appveyor_Build=True ${env:APPVEYOR_PROJECT_NAME} artifacts: - path: build\src\game_fallout4.dll From 745e580f551469ecc8e425167ba09665a0be51aa Mon Sep 17 00:00:00 2001 From: Jeremy Rimpo Date: Sun, 20 Sep 2020 22:34:35 -0500 Subject: [PATCH 1028/1544] [game_fallout3] Finalize appveyor script update --- src/games/fallout3/appveyor.yml | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/src/games/fallout3/appveyor.yml b/src/games/fallout3/appveyor.yml index 704a93cb..41ec7d74 100644 --- a/src/games/fallout3/appveyor.yml +++ b/src/games/fallout3/appveyor.yml @@ -5,15 +5,15 @@ environment: WEBHOOK_URL: secure: gOKbXaZM9ImtMD5XrYITvdyZUW/az082G9OIN1EC1Vbg57wBaeLhi49uGjxPw5GVujHku6kxN6ab89zhbS5GVeluR76GM83IbKV4Sh7udXzoYZZdg6YudtYHzdhCgUeiedpswbuczTq9ceIkkfSEWZuh/lMAAVVwvcGsJAnoPFw= build_script: -- ps: >- - git clone --depth=1 https://github.com/ModOrganizer2/modorganizer-umbrella.git c:\projects\modorganizer-umbrella 2> $null +- pwsh: >- + git clone --depth=1 https://github.com/ModOrganizer2/modorganizer-umbrella.git c:\projects\modorganizer-umbrella - git checkout $(git show-ref --verify --quiet refs/remotes/origin/${env:APPVEYOR_REPO_BRANCH} || echo '-b') ${env:APPVEYOR_REPO_BRANCH} - - mkdir c:\projects\modorganizer-build -type directory + New-Item -ItemType Directory -Path c:\projects\modorganizer-build cd c:\projects\modorganizer-umbrella + git checkout $(git show-ref --verify --quiet refs/remotes/origin/${env:APPVEYOR_REPO_BRANCH} || echo '-b') ${env:APPVEYOR_REPO_BRANCH} + C:\Python37-x64\python.exe unimake.py -d c:\projects\modorganizer-build -s Appveyor_Build=True ${env:APPVEYOR_PROJECT_NAME} artifacts: - path: build\src\game_fallout3.dll From bf93c25c49316bdb81100bacc653bf871ef702c1 Mon Sep 17 00:00:00 2001 From: Jeremy Rimpo Date: Sun, 20 Sep 2020 22:34:36 -0500 Subject: [PATCH 1029/1544] [game_skyrimse] Finalize appveyor script update --- src/games/skyrimse/appveyor.yml | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/src/games/skyrimse/appveyor.yml b/src/games/skyrimse/appveyor.yml index 6b38e040..5365d795 100644 --- a/src/games/skyrimse/appveyor.yml +++ b/src/games/skyrimse/appveyor.yml @@ -5,15 +5,15 @@ environment: WEBHOOK_URL: secure: gOKbXaZM9ImtMD5XrYITvdyZUW/az082G9OIN1EC1Vbg57wBaeLhi49uGjxPw5GVujHku6kxN6ab89zhbS5GVeluR76GM83IbKV4Sh7udXzoYZZdg6YudtYHzdhCgUeiedpswbuczTq9ceIkkfSEWZuh/lMAAVVwvcGsJAnoPFw= build_script: -- ps: >- - git clone --depth=1 https://github.com/ModOrganizer2/modorganizer-umbrella.git c:\projects\modorganizer-umbrella 2> $null +- pwsh: >- + git clone --depth=1 https://github.com/ModOrganizer2/modorganizer-umbrella.git c:\projects\modorganizer-umbrella - git checkout $(git show-ref --verify --quiet refs/remotes/origin/${env:APPVEYOR_REPO_BRANCH} || echo '-b') ${env:APPVEYOR_REPO_BRANCH} - - mkdir c:\projects\modorganizer-build -type directory + New-Item -ItemType Directory -Path c:\projects\modorganizer-build cd c:\projects\modorganizer-umbrella + git checkout $(git show-ref --verify --quiet refs/remotes/origin/${env:APPVEYOR_REPO_BRANCH} || echo '-b') ${env:APPVEYOR_REPO_BRANCH} + C:\Python37-x64\python.exe unimake.py -d c:\projects\modorganizer-build -s Appveyor_Build=True ${env:APPVEYOR_PROJECT_NAME} artifacts: - path: build\src\game_skyrimse.dll From 049da1cfb9958873f2f19f97d991f6a355d2923d Mon Sep 17 00:00:00 2001 From: Jeremy Rimpo Date: Sun, 20 Sep 2020 22:34:36 -0500 Subject: [PATCH 1030/1544] [game_oblivion] Finalize appveyor script update --- src/games/oblivion/appveyor.yml | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/src/games/oblivion/appveyor.yml b/src/games/oblivion/appveyor.yml index 5399d664..e6c38030 100644 --- a/src/games/oblivion/appveyor.yml +++ b/src/games/oblivion/appveyor.yml @@ -5,15 +5,15 @@ environment: WEBHOOK_URL: secure: gOKbXaZM9ImtMD5XrYITvdyZUW/az082G9OIN1EC1Vbg57wBaeLhi49uGjxPw5GVujHku6kxN6ab89zhbS5GVeluR76GM83IbKV4Sh7udXzoYZZdg6YudtYHzdhCgUeiedpswbuczTq9ceIkkfSEWZuh/lMAAVVwvcGsJAnoPFw= build_script: -- ps: >- - git clone --depth=1 https://github.com/ModOrganizer2/modorganizer-umbrella.git c:\projects\modorganizer-umbrella 2> $null +- pwsh: >- + git clone --depth=1 https://github.com/ModOrganizer2/modorganizer-umbrella.git c:\projects\modorganizer-umbrella - git checkout $(git show-ref --verify --quiet refs/remotes/origin/${env:APPVEYOR_REPO_BRANCH} || echo '-b') ${env:APPVEYOR_REPO_BRANCH} - - mkdir c:\projects\modorganizer-build -type directory + New-Item -ItemType Directory -Path c:\projects\modorganizer-build cd c:\projects\modorganizer-umbrella + git checkout $(git show-ref --verify --quiet refs/remotes/origin/${env:APPVEYOR_REPO_BRANCH} || echo '-b') ${env:APPVEYOR_REPO_BRANCH} + C:\Python37-x64\python.exe unimake.py -d c:\projects\modorganizer-build -s Appveyor_Build=True ${env:APPVEYOR_PROJECT_NAME} artifacts: - path: build\src\game_oblivion.dll From 446031392ecfb775c98ec7041624878bdc7101a5 Mon Sep 17 00:00:00 2001 From: Jeremy Rimpo Date: Sun, 20 Sep 2020 22:34:39 -0500 Subject: [PATCH 1031/1544] [game_skyrim] Finalize appveyor script update --- src/games/skyrim/appveyor.yml | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/src/games/skyrim/appveyor.yml b/src/games/skyrim/appveyor.yml index 95f2fd69..a82e4fe1 100644 --- a/src/games/skyrim/appveyor.yml +++ b/src/games/skyrim/appveyor.yml @@ -5,15 +5,15 @@ environment: WEBHOOK_URL: secure: gOKbXaZM9ImtMD5XrYITvdyZUW/az082G9OIN1EC1Vbg57wBaeLhi49uGjxPw5GVujHku6kxN6ab89zhbS5GVeluR76GM83IbKV4Sh7udXzoYZZdg6YudtYHzdhCgUeiedpswbuczTq9ceIkkfSEWZuh/lMAAVVwvcGsJAnoPFw= build_script: -- ps: >- - git clone --depth=1 https://github.com/ModOrganizer2/modorganizer-umbrella.git c:\projects\modorganizer-umbrella 2> $null +- pwsh: >- + git clone --depth=1 https://github.com/ModOrganizer2/modorganizer-umbrella.git c:\projects\modorganizer-umbrella - git checkout $(git show-ref --verify --quiet refs/remotes/origin/${env:APPVEYOR_REPO_BRANCH} || echo '-b') ${env:APPVEYOR_REPO_BRANCH} - - mkdir c:\projects\modorganizer-build -type directory + New-Item -ItemType Directory -Path c:\projects\modorganizer-build cd c:\projects\modorganizer-umbrella + git checkout $(git show-ref --verify --quiet refs/remotes/origin/${env:APPVEYOR_REPO_BRANCH} || echo '-b') ${env:APPVEYOR_REPO_BRANCH} + C:\Python37-x64\python.exe unimake.py -d c:\projects\modorganizer-build -s Appveyor_Build=True ${env:APPVEYOR_PROJECT_NAME} artifacts: - path: build\src\game_skyrim.dll From 2066f8b634fd234707e62899658a953df5ae1131 Mon Sep 17 00:00:00 2001 From: Jeremy Rimpo Date: Sun, 20 Sep 2020 22:34:41 -0500 Subject: [PATCH 1032/1544] [game_ttw] Finalize appveyor script update --- src/games/ttw/appveyor.yml | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/src/games/ttw/appveyor.yml b/src/games/ttw/appveyor.yml index 1b41b988..e3a3b6c6 100644 --- a/src/games/ttw/appveyor.yml +++ b/src/games/ttw/appveyor.yml @@ -5,15 +5,15 @@ environment: WEBHOOK_URL: secure: gOKbXaZM9ImtMD5XrYITvdyZUW/az082G9OIN1EC1Vbg57wBaeLhi49uGjxPw5GVujHku6kxN6ab89zhbS5GVeluR76GM83IbKV4Sh7udXzoYZZdg6YudtYHzdhCgUeiedpswbuczTq9ceIkkfSEWZuh/lMAAVVwvcGsJAnoPFw= build_script: -- ps: >- - git clone --depth=1 https://github.com/ModOrganizer2/modorganizer-umbrella.git c:\projects\modorganizer-umbrella 2> $null +- pwsh: >- + git clone --depth=1 https://github.com/ModOrganizer2/modorganizer-umbrella.git c:\projects\modorganizer-umbrella - git checkout $(git show-ref --verify --quiet refs/remotes/origin/${env:APPVEYOR_REPO_BRANCH} || echo '-b') ${env:APPVEYOR_REPO_BRANCH} - - mkdir c:\projects\modorganizer-build -type directory + New-Item -ItemType Directory -Path c:\projects\modorganizer-build cd c:\projects\modorganizer-umbrella + git checkout $(git show-ref --verify --quiet refs/remotes/origin/${env:APPVEYOR_REPO_BRANCH} || echo '-b') ${env:APPVEYOR_REPO_BRANCH} + C:\Python37-x64\python.exe unimake.py -d c:\projects\modorganizer-build -s Appveyor_Build=True ${env:APPVEYOR_PROJECT_NAME} artifacts: - path: build\src\game_ttw.dll From fbd1360e52fb1e511ba73b14a886000aa959fa7b Mon Sep 17 00:00:00 2001 From: Jeremy Rimpo Date: Mon, 21 Sep 2020 05:02:20 -0500 Subject: [PATCH 1033/1544] [game_fallout4vr] [skip ci] Pull data from all branches --- src/games/fallout4vr/appveyor.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/games/fallout4vr/appveyor.yml b/src/games/fallout4vr/appveyor.yml index 10e33f1a..24904a13 100644 --- a/src/games/fallout4vr/appveyor.yml +++ b/src/games/fallout4vr/appveyor.yml @@ -6,7 +6,7 @@ environment: secure: gOKbXaZM9ImtMD5XrYITvdyZUW/az082G9OIN1EC1Vbg57wBaeLhi49uGjxPw5GVujHku6kxN6ab89zhbS5GVeluR76GM83IbKV4Sh7udXzoYZZdg6YudtYHzdhCgUeiedpswbuczTq9ceIkkfSEWZuh/lMAAVVwvcGsJAnoPFw= build_script: - pwsh: >- - git clone --depth=1 https://github.com/ModOrganizer2/modorganizer-umbrella.git c:\projects\modorganizer-umbrella + git clone --depth=1 --no-single-branch https://github.com/ModOrganizer2/modorganizer-umbrella.git c:\projects\modorganizer-umbrella New-Item -ItemType Directory -Path c:\projects\modorganizer-build From 916c06b77c9bf28aef5790d4e8f3a18d70c9bb91 Mon Sep 17 00:00:00 2001 From: Jeremy Rimpo Date: Mon, 21 Sep 2020 05:02:23 -0500 Subject: [PATCH 1034/1544] [game_falloutnv] [skip ci] Pull data from all branches --- src/games/falloutnv/appveyor.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/games/falloutnv/appveyor.yml b/src/games/falloutnv/appveyor.yml index a5d2fd14..91e48e99 100644 --- a/src/games/falloutnv/appveyor.yml +++ b/src/games/falloutnv/appveyor.yml @@ -6,7 +6,7 @@ environment: secure: gOKbXaZM9ImtMD5XrYITvdyZUW/az082G9OIN1EC1Vbg57wBaeLhi49uGjxPw5GVujHku6kxN6ab89zhbS5GVeluR76GM83IbKV4Sh7udXzoYZZdg6YudtYHzdhCgUeiedpswbuczTq9ceIkkfSEWZuh/lMAAVVwvcGsJAnoPFw= build_script: - pwsh: >- - git clone --depth=1 https://github.com/ModOrganizer2/modorganizer-umbrella.git c:\projects\modorganizer-umbrella + git clone --depth=1 --no-single-branch https://github.com/ModOrganizer2/modorganizer-umbrella.git c:\projects\modorganizer-umbrella New-Item -ItemType Directory -Path c:\projects\modorganizer-build From 0a7795543b6988d36add4664051028d033df73a7 Mon Sep 17 00:00:00 2001 From: Jeremy Rimpo Date: Mon, 21 Sep 2020 05:02:25 -0500 Subject: [PATCH 1035/1544] [game_morrowind] [skip ci] Pull data from all branches --- src/games/morrowind/appveyor.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/games/morrowind/appveyor.yml b/src/games/morrowind/appveyor.yml index 75d550ba..b85fd713 100644 --- a/src/games/morrowind/appveyor.yml +++ b/src/games/morrowind/appveyor.yml @@ -6,7 +6,7 @@ environment: secure: gOKbXaZM9ImtMD5XrYITvdyZUW/az082G9OIN1EC1Vbg57wBaeLhi49uGjxPw5GVujHku6kxN6ab89zhbS5GVeluR76GM83IbKV4Sh7udXzoYZZdg6YudtYHzdhCgUeiedpswbuczTq9ceIkkfSEWZuh/lMAAVVwvcGsJAnoPFw= build_script: - pwsh: >- - git clone --depth=1 https://github.com/ModOrganizer2/modorganizer-umbrella.git c:\projects\modorganizer-umbrella + git clone --depth=1 --no-single-branch https://github.com/ModOrganizer2/modorganizer-umbrella.git c:\projects\modorganizer-umbrella New-Item -ItemType Directory -Path c:\projects\modorganizer-build From 4f6e94eb847ad1a7df3ff17074aa8ccae5ffe902 Mon Sep 17 00:00:00 2001 From: Jeremy Rimpo Date: Mon, 21 Sep 2020 05:02:28 -0500 Subject: [PATCH 1036/1544] [game_fallout3] [skip ci] Pull data from all branches --- src/games/fallout3/appveyor.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/games/fallout3/appveyor.yml b/src/games/fallout3/appveyor.yml index 41ec7d74..722dcc78 100644 --- a/src/games/fallout3/appveyor.yml +++ b/src/games/fallout3/appveyor.yml @@ -6,7 +6,7 @@ environment: secure: gOKbXaZM9ImtMD5XrYITvdyZUW/az082G9OIN1EC1Vbg57wBaeLhi49uGjxPw5GVujHku6kxN6ab89zhbS5GVeluR76GM83IbKV4Sh7udXzoYZZdg6YudtYHzdhCgUeiedpswbuczTq9ceIkkfSEWZuh/lMAAVVwvcGsJAnoPFw= build_script: - pwsh: >- - git clone --depth=1 https://github.com/ModOrganizer2/modorganizer-umbrella.git c:\projects\modorganizer-umbrella + git clone --depth=1 --no-single-branch https://github.com/ModOrganizer2/modorganizer-umbrella.git c:\projects\modorganizer-umbrella New-Item -ItemType Directory -Path c:\projects\modorganizer-build From 29646dfdfeabd38a2f72d1d6f3cd1e48005db39a Mon Sep 17 00:00:00 2001 From: Jeremy Rimpo Date: Mon, 21 Sep 2020 05:02:29 -0500 Subject: [PATCH 1037/1544] [game_skyrimse] [skip ci] Pull data from all branches --- src/games/skyrimse/appveyor.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/games/skyrimse/appveyor.yml b/src/games/skyrimse/appveyor.yml index 5365d795..63539973 100644 --- a/src/games/skyrimse/appveyor.yml +++ b/src/games/skyrimse/appveyor.yml @@ -6,7 +6,7 @@ environment: secure: gOKbXaZM9ImtMD5XrYITvdyZUW/az082G9OIN1EC1Vbg57wBaeLhi49uGjxPw5GVujHku6kxN6ab89zhbS5GVeluR76GM83IbKV4Sh7udXzoYZZdg6YudtYHzdhCgUeiedpswbuczTq9ceIkkfSEWZuh/lMAAVVwvcGsJAnoPFw= build_script: - pwsh: >- - git clone --depth=1 https://github.com/ModOrganizer2/modorganizer-umbrella.git c:\projects\modorganizer-umbrella + git clone --depth=1 --no-single-branch https://github.com/ModOrganizer2/modorganizer-umbrella.git c:\projects\modorganizer-umbrella New-Item -ItemType Directory -Path c:\projects\modorganizer-build From d6cb8ee61886a34a849c726ae74ad1771980922b Mon Sep 17 00:00:00 2001 From: Jeremy Rimpo Date: Mon, 21 Sep 2020 05:02:30 -0500 Subject: [PATCH 1038/1544] [skip ci] Pull data from all branches --- appveyor.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/appveyor.yml b/appveyor.yml index 2a38bb46..0c4e1f39 100644 --- a/appveyor.yml +++ b/appveyor.yml @@ -6,7 +6,7 @@ environment: secure: gOKbXaZM9ImtMD5XrYITvdyZUW/az082G9OIN1EC1Vbg57wBaeLhi49uGjxPw5GVujHku6kxN6ab89zhbS5GVeluR76GM83IbKV4Sh7udXzoYZZdg6YudtYHzdhCgUeiedpswbuczTq9ceIkkfSEWZuh/lMAAVVwvcGsJAnoPFw= build_script: - pwsh: >- - git clone --depth=1 https://github.com/ModOrganizer2/modorganizer-umbrella.git c:\projects\modorganizer-umbrella + git clone --depth=1 --no-single-branch https://github.com/ModOrganizer2/modorganizer-umbrella.git c:\projects\modorganizer-umbrella New-Item -ItemType Directory -Path c:\projects\modorganizer-build From 73c1b9b96340baa8d61f4638a8cf112b65137d24 Mon Sep 17 00:00:00 2001 From: Jeremy Rimpo Date: Mon, 21 Sep 2020 05:02:30 -0500 Subject: [PATCH 1039/1544] [game_fallout4] [skip ci] Pull data from all branches --- src/games/fallout4/appveyor.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/games/fallout4/appveyor.yml b/src/games/fallout4/appveyor.yml index ffd2a897..df5d8eaf 100644 --- a/src/games/fallout4/appveyor.yml +++ b/src/games/fallout4/appveyor.yml @@ -6,7 +6,7 @@ environment: secure: gOKbXaZM9ImtMD5XrYITvdyZUW/az082G9OIN1EC1Vbg57wBaeLhi49uGjxPw5GVujHku6kxN6ab89zhbS5GVeluR76GM83IbKV4Sh7udXzoYZZdg6YudtYHzdhCgUeiedpswbuczTq9ceIkkfSEWZuh/lMAAVVwvcGsJAnoPFw= build_script: - pwsh: >- - git clone --depth=1 https://github.com/ModOrganizer2/modorganizer-umbrella.git c:\projects\modorganizer-umbrella + git clone --depth=1 --no-single-branch https://github.com/ModOrganizer2/modorganizer-umbrella.git c:\projects\modorganizer-umbrella New-Item -ItemType Directory -Path c:\projects\modorganizer-build From ca67b7b80ada2de9f85fa6945754aaab0c71438e Mon Sep 17 00:00:00 2001 From: Jeremy Rimpo Date: Mon, 21 Sep 2020 05:02:31 -0500 Subject: [PATCH 1040/1544] [game_oblivion] [skip ci] Pull data from all branches --- src/games/oblivion/appveyor.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/games/oblivion/appveyor.yml b/src/games/oblivion/appveyor.yml index e6c38030..9b87e502 100644 --- a/src/games/oblivion/appveyor.yml +++ b/src/games/oblivion/appveyor.yml @@ -6,7 +6,7 @@ environment: secure: gOKbXaZM9ImtMD5XrYITvdyZUW/az082G9OIN1EC1Vbg57wBaeLhi49uGjxPw5GVujHku6kxN6ab89zhbS5GVeluR76GM83IbKV4Sh7udXzoYZZdg6YudtYHzdhCgUeiedpswbuczTq9ceIkkfSEWZuh/lMAAVVwvcGsJAnoPFw= build_script: - pwsh: >- - git clone --depth=1 https://github.com/ModOrganizer2/modorganizer-umbrella.git c:\projects\modorganizer-umbrella + git clone --depth=1 --no-single-branch https://github.com/ModOrganizer2/modorganizer-umbrella.git c:\projects\modorganizer-umbrella New-Item -ItemType Directory -Path c:\projects\modorganizer-build From 16e40afee79cd8590c3c0c2d423f9fc14de15570 Mon Sep 17 00:00:00 2001 From: Jeremy Rimpo Date: Mon, 21 Sep 2020 05:02:33 -0500 Subject: [PATCH 1041/1544] [game_skyrimvr] [skip ci] Pull data from all branches --- src/games/skyrimvr/appveyor.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/games/skyrimvr/appveyor.yml b/src/games/skyrimvr/appveyor.yml index 8c11e8d8..6812fce1 100644 --- a/src/games/skyrimvr/appveyor.yml +++ b/src/games/skyrimvr/appveyor.yml @@ -6,7 +6,7 @@ environment: secure: gOKbXaZM9ImtMD5XrYITvdyZUW/az082G9OIN1EC1Vbg57wBaeLhi49uGjxPw5GVujHku6kxN6ab89zhbS5GVeluR76GM83IbKV4Sh7udXzoYZZdg6YudtYHzdhCgUeiedpswbuczTq9ceIkkfSEWZuh/lMAAVVwvcGsJAnoPFw= build_script: - pwsh: >- - git clone --depth=1 https://github.com/ModOrganizer2/modorganizer-umbrella.git c:\projects\modorganizer-umbrella + git clone --depth=1 --no-single-branch https://github.com/ModOrganizer2/modorganizer-umbrella.git c:\projects\modorganizer-umbrella New-Item -ItemType Directory -Path c:\projects\modorganizer-build From c82c21394a674bcc10906d7ab3be4f35458bda4b Mon Sep 17 00:00:00 2001 From: Jeremy Rimpo Date: Mon, 21 Sep 2020 05:02:36 -0500 Subject: [PATCH 1042/1544] [game_skyrim] [skip ci] Pull data from all branches --- src/games/skyrim/appveyor.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/games/skyrim/appveyor.yml b/src/games/skyrim/appveyor.yml index a82e4fe1..2d88bf51 100644 --- a/src/games/skyrim/appveyor.yml +++ b/src/games/skyrim/appveyor.yml @@ -6,7 +6,7 @@ environment: secure: gOKbXaZM9ImtMD5XrYITvdyZUW/az082G9OIN1EC1Vbg57wBaeLhi49uGjxPw5GVujHku6kxN6ab89zhbS5GVeluR76GM83IbKV4Sh7udXzoYZZdg6YudtYHzdhCgUeiedpswbuczTq9ceIkkfSEWZuh/lMAAVVwvcGsJAnoPFw= build_script: - pwsh: >- - git clone --depth=1 https://github.com/ModOrganizer2/modorganizer-umbrella.git c:\projects\modorganizer-umbrella + git clone --depth=1 --no-single-branch https://github.com/ModOrganizer2/modorganizer-umbrella.git c:\projects\modorganizer-umbrella New-Item -ItemType Directory -Path c:\projects\modorganizer-build From 04cef110a982effa633484ec28a83123b776915b Mon Sep 17 00:00:00 2001 From: Jeremy Rimpo Date: Mon, 21 Sep 2020 05:02:39 -0500 Subject: [PATCH 1043/1544] [game_ttw] [skip ci] Pull data from all branches --- src/games/ttw/appveyor.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/games/ttw/appveyor.yml b/src/games/ttw/appveyor.yml index e3a3b6c6..ba96d533 100644 --- a/src/games/ttw/appveyor.yml +++ b/src/games/ttw/appveyor.yml @@ -6,7 +6,7 @@ environment: secure: gOKbXaZM9ImtMD5XrYITvdyZUW/az082G9OIN1EC1Vbg57wBaeLhi49uGjxPw5GVujHku6kxN6ab89zhbS5GVeluR76GM83IbKV4Sh7udXzoYZZdg6YudtYHzdhCgUeiedpswbuczTq9ceIkkfSEWZuh/lMAAVVwvcGsJAnoPFw= build_script: - pwsh: >- - git clone --depth=1 https://github.com/ModOrganizer2/modorganizer-umbrella.git c:\projects\modorganizer-umbrella + git clone --depth=1 --no-single-branch https://github.com/ModOrganizer2/modorganizer-umbrella.git c:\projects\modorganizer-umbrella New-Item -ItemType Directory -Path c:\projects\modorganizer-build From 484c6b5c27925ee8cfe2ccccd22d5239c54a6b19 Mon Sep 17 00:00:00 2001 From: Jeremy Rimpo Date: Mon, 21 Sep 2020 06:25:02 -0500 Subject: [PATCH 1044/1544] [game_fallout4vr] [skip ci] Force exit PS with last exit code after umbrella build error --- src/games/fallout4vr/appveyor.yml | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/src/games/fallout4vr/appveyor.yml b/src/games/fallout4vr/appveyor.yml index 24904a13..303326dc 100644 --- a/src/games/fallout4vr/appveyor.yml +++ b/src/games/fallout4vr/appveyor.yml @@ -6,6 +6,8 @@ environment: secure: gOKbXaZM9ImtMD5XrYITvdyZUW/az082G9OIN1EC1Vbg57wBaeLhi49uGjxPw5GVujHku6kxN6ab89zhbS5GVeluR76GM83IbKV4Sh7udXzoYZZdg6YudtYHzdhCgUeiedpswbuczTq9ceIkkfSEWZuh/lMAAVVwvcGsJAnoPFw= build_script: - pwsh: >- + $ErrorActionPreference = 'Stop' + git clone --depth=1 --no-single-branch https://github.com/ModOrganizer2/modorganizer-umbrella.git c:\projects\modorganizer-umbrella New-Item -ItemType Directory -Path c:\projects\modorganizer-build @@ -15,6 +17,8 @@ build_script: git checkout $(git show-ref --verify --quiet refs/remotes/origin/${env:APPVEYOR_REPO_BRANCH} || echo '-b') ${env:APPVEYOR_REPO_BRANCH} C:\Python37-x64\python.exe unimake.py -d c:\projects\modorganizer-build -s Appveyor_Build=True ${env:APPVEYOR_PROJECT_NAME} + + if($LastExitCode -ne 0) { $host.SetShouldExit($LastExitCode ) } artifacts: - path: build\src\game_fallout4vr.dll name: game_fallout4vr_dll From 841664bab2c86db3afd890f0b697a00dc1dc5b9b Mon Sep 17 00:00:00 2001 From: Jeremy Rimpo Date: Mon, 21 Sep 2020 06:25:05 -0500 Subject: [PATCH 1045/1544] [game_falloutnv] [skip ci] Force exit PS with last exit code after umbrella build error --- src/games/falloutnv/appveyor.yml | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/src/games/falloutnv/appveyor.yml b/src/games/falloutnv/appveyor.yml index 91e48e99..ee63b30e 100644 --- a/src/games/falloutnv/appveyor.yml +++ b/src/games/falloutnv/appveyor.yml @@ -6,6 +6,8 @@ environment: secure: gOKbXaZM9ImtMD5XrYITvdyZUW/az082G9OIN1EC1Vbg57wBaeLhi49uGjxPw5GVujHku6kxN6ab89zhbS5GVeluR76GM83IbKV4Sh7udXzoYZZdg6YudtYHzdhCgUeiedpswbuczTq9ceIkkfSEWZuh/lMAAVVwvcGsJAnoPFw= build_script: - pwsh: >- + $ErrorActionPreference = 'Stop' + git clone --depth=1 --no-single-branch https://github.com/ModOrganizer2/modorganizer-umbrella.git c:\projects\modorganizer-umbrella New-Item -ItemType Directory -Path c:\projects\modorganizer-build @@ -15,6 +17,8 @@ build_script: git checkout $(git show-ref --verify --quiet refs/remotes/origin/${env:APPVEYOR_REPO_BRANCH} || echo '-b') ${env:APPVEYOR_REPO_BRANCH} C:\Python37-x64\python.exe unimake.py -d c:\projects\modorganizer-build -s Appveyor_Build=True ${env:APPVEYOR_PROJECT_NAME} + + if($LastExitCode -ne 0) { $host.SetShouldExit($LastExitCode ) } artifacts: - path: build\src\game_falloutNV.dll name: game_falloutNV_dll From dfc7bd3c71014cac136018dff2657288483c9dfd Mon Sep 17 00:00:00 2001 From: Jeremy Rimpo Date: Mon, 21 Sep 2020 06:25:06 -0500 Subject: [PATCH 1046/1544] [game_morrowind] [skip ci] Force exit PS with last exit code after umbrella build error --- src/games/morrowind/appveyor.yml | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/src/games/morrowind/appveyor.yml b/src/games/morrowind/appveyor.yml index b85fd713..5d82f432 100644 --- a/src/games/morrowind/appveyor.yml +++ b/src/games/morrowind/appveyor.yml @@ -6,6 +6,8 @@ environment: secure: gOKbXaZM9ImtMD5XrYITvdyZUW/az082G9OIN1EC1Vbg57wBaeLhi49uGjxPw5GVujHku6kxN6ab89zhbS5GVeluR76GM83IbKV4Sh7udXzoYZZdg6YudtYHzdhCgUeiedpswbuczTq9ceIkkfSEWZuh/lMAAVVwvcGsJAnoPFw= build_script: - pwsh: >- + $ErrorActionPreference = 'Stop' + git clone --depth=1 --no-single-branch https://github.com/ModOrganizer2/modorganizer-umbrella.git c:\projects\modorganizer-umbrella New-Item -ItemType Directory -Path c:\projects\modorganizer-build @@ -15,6 +17,8 @@ build_script: git checkout $(git show-ref --verify --quiet refs/remotes/origin/${env:APPVEYOR_REPO_BRANCH} || echo '-b') ${env:APPVEYOR_REPO_BRANCH} C:\Python37-x64\python.exe unimake.py -d c:\projects\modorganizer-build -s Appveyor_Build=True ${env:APPVEYOR_PROJECT_NAME} + + if($LastExitCode -ne 0) { $host.SetShouldExit($LastExitCode ) } artifacts: - path: build\src\game_morrowind.dll name: game_morrowind_dll From 9b1fec862be384a0823140db257b3ab2ce617eda Mon Sep 17 00:00:00 2001 From: Jeremy Rimpo Date: Mon, 21 Sep 2020 06:25:09 -0500 Subject: [PATCH 1047/1544] [game_fallout3] [skip ci] Force exit PS with last exit code after umbrella build error --- src/games/fallout3/appveyor.yml | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/src/games/fallout3/appveyor.yml b/src/games/fallout3/appveyor.yml index 722dcc78..eb9d281a 100644 --- a/src/games/fallout3/appveyor.yml +++ b/src/games/fallout3/appveyor.yml @@ -6,6 +6,8 @@ environment: secure: gOKbXaZM9ImtMD5XrYITvdyZUW/az082G9OIN1EC1Vbg57wBaeLhi49uGjxPw5GVujHku6kxN6ab89zhbS5GVeluR76GM83IbKV4Sh7udXzoYZZdg6YudtYHzdhCgUeiedpswbuczTq9ceIkkfSEWZuh/lMAAVVwvcGsJAnoPFw= build_script: - pwsh: >- + $ErrorActionPreference = 'Stop' + git clone --depth=1 --no-single-branch https://github.com/ModOrganizer2/modorganizer-umbrella.git c:\projects\modorganizer-umbrella New-Item -ItemType Directory -Path c:\projects\modorganizer-build @@ -15,6 +17,8 @@ build_script: git checkout $(git show-ref --verify --quiet refs/remotes/origin/${env:APPVEYOR_REPO_BRANCH} || echo '-b') ${env:APPVEYOR_REPO_BRANCH} C:\Python37-x64\python.exe unimake.py -d c:\projects\modorganizer-build -s Appveyor_Build=True ${env:APPVEYOR_PROJECT_NAME} + + if($LastExitCode -ne 0) { $host.SetShouldExit($LastExitCode ) } artifacts: - path: build\src\game_fallout3.dll name: game_fallout3_dll From b6e555f8617cc02ffeccdc18948a859660938b34 Mon Sep 17 00:00:00 2001 From: Jeremy Rimpo Date: Mon, 21 Sep 2020 06:25:09 -0500 Subject: [PATCH 1048/1544] [game_skyrimse] [skip ci] Force exit PS with last exit code after umbrella build error --- src/games/skyrimse/appveyor.yml | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/src/games/skyrimse/appveyor.yml b/src/games/skyrimse/appveyor.yml index 63539973..2e2dc942 100644 --- a/src/games/skyrimse/appveyor.yml +++ b/src/games/skyrimse/appveyor.yml @@ -6,6 +6,8 @@ environment: secure: gOKbXaZM9ImtMD5XrYITvdyZUW/az082G9OIN1EC1Vbg57wBaeLhi49uGjxPw5GVujHku6kxN6ab89zhbS5GVeluR76GM83IbKV4Sh7udXzoYZZdg6YudtYHzdhCgUeiedpswbuczTq9ceIkkfSEWZuh/lMAAVVwvcGsJAnoPFw= build_script: - pwsh: >- + $ErrorActionPreference = 'Stop' + git clone --depth=1 --no-single-branch https://github.com/ModOrganizer2/modorganizer-umbrella.git c:\projects\modorganizer-umbrella New-Item -ItemType Directory -Path c:\projects\modorganizer-build @@ -15,6 +17,8 @@ build_script: git checkout $(git show-ref --verify --quiet refs/remotes/origin/${env:APPVEYOR_REPO_BRANCH} || echo '-b') ${env:APPVEYOR_REPO_BRANCH} C:\Python37-x64\python.exe unimake.py -d c:\projects\modorganizer-build -s Appveyor_Build=True ${env:APPVEYOR_PROJECT_NAME} + + if($LastExitCode -ne 0) { $host.SetShouldExit($LastExitCode ) } artifacts: - path: build\src\game_skyrimse.dll name: game_skyrimse_dll From f1cae89425d12a0aa9c5227c33d29cddedddf60a Mon Sep 17 00:00:00 2001 From: Jeremy Rimpo Date: Mon, 21 Sep 2020 06:25:10 -0500 Subject: [PATCH 1049/1544] [skip ci] Force exit PS with last exit code after umbrella build error --- appveyor.yml | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/appveyor.yml b/appveyor.yml index 0c4e1f39..b7bbfda2 100644 --- a/appveyor.yml +++ b/appveyor.yml @@ -6,6 +6,8 @@ environment: secure: gOKbXaZM9ImtMD5XrYITvdyZUW/az082G9OIN1EC1Vbg57wBaeLhi49uGjxPw5GVujHku6kxN6ab89zhbS5GVeluR76GM83IbKV4Sh7udXzoYZZdg6YudtYHzdhCgUeiedpswbuczTq9ceIkkfSEWZuh/lMAAVVwvcGsJAnoPFw= build_script: - pwsh: >- + $ErrorActionPreference = 'Stop' + git clone --depth=1 --no-single-branch https://github.com/ModOrganizer2/modorganizer-umbrella.git c:\projects\modorganizer-umbrella New-Item -ItemType Directory -Path c:\projects\modorganizer-build @@ -15,6 +17,8 @@ build_script: git checkout $(git show-ref --verify --quiet refs/remotes/origin/${env:APPVEYOR_REPO_BRANCH} || echo '-b') ${env:APPVEYOR_REPO_BRANCH} C:\Python37-x64\python.exe unimake.py -d c:\projects\modorganizer-build -s Appveyor_Build=True ${env:APPVEYOR_PROJECT_NAME} + + if($LastExitCode -ne 0) { $host.SetShouldExit($LastExitCode ) } artifacts: - path: build\src\gamebryo\game_gamebryo.lib name: game_gamebryo_lib From 81780163404dde8b113e1ca4dd2c0ce79653225b Mon Sep 17 00:00:00 2001 From: Jeremy Rimpo Date: Mon, 21 Sep 2020 06:25:11 -0500 Subject: [PATCH 1050/1544] [game_oblivion] [skip ci] Force exit PS with last exit code after umbrella build error --- src/games/oblivion/appveyor.yml | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/src/games/oblivion/appveyor.yml b/src/games/oblivion/appveyor.yml index 9b87e502..63c93ae3 100644 --- a/src/games/oblivion/appveyor.yml +++ b/src/games/oblivion/appveyor.yml @@ -6,6 +6,8 @@ environment: secure: gOKbXaZM9ImtMD5XrYITvdyZUW/az082G9OIN1EC1Vbg57wBaeLhi49uGjxPw5GVujHku6kxN6ab89zhbS5GVeluR76GM83IbKV4Sh7udXzoYZZdg6YudtYHzdhCgUeiedpswbuczTq9ceIkkfSEWZuh/lMAAVVwvcGsJAnoPFw= build_script: - pwsh: >- + $ErrorActionPreference = 'Stop' + git clone --depth=1 --no-single-branch https://github.com/ModOrganizer2/modorganizer-umbrella.git c:\projects\modorganizer-umbrella New-Item -ItemType Directory -Path c:\projects\modorganizer-build @@ -15,6 +17,8 @@ build_script: git checkout $(git show-ref --verify --quiet refs/remotes/origin/${env:APPVEYOR_REPO_BRANCH} || echo '-b') ${env:APPVEYOR_REPO_BRANCH} C:\Python37-x64\python.exe unimake.py -d c:\projects\modorganizer-build -s Appveyor_Build=True ${env:APPVEYOR_PROJECT_NAME} + + if($LastExitCode -ne 0) { $host.SetShouldExit($LastExitCode ) } artifacts: - path: build\src\game_oblivion.dll name: game_oblivion_dll From a240b3ad21c36b0da204135a58ee6c3db5b524f4 Mon Sep 17 00:00:00 2001 From: Jeremy Rimpo Date: Mon, 21 Sep 2020 06:25:11 -0500 Subject: [PATCH 1051/1544] [game_fallout4] [skip ci] Force exit PS with last exit code after umbrella build error --- src/games/fallout4/appveyor.yml | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/src/games/fallout4/appveyor.yml b/src/games/fallout4/appveyor.yml index df5d8eaf..49d09b55 100644 --- a/src/games/fallout4/appveyor.yml +++ b/src/games/fallout4/appveyor.yml @@ -6,6 +6,8 @@ environment: secure: gOKbXaZM9ImtMD5XrYITvdyZUW/az082G9OIN1EC1Vbg57wBaeLhi49uGjxPw5GVujHku6kxN6ab89zhbS5GVeluR76GM83IbKV4Sh7udXzoYZZdg6YudtYHzdhCgUeiedpswbuczTq9ceIkkfSEWZuh/lMAAVVwvcGsJAnoPFw= build_script: - pwsh: >- + $ErrorActionPreference = 'Stop' + git clone --depth=1 --no-single-branch https://github.com/ModOrganizer2/modorganizer-umbrella.git c:\projects\modorganizer-umbrella New-Item -ItemType Directory -Path c:\projects\modorganizer-build @@ -15,6 +17,8 @@ build_script: git checkout $(git show-ref --verify --quiet refs/remotes/origin/${env:APPVEYOR_REPO_BRANCH} || echo '-b') ${env:APPVEYOR_REPO_BRANCH} C:\Python37-x64\python.exe unimake.py -d c:\projects\modorganizer-build -s Appveyor_Build=True ${env:APPVEYOR_PROJECT_NAME} + + if($LastExitCode -ne 0) { $host.SetShouldExit($LastExitCode ) } artifacts: - path: build\src\game_fallout4.dll name: game_fallout4_dll From 1fad20969e6eaeff7f11c266b4b9fd4e14f6f10e Mon Sep 17 00:00:00 2001 From: Jeremy Rimpo Date: Mon, 21 Sep 2020 06:25:12 -0500 Subject: [PATCH 1052/1544] [game_skyrimvr] [skip ci] Force exit PS with last exit code after umbrella build error --- src/games/skyrimvr/appveyor.yml | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/src/games/skyrimvr/appveyor.yml b/src/games/skyrimvr/appveyor.yml index 6812fce1..08fa0ac0 100644 --- a/src/games/skyrimvr/appveyor.yml +++ b/src/games/skyrimvr/appveyor.yml @@ -6,6 +6,8 @@ environment: secure: gOKbXaZM9ImtMD5XrYITvdyZUW/az082G9OIN1EC1Vbg57wBaeLhi49uGjxPw5GVujHku6kxN6ab89zhbS5GVeluR76GM83IbKV4Sh7udXzoYZZdg6YudtYHzdhCgUeiedpswbuczTq9ceIkkfSEWZuh/lMAAVVwvcGsJAnoPFw= build_script: - pwsh: >- + $ErrorActionPreference = 'Stop' + git clone --depth=1 --no-single-branch https://github.com/ModOrganizer2/modorganizer-umbrella.git c:\projects\modorganizer-umbrella New-Item -ItemType Directory -Path c:\projects\modorganizer-build @@ -15,6 +17,8 @@ build_script: git checkout $(git show-ref --verify --quiet refs/remotes/origin/${env:APPVEYOR_REPO_BRANCH} || echo '-b') ${env:APPVEYOR_REPO_BRANCH} C:\Python37-x64\python.exe unimake.py -d c:\projects\modorganizer-build -s Appveyor_Build=True ${env:APPVEYOR_PROJECT_NAME} + + if($LastExitCode -ne 0) { $host.SetShouldExit($LastExitCode ) } artifacts: - path: build\src\game_skyrimvr.dll name: game_skyrimvr_dll From 4cf8f29a595c1cdd79445113fd6458e87bf16215 Mon Sep 17 00:00:00 2001 From: Jeremy Rimpo Date: Mon, 21 Sep 2020 06:25:15 -0500 Subject: [PATCH 1053/1544] [game_skyrim] [skip ci] Force exit PS with last exit code after umbrella build error --- src/games/skyrim/appveyor.yml | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/src/games/skyrim/appveyor.yml b/src/games/skyrim/appveyor.yml index 2d88bf51..22bd43ee 100644 --- a/src/games/skyrim/appveyor.yml +++ b/src/games/skyrim/appveyor.yml @@ -6,6 +6,8 @@ environment: secure: gOKbXaZM9ImtMD5XrYITvdyZUW/az082G9OIN1EC1Vbg57wBaeLhi49uGjxPw5GVujHku6kxN6ab89zhbS5GVeluR76GM83IbKV4Sh7udXzoYZZdg6YudtYHzdhCgUeiedpswbuczTq9ceIkkfSEWZuh/lMAAVVwvcGsJAnoPFw= build_script: - pwsh: >- + $ErrorActionPreference = 'Stop' + git clone --depth=1 --no-single-branch https://github.com/ModOrganizer2/modorganizer-umbrella.git c:\projects\modorganizer-umbrella New-Item -ItemType Directory -Path c:\projects\modorganizer-build @@ -15,6 +17,8 @@ build_script: git checkout $(git show-ref --verify --quiet refs/remotes/origin/${env:APPVEYOR_REPO_BRANCH} || echo '-b') ${env:APPVEYOR_REPO_BRANCH} C:\Python37-x64\python.exe unimake.py -d c:\projects\modorganizer-build -s Appveyor_Build=True ${env:APPVEYOR_PROJECT_NAME} + + if($LastExitCode -ne 0) { $host.SetShouldExit($LastExitCode ) } artifacts: - path: build\src\game_skyrim.dll name: game_skyrim_dll From caad97fabd7c197fa6bb992eaa2de16856e2bd00 Mon Sep 17 00:00:00 2001 From: Jeremy Rimpo Date: Mon, 21 Sep 2020 06:25:18 -0500 Subject: [PATCH 1054/1544] [game_ttw] [skip ci] Force exit PS with last exit code after umbrella build error --- src/games/ttw/appveyor.yml | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/src/games/ttw/appveyor.yml b/src/games/ttw/appveyor.yml index ba96d533..2b5ce8b3 100644 --- a/src/games/ttw/appveyor.yml +++ b/src/games/ttw/appveyor.yml @@ -6,6 +6,8 @@ environment: secure: gOKbXaZM9ImtMD5XrYITvdyZUW/az082G9OIN1EC1Vbg57wBaeLhi49uGjxPw5GVujHku6kxN6ab89zhbS5GVeluR76GM83IbKV4Sh7udXzoYZZdg6YudtYHzdhCgUeiedpswbuczTq9ceIkkfSEWZuh/lMAAVVwvcGsJAnoPFw= build_script: - pwsh: >- + $ErrorActionPreference = 'Stop' + git clone --depth=1 --no-single-branch https://github.com/ModOrganizer2/modorganizer-umbrella.git c:\projects\modorganizer-umbrella New-Item -ItemType Directory -Path c:\projects\modorganizer-build @@ -15,6 +17,8 @@ build_script: git checkout $(git show-ref --verify --quiet refs/remotes/origin/${env:APPVEYOR_REPO_BRANCH} || echo '-b') ${env:APPVEYOR_REPO_BRANCH} C:\Python37-x64\python.exe unimake.py -d c:\projects\modorganizer-build -s Appveyor_Build=True ${env:APPVEYOR_PROJECT_NAME} + + if($LastExitCode -ne 0) { $host.SetShouldExit($LastExitCode ) } artifacts: - path: build\src\game_ttw.dll name: game_ttw_dll From dbcebf911eccdc6c8ff56ab8e686ce0c342e42a7 Mon Sep 17 00:00:00 2001 From: Jeremy Rimpo Date: Fri, 25 Sep 2020 00:34:13 -0500 Subject: [PATCH 1055/1544] [game_fallout4vr] [skip ci] Use PR branch for umbrella repo (if it exists) --- src/games/fallout4vr/appveyor.yml | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/src/games/fallout4vr/appveyor.yml b/src/games/fallout4vr/appveyor.yml index 303326dc..d88dc03d 100644 --- a/src/games/fallout4vr/appveyor.yml +++ b/src/games/fallout4vr/appveyor.yml @@ -13,8 +13,10 @@ build_script: New-Item -ItemType Directory -Path c:\projects\modorganizer-build cd c:\projects\modorganizer-umbrella + + ($env:APPVEYOR_PULL_REQUEST_HEAD_REPO_BRANCH -eq $null) ? ($branch = $env:APPVEYOR_REPO_BRANCH) : ($branch = $env:APPVEYOR_PULL_REQUEST_HEAD_REPO_BRANCH) - git checkout $(git show-ref --verify --quiet refs/remotes/origin/${env:APPVEYOR_REPO_BRANCH} || echo '-b') ${env:APPVEYOR_REPO_BRANCH} + git checkout $(git show-ref --verify --quiet refs/remotes/origin/${branch} || echo '-b') ${branch} C:\Python37-x64\python.exe unimake.py -d c:\projects\modorganizer-build -s Appveyor_Build=True ${env:APPVEYOR_PROJECT_NAME} From 52e38b464f70f36ac62729fea01cca39978b086f Mon Sep 17 00:00:00 2001 From: Jeremy Rimpo Date: Fri, 25 Sep 2020 00:34:15 -0500 Subject: [PATCH 1056/1544] [game_morrowind] [skip ci] Use PR branch for umbrella repo (if it exists) --- src/games/morrowind/appveyor.yml | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/src/games/morrowind/appveyor.yml b/src/games/morrowind/appveyor.yml index 5d82f432..d14f97cd 100644 --- a/src/games/morrowind/appveyor.yml +++ b/src/games/morrowind/appveyor.yml @@ -13,8 +13,10 @@ build_script: New-Item -ItemType Directory -Path c:\projects\modorganizer-build cd c:\projects\modorganizer-umbrella + + ($env:APPVEYOR_PULL_REQUEST_HEAD_REPO_BRANCH -eq $null) ? ($branch = $env:APPVEYOR_REPO_BRANCH) : ($branch = $env:APPVEYOR_PULL_REQUEST_HEAD_REPO_BRANCH) - git checkout $(git show-ref --verify --quiet refs/remotes/origin/${env:APPVEYOR_REPO_BRANCH} || echo '-b') ${env:APPVEYOR_REPO_BRANCH} + git checkout $(git show-ref --verify --quiet refs/remotes/origin/${branch} || echo '-b') ${branch} C:\Python37-x64\python.exe unimake.py -d c:\projects\modorganizer-build -s Appveyor_Build=True ${env:APPVEYOR_PROJECT_NAME} From 3ba3258be38c06709c73a76d6121b10f213adb43 Mon Sep 17 00:00:00 2001 From: Jeremy Rimpo Date: Fri, 25 Sep 2020 00:34:15 -0500 Subject: [PATCH 1057/1544] [game_falloutnv] [skip ci] Use PR branch for umbrella repo (if it exists) --- src/games/falloutnv/appveyor.yml | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/src/games/falloutnv/appveyor.yml b/src/games/falloutnv/appveyor.yml index ee63b30e..5986a05d 100644 --- a/src/games/falloutnv/appveyor.yml +++ b/src/games/falloutnv/appveyor.yml @@ -13,8 +13,10 @@ build_script: New-Item -ItemType Directory -Path c:\projects\modorganizer-build cd c:\projects\modorganizer-umbrella + + ($env:APPVEYOR_PULL_REQUEST_HEAD_REPO_BRANCH -eq $null) ? ($branch = $env:APPVEYOR_REPO_BRANCH) : ($branch = $env:APPVEYOR_PULL_REQUEST_HEAD_REPO_BRANCH) - git checkout $(git show-ref --verify --quiet refs/remotes/origin/${env:APPVEYOR_REPO_BRANCH} || echo '-b') ${env:APPVEYOR_REPO_BRANCH} + git checkout $(git show-ref --verify --quiet refs/remotes/origin/${branch} || echo '-b') ${branch} C:\Python37-x64\python.exe unimake.py -d c:\projects\modorganizer-build -s Appveyor_Build=True ${env:APPVEYOR_PROJECT_NAME} From 9db5fb36744feb3c9df4b6150501965b6dd29aa3 Mon Sep 17 00:00:00 2001 From: Jeremy Rimpo Date: Fri, 25 Sep 2020 00:34:19 -0500 Subject: [PATCH 1058/1544] [game_oblivion] [skip ci] Use PR branch for umbrella repo (if it exists) --- src/games/oblivion/appveyor.yml | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/src/games/oblivion/appveyor.yml b/src/games/oblivion/appveyor.yml index 63c93ae3..8d8164c1 100644 --- a/src/games/oblivion/appveyor.yml +++ b/src/games/oblivion/appveyor.yml @@ -13,8 +13,10 @@ build_script: New-Item -ItemType Directory -Path c:\projects\modorganizer-build cd c:\projects\modorganizer-umbrella + + ($env:APPVEYOR_PULL_REQUEST_HEAD_REPO_BRANCH -eq $null) ? ($branch = $env:APPVEYOR_REPO_BRANCH) : ($branch = $env:APPVEYOR_PULL_REQUEST_HEAD_REPO_BRANCH) - git checkout $(git show-ref --verify --quiet refs/remotes/origin/${env:APPVEYOR_REPO_BRANCH} || echo '-b') ${env:APPVEYOR_REPO_BRANCH} + git checkout $(git show-ref --verify --quiet refs/remotes/origin/${branch} || echo '-b') ${branch} C:\Python37-x64\python.exe unimake.py -d c:\projects\modorganizer-build -s Appveyor_Build=True ${env:APPVEYOR_PROJECT_NAME} From a56cfbbe5b87b9c0470c43c80a2095c43d3876d9 Mon Sep 17 00:00:00 2001 From: Jeremy Rimpo Date: Fri, 25 Sep 2020 00:34:20 -0500 Subject: [PATCH 1059/1544] [game_skyrimvr] [skip ci] Use PR branch for umbrella repo (if it exists) --- src/games/skyrimvr/appveyor.yml | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/src/games/skyrimvr/appveyor.yml b/src/games/skyrimvr/appveyor.yml index 08fa0ac0..f37f060f 100644 --- a/src/games/skyrimvr/appveyor.yml +++ b/src/games/skyrimvr/appveyor.yml @@ -13,8 +13,10 @@ build_script: New-Item -ItemType Directory -Path c:\projects\modorganizer-build cd c:\projects\modorganizer-umbrella + + ($env:APPVEYOR_PULL_REQUEST_HEAD_REPO_BRANCH -eq $null) ? ($branch = $env:APPVEYOR_REPO_BRANCH) : ($branch = $env:APPVEYOR_PULL_REQUEST_HEAD_REPO_BRANCH) - git checkout $(git show-ref --verify --quiet refs/remotes/origin/${env:APPVEYOR_REPO_BRANCH} || echo '-b') ${env:APPVEYOR_REPO_BRANCH} + git checkout $(git show-ref --verify --quiet refs/remotes/origin/${branch} || echo '-b') ${branch} C:\Python37-x64\python.exe unimake.py -d c:\projects\modorganizer-build -s Appveyor_Build=True ${env:APPVEYOR_PROJECT_NAME} From 9a7bbbff5ae2f8779fd58ab93c4c2be3711bfbb1 Mon Sep 17 00:00:00 2001 From: Jeremy Rimpo Date: Fri, 25 Sep 2020 00:34:21 -0500 Subject: [PATCH 1060/1544] [game_fallout3] [skip ci] Use PR branch for umbrella repo (if it exists) --- src/games/fallout3/appveyor.yml | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/src/games/fallout3/appveyor.yml b/src/games/fallout3/appveyor.yml index eb9d281a..61925c54 100644 --- a/src/games/fallout3/appveyor.yml +++ b/src/games/fallout3/appveyor.yml @@ -13,8 +13,10 @@ build_script: New-Item -ItemType Directory -Path c:\projects\modorganizer-build cd c:\projects\modorganizer-umbrella + + ($env:APPVEYOR_PULL_REQUEST_HEAD_REPO_BRANCH -eq $null) ? ($branch = $env:APPVEYOR_REPO_BRANCH) : ($branch = $env:APPVEYOR_PULL_REQUEST_HEAD_REPO_BRANCH) - git checkout $(git show-ref --verify --quiet refs/remotes/origin/${env:APPVEYOR_REPO_BRANCH} || echo '-b') ${env:APPVEYOR_REPO_BRANCH} + git checkout $(git show-ref --verify --quiet refs/remotes/origin/${branch} || echo '-b') ${branch} C:\Python37-x64\python.exe unimake.py -d c:\projects\modorganizer-build -s Appveyor_Build=True ${env:APPVEYOR_PROJECT_NAME} From 95836bb81773ba5b0ecd8ad616819f7afe51953d Mon Sep 17 00:00:00 2001 From: Jeremy Rimpo Date: Fri, 25 Sep 2020 00:34:21 -0500 Subject: [PATCH 1061/1544] [game_fallout4] [skip ci] Use PR branch for umbrella repo (if it exists) --- src/games/fallout4/appveyor.yml | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/src/games/fallout4/appveyor.yml b/src/games/fallout4/appveyor.yml index 49d09b55..07c567fd 100644 --- a/src/games/fallout4/appveyor.yml +++ b/src/games/fallout4/appveyor.yml @@ -13,8 +13,10 @@ build_script: New-Item -ItemType Directory -Path c:\projects\modorganizer-build cd c:\projects\modorganizer-umbrella + + ($env:APPVEYOR_PULL_REQUEST_HEAD_REPO_BRANCH -eq $null) ? ($branch = $env:APPVEYOR_REPO_BRANCH) : ($branch = $env:APPVEYOR_PULL_REQUEST_HEAD_REPO_BRANCH) - git checkout $(git show-ref --verify --quiet refs/remotes/origin/${env:APPVEYOR_REPO_BRANCH} || echo '-b') ${env:APPVEYOR_REPO_BRANCH} + git checkout $(git show-ref --verify --quiet refs/remotes/origin/${branch} || echo '-b') ${branch} C:\Python37-x64\python.exe unimake.py -d c:\projects\modorganizer-build -s Appveyor_Build=True ${env:APPVEYOR_PROJECT_NAME} From 0d4b44c51a19cd21dfdd556c77f63b88e57b0ad4 Mon Sep 17 00:00:00 2001 From: Jeremy Rimpo Date: Fri, 25 Sep 2020 00:34:22 -0500 Subject: [PATCH 1062/1544] [skip ci] Use PR branch for umbrella repo (if it exists) --- appveyor.yml | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/appveyor.yml b/appveyor.yml index b7bbfda2..bea8130b 100644 --- a/appveyor.yml +++ b/appveyor.yml @@ -13,8 +13,10 @@ build_script: New-Item -ItemType Directory -Path c:\projects\modorganizer-build cd c:\projects\modorganizer-umbrella + + ($env:APPVEYOR_PULL_REQUEST_HEAD_REPO_BRANCH -eq $null) ? ($branch = $env:APPVEYOR_REPO_BRANCH) : ($branch = $env:APPVEYOR_PULL_REQUEST_HEAD_REPO_BRANCH) - git checkout $(git show-ref --verify --quiet refs/remotes/origin/${env:APPVEYOR_REPO_BRANCH} || echo '-b') ${env:APPVEYOR_REPO_BRANCH} + git checkout $(git show-ref --verify --quiet refs/remotes/origin/${branch} || echo '-b') ${branch} C:\Python37-x64\python.exe unimake.py -d c:\projects\modorganizer-build -s Appveyor_Build=True ${env:APPVEYOR_PROJECT_NAME} From e8dba0271a5307c5f8934807461e1f5b94937625 Mon Sep 17 00:00:00 2001 From: Jeremy Rimpo Date: Fri, 25 Sep 2020 00:34:22 -0500 Subject: [PATCH 1063/1544] [game_skyrimse] [skip ci] Use PR branch for umbrella repo (if it exists) --- src/games/skyrimse/appveyor.yml | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/src/games/skyrimse/appveyor.yml b/src/games/skyrimse/appveyor.yml index 2e2dc942..1b943e5e 100644 --- a/src/games/skyrimse/appveyor.yml +++ b/src/games/skyrimse/appveyor.yml @@ -13,8 +13,10 @@ build_script: New-Item -ItemType Directory -Path c:\projects\modorganizer-build cd c:\projects\modorganizer-umbrella + + ($env:APPVEYOR_PULL_REQUEST_HEAD_REPO_BRANCH -eq $null) ? ($branch = $env:APPVEYOR_REPO_BRANCH) : ($branch = $env:APPVEYOR_PULL_REQUEST_HEAD_REPO_BRANCH) - git checkout $(git show-ref --verify --quiet refs/remotes/origin/${env:APPVEYOR_REPO_BRANCH} || echo '-b') ${env:APPVEYOR_REPO_BRANCH} + git checkout $(git show-ref --verify --quiet refs/remotes/origin/${branch} || echo '-b') ${branch} C:\Python37-x64\python.exe unimake.py -d c:\projects\modorganizer-build -s Appveyor_Build=True ${env:APPVEYOR_PROJECT_NAME} From 6349035e12336114777b0bce0c9fea33d299a880 Mon Sep 17 00:00:00 2001 From: Jeremy Rimpo Date: Fri, 25 Sep 2020 00:34:26 -0500 Subject: [PATCH 1064/1544] [game_skyrim] [skip ci] Use PR branch for umbrella repo (if it exists) --- src/games/skyrim/appveyor.yml | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/src/games/skyrim/appveyor.yml b/src/games/skyrim/appveyor.yml index 22bd43ee..c5ed68a3 100644 --- a/src/games/skyrim/appveyor.yml +++ b/src/games/skyrim/appveyor.yml @@ -13,8 +13,10 @@ build_script: New-Item -ItemType Directory -Path c:\projects\modorganizer-build cd c:\projects\modorganizer-umbrella + + ($env:APPVEYOR_PULL_REQUEST_HEAD_REPO_BRANCH -eq $null) ? ($branch = $env:APPVEYOR_REPO_BRANCH) : ($branch = $env:APPVEYOR_PULL_REQUEST_HEAD_REPO_BRANCH) - git checkout $(git show-ref --verify --quiet refs/remotes/origin/${env:APPVEYOR_REPO_BRANCH} || echo '-b') ${env:APPVEYOR_REPO_BRANCH} + git checkout $(git show-ref --verify --quiet refs/remotes/origin/${branch} || echo '-b') ${branch} C:\Python37-x64\python.exe unimake.py -d c:\projects\modorganizer-build -s Appveyor_Build=True ${env:APPVEYOR_PROJECT_NAME} From c6b727acc59ee1d126d1f5cd7a49c3983735b64f Mon Sep 17 00:00:00 2001 From: Jeremy Rimpo Date: Fri, 25 Sep 2020 00:34:29 -0500 Subject: [PATCH 1065/1544] [game_ttw] [skip ci] Use PR branch for umbrella repo (if it exists) --- src/games/ttw/appveyor.yml | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/src/games/ttw/appveyor.yml b/src/games/ttw/appveyor.yml index 2b5ce8b3..e0300424 100644 --- a/src/games/ttw/appveyor.yml +++ b/src/games/ttw/appveyor.yml @@ -13,8 +13,10 @@ build_script: New-Item -ItemType Directory -Path c:\projects\modorganizer-build cd c:\projects\modorganizer-umbrella + + ($env:APPVEYOR_PULL_REQUEST_HEAD_REPO_BRANCH -eq $null) ? ($branch = $env:APPVEYOR_REPO_BRANCH) : ($branch = $env:APPVEYOR_PULL_REQUEST_HEAD_REPO_BRANCH) - git checkout $(git show-ref --verify --quiet refs/remotes/origin/${env:APPVEYOR_REPO_BRANCH} || echo '-b') ${env:APPVEYOR_REPO_BRANCH} + git checkout $(git show-ref --verify --quiet refs/remotes/origin/${branch} || echo '-b') ${branch} C:\Python37-x64\python.exe unimake.py -d c:\projects\modorganizer-build -s Appveyor_Build=True ${env:APPVEYOR_PROJECT_NAME} From 29c9d7a042a389e80d02e4c32d7190b187ab491d Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Mika=C3=ABl=20Capelle?= Date: Sun, 25 Oct 2020 16:54:29 +0100 Subject: [PATCH 1066/1544] Move IOrganizer::modsSortedByProfilePriority() to IModList::allModsByProfilePriority(). --- src/gamebryo/gamebryosavegameinfo.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/gamebryo/gamebryosavegameinfo.cpp b/src/gamebryo/gamebryosavegameinfo.cpp index 12f723fa..39334718 100644 --- a/src/gamebryo/gamebryosavegameinfo.cpp +++ b/src/gamebryo/gamebryosavegameinfo.cpp @@ -57,7 +57,7 @@ GamebryoSaveGameInfo::MissingAssets GamebryoSaveGameInfo::getMissingAssets(QStri QString dataDir(organizerCore->managedGame()->dataDirectory().absolutePath()); //Search normal mods. A note: This will also find mods in data. - for (QString const &mod : organizerCore->modsSortedByProfilePriority()) { + for (QString const &mod : organizerCore->modList()->allModsByProfilePriority()) { MOBase::IModInterface *modInfo = organizerCore->getMod(mod); QStringList esps = QDir(modInfo->absolutePath()).entryList(espFilter); for (QString const &esp : esps) { From 0317e249b2a2c20cb8208a6c6fbe70a0db59c24a Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Mika=C3=ABl=20Capelle?= Date: Sun, 25 Oct 2020 17:41:31 +0100 Subject: [PATCH 1067/1544] Fix for getMod(). --- src/gamebryo/gamebryogameplugins.cpp | 4 ++-- src/gamebryo/gamebryosavegameinfo.cpp | 2 +- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/src/gamebryo/gamebryogameplugins.cpp b/src/gamebryo/gamebryogameplugins.cpp index 301df04b..71683a60 100644 --- a/src/gamebryo/gamebryogameplugins.cpp +++ b/src/gamebryo/gamebryogameplugins.cpp @@ -181,8 +181,8 @@ QStringList GamebryoGamePlugins::readPluginList(MOBase::IPluginList *pluginList) // Always use filetime loadorder to get the actual load order std::sort(plugins.begin(), plugins.end(), [&](const QString &lhs, const QString &rhs) { - MOBase::IModInterface *lhm = organizer()->getMod(pluginList->origin(lhs)); - MOBase::IModInterface *rhm = organizer()->getMod(pluginList->origin(rhs)); + MOBase::IModInterface *lhm = organizer()->modList()->getMod(pluginList->origin(lhs)); + MOBase::IModInterface *rhm = organizer()->modList()->getMod(pluginList->origin(rhs)); QDir lhd = organizer()->managedGame()->dataDirectory(); QDir rhd = organizer()->managedGame()->dataDirectory(); if (lhm != nullptr) diff --git a/src/gamebryo/gamebryosavegameinfo.cpp b/src/gamebryo/gamebryosavegameinfo.cpp index 39334718..69c1789b 100644 --- a/src/gamebryo/gamebryosavegameinfo.cpp +++ b/src/gamebryo/gamebryosavegameinfo.cpp @@ -58,7 +58,7 @@ GamebryoSaveGameInfo::MissingAssets GamebryoSaveGameInfo::getMissingAssets(QStri //Search normal mods. A note: This will also find mods in data. for (QString const &mod : organizerCore->modList()->allModsByProfilePriority()) { - MOBase::IModInterface *modInfo = organizerCore->getMod(mod); + MOBase::IModInterface *modInfo = organizerCore->modList()->getMod(mod); QStringList esps = QDir(modInfo->absolutePath()).entryList(espFilter); for (QString const &esp : esps) { MissingAssets::iterator iter = missingAssets.find(esp); From 50ee33fc0182bf39b236e19929fa34d6e28086ed Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Mika=C3=ABl=20Capelle?= Date: Sun, 25 Oct 2020 17:41:54 +0100 Subject: [PATCH 1068/1544] [game_morrowind] Fix for getMod(). --- src/games/morrowind/src/morrowindgameplugins.cpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/games/morrowind/src/morrowindgameplugins.cpp b/src/games/morrowind/src/morrowindgameplugins.cpp index 3c96ba26..81ae28dc 100644 --- a/src/games/morrowind/src/morrowindgameplugins.cpp +++ b/src/games/morrowind/src/morrowindgameplugins.cpp @@ -141,8 +141,8 @@ QStringList MorrowindGamePlugins::readPluginList(MOBase::IPluginList *pluginList // Always use filetime loadorder to get the actual load order std::sort(plugins.begin(), plugins.end(), [&](const QString &lhs, const QString &rhs) { - MOBase::IModInterface *lhm = organizer()->getMod(pluginList->origin(lhs)); - MOBase::IModInterface *rhm = organizer()->getMod(pluginList->origin(rhs)); + MOBase::IModInterface *lhm = organizer()->modList()->getMod(pluginList->origin(lhs)); + MOBase::IModInterface *rhm = organizer()->modList()->getMod(pluginList->origin(rhs)); QDir lhd = organizer()->managedGame()->dataDirectory(); QDir rhd = organizer()->managedGame()->dataDirectory(); if (lhm != nullptr) From 42c6b14309b8fbf01b284cdd8dc8e19cbb5ed5f0 Mon Sep 17 00:00:00 2001 From: AL <26797547+Al12rs@users.noreply.github.com> Date: Tue, 27 Oct 2020 15:47:30 +0100 Subject: [PATCH 1069/1544] [game_skyrim] Add Nemesis_Engine to list of valid top level folders. --- src/games/skyrim/src/skyrimmoddatachecker.h | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/src/games/skyrim/src/skyrimmoddatachecker.h b/src/games/skyrim/src/skyrimmoddatachecker.h index f9264a09..d2b91d3c 100644 --- a/src/games/skyrim/src/skyrimmoddatachecker.h +++ b/src/games/skyrim/src/skyrimmoddatachecker.h @@ -14,7 +14,8 @@ protected: "fonts", "interface", "menus", "meshes", "music", "scripts", "shaders", "sound", "strings", "textures", "trees", "video", "facegen", "materials", "skse", "distantlod", "asi", "Tools", "MCM", "distantland", "mits", - "dllplugins", "SkyProc Patchers", "CalienteTools", "NetScriptFramework", "shadersfx" + "dllplugins", "SkyProc Patchers", "CalienteTools", "NetScriptFramework", + "shadersfx", "Nemesis_Engine" }; return result; } From 301c9d7dc32dd079615a237f6be28259c62e50c4 Mon Sep 17 00:00:00 2001 From: AL <26797547+Al12rs@users.noreply.github.com> Date: Tue, 27 Oct 2020 15:47:42 +0100 Subject: [PATCH 1070/1544] [game_skyrimse] Add Nemesis_Engine to list of valid top level folders. --- src/games/skyrimse/src/skyrimsemoddatachecker.h | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/src/games/skyrimse/src/skyrimsemoddatachecker.h b/src/games/skyrimse/src/skyrimsemoddatachecker.h index 7d4ab8c3..ec530488 100644 --- a/src/games/skyrimse/src/skyrimsemoddatachecker.h +++ b/src/games/skyrimse/src/skyrimsemoddatachecker.h @@ -14,7 +14,8 @@ protected: "fonts", "interface", "menus", "meshes", "music", "scripts", "shaders", "sound", "strings", "textures", "trees", "video", "facegen", "materials", "skse", "distantlod", "asi", "Tools", "MCM", "distantland", "mits", - "dllplugins", "CalienteTools", "NetScriptFramework", "shadersfx" + "dllplugins", "CalienteTools", "NetScriptFramework", "shadersfx", + "Nemesis_Engine" }; return result; } From 690b5389a208bed7f453dafe83ac1671582b4367 Mon Sep 17 00:00:00 2001 From: Al <26797547+Al12rs@users.noreply.github.com> Date: Tue, 27 Oct 2020 08:10:17 -0700 Subject: [PATCH 1071/1544] [game_skyrimvr] Add Nemesis_Engine to list of valid top level folders. (#18) --- src/games/skyrimvr/src/skyrimvrmoddatachecker.h | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/src/games/skyrimvr/src/skyrimvrmoddatachecker.h b/src/games/skyrimvr/src/skyrimvrmoddatachecker.h index c0ce9fa8..8cbdec5f 100644 --- a/src/games/skyrimvr/src/skyrimvrmoddatachecker.h +++ b/src/games/skyrimvr/src/skyrimvrmoddatachecker.h @@ -14,7 +14,8 @@ protected: "fonts", "interface", "menus", "meshes", "music", "scripts", "shaders", "sound", "strings", "textures", "trees", "video", "facegen", "materials", "skse", "distantlod", "asi", "Tools", "MCM", "distantland", "mits", - "dllplugins", "CalienteTools", "NetScriptFramework", "shadersfx" + "dllplugins", "CalienteTools", "NetScriptFramework", "shadersfx", + "Nemesis_Engine" }; return result; } From 38ae0b8498eba63d3a6606ee4291a5b014048919 Mon Sep 17 00:00:00 2001 From: isanae <14251494+isanae@users.noreply.github.com> Date: Wed, 4 Nov 2020 22:54:35 -0500 Subject: [PATCH 1072/1544] [game_ttw] moved path detection to registered() --- src/games/ttw/src/gamefalloutttw.cpp | 9 +++++++-- src/games/ttw/src/gamefalloutttw.h | 3 ++- 2 files changed, 9 insertions(+), 3 deletions(-) diff --git a/src/games/ttw/src/gamefalloutttw.cpp b/src/games/ttw/src/gamefalloutttw.cpp index f3cc1d9c..c0149d7c 100644 --- a/src/games/ttw/src/gamefalloutttw.cpp +++ b/src/games/ttw/src/gamefalloutttw.cpp @@ -30,13 +30,18 @@ GameFalloutTTW::GameFalloutTTW() { } +void GameFalloutTTW::registered() +{ + GameGamebryo::registered(); + m_MyGamesPath = determineMyGamesPath("FalloutNV"); +} + bool GameFalloutTTW::init(IOrganizer *moInfo) { if (!GameGamebryo::init(moInfo)) { return false; } - m_GamePath = identifyGamePath(); - m_MyGamesPath = determineMyGamesPath("FalloutNV"); + registerFeature(new FalloutTTWScriptExtender(this)); registerFeature(new FalloutTTWDataArchives(myGamesPath())); registerFeature(new FalloutTTWBSAInvalidation(feature(), this)); diff --git a/src/games/ttw/src/gamefalloutttw.h b/src/games/ttw/src/gamefalloutttw.h index 2f1bda41..3f93df2b 100644 --- a/src/games/ttw/src/gamefalloutttw.h +++ b/src/games/ttw/src/gamefalloutttw.h @@ -17,7 +17,8 @@ public: GameFalloutTTW(); - virtual bool init(MOBase::IOrganizer *moInfo) override; + void registered() override; + bool init(MOBase::IOrganizer *moInfo) override; public: // IPluginGame interface From 98e8d5ba747484361510e4ecf8102a62b231b50a Mon Sep 17 00:00:00 2001 From: isanae <14251494+isanae@users.noreply.github.com> Date: Wed, 4 Nov 2020 22:55:24 -0500 Subject: [PATCH 1073/1544] [game_skyrimvr] removed redundant path detection, already done by gamebryo --- src/games/skyrimvr/src/gameskyrimvr.cpp | 3 --- 1 file changed, 3 deletions(-) diff --git a/src/games/skyrimvr/src/gameskyrimvr.cpp b/src/games/skyrimvr/src/gameskyrimvr.cpp index 1a21cd5c..b5266882 100644 --- a/src/games/skyrimvr/src/gameskyrimvr.cpp +++ b/src/games/skyrimvr/src/gameskyrimvr.cpp @@ -67,9 +67,6 @@ bool GameSkyrimVR::init(IOrganizer *moInfo) return false; } - m_GamePath = GameSkyrimVR::identifyGamePath(); - m_MyGamesPath = determineMyGamesPath(gameName()); - registerFeature(new SkyrimVRScriptExtender(this)); registerFeature(new SkyrimVRDataArchives(myGamesPath())); registerFeature(new GamebryoLocalSavegames(myGamesPath(), "SkyrimVR.ini")); From cda73aea1bb2c2c1eb9b509639064d17af9ca5fe Mon Sep 17 00:00:00 2001 From: isanae <14251494+isanae@users.noreply.github.com> Date: Wed, 4 Nov 2020 22:56:09 -0500 Subject: [PATCH 1074/1544] [game_skyrimse] removed redundant path detection, already done by gamebryo --- src/games/skyrimse/src/gameskyrimse.cpp | 3 --- 1 file changed, 3 deletions(-) diff --git a/src/games/skyrimse/src/gameskyrimse.cpp b/src/games/skyrimse/src/gameskyrimse.cpp index 7e8fe314..369cbe2e 100644 --- a/src/games/skyrimse/src/gameskyrimse.cpp +++ b/src/games/skyrimse/src/gameskyrimse.cpp @@ -68,9 +68,6 @@ bool GameSkyrimSE::init(IOrganizer *moInfo) return false; } - m_GamePath = GameSkyrimSE::identifyGamePath(); - m_MyGamesPath = determineMyGamesPath(gameName()); - registerFeature(new SkyrimSEScriptExtender(this)); registerFeature(new SkyrimSEDataArchives(myGamesPath())); registerFeature(new GamebryoLocalSavegames(myGamesPath(), "Skyrimcustom.ini")); From 2ddeb23e8825f8fc48a85a60637b464f92c529df Mon Sep 17 00:00:00 2001 From: isanae <14251494+isanae@users.noreply.github.com> Date: Wed, 4 Nov 2020 22:56:58 -0500 Subject: [PATCH 1075/1544] moved path detection to registered() so it can happen without init() being called --- src/gamebryo/gamegamebryo.cpp | 8 ++++++-- src/gamebryo/gamegamebryo.h | 3 ++- 2 files changed, 8 insertions(+), 3 deletions(-) diff --git a/src/gamebryo/gamegamebryo.cpp b/src/gamebryo/gamegamebryo.cpp index 57cf574a..371290f6 100644 --- a/src/gamebryo/gamegamebryo.cpp +++ b/src/gamebryo/gamegamebryo.cpp @@ -32,10 +32,14 @@ GameGamebryo::GameGamebryo() { } -bool GameGamebryo::init(MOBase::IOrganizer *moInfo) +void GameGamebryo::registered() { m_GamePath = identifyGamePath(); m_MyGamesPath = determineMyGamesPath(gameShortName()); +} + +bool GameGamebryo::init(MOBase::IOrganizer *moInfo) +{ m_Organizer = moInfo; return true; } @@ -124,7 +128,7 @@ bool GameGamebryo::looksValid(QDir const &path) const QString GameGamebryo::gameVersion() const { // We try the file version, but if it looks invalid (starts with the fallback - // version), we look the product version instead. If the product version is + // version), we look the product version instead. If the product version is // not empty, we use it. QString binaryAbsPath = gameDirectory().absoluteFilePath(binaryName()); QString version = MOBase::getFileVersion(binaryAbsPath); diff --git a/src/gamebryo/gamegamebryo.h b/src/gamebryo/gamegamebryo.h index b58ea931..9872f662 100644 --- a/src/gamebryo/gamegamebryo.h +++ b/src/gamebryo/gamegamebryo.h @@ -42,7 +42,8 @@ public: GameGamebryo(); - virtual bool init(MOBase::IOrganizer *moInfo) override; + void registered() override; + bool init(MOBase::IOrganizer *moInfo) override; public: // IPluginGame interface From 1513e96e907701caa0602da205e9e42108ad1909 Mon Sep 17 00:00:00 2001 From: isanae <14251494+isanae@users.noreply.github.com> Date: Wed, 4 Nov 2020 22:57:35 -0500 Subject: [PATCH 1076/1544] [game_fallout4vr] removed redundant path detection, already done by gamebryo --- src/games/fallout4vr/src/gamefallout4vr.cpp | 2 -- 1 file changed, 2 deletions(-) diff --git a/src/games/fallout4vr/src/gamefallout4vr.cpp b/src/games/fallout4vr/src/gamefallout4vr.cpp index eec13e5b..c77c2d05 100644 --- a/src/games/fallout4vr/src/gamefallout4vr.cpp +++ b/src/games/fallout4vr/src/gamefallout4vr.cpp @@ -36,8 +36,6 @@ bool GameFallout4VR::init(IOrganizer *moInfo) return false; } - m_GamePath = identifyGamePath(); - registerFeature(new Fallout4VRDataArchives(myGamesPath())); registerFeature(new GamebryoLocalSavegames(myGamesPath(), "fallout4custom.ini")); registerFeature(new Fallout4VRModDataChecker(this)); From 671afb3ac1e158a38e2064406405156a69465b71 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Mika=C3=ABl=20Capelle?= Date: Fri, 6 Nov 2020 18:56:00 +0100 Subject: [PATCH 1077/1544] [game_ttw] Replace IPlugin::registered() by IPluginGame::detectGame(). --- src/games/ttw/src/gamefalloutttw.cpp | 4 ++-- src/games/ttw/src/gamefalloutttw.h | 2 +- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/src/games/ttw/src/gamefalloutttw.cpp b/src/games/ttw/src/gamefalloutttw.cpp index c0149d7c..85c710f8 100644 --- a/src/games/ttw/src/gamefalloutttw.cpp +++ b/src/games/ttw/src/gamefalloutttw.cpp @@ -30,9 +30,9 @@ GameFalloutTTW::GameFalloutTTW() { } -void GameFalloutTTW::registered() +void GameFalloutTTW::detectGame() { - GameGamebryo::registered(); + GameGamebryo::detectGame(); m_MyGamesPath = determineMyGamesPath("FalloutNV"); } diff --git a/src/games/ttw/src/gamefalloutttw.h b/src/games/ttw/src/gamefalloutttw.h index 3f93df2b..31e20373 100644 --- a/src/games/ttw/src/gamefalloutttw.h +++ b/src/games/ttw/src/gamefalloutttw.h @@ -17,7 +17,7 @@ public: GameFalloutTTW(); - void registered() override; + void detectGame() override; bool init(MOBase::IOrganizer *moInfo) override; public: // IPluginGame interface From 03c6adef82e75f9d0969cf651ecc37a6ee1c0e14 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Mika=C3=ABl=20Capelle?= Date: Fri, 6 Nov 2020 18:56:00 +0100 Subject: [PATCH 1078/1544] Replace IPlugin::registered() by IPluginGame::detectGame(). --- src/gamebryo/gamegamebryo.cpp | 2 +- src/gamebryo/gamegamebryo.h | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/src/gamebryo/gamegamebryo.cpp b/src/gamebryo/gamegamebryo.cpp index 371290f6..63d4df57 100644 --- a/src/gamebryo/gamegamebryo.cpp +++ b/src/gamebryo/gamegamebryo.cpp @@ -32,7 +32,7 @@ GameGamebryo::GameGamebryo() { } -void GameGamebryo::registered() +void GameGamebryo::detectGame() { m_GamePath = identifyGamePath(); m_MyGamesPath = determineMyGamesPath(gameShortName()); diff --git a/src/gamebryo/gamegamebryo.h b/src/gamebryo/gamegamebryo.h index 9872f662..aecd51d2 100644 --- a/src/gamebryo/gamegamebryo.h +++ b/src/gamebryo/gamegamebryo.h @@ -42,7 +42,7 @@ public: GameGamebryo(); - void registered() override; + void detectGame() override; bool init(MOBase::IOrganizer *moInfo) override; public: // IPluginGame interface From 2b5d8efa106de89f2590cce13d0f5b7648f7e353 Mon Sep 17 00:00:00 2001 From: isanae <14251494+isanae@users.noreply.github.com> Date: Mon, 9 Nov 2020 17:18:31 -0500 Subject: [PATCH 1079/1544] some games use the short name, some use the long name, so try both --- src/gamebryo/gamegamebryo.cpp | 9 +++++++++ 1 file changed, 9 insertions(+) diff --git a/src/gamebryo/gamegamebryo.cpp b/src/gamebryo/gamegamebryo.cpp index 63d4df57..24cb38ef 100644 --- a/src/gamebryo/gamegamebryo.cpp +++ b/src/gamebryo/gamegamebryo.cpp @@ -35,7 +35,11 @@ GameGamebryo::GameGamebryo() void GameGamebryo::detectGame() { m_GamePath = identifyGamePath(); + m_MyGamesPath = determineMyGamesPath(gameShortName()); + if (m_MyGamesPath.isEmpty()) { + m_MyGamesPath = determineMyGamesPath(gameName()); + } } bool GameGamebryo::init(MOBase::IOrganizer *moInfo) @@ -342,5 +346,10 @@ QString GameGamebryo::determineMyGamesPath(const QString &gameName) result = getSpecialPath("Personal"); } + if (result.isEmpty() + || !QFileInfo(result + "/My Games/" + gameName).exists()) { + return {}; + } + return result + "/My Games/" + gameName; } From 36ef2a0baaa89b1c3f50feb5ae6d89b9a0b543c5 Mon Sep 17 00:00:00 2001 From: isanae <14251494+isanae@users.noreply.github.com> Date: Tue, 10 Nov 2020 11:52:02 -0500 Subject: [PATCH 1080/1544] refactored determineMyGamesPath() --- src/gamebryo/gamegamebryo.cpp | 51 ++++++++++++++++++++++++----------- 1 file changed, 35 insertions(+), 16 deletions(-) diff --git a/src/gamebryo/gamegamebryo.cpp b/src/gamebryo/gamegamebryo.cpp index 24cb38ef..bf4571bd 100644 --- a/src/gamebryo/gamegamebryo.cpp +++ b/src/gamebryo/gamegamebryo.cpp @@ -23,8 +23,8 @@ #include #include -#include #include +#include #include @@ -36,9 +36,16 @@ void GameGamebryo::detectGame() { m_GamePath = identifyGamePath(); - m_MyGamesPath = determineMyGamesPath(gameShortName()); + // some games have the same short and long names, such as "Skyrim"; others + // have different values, such as "SkyrimSE" and "Skyrim Special Edition" + // + // games with different short/long names typically use the long name in + // "My Games", so that's tried first; if it fails, the short name is tried + m_MyGamesPath = determineMyGamesPath(gameName()); if (m_MyGamesPath.isEmpty()) { - m_MyGamesPath = determineMyGamesPath(gameName()); + if (gameName() != gameShortName()) { + m_MyGamesPath = determineMyGamesPath(gameShortName()); + } } } @@ -332,24 +339,36 @@ QString GameGamebryo::getSpecialPath(const QString &name) QString GameGamebryo::determineMyGamesPath(const QString &gameName) { + const QString pattern = "%1/My Games/" + gameName; + + auto tryDir = [&](const QString& dir) -> std::optional { + if (dir.isEmpty()) { + return {}; + } + + const auto path = pattern.arg(dir); + if (!QFileInfo(path).exists()) { + return {}; + } + + return path; + }; + + // a) this is the way it should work. get the configured My Documents directory - QString result = getKnownFolderPath(FOLDERID_Documents, false); + if (auto d=tryDir(getKnownFolderPath(FOLDERID_Documents, false))) { + return *d; + } // b) if there is no directory there, look in the default directory - if (result.isEmpty() - || !QFileInfo(result + "/My Games/" + gameName).exists()) { - result = getKnownFolderPath(FOLDERID_Documents, true); + if (auto d=tryDir(getKnownFolderPath(FOLDERID_Documents, true))) { + return *d; } + // c) finally, look in the registry. This is discouraged - if (result.isEmpty() - || !QFileInfo(result + "/My Games/" + gameName).exists()) { - result = getSpecialPath("Personal"); + if (auto d=tryDir(getSpecialPath("Personal"))) { + return *d; } - if (result.isEmpty() - || !QFileInfo(result + "/My Games/" + gameName).exists()) { - return {}; - } - - return result + "/My Games/" + gameName; + return {}; } From e50a91b3824b7c3213a1906b76ff33a4b2f2fe75 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Mika=C3=ABl=20Capelle?= Date: Wed, 11 Nov 2020 15:12:20 +0100 Subject: [PATCH 1081/1544] [game_fallout3] Update following removal of IPlugin::isActive(). --- src/games/fallout3/src/gamefallout3.cpp | 9 +++++---- src/games/fallout3/src/gamefallout3.h | 12 ++++++------ 2 files changed, 11 insertions(+), 10 deletions(-) diff --git a/src/games/fallout3/src/gamefallout3.cpp b/src/games/fallout3/src/gamefallout3.cpp index 33125d70..84a7c1ce 100644 --- a/src/games/fallout3/src/gamefallout3.cpp +++ b/src/games/fallout3/src/gamefallout3.cpp @@ -75,6 +75,11 @@ QString GameFallout3::name() const return "Fallout 3 Support Plugin"; } +QString GameFallout3::localizedName() const +{ + return tr("Fallout 3 Support Plugin"); +} + QString GameFallout3::author() const { return "Tannin"; @@ -90,10 +95,6 @@ MOBase::VersionInfo GameFallout3::version() const return VersionInfo(1, 4, 1, VersionInfo::RELEASE_FINAL); } -bool GameFallout3::isActive() const -{ - return qApp->property("managed_game").value() == this; -} QList GameFallout3::settings() const { diff --git a/src/games/fallout3/src/gamefallout3.h b/src/games/fallout3/src/gamefallout3.h index 787bc301..43b38bbf 100644 --- a/src/games/fallout3/src/gamefallout3.h +++ b/src/games/fallout3/src/gamefallout3.h @@ -39,12 +39,12 @@ public: // IPluginGame interface public: // IPlugin interface - virtual QString name() const; - virtual QString author() const; - virtual QString description() const; - virtual MOBase::VersionInfo version() const; - virtual bool isActive() const; - virtual QList settings() const; + 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 settings() const override; protected: From 91dab49182a8e237fc2e5e5db73c6beb0db6e052 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Mika=C3=ABl=20Capelle?= Date: Wed, 11 Nov 2020 15:12:21 +0100 Subject: [PATCH 1082/1544] [game_fallout4] Update following removal of IPlugin::isActive(). --- src/games/fallout4/src/gamefallout4.cpp | 11 ++++++----- src/games/fallout4/src/gamefallout4.h | 2 +- 2 files changed, 7 insertions(+), 6 deletions(-) diff --git a/src/games/fallout4/src/gamefallout4.cpp b/src/games/fallout4/src/gamefallout4.cpp index f5a2d220..6bb84622 100644 --- a/src/games/fallout4/src/gamefallout4.cpp +++ b/src/games/fallout4/src/gamefallout4.cpp @@ -75,6 +75,12 @@ QString GameFallout4::name() const return "Fallout 4 Support Plugin"; } +QString GameFallout4::localizedName() const +{ + return tr("Fallout 4 Support Plugin"); +} + + QString GameFallout4::author() const { return "Tannin"; @@ -91,11 +97,6 @@ MOBase::VersionInfo GameFallout4::version() const return VersionInfo(1, 5, 0, VersionInfo::RELEASE_FINAL); } -bool GameFallout4::isActive() const -{ - return qApp->property("managed_game").value() == this; -} - QList GameFallout4::settings() const { return QList(); diff --git a/src/games/fallout4/src/gamefallout4.h b/src/games/fallout4/src/gamefallout4.h index e901eeaa..51c4af3f 100644 --- a/src/games/fallout4/src/gamefallout4.h +++ b/src/games/fallout4/src/gamefallout4.h @@ -42,10 +42,10 @@ public: // IPluginGame interface 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 bool isActive() const override; virtual QList settings() const override; }; From ef9f294cd2bc2328262490d6a38cb80983de125d Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Mika=C3=ABl=20Capelle?= Date: Wed, 11 Nov 2020 15:12:21 +0100 Subject: [PATCH 1083/1544] [game_fallout4vr] Update following removal of IPlugin::isActive(). --- src/games/fallout4vr/src/gamefallout4vr.cpp | 11 ++++++----- src/games/fallout4vr/src/gamefallout4vr.h | 2 +- 2 files changed, 7 insertions(+), 6 deletions(-) diff --git a/src/games/fallout4vr/src/gamefallout4vr.cpp b/src/games/fallout4vr/src/gamefallout4vr.cpp index c77c2d05..1890654a 100644 --- a/src/games/fallout4vr/src/gamefallout4vr.cpp +++ b/src/games/fallout4vr/src/gamefallout4vr.cpp @@ -71,6 +71,12 @@ QString GameFallout4VR::name() const return "Fallout 4 VR Support Plugin"; } +QString GameFallout4VR::localizedName() const +{ + return tr("Fallout 4 VR Support Plugin"); +} + + QString GameFallout4VR::author() const { return "MO2 Contibutors"; @@ -87,11 +93,6 @@ MOBase::VersionInfo GameFallout4VR::version() const return VersionInfo(1, 4, 1, VersionInfo::RELEASE_FINAL); } -bool GameFallout4VR::isActive() const -{ - return qApp->property("managed_game").value() == this; -} - QList GameFallout4VR::settings() const { return QList(); diff --git a/src/games/fallout4vr/src/gamefallout4vr.h b/src/games/fallout4vr/src/gamefallout4vr.h index 87ae4e3a..3a956862 100644 --- a/src/games/fallout4vr/src/gamefallout4vr.h +++ b/src/games/fallout4vr/src/gamefallout4vr.h @@ -45,10 +45,10 @@ public: // IPluginGame interface 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 bool isActive() const override; virtual QList settings() const override; protected: From 0fb3afeaabd52266528c17dfe60a3357389f7631 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Mika=C3=ABl=20Capelle?= Date: Wed, 11 Nov 2020 15:12:21 +0100 Subject: [PATCH 1084/1544] [game_falloutnv] Update following removal of IPlugin::isActive(). --- src/games/falloutnv/src/gamefalloutnv.cpp | 11 ++++++----- src/games/falloutnv/src/gamefalloutnv.h | 12 ++++++------ 2 files changed, 12 insertions(+), 11 deletions(-) diff --git a/src/games/falloutnv/src/gamefalloutnv.cpp b/src/games/falloutnv/src/gamefalloutnv.cpp index da5026ef..75f491d1 100644 --- a/src/games/falloutnv/src/gamefalloutnv.cpp +++ b/src/games/falloutnv/src/gamefalloutnv.cpp @@ -75,6 +75,12 @@ QString GameFalloutNV::name() const return "Fallout NV Support Plugin"; } +QString GameFalloutNV::localizedName() const +{ + return tr("Fallout NV Support Plugin"); +} + + QString GameFalloutNV::author() const { return "Tannin"; @@ -90,11 +96,6 @@ MOBase::VersionInfo GameFalloutNV::version() const return VersionInfo(1, 4, 1, VersionInfo::RELEASE_FINAL); } -bool GameFalloutNV::isActive() const -{ - return qApp->property("managed_game").value() == this; -} - QList GameFalloutNV::settings() const { return QList(); diff --git a/src/games/falloutnv/src/gamefalloutnv.h b/src/games/falloutnv/src/gamefalloutnv.h index 5efee187..a32d9d4a 100644 --- a/src/games/falloutnv/src/gamefalloutnv.h +++ b/src/games/falloutnv/src/gamefalloutnv.h @@ -39,12 +39,12 @@ public: // IPluginGame interface public: // IPlugin interface - virtual QString name() const; - virtual QString author() const; - virtual QString description() const; - virtual MOBase::VersionInfo version() const; - virtual bool isActive() const; - virtual QList settings() const; + 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 settings() const override; }; From 991b37d00fcb2dc2e673015a1d3327acfc46e62e Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Mika=C3=ABl=20Capelle?= Date: Wed, 11 Nov 2020 15:12:22 +0100 Subject: [PATCH 1085/1544] [game_morrowind] Update following removal of IPlugin::isActive(). --- src/games/morrowind/src/gamemorrowind.cpp | 11 ++++++----- src/games/morrowind/src/gamemorrowind.h | 12 ++++++------ 2 files changed, 12 insertions(+), 11 deletions(-) diff --git a/src/games/morrowind/src/gamemorrowind.cpp b/src/games/morrowind/src/gamemorrowind.cpp index 841c1968..26083c5e 100644 --- a/src/games/morrowind/src/gamemorrowind.cpp +++ b/src/games/morrowind/src/gamemorrowind.cpp @@ -98,6 +98,12 @@ QString GameMorrowind::name() const return "Morrowind Support Plugin"; } +QString GameMorrowind::localizedName() const +{ + return tr("Morrowind Support Plugin"); +} + + QString GameMorrowind::author() const { return "Schilduin"; @@ -114,11 +120,6 @@ MOBase::VersionInfo GameMorrowind::version() const return VersionInfo(1, 4, 0, VersionInfo::RELEASE_FINAL); } -bool GameMorrowind::isActive() const -{ - return qApp->property("managed_game").value() == this; -} - QList GameMorrowind::settings() const { return QList(); diff --git a/src/games/morrowind/src/gamemorrowind.h b/src/games/morrowind/src/gamemorrowind.h index 1ce652ae..17b21c7e 100644 --- a/src/games/morrowind/src/gamemorrowind.h +++ b/src/games/morrowind/src/gamemorrowind.h @@ -48,12 +48,12 @@ public: // IPluginGame interface public: // IPlugin interface - virtual QString name() const; - virtual QString author() const; - virtual QString description() const; - virtual MOBase::VersionInfo version() const; - virtual bool isActive() const; - virtual QList settings() const; + 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 settings() const override; private: From 98dce5709ee21967dcc2ebc91c42a7720600374f Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Mika=C3=ABl=20Capelle?= Date: Wed, 11 Nov 2020 15:12:22 +0100 Subject: [PATCH 1086/1544] [game_oblivion] Update following removal of IPlugin::isActive(). --- src/games/oblivion/src/gameoblivion.cpp | 10 +++++----- src/games/oblivion/src/gameoblivion.h | 12 ++++++------ 2 files changed, 11 insertions(+), 11 deletions(-) diff --git a/src/games/oblivion/src/gameoblivion.cpp b/src/games/oblivion/src/gameoblivion.cpp index 72663ca5..d76d98c8 100644 --- a/src/games/oblivion/src/gameoblivion.cpp +++ b/src/games/oblivion/src/gameoblivion.cpp @@ -74,6 +74,11 @@ QString GameOblivion::name() const return "Oblivion Support Plugin"; } +QString GameOblivion::localizedName() const +{ + return tr("Oblivion Support Plugin"); +} + QString GameOblivion::author() const { return "Tannin"; @@ -89,11 +94,6 @@ MOBase::VersionInfo GameOblivion::version() const return VersionInfo(1, 4, 1, VersionInfo::RELEASE_FINAL); } -bool GameOblivion::isActive() const -{ - return qApp->property("managed_game").value() == this; -} - QList GameOblivion::settings() const { return QList(); diff --git a/src/games/oblivion/src/gameoblivion.h b/src/games/oblivion/src/gameoblivion.h index e2a88a21..6efd29e3 100644 --- a/src/games/oblivion/src/gameoblivion.h +++ b/src/games/oblivion/src/gameoblivion.h @@ -36,12 +36,12 @@ public: // IPluginGame interface public: // IPlugin interface - virtual QString name() const; - virtual QString author() const; - virtual QString description() const; - virtual MOBase::VersionInfo version() const; - virtual bool isActive() const; - virtual QList settings() const; + 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 settings() const override; }; From 38c34bf11096cd29878d88386779ebc55f7256cd Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Mika=C3=ABl=20Capelle?= Date: Wed, 11 Nov 2020 15:12:22 +0100 Subject: [PATCH 1087/1544] [game_skyrim] Update following removal of IPlugin::isActive(). --- src/games/skyrim/src/gameskyrim.cpp | 10 +++++----- src/games/skyrim/src/gameskyrim.h | 12 ++++++------ 2 files changed, 11 insertions(+), 11 deletions(-) diff --git a/src/games/skyrim/src/gameskyrim.cpp b/src/games/skyrim/src/gameskyrim.cpp index 3be28b6b..d60175d1 100644 --- a/src/games/skyrim/src/gameskyrim.cpp +++ b/src/games/skyrim/src/gameskyrim.cpp @@ -81,6 +81,11 @@ QString GameSkyrim::name() const return "Skyrim Support Plugin"; } +QString GameSkyrim::localizedName() const +{ + return tr("Skyrim Support Plugin"); +} + QString GameSkyrim::author() const { return "Tannin"; @@ -96,11 +101,6 @@ MOBase::VersionInfo GameSkyrim::version() const return VersionInfo(1, 5, 0, VersionInfo::RELEASE_FINAL); } -bool GameSkyrim::isActive() const -{ - return qApp->property("managed_game").value() == this; -} - QList GameSkyrim::settings() const { QList results; diff --git a/src/games/skyrim/src/gameskyrim.h b/src/games/skyrim/src/gameskyrim.h index d89b29a8..e2ff3a46 100644 --- a/src/games/skyrim/src/gameskyrim.h +++ b/src/games/skyrim/src/gameskyrim.h @@ -41,12 +41,12 @@ public: // IPluginGame interface public: // IPlugin interface - virtual QString name() const; - virtual QString author() const; - virtual QString description() const; - virtual MOBase::VersionInfo version() const; - virtual bool isActive() const; - virtual QList settings() const; + 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 settings() const override; }; #endif // GAMESKYRIM_H From 4170c66ad29c3a454150db13ffa1d8f64a151e10 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Mika=C3=ABl=20Capelle?= Date: Wed, 11 Nov 2020 15:12:22 +0100 Subject: [PATCH 1088/1544] [game_skyrimse] Update following removal of IPlugin::isActive(). --- src/games/skyrimse/src/gameskyrimse.cpp | 10 +++++----- src/games/skyrimse/src/gameskyrimse.h | 2 +- 2 files changed, 6 insertions(+), 6 deletions(-) diff --git a/src/games/skyrimse/src/gameskyrimse.cpp b/src/games/skyrimse/src/gameskyrimse.cpp index 369cbe2e..08880fbf 100644 --- a/src/games/skyrimse/src/gameskyrimse.cpp +++ b/src/games/skyrimse/src/gameskyrimse.cpp @@ -113,6 +113,11 @@ QString GameSkyrimSE::name() const return "Skyrim Special Edition Support Plugin"; } +QString GameSkyrimSE::localizedName() const +{ + return tr("Skyrim Special Edition Support Plugin"); +} + QString GameSkyrimSE::author() const { return "Archost & ZachHaber"; @@ -128,11 +133,6 @@ MOBase::VersionInfo GameSkyrimSE::version() const return VersionInfo(1, 5, 0, VersionInfo::RELEASE_FINAL); } -bool GameSkyrimSE::isActive() const -{ - return qApp->property("managed_game").value() == this; -} - QList GameSkyrimSE::settings() const { return QList(); diff --git a/src/games/skyrimse/src/gameskyrimse.h b/src/games/skyrimse/src/gameskyrimse.h index 1f5d6618..2be0e1b9 100644 --- a/src/games/skyrimse/src/gameskyrimse.h +++ b/src/games/skyrimse/src/gameskyrimse.h @@ -48,10 +48,10 @@ public: // IPluginGame interface 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 bool isActive() const override; virtual QList settings() const override; virtual MappingType mappings() const override; From 86659bbdee9dc1b2d4a6af97def4a0723471e612 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Mika=C3=ABl=20Capelle?= Date: Wed, 11 Nov 2020 15:12:23 +0100 Subject: [PATCH 1089/1544] [game_skyrimvr] Update following removal of IPlugin::isActive(). --- src/games/skyrimvr/src/gameskyrimvr.cpp | 10 +++++----- src/games/skyrimvr/src/gameskyrimvr.h | 2 +- 2 files changed, 6 insertions(+), 6 deletions(-) diff --git a/src/games/skyrimvr/src/gameskyrimvr.cpp b/src/games/skyrimvr/src/gameskyrimvr.cpp index b5266882..e8bc38d6 100644 --- a/src/games/skyrimvr/src/gameskyrimvr.cpp +++ b/src/games/skyrimvr/src/gameskyrimvr.cpp @@ -111,6 +111,11 @@ QString GameSkyrimVR::name() const return "Skyrim VR Support Plugin"; } +QString GameSkyrimVR::localizedName() const +{ + return tr("Skyrim VR Support Plugin"); +} + QString GameSkyrimVR::author() const { return "Brixified & MO2 Team"; @@ -126,11 +131,6 @@ MOBase::VersionInfo GameSkyrimVR::version() const return VersionInfo(1, 4, 1, VersionInfo::RELEASE_FINAL); } -bool GameSkyrimVR::isActive() const -{ - return qApp->property("managed_game").value() == this; -} - QList GameSkyrimVR::settings() const { return QList(); diff --git a/src/games/skyrimvr/src/gameskyrimvr.h b/src/games/skyrimvr/src/gameskyrimvr.h index 0987c1c5..eee89d3e 100644 --- a/src/games/skyrimvr/src/gameskyrimvr.h +++ b/src/games/skyrimvr/src/gameskyrimvr.h @@ -46,10 +46,10 @@ public: // IPluginGame interface 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 bool isActive() const override; virtual QList settings() const override; public: // IPluginFileMapper From 33462f5c70582f3dafba6e24d585c6a65894b0ae Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Mika=C3=ABl=20Capelle?= Date: Wed, 11 Nov 2020 15:12:23 +0100 Subject: [PATCH 1090/1544] [game_ttw] Update following removal of IPlugin::isActive(). --- src/games/ttw/src/gamefalloutttw.cpp | 10 +++++----- src/games/ttw/src/gamefalloutttw.h | 2 +- 2 files changed, 6 insertions(+), 6 deletions(-) diff --git a/src/games/ttw/src/gamefalloutttw.cpp b/src/games/ttw/src/gamefalloutttw.cpp index 85c710f8..6eafa076 100644 --- a/src/games/ttw/src/gamefalloutttw.cpp +++ b/src/games/ttw/src/gamefalloutttw.cpp @@ -82,6 +82,11 @@ 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"; @@ -97,11 +102,6 @@ MOBase::VersionInfo GameFalloutTTW::version() const return VersionInfo(1, 4, 1, VersionInfo::RELEASE_FINAL); } -bool GameFalloutTTW::isActive() const -{ - return qApp->property("managed_game").value() == this; -} - QList GameFalloutTTW::settings() const { return QList(); diff --git a/src/games/ttw/src/gamefalloutttw.h b/src/games/ttw/src/gamefalloutttw.h index 31e20373..3305ddac 100644 --- a/src/games/ttw/src/gamefalloutttw.h +++ b/src/games/ttw/src/gamefalloutttw.h @@ -45,10 +45,10 @@ public: // IPluginGame interface 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 bool isActive() const override; virtual QList settings() const override; public: // IPluginFileMapper interface From b6f35b1ad4960801a82e8b5eee729a51117c2269 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Mika=C3=ABl=20Capelle?= Date: Wed, 18 Nov 2020 19:24:38 +0100 Subject: [PATCH 1091/1544] Update for IPluginGame::listSaves(). --- src/gamebryo/gamebryosavegame.cpp | 134 +++++++++++--------- src/gamebryo/gamebryosavegame.h | 90 ++++++++----- src/gamebryo/gamebryosavegameinfo.cpp | 14 +- src/gamebryo/gamebryosavegameinfo.h | 4 +- src/gamebryo/gamebryosavegameinfowidget.cpp | 27 ++-- src/gamebryo/gamebryosavegameinfowidget.h | 2 +- src/gamebryo/gamegamebryo.cpp | 22 ++++ src/gamebryo/gamegamebryo.h | 16 ++- 8 files changed, 191 insertions(+), 118 deletions(-) diff --git a/src/gamebryo/gamebryosavegame.cpp b/src/gamebryo/gamebryosavegame.cpp index 544ba127..86f23fa1 100644 --- a/src/gamebryo/gamebryosavegame.cpp +++ b/src/gamebryo/gamebryosavegame.cpp @@ -2,6 +2,7 @@ #include "iplugingame.h" #include "scriptextender.h" +#include "log.h" #include #include @@ -15,11 +16,15 @@ #include #include -GamebryoSaveGame::GamebryoSaveGame(QString const &file, MOBase::IPluginGame const *game, bool const lightEnabled) : + +#include "gamegamebryo.h" + +GamebryoSaveGame::GamebryoSaveGame(QString const &file, GameGamebryo const *game, bool const lightEnabled) : m_FileName(file), m_CreationTime(QFileInfo(file).lastModified()), m_Game(game), - m_LightEnabled(lightEnabled) + m_LightEnabled(lightEnabled), + m_DataFields([this]() { return fetchDataFields(); }) { } @@ -27,7 +32,7 @@ GamebryoSaveGame::~GamebryoSaveGame() { } -QString GamebryoSaveGame::getFilename() const +QString GamebryoSaveGame::getFilepath() const { return m_FileName; } @@ -37,6 +42,15 @@ QDateTime GamebryoSaveGame::getCreationTime() const return m_CreationTime; } +QString GamebryoSaveGame::getName() const +{ + return QObject::tr("%1, #%2, Level %3, %4") + .arg(m_PCName) + .arg(m_SaveNumber) + .arg(m_PCLevel) + .arg(m_PCLocation); +} + QString GamebryoSaveGame::getSaveGroupIdentifier() const { return m_PCName; @@ -81,15 +95,13 @@ void GamebryoSaveGame::setCreationTime(_SYSTEMTIME const &ctime) m_CreationTime = QDateTime(date, time, Qt::UTC); } -GamebryoSaveGame::FileWrapper::FileWrapper(GamebryoSaveGame *game, - QString const &expected) : - m_Game(game), - m_File(game->m_FileName), +GamebryoSaveGame::FileWrapper::FileWrapper(QString const& filepath, QString const &expected) : + m_File(filepath), m_HasFieldMarkers(false), m_PluginString(StringType::TYPE_WSTRING) { if (!m_File.open(QIODevice::ReadOnly)) { - throw std::runtime_error(QObject::tr("failed to open %1").arg(game->m_FileName).toUtf8().constData()); + throw std::runtime_error(QObject::tr("failed to open %1").arg(filepath).toUtf8().constData()); } std::vector fileID(expected.length() + 1); @@ -151,16 +163,16 @@ void GamebryoSaveGame::FileWrapper::read(void *buff, std::size_t length) } } -void GamebryoSaveGame::FileWrapper::readImage(int scale, bool alpha) +QImage GamebryoSaveGame::FileWrapper::readImage(int scale, bool alpha) { unsigned long width; read(width); unsigned long height; read(height); - readImage(width, height, scale, alpha); + return readImage(width, height, scale, alpha); } -void GamebryoSaveGame::FileWrapper::readImage(unsigned long width, unsigned long height, int scale, bool alpha) +QImage GamebryoSaveGame::FileWrapper::readImage(unsigned long width, unsigned long height, int scale, bool alpha) { int bpp = alpha ? 4 : 3; QScopedArrayPointer buffer(new unsigned char[width * height * bpp]); @@ -168,12 +180,12 @@ void GamebryoSaveGame::FileWrapper::readImage(unsigned long width, unsigned long QImage image(buffer.data(), width, height, alpha ? QImage::Format_RGBA8888_Premultiplied : QImage::Format_RGB888); if (scale != 0) { - m_Game->m_Screenshot = image.copy().scaledToWidth(scale); + return image.copy().scaledToWidth(scale); } else { // why do I have to copy here? without the copy, the buffer seems to get // deleted after the temporary vanishes, but shouldn't Qts implicit sharing // handle that? - m_Game->m_Screenshot = image.copy(); + return image.copy(); } } void readQDataStream(QDataStream &data, void *buff, std::size_t length) { @@ -201,31 +213,36 @@ template <> void readQDataStream(QDataStream &data, QString &value) value = QString::fromLatin1(buffer.data(), length); } +void GamebryoSaveGame::FileWrapper::setCompressionType(uint16_t compressionType) +{ + m_CompressionType = compressionType; +} + void GamebryoSaveGame::FileWrapper::closeCompressedData() { - if (m_Game->m_CompressionType == 0) { + if (m_CompressionType == 0) { } - else if (m_Game->m_CompressionType == 1) { - m_Game->m_Plugins.push_back("Please create an issue on the MO github labeled \"Found zlib Compressed\" with your savefile attached"); + else if (m_CompressionType == 1) { + MOBase::log::warn("Please create an issue on the MO github labeled \"Found zlib Compressed\" with your savefile attached"); } - else if (m_Game->m_CompressionType == 2) { + else if (m_CompressionType == 2) { m_Data->device()->close(); delete m_Data; } else - m_Game->m_Plugins.push_back("Please create an issue on the MO github labeled \"Found unknown Compressed\" with your savefile attached"); + MOBase::log::warn("Please create an issue on the MO github labeled \"Found unknown Compressed\" with your savefile attached"); } bool GamebryoSaveGame::FileWrapper::openCompressedData(int bytesToIgnore) { - if (m_Game->m_CompressionType == 0) { + if (m_CompressionType == 0) { if (bytesToIgnore>0)//Just to make certain skip(bytesToIgnore); return false; - } else if (m_Game->m_CompressionType == 1) { - m_Game->m_Plugins.push_back("Please create an issue on the MO github labeled \"Found zlib Compressed\" with your savefile attached"); + } else if (m_CompressionType == 1) { + MOBase::log::warn("Please create an issue on the MO github labeled \"Found zlib Compressed\" with your savefile attached"); return false; - } else if (m_Game->m_CompressionType == 2) { + } else if (m_CompressionType == 2) { uint32_t uncompressedSize; read(uncompressedSize); uint32_t compressedSize; @@ -243,23 +260,23 @@ bool GamebryoSaveGame::FileWrapper::openCompressedData(int bytesToIgnore) return true; } else { - m_Game->m_Plugins.push_back("Please create an issue on the MO github labeled \"Found unknown Compressed\" with your savefile attached"); + MOBase::log::warn("Please create an issue on the MO github labeled \"Found unknown Compressed\" with your savefile attached"); return false; } } uint8_t GamebryoSaveGame::FileWrapper::readChar(int bytesToIgnore) { - if (m_Game->m_CompressionType == 0) { + if (m_CompressionType == 0) { if (bytesToIgnore>0)//Just to make certain skip(bytesToIgnore); uint8_t version; read(version); return version; - } else if (m_Game->m_CompressionType == 1) { - m_Game->m_Plugins.push_back("Please create an issue on the MO github labeled \"Found zlib Compressed\" with your savefile attached"); + } else if (m_CompressionType == 1) { + MOBase::log::warn("Please create an issue on the MO github labeled \"Found zlib Compressed\" with your savefile attached"); return 0; - } else if (m_Game->m_CompressionType == 2) { + } else if (m_CompressionType == 2) { // decompression already done by readSaveGameVersion m_Data->skipRawData(bytesToIgnore); @@ -268,23 +285,23 @@ uint8_t GamebryoSaveGame::FileWrapper::readChar(int bytesToIgnore) return version; } else { - m_Game->m_Plugins.push_back("Please create an issue on the MO github labeled \"Found unknown Compressed\" with your savefile attached"); + MOBase::log::warn("Please create an issue on the MO github labeled \"Found unknown Compressed\" with your savefile attached"); return 0; } } uint16_t GamebryoSaveGame::FileWrapper::readShort(int bytesToIgnore) { - if (m_Game->m_CompressionType == 0) { + if (m_CompressionType == 0) { if (bytesToIgnore>0)//Just to make certain skip(bytesToIgnore); uint16_t size; read(size); return size; - } else if (m_Game->m_CompressionType == 1) { - m_Game->m_Plugins.push_back("Please create an issue on the MO github labeled \"Found zlib Compressed\" with your savefile attached"); + } else if (m_CompressionType == 1) { + MOBase::log::warn("Please create an issue on the MO github labeled \"Found zlib Compressed\" with your savefile attached"); return 0; - } else if (m_Game->m_CompressionType == 2) { + } else if (m_CompressionType == 2) { // decompression already done by readSaveGameVersion m_Data->skipRawData(bytesToIgnore); @@ -292,23 +309,23 @@ uint16_t GamebryoSaveGame::FileWrapper::readShort(int bytesToIgnore) readQDataStream(*m_Data, size); return size; } else { - m_Game->m_Plugins.push_back("Please create an issue on the MO github labeled \"Found unknown Compressed\" with your savefile attached"); + MOBase::log::warn("Please create an issue on the MO github labeled \"Found unknown Compressed\" with your savefile attached"); return 0; } } uint32_t GamebryoSaveGame::FileWrapper::readInt(int bytesToIgnore) { - if (m_Game->m_CompressionType == 0) { + if (m_CompressionType == 0) { if (bytesToIgnore>0)//Just to make certain skip(bytesToIgnore); uint32_t size; read(size); return size; - } else if (m_Game->m_CompressionType == 1) { - m_Game->m_Plugins.push_back("Please create an issue on the MO github labeled \"Found zlib Compressed\" with your savefile attached"); + } else if (m_CompressionType == 1) { + MOBase::log::warn("Please create an issue on the MO github labeled \"Found zlib Compressed\" with your savefile attached"); return 0; - } else if (m_Game->m_CompressionType == 2) { + } else if (m_CompressionType == 2) { // decompression already done by readSaveGameVersion m_Data->skipRawData(bytesToIgnore); @@ -316,69 +333,72 @@ uint32_t GamebryoSaveGame::FileWrapper::readInt(int bytesToIgnore) readQDataStream(*m_Data, size); return size; } else { - m_Game->m_Plugins.push_back("Please create an issue on the MO github labeled \"Found unknown Compressed\" with your savefile attached"); + MOBase::log::warn("Please create an issue on the MO github labeled \"Found unknown Compressed\" with your savefile attached"); return 0; } } -void GamebryoSaveGame::FileWrapper::readPlugins(int bytesToIgnore) +QStringList GamebryoSaveGame::FileWrapper::readPlugins(int bytesToIgnore) { - if (m_Game->m_CompressionType == 0) { + QStringList plugins; + if (m_CompressionType == 0) { if (bytesToIgnore>0)//Just to make certain skip(bytesToIgnore); uint8_t count; read(count); uint16_t finalCount = count; - m_Game->m_Plugins.reserve(finalCount); + plugins.reserve(finalCount); for (std::size_t i = 0; i < finalCount; ++i) { QString name; read(name); - m_Game->m_Plugins.push_back(name); + plugins.push_back(name); } - } else if (m_Game->m_CompressionType == 1) { - m_Game->m_Plugins.push_back("Please create an issue on the MO github labeled \"Found zlib Compressed\" with your savefile attached"); - } else if (m_Game->m_CompressionType == 2) { + } else if (m_CompressionType == 1) { + MOBase::log::warn("Please create an issue on the MO github labeled \"Found zlib Compressed\" with your savefile attached"); + } else if (m_CompressionType == 2) { m_Data->skipRawData(bytesToIgnore); uint8_t count; readQDataStream(*m_Data, count); uint16_t finalCount = count; - m_Game->m_Plugins.reserve(finalCount); + plugins.reserve(finalCount); for (std::size_t i = 0; im_Plugins.push_back(name); + plugins.push_back(name); } } + return plugins; } -void GamebryoSaveGame::FileWrapper::readLightPlugins(int bytesToIgnore) +QStringList GamebryoSaveGame::FileWrapper::readLightPlugins(int bytesToIgnore) { - if (m_Game->m_CompressionType == 0) { + QStringList plugins; + if (m_CompressionType == 0) { if (bytesToIgnore>0)//Just to make certain skip(bytesToIgnore); uint16_t count; read(count); - m_Game->m_LightPlugins.reserve(count); + plugins.reserve(count); for (std::size_t i = 0; i < count; ++i) { QString name; read(name); - m_Game->m_LightPlugins.push_back(name); + plugins.push_back(name); } - } else if (m_Game->m_CompressionType == 1) { - m_Game->m_Plugins.push_back("Please create an issue on the MO github labeled \"Found zlib Compressed\" with your savefile attached"); - } else if (m_Game->m_CompressionType == 2) { + } else if (m_CompressionType == 1) { + MOBase::log::warn("Please create an issue on the MO github labeled \"Found zlib Compressed\" with your savefile attached"); + } else if (m_CompressionType == 2) { m_Data->skipRawData(bytesToIgnore); uint16_t count; readQDataStream(*m_Data, count); - m_Game->m_LightPlugins.reserve(count); + plugins.reserve(count); for (std::size_t i = 0; im_LightPlugins.push_back(name); + plugins.push_back(name); } - } + return plugins; } void GamebryoSaveGame::FileWrapper::close() diff --git a/src/gamebryo/gamebryosavegame.h b/src/gamebryo/gamebryosavegame.h index 28e21aa8..1d92182b 100644 --- a/src/gamebryo/gamebryosavegame.h +++ b/src/gamebryo/gamebryosavegame.h @@ -2,6 +2,7 @@ #define GAMEBRYOSAVEGAME_H #include "isavegame.h" +#include "memoizedlock.h" #include #include @@ -16,32 +17,38 @@ struct _SYSTEMTIME; namespace MOBase { class IPluginGame; } +class GameGamebryo; + class GamebryoSaveGame : public MOBase::ISaveGame { public: - GamebryoSaveGame(QString const &file, MOBase::IPluginGame const *game, bool const lightEnabled = false); + GamebryoSaveGame(QString const &file, GameGamebryo const *game, bool const lightEnabled = false); virtual ~GamebryoSaveGame(); - virtual QString getFilename() const override; +public: // ISaveGame interface + virtual QString getFilepath() const override; virtual QDateTime getCreationTime() const override; - + virtual QString getName() const override; virtual QString getSaveGroupIdentifier() const override; - virtual QStringList allFiles() const override; - virtual bool hasScriptExtenderFile() const override; +public: + + bool hasScriptExtenderFile() const; //Simple getters - QString getPCName() const { return m_PCName; } - unsigned short getPCLevel() const { return m_PCLevel; } - QString getPCLocation() const { return m_PCLocation; } - unsigned long getSaveNumber() const { return m_SaveNumber; } - QStringList const &getPlugins() const { return m_Plugins; } - QStringList const &getLightPlugins() const { return m_LightPlugins; } - QImage const &getScreenshot() const { return m_Screenshot; } - bool const &isLightEnabled() const { return m_LightEnabled; } + virtual QString getPCName() const { return m_PCName; } + virtual unsigned short getPCLevel() const { return m_PCLevel; } + virtual QString getPCLocation() const { return m_PCLocation; } + virtual unsigned long getSaveNumber() const { return m_SaveNumber; } + + QStringList const &getPlugins() const { return m_DataFields.value()->Plugins; } + QStringList const &getLightPlugins() const { return m_DataFields.value()->LightPlugins; } + QImage const &getScreenshot() const { return m_DataFields.value()->Screenshot; } + + bool isLightEnabled() const { return m_LightEnabled; } enum StringType { @@ -57,10 +64,14 @@ protected: class FileWrapper { public: - /** Construct the save file information. - * @params expected - expect bytes at start of file - **/ - FileWrapper(GamebryoSaveGame *game, QString const &expected); + /** + * @brief Construct the save file information. + * + * @param filepath The path to the save file. + * @params expected Expecte bytes at start of file. + * + **/ + FileWrapper(QString const& filepath, QString const &expected); /** Set this for save games that have a marker at the end of each * field. Specifically fallout @@ -101,10 +112,13 @@ protected: /* Reads RGB image from save * Assumes picture dimentions come immediately before the save */ - void readImage(int scale = 0, bool alpha = false); + QImage readImage(int scale = 0, bool alpha = false); /* Reads RGB image from save */ - void readImage(unsigned long width, unsigned long height, int scale = 0, bool alpha = false); + QImage readImage(unsigned long width, unsigned long height, int scale = 0, bool alpha = false); + + /* Sets the compression type. */ + void setCompressionType(uint16_t type); /* uncompress the begining of the compressed block */ bool openCompressedData(int bytesToIgnore = 0); @@ -120,38 +134,52 @@ protected: uint32_t readInt(int bytesToIgnore = 0); /* Read the plugin list */ - void readPlugins(int bytesToIgnore = 0); + QStringList readPlugins(int bytesToIgnore = 0); /* Read the light plugin list */ - void readLightPlugins(int bytesToIgnore = 0); - - /* Set the creation time from a system date */ - void setCreationTime(::_SYSTEMTIME const &); + QStringList readLightPlugins(int bytesToIgnore = 0); void close(); private: - GamebryoSaveGame *m_Game; QFile m_File; bool m_HasFieldMarkers; StringType m_PluginString; QDataStream *m_Data; + uint16_t m_CompressionType = 0; }; void setCreationTime(_SYSTEMTIME const &time); + GameGamebryo const* m_Game; + bool m_LightEnabled; + QString m_FileName; QString m_PCName; unsigned short m_PCLevel; QString m_PCLocation; unsigned long m_SaveNumber; QDateTime m_CreationTime; - QStringList m_Plugins; - QStringList m_LightPlugins; - QImage m_Screenshot; - MOBase::IPluginGame const *m_Game; - uint16_t m_CompressionType = 0; - bool m_LightEnabled; + + // Those three fields are usually much slower to fetch than + // the other, so we do not fetch them if not needed. + // + // This is virtual so child class can add fields if those are + // hard to access. + struct DataFields { + QStringList Plugins; + QStringList LightPlugins; + QImage Screenshot; + + // We need this constructor. + DataFields() { } + virtual ~DataFields() { } + }; + MOBase::MemoizedLocked> m_DataFields; + + // Fetch the field. + virtual std::unique_ptr fetchDataFields() const = 0; + }; diff --git a/src/gamebryo/gamebryosavegameinfo.cpp b/src/gamebryo/gamebryosavegameinfo.cpp index 69c1789b..a165ad1b 100644 --- a/src/gamebryo/gamebryosavegameinfo.cpp +++ b/src/gamebryo/gamebryosavegameinfo.cpp @@ -21,15 +21,15 @@ GamebryoSaveGameInfo::~GamebryoSaveGameInfo() { } -GamebryoSaveGameInfo::MissingAssets GamebryoSaveGameInfo::getMissingAssets(QString const &file) const +GamebryoSaveGameInfo::MissingAssets GamebryoSaveGameInfo::getMissingAssets(MOBase::ISaveGame const& save) const { - GamebryoSaveGame const *save = dynamic_cast(getSaveGameInfo(file)); + GamebryoSaveGame const &gamebryoSave = dynamic_cast(save); MOBase::IOrganizer *organizerCore = m_Game->m_Organizer; // collect the list of missing plugins MissingAssets missingAssets; - for (QString const &pluginName : save->getPlugins()) { + for (QString const &pluginName : gamebryoSave.getPlugins()) { switch (organizerCore->pluginList()->state(pluginName)) { case MOBase::IPluginList::STATE_INACTIVE: missingAssets[pluginName] = ProvidingModules { organizerCore->pluginList()->origin(pluginName) }; @@ -40,7 +40,7 @@ GamebryoSaveGameInfo::MissingAssets GamebryoSaveGameInfo::getMissingAssets(QStri } } - for (QString const &pluginName : save->getLightPlugins()) { + for (QString const &pluginName : gamebryoSave.getLightPlugins()) { switch (organizerCore->pluginList()->state(pluginName)) { case MOBase::IPluginList::STATE_INACTIVE: missingAssets[pluginName] = ProvidingModules{ organizerCore->pluginList()->origin(pluginName) }; @@ -99,9 +99,3 @@ MOBase::ISaveGameInfoWidget *GamebryoSaveGameInfo::getSaveGameWidget(QWidget *pa { return new GamebryoSaveGameInfoWidget(this, parent); } - -bool GamebryoSaveGameInfo::hasScriptExtenderSave(QString const &file) const -{ - GamebryoSaveGame const *save = dynamic_cast(getSaveGameInfo(file)); - return save->hasScriptExtenderFile(); -} diff --git a/src/gamebryo/gamebryosavegameinfo.h b/src/gamebryo/gamebryosavegameinfo.h index 60df58e6..55bc6655 100644 --- a/src/gamebryo/gamebryosavegameinfo.h +++ b/src/gamebryo/gamebryosavegameinfo.h @@ -11,12 +11,10 @@ public: GamebryoSaveGameInfo(GameGamebryo const *game); ~GamebryoSaveGameInfo(); - virtual MissingAssets getMissingAssets(QString const &file) const override; + virtual MissingAssets getMissingAssets(MOBase::ISaveGame const& save) const override; virtual MOBase::ISaveGameInfoWidget *getSaveGameWidget(QWidget *) const override; - virtual bool hasScriptExtenderSave(QString const &file) const override; - protected: friend class GamebryoSaveGameInfoWidget; GameGamebryo const *m_Game; diff --git a/src/gamebryo/gamebryosavegameinfowidget.cpp b/src/gamebryo/gamebryosavegameinfowidget.cpp index dda5a5bb..85bdee02 100644 --- a/src/gamebryo/gamebryosavegameinfowidget.cpp +++ b/src/gamebryo/gamebryosavegameinfowidget.cpp @@ -43,19 +43,18 @@ GamebryoSaveGameInfoWidget::~GamebryoSaveGameInfoWidget() { delete ui; } -void GamebryoSaveGameInfoWidget::setSave(QString const &file) { - std::unique_ptr save( - std::move(dynamic_cast(m_Info->getSaveGameInfo(file)))); - ui->saveNumLabel->setText(QString("%1").arg(save->getSaveNumber())); - ui->characterLabel->setText(save->getPCName()); - ui->locationLabel->setText(save->getPCLocation()); - ui->levelLabel->setText(QString("%1").arg(save->getPCLevel())); +void GamebryoSaveGameInfoWidget::setSave(MOBase::ISaveGame const& save) { + auto& gamebryoSave = dynamic_cast(save); + ui->saveNumLabel->setText(QString("%1").arg(gamebryoSave.getSaveNumber())); + ui->characterLabel->setText(gamebryoSave.getPCName()); + ui->locationLabel->setText(gamebryoSave.getPCLocation()); + ui->levelLabel->setText(QString("%1").arg(gamebryoSave.getPCLevel())); //This somewhat contorted code is because on my system at least, the //old way of doing this appears to give short date and long time. - QDateTime t = save->getCreationTime(); + QDateTime t = gamebryoSave.getCreationTime(); ui->dateLabel->setText(t.date().toString(Qt::DefaultLocaleShortDate) + " " + t.time().toString(Qt::DefaultLocaleLongDate)); - ui->screenshotLabel->setPixmap(QPixmap::fromImage(save->getScreenshot())); + ui->screenshotLabel->setPixmap(QPixmap::fromImage(gamebryoSave.getScreenshot())); if (ui->gameFrame->layout() != nullptr) { QLayoutItem *item = nullptr; while ((item = ui->gameFrame->layout()->takeAt(0)) != nullptr) { @@ -64,12 +63,12 @@ void GamebryoSaveGameInfoWidget::setSave(QString const &file) { } ui->gameFrame->layout()->setSizeConstraint(QLayout::SetFixedSize); } - + // Resize box to new content this->resize(0, 0); QLayout *layout = ui->gameFrame->layout(); - if (m_Info->hasScriptExtenderSave(file)) { + if (gamebryoSave.hasScriptExtenderFile()) { QLabel *scriptExtender = new QLabel(tr("Has Script Extender Data")); QFont headerFont = scriptExtender->font(); headerFont.setBold(true); @@ -85,7 +84,7 @@ void GamebryoSaveGameInfoWidget::setSave(QString const &file) { layout->addWidget(header); int count = 0; MOBase::IPluginList *pluginList = m_Info->m_Game->m_Organizer->pluginList(); - for (QString const &pluginName : save->getPlugins()) { + for (QString const &pluginName : gamebryoSave.getPlugins()) { if (pluginList->state(pluginName) == MOBase::IPluginList::STATE_ACTIVE) { continue; } @@ -113,7 +112,7 @@ void GamebryoSaveGameInfoWidget::setSave(QString const &file) { dotDotLabel->setFont(contentFont); layout->addWidget(dotDotLabel); } - if (save->isLightEnabled()) { + if (gamebryoSave.isLightEnabled()) { QLabel *headerEsl = new QLabel(tr("Missing ESLs")); QFont headerEslFont = headerEsl->font(); QFont contentEslFont = headerEslFont; @@ -123,7 +122,7 @@ void GamebryoSaveGameInfoWidget::setSave(QString const &file) { headerEsl->setFont(headerEslFont); layout->addWidget(headerEsl); int countEsl = 0; - for (QString const &pluginName : save->getLightPlugins()) { + for (QString const &pluginName : gamebryoSave.getLightPlugins()) { if (pluginList->state(pluginName) == MOBase::IPluginList::STATE_ACTIVE) { continue; } diff --git a/src/gamebryo/gamebryosavegameinfowidget.h b/src/gamebryo/gamebryosavegameinfowidget.h index 387d4865..665a0aba 100644 --- a/src/gamebryo/gamebryosavegameinfowidget.h +++ b/src/gamebryo/gamebryosavegameinfowidget.h @@ -17,7 +17,7 @@ public: GamebryoSaveGameInfoWidget(GamebryoSaveGameInfo const *info, QWidget *parent); ~GamebryoSaveGameInfoWidget(); - virtual void setSave(QString const &) override; + virtual void setSave(MOBase::ISaveGame const &) override; private: Ui::GamebryoSaveGameInfoWidget *ui; diff --git a/src/gamebryo/gamegamebryo.cpp b/src/gamebryo/gamegamebryo.cpp index bf4571bd..9a398c7b 100644 --- a/src/gamebryo/gamegamebryo.cpp +++ b/src/gamebryo/gamegamebryo.cpp @@ -7,8 +7,11 @@ #include "scopeguard.h" #include "utility.h" #include "gamebryomoddatacontent.h" +#include "gamebryosavegame.h" +#include "gameplugins.h" #include +#include #include #include #include @@ -90,6 +93,25 @@ QDir GameGamebryo::savesDirectory() const return QDir(m_MyGamesPath + "/Saves"); } +std::vector> +GameGamebryo::listSaves(QDir folder) const +{ + QStringList filters; + filters << QString("*.") + savegameExtension(); + + folder.setNameFilters(filters); + folder.setFilter(QDir::Files); + QDirIterator it(folder, QDirIterator::Subdirectories); + + std::vector> saves; + while (it.hasNext()) { + it.next(); + saves.push_back(makeSaveGame(it.filePath())); + } + + return saves; +} + QStringList GameGamebryo::gameVariants() const { return QStringList(); diff --git a/src/gamebryo/gamegamebryo.h b/src/gamebryo/gamegamebryo.h index aecd51d2..3ddc156d 100644 --- a/src/gamebryo/gamegamebryo.h +++ b/src/gamebryo/gamegamebryo.h @@ -21,6 +21,8 @@ class UnmanagedMods; #include #include +#include "gamebryosavegame.h" + class GameGamebryo : public MOBase::IPluginGame, public MOBase::IPluginFileMapper { @@ -49,8 +51,8 @@ public: // IPluginGame interface //getName //initializeProfile - //savegameExtension - //savegameSEExtension + virtual std::vector> listSaves(QDir folder) const override; + virtual bool isInstalled() const override; virtual QIcon gameIcon() const override; virtual QDir gameDirectory() const override; @@ -84,6 +86,16 @@ public: // IPluginFileMapper interface protected: + friend class GamebryoSaveGame; + + // Retrieve the saves extension for the game. + virtual QString savegameExtension() const = 0; + virtual QString savegameSEExtension() const = 0; + + // Create a save game: + virtual std::shared_ptr makeSaveGame(QString filepath) const = 0; + + QFileInfo findInGameFolder(const QString &relativePath) const; QString myGamesPath() const; QString selectedVariant() const; From 42571fc76865f37d99d1d84430d9d1e6e8ef234d Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Mika=C3=ABl=20Capelle?= Date: Wed, 18 Nov 2020 19:24:38 +0100 Subject: [PATCH 1092/1544] [game_falloutnv] Update for IPluginGame::listSaves(). --- src/games/falloutnv/src/falloutnvsavegame.cpp | 57 ++++++++++++++----- src/games/falloutnv/src/falloutnvsavegame.h | 18 +++++- .../falloutnv/src/falloutnvsavegameinfo.cpp | 18 ------ .../falloutnv/src/falloutnvsavegameinfo.h | 17 ------ src/games/falloutnv/src/gamefalloutnv.cpp | 10 +++- src/games/falloutnv/src/gamefalloutnv.h | 8 ++- 6 files changed, 72 insertions(+), 56 deletions(-) delete mode 100644 src/games/falloutnv/src/falloutnvsavegameinfo.cpp delete mode 100644 src/games/falloutnv/src/falloutnvsavegameinfo.h diff --git a/src/games/falloutnv/src/falloutnvsavegame.cpp b/src/games/falloutnv/src/falloutnvsavegame.cpp index 24c5505b..21560de2 100644 --- a/src/games/falloutnv/src/falloutnvsavegame.cpp +++ b/src/games/falloutnv/src/falloutnvsavegame.cpp @@ -1,10 +1,25 @@ #include "falloutnvsavegame.h" -FalloutNVSaveGame::FalloutNVSaveGame(QString const &fileName, MOBase::IPluginGame const *game) : +#include "gamefalloutnv.h" + +FalloutNVSaveGame::FalloutNVSaveGame(QString const &fileName, GameFalloutNV const *game) : GamebryoSaveGame(fileName, game) { - FileWrapper file(this, "FO3SAVEGAME"); + FileWrapper file(getFilepath(), "FO3SAVEGAME"); + unsigned long width, height; + fetchInformationFields(file, width, height, m_SaveNumber, m_PCName, m_PCLevel, m_PCLocation); +} + +void FalloutNVSaveGame::fetchInformationFields( + FileWrapper& file, + unsigned long& width, + unsigned long& height, + unsigned long& saveNumber, + QString& playerName, + unsigned short& playerLevel, + QString& playerLocation) const +{ file.skip(); //Save header size file.skip(); //File version? @@ -20,33 +35,45 @@ FalloutNVSaveGame::FalloutNVSaveGame(QString const &fileName, MOBase::IPluginGam file.setHasFieldMarkers(true); file.setPluginString(GamebryoSaveGame::StringType::TYPE_BZSTRING); - unsigned long width; file.read(width); - - unsigned long height; file.read(height); - - file.read(m_SaveNumber); - - file.read(m_PCName); + file.read(saveNumber); + file.read(playerName); QString whatthis; file.read(whatthis); long level; file.read(level); - m_PCLevel = level; + playerLevel = level; + file.read(playerLocation); +} - file.read(m_PCLocation); +std::unique_ptr FalloutNVSaveGame::fetchDataFields() const +{ + FileWrapper file(getFilepath(), "FO3SAVEGAME"); + + std::unique_ptr fields = std::make_unique(); + + unsigned long width, height; + { + QString dummyName, dummyLocation; + unsigned short dummyLevel; + unsigned long dummySaveNumber; + + fetchInformationFields(file, width, height, + dummySaveNumber, dummyName, dummyLevel, dummyLocation); + } QString playtime; file.read(playtime); - file.readImage(width, height, 256); + fields->Screenshot = file.readImage(width, height, 256); - file.skip(5); // unknown byte, size of plugin data + file.skip(5); // unknown (1 byte), plugin size (4 bytes) - //Abstract this file.setPluginString(GamebryoSaveGame::StringType::TYPE_BSTRING); - file.readPlugins(); + fields->Plugins = file.readPlugins(); + + return fields; } diff --git a/src/games/falloutnv/src/falloutnvsavegame.h b/src/games/falloutnv/src/falloutnvsavegame.h index b045469a..b1772e3f 100644 --- a/src/games/falloutnv/src/falloutnvsavegame.h +++ b/src/games/falloutnv/src/falloutnvsavegame.h @@ -3,12 +3,26 @@ #include "gamebryosavegame.h" -namespace MOBase { class IPluginGame; } +class GameFalloutNV; class FalloutNVSaveGame : public GamebryoSaveGame { public: - FalloutNVSaveGame(QString const &fileName, MOBase::IPluginGame const *game); + FalloutNVSaveGame(QString const &fileName, GameFalloutNV const *game); + +protected: + + // Fetch easy-to-access information. + void fetchInformationFields( + FileWrapper& wrapper, + unsigned long& width, + unsigned long& height, + unsigned long& saveNumber, + QString& playerName, + unsigned short& playerLevel, + QString& playerLocation) const; + + std::unique_ptr fetchDataFields() const override; }; #endif // FALLOUTNVSAVEGAME_H diff --git a/src/games/falloutnv/src/falloutnvsavegameinfo.cpp b/src/games/falloutnv/src/falloutnvsavegameinfo.cpp deleted file mode 100644 index 830d5030..00000000 --- a/src/games/falloutnv/src/falloutnvsavegameinfo.cpp +++ /dev/null @@ -1,18 +0,0 @@ -#include "falloutnvsavegameinfo.h" - -#include "falloutnvsavegame.h" -#include "gamegamebryo.h" - -FalloutNVSaveGameInfo::FalloutNVSaveGameInfo(GameGamebryo const *game) : - GamebryoSaveGameInfo(game) -{ -} - -FalloutNVSaveGameInfo::~FalloutNVSaveGameInfo() -{ -} - -MOBase::ISaveGame const *FalloutNVSaveGameInfo::getSaveGameInfo(QString const &file) const -{ - return new FalloutNVSaveGame(file, m_Game); -} diff --git a/src/games/falloutnv/src/falloutnvsavegameinfo.h b/src/games/falloutnv/src/falloutnvsavegameinfo.h deleted file mode 100644 index 6819e3e9..00000000 --- a/src/games/falloutnv/src/falloutnvsavegameinfo.h +++ /dev/null @@ -1,17 +0,0 @@ -#ifndef FALLOUTNVSAVEGAMEINFO_H -#define FALLOUTNVSAVEGAMEINFO_H - -#include "gamebryosavegameinfo.h" - -class GameGamebryo; - -class FalloutNVSaveGameInfo : public GamebryoSaveGameInfo -{ -public: - FalloutNVSaveGameInfo(GameGamebryo const *game); - ~FalloutNVSaveGameInfo(); - - virtual MOBase::ISaveGame const *getSaveGameInfo(QString const &file) const override; - -}; -#endif // FALLOUTNVSAVEGAMEINFO_H diff --git a/src/games/falloutnv/src/gamefalloutnv.cpp b/src/games/falloutnv/src/gamefalloutnv.cpp index 75f491d1..4db39428 100644 --- a/src/games/falloutnv/src/gamefalloutnv.cpp +++ b/src/games/falloutnv/src/gamefalloutnv.cpp @@ -2,16 +2,17 @@ #include "falloutnvbsainvalidation.h" #include "falloutnvdataarchives.h" -#include "falloutnvsavegameinfo.h" #include "falloutnvscriptextender.h" #include "falloutnvmoddatachecker.h" #include "falloutnvmoddatacontent.h" +#include "falloutnvsavegame.h" #include "executableinfo.h" #include "pluginsetting.h" #include "versioninfo.h" #include #include +#include #include #include @@ -38,7 +39,7 @@ bool GameFalloutNV::init(IOrganizer *moInfo) registerFeature(new FalloutNVScriptExtender(this)); registerFeature(new FalloutNVDataArchives(myGamesPath())); registerFeature(new FalloutNVBSAInvalidation(feature(), this)); - registerFeature(new FalloutNVSaveGameInfo(this)); + registerFeature(new GamebryoSaveGameInfo(this)); registerFeature(new GamebryoLocalSavegames(myGamesPath(), "fallout.ini")); registerFeature(new FalloutNVModDataChecker(this)); registerFeature(new FalloutNVModDataContent(this)); @@ -135,6 +136,11 @@ QString GameFalloutNV::savegameSEExtension() const return "nvse"; } +std::shared_ptr GameFalloutNV::makeSaveGame(QString filePath) const +{ + return std::make_shared(filePath, this); +} + QString GameFalloutNV::steamAPPId() const { return "22380"; diff --git a/src/games/falloutnv/src/gamefalloutnv.h b/src/games/falloutnv/src/gamefalloutnv.h index a32d9d4a..d2ac8621 100644 --- a/src/games/falloutnv/src/gamefalloutnv.h +++ b/src/games/falloutnv/src/gamefalloutnv.h @@ -25,8 +25,6 @@ public: // IPluginGame interface virtual QList executables() const override; virtual QList executableForcedLoads() const override; virtual void initializeProfile(const QDir &path, ProfileSettings settings) const override; - virtual QString savegameExtension() const override; - virtual QString savegameSEExtension() const override; virtual QString steamAPPId() const override; virtual QStringList primaryPlugins() const override; virtual QString gameShortName() const override; @@ -46,6 +44,12 @@ public: // IPlugin interface virtual MOBase::VersionInfo version() const override; virtual QList settings() const override; +protected: + + virtual QString savegameExtension() const override; + virtual QString savegameSEExtension() const override; + std::shared_ptr makeSaveGame(QString filePath) const override; + }; #endif // GAMEFALLOUTNV_H From a33c39697caee96ecd4d591f9b0eeaf6f4ac8e89 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Mika=C3=ABl=20Capelle?= Date: Wed, 18 Nov 2020 19:24:38 +0100 Subject: [PATCH 1093/1544] [game_fallout4] Update for IPluginGame::listSaves(). --- src/games/fallout4/src/fallout4savegame.cpp | 76 ++++++++++++++----- src/games/fallout4/src/fallout4savegame.h | 19 ++++- .../fallout4/src/fallout4savegameinfo.cpp | 19 ----- src/games/fallout4/src/fallout4savegameinfo.h | 17 ----- src/games/fallout4/src/gamefallout4.cpp | 10 ++- src/games/fallout4/src/gamefallout4.h | 8 +- 6 files changed, 87 insertions(+), 62 deletions(-) delete mode 100644 src/games/fallout4/src/fallout4savegameinfo.cpp delete mode 100644 src/games/fallout4/src/fallout4savegameinfo.h diff --git a/src/games/fallout4/src/fallout4savegame.cpp b/src/games/fallout4/src/fallout4savegame.cpp index 429cf1cc..53bb5dcc 100644 --- a/src/games/fallout4/src/fallout4savegame.cpp +++ b/src/games/fallout4/src/fallout4savegame.cpp @@ -2,20 +2,43 @@ #include -Fallout4SaveGame::Fallout4SaveGame(QString const &fileName, MOBase::IPluginGame const *game, bool const lightEnabled) : - GamebryoSaveGame(fileName, game, lightEnabled) +#include "gamefallout4.h" + +Fallout4SaveGame::Fallout4SaveGame(QString const &fileName, GameFallout4 const* game) : + GamebryoSaveGame(fileName, game, true) +{ + FileWrapper file(getFilepath(), "FO4_SAVEGAME"); + + FILETIME creationTime; + fetchInformationFields(file, m_SaveNumber, m_PCName, m_PCLevel, m_PCLocation, creationTime); + + //A file time is a 64-bit value that represents the number of 100-nanosecond + //intervals that have elapsed since 12:00 A.M. January 1, 1601 Coordinated Universal Time (UTC). + //So we need to convert that to something useful + SYSTEMTIME ctime; + ::FileTimeToSystemTime(&creationTime, &ctime); + + setCreationTime(ctime); +} + +void Fallout4SaveGame::fetchInformationFields( + FileWrapper& file, + unsigned long& saveNumber, + QString& playerName, + unsigned short& playerLevel, + QString& playerLocation, + FILETIME& creationTime) const { - FileWrapper file(this, "FO4_SAVEGAME"); file.skip(); // header size file.skip(); // header version - file.read(m_SaveNumber); + file.read(saveNumber); - file.read(m_PCName); + file.read(playerName); unsigned long temp; file.read(temp); - m_PCLevel = static_cast(temp); - file.read(m_PCLocation); + playerLevel = static_cast(temp); + file.read(playerLocation); QString ignore; file.read(ignore); // playtime as ascii hh.mm.ss @@ -24,23 +47,36 @@ Fallout4SaveGame::Fallout4SaveGame(QString const &fileName, MOBase::IPluginGame file.skip(); // Player gender (0 = male) file.skip(2); // experience gathered, experience required - FILETIME ftime; - file.read(ftime); - //A file time is a 64-bit value that represents the number of 100-nanosecond - //intervals that have elapsed since 12:00 A.M. January 1, 1601 Coordinated Universal Time (UTC). - //So we need to convert that to something useful - SYSTEMTIME ctime; - ::FileTimeToSystemTime(&ftime, &ctime); + file.read(creationTime); +} - setCreationTime(ctime); +std::unique_ptr Fallout4SaveGame::fetchDataFields() const +{ + FileWrapper file(getFilepath(), "FO4_SAVEGAME"); //10bytes - file.readImage(384, true); + { + QString dummyName, dummyLocation; + unsigned short dummyLevel; + unsigned long dummySaveNumber; + FILETIME dummyTime; + + fetchInformationFields(file, dummySaveNumber, dummyName, dummyLevel, + dummyLocation, dummyTime); + } + + QString ignore; + std::unique_ptr fields = std::make_unique(); + + fields->Screenshot = file.readImage(384, true); uint8_t saveGameVersion = file.readChar(); file.read(ignore); // game version file.skip(); // plugin info size - file.readPlugins(); - if (saveGameVersion >= 68) - file.readLightPlugins(); -} + fields->Plugins = file.readPlugins(); + if (saveGameVersion >= 68) { + fields->LightPlugins = file.readLightPlugins(); + } + + return fields; +} \ No newline at end of file diff --git a/src/games/fallout4/src/fallout4savegame.h b/src/games/fallout4/src/fallout4savegame.h index 98dffc9f..3c302e5a 100644 --- a/src/games/fallout4/src/fallout4savegame.h +++ b/src/games/fallout4/src/fallout4savegame.h @@ -3,12 +3,27 @@ #include "gamebryosavegame.h" -namespace MOBase { class IPluginGame; } +#include + +class GameFallout4; class Fallout4SaveGame : public GamebryoSaveGame { public: - Fallout4SaveGame(QString const &fileName, MOBase::IPluginGame const *game, bool const lightEnabled = true); + Fallout4SaveGame(QString const &fileName, GameFallout4 const* game); + +protected: + + // Fetch easy-to-access information. + void fetchInformationFields( + FileWrapper& file, + unsigned long& saveNumber, + QString& playerName, + unsigned short& playerLevel, + QString& playerLocation, + FILETIME& creationTime) const; + + std::unique_ptr fetchDataFields() const override; }; #endif // FALLOUT4SAVEGAME_H diff --git a/src/games/fallout4/src/fallout4savegameinfo.cpp b/src/games/fallout4/src/fallout4savegameinfo.cpp deleted file mode 100644 index 22856d86..00000000 --- a/src/games/fallout4/src/fallout4savegameinfo.cpp +++ /dev/null @@ -1,19 +0,0 @@ -#include "fallout4savegameinfo.h" - -#include "fallout4savegame.h" -#include "gamegamebryo.h" - -Fallout4SaveGameInfo::Fallout4SaveGameInfo(GameGamebryo const *game) : - GamebryoSaveGameInfo(game) -{ -} - -Fallout4SaveGameInfo::~Fallout4SaveGameInfo() -{ -} - -const MOBase::ISaveGame *Fallout4SaveGameInfo::getSaveGameInfo(const QString &file) const -{ - return new Fallout4SaveGame(file, m_Game); -} - diff --git a/src/games/fallout4/src/fallout4savegameinfo.h b/src/games/fallout4/src/fallout4savegameinfo.h deleted file mode 100644 index c36ec6f4..00000000 --- a/src/games/fallout4/src/fallout4savegameinfo.h +++ /dev/null @@ -1,17 +0,0 @@ -#ifndef SKYRIMSAVEGAMEINFO_H -#define SKYRIMSAVEGAMEINFO_H - -#include "gamebryosavegameinfo.h" - -class GameGamebryo; - -class Fallout4SaveGameInfo : public GamebryoSaveGameInfo -{ -public: - Fallout4SaveGameInfo(GameGamebryo const *game); - ~Fallout4SaveGameInfo(); - - virtual MOBase::ISaveGame const *getSaveGameInfo(QString const &file) const override; -}; - -#endif // SKYRIMSAVEGAMEINFO_H diff --git a/src/games/fallout4/src/gamefallout4.cpp b/src/games/fallout4/src/gamefallout4.cpp index 6bb84622..f155976a 100644 --- a/src/games/fallout4/src/gamefallout4.cpp +++ b/src/games/fallout4/src/gamefallout4.cpp @@ -2,14 +2,15 @@ #include "fallout4dataarchives.h" #include "fallout4scriptextender.h" -#include "fallout4savegameinfo.h" #include "fallout4unmanagedmods.h" #include "fallout4moddatachecker.h" #include "fallout4moddatacontent.h" +#include "fallout4savegame.h" #include #include #include +#include #include #include "versioninfo.h" @@ -42,7 +43,7 @@ bool GameFallout4::init(IOrganizer *moInfo) registerFeature(new GamebryoLocalSavegames(myGamesPath(), "fallout4custom.ini")); registerFeature(new Fallout4ModDataChecker(this)); registerFeature(new Fallout4ModDataContent(this)); - registerFeature(new Fallout4SaveGameInfo(this)); + registerFeature(new GamebryoSaveGameInfo(this)); registerFeature(new CreationGamePlugins(moInfo)); registerFeature(new Fallout4UnmangedMods(this)); @@ -132,6 +133,11 @@ QString GameFallout4::savegameSEExtension() const return "f4se"; } +std::shared_ptr GameFallout4::makeSaveGame(QString filePath) const +{ + return std::make_shared(filePath, this); +} + QString GameFallout4::steamAPPId() const { return "377160"; diff --git a/src/games/fallout4/src/gamefallout4.h b/src/games/fallout4/src/gamefallout4.h index 51c4af3f..72a7af62 100644 --- a/src/games/fallout4/src/gamefallout4.h +++ b/src/games/fallout4/src/gamefallout4.h @@ -25,8 +25,6 @@ public: // IPluginGame interface virtual QList executables() const override; virtual QList executableForcedLoads() const override; virtual void initializeProfile(const QDir &path, ProfileSettings settings) const override; - virtual QString savegameExtension() const override; - virtual QString savegameSEExtension() const override; virtual QString steamAPPId() const override; virtual QStringList primaryPlugins() const override; virtual QStringList gameVariants() const override; @@ -48,6 +46,12 @@ public: // IPlugin interface virtual MOBase::VersionInfo version() const override; virtual QList settings() const override; +protected: + + std::shared_ptr makeSaveGame(QString filePath) const override; + QString savegameExtension() const override; + QString savegameSEExtension() const override; + }; #endif // GAMEFallout4_H From 69b12913409e04efa4964c5f366f222b11c6a34d Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Mika=C3=ABl=20Capelle?= Date: Wed, 18 Nov 2020 19:24:38 +0100 Subject: [PATCH 1094/1544] [game_fallout3] Update for IPluginGame::listSaves(). --- src/games/fallout3/src/fallout3savegame.cpp | 56 ++++++++++++++----- src/games/fallout3/src/fallout3savegame.h | 18 +++++- .../fallout3/src/fallout3savegameinfo.cpp | 19 ------- src/games/fallout3/src/fallout3savegameinfo.h | 17 ------ src/games/fallout3/src/gamefallout3.cpp | 14 +++-- src/games/fallout3/src/gamefallout3.h | 6 +- 6 files changed, 72 insertions(+), 58 deletions(-) delete mode 100644 src/games/fallout3/src/fallout3savegameinfo.cpp delete mode 100644 src/games/fallout3/src/fallout3savegameinfo.h diff --git a/src/games/fallout3/src/fallout3savegame.cpp b/src/games/fallout3/src/fallout3savegame.cpp index e62e726e..765be18f 100644 --- a/src/games/fallout3/src/fallout3savegame.cpp +++ b/src/games/fallout3/src/fallout3savegame.cpp @@ -1,10 +1,25 @@ #include "fallout3savegame.h" -Fallout3SaveGame::Fallout3SaveGame(QString const &fileName, MOBase::IPluginGame const *game) : +#include "gamefallout3.h" + +Fallout3SaveGame::Fallout3SaveGame(QString const &fileName, GameFallout3 const *game) : GamebryoSaveGame(fileName, game) { - FileWrapper file(this, "FO3SAVEGAME"); + FileWrapper file(getFilepath(), "FO3SAVEGAME"); + unsigned long width, height; + fetchInformationFields(file, width, height, m_SaveNumber, m_PCName, m_PCLevel, m_PCLocation); +} + +void Fallout3SaveGame::fetchInformationFields( + FileWrapper& file, + unsigned long& width, + unsigned long& height, + unsigned long& saveNumber, + QString& playerName, + unsigned short& playerLevel, + QString& playerLocation) const +{ file.skip(); //Save header size file.setHasFieldMarkers(true); @@ -13,33 +28,46 @@ Fallout3SaveGame::Fallout3SaveGame(QString const &fileName, MOBase::IPluginGame file.skip(); //File version ? file.skip(); //delimiter - unsigned long width; file.read(width); - - unsigned long height; file.read(height); - - file.read(m_SaveNumber); - - file.read(m_PCName); + file.read(saveNumber); + file.read(playerName); QString whatthis; file.read(whatthis); long level; file.read(level); - m_PCLevel = level; + playerLevel = level; - file.read(m_PCLocation); + file.read(playerLocation); +} + +std::unique_ptr Fallout3SaveGame::fetchDataFields() const +{ + FileWrapper file(getFilepath(), "FO3SAVEGAME"); + + std::unique_ptr fields = std::make_unique(); + + unsigned long width, height; + { + QString dummyName, dummyLocation; + unsigned short dummyLevel; + unsigned long dummySaveNumber; + + fetchInformationFields(file, width, height, + dummySaveNumber, dummyName, dummyLevel, dummyLocation); + } QString playtime; file.read(playtime); - file.readImage(width, height, 256); + fields->Screenshot = file.readImage(width, height, 256); file.skip(5); // unknown (1 byte), plugin size (4 bytes) file.setPluginString(GamebryoSaveGame::StringType::TYPE_BSTRING); - file.readPlugins(); -} + fields->Plugins = file.readPlugins(); + return fields; +} diff --git a/src/games/fallout3/src/fallout3savegame.h b/src/games/fallout3/src/fallout3savegame.h index a84cfda5..d325bb90 100644 --- a/src/games/fallout3/src/fallout3savegame.h +++ b/src/games/fallout3/src/fallout3savegame.h @@ -3,12 +3,26 @@ #include "gamebryosavegame.h" -namespace MOBase { class IPluginGame; } +class GameFallout3; class Fallout3SaveGame : public GamebryoSaveGame { public: - Fallout3SaveGame(QString const &fileName, MOBase::IPluginGame const *game); + Fallout3SaveGame(QString const &fileName, GameFallout3 const *game); + +protected: + + // Fetch easy-to-access information. + void fetchInformationFields( + FileWrapper& wrapper, + unsigned long& width, + unsigned long& height, + unsigned long& saveNumber, + QString& playerName, + unsigned short& playerLevel, + QString& playerLocation) const; + + std::unique_ptr fetchDataFields() const override; }; #endif // FALLOUT3SAVEGAME_H diff --git a/src/games/fallout3/src/fallout3savegameinfo.cpp b/src/games/fallout3/src/fallout3savegameinfo.cpp deleted file mode 100644 index a1401052..00000000 --- a/src/games/fallout3/src/fallout3savegameinfo.cpp +++ /dev/null @@ -1,19 +0,0 @@ -#include "fallout3savegameinfo.h" - -#include "fallout3savegame.h" -#include "gamegamebryo.h" - -Fallout3SaveGameInfo::Fallout3SaveGameInfo(GameGamebryo const *game) : - GamebryoSaveGameInfo(game) -{ -} - -Fallout3SaveGameInfo::~Fallout3SaveGameInfo() -{ -} - -MOBase::ISaveGame const *Fallout3SaveGameInfo::getSaveGameInfo(const QString &file) const -{ - return new Fallout3SaveGame(file, m_Game); -} - diff --git a/src/games/fallout3/src/fallout3savegameinfo.h b/src/games/fallout3/src/fallout3savegameinfo.h deleted file mode 100644 index d42d4746..00000000 --- a/src/games/fallout3/src/fallout3savegameinfo.h +++ /dev/null @@ -1,17 +0,0 @@ -#ifndef FALLOUT3SAVEGAMEINFO_H -#define FALLOUT3SAVEGAMEINFO_H - -#include "gamebryosavegameinfo.h" - -class GameGamebryo; - -class Fallout3SaveGameInfo : public GamebryoSaveGameInfo -{ -public: - Fallout3SaveGameInfo(GameGamebryo const *game); - ~Fallout3SaveGameInfo(); - - virtual MOBase::ISaveGame const *getSaveGameInfo(QString const &file) const override; -}; - -#endif // FALLOUT3SAVEGAMEINFO_H diff --git a/src/games/fallout3/src/gamefallout3.cpp b/src/games/fallout3/src/gamefallout3.cpp index 84a7c1ce..275dba6a 100644 --- a/src/games/fallout3/src/gamefallout3.cpp +++ b/src/games/fallout3/src/gamefallout3.cpp @@ -3,9 +3,9 @@ #include "fallout3bsainvalidation.h" #include "fallout3scriptextender.h" #include "fallout3dataarchives.h" -#include "fallout3savegameinfo.h" #include "fallout3moddatachecker.h" #include "fallout3moddatacontent.h" +#include "fallout3savegame.h" #include "executableinfo.h" #include "pluginsetting.h" @@ -13,6 +13,7 @@ #include #include #include +#include #include #include @@ -38,7 +39,7 @@ bool GameFallout3::init(IOrganizer *moInfo) registerFeature(new Fallout3ScriptExtender(this)); registerFeature(new Fallout3DataArchives(myGamesPath())); registerFeature(new Fallout3BSAInvalidation(feature(), this)); - registerFeature(new Fallout3SaveGameInfo(this)); + registerFeature(new GamebryoSaveGameInfo(this)); registerFeature(new GamebryoLocalSavegames(myGamesPath(), "fallout.ini")); registerFeature(new Fallout3ModDataChecker(this)); registerFeature(new Fallout3ModDataContent(this)); @@ -117,8 +118,8 @@ void GameFallout3::initializeProfile(const QDir &path, ProfileSettings settings) } copyToProfile(myGamesPath(), path, "falloutprefs.ini"); - copyToProfile(myGamesPath(), path, "FalloutCustom.ini"); - copyToProfile(myGamesPath(), path, "custom.ini"); + copyToProfile(myGamesPath(), path, "FalloutCustom.ini"); + copyToProfile(myGamesPath(), path, "custom.ini"); copyToProfile(myGamesPath(), path, "GECKCustom.ini"); copyToProfile(myGamesPath(), path, "GECKPrefs.ini"); } @@ -134,6 +135,11 @@ QString GameFallout3::savegameSEExtension() const return ""; } +std::shared_ptr GameFallout3::makeSaveGame(QString filePath) const +{ + return std::make_shared(filePath, this); +} + QString GameFallout3::steamAPPId() const { if (selectedVariant() == "Game Of The Year") { diff --git a/src/games/fallout3/src/gamefallout3.h b/src/games/fallout3/src/gamefallout3.h index 43b38bbf..e77c21fb 100644 --- a/src/games/fallout3/src/gamefallout3.h +++ b/src/games/fallout3/src/gamefallout3.h @@ -23,8 +23,6 @@ public: // IPluginGame interface virtual QList executables() const override; virtual QList executableForcedLoads() const override; virtual void initializeProfile(const QDir &path, ProfileSettings settings) const override; - virtual QString savegameExtension() const override; - virtual QString savegameSEExtension() const override; virtual QString steamAPPId() const override; virtual QStringList primaryPlugins() const override; virtual QStringList gameVariants() const; @@ -48,6 +46,10 @@ public: // IPlugin interface protected: + virtual QString savegameExtension() const override; + virtual QString savegameSEExtension() const override; + std::shared_ptr makeSaveGame(QString filePath) const override; + }; #endif // GAMEFALLOUT3_H From 0462f68054023fc7481b337df9b875f20bbb8983 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Mika=C3=ABl=20Capelle?= Date: Wed, 18 Nov 2020 19:24:38 +0100 Subject: [PATCH 1095/1544] [game_skyrimvr] Update for IPluginGame::listSaves(). --- src/games/skyrimvr/src/gameskyrimvr.cpp | 11 +- src/games/skyrimvr/src/gameskyrimvr.h | 83 +++++---- src/games/skyrimvr/src/skyrimvrsavegame.cpp | 172 +++++++++++------- src/games/skyrimvr/src/skyrimvrsavegame.h | 19 +- .../skyrimvr/src/skyrimvrsavegameinfo.cpp | 18 -- src/games/skyrimvr/src/skyrimvrsavegameinfo.h | 17 -- 6 files changed, 179 insertions(+), 141 deletions(-) delete mode 100644 src/games/skyrimvr/src/skyrimvrsavegameinfo.cpp delete mode 100644 src/games/skyrimvr/src/skyrimvrsavegameinfo.h diff --git a/src/games/skyrimvr/src/gameskyrimvr.cpp b/src/games/skyrimvr/src/gameskyrimvr.cpp index e8bc38d6..3749c1ca 100644 --- a/src/games/skyrimvr/src/gameskyrimvr.cpp +++ b/src/games/skyrimvr/src/gameskyrimvr.cpp @@ -2,14 +2,15 @@ #include "skyrimvrdataarchives.h" #include "skyrimvrscriptextender.h" -#include "skyrimvrsavegameinfo.h" #include "skyrimvrunmanagedmods.h" #include "skyrimvrmoddatachecker.h" #include "skyrimvrmoddatacontent.h" +#include "skyrimvrsavegame.h" #include #include #include +#include #include #include "versioninfo.h" @@ -71,7 +72,7 @@ bool GameSkyrimVR::init(IOrganizer *moInfo) registerFeature(new SkyrimVRDataArchives(myGamesPath())); registerFeature(new GamebryoLocalSavegames(myGamesPath(), "SkyrimVR.ini")); registerFeature(new SkyrimVRModDataChecker(this)); - registerFeature(new SkyrimVRSaveGameInfo(this)); + registerFeature(new GamebryoSaveGameInfo(this)); registerFeature(new SkyrimVRModDataContent(this)); registerFeature(new CreationGamePlugins(moInfo)); registerFeature(new SkyrimVRUnmangedMods(this)); @@ -165,6 +166,12 @@ QString GameSkyrimVR::savegameSEExtension() const return "skse"; } +std::shared_ptr GameSkyrimVR::makeSaveGame(QString filePath) const +{ + return std::make_shared(filePath, this); +} + + QString GameSkyrimVR::steamAPPId() const { return "611670"; diff --git a/src/games/skyrimvr/src/gameskyrimvr.h b/src/games/skyrimvr/src/gameskyrimvr.h index eee89d3e..6fd19ba9 100644 --- a/src/games/skyrimvr/src/gameskyrimvr.h +++ b/src/games/skyrimvr/src/gameskyrimvr.h @@ -8,59 +8,62 @@ class GameSkyrimVR : public GameGamebryo { - Q_OBJECT - Q_PLUGIN_METADATA(IID "com.soundcontactstudio.GameSkyrimVR" FILE "gameskyrimVR.json") + Q_OBJECT + Q_PLUGIN_METADATA(IID "com.soundcontactstudio.GameSkyrimVR" FILE "gameskyrimVR.json") public: - GameSkyrimVR(); + GameSkyrimVR(); - virtual bool init(MOBase::IOrganizer *moInfo) override; + virtual bool init(MOBase::IOrganizer *moInfo) override; public: // IPluginGame interface - virtual QString gameName() const override; + virtual QString gameName() const override; - virtual QList executables() const override; - virtual QList executableForcedLoads() const override; - virtual void initializeProfile(const QDir &path, ProfileSettings settings) const override; - virtual QString savegameExtension() const override; - virtual QString savegameSEExtension() const override; - virtual QString steamAPPId() const override; - virtual QStringList primaryPlugins() const override; - virtual QStringList gameVariants() const override; - virtual QString gameShortName() const override; - virtual QStringList primarySources() const override; - virtual QStringList validShortNames() const override; - virtual QString gameNexusName() const override; - virtual QStringList iniFiles() const override; - virtual QStringList DLCPlugins() const override; - virtual QStringList CCPlugins() const override; - virtual LoadOrderMechanism loadOrderMechanism() const override; - virtual SortMechanism sortMechanism() const override; - virtual int nexusModOrganizerID() const override; - virtual int nexusGameID() const override; - virtual QString getLauncherName() const override; + virtual QList executables() const override; + virtual QList 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 gameShortName() const override; + virtual QStringList primarySources() const override; + virtual QStringList validShortNames() const override; + virtual QString gameNexusName() const override; + virtual QStringList iniFiles() const override; + virtual QStringList DLCPlugins() const override; + virtual QStringList CCPlugins() const override; + virtual LoadOrderMechanism loadOrderMechanism() const override; + virtual SortMechanism sortMechanism() const override; + virtual int nexusModOrganizerID() const override; + virtual int nexusGameID() const override; + virtual QString getLauncherName() const override; - virtual bool isInstalled() const override; - virtual void setGamePath(const QString &path) override; - virtual QDir gameDirectory() 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 settings() const override; + 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 settings() const override; public: // IPluginFileMapper - virtual MappingType mappings() const override; + virtual MappingType mappings() const override; protected: - QDir documentsDirectory() const; - QDir savesDirectory() const; - QFileInfo findInGameFolder(const QString &relativePath) const; - QString myGamesPath() const; - virtual QString identifyGamePath() const override; + + std::shared_ptr makeSaveGame(QString filePath) const override; + QString savegameExtension() const override; + QString savegameSEExtension() const override; + + QDir documentsDirectory() const; + QDir savesDirectory() const; + QFileInfo findInGameFolder(const QString &relativePath) const; + QString myGamesPath() const; + virtual QString identifyGamePath() const override; }; #endif // _GAMESKYRIMVR_H diff --git a/src/games/skyrimvr/src/skyrimvrsavegame.cpp b/src/games/skyrimvr/src/skyrimvrsavegame.cpp index b05b914d..3da7ccd4 100644 --- a/src/games/skyrimvr/src/skyrimvrsavegame.cpp +++ b/src/games/skyrimvr/src/skyrimvrsavegame.cpp @@ -2,72 +2,120 @@ #include -SkyrimVRSaveGame::SkyrimVRSaveGame(QString const &fileName, MOBase::IPluginGame const *game, bool const lightEnabled) : - GamebryoSaveGame(fileName, game, lightEnabled) +#include "gameskyrimvr.h" + +SkyrimVRSaveGame::SkyrimVRSaveGame(QString const &fileName, GameSkyrimVR const *game) : + GamebryoSaveGame(fileName, game, true) { - FileWrapper file(this, "TESV_SAVEGAME"); //10bytes - unsigned long headerSize; - file.read(headerSize); // header size "TESV_SAVEGAME" - file.skip(); // header version 74. Original Skyrim is 79 - file.read(m_SaveNumber); + FileWrapper file(fileName, "TESV_SAVEGAME"); //10bytes - file.read(m_PCName); + unsigned long version; + FILETIME ftime; + fetchInformationFields(file, version, m_PCName, m_PCLevel, m_PCLocation, m_SaveNumber, ftime); - unsigned long temp; - file.read(temp); - m_PCLevel = static_cast(temp); + //A file time is a 64-bit value that represents the number of 100-nanosecond + //intervals that have elapsed since 12:00 A.M. January 1, 1601 Coordinated Universal Time (UTC). + //So we need to convert that to something useful - file.read(m_PCLocation); + //For some reason, the file time is off by about 6 hours. + //So we need to subtract those 6 hours from the filetime. + _ULARGE_INTEGER time; + time.LowPart = ftime.dwLowDateTime; + time.HighPart = ftime.dwHighDateTime; + time.QuadPart -= 2.16e11; + ftime.dwHighDateTime = time.HighPart; + ftime.dwLowDateTime = time.LowPart; - QString timeOfDay; - file.read(timeOfDay); + SYSTEMTIME ctime; + ::FileTimeToSystemTime(&ftime, &ctime); - QString race; - file.read(race); // race name (i.e. BretonRace) - - file.skip(); // Player gender (0 = male) - file.skip(2); // experience gathered, experience required - - FILETIME ftime; - file.read(ftime); //filetime - //A file time is a 64-bit value that represents the number of 100-nanosecond - //intervals that have elapsed since 12:00 A.M. January 1, 1601 Coordinated Universal Time (UTC). - //So we need to convert that to something useful - - //For some reason, the file time is off by about 6 hours. - //So we need to subtract those 6 hours from the filetime. - _ULARGE_INTEGER time; - time.LowPart = ftime.dwLowDateTime; - time.HighPart = ftime.dwHighDateTime; - time.QuadPart -= 2.16e11; - ftime.dwHighDateTime = time.HighPart; - ftime.dwLowDateTime = time.LowPart; - - SYSTEMTIME ctime; - ::FileTimeToSystemTime(&ftime, &ctime); - - setCreationTime(ctime); - - unsigned long width; - unsigned long height; - file.read(width); - file.read(height); - - file.read(m_CompressionType); - - file.readImage(width, height, 320, true); - - file.openCompressedData(); - - uint8_t saveGameVersion = file.readChar(); - uint8_t pluginInfoSize = file.readChar(); - uint16_t other = file.readShort(); //Unknown - - file.readPlugins(1); // Just empty data - - if (saveGameVersion >= 78) { - file.readLightPlugins(); - } - - file.closeCompressedData(); + setCreationTime(ctime); } + + +void SkyrimVRSaveGame::fetchInformationFields( + FileWrapper& file, + unsigned long& version, + QString& playerName, + unsigned short& playerLevel, + QString& playerLocation, + unsigned long& saveNumber, + FILETIME& creationTime) const +{ + unsigned long headerSize; + file.read(headerSize); // header size "TESV_SAVEGAME" + file.read(version); + file.read(saveNumber); + + file.read(playerName); + + unsigned long temp; + file.read(temp); + playerLevel = static_cast(temp); + + file.read(playerLocation); + + QString timeOfDay; + file.read(timeOfDay); + + QString race; + file.read(race); // race name (i.e. BretonRace) + + file.skip(); // Player gender (0 = male) + file.skip(2); // experience gathered, experience required + + file.read(creationTime); //filetime +} + +std::unique_ptr SkyrimVRSaveGame::fetchDataFields() const +{ + FileWrapper file(getFilepath(), "TESV_SAVEGAME"); //10bytes + + unsigned long version = 0; + { + QString dummyName, dummyLocation; + unsigned short dummyLevel; + unsigned long dummySaveNumber; + FILETIME dummyTime; + + fetchInformationFields(file, version, dummyName, dummyLevel, + dummyLocation, dummySaveNumber, dummyTime); + } + + std::unique_ptr fields = std::make_unique(); + + unsigned long width; + unsigned long height; + file.read(width); + file.read(height); + + bool alpha = false; + + // compatibility between LE and SE: + // SE has an additional uin16_t for compression + // SE uses an alpha channel, whereas LE does not + if (version == 12) { + uint16_t compressionType; + file.read(compressionType); + file.setCompressionType(compressionType); + alpha = true; + } + + fields->Screenshot = file.readImage(width, height, 320, alpha); + + file.openCompressedData(); + + uint8_t saveGameVersion = file.readChar(); + uint8_t pluginInfoSize = file.readChar(); + uint16_t other = file.readShort(); //Unknown + + fields->Plugins = file.readPlugins(1); // Just empty data + + if (saveGameVersion >= 78) { + fields->LightPlugins = file.readLightPlugins(); + } + + file.closeCompressedData(); + + return fields; +} \ No newline at end of file diff --git a/src/games/skyrimvr/src/skyrimvrsavegame.h b/src/games/skyrimvr/src/skyrimvrsavegame.h index 5f274dac..db8b95da 100644 --- a/src/games/skyrimvr/src/skyrimvrsavegame.h +++ b/src/games/skyrimvr/src/skyrimvrsavegame.h @@ -3,12 +3,27 @@ #include "gamebryosavegame.h" -namespace MOBase { class IPluginGame; } +#include + +class GameSkyrimVR; class SkyrimVRSaveGame : public GamebryoSaveGame { public: - SkyrimVRSaveGame(QString const &fileName, MOBase::IPluginGame const *game, bool const lightEnabled = true); + SkyrimVRSaveGame(QString const &fileName, GameSkyrimVR const *game); + +protected: + + // Fetch easy-to-access information. + void fetchInformationFields(FileWrapper& wrapper, + unsigned long& version, + QString& playerName, + unsigned short& playerLevel, + QString& playerLocation, + unsigned long& saveNumber, + FILETIME& creationTime) const; + + std::unique_ptr fetchDataFields() const override; }; #endif // _SKYRIMVRSAVEGAME_H diff --git a/src/games/skyrimvr/src/skyrimvrsavegameinfo.cpp b/src/games/skyrimvr/src/skyrimvrsavegameinfo.cpp deleted file mode 100644 index 9f1bd18f..00000000 --- a/src/games/skyrimvr/src/skyrimvrsavegameinfo.cpp +++ /dev/null @@ -1,18 +0,0 @@ -#include "skyrimvrsavegameinfo.h" - -#include "skyrimvrsavegame.h" -#include "gamegamebryo.h" - -SkyrimVRSaveGameInfo::SkyrimVRSaveGameInfo(GameGamebryo const *game) : - GamebryoSaveGameInfo(game) -{ -} - -SkyrimVRSaveGameInfo::~SkyrimVRSaveGameInfo() -{ -} - -const MOBase::ISaveGame *SkyrimVRSaveGameInfo::getSaveGameInfo(const QString &file) const -{ - return new SkyrimVRSaveGame(file, m_Game); -} diff --git a/src/games/skyrimvr/src/skyrimvrsavegameinfo.h b/src/games/skyrimvr/src/skyrimvrsavegameinfo.h deleted file mode 100644 index 677ec1dc..00000000 --- a/src/games/skyrimvr/src/skyrimvrsavegameinfo.h +++ /dev/null @@ -1,17 +0,0 @@ -#ifndef _SKYRIMVRSAVEGAMEINFO_H -#define _SKYRIMVRSAVEGAMEINFO_H - -#include "gamebryosavegameinfo.h" - -class GameGamebryo; - -class SkyrimVRSaveGameInfo : public GamebryoSaveGameInfo -{ -public: - SkyrimVRSaveGameInfo(GameGamebryo const *game); - ~SkyrimVRSaveGameInfo(); - - virtual MOBase::ISaveGame const *getSaveGameInfo(QString const &file) const override; -}; - -#endif // _SKYRIMVRSAVEGAMEINFO_H From 27fbe5d2c31eb03990d28eba4db139acbe39cc20 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Mika=C3=ABl=20Capelle?= Date: Wed, 18 Nov 2020 19:24:38 +0100 Subject: [PATCH 1096/1544] [game_ttw] Update for IPluginGame::listSaves(). --- src/games/ttw/src/falloutttwsavegame.cpp | 57 ++++++++++++++------ src/games/ttw/src/falloutttwsavegame.h | 18 ++++++- src/games/ttw/src/falloutttwsavegameinfo.cpp | 18 ------- src/games/ttw/src/falloutttwsavegameinfo.h | 17 ------ src/games/ttw/src/gamefalloutttw.cpp | 11 +++- src/games/ttw/src/gamefalloutttw.h | 6 ++- 6 files changed, 71 insertions(+), 56 deletions(-) delete mode 100644 src/games/ttw/src/falloutttwsavegameinfo.cpp delete mode 100644 src/games/ttw/src/falloutttwsavegameinfo.h diff --git a/src/games/ttw/src/falloutttwsavegame.cpp b/src/games/ttw/src/falloutttwsavegame.cpp index 32bc2545..910dcc81 100644 --- a/src/games/ttw/src/falloutttwsavegame.cpp +++ b/src/games/ttw/src/falloutttwsavegame.cpp @@ -1,10 +1,25 @@ #include "falloutttwsavegame.h" -FalloutTTWSaveGame::FalloutTTWSaveGame(QString const &fileName, MOBase::IPluginGame const *game) : +#include "gamefalloutttw.h" + +FalloutTTWSaveGame::FalloutTTWSaveGame(QString const &fileName, GameFalloutTTW const *game) : GamebryoSaveGame(fileName, game) { - FileWrapper file(this, "FO3SAVEGAME"); + FileWrapper file(getFilepath(), "FO3SAVEGAME"); + unsigned long width, height; + fetchInformationFields(file, width, height, m_SaveNumber, m_PCName, m_PCLevel, m_PCLocation); +} + +void FalloutTTWSaveGame::fetchInformationFields( + FileWrapper& file, + unsigned long& width, + unsigned long& height, + unsigned long& saveNumber, + QString& playerName, + unsigned short& playerLevel, + QString& playerLocation) const +{ file.skip(); //Save header size file.skip(); //File version? @@ -20,33 +35,45 @@ FalloutTTWSaveGame::FalloutTTWSaveGame(QString const &fileName, MOBase::IPluginG file.setHasFieldMarkers(true); file.setPluginString(GamebryoSaveGame::StringType::TYPE_BZSTRING); - unsigned long width; file.read(width); - - unsigned long height; file.read(height); - - file.read(m_SaveNumber); - - file.read(m_PCName); + file.read(saveNumber); + file.read(playerName); QString whatthis; file.read(whatthis); long level; file.read(level); - m_PCLevel = level; + playerLevel = level; + file.read(playerLocation); +} - file.read(m_PCLocation); +std::unique_ptr FalloutTTWSaveGame::fetchDataFields() const +{ + FileWrapper file(getFilepath(), "FO3SAVEGAME"); + + std::unique_ptr fields = std::make_unique(); + + unsigned long width, height; + { + QString dummyName, dummyLocation; + unsigned short dummyLevel; + unsigned long dummySaveNumber; + + fetchInformationFields(file, width, height, + dummySaveNumber, dummyName, dummyLevel, dummyLocation); + } QString playtime; file.read(playtime); - file.readImage(width, height, 256); + fields->Screenshot = file.readImage(width, height, 256); - file.skip(5); // unknown byte, size of plugin data + file.skip(5); // unknown (1 byte), plugin size (4 bytes) - //Abstract this file.setPluginString(GamebryoSaveGame::StringType::TYPE_BSTRING); - file.readPlugins(); + fields->Plugins = file.readPlugins(); + + return fields; } diff --git a/src/games/ttw/src/falloutttwsavegame.h b/src/games/ttw/src/falloutttwsavegame.h index 995c7477..0344eb23 100644 --- a/src/games/ttw/src/falloutttwsavegame.h +++ b/src/games/ttw/src/falloutttwsavegame.h @@ -3,12 +3,26 @@ #include "gamebryosavegame.h" -namespace MOBase { class IPluginGame; } +class GameFalloutTTW; class FalloutTTWSaveGame : public GamebryoSaveGame { public: - FalloutTTWSaveGame(QString const &fileName, MOBase::IPluginGame const *game); + FalloutTTWSaveGame(QString const &fileName, GameFalloutTTW const *game); + +protected: + + // Fetch easy-to-access information. + void fetchInformationFields( + FileWrapper& wrapper, + unsigned long& width, + unsigned long& height, + unsigned long& saveNumber, + QString& playerName, + unsigned short& playerLevel, + QString& playerLocation) const; + + std::unique_ptr fetchDataFields() const override; }; #endif // FALLOUTTTWSAVEGAME_H diff --git a/src/games/ttw/src/falloutttwsavegameinfo.cpp b/src/games/ttw/src/falloutttwsavegameinfo.cpp deleted file mode 100644 index 3535f637..00000000 --- a/src/games/ttw/src/falloutttwsavegameinfo.cpp +++ /dev/null @@ -1,18 +0,0 @@ -#include "falloutttwsavegameinfo.h" - -#include "falloutttwsavegame.h" -#include "gamegamebryo.h" - -FalloutTTWSaveGameInfo::FalloutTTWSaveGameInfo(GameGamebryo const *game) : - GamebryoSaveGameInfo(game) -{ -} - -FalloutTTWSaveGameInfo::~FalloutTTWSaveGameInfo() -{ -} - -MOBase::ISaveGame const *FalloutTTWSaveGameInfo::getSaveGameInfo(QString const &file) const -{ - return new FalloutTTWSaveGame(file, m_Game); -} diff --git a/src/games/ttw/src/falloutttwsavegameinfo.h b/src/games/ttw/src/falloutttwsavegameinfo.h deleted file mode 100644 index 46df7a83..00000000 --- a/src/games/ttw/src/falloutttwsavegameinfo.h +++ /dev/null @@ -1,17 +0,0 @@ -#ifndef FALLOUTTTWSAVEGAMEINFO_H -#define FALLOUTTTWSAVEGAMEINFO_H - -#include "gamebryosavegameinfo.h" - -class GameGamebryo; - -class FalloutTTWSaveGameInfo : public GamebryoSaveGameInfo -{ -public: - FalloutTTWSaveGameInfo(GameGamebryo const *game); - ~FalloutTTWSaveGameInfo(); - - virtual MOBase::ISaveGame const *getSaveGameInfo(QString const &file) const override; - -}; -#endif // FALLOUTTTWSAVEGAMEINFO_H diff --git a/src/games/ttw/src/gamefalloutttw.cpp b/src/games/ttw/src/gamefalloutttw.cpp index 6eafa076..b32e92c5 100644 --- a/src/games/ttw/src/gamefalloutttw.cpp +++ b/src/games/ttw/src/gamefalloutttw.cpp @@ -2,16 +2,17 @@ #include "falloutttwbsainvalidation.h" #include "falloutttwdataarchives.h" -#include "falloutttwsavegameinfo.h" #include "falloutttwscriptextender.h" #include "falloutttwmoddatachecker.h" #include "falloutttwmoddatacontent.h" +#include "falloutttwsavegame.h" #include "executableinfo.h" #include "pluginsetting.h" #include "versioninfo.h" #include #include +#include #include #include @@ -45,7 +46,7 @@ bool GameFalloutTTW::init(IOrganizer *moInfo) registerFeature(new FalloutTTWScriptExtender(this)); registerFeature(new FalloutTTWDataArchives(myGamesPath())); registerFeature(new FalloutTTWBSAInvalidation(feature(), this)); - registerFeature(new FalloutTTWSaveGameInfo(this)); + registerFeature(new GamebryoSaveGameInfo(this)); registerFeature(new GamebryoLocalSavegames(myGamesPath(), "fallout.ini")); registerFeature(new FalloutTTWModDataChecker(this)); registerFeature(new FalloutTTWModDataContent(this)); @@ -140,6 +141,12 @@ QString GameFalloutTTW::savegameSEExtension() const return "nvse"; } +std::shared_ptr GameFalloutTTW::makeSaveGame(QString filePath) const +{ + return std::make_shared(filePath, this); +} + + QString GameFalloutTTW::steamAPPId() const { return "22380"; diff --git a/src/games/ttw/src/gamefalloutttw.h b/src/games/ttw/src/gamefalloutttw.h index 3305ddac..95d20424 100644 --- a/src/games/ttw/src/gamefalloutttw.h +++ b/src/games/ttw/src/gamefalloutttw.h @@ -26,8 +26,6 @@ public: // IPluginGame interface virtual QList executables() const override; virtual QList executableForcedLoads() const override; virtual void initializeProfile(const QDir &path, ProfileSettings settings) const override; - virtual QString savegameExtension() const override; - virtual QString savegameSEExtension() const override; virtual QString steamAPPId() const override; virtual QStringList primaryPlugins() const override; virtual QString binaryName() const override; @@ -57,6 +55,10 @@ public: // IPluginFileMapper interface protected: + virtual QString savegameExtension() const override; + virtual QString savegameSEExtension() const override; + std::shared_ptr makeSaveGame(QString filePath) const override; + virtual QString identifyGamePath() const override; }; From a2f80c3180eb7b1ef22e8e052c222c1f492e2f87 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Mika=C3=ABl=20Capelle?= Date: Wed, 18 Nov 2020 19:24:38 +0100 Subject: [PATCH 1097/1544] [game_skyrimse] Update for IPluginGame::listSaves(). --- src/games/skyrimse/src/gameskyrimse.cpp | 10 +- src/games/skyrimse/src/gameskyrimse.h | 77 +++++++------ src/games/skyrimse/src/skyrimsesavegame.cpp | 106 ++++++++++++------ src/games/skyrimse/src/skyrimsesavegame.h | 17 ++- .../skyrimse/src/skyrimsesavegameinfo.cpp | 19 ---- src/games/skyrimse/src/skyrimsesavegameinfo.h | 17 --- 6 files changed, 134 insertions(+), 112 deletions(-) delete mode 100644 src/games/skyrimse/src/skyrimsesavegameinfo.cpp delete mode 100644 src/games/skyrimse/src/skyrimsesavegameinfo.h diff --git a/src/games/skyrimse/src/gameskyrimse.cpp b/src/games/skyrimse/src/gameskyrimse.cpp index 08880fbf..8815f345 100644 --- a/src/games/skyrimse/src/gameskyrimse.cpp +++ b/src/games/skyrimse/src/gameskyrimse.cpp @@ -2,13 +2,14 @@ #include "skyrimsedataarchives.h" #include "skyrimsescriptextender.h" -#include "skyrimsesavegameinfo.h" #include "skyrimseunmanagedmods.h" #include "skyrimsemoddatachecker.h" #include "skyrimsemoddatacontent.h" +#include "skyrimsesavegame.h" #include #include +#include #include #include #include "versioninfo.h" @@ -73,7 +74,7 @@ bool GameSkyrimSE::init(IOrganizer *moInfo) registerFeature(new GamebryoLocalSavegames(myGamesPath(), "Skyrimcustom.ini")); registerFeature(new SkyrimSEModDataChecker(this)); registerFeature(new SkyrimSEModDataContent(this)); - registerFeature(new SkyrimSESaveGameInfo(this)); + registerFeature(new GamebryoSaveGameInfo(this)); registerFeature(new CreationGamePlugins(moInfo)); registerFeature(new SkyrimSEUnmangedMods(this)); @@ -169,6 +170,11 @@ QString GameSkyrimSE::savegameSEExtension() const return "skse"; } +std::shared_ptr GameSkyrimSE::makeSaveGame(QString filePath) const +{ + return std::make_shared(filePath, this); +} + QString GameSkyrimSE::steamAPPId() const { return "489830"; diff --git a/src/games/skyrimse/src/gameskyrimse.h b/src/games/skyrimse/src/gameskyrimse.h index 2be0e1b9..625cae9c 100644 --- a/src/games/skyrimse/src/gameskyrimse.h +++ b/src/games/skyrimse/src/gameskyrimse.h @@ -9,60 +9,63 @@ class GameSkyrimSE : public GameGamebryo { - Q_OBJECT + Q_OBJECT - Q_PLUGIN_METADATA(IID "com.soundcontactstudio.GameSkyrimSE" FILE "gameskyrimse.json") + Q_PLUGIN_METADATA(IID "com.soundcontactstudio.GameSkyrimSE" FILE "gameskyrimse.json") public: - GameSkyrimSE(); + GameSkyrimSE(); - virtual bool init(MOBase::IOrganizer *moInfo) override; + virtual bool init(MOBase::IOrganizer *moInfo) override; public: // IPluginGame interface - virtual QString gameName() const override; + virtual QString gameName() const override; - virtual QList executables() const override; - virtual QList executableForcedLoads() const override; - virtual void initializeProfile(const QDir &path, ProfileSettings settings) const override; - virtual QString savegameExtension() const override; - virtual QString savegameSEExtension() const override; - virtual QString steamAPPId() const override; - virtual QStringList primaryPlugins() const override; - virtual QStringList gameVariants() const override; - virtual QString gameShortName() const override; - virtual QString gameNexusName() const override; - virtual QStringList validShortNames() const override; - virtual QStringList iniFiles() const override; - virtual QStringList DLCPlugins() const override; - virtual QStringList CCPlugins() const override; - virtual LoadOrderMechanism loadOrderMechanism() const override; - virtual int nexusModOrganizerID() const override; - virtual int nexusGameID() const override; + virtual QList executables() const override; + virtual QList 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 gameShortName() const override; + virtual QString gameNexusName() const override; + virtual QStringList validShortNames() const override; + virtual QStringList iniFiles() const override; + virtual QStringList DLCPlugins() const override; + virtual QStringList CCPlugins() const override; + virtual LoadOrderMechanism loadOrderMechanism() const override; + virtual int nexusModOrganizerID() const override; + virtual int nexusGameID() const override; - virtual bool isInstalled() const override; - virtual void setGamePath(const QString &path) override; - virtual QDir gameDirectory() 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 settings() const override; - virtual MappingType mappings() const override; + 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 settings() const override; + virtual MappingType mappings() const override; protected: - QDir documentsDirectory() const; - QDir savesDirectory() const; - QFileInfo findInGameFolder(const QString &relativePath) const; - QString myGamesPath() const; - virtual QString identifyGamePath() const override; + std::shared_ptr makeSaveGame(QString filePath) const override; + QString savegameExtension() const override; + QString savegameSEExtension() const override; + + QDir documentsDirectory() const; + QDir savesDirectory() const; + QFileInfo findInGameFolder(const QString &relativePath) const; + QString myGamesPath() const; + + virtual QString identifyGamePath() const override; }; diff --git a/src/games/skyrimse/src/skyrimsesavegame.cpp b/src/games/skyrimse/src/skyrimsesavegame.cpp index c4a807e9..ca727afe 100644 --- a/src/games/skyrimse/src/skyrimsesavegame.cpp +++ b/src/games/skyrimse/src/skyrimsesavegame.cpp @@ -2,41 +2,21 @@ #include -SkyrimSESaveGame::SkyrimSESaveGame(QString const &fileName, MOBase::IPluginGame const *game, bool const lightEnabled) : - GamebryoSaveGame(fileName, game, lightEnabled) +SkyrimSESaveGame::SkyrimSESaveGame(QString const &fileName, GameSkyrimSE const *game) : + GamebryoSaveGame(fileName, game, true) { - FileWrapper file(this, "TESV_SAVEGAME"); //10bytes - unsigned long headerSize; - file.read(headerSize); // header size "TESV_SAVEGAME" - unsigned long version = 0; - file.read(version); - file.read(m_SaveNumber); - - file.read(m_PCName); - - unsigned long temp; - file.read(temp); - m_PCLevel = static_cast(temp); - - file.read(m_PCLocation); - - QString timeOfDay; - file.read(timeOfDay); - - QString race; - file.read(race); // race name (i.e. BretonRace) - - file.skip(); // Player gender (0 = male) - file.skip(2); // experience gathered, experience required + FileWrapper file(fileName, "TESV_SAVEGAME"); //10bytes + unsigned long version; FILETIME ftime; - file.read(ftime); //filetime - //A file time is a 64-bit value that represents the number of 100-nanosecond - //intervals that have elapsed since 12:00 A.M. January 1, 1601 Coordinated Universal Time (UTC). - //So we need to convert that to something useful + fetchInformationFields(file, version, m_PCName, m_PCLevel, m_PCLocation, m_SaveNumber, ftime); - //For some reason, the file time is off by about 6 hours. - //So we need to subtract those 6 hours from the filetime. + //A file time is a 64-bit value that represents the number of 100-nanosecond + //intervals that have elapsed since 12:00 A.M. January 1, 1601 Coordinated Universal Time (UTC). + //So we need to convert that to something useful + + //For some reason, the file time is off by about 6 hours. + //So we need to subtract those 6 hours from the filetime. _ULARGE_INTEGER time; time.LowPart = ftime.dwLowDateTime; time.HighPart = ftime.dwHighDateTime; @@ -48,6 +28,56 @@ SkyrimSESaveGame::SkyrimSESaveGame(QString const &fileName, MOBase::IPluginGame ::FileTimeToSystemTime(&ftime, &ctime); setCreationTime(ctime); +} + +void SkyrimSESaveGame::fetchInformationFields( + FileWrapper& file, + unsigned long& version, + QString& playerName, + unsigned short& playerLevel, + QString& playerLocation, + unsigned long& saveNumber, + FILETIME& creationTime) const +{ + unsigned long headerSize; + file.read(headerSize); // header size "TESV_SAVEGAME" + file.read(version); + file.read(saveNumber); + file.read(playerName); + + unsigned long temp; + file.read(temp); + playerLevel = static_cast(temp); + file.read(playerLocation); + + QString timeOfDay; + file.read(timeOfDay); + + QString race; + file.read(race); // race name (i.e. BretonRace) + + file.skip(); // Player gender (0 = male) + file.skip(2); // experience gathered, experience required + + file.read(creationTime); //filetime +} + +std::unique_ptr SkyrimSESaveGame::fetchDataFields() const +{ + FileWrapper file(getFilepath(), "TESV_SAVEGAME"); //10bytes + + unsigned long version = 0; + { + QString dummyName, dummyLocation; + unsigned short dummyLevel; + unsigned long dummySaveNumber; + FILETIME dummyTime; + + fetchInformationFields(file, version, dummyName, dummyLevel, + dummyLocation, dummySaveNumber, dummyTime); + } + + std::unique_ptr fields = std::make_unique(); unsigned long width; unsigned long height; @@ -60,11 +90,13 @@ SkyrimSESaveGame::SkyrimSESaveGame(QString const &fileName, MOBase::IPluginGame // SE has an additional uin16_t for compression // SE uses an alpha channel, whereas LE does not if (version == 12) { - file.read(m_CompressionType); + uint16_t compressionType; + file.read(compressionType); + file.setCompressionType(compressionType); alpha = true; } - file.readImage(width, height, 320, alpha); + fields->Screenshot = file.readImage(width, height, 320, alpha); file.openCompressedData(); @@ -72,11 +104,13 @@ SkyrimSESaveGame::SkyrimSESaveGame(QString const &fileName, MOBase::IPluginGame uint8_t pluginInfoSize = file.readChar(); uint16_t other = file.readShort(); //Unknown - file.readPlugins(1); // Just empty data + fields->Plugins = file.readPlugins(1); // Just empty data if (saveGameVersion >= 78) { - file.readLightPlugins(); + fields->LightPlugins = file.readLightPlugins(); } file.closeCompressedData(); -} + + return fields; +} \ No newline at end of file diff --git a/src/games/skyrimse/src/skyrimsesavegame.h b/src/games/skyrimse/src/skyrimsesavegame.h index 0fe7c3d7..ec2f1549 100644 --- a/src/games/skyrimse/src/skyrimsesavegame.h +++ b/src/games/skyrimse/src/skyrimsesavegame.h @@ -2,13 +2,28 @@ #define _SKYRIMSESAVEGAME_H #include "gamebryosavegame.h" +#include "gameskyrimse.h" namespace MOBase { class IPluginGame; } class SkyrimSESaveGame : public GamebryoSaveGame { public: - SkyrimSESaveGame(QString const &fileName, MOBase::IPluginGame const *game, bool const lightEnabled = true); + SkyrimSESaveGame(QString const &fileName, GameSkyrimSE const *game); + +protected: + + // Fetch easy-to-access information. + void fetchInformationFields(FileWrapper& wrapper, + unsigned long& version, + QString& playerName, + unsigned short& playerLevel, + QString& playerLocation, + unsigned long& saveNumber, + FILETIME& creationTime) const; + + std::unique_ptr fetchDataFields() const override; + }; #endif // _SKYRIMSESAVEGAME_H diff --git a/src/games/skyrimse/src/skyrimsesavegameinfo.cpp b/src/games/skyrimse/src/skyrimsesavegameinfo.cpp deleted file mode 100644 index c5339c07..00000000 --- a/src/games/skyrimse/src/skyrimsesavegameinfo.cpp +++ /dev/null @@ -1,19 +0,0 @@ -#include "skyrimSEsavegameinfo.h" - -#include "skyrimSEsavegame.h" -#include "gamegamebryo.h" - -SkyrimSESaveGameInfo::SkyrimSESaveGameInfo(GameGamebryo const *game) : - GamebryoSaveGameInfo(game) -{ -} - -SkyrimSESaveGameInfo::~SkyrimSESaveGameInfo() -{ -} - -const MOBase::ISaveGame *SkyrimSESaveGameInfo::getSaveGameInfo(const QString &file) const -{ - return new SkyrimSESaveGame(file, m_Game); -} - diff --git a/src/games/skyrimse/src/skyrimsesavegameinfo.h b/src/games/skyrimse/src/skyrimsesavegameinfo.h deleted file mode 100644 index c1a8fe3f..00000000 --- a/src/games/skyrimse/src/skyrimsesavegameinfo.h +++ /dev/null @@ -1,17 +0,0 @@ -#ifndef _SKYRIMSAVEGAMEINFO_H -#define _SKYRIMSAVEGAMEINFO_H - -#include "gamebryosavegameinfo.h" - -class GameGamebryo; - -class SkyrimSESaveGameInfo : public GamebryoSaveGameInfo -{ -public: - SkyrimSESaveGameInfo(GameGamebryo const *game); - ~SkyrimSESaveGameInfo(); - - virtual MOBase::ISaveGame const *getSaveGameInfo(QString const &file) const override; -}; - -#endif // _SKYRIMSAVEGAMEINFO_H From 443159fafd5f3ddf31d4adfafa75021c2a8bce62 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Mika=C3=ABl=20Capelle?= Date: Wed, 18 Nov 2020 19:24:38 +0100 Subject: [PATCH 1098/1544] [game_skyrim] Update for IPluginGame::listSaves(). --- src/games/skyrim/src/gameskyrim.cpp | 10 +++- src/games/skyrim/src/gameskyrim.h | 8 ++- src/games/skyrim/src/skyrimsavegame.cpp | 64 +++++++++++++++------ src/games/skyrim/src/skyrimsavegame.h | 18 +++++- src/games/skyrim/src/skyrimsavegameinfo.cpp | 19 ------ src/games/skyrim/src/skyrimsavegameinfo.h | 17 ------ 6 files changed, 79 insertions(+), 57 deletions(-) delete mode 100644 src/games/skyrim/src/skyrimsavegameinfo.cpp delete mode 100644 src/games/skyrim/src/skyrimsavegameinfo.h diff --git a/src/games/skyrim/src/gameskyrim.cpp b/src/games/skyrim/src/gameskyrim.cpp index d60175d1..f68c5c40 100644 --- a/src/games/skyrim/src/gameskyrim.cpp +++ b/src/games/skyrim/src/gameskyrim.cpp @@ -3,10 +3,10 @@ #include "skyrimbsainvalidation.h" #include "skyrimscriptextender.h" #include "skyrimdataarchives.h" -#include "skyrimsavegameinfo.h" #include "skyrimgameplugins.h" #include "skyrimmoddatachecker.h" #include "skyrimmoddatacontent.h" +#include "skyrimsavegame.h" #include "executableinfo.h" #include "pluginsetting.h" @@ -14,6 +14,7 @@ #include #include #include +#include #include #include @@ -44,7 +45,7 @@ bool GameSkyrim::init(IOrganizer *moInfo) registerFeature(new SkyrimScriptExtender(this)); registerFeature(new SkyrimDataArchives(myGamesPath())); registerFeature(new SkyrimBSAInvalidation(feature(), this)); - registerFeature(new SkyrimSaveGameInfo(this)); + registerFeature(new GamebryoSaveGameInfo(this)); registerFeature(new GamebryoLocalSavegames(myGamesPath(), "skyrim.ini")); registerFeature(new SkyrimModDataChecker(this)); registerFeature(new SkyrimModDataContent(this)); @@ -137,6 +138,11 @@ QString GameSkyrim::savegameSEExtension() const return "skse"; } +std::shared_ptr GameSkyrim::makeSaveGame(QString filepath) const +{ + return std::make_shared(filepath, this); +} + QString GameSkyrim::steamAPPId() const { return "72850"; diff --git a/src/games/skyrim/src/gameskyrim.h b/src/games/skyrim/src/gameskyrim.h index e2ff3a46..6764777d 100644 --- a/src/games/skyrim/src/gameskyrim.h +++ b/src/games/skyrim/src/gameskyrim.h @@ -25,8 +25,6 @@ public: // IPluginGame interface virtual QList executables() const override; virtual QList executableForcedLoads() const override; virtual void initializeProfile(const QDir &path, ProfileSettings settings) const override; - virtual QString savegameExtension() const override; - virtual QString savegameSEExtension() const override; virtual QString steamAPPId() const override; virtual QStringList primaryPlugins() const override; virtual QString binaryName() const override; @@ -47,6 +45,12 @@ public: // IPlugin interface virtual QString description() const override; virtual MOBase::VersionInfo version() const override; virtual QList settings() const override; + +protected: + + virtual QString savegameExtension() const override; + virtual QString savegameSEExtension() const override; + virtual std::shared_ptr makeSaveGame(QString filepath) const override; }; #endif // GAMESKYRIM_H diff --git a/src/games/skyrim/src/skyrimsavegame.cpp b/src/games/skyrim/src/skyrimsavegame.cpp index fa3f8e6d..0797b20e 100644 --- a/src/games/skyrim/src/skyrimsavegame.cpp +++ b/src/games/skyrim/src/skyrimsavegame.cpp @@ -2,21 +2,43 @@ #include -SkyrimSaveGame::SkyrimSaveGame(QString const &fileName, MOBase::IPluginGame const *game) : +#include "gameskyrim.h" + +SkyrimSaveGame::SkyrimSaveGame(QString const &fileName, GameSkyrim const *game) : GamebryoSaveGame(fileName, game) { - FileWrapper file(this, "TESV_SAVEGAME"); + FileWrapper file(getFilepath(), "TESV_SAVEGAME"); + + FILETIME ftime; + fetchInformationFields(file, m_SaveNumber, m_PCName, m_PCLevel, m_PCLocation, ftime); + + //A file time is a 64-bit value that represents the number of 100-nanosecond + //intervals that have elapsed since 12:00 A.M. January 1, 1601 Coordinated Universal Time (UTC). + //So we need to convert that to something useful + SYSTEMTIME ctime; + ::FileTimeToSystemTime(&ftime, &ctime); + setCreationTime(ctime); +} + + +void SkyrimSaveGame::fetchInformationFields(FileWrapper& file, + unsigned long& saveNumber, + QString& playerName, + unsigned short& playerLevel, + QString& playerLocation, + FILETIME& creationTime) const +{ file.skip(); // header size file.skip(); // header version - file.read(m_SaveNumber); + file.read(saveNumber); - file.read(m_PCName); + file.read(playerName); unsigned long temp; file.read(temp); - m_PCLevel = static_cast(temp); + playerLevel = static_cast(temp); - file.read(m_PCLocation); + file.read(playerLocation); QString timeOfDay; file.read(timeOfDay); @@ -27,20 +49,30 @@ SkyrimSaveGame::SkyrimSaveGame(QString const &fileName, MOBase::IPluginGame cons file.skip(); // Player gender (0 = male) file.skip(2); // experience gathered, experience required - FILETIME ftime; - file.read(ftime); - //A file time is a 64-bit value that represents the number of 100-nanosecond - //intervals that have elapsed since 12:00 A.M. January 1, 1601 Coordinated Universal Time (UTC). - //So we need to convert that to something useful - SYSTEMTIME ctime; - ::FileTimeToSystemTime(&ftime, &ctime); + file.read(creationTime); +} - setCreationTime(ctime); +std::unique_ptr SkyrimSaveGame::fetchDataFields() const +{ + FileWrapper file(getFilepath(), "TESV_SAVEGAME"); + std::unique_ptr fields = std::make_unique(); - file.readImage(); + { + QString dummyName, dummyLocation; + unsigned short dummyLevel; + unsigned long dummySaveNumber; + FILETIME dummyTime; + + fetchInformationFields(file, dummySaveNumber, dummyName, dummyLevel, + dummyLocation, dummyTime); + } + + fields->Screenshot = file.readImage(); file.skip(); // form version file.skip(); // plugin info size - file.readPlugins(); + fields->Plugins = file.readPlugins(); + + return fields; } diff --git a/src/games/skyrim/src/skyrimsavegame.h b/src/games/skyrim/src/skyrimsavegame.h index 77740ba9..235f6dcd 100644 --- a/src/games/skyrim/src/skyrimsavegame.h +++ b/src/games/skyrim/src/skyrimsavegame.h @@ -3,12 +3,28 @@ #include "gamebryosavegame.h" +#include + namespace MOBase { class IPluginGame; } +class GameSkyrim; + class SkyrimSaveGame : public GamebryoSaveGame { public: - SkyrimSaveGame(QString const &fileName, MOBase::IPluginGame const *game); + SkyrimSaveGame(QString const &fileName, GameSkyrim const *game); + +protected: + + // Fetch easy-to-access information. + void fetchInformationFields(FileWrapper& wrapper, + unsigned long& saveNumber, + QString& playerName, + unsigned short& playerLevel, + QString& playerLocation, + FILETIME& creationTime) const; + + std::unique_ptr fetchDataFields() const override; }; #endif // SKYRIMSAVEGAME_H diff --git a/src/games/skyrim/src/skyrimsavegameinfo.cpp b/src/games/skyrim/src/skyrimsavegameinfo.cpp deleted file mode 100644 index 558b83b9..00000000 --- a/src/games/skyrim/src/skyrimsavegameinfo.cpp +++ /dev/null @@ -1,19 +0,0 @@ -#include "skyrimsavegameinfo.h" - -#include "skyrimsavegame.h" -#include "gamegamebryo.h" - -SkyrimSaveGameInfo::SkyrimSaveGameInfo(GameGamebryo const *game) : - GamebryoSaveGameInfo(game) -{ -} - -SkyrimSaveGameInfo::~SkyrimSaveGameInfo() -{ -} - - -MOBase::ISaveGame const *SkyrimSaveGameInfo::getSaveGameInfo(QString const &file) const -{ - return new SkyrimSaveGame(file, m_Game); -} diff --git a/src/games/skyrim/src/skyrimsavegameinfo.h b/src/games/skyrim/src/skyrimsavegameinfo.h deleted file mode 100644 index fab45e5e..00000000 --- a/src/games/skyrim/src/skyrimsavegameinfo.h +++ /dev/null @@ -1,17 +0,0 @@ -#ifndef SKYRIMSAVEGAMEINFO_H -#define SKYRIMSAVEGAMEINFO_H - -#include "gamebryosavegameinfo.h" - -class GameGamebryo; - -class SkyrimSaveGameInfo : public GamebryoSaveGameInfo -{ -public: - SkyrimSaveGameInfo(GameGamebryo const *game); - ~SkyrimSaveGameInfo(); - - virtual MOBase::ISaveGame const *getSaveGameInfo(QString const &file) const override; -}; - -#endif // SKYRIMSAVEGAMEINFO_H From 9df189473f3a7f01e54f67ef6386da2a940044d6 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Mika=C3=ABl=20Capelle?= Date: Wed, 18 Nov 2020 19:24:38 +0100 Subject: [PATCH 1099/1544] [game_oblivion] Update for IPluginGame::listSaves(). --- src/games/oblivion/src/gameoblivion.cpp | 10 +++- src/games/oblivion/src/gameoblivion.h | 8 ++- src/games/oblivion/src/oblivionsavegame.cpp | 53 ++++++++++++++----- src/games/oblivion/src/oblivionsavegame.h | 15 +++++- .../oblivion/src/oblivionsavegameinfo.cpp | 19 ------- src/games/oblivion/src/oblivionsavegameinfo.h | 17 ------ 6 files changed, 69 insertions(+), 53 deletions(-) delete mode 100644 src/games/oblivion/src/oblivionsavegameinfo.cpp delete mode 100644 src/games/oblivion/src/oblivionsavegameinfo.h diff --git a/src/games/oblivion/src/gameoblivion.cpp b/src/games/oblivion/src/gameoblivion.cpp index d76d98c8..b775c41d 100644 --- a/src/games/oblivion/src/gameoblivion.cpp +++ b/src/games/oblivion/src/gameoblivion.cpp @@ -2,16 +2,17 @@ #include "oblivionbsainvalidation.h" #include "obliviondataarchives.h" -#include "oblivionsavegameinfo.h" #include "oblivionscriptextender.h" #include "oblivionmoddatachecker.h" #include "oblivionmoddatacontent.h" +#include "oblivionsavegame.h" #include "pluginsetting.h" #include "executableinfo.h" #include #include #include +#include #include #include @@ -33,7 +34,7 @@ bool GameOblivion::init(IOrganizer *moInfo) registerFeature(new OblivionScriptExtender(this)); registerFeature(new OblivionDataArchives(myGamesPath())); registerFeature(new OblivionBSAInvalidation(feature(), this)); - registerFeature(new OblivionSaveGameInfo(this)); + registerFeature(new GamebryoSaveGameInfo(this)); registerFeature(new GamebryoLocalSavegames(myGamesPath(), "oblivion.ini")); registerFeature(new OblivionModDataChecker(this)); registerFeature(new OblivionModDataContent(this)); @@ -128,6 +129,11 @@ QString GameOblivion::savegameSEExtension() const return "obse"; } +std::shared_ptr GameOblivion::makeSaveGame(QString filePath) const +{ + return std::make_shared(filePath, this); +} + QString GameOblivion::steamAPPId() const { return "22330"; diff --git a/src/games/oblivion/src/gameoblivion.h b/src/games/oblivion/src/gameoblivion.h index 6efd29e3..5ab867f7 100644 --- a/src/games/oblivion/src/gameoblivion.h +++ b/src/games/oblivion/src/gameoblivion.h @@ -23,8 +23,6 @@ public: // IPluginGame interface virtual QList executables() const override; virtual QList executableForcedLoads() const override; virtual void initializeProfile(const QDir &path, ProfileSettings settings) const override; - virtual QString savegameExtension() const override; - virtual QString savegameSEExtension() const override; virtual QString steamAPPId() const override; virtual QStringList primaryPlugins() const override; virtual QString gameShortName() const override; @@ -43,6 +41,12 @@ public: // IPlugin interface virtual MOBase::VersionInfo version() const override; virtual QList settings() const override; +protected: + + std::shared_ptr makeSaveGame(QString filePath) const override; + QString savegameExtension() const override; + QString savegameSEExtension() const override; + }; #endif // GAMEOBLIVION_H diff --git a/src/games/oblivion/src/oblivionsavegame.cpp b/src/games/oblivion/src/oblivionsavegame.cpp index 62c80ac0..52089e86 100644 --- a/src/games/oblivion/src/oblivionsavegame.cpp +++ b/src/games/oblivion/src/oblivionsavegame.cpp @@ -2,12 +2,24 @@ #include -OblivionSaveGame::OblivionSaveGame(QString const &fileName, MOBase::IPluginGame const *game) : +OblivionSaveGame::OblivionSaveGame(QString const &fileName, GameOblivion const *game) : GamebryoSaveGame(fileName, game) { - FileWrapper file(this, "TES4SAVEGAME"); + FileWrapper file(getFilepath(), "TES4SAVEGAME"); file.setPluginString(GamebryoSaveGame::StringType::TYPE_BSTRING); + SYSTEMTIME creationTime; + fetchInformationFields(file, m_SaveNumber, m_PCName, m_PCLevel, m_PCLocation, creationTime); + setCreationTime(creationTime); +} + +void OblivionSaveGame::fetchInformationFields(FileWrapper& file, + unsigned long& saveNumber, + QString& playerName, + unsigned short& playerLevel, + QString& playerLocation, + SYSTEMTIME& creationTime) const +{ file.skip(); //Major version file.skip(); //Minor version @@ -16,11 +28,11 @@ OblivionSaveGame::OblivionSaveGame(QString const &fileName, MOBase::IPluginGame file.skip(); //Header version file.skip(); //Header size - file.read(m_SaveNumber); + file.read(saveNumber); - file.read(m_PCName); - file.read(m_PCLevel); - file.read(m_PCLocation); + file.read(playerName); + file.read(playerLevel); + file.read(playerLocation); file.skip(); //game days file.skip(); //game ticks @@ -29,16 +41,33 @@ OblivionSaveGame::OblivionSaveGame(QString const &fileName, MOBase::IPluginGame //could have been copied. //Note: This says it uses getlocaltime api to obtain it which is u/s - if so //we should ignore this. - SYSTEMTIME ctime; - file.read(ctime); - setCreationTime(ctime); + file.read(creationTime); +} + +std::unique_ptr OblivionSaveGame::fetchDataFields() const +{ + FileWrapper file(getFilepath(), "TES4SAVEGAME"); + file.setPluginString(GamebryoSaveGame::StringType::TYPE_BSTRING); + + std::unique_ptr fields = std::make_unique(); + + { + QString dummyName, dummyLocation; + unsigned short dummyLevel; + unsigned long dummySaveNumber; + SYSTEMTIME dummyTime; + + fetchInformationFields(file, dummySaveNumber, dummyName, dummyLevel, + dummyLocation, dummyTime); + } //Note that screenshot size, width, height and data are apparently the same //structure file.skip(); //Screenshot size. - file.readImage(); + fields->Screenshot = file.readImage(); - //file.setPluginString(GamebryoSaveGame::StringType::TYPE_BSTRING); - file.readPlugins(); + fields->Plugins = file.readPlugins(); + + return fields; } diff --git a/src/games/oblivion/src/oblivionsavegame.h b/src/games/oblivion/src/oblivionsavegame.h index 2df34f9b..0c9de37d 100644 --- a/src/games/oblivion/src/oblivionsavegame.h +++ b/src/games/oblivion/src/oblivionsavegame.h @@ -2,11 +2,24 @@ #define OBLIVIONSAVEGAME_H #include "gamebryosavegame.h" +#include "gameoblivion.h" class OblivionSaveGame : public GamebryoSaveGame { public: - OblivionSaveGame(QString const &fileName, MOBase::IPluginGame const *game); + OblivionSaveGame(QString const &fileName, GameOblivion const *game); + +protected: + + // Fetch easy-to-access information. + void fetchInformationFields(FileWrapper& wrapper, + unsigned long& saveNumber, + QString& playerName, + unsigned short& playerLevel, + QString& playerLocation, + SYSTEMTIME& creationTime) const; + + std::unique_ptr fetchDataFields() const override; }; #endif // OBLIVIONSAVEGAME_H diff --git a/src/games/oblivion/src/oblivionsavegameinfo.cpp b/src/games/oblivion/src/oblivionsavegameinfo.cpp deleted file mode 100644 index 2fe16526..00000000 --- a/src/games/oblivion/src/oblivionsavegameinfo.cpp +++ /dev/null @@ -1,19 +0,0 @@ -#include "oblivionsavegameinfo.h" - -#include "oblivionsavegame.h" -#include "gamegamebryo.h" - -OblivionSaveGameInfo::OblivionSaveGameInfo(GameGamebryo const *game) : - GamebryoSaveGameInfo(game) -{ -} - -OblivionSaveGameInfo::~OblivionSaveGameInfo() -{ -} - -MOBase::ISaveGame const *OblivionSaveGameInfo::getSaveGameInfo(QString const &file) const -{ - return new OblivionSaveGame(file, m_Game); -} - diff --git a/src/games/oblivion/src/oblivionsavegameinfo.h b/src/games/oblivion/src/oblivionsavegameinfo.h deleted file mode 100644 index 0639c756..00000000 --- a/src/games/oblivion/src/oblivionsavegameinfo.h +++ /dev/null @@ -1,17 +0,0 @@ -#ifndef OBLIVIONSAVEGAMEINFO_H -#define OBLIVIONSAVEGAMEINFO_H - -#include "gamebryosavegameinfo.h" - -class GameGamebryo; - -class OblivionSaveGameInfo : public GamebryoSaveGameInfo -{ -public: - OblivionSaveGameInfo(GameGamebryo const *game); - ~OblivionSaveGameInfo(); - - virtual MOBase::ISaveGame const *getSaveGameInfo(QString const &file) const override; - -}; -#endif // OBLIVIONSAVEGAMEINFO_H From 50b0db1fb2ad6a6b7e07053129f1b09aa717f04c Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Mika=C3=ABl=20Capelle?= Date: Wed, 18 Nov 2020 19:24:38 +0100 Subject: [PATCH 1100/1544] [game_morrowind] Update for IPluginGame::listSaves(). --- src/games/morrowind/src/gamemorrowind.cpp | 6 + src/games/morrowind/src/gamemorrowind.h | 8 +- src/games/morrowind/src/morrowindsavegame.cpp | 103 +++++++++++++----- src/games/morrowind/src/morrowindsavegame.h | 36 +++++- .../morrowind/src/morrowindsavegameinfo.cpp | 6 - .../morrowind/src/morrowindsavegameinfo.h | 2 - .../src/morrowindsavegameinfowidget.cpp | 25 +++-- .../src/morrowindsavegameinfowidget.h | 2 +- 8 files changed, 135 insertions(+), 53 deletions(-) diff --git a/src/games/morrowind/src/gamemorrowind.cpp b/src/games/morrowind/src/gamemorrowind.cpp index 26083c5e..dacb1d0c 100644 --- a/src/games/morrowind/src/gamemorrowind.cpp +++ b/src/games/morrowind/src/gamemorrowind.cpp @@ -4,6 +4,7 @@ #include "morrowinddataarchives.h" #include "morrowindgameplugins.h" #include "morrowindlocalsavegames.h" +#include "morrowindsavegame.h" #include "morrowindsavegameinfo.h" #include "morrowindmoddatachecker.h" #include "morrowindmoddatacontent.h" @@ -147,6 +148,11 @@ QString GameMorrowind::savegameSEExtension() const return "mwse"; } +std::shared_ptr GameMorrowind::makeSaveGame(QString filePath) const +{ + return std::make_shared(filePath, this); +} + QString GameMorrowind::steamAPPId() const { return "22320"; diff --git a/src/games/morrowind/src/gamemorrowind.h b/src/games/morrowind/src/gamemorrowind.h index 17b21c7e..b98d73b8 100644 --- a/src/games/morrowind/src/gamemorrowind.h +++ b/src/games/morrowind/src/gamemorrowind.h @@ -32,8 +32,6 @@ public: // IPluginGame interface virtual QList executables() const override; virtual QList executableForcedLoads() const override; virtual void initializeProfile(const QDir &path, ProfileSettings settings) const override; - virtual QString savegameExtension() const override; - virtual QString savegameSEExtension() const override; virtual QString steamAPPId() const override; virtual QStringList primaryPlugins() const override; virtual QString binaryName() const override; @@ -55,6 +53,12 @@ public: // IPlugin interface virtual MOBase::VersionInfo version() const override; virtual QList settings() const override; +protected: + + virtual QString savegameExtension() const override; + virtual QString savegameSEExtension() const override; + virtual std::shared_ptr makeSaveGame(QString filepath) const override; + private: MOBase::IOrganizer *m_Organizer; diff --git a/src/games/morrowind/src/morrowindsavegame.cpp b/src/games/morrowind/src/morrowindsavegame.cpp index fb216fa8..f73d696f 100644 --- a/src/games/morrowind/src/morrowindsavegame.cpp +++ b/src/games/morrowind/src/morrowindsavegame.cpp @@ -4,69 +4,118 @@ #include #include -MorrowindSaveGame::MorrowindSaveGame(QString const &fileName, MOBase::IPluginGame const *game) : +MorrowindSaveGame::MorrowindSaveGame(QString const &fileName, GameMorrowind const *game) : GamebryoSaveGame(fileName, game) { - FileWrapper file(this, "TES3"); + std::filesystem::path realFile(fileName.toStdWString()); + QString realFileName = QString::fromStdWString(realFile.filename().wstring()); + m_SaveNumber = realFileName.mid(4, 5).remove(QRegExp("0+$")).toInt(); + + FileWrapper file(fileName, "TES3"); + QStringList dummyPlugins; + fetchInformationFields(file, m_SaveName, dummyPlugins, + m_PCCurrentHealth, m_PCCMaxHealth, m_PCLocation, m_GameDays, m_PCName); +} + +QString MorrowindSaveGame::getName() const +{ + return QString("%1, #%2, %3") + .arg(m_PCName) + .arg(m_SaveNumber) + .arg(m_PCLocation); +} + +unsigned short MorrowindSaveGame::getPCLevel() const +{ + return dynamic_cast(m_DataFields.value().get())->PCLevel; +} + + + +// Fetch easy-to-access information. +void MorrowindSaveGame::fetchInformationFields(FileWrapper& file, + QString& saveName, + QStringList& plugins, + float& playerCurrentHealth, + float& playerMaxHealth, + QString& playerLocation, + float& gameDays, + QString& playerName) const +{ file.skip(3); // data size file.skip(4); // HEDR tag file.skip(); // header size file.skip(); // header version file.skip(); // following data chunk size? seems to be 9 groupings of 32 bytes file.skip(32); // Author empty for save files - std::vector saveName(256); // 31 char save name with a null terminator - file.read(saveName.data(), 256); - m_SaveName = QString::fromLatin1(saveName.data(), 256).trimmed(); // The defined save name. This is technically the description, but is likely only 31+\0 chars max. + std::vector saveNameBuffer(256); // 31 char save name with a null terminator + file.read(saveNameBuffer.data(), 256); + saveName = QString::fromLatin1(saveNameBuffer.data(), 256).trimmed(); // The defined save name. This is technically the description, but is likely only 31+\0 chars max. file.skip(); // NumRecords (for the entire save) std::vector buffer(255); file.read(buffer.data(), 4); // Parse the MAST/DATA records - while (QString::fromLatin1(buffer.data(), 4)=="MAST") { + while (QString::fromLatin1(buffer.data(), 4) == "MAST") { uint32_t len; file.read(len); // Length of master name - QString name; file.read(buffer.data(), len); // Name of master - name = QString::fromLatin1(buffer.data(), len - 1); - file.skip(4); // DATA record + QString name = QString::fromLatin1(buffer.data(), len - 1); + file.skip(4); // DATA record file.read(len); // Length file.skip(len); // Typically size 8 - contains length of master data for version checking - + file.read(buffer.data(), 4); // Get next record type - this->m_Plugins.push_back(name); + plugins.push_back(name); } - + // Start of GMDT file.skip(); // size of record - file.read(m_PCCurrentHealth); - file.read(m_PCCMaxHealth); + file.read(playerCurrentHealth); + file.read(playerMaxHealth); file.skip(); // current stam? file.skip(); // max stam? //file.skip(2); // unknown values file.read(buffer.data(), 64); - m_PCLocation = QString::fromLatin1(buffer.data(), 64).trimmed(); + playerLocation = QString::fromLatin1(buffer.data(), 64).trimmed(); - file.read(m_GameDays); + file.read(gameDays); file.read(buffer.data(), 32); - m_PCName=QString::fromLatin1(buffer.data(), 32).trimmed(); + playerName = QString::fromLatin1(buffer.data(), 32).trimmed(); // End of GMDT - +} + +std::unique_ptr MorrowindSaveGame::fetchDataFields() const +{ + FileWrapper file(getFilepath(), "TES3"); + std::vector buffer(255); + + std::unique_ptr fields = std::make_unique(); + + { + QString dummy; + float dummyF; + fetchInformationFields(file, dummy, fields->Plugins, + dummyF, dummyF, dummy, dummyF, dummy); + } + file.skip(28); // Skip the SCRD // I believe this tells the engine what color each pixel represents and the bitness of the image // Start of screenshot file.skip(4); // SCRS file.skip(); // Size of screenshot always 65536 (128x128x4) RGBA8888 - readImageBGRA(file, 128, 128, 0, 1); - this->m_Screenshot = this->m_Screenshot.scaled(252,192); + + QImage image = readImageBGRA(file, 128, 128, 0, 1); + fields->Screenshot = image.scaled(252, 192); //definitively have to use another method to access the player level //it is stored in the fifth byte of the NPDT subrecord of the first NPC_ record - + //Globals, Scripts, Regions //file.skip(); std::vector buff(4); @@ -95,7 +144,7 @@ MorrowindSaveGame::MorrowindSaveGame(QString const &fileName, MOBase::IPluginGam file.read(buff.data(), 4); } file.skip(); - file.read(m_PCLevel); + file.read(fields->PCLevel); } else { @@ -103,12 +152,10 @@ MorrowindSaveGame::MorrowindSaveGame(QString const &fileName, MOBase::IPluginGam } } - std::filesystem::path realFile(fileName.toStdWString()); - QString realFileName = QString::fromStdWString(realFile.filename().wstring()); - m_SaveNumber = realFileName.mid(4, 5).remove(QRegExp("0+$")).toInt(); + return fields; } -void MorrowindSaveGame::readImageBGRA(GamebryoSaveGame::FileWrapper &file, unsigned long width, unsigned long height, int scale = 0, bool alpha = false) +QImage MorrowindSaveGame::readImageBGRA(GamebryoSaveGame::FileWrapper &file, unsigned long width, unsigned long height, int scale = 0, bool alpha = false) const { QImage image(width, height, QImage::Format_RGBA8888); for (unsigned long h = 0; h < width; h++) { @@ -127,7 +174,7 @@ void MorrowindSaveGame::readImageBGRA(GamebryoSaveGame::FileWrapper &file, unsig } } if (scale != 0) - m_Screenshot = image.copy().scaledToWidth(scale); + return image.copy().scaledToWidth(scale); else - m_Screenshot = image.copy(); + return image.copy(); } \ No newline at end of file diff --git a/src/games/morrowind/src/morrowindsavegame.h b/src/games/morrowind/src/morrowindsavegame.h index 972f37e7..439f632f 100644 --- a/src/games/morrowind/src/morrowindsavegame.h +++ b/src/games/morrowind/src/morrowindsavegame.h @@ -2,14 +2,25 @@ #define MORROWINDSAVEGAME_H #include "gamebryosavegame.h" +#include "gamemorrowind.h" namespace MOBase { class IPluginGame; } class MorrowindSaveGame : public GamebryoSaveGame { public: - MorrowindSaveGame(QString const &fileName, MOBase::IPluginGame const *game); + MorrowindSaveGame(QString const &fileName, GameMorrowind const *game); +public: // ISaveGame interface + + // We need to override getName() because we do not read the level at + // the beginning. + virtual QString getName() const override; + + // The PC level is not pre-fetch for morrowind. + unsigned short getPCLevel() const override; + +public: //Simple getters QString getSaveName() const { return m_SaveName; } float getPCCurrentHealth() const { return m_PCCurrentHealth; } @@ -23,7 +34,28 @@ protected: float m_GameDays; protected: - void readImageBGRA(GamebryoSaveGame::FileWrapper &file, unsigned long width, unsigned long height, int scale, bool alpha); + QImage readImageBGRA( + GamebryoSaveGame::FileWrapper &file, unsigned long width, + unsigned long height, int scale, bool alpha) const; + + // We need to add the PC level here. + struct MorrowindDataFields : public DataFields { + unsigned short PCLevel = 0; + }; + + // Fetch easy-to-access information. + void fetchInformationFields( + FileWrapper& file, + QString& saveName, + QStringList& plugins, + float& playerCurrentHealth, + float& playerMaxHealth, + QString& playerLocation, + float& gameDays, + QString& playerName) const; + + std::unique_ptr fetchDataFields() const override; + }; #endif // MORROWINDSAVEGAME_H diff --git a/src/games/morrowind/src/morrowindsavegameinfo.cpp b/src/games/morrowind/src/morrowindsavegameinfo.cpp index 292bb0b7..8a20aae2 100644 --- a/src/games/morrowind/src/morrowindsavegameinfo.cpp +++ b/src/games/morrowind/src/morrowindsavegameinfo.cpp @@ -13,12 +13,6 @@ MorrowindSaveGameInfo::~MorrowindSaveGameInfo() { } - -MOBase::ISaveGame const *MorrowindSaveGameInfo::getSaveGameInfo(QString const &file) const -{ - return new MorrowindSaveGame(file, m_Game); -} - MOBase::ISaveGameInfoWidget *MorrowindSaveGameInfo::getSaveGameWidget(QWidget *parent) const { return new MorrowindSaveGameInfoWidget(this, parent); diff --git a/src/games/morrowind/src/morrowindsavegameinfo.h b/src/games/morrowind/src/morrowindsavegameinfo.h index 91adc9a3..3a081a88 100644 --- a/src/games/morrowind/src/morrowindsavegameinfo.h +++ b/src/games/morrowind/src/morrowindsavegameinfo.h @@ -14,8 +14,6 @@ public: virtual MOBase::ISaveGameInfoWidget *getSaveGameWidget(QWidget *) const override; - virtual MOBase::ISaveGame const *getSaveGameInfo(QString const &file) const override; - protected: friend class MorrowindSaveGameInfoWidget; GameMorrowind const *m_Game; diff --git a/src/games/morrowind/src/morrowindsavegameinfowidget.cpp b/src/games/morrowind/src/morrowindsavegameinfowidget.cpp index 93dcd124..567096cc 100644 --- a/src/games/morrowind/src/morrowindsavegameinfowidget.cpp +++ b/src/games/morrowind/src/morrowindsavegameinfowidget.cpp @@ -43,21 +43,22 @@ MorrowindSaveGameInfoWidget::~MorrowindSaveGameInfoWidget() { delete ui; } -void MorrowindSaveGameInfoWidget::setSave(QString const &file) { - std::unique_ptr < MorrowindSaveGame const> save( - std::move(dynamic_cast(m_Info->getSaveGameInfo(file)))); - ui->saveNameLabel->setText(QString("%1 (Day %2)").arg(save->getSaveName()).arg(save->getGameDays())); - ui->saveNumLabel->setText(QString("%1").arg(save->getSaveNumber())); - ui->healthLabel->setText(QString("%1 / %2").arg(round(save->getPCCurrentHealth())).arg(save->getPCMaxHealth())); - ui->characterLabel->setText(save->getPCName()); - ui->locationLabel->setText(save->getPCLocation()); - ui->levelLabel->setText(QString("%1").arg(save->getPCLevel())); +void MorrowindSaveGameInfoWidget::setSave(MOBase::ISaveGame const& save) { + auto const& morrowindSave = dynamic_cast(save); + + ui->saveNameLabel->setText(QString("%1 (Day %2)").arg(morrowindSave.getSaveName()).arg(morrowindSave.getGameDays())); + ui->saveNumLabel->setText(QString("%1").arg(morrowindSave.getSaveNumber())); + ui->healthLabel->setText(QString("%1 / %2").arg(round(morrowindSave.getPCCurrentHealth())).arg(morrowindSave.getPCMaxHealth())); + ui->characterLabel->setText(morrowindSave.getPCName()); + ui->locationLabel->setText(morrowindSave.getPCLocation()); + ui->levelLabel->setText(QString("%1").arg(morrowindSave.getPCLevel())); + //This somewhat contorted code is because on my system at least, the //old way of doing this appears to give short date and long time. - QDateTime t = save->getCreationTime(); + QDateTime t = morrowindSave.getCreationTime(); ui->dateLabel->setText(t.date().toString(Qt::DefaultLocaleShortDate) + " " + t.time().toString(Qt::DefaultLocaleLongDate)); - ui->screenshotLabel->setPixmap(QPixmap::fromImage(save->getScreenshot())); + ui->screenshotLabel->setPixmap(QPixmap::fromImage(morrowindSave.getScreenshot())); if (ui->gameFrame->layout() != nullptr) { QLayoutItem *item = nullptr; while ((item = ui->gameFrame->layout()->takeAt(0)) != nullptr) { @@ -81,7 +82,7 @@ void MorrowindSaveGameInfoWidget::setSave(QString const &file) { layout->addWidget(header); int count = 0; MOBase::IPluginList *pluginList = m_Info->m_Game->m_Organizer->pluginList(); - for (QString const &pluginName : save->getPlugins()) { + for (QString const &pluginName : morrowindSave.getPlugins()) { if (pluginList->state(pluginName) == MOBase::IPluginList::STATE_ACTIVE) { continue; } diff --git a/src/games/morrowind/src/morrowindsavegameinfowidget.h b/src/games/morrowind/src/morrowindsavegameinfowidget.h index 298f5916..df0628bd 100644 --- a/src/games/morrowind/src/morrowindsavegameinfowidget.h +++ b/src/games/morrowind/src/morrowindsavegameinfowidget.h @@ -18,7 +18,7 @@ public: MorrowindSaveGameInfoWidget(MorrowindSaveGameInfo const *info, QWidget *parent); ~MorrowindSaveGameInfoWidget(); - virtual void setSave(QString const &) override; + virtual void setSave(MOBase::ISaveGame const&) override; private: Ui::MorrowindSaveGameInfoWidget *ui; From 8d45524fbbdf5a569597588b411ea0eb98f0bcb3 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Mika=C3=ABl=20Capelle?= Date: Thu, 19 Nov 2020 09:39:32 +0100 Subject: [PATCH 1101/1544] Clean readImage() comment. --- src/gamebryo/gamebryosavegame.cpp | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/src/gamebryo/gamebryosavegame.cpp b/src/gamebryo/gamebryosavegame.cpp index 86f23fa1..f7ab16b8 100644 --- a/src/gamebryo/gamebryosavegame.cpp +++ b/src/gamebryo/gamebryosavegame.cpp @@ -179,12 +179,12 @@ QImage GamebryoSaveGame::FileWrapper::readImage(unsigned long width, unsigned lo read(buffer.data(), width * height * bpp); QImage image(buffer.data(), width, height, alpha ? QImage::Format_RGBA8888_Premultiplied : QImage::Format_RGB888); + + // We need to copy the image here because QImage does not make a copy of the + // buffer when constructed. if (scale != 0) { return image.copy().scaledToWidth(scale); } else { - // why do I have to copy here? without the copy, the buffer seems to get - // deleted after the temporary vanishes, but shouldn't Qts implicit sharing - // handle that? return image.copy(); } } From fc365dbd4db21fbd37b6d880bf13cdfe8cdebccd Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Mika=C3=ABl=20Capelle?= Date: Thu, 19 Nov 2020 09:45:46 +0100 Subject: [PATCH 1102/1544] Clean comment. --- src/gamebryo/gamegamebryo.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/gamebryo/gamegamebryo.h b/src/gamebryo/gamegamebryo.h index 3ddc156d..1a0ebc8b 100644 --- a/src/gamebryo/gamegamebryo.h +++ b/src/gamebryo/gamegamebryo.h @@ -92,7 +92,7 @@ protected: virtual QString savegameExtension() const = 0; virtual QString savegameSEExtension() const = 0; - // Create a save game: + // Create a save game. virtual std::shared_ptr makeSaveGame(QString filepath) const = 0; From 1b0559fd5b109c4d33c572971416c4da3fb2ba18 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Mika=C3=ABl=20Capelle?= Date: Fri, 20 Nov 2020 21:28:30 +0100 Subject: [PATCH 1103/1544] Do not list saves recursively. --- src/gamebryo/gamegamebryo.cpp | 9 ++------- 1 file changed, 2 insertions(+), 7 deletions(-) diff --git a/src/gamebryo/gamegamebryo.cpp b/src/gamebryo/gamegamebryo.cpp index 9a398c7b..c0bb5d94 100644 --- a/src/gamebryo/gamegamebryo.cpp +++ b/src/gamebryo/gamegamebryo.cpp @@ -99,14 +99,9 @@ GameGamebryo::listSaves(QDir folder) const QStringList filters; filters << QString("*.") + savegameExtension(); - folder.setNameFilters(filters); - folder.setFilter(QDir::Files); - QDirIterator it(folder, QDirIterator::Subdirectories); - std::vector> saves; - while (it.hasNext()) { - it.next(); - saves.push_back(makeSaveGame(it.filePath())); + for (auto info : folder.entryInfoList(filters, QDir::Files)) { + saves.push_back(makeSaveGame(info.filePath())); } return saves; From 3d09f016da0a7850f496115cc0f7c9f79c22a369 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Mika=C3=ABl=20Capelle?= Date: Sat, 21 Nov 2020 12:24:28 +0100 Subject: [PATCH 1104/1544] Replace ScriptExtender saveGameAttachmentExtensions with savegameExtension. --- src/gamebryo/gamebryosavegame.cpp | 7 ------- src/gamebryo/gamebryoscriptextender.cpp | 5 +++++ src/gamebryo/gamebryoscriptextender.h | 2 ++ src/gamebryo/gamegamebryo.h | 3 +-- 4 files changed, 8 insertions(+), 9 deletions(-) diff --git a/src/gamebryo/gamebryosavegame.cpp b/src/gamebryo/gamebryosavegame.cpp index f7ab16b8..2227eb0d 100644 --- a/src/gamebryo/gamebryosavegame.cpp +++ b/src/gamebryo/gamebryosavegame.cpp @@ -63,13 +63,6 @@ QStringList GamebryoSaveGame::allFiles() const ScriptExtender const *e = m_Game->feature(); if (e != nullptr) { QFileInfo file(m_FileName); - for (QString const &ext : e->saveGameAttachmentExtensions()) { - QFileInfo name(file.absoluteDir().absoluteFilePath(file.completeBaseName() + "." + ext)); - if (name.exists()) { - res.push_back(name.absoluteFilePath()); - } - } - QFileInfo SEfile(file.absolutePath() + "/" + file.completeBaseName() + "." + m_Game->savegameSEExtension()); if (SEfile.exists()) { res.push_back(SEfile.absoluteFilePath()); diff --git a/src/gamebryo/gamebryoscriptextender.cpp b/src/gamebryo/gamebryoscriptextender.cpp index fe743968..a7d6016d 100644 --- a/src/gamebryo/gamebryoscriptextender.cpp +++ b/src/gamebryo/gamebryoscriptextender.cpp @@ -26,6 +26,11 @@ QString GamebryoScriptExtender::loaderPath() const return m_Game->gameDirectory().absoluteFilePath(loaderName()); } +QString GamebryoScriptExtender::savegameExtension() const +{ + return m_Game->savegameSEExtension(); +} + bool GamebryoScriptExtender::isInstalled() const { //A note: It is possibly also OK if xxse_steam_loader.dll exists, but it's diff --git a/src/gamebryo/gamebryoscriptextender.h b/src/gamebryo/gamebryoscriptextender.h index 807e7cf5..c11328c0 100644 --- a/src/gamebryo/gamebryoscriptextender.h +++ b/src/gamebryo/gamebryoscriptextender.h @@ -16,6 +16,8 @@ public: virtual QString loaderPath() const override; + virtual QString savegameExtension() const override; + virtual bool isInstalled() const override; virtual QString getExtenderVersion() const override; diff --git a/src/gamebryo/gamegamebryo.h b/src/gamebryo/gamegamebryo.h index 1a0ebc8b..ce4e274f 100644 --- a/src/gamebryo/gamegamebryo.h +++ b/src/gamebryo/gamegamebryo.h @@ -32,6 +32,7 @@ class GameGamebryo : public MOBase::IPluginGame, friend class GamebryoScriptExtender; friend class GamebryoSaveGameInfo; friend class GamebryoSaveGameInfoWidget; + friend class GamebryoSaveGame; /** * Some Bethesda games do not have a valid file version but a valid product @@ -86,8 +87,6 @@ public: // IPluginFileMapper interface protected: - friend class GamebryoSaveGame; - // Retrieve the saves extension for the game. virtual QString savegameExtension() const = 0; virtual QString savegameSEExtension() const = 0; From 2c2a7945255a482239e447d709e95df14eaefe24 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Mika=C3=ABl=20Capelle?= Date: Sat, 21 Nov 2020 12:24:28 +0100 Subject: [PATCH 1105/1544] [game_falloutnv] Replace ScriptExtender saveGameAttachmentExtensions with savegameExtension. --- src/games/falloutnv/src/falloutnvscriptextender.cpp | 5 ----- src/games/falloutnv/src/falloutnvscriptextender.h | 2 -- 2 files changed, 7 deletions(-) diff --git a/src/games/falloutnv/src/falloutnvscriptextender.cpp b/src/games/falloutnv/src/falloutnvscriptextender.cpp index 72f11d82..987b5012 100644 --- a/src/games/falloutnv/src/falloutnvscriptextender.cpp +++ b/src/games/falloutnv/src/falloutnvscriptextender.cpp @@ -17,8 +17,3 @@ QString FalloutNVScriptExtender::PluginPath() const { return "nvse/plugins"; } - -QStringList FalloutNVScriptExtender::saveGameAttachmentExtensions() const -{ - return { }; -} diff --git a/src/games/falloutnv/src/falloutnvscriptextender.h b/src/games/falloutnv/src/falloutnvscriptextender.h index 41a095b7..66e4274e 100644 --- a/src/games/falloutnv/src/falloutnvscriptextender.h +++ b/src/games/falloutnv/src/falloutnvscriptextender.h @@ -13,8 +13,6 @@ public: virtual QString BinaryName() const override; virtual QString PluginPath() const override; - virtual QStringList saveGameAttachmentExtensions() const override; - }; #endif // FALLOUTNVSCRIPTEXTENDER_H From c91451ab5a13bc701b885916b5dac557721b937a Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Mika=C3=ABl=20Capelle?= Date: Sat, 21 Nov 2020 12:24:28 +0100 Subject: [PATCH 1106/1544] [game_fallout4] Replace ScriptExtender saveGameAttachmentExtensions with savegameExtension. --- src/games/fallout4/src/fallout4scriptextender.cpp | 5 ----- src/games/fallout4/src/fallout4scriptextender.h | 2 -- 2 files changed, 7 deletions(-) diff --git a/src/games/fallout4/src/fallout4scriptextender.cpp b/src/games/fallout4/src/fallout4scriptextender.cpp index 21c930c9..d40a09ad 100644 --- a/src/games/fallout4/src/fallout4scriptextender.cpp +++ b/src/games/fallout4/src/fallout4scriptextender.cpp @@ -17,8 +17,3 @@ QString Fallout4ScriptExtender::PluginPath() const { return "f4se/plugins"; } - -QStringList Fallout4ScriptExtender::saveGameAttachmentExtensions() const -{ - return { }; -} diff --git a/src/games/fallout4/src/fallout4scriptextender.h b/src/games/fallout4/src/fallout4scriptextender.h index 4c134276..319beb6c 100644 --- a/src/games/fallout4/src/fallout4scriptextender.h +++ b/src/games/fallout4/src/fallout4scriptextender.h @@ -13,8 +13,6 @@ public: virtual QString BinaryName() const override; virtual QString PluginPath() const override; - virtual QStringList saveGameAttachmentExtensions() const override; - }; #endif // FALLOUT4SCRIPTEXTENDER_H From 5d3173274f61c89bcc3da3a02c923054676e771d Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Mika=C3=ABl=20Capelle?= Date: Sat, 21 Nov 2020 12:24:28 +0100 Subject: [PATCH 1107/1544] [game_fallout3] Replace ScriptExtender saveGameAttachmentExtensions with savegameExtension. --- src/games/fallout3/src/fallout3scriptextender.cpp | 5 ----- src/games/fallout3/src/fallout3scriptextender.h | 2 -- 2 files changed, 7 deletions(-) diff --git a/src/games/fallout3/src/fallout3scriptextender.cpp b/src/games/fallout3/src/fallout3scriptextender.cpp index c0f17fbb..b39e8953 100644 --- a/src/games/fallout3/src/fallout3scriptextender.cpp +++ b/src/games/fallout3/src/fallout3scriptextender.cpp @@ -17,8 +17,3 @@ QString Fallout3ScriptExtender::PluginPath() const { return "fose/plugins"; } - -QStringList Fallout3ScriptExtender::saveGameAttachmentExtensions() const -{ - return { }; -} diff --git a/src/games/fallout3/src/fallout3scriptextender.h b/src/games/fallout3/src/fallout3scriptextender.h index 828f5b77..108196bf 100644 --- a/src/games/fallout3/src/fallout3scriptextender.h +++ b/src/games/fallout3/src/fallout3scriptextender.h @@ -14,8 +14,6 @@ public: virtual QString BinaryName() const override; virtual QString PluginPath() const override; - virtual QStringList saveGameAttachmentExtensions() const override; - }; #endif // FALLOUT3SCRIPTEXTENDER_H From 0a4ef82d3137da19269caf51bd873fab9459d97c Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Mika=C3=ABl=20Capelle?= Date: Sat, 21 Nov 2020 12:24:29 +0100 Subject: [PATCH 1108/1544] [game_skyrimvr] Replace ScriptExtender saveGameAttachmentExtensions with savegameExtension. --- src/games/skyrimvr/src/skyrimvrscriptextender.cpp | 5 ----- src/games/skyrimvr/src/skyrimvrscriptextender.h | 2 -- 2 files changed, 7 deletions(-) diff --git a/src/games/skyrimvr/src/skyrimvrscriptextender.cpp b/src/games/skyrimvr/src/skyrimvrscriptextender.cpp index c272231f..8668a7ce 100644 --- a/src/games/skyrimvr/src/skyrimvrscriptextender.cpp +++ b/src/games/skyrimvr/src/skyrimvrscriptextender.cpp @@ -17,8 +17,3 @@ QString SkyrimVRScriptExtender::PluginPath() const { return "skse/plugins"; } - -QStringList SkyrimVRScriptExtender::saveGameAttachmentExtensions() const -{ - return { }; -} diff --git a/src/games/skyrimvr/src/skyrimvrscriptextender.h b/src/games/skyrimvr/src/skyrimvrscriptextender.h index 4afc8a0e..a3a580db 100644 --- a/src/games/skyrimvr/src/skyrimvrscriptextender.h +++ b/src/games/skyrimvr/src/skyrimvrscriptextender.h @@ -13,8 +13,6 @@ public: virtual QString BinaryName() const override; virtual QString PluginPath() const override; - virtual QStringList saveGameAttachmentExtensions() const override; - }; #endif // _SKYRIMVRSCRIPTEXTENDER_H From 34b204282cebf1077616fab4fe0a7dd0e3ae4f67 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Mika=C3=ABl=20Capelle?= Date: Sat, 21 Nov 2020 12:24:29 +0100 Subject: [PATCH 1109/1544] [game_ttw] Replace ScriptExtender saveGameAttachmentExtensions with savegameExtension. --- src/games/ttw/src/falloutttwscriptextender.cpp | 5 ----- src/games/ttw/src/falloutttwscriptextender.h | 2 -- 2 files changed, 7 deletions(-) diff --git a/src/games/ttw/src/falloutttwscriptextender.cpp b/src/games/ttw/src/falloutttwscriptextender.cpp index 33ef7360..cd542e6e 100644 --- a/src/games/ttw/src/falloutttwscriptextender.cpp +++ b/src/games/ttw/src/falloutttwscriptextender.cpp @@ -17,8 +17,3 @@ QString FalloutTTWScriptExtender::PluginPath() const { return "nvse/plugins"; } - -QStringList FalloutTTWScriptExtender::saveGameAttachmentExtensions() const -{ - return { }; -} diff --git a/src/games/ttw/src/falloutttwscriptextender.h b/src/games/ttw/src/falloutttwscriptextender.h index d45c82a7..cd91f1d5 100644 --- a/src/games/ttw/src/falloutttwscriptextender.h +++ b/src/games/ttw/src/falloutttwscriptextender.h @@ -13,8 +13,6 @@ public: virtual QString BinaryName() const override; virtual QString PluginPath() const override; - virtual QStringList saveGameAttachmentExtensions() const override; - }; #endif // FALLOUTTTWSCRIPTEXTENDER_H From c1cb3b394a5cfd064d4ee9f902d57c2fcb394853 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Mika=C3=ABl=20Capelle?= Date: Sat, 21 Nov 2020 12:24:29 +0100 Subject: [PATCH 1110/1544] [game_skyrimse] Replace ScriptExtender saveGameAttachmentExtensions with savegameExtension. --- src/games/skyrimse/src/skyrimsescriptextender.cpp | 5 ----- src/games/skyrimse/src/skyrimsescriptextender.h | 2 -- 2 files changed, 7 deletions(-) diff --git a/src/games/skyrimse/src/skyrimsescriptextender.cpp b/src/games/skyrimse/src/skyrimsescriptextender.cpp index 5e09f3c3..1fc5a30a 100644 --- a/src/games/skyrimse/src/skyrimsescriptextender.cpp +++ b/src/games/skyrimse/src/skyrimsescriptextender.cpp @@ -17,8 +17,3 @@ QString SkyrimSEScriptExtender::PluginPath() const { return "skse/plugins"; } - -QStringList SkyrimSEScriptExtender::saveGameAttachmentExtensions() const -{ - return { }; -} diff --git a/src/games/skyrimse/src/skyrimsescriptextender.h b/src/games/skyrimse/src/skyrimsescriptextender.h index df1337a5..b8f7ee9c 100644 --- a/src/games/skyrimse/src/skyrimsescriptextender.h +++ b/src/games/skyrimse/src/skyrimsescriptextender.h @@ -13,8 +13,6 @@ public: virtual QString BinaryName() const override; virtual QString PluginPath() const override; - virtual QStringList saveGameAttachmentExtensions() const override; - }; #endif // _SKYRIMSESCRIPTEXTENDER_H From 670c1bb27a6e08cee509359ed8bf3ac1a766903e Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Mika=C3=ABl=20Capelle?= Date: Sat, 21 Nov 2020 12:24:29 +0100 Subject: [PATCH 1111/1544] [game_skyrim] Replace ScriptExtender saveGameAttachmentExtensions with savegameExtension. --- src/games/skyrim/src/skyrimscriptextender.cpp | 5 ----- src/games/skyrim/src/skyrimscriptextender.h | 2 -- 2 files changed, 7 deletions(-) diff --git a/src/games/skyrim/src/skyrimscriptextender.cpp b/src/games/skyrim/src/skyrimscriptextender.cpp index 352bd01e..62a7f669 100644 --- a/src/games/skyrim/src/skyrimscriptextender.cpp +++ b/src/games/skyrim/src/skyrimscriptextender.cpp @@ -17,8 +17,3 @@ QString SkyrimScriptExtender::PluginPath() const { return "skse/plugins"; } - -QStringList SkyrimScriptExtender::saveGameAttachmentExtensions() const -{ - return { }; -} diff --git a/src/games/skyrim/src/skyrimscriptextender.h b/src/games/skyrim/src/skyrimscriptextender.h index 43242413..b1a370c1 100644 --- a/src/games/skyrim/src/skyrimscriptextender.h +++ b/src/games/skyrim/src/skyrimscriptextender.h @@ -13,8 +13,6 @@ public: virtual QString BinaryName() const override; virtual QString PluginPath() const override; - virtual QStringList saveGameAttachmentExtensions() const override; - }; #endif // SKYRIMSCRIPTEXTENDER_H From c9ba32a542085355e997189cd78aa08b4ccb92fd Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Mika=C3=ABl=20Capelle?= Date: Sat, 21 Nov 2020 12:24:29 +0100 Subject: [PATCH 1112/1544] [game_oblivion] Replace ScriptExtender saveGameAttachmentExtensions with savegameExtension. --- src/games/oblivion/src/oblivionscriptextender.cpp | 5 ----- src/games/oblivion/src/oblivionscriptextender.h | 2 -- 2 files changed, 7 deletions(-) diff --git a/src/games/oblivion/src/oblivionscriptextender.cpp b/src/games/oblivion/src/oblivionscriptextender.cpp index ecbd95ef..8d18c1d7 100644 --- a/src/games/oblivion/src/oblivionscriptextender.cpp +++ b/src/games/oblivion/src/oblivionscriptextender.cpp @@ -21,8 +21,3 @@ QString OblivionScriptExtender::PluginPath() const { return "obse/plugins"; } - -QStringList OblivionScriptExtender::saveGameAttachmentExtensions() const -{ - return {}; -} diff --git a/src/games/oblivion/src/oblivionscriptextender.h b/src/games/oblivion/src/oblivionscriptextender.h index 310573e6..5155b552 100644 --- a/src/games/oblivion/src/oblivionscriptextender.h +++ b/src/games/oblivion/src/oblivionscriptextender.h @@ -14,8 +14,6 @@ public: virtual QString BinaryName() const override; virtual QString PluginPath() const override; - virtual QStringList saveGameAttachmentExtensions() const override; - }; #endif // OBLIVIONSCRIPTEXTENDER_H From ee3abe3a3add25a56996f63ce5fdb3bbb149d9a4 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Mika=C3=ABl=20Capelle?= Date: Thu, 26 Nov 2020 19:27:38 +0100 Subject: [PATCH 1113/1544] [game_skyrimvr] Fix save game. --- src/games/skyrimvr/src/skyrimvrsavegame.cpp | 26 +++++++-------------- 1 file changed, 9 insertions(+), 17 deletions(-) diff --git a/src/games/skyrimvr/src/skyrimvrsavegame.cpp b/src/games/skyrimvr/src/skyrimvrsavegame.cpp index 3da7ccd4..09d414ab 100644 --- a/src/games/skyrimvr/src/skyrimvrsavegame.cpp +++ b/src/games/skyrimvr/src/skyrimvrsavegame.cpp @@ -13,12 +13,12 @@ SkyrimVRSaveGame::SkyrimVRSaveGame(QString const &fileName, GameSkyrimVR const * FILETIME ftime; fetchInformationFields(file, version, m_PCName, m_PCLevel, m_PCLocation, m_SaveNumber, ftime); - //A file time is a 64-bit value that represents the number of 100-nanosecond - //intervals that have elapsed since 12:00 A.M. January 1, 1601 Coordinated Universal Time (UTC). - //So we need to convert that to something useful + // A file time is a 64-bit value that represents the number of 100-nanosecond + // intervals that have elapsed since 12:00 A.M. January 1, 1601 Coordinated Universal Time (UTC). + // So we need to convert that to something useful - //For some reason, the file time is off by about 6 hours. - //So we need to subtract those 6 hours from the filetime. + // For some reason, the file time is off by about 6 hours. + // So we need to subtract those 6 hours from the filetime. _ULARGE_INTEGER time; time.LowPart = ftime.dwLowDateTime; time.HighPart = ftime.dwHighDateTime; @@ -89,19 +89,11 @@ std::unique_ptr SkyrimVRSaveGame::fetchDataFields( file.read(width); file.read(height); - bool alpha = false; + uint16_t compressionType; + file.read(compressionType); + file.setCompressionType(compressionType); - // compatibility between LE and SE: - // SE has an additional uin16_t for compression - // SE uses an alpha channel, whereas LE does not - if (version == 12) { - uint16_t compressionType; - file.read(compressionType); - file.setCompressionType(compressionType); - alpha = true; - } - - fields->Screenshot = file.readImage(width, height, 320, alpha); + fields->Screenshot = file.readImage(width, height, 320, true); file.openCompressedData(); From 6858155b197c20c09baebdc9601dc8a23e506d36 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Mika=C3=ABl=20Capelle?= Date: Thu, 26 Nov 2020 19:38:14 +0100 Subject: [PATCH 1114/1544] [game_skyrimvr] Restore version comment. --- src/games/skyrimvr/src/skyrimvrsavegame.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/games/skyrimvr/src/skyrimvrsavegame.cpp b/src/games/skyrimvr/src/skyrimvrsavegame.cpp index 09d414ab..29d7a1c6 100644 --- a/src/games/skyrimvr/src/skyrimvrsavegame.cpp +++ b/src/games/skyrimvr/src/skyrimvrsavegame.cpp @@ -44,7 +44,7 @@ void SkyrimVRSaveGame::fetchInformationFields( { unsigned long headerSize; file.read(headerSize); // header size "TESV_SAVEGAME" - file.read(version); + file.read(version); // header version 74 (original Skyrim is 79) file.read(saveNumber); file.read(playerName); From 7ff1dc85e80d782ecc21e1f8fe13949d6ec912a6 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Mika=C3=ABl=20Capelle?= Date: Fri, 27 Nov 2020 20:58:52 +0100 Subject: [PATCH 1115/1544] [game_oblivion] Automatically move OBSE plugins to the right place. --- .../oblivion/src/oblivionmoddatachecker.cpp | 30 +++++++++++++++++++ .../oblivion/src/oblivionmoddatachecker.h | 3 ++ 2 files changed, 33 insertions(+) create mode 100644 src/games/oblivion/src/oblivionmoddatachecker.cpp diff --git a/src/games/oblivion/src/oblivionmoddatachecker.cpp b/src/games/oblivion/src/oblivionmoddatachecker.cpp new file mode 100644 index 00000000..0cc3546c --- /dev/null +++ b/src/games/oblivion/src/oblivionmoddatachecker.cpp @@ -0,0 +1,30 @@ +#include "oblivionmoddatachecker.h" + +ModDataChecker::CheckReturn OblivionModDataChecker::dataLooksValid( + std::shared_ptr fileTree) const +{ + // Check with Gamebryo stuff: + auto check = GamebryoModDataChecker::dataLooksValid(fileTree); + if (check == CheckReturn::VALID) { + return check; + } + + // Check for OBSE_ files: + for (auto const& entry : *fileTree) { + if (entry->isDir() || !entry->name().startsWith("OBSE", Qt::CaseInsensitive)) { + return CheckReturn::INVALID; + } + } + + return CheckReturn::FIXABLE; +} + +std::shared_ptr OblivionModDataChecker::fix( + std::shared_ptr fileTree) const +{ + // If we arrive here, it means all files starts with OBSE. + auto data = fileTree->createOrphanTree(); + auto obse = data->addDirectory("OBSE/Plugins"); + obse->merge(fileTree); + return data; +} \ No newline at end of file diff --git a/src/games/oblivion/src/oblivionmoddatachecker.h b/src/games/oblivion/src/oblivionmoddatachecker.h index 50a88b65..f9b14e9a 100644 --- a/src/games/oblivion/src/oblivionmoddatachecker.h +++ b/src/games/oblivion/src/oblivionmoddatachecker.h @@ -8,6 +8,9 @@ class OblivionModDataChecker : public GamebryoModDataChecker public: using GamebryoModDataChecker::GamebryoModDataChecker; + CheckReturn dataLooksValid(std::shared_ptr fileTree) const override; + std::shared_ptr fix(std::shared_ptr fileTree) const override; + protected: virtual const FileNameSet& possibleFolderNames() const override { static FileNameSet result{ From 08f9d22e0b71f5b14cf1f4541d839a47a96f5d0e Mon Sep 17 00:00:00 2001 From: Chris Bessent Date: Thu, 26 Nov 2020 22:17:51 -0700 Subject: [PATCH 1116/1544] Set [Launcher] bEnableFileSelection=1 when running executable --- src/gamebryo/gamegamebryo.cpp | 35 +++++++++++++++++++++++++++++++---- src/gamebryo/gamegamebryo.h | 2 ++ 2 files changed, 33 insertions(+), 4 deletions(-) diff --git a/src/gamebryo/gamegamebryo.cpp b/src/gamebryo/gamegamebryo.cpp index bf4571bd..8ff7141c 100644 --- a/src/gamebryo/gamegamebryo.cpp +++ b/src/gamebryo/gamegamebryo.cpp @@ -2,11 +2,13 @@ #include "bsainvalidation.h" #include "dataarchives.h" -#include "savegameinfo.h" -#include "scriptextender.h" -#include "scopeguard.h" -#include "utility.h" #include "gamebryomoddatacontent.h" +#include "iprofile.h" +#include "registry.h" +#include "savegameinfo.h" +#include "scopeguard.h" +#include "scriptextender.h" +#include "utility.h" #include #include @@ -51,7 +53,9 @@ void GameGamebryo::detectGame() bool GameGamebryo::init(MOBase::IOrganizer *moInfo) { + using namespace std::placeholders; m_Organizer = moInfo; + m_Organizer->onAboutToRun(std::bind(&GameGamebryo::prepareIni, this, _1)); return true; } @@ -209,6 +213,29 @@ QString GameGamebryo::identifyGamePath() const return findInRegistry(HKEY_LOCAL_MACHINE, path.toStdWString().c_str(), L"Installed Path"); } +bool GameGamebryo::prepareIni(const QString& exec) +{ + MOBase::IProfile *profile = m_Organizer->profile(); + + QString basePath + = profile->localSettingsEnabled() + ? profile->absolutePath() + : documentsDirectory().absolutePath(); + + if (!iniFiles().isEmpty()) { + + QString profileIni = basePath + "/" + iniFiles()[0]; + + WCHAR setting[512]; + if (!GetPrivateProfileStringW(L"Launcher", L"bEnableFileSelection", L"0", setting, 512, profileIni.toStdWString().c_str()) + || wcstol(setting, nullptr, 10) != 1) { + MOBase::WriteRegistryValue(L"Launcher", L"bEnableFileSelection", L"1", profileIni.toStdWString().c_str()); + } + } + + return true; +} + QString GameGamebryo::selectedVariant() const { return m_GameVariant; diff --git a/src/gamebryo/gamegamebryo.h b/src/gamebryo/gamegamebryo.h index aecd51d2..88326468 100644 --- a/src/gamebryo/gamegamebryo.h +++ b/src/gamebryo/gamegamebryo.h @@ -107,6 +107,8 @@ protected: virtual QString identifyGamePath() const; + virtual bool prepareIni(const QString& exec); + static std::unique_ptr getRegValue(HKEY key, LPCWSTR path, LPCWSTR value, DWORD flags, LPDWORD type); static QString findInRegistry(HKEY baseKey, LPCWSTR path, LPCWSTR value); From 2176eb2035b543658461f9276b1368b396eb6bf8 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Mika=C3=ABl=20Capelle?= Date: Sat, 28 Nov 2020 15:42:25 +0100 Subject: [PATCH 1117/1544] [game_fallout4vr] IPluginGame::listSaves (#19) * Update for IPluginGame::listSaves(). * Replace ScriptExtender saveGameAttachmentExtensions with savegameExtension. --- .../fallout4vr/src/fallout4vrsavegame.cpp | 76 ++++++++++++++----- src/games/fallout4vr/src/fallout4vrsavegame.h | 19 ++++- .../fallout4vr/src/fallout4vrsavegameinfo.cpp | 19 ----- .../fallout4vr/src/fallout4vrsavegameinfo.h | 17 ----- .../src/fallout4vrscriptextender.cpp | 5 -- .../fallout4vr/src/fallout4vrscriptextender.h | 2 - src/games/fallout4vr/src/gamefallout4vr.cpp | 10 ++- src/games/fallout4vr/src/gamefallout4vr.h | 6 +- 8 files changed, 85 insertions(+), 69 deletions(-) delete mode 100644 src/games/fallout4vr/src/fallout4vrsavegameinfo.cpp delete mode 100644 src/games/fallout4vr/src/fallout4vrsavegameinfo.h diff --git a/src/games/fallout4vr/src/fallout4vrsavegame.cpp b/src/games/fallout4vr/src/fallout4vrsavegame.cpp index e47a330f..7d6e47f3 100644 --- a/src/games/fallout4vr/src/fallout4vrsavegame.cpp +++ b/src/games/fallout4vr/src/fallout4vrsavegame.cpp @@ -2,20 +2,43 @@ #include -Fallout4VRSaveGame::Fallout4VRSaveGame(QString const &fileName, MOBase::IPluginGame const *game, bool const lightEnabled) : - GamebryoSaveGame(fileName, game, lightEnabled) +#include "gamefallout4vr.h" + +Fallout4VRSaveGame::Fallout4VRSaveGame(QString const &fileName, GameFallout4VR const *game) : + GamebryoSaveGame(fileName, game, true) +{ + FileWrapper file(getFilepath(), "FO4_SAVEGAME"); + + FILETIME creationTime; + fetchInformationFields(file, m_SaveNumber, m_PCName, m_PCLevel, m_PCLocation, creationTime); + + //A file time is a 64-bit value that represents the number of 100-nanosecond + //intervals that have elapsed since 12:00 A.M. January 1, 1601 Coordinated Universal Time (UTC). + //So we need to convert that to something useful + SYSTEMTIME ctime; + ::FileTimeToSystemTime(&creationTime, &ctime); + + setCreationTime(ctime); +} + +void Fallout4VRSaveGame::fetchInformationFields( + FileWrapper& file, + unsigned long& saveNumber, + QString& playerName, + unsigned short& playerLevel, + QString& playerLocation, + FILETIME& creationTime) const { - FileWrapper file(this, "FO4_SAVEGAME"); file.skip(); // header size file.skip(); // header version - file.read(m_SaveNumber); + file.read(saveNumber); - file.read(m_PCName); + file.read(playerName); unsigned long temp; file.read(temp); - m_PCLevel = static_cast(temp); - file.read(m_PCLocation); + playerLevel = static_cast(temp); + file.read(playerLocation); QString ignore; file.read(ignore); // playtime as ascii hh.mm.ss @@ -24,23 +47,36 @@ Fallout4VRSaveGame::Fallout4VRSaveGame(QString const &fileName, MOBase::IPluginG file.skip(); // Player gender (0 = male) file.skip(2); // experience gathered, experience required - FILETIME ftime; - file.read(ftime); - //A file time is a 64-bit value that represents the number of 100-nanosecond - //intervals that have elapsed since 12:00 A.M. January 1, 1601 Coordinated Universal Time (UTC). - //So we need to convert that to something useful - SYSTEMTIME ctime; - ::FileTimeToSystemTime(&ftime, &ctime); + file.read(creationTime); +} - setCreationTime(ctime); +std::unique_ptr Fallout4VRSaveGame::fetchDataFields() const +{ + FileWrapper file(getFilepath(), "FO4_SAVEGAME"); //10bytes - file.readImage(384, true); + { + QString dummyName, dummyLocation; + unsigned short dummyLevel; + unsigned long dummySaveNumber; + FILETIME dummyTime; + + fetchInformationFields(file, dummySaveNumber, dummyName, dummyLevel, + dummyLocation, dummyTime); + } + + QString ignore; + std::unique_ptr fields = std::make_unique(); + + fields->Screenshot = file.readImage(384, true); uint8_t saveGameVersion = file.readChar(); file.read(ignore); // game version file.skip(); // plugin info size - file.readPlugins(); - if (saveGameVersion >= 68) - file.readLightPlugins(); -} + fields->Plugins = file.readPlugins(); + if (saveGameVersion >= 68) { + fields->LightPlugins = file.readLightPlugins(); + } + + return fields; +} \ No newline at end of file diff --git a/src/games/fallout4vr/src/fallout4vrsavegame.h b/src/games/fallout4vr/src/fallout4vrsavegame.h index 316c7cb8..aaa7230d 100644 --- a/src/games/fallout4vr/src/fallout4vrsavegame.h +++ b/src/games/fallout4vr/src/fallout4vrsavegame.h @@ -3,12 +3,27 @@ #include "gamebryosavegame.h" -namespace MOBase { class IPluginGame; } +#include + +class GameFallout4VR; class Fallout4VRSaveGame : public GamebryoSaveGame { public: - Fallout4VRSaveGame(QString const &fileName, MOBase::IPluginGame const *game, bool const lightEnabled = true); + Fallout4VRSaveGame(QString const &fileName, GameFallout4VR const *game); + +protected: + + // Fetch easy-to-access information. + void fetchInformationFields( + FileWrapper& file, + unsigned long& saveNumber, + QString& playerName, + unsigned short& playerLevel, + QString& playerLocation, + FILETIME& creationTime) const; + + std::unique_ptr fetchDataFields() const override; }; #endif // FALLOUT4VRSAVEGAME_H diff --git a/src/games/fallout4vr/src/fallout4vrsavegameinfo.cpp b/src/games/fallout4vr/src/fallout4vrsavegameinfo.cpp deleted file mode 100644 index efb407c3..00000000 --- a/src/games/fallout4vr/src/fallout4vrsavegameinfo.cpp +++ /dev/null @@ -1,19 +0,0 @@ -#include "fallout4vrsavegameinfo.h" - -#include "fallout4vrsavegame.h" -#include "gamegamebryo.h" - -Fallout4VRSaveGameInfo::Fallout4VRSaveGameInfo(GameGamebryo const *game) : - GamebryoSaveGameInfo(game) -{ -} - -Fallout4VRSaveGameInfo::~Fallout4VRSaveGameInfo() -{ -} - -const MOBase::ISaveGame *Fallout4VRSaveGameInfo::getSaveGameInfo(const QString &file) const -{ - return new Fallout4VRSaveGame(file, m_Game); -} - diff --git a/src/games/fallout4vr/src/fallout4vrsavegameinfo.h b/src/games/fallout4vr/src/fallout4vrsavegameinfo.h deleted file mode 100644 index 1ea49f51..00000000 --- a/src/games/fallout4vr/src/fallout4vrsavegameinfo.h +++ /dev/null @@ -1,17 +0,0 @@ -#ifndef SKYRIMSAVEGAMEINFO_H -#define SKYRIMSAVEGAMEINFO_H - -#include "gamebryosavegameinfo.h" - -class GameGamebryo; - -class Fallout4VRSaveGameInfo : public GamebryoSaveGameInfo -{ -public: - Fallout4VRSaveGameInfo(GameGamebryo const *game); - ~Fallout4VRSaveGameInfo(); - - virtual MOBase::ISaveGame const *getSaveGameInfo(QString const &file) const override; -}; - -#endif // SKYRIMSAVEGAMEINFO_H diff --git a/src/games/fallout4vr/src/fallout4vrscriptextender.cpp b/src/games/fallout4vr/src/fallout4vrscriptextender.cpp index 3266c5b4..8ae0e1b2 100644 --- a/src/games/fallout4vr/src/fallout4vrscriptextender.cpp +++ b/src/games/fallout4vr/src/fallout4vrscriptextender.cpp @@ -17,8 +17,3 @@ QString Fallout4VRScriptExtender::PluginPath() const { return "f4se/plugins"; } - -QStringList Fallout4VRScriptExtender::saveGameAttachmentExtensions() const -{ - return { }; -} diff --git a/src/games/fallout4vr/src/fallout4vrscriptextender.h b/src/games/fallout4vr/src/fallout4vrscriptextender.h index e13bbf16..4d738fce 100644 --- a/src/games/fallout4vr/src/fallout4vrscriptextender.h +++ b/src/games/fallout4vr/src/fallout4vrscriptextender.h @@ -13,8 +13,6 @@ public: virtual QString BinaryName() const override; virtual QString PluginPath() const override; - virtual QStringList saveGameAttachmentExtensions() const override; - }; #endif // FALLOUT4SCRIPTEXTENDER_H diff --git a/src/games/fallout4vr/src/gamefallout4vr.cpp b/src/games/fallout4vr/src/gamefallout4vr.cpp index 1890654a..fef6c37e 100644 --- a/src/games/fallout4vr/src/gamefallout4vr.cpp +++ b/src/games/fallout4vr/src/gamefallout4vr.cpp @@ -1,14 +1,15 @@ #include "gameFallout4vr.h" #include "fallout4vrdataarchives.h" -#include "fallout4vrsavegameinfo.h" #include "fallout4vrunmanagedmods.h" #include "fallout4vrmoddatachecker.h" #include "fallout4vrmoddatacontent.h" +#include "fallout4vrsavegame.h" #include #include #include +#include #include #include "versioninfo.h" @@ -40,7 +41,7 @@ bool GameFallout4VR::init(IOrganizer *moInfo) registerFeature(new GamebryoLocalSavegames(myGamesPath(), "fallout4custom.ini")); registerFeature(new Fallout4VRModDataChecker(this)); registerFeature(new Fallout4VRModDataContent(this)); - registerFeature(new Fallout4VRSaveGameInfo(this)); + registerFeature(new GamebryoSaveGameInfo(this)); registerFeature(new CreationGamePlugins(moInfo)); registerFeature(new Fallout4VRUnmangedMods(this)); @@ -128,6 +129,11 @@ QString GameFallout4VR::savegameSEExtension() const return "f4se"; } +std::shared_ptr GameFallout4VR::makeSaveGame(QString filePath) const +{ + return std::make_shared(filePath, this); +} + QString GameFallout4VR::steamAPPId() const { return "611660"; diff --git a/src/games/fallout4vr/src/gamefallout4vr.h b/src/games/fallout4vr/src/gamefallout4vr.h index 3a956862..15617b1a 100644 --- a/src/games/fallout4vr/src/gamefallout4vr.h +++ b/src/games/fallout4vr/src/gamefallout4vr.h @@ -25,8 +25,6 @@ public: // IPluginGame interface virtual QList executables() const override; virtual QList executableForcedLoads() const override; virtual void initializeProfile(const QDir &path, ProfileSettings settings) const override; - virtual QString savegameExtension() const override; - virtual QString savegameSEExtension() const override; virtual QString steamAPPId() const override; virtual QStringList primaryPlugins() const override; virtual QStringList gameVariants() const override; @@ -53,6 +51,10 @@ public: // IPlugin interface protected: + std::shared_ptr makeSaveGame(QString filePath) const override; + QString savegameExtension() const override; + QString savegameSEExtension() const override; + virtual QString identifyGamePath() const override; }; From 4d5e4e812f00445c764d6148b2d2bc70354296fb Mon Sep 17 00:00:00 2001 From: Jeremy Rimpo Date: Fri, 29 Jan 2021 10:53:34 -0600 Subject: [PATCH 1118/1544] [game_fallout4vr] [ci skip] Update artifacts paths for msbuild --- src/games/fallout4vr/appveyor.yml | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/src/games/fallout4vr/appveyor.yml b/src/games/fallout4vr/appveyor.yml index d88dc03d..2a42ba2a 100644 --- a/src/games/fallout4vr/appveyor.yml +++ b/src/games/fallout4vr/appveyor.yml @@ -22,11 +22,11 @@ build_script: if($LastExitCode -ne 0) { $host.SetShouldExit($LastExitCode ) } artifacts: -- path: build\src\game_fallout4vr.dll +- path: vsbuild\src\RelWithDebInfo\game_fallout4vr.dll name: game_fallout4vr_dll -- path: build\src\game_fallout4vr.pdb +- path: vsbuild\src\RelWithDebInfo\game_fallout4vr.pdb name: game_fallout4vr_pdb -- path: build\src\game_fallout4vr.lib +- path: vsbuild\src\RelWithDebInfo\game_fallout4vr.lib name: game_fallout4vr_lib on_success: - ps: Set-Location -Path $env:APPVEYOR_BUILD_FOLDER From 122b1f3ecdf9c153047595d85b2f4e99fd62055d Mon Sep 17 00:00:00 2001 From: Jeremy Rimpo Date: Fri, 29 Jan 2021 10:53:35 -0600 Subject: [PATCH 1119/1544] [game_falloutnv] [ci skip] Update artifacts paths for msbuild --- src/games/falloutnv/appveyor.yml | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/src/games/falloutnv/appveyor.yml b/src/games/falloutnv/appveyor.yml index 5986a05d..78c3cb1b 100644 --- a/src/games/falloutnv/appveyor.yml +++ b/src/games/falloutnv/appveyor.yml @@ -22,11 +22,11 @@ build_script: if($LastExitCode -ne 0) { $host.SetShouldExit($LastExitCode ) } artifacts: -- path: build\src\game_falloutNV.dll +- path: vsbuild\src\RelWithDebInfo\game_falloutNV.dll name: game_falloutNV_dll -- path: build\src\game_falloutNV.pdb +- path: vsbuild\src\RelWithDebInfo\game_falloutNV.pdb name: game_falloutNV_pdb -- path: build\src\game_falloutNV.lib +- path: vsbuild\src\RelWithDebInfo\game_falloutNV.lib name: game_falloutNVe_lib on_success: - ps: Set-Location -Path $env:APPVEYOR_BUILD_FOLDER From 604d85ab924f4760c33e2e8f27055d31e8897ae8 Mon Sep 17 00:00:00 2001 From: Jeremy Rimpo Date: Fri, 29 Jan 2021 10:53:36 -0600 Subject: [PATCH 1120/1544] [game_morrowind] [ci skip] Update artifacts paths for msbuild --- src/games/morrowind/appveyor.yml | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/src/games/morrowind/appveyor.yml b/src/games/morrowind/appveyor.yml index d14f97cd..97872c2b 100644 --- a/src/games/morrowind/appveyor.yml +++ b/src/games/morrowind/appveyor.yml @@ -22,11 +22,11 @@ build_script: if($LastExitCode -ne 0) { $host.SetShouldExit($LastExitCode ) } artifacts: -- path: build\src\game_morrowind.dll +- path: vsbuild\src\RelWithDebInfo\game_morrowind.dll name: game_morrowind_dll -- path: build\src\game_morrowind.pdb +- path: vsbuild\src\RelWithDebInfo\game_morrowind.pdb name: game_morrowind_pdb -- path: build\src\game_morrowind.lib +- path: vsbuild\src\RelWithDebInfo\game_morrowind.lib name: game_morrowind_lib on_success: - ps: Set-Location -Path $env:APPVEYOR_BUILD_FOLDER From 0e15e20b72aca8dbff6aba8ed684e817ce38bfeb Mon Sep 17 00:00:00 2001 From: Jeremy Rimpo Date: Fri, 29 Jan 2021 10:53:38 -0600 Subject: [PATCH 1121/1544] [game_fallout4] [ci skip] Update artifacts paths for msbuild --- src/games/fallout4/appveyor.yml | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/src/games/fallout4/appveyor.yml b/src/games/fallout4/appveyor.yml index 07c567fd..1e625dd0 100644 --- a/src/games/fallout4/appveyor.yml +++ b/src/games/fallout4/appveyor.yml @@ -22,11 +22,11 @@ build_script: if($LastExitCode -ne 0) { $host.SetShouldExit($LastExitCode ) } artifacts: -- path: build\src\game_fallout4.dll +- path: vsbuild\src\RelWithDebInfo\game_fallout4.dll name: game_fallout4_dll -- path: build\src\game_fallout4.pdb +- path: vsbuild\src\RelWithDebInfo\game_fallout4.pdb name: game_fallout4_pdb -- path: build\src\game_fallout4.lib +- path: vsbuild\src\RelWithDebInfo\game_fallout4.lib name: game_fallout4_lib on_success: - ps: Set-Location -Path $env:APPVEYOR_BUILD_FOLDER From c6c99bf35560d45658d2dc6b4fac9526576b50fa Mon Sep 17 00:00:00 2001 From: Jeremy Rimpo Date: Fri, 29 Jan 2021 10:53:39 -0600 Subject: [PATCH 1122/1544] [game_skyrimvr] [ci skip] Update artifacts paths for msbuild --- src/games/skyrimvr/appveyor.yml | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/src/games/skyrimvr/appveyor.yml b/src/games/skyrimvr/appveyor.yml index f37f060f..7707d706 100644 --- a/src/games/skyrimvr/appveyor.yml +++ b/src/games/skyrimvr/appveyor.yml @@ -22,11 +22,11 @@ build_script: if($LastExitCode -ne 0) { $host.SetShouldExit($LastExitCode ) } artifacts: -- path: build\src\game_skyrimvr.dll +- path: vsbuild\src\RelWithDebInfo\game_skyrimvr.dll name: game_skyrimvr_dll -- path: build\src\game_skyrimvr.pdb +- path: vsbuild\src\RelWithDebInfo\game_skyrimvr.pdb name: game_skyrimvr_pdb -- path: build\src\game_skyrimvr.lib +- path: vsbuild\src\RelWithDebInfo\game_skyrimvr.lib name: game_skyrimvr_lib on_success: - ps: Set-Location -Path $env:APPVEYOR_BUILD_FOLDER From a54b4d2b133c374257f2c9a7a2bda134b00b1ad6 Mon Sep 17 00:00:00 2001 From: Jeremy Rimpo Date: Fri, 29 Jan 2021 10:53:39 -0600 Subject: [PATCH 1123/1544] [game_oblivion] [ci skip] Update artifacts paths for msbuild --- src/games/oblivion/appveyor.yml | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/src/games/oblivion/appveyor.yml b/src/games/oblivion/appveyor.yml index 8d8164c1..998a5f8b 100644 --- a/src/games/oblivion/appveyor.yml +++ b/src/games/oblivion/appveyor.yml @@ -22,11 +22,11 @@ build_script: if($LastExitCode -ne 0) { $host.SetShouldExit($LastExitCode ) } artifacts: -- path: build\src\game_oblivion.dll +- path: vsbuild\src\RelWithDebInfo\game_oblivion.dll name: game_oblivion_dll -- path: build\src\game_oblivion.pdb +- path: vsbuild\src\RelWithDebInfo\game_oblivion.pdb name: game_oblivion_pdb -- path: build\src\game_oblivion.lib +- path: vsbuild\src\RelWithDebInfo\game_oblivion.lib name: game_oblivion_lib on_success: - ps: Set-Location -Path $env:APPVEYOR_BUILD_FOLDER From a608e40b27487164399a41bdee6510f1a29040e0 Mon Sep 17 00:00:00 2001 From: Jeremy Rimpo Date: Fri, 29 Jan 2021 10:53:41 -0600 Subject: [PATCH 1124/1544] [game_fallout3] [ci skip] Update artifacts paths for msbuild --- src/games/fallout3/appveyor.yml | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/src/games/fallout3/appveyor.yml b/src/games/fallout3/appveyor.yml index 61925c54..b5abb0e1 100644 --- a/src/games/fallout3/appveyor.yml +++ b/src/games/fallout3/appveyor.yml @@ -22,11 +22,11 @@ build_script: if($LastExitCode -ne 0) { $host.SetShouldExit($LastExitCode ) } artifacts: -- path: build\src\game_fallout3.dll +- path: vsbuild\src\RelWithDebInfo\game_fallout3.dll name: game_fallout3_dll -- path: build\src\game_fallout3.pdb +- path: vsbuild\src\RelWithDebInfo\game_fallout3.pdb name: game_fallout3_pdb -- path: build\src\game_fallout3.lib +- path: vsbuild\src\RelWithDebInfo\game_fallout3.lib name: game_fallout3_lib on_success: - ps: Set-Location -Path $env:APPVEYOR_BUILD_FOLDER From 64241740168b172b65ccded8bca89bde3f12de28 Mon Sep 17 00:00:00 2001 From: Jeremy Rimpo Date: Fri, 29 Jan 2021 10:53:41 -0600 Subject: [PATCH 1125/1544] [game_skyrimse] [ci skip] Update artifacts paths for msbuild --- src/games/skyrimse/appveyor.yml | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/src/games/skyrimse/appveyor.yml b/src/games/skyrimse/appveyor.yml index 1b943e5e..2faa4a11 100644 --- a/src/games/skyrimse/appveyor.yml +++ b/src/games/skyrimse/appveyor.yml @@ -22,11 +22,11 @@ build_script: if($LastExitCode -ne 0) { $host.SetShouldExit($LastExitCode ) } artifacts: -- path: build\src\game_skyrimse.dll +- path: vsbuild\src\RelWithDebInfo\game_skyrimse.dll name: game_skyrimse_dll -- path: build\src\game_skyrimse.pdb +- path: vsbuild\src\RelWithDebInfo\game_skyrimse.pdb name: game_skyrimse_pdb -- path: build\src\game_skyrimse.lib +- path: vsbuild\src\RelWithDebInfo\game_skyrimse.lib name: game_skyrimse_lib on_success: - ps: Set-Location -Path $env:APPVEYOR_BUILD_FOLDER From 9036658aa06ce560723e278a9911801bbb719bc5 Mon Sep 17 00:00:00 2001 From: Jeremy Rimpo Date: Fri, 29 Jan 2021 10:53:42 -0600 Subject: [PATCH 1126/1544] [ci skip] Update artifacts paths for msbuild --- appveyor.yml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/appveyor.yml b/appveyor.yml index bea8130b..fbc95807 100644 --- a/appveyor.yml +++ b/appveyor.yml @@ -22,9 +22,9 @@ build_script: if($LastExitCode -ne 0) { $host.SetShouldExit($LastExitCode ) } artifacts: -- path: build\src\gamebryo\game_gamebryo.lib +- path: vsbuild\src\RelWithDebInfo\gamebryo\game_gamebryo.lib name: game_gamebryo_lib -- path: build\src\creation\game_creation.lib +- path: vsbuild\src\RelWithDebInfo\creation\game_creation.lib name: game_creation_lib on_success: - ps: Set-Location -Path $env:APPVEYOR_BUILD_FOLDER From 49173697894302c01b4fb0d82011cfe9465f3a77 Mon Sep 17 00:00:00 2001 From: Jeremy Rimpo Date: Fri, 29 Jan 2021 10:53:44 -0600 Subject: [PATCH 1127/1544] [game_skyrim] [ci skip] Update artifacts paths for msbuild --- src/games/skyrim/appveyor.yml | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/src/games/skyrim/appveyor.yml b/src/games/skyrim/appveyor.yml index c5ed68a3..3bc4f719 100644 --- a/src/games/skyrim/appveyor.yml +++ b/src/games/skyrim/appveyor.yml @@ -22,11 +22,11 @@ build_script: if($LastExitCode -ne 0) { $host.SetShouldExit($LastExitCode ) } artifacts: -- path: build\src\game_skyrim.dll +- path: vsbuild\src\RelWithDebInfo\game_skyrim.dll name: game_skyrim_dll -- path: build\src\game_skyrim.pdb +- path: vsbuild\src\RelWithDebInfo\game_skyrim.pdb name: game_skyrim_pdb -- path: build\src\game_skyrim.lib +- path: vsbuild\src\RelWithDebInfo\game_skyrim.lib name: game_skyrim_lib on_success: - ps: Set-Location -Path $env:APPVEYOR_BUILD_FOLDER From 9af9cff9298f1f2d138d862647e12663e18f5ee4 Mon Sep 17 00:00:00 2001 From: Jeremy Rimpo Date: Fri, 29 Jan 2021 10:53:47 -0600 Subject: [PATCH 1128/1544] [game_ttw] [ci skip] Update artifacts paths for msbuild --- src/games/ttw/appveyor.yml | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/src/games/ttw/appveyor.yml b/src/games/ttw/appveyor.yml index e0300424..5b490bd8 100644 --- a/src/games/ttw/appveyor.yml +++ b/src/games/ttw/appveyor.yml @@ -22,11 +22,11 @@ build_script: if($LastExitCode -ne 0) { $host.SetShouldExit($LastExitCode ) } artifacts: -- path: build\src\game_ttw.dll +- path: vsbuild\src\RelWithDebInfo\game_ttw.dll name: game_ttw_dll -- path: build\src\game_ttw.pdb +- path: vsbuild\src\RelWithDebInfo\game_ttw.pdb name: game_ttw_pdb -- path: build\src\game_ttw.lib +- path: vsbuild\src\RelWithDebInfo\game_ttw.lib name: game_ttw_lib on_success: - ps: Set-Location -Path $env:APPVEYOR_BUILD_FOLDER From b7c5c71daf12a35781609d247d338727b2985952 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Mika=C3=ABl=20Capelle?= Date: Sun, 31 Jan 2021 16:12:43 +0100 Subject: [PATCH 1129/1544] Make reading the plugin list case-insensitive. --- src/creation/creationgameplugins.cpp | 73 ++++++++++++++-------------- src/game_gamebryo_en.ts | 24 +++++---- src/gamebryo/gamebryogameplugins.cpp | 59 +++++++++++----------- 3 files changed, 80 insertions(+), 76 deletions(-) diff --git a/src/creation/creationgameplugins.cpp b/src/creation/creationgameplugins.cpp index 6753606e..45bedc30 100644 --- a/src/creation/creationgameplugins.cpp +++ b/src/creation/creationgameplugins.cpp @@ -66,7 +66,7 @@ void CreationGamePlugins::writePluginList(const IPluginList *pluginList, //TODO: do not write plugins in OFFICIAL_FILES container for (const QString &pluginName : plugins) { - if (!PrimaryPlugins.contains(pluginName,Qt::CaseInsensitive)) { + if (!PrimaryPlugins.contains(pluginName,Qt::CaseInsensitive)) { if (pluginList->state(pluginName) == IPluginList::STATE_ACTIVE) { if (!textCodec->canEncode(pluginName)) { invalidFileNames = true; @@ -81,8 +81,8 @@ void CreationGamePlugins::writePluginList(const IPluginList *pluginList, file->write("\r\n"); ++writtenCount; } - else - { + else + { if (!textCodec->canEncode(pluginName)) { invalidFileNames = true; qCritical("invalid plugin name %s", qUtf8Printable(pluginName)); @@ -93,7 +93,7 @@ void CreationGamePlugins::writePluginList(const IPluginList *pluginList, } file->write("\r\n"); ++writtenCount; - } + } } } @@ -109,8 +109,8 @@ void CreationGamePlugins::writePluginList(const IPluginList *pluginList, QStringList CreationGamePlugins::readPluginList(MOBase::IPluginList *pluginList) { - QStringList plugins = pluginList->pluginNames(); - QStringList primaryPlugins = organizer()->managedGame()->primaryPlugins(); + const auto plugins = pluginList->pluginNames(); + const auto primaryPlugins = organizer()->managedGame()->primaryPlugins(); QStringList loadOrder(primaryPlugins); for (const QString &pluginName : loadOrder) { @@ -134,46 +134,47 @@ QStringList CreationGamePlugins::readPluginList(MOBase::IPluginList *pluginList) return loadOrder; } + QStringList pluginsFound; while (!file.atEnd()) { QByteArray line = file.readLine(); QString pluginName; if ((line.size() > 0) && (line.at(0) != '#')) { pluginName = localCodec()->toUnicode(line.trimmed().constData()); } - if (!primaryPlugins.contains(pluginName, Qt::CaseInsensitive)) { - if (pluginName.startsWith('*')) { - pluginName.remove(0, 1); - if (pluginName.size() > 0) { - pluginList->setState(pluginName, IPluginList::STATE_ACTIVE); - plugins.removeAll(pluginName); - if (!loadOrder.contains(pluginName, Qt::CaseInsensitive)) { - loadOrder.append(pluginName); - } - } - } - else - { - if (pluginName.size() > 0) { - pluginList->setState(pluginName, IPluginList::STATE_INACTIVE); - plugins.removeAll(pluginName); - if (!loadOrder.contains(pluginName, Qt::CaseInsensitive)) { - loadOrder.append(pluginName); - } - } - } - } - else - { - pluginName.remove(0, 1); - plugins.removeAll(pluginName); - } + if (!primaryPlugins.contains(pluginName, Qt::CaseInsensitive)) { + if (pluginName.startsWith('*')) { + pluginName.remove(0, 1); + if (pluginName.size() > 0) { + pluginList->setState(pluginName, IPluginList::STATE_ACTIVE); + pluginsFound.append(pluginName); + if (!loadOrder.contains(pluginName, Qt::CaseInsensitive)) { + loadOrder.append(pluginName); + } + } + } + else { + if (pluginName.size() > 0) { + pluginList->setState(pluginName, IPluginList::STATE_INACTIVE); + pluginsFound.append(pluginName); + if (!loadOrder.contains(pluginName, Qt::CaseInsensitive)) { + loadOrder.append(pluginName); + } + } + } + } + else { + pluginName.remove(0, 1); + pluginsFound.append(pluginName); + } } file.close(); - // we removed each plugin found in the file, so what's left are inactive mods - for (const QString &pluginName : plugins) { - pluginList->setState(pluginName, IPluginList::STATE_INACTIVE); + // set all plugins not found inactive + for (const auto& pluginName : plugins) { + if (!pluginsFound.contains(pluginName, Qt::CaseInsensitive)) { + pluginList->setState(pluginName, IPluginList::STATE_INACTIVE); + } } return loadOrder; diff --git a/src/game_gamebryo_en.ts b/src/game_gamebryo_en.ts index a5cbfcd0..e4ecb50c 100644 --- a/src/game_gamebryo_en.ts +++ b/src/game_gamebryo_en.ts @@ -102,23 +102,23 @@ - + Has Script Extender Data - + Missing ESPs - - + + None - + Missing ESLs @@ -126,28 +126,32 @@ QObject - Some of your plugins have invalid names! These plugins can not be loaded by the game. Please see mo_interface.log for a list of affected plugins and rename them. - + + %1, #%2, Level %3, %4 + + + + failed to open %1 - + wrong file format - expected %1 got %2 - + failed to query registry path (preflight): %1 - + failed to query registry path (read): %1 diff --git a/src/gamebryo/gamebryogameplugins.cpp b/src/gamebryo/gamebryogameplugins.cpp index 71683a60..3c116a05 100644 --- a/src/gamebryo/gamebryogameplugins.cpp +++ b/src/gamebryo/gamebryogameplugins.cpp @@ -167,16 +167,16 @@ QStringList GamebryoGamePlugins::readLoadOrderList( QStringList GamebryoGamePlugins::readPluginList(MOBase::IPluginList *pluginList) { QStringList primary = organizer()->managedGame()->primaryPlugins(); for (const QString &pluginName : primary) { - if (pluginList->state(pluginName) != IPluginList::STATE_MISSING) { - pluginList->setState(pluginName, IPluginList::STATE_ACTIVE); - } + if (pluginList->state(pluginName) != IPluginList::STATE_MISSING) { + pluginList->setState(pluginName, IPluginList::STATE_ACTIVE); + } } QStringList plugins = pluginList->pluginNames(); QStringList pluginsClone(plugins); // Do not sort the primary plugins. Their load order should be locked as defined in "primaryPlugins". - for (QString plugin : pluginsClone) { - if (primary.contains(plugin, Qt::CaseInsensitive)) - plugins.removeAll(plugin); + for (const auto& plugin : pluginsClone) { + if (primary.contains(plugin, Qt::CaseInsensitive)) + plugins.removeAll(plugin); } // Always use filetime loadorder to get the actual load order @@ -200,43 +200,42 @@ QStringList GamebryoGamePlugins::readPluginList(MOBase::IPluginList *pluginList) QString filePath = organizer()->profile()->absolutePath() + "/plugins.txt"; QFile file(filePath); if (!file.open(QIODevice::ReadOnly)) { - pluginsTxtExists = false; + pluginsTxtExists = false; } ON_BLOCK_EXIT([&]() { - file.close(); + file.close(); }); if (file.size() == 0) { - // MO stores at least a header in the file. if it's completely empty the - // file is broken - pluginsTxtExists = false; + // MO stores at least a header in the file. if it's completely empty the + // file is broken + pluginsTxtExists = false; } QStringList activePlugins; QStringList inactivePlugins; if (pluginsTxtExists) { - while (!file.atEnd()) { - QByteArray line = file.readLine(); - QString pluginName; - if ((line.size() > 0) && (line.at(0) != '#')) { - pluginName = m_LocalCodec->toUnicode(line.trimmed().constData()); - } - if (pluginName.size() > 0) { - pluginList->setState(pluginName, IPluginList::STATE_ACTIVE); - activePlugins.push_back(pluginName); - } + while (!file.atEnd()) { + QByteArray line = file.readLine(); + QString pluginName; + if ((line.size() > 0) && (line.at(0) != '#')) { + pluginName = m_LocalCodec->toUnicode(line.trimmed().constData()); } + if (pluginName.size() > 0) { + pluginList->setState(pluginName, IPluginList::STATE_ACTIVE); + activePlugins.push_back(pluginName); + } + } - for (const QString &pluginName : plugins) - if (!activePlugins.contains(pluginName)) - inactivePlugins.push_back(pluginName); - - for (const QString &pluginName : inactivePlugins) - pluginList->setState(pluginName, IPluginList::STATE_INACTIVE); + for (const auto& pluginName : plugins) { + if (!activePlugins.contains(pluginName, Qt::CaseInsensitive)) { + pluginList->setState(pluginName, IPluginList::STATE_INACTIVE); + } + } } else { - for (const QString &pluginName : plugins) { - pluginList->setState(pluginName, IPluginList::STATE_INACTIVE); - } + for (const QString &pluginName : plugins) { + pluginList->setState(pluginName, IPluginList::STATE_INACTIVE); + } } return primary + plugins; From e5d425ecbb3e81c1c44b19c81e204d596af24afc Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Mika=C3=ABl=20Capelle?= Date: Tue, 2 Feb 2021 20:39:12 +0100 Subject: [PATCH 1130/1544] [game_falloutnv] Update translation file. --- src/games/falloutnv/src/game_falloutNV_en.ts | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/src/games/falloutnv/src/game_falloutNV_en.ts b/src/games/falloutnv/src/game_falloutNV_en.ts index a44dd734..f100d146 100644 --- a/src/games/falloutnv/src/game_falloutNV_en.ts +++ b/src/games/falloutnv/src/game_falloutNV_en.ts @@ -4,7 +4,12 @@ GameFalloutNV - + + Fallout NV Support Plugin + + + + Adds support for the game Fallout New Vegas From 44bcfaccb3b0dea6e95c06576fb9a3c78cd4e1a7 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Mika=C3=ABl=20Capelle?= Date: Tue, 2 Feb 2021 20:39:12 +0100 Subject: [PATCH 1131/1544] [game_fallout4vr] Update translation file. --- src/games/fallout4vr/src/game_fallout4vr_en.ts | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/src/games/fallout4vr/src/game_fallout4vr_en.ts b/src/games/fallout4vr/src/game_fallout4vr_en.ts index 916a4158..6a642dfa 100644 --- a/src/games/fallout4vr/src/game_fallout4vr_en.ts +++ b/src/games/fallout4vr/src/game_fallout4vr_en.ts @@ -4,7 +4,12 @@ GameFallout4VR - + + Fallout 4 VR Support Plugin + + + + Adds support for the game Fallout 4 VR. Splash by %1 From fece1656cad733e1688660a2a7341fa83e832b7b Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Mika=C3=ABl=20Capelle?= Date: Tue, 2 Feb 2021 20:39:12 +0100 Subject: [PATCH 1132/1544] [game_fallout4] Update translation file. --- src/games/fallout4/src/game_fallout4_en.ts | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/src/games/fallout4/src/game_fallout4_en.ts b/src/games/fallout4/src/game_fallout4_en.ts index b80846b9..addc4d66 100644 --- a/src/games/fallout4/src/game_fallout4_en.ts +++ b/src/games/fallout4/src/game_fallout4_en.ts @@ -4,7 +4,12 @@ GameFallout4 - + + Fallout 4 Support Plugin + + + + Adds support for the game Fallout 4. Splash by %1 From be9e53323b0a93525b107103e8debea977635bf4 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Mika=C3=ABl=20Capelle?= Date: Tue, 2 Feb 2021 20:39:12 +0100 Subject: [PATCH 1133/1544] [game_fallout3] Update translation file. --- src/games/fallout3/src/game_fallout3_en.ts | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/src/games/fallout3/src/game_fallout3_en.ts b/src/games/fallout3/src/game_fallout3_en.ts index a6f77373..39f10bc8 100644 --- a/src/games/fallout3/src/game_fallout3_en.ts +++ b/src/games/fallout3/src/game_fallout3_en.ts @@ -4,7 +4,12 @@ GameFallout3 - + + Fallout 3 Support Plugin + + + + Adds support for the game Fallout 3s From 37b762fcba1fe29002c8e09970d81b20bc227229 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Mika=C3=ABl=20Capelle?= Date: Tue, 2 Feb 2021 20:39:12 +0100 Subject: [PATCH 1134/1544] [game_morrowind] Update translation file. --- src/games/morrowind/src/game_morrowind_en.ts | 11 ++++++++--- 1 file changed, 8 insertions(+), 3 deletions(-) diff --git a/src/games/morrowind/src/game_morrowind_en.ts b/src/games/morrowind/src/game_morrowind_en.ts index 226f1bdf..4b1afd58 100644 --- a/src/games/morrowind/src/game_morrowind_en.ts +++ b/src/games/morrowind/src/game_morrowind_en.ts @@ -4,7 +4,12 @@ GameMorrowind - + + Morrowind Support Plugin + + + + Adds support for the game Morrowind. Splash by %1 @@ -43,12 +48,12 @@ Splash by %1 - + Missing ESPs - + None From a20943e22578c0523b6772227416106979ace19e Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Mika=C3=ABl=20Capelle?= Date: Tue, 2 Feb 2021 20:39:13 +0100 Subject: [PATCH 1135/1544] [game_skyrimse] Update translation file. --- src/games/skyrimse/src/game_skyrimse_en.ts | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/src/games/skyrimse/src/game_skyrimse_en.ts b/src/games/skyrimse/src/game_skyrimse_en.ts index 30758a37..d7f078f7 100644 --- a/src/games/skyrimse/src/game_skyrimse_en.ts +++ b/src/games/skyrimse/src/game_skyrimse_en.ts @@ -4,7 +4,12 @@ GameSkyrimSE - + + Skyrim Special Edition Support Plugin + + + + Adds support for the game Skyrim Special Edition. From 600c511419c465b6397a0c4412db83c2f899bb4d Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Mika=C3=ABl=20Capelle?= Date: Tue, 2 Feb 2021 20:39:13 +0100 Subject: [PATCH 1136/1544] [game_ttw] Update translation file. --- src/games/ttw/src/game_ttw_en.ts | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/src/games/ttw/src/game_ttw_en.ts b/src/games/ttw/src/game_ttw_en.ts index 18ee55e7..087ed480 100644 --- a/src/games/ttw/src/game_ttw_en.ts +++ b/src/games/ttw/src/game_ttw_en.ts @@ -4,7 +4,12 @@ GameFalloutTTW - + + Fallout TTW Support Plugin + + + + Adds support for the game Fallout TTW From 6622034ad8a3f356c9f226377b3f2dd63be86c8a Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Mika=C3=ABl=20Capelle?= Date: Tue, 2 Feb 2021 20:39:13 +0100 Subject: [PATCH 1137/1544] [game_skyrimvr] Update translation file. --- src/games/skyrimvr/src/game_skyrimvr_en.ts | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/src/games/skyrimvr/src/game_skyrimvr_en.ts b/src/games/skyrimvr/src/game_skyrimvr_en.ts index 398fc857..ecc3f2a7 100644 --- a/src/games/skyrimvr/src/game_skyrimvr_en.ts +++ b/src/games/skyrimvr/src/game_skyrimvr_en.ts @@ -4,7 +4,12 @@ GameSkyrimVR - + + Skyrim VR Support Plugin + + + + Adds support for the game Skyrim VR. From d567dc8c49d546593c20333de5d7854573bf8cdd Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Mika=C3=ABl=20Capelle?= Date: Tue, 2 Feb 2021 20:39:13 +0100 Subject: [PATCH 1138/1544] [game_skyrim] Update translation file. --- src/games/skyrim/src/game_skyrim_en.ts | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/src/games/skyrim/src/game_skyrim_en.ts b/src/games/skyrim/src/game_skyrim_en.ts index 4cf9d8ce..6a04abbd 100644 --- a/src/games/skyrim/src/game_skyrim_en.ts +++ b/src/games/skyrim/src/game_skyrim_en.ts @@ -4,7 +4,12 @@ GameSkyrim - + + Skyrim Support Plugin + + + + Adds support for the game Skyrim From 0242ed79ad5a9e79c9668573cdde1424a78a1eac Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Mika=C3=ABl=20Capelle?= Date: Tue, 2 Feb 2021 20:39:13 +0100 Subject: [PATCH 1139/1544] [game_oblivion] Update translation file. --- src/games/oblivion/src/game_oblivion_en.ts | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/src/games/oblivion/src/game_oblivion_en.ts b/src/games/oblivion/src/game_oblivion_en.ts index 16dffce9..ad614a85 100644 --- a/src/games/oblivion/src/game_oblivion_en.ts +++ b/src/games/oblivion/src/game_oblivion_en.ts @@ -4,7 +4,12 @@ GameOblivion - + + Oblivion Support Plugin + + + + Adds support for the game Oblivion From 5d76c3f243338067193591ff585d001bffd011dd Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Mika=C3=ABl=20Capelle?= Date: Wed, 24 Feb 2021 21:52:02 +0100 Subject: [PATCH 1140/1544] [game_enderalse] Initial commit. --- src/games/enderalse/.gitignore | 5 + src/games/enderalse/CMakeLists.txt | 12 + src/games/enderalse/appveyor.yml | 40 +++ src/games/enderalse/src/CMakeLists.txt | 7 + .../src/enderalsebsainvalidation.cpp | 16 + .../enderalse/src/enderalsebsainvalidation.h | 23 ++ .../enderalse/src/enderalsedataarchives.cpp | 66 ++++ .../enderalse/src/enderalsedataarchives.h | 29 ++ .../enderalse/src/enderalsemoddatachecker.h | 30 ++ .../enderalse/src/enderalsemoddatacontent.h | 20 ++ src/games/enderalse/src/enderalsesavegame.cpp | 116 ++++++++ src/games/enderalse/src/enderalsesavegame.h | 29 ++ .../enderalse/src/enderalsescriptextender.cpp | 19 ++ .../enderalse/src/enderalsescriptextender.h | 18 ++ .../enderalse/src/enderalseunmanagedmods.cpp | 32 ++ .../enderalse/src/enderalseunmanagedmods.h | 19 ++ src/games/enderalse/src/game_enderalse_en.ts | 17 ++ src/games/enderalse/src/gameenderalse.cpp | 281 ++++++++++++++++++ src/games/enderalse/src/gameenderalse.h | 75 +++++ src/games/enderalse/src/gameenderalse.json | 1 + 20 files changed, 855 insertions(+) create mode 100644 src/games/enderalse/.gitignore create mode 100644 src/games/enderalse/CMakeLists.txt create mode 100644 src/games/enderalse/appveyor.yml create mode 100644 src/games/enderalse/src/CMakeLists.txt create mode 100644 src/games/enderalse/src/enderalsebsainvalidation.cpp create mode 100644 src/games/enderalse/src/enderalsebsainvalidation.h create mode 100644 src/games/enderalse/src/enderalsedataarchives.cpp create mode 100644 src/games/enderalse/src/enderalsedataarchives.h create mode 100644 src/games/enderalse/src/enderalsemoddatachecker.h create mode 100644 src/games/enderalse/src/enderalsemoddatacontent.h create mode 100644 src/games/enderalse/src/enderalsesavegame.cpp create mode 100644 src/games/enderalse/src/enderalsesavegame.h create mode 100644 src/games/enderalse/src/enderalsescriptextender.cpp create mode 100644 src/games/enderalse/src/enderalsescriptextender.h create mode 100644 src/games/enderalse/src/enderalseunmanagedmods.cpp create mode 100644 src/games/enderalse/src/enderalseunmanagedmods.h create mode 100644 src/games/enderalse/src/game_enderalse_en.ts create mode 100644 src/games/enderalse/src/gameenderalse.cpp create mode 100644 src/games/enderalse/src/gameenderalse.h create mode 100644 src/games/enderalse/src/gameenderalse.json diff --git a/src/games/enderalse/.gitignore b/src/games/enderalse/.gitignore new file mode 100644 index 00000000..cf71be77 --- /dev/null +++ b/src/games/enderalse/.gitignore @@ -0,0 +1,5 @@ +edit +CMakeLists.txt.user +/msbuild.log +/*std*.log +/*build diff --git a/src/games/enderalse/CMakeLists.txt b/src/games/enderalse/CMakeLists.txt new file mode 100644 index 00000000..feaf7fdd --- /dev/null +++ b/src/games/enderalse/CMakeLists.txt @@ -0,0 +1,12 @@ +cmake_minimum_required(VERSION 3.16) + +project(game_enderalse) +set(project_type plugin) +set(enable_warnings OFF) + +if(DEFINED DEPENDENCIES_DIR) + include(${DEPENDENCIES_DIR}/modorganizer_super/cmake_common/project.cmake) +else() + include(../cmake_common/project.cmake) +endif() +add_subdirectory(src) diff --git a/src/games/enderalse/appveyor.yml b/src/games/enderalse/appveyor.yml new file mode 100644 index 00000000..2faa4a11 --- /dev/null +++ b/src/games/enderalse/appveyor.yml @@ -0,0 +1,40 @@ +version: 1.0.{build} +skip_branch_with_pr: true +image: Visual Studio 2019 +environment: + WEBHOOK_URL: + secure: gOKbXaZM9ImtMD5XrYITvdyZUW/az082G9OIN1EC1Vbg57wBaeLhi49uGjxPw5GVujHku6kxN6ab89zhbS5GVeluR76GM83IbKV4Sh7udXzoYZZdg6YudtYHzdhCgUeiedpswbuczTq9ceIkkfSEWZuh/lMAAVVwvcGsJAnoPFw= +build_script: +- pwsh: >- + $ErrorActionPreference = 'Stop' + + git clone --depth=1 --no-single-branch https://github.com/ModOrganizer2/modorganizer-umbrella.git c:\projects\modorganizer-umbrella + + New-Item -ItemType Directory -Path c:\projects\modorganizer-build + + cd c:\projects\modorganizer-umbrella + + ($env:APPVEYOR_PULL_REQUEST_HEAD_REPO_BRANCH -eq $null) ? ($branch = $env:APPVEYOR_REPO_BRANCH) : ($branch = $env:APPVEYOR_PULL_REQUEST_HEAD_REPO_BRANCH) + + git checkout $(git show-ref --verify --quiet refs/remotes/origin/${branch} || echo '-b') ${branch} + + C:\Python37-x64\python.exe unimake.py -d c:\projects\modorganizer-build -s Appveyor_Build=True ${env:APPVEYOR_PROJECT_NAME} + + if($LastExitCode -ne 0) { $host.SetShouldExit($LastExitCode ) } +artifacts: +- path: vsbuild\src\RelWithDebInfo\game_skyrimse.dll + name: game_skyrimse_dll +- path: vsbuild\src\RelWithDebInfo\game_skyrimse.pdb + name: game_skyrimse_pdb +- path: vsbuild\src\RelWithDebInfo\game_skyrimse.lib + name: game_skyrimse_lib +on_success: + - ps: Set-Location -Path $env:APPVEYOR_BUILD_FOLDER + - ps: Invoke-RestMethod https://raw.githubusercontent.com/DiscordHooks/appveyor-discord-webhook/master/send.ps1 -o send.ps1 + - ps: ./send.ps1 success $env:WEBHOOK_URL +on_failure: + - ps: Set-Location -Path $env:APPVEYOR_BUILD_FOLDER + - ps: Push-AppveyorArtifact ${env:APPVEYOR_BUILD_FOLDER}\stdout.log + - ps: Push-AppveyorArtifact ${env:APPVEYOR_BUILD_FOLDER}\stderr.log + - ps: Invoke-RestMethod https://raw.githubusercontent.com/DiscordHooks/appveyor-discord-webhook/master/send.ps1 -o send.ps1 + - ps: ./send.ps1 failure $env:WEBHOOK_URL \ No newline at end of file diff --git a/src/games/enderalse/src/CMakeLists.txt b/src/games/enderalse/src/CMakeLists.txt new file mode 100644 index 00000000..1f12c529 --- /dev/null +++ b/src/games/enderalse/src/CMakeLists.txt @@ -0,0 +1,7 @@ +cmake_minimum_required(VERSION 3.16) +if(DEFINED DEPENDENCIES_DIR) + include(${DEPENDENCIES_DIR}/modorganizer_super/cmake_common/src.cmake) +else() + include(../../cmake_common/src.cmake) +endif() +requires_project(game_gamebryo game_features) diff --git a/src/games/enderalse/src/enderalsebsainvalidation.cpp b/src/games/enderalse/src/enderalsebsainvalidation.cpp new file mode 100644 index 00000000..523c2de9 --- /dev/null +++ b/src/games/enderalse/src/enderalsebsainvalidation.cpp @@ -0,0 +1,16 @@ +#include "enderalsebsainvalidation.h" + +EnderalSEBSAInvalidation::EnderalSEBSAInvalidation(DataArchives* dataArchives, MOBase::IPluginGame const* game) + : GamebryoBSAInvalidation(dataArchives, "skyrim.ini", game) +{ +} + +QString EnderalSEBSAInvalidation::invalidationBSAName() const +{ + return "Enderal - Invalidation.bsa"; +} + +unsigned long EnderalSEBSAInvalidation::bsaVersion() const +{ + return 0x69; +} \ No newline at end of file diff --git a/src/games/enderalse/src/enderalsebsainvalidation.h b/src/games/enderalse/src/enderalsebsainvalidation.h new file mode 100644 index 00000000..0ce53613 --- /dev/null +++ b/src/games/enderalse/src/enderalsebsainvalidation.h @@ -0,0 +1,23 @@ +#ifndef ENDERALSEBSAINVALIDATION_H +#define ENDERALSEBSAINVALIDATION_H + + +#include "gamebryobsainvalidation.h" +#include "enderalsedataarchives.h" + +#include + +class EnderalSEBSAInvalidation : public GamebryoBSAInvalidation +{ +public: + + EnderalSEBSAInvalidation(DataArchives* dataArchives, MOBase::IPluginGame const* game); + +private: + + virtual QString invalidationBSAName() const override; + virtual unsigned long bsaVersion() const override; + +}; + +#endif // ENDERALSEBSAINVALIDATION_H \ No newline at end of file diff --git a/src/games/enderalse/src/enderalsedataarchives.cpp b/src/games/enderalse/src/enderalsedataarchives.cpp new file mode 100644 index 00000000..dcb0b20f --- /dev/null +++ b/src/games/enderalse/src/enderalsedataarchives.cpp @@ -0,0 +1,66 @@ +#include "enderalSEdataarchives.h" + +#include "iprofile.h" +#include + +EnderalSEDataArchives::EnderalSEDataArchives(const QDir &myGamesDir) : + GamebryoDataArchives(myGamesDir) +{} + +QStringList EnderalSEDataArchives::vanillaArchives() const +{ + return { + "Skyrim - Textures0.bsa", + "Skyrim - Textures1.bsa", + "Skyrim - Textures2.bsa", + "Skyrim - Textures3.bsa", + "Skyrim - Textures4.bsa", + "Skyrim - Textures5.bsa", + "Skyrim - Textures6.bsa", + "Skyrim - Textures7.bsa", + "Skyrim - Textures8.bsa", + "Skyrim - Meshes0.bsa", + "Skyrim - Meshes1.bsa", + "Skyrim - Voices_en0.bsa", + "Skyrim - Sounds.bsa", + "Skyrim - Interface.bsa", + "Skyrim - Animations.bsa", + "Skyrim - Shaders.bsa", + "Skyrim - Misc.bsa", + "E - Meshes.bsa", + "E - SE.bsa", + "E - Scripts.bsa", + "E - Sounds.bsa", + "E - Textures1.bsa", + "E - Textures2.bsa", + "E - Textures3.bsa", + "L - Textures.bsa", + "L - Voices.bsa" + }; +} + + +QStringList EnderalSEDataArchives::archives(const MOBase::IProfile *profile) const +{ + QStringList result; + + QString iniFile = profile->localSettingsEnabled() ? QDir(profile->absolutePath()).absoluteFilePath("skyrim.ini") : m_LocalGameDir.absoluteFilePath("skyrim.ini"); + result.append(getArchivesFromKey(iniFile, "SResourceArchiveList")); + result.append(getArchivesFromKey(iniFile, "SResourceArchiveList2")); + + return result; +} + +void EnderalSEDataArchives::writeArchiveList(MOBase::IProfile *profile, const QStringList &before) +{ + QString list = before.join(", "); + + QString iniFile = profile->localSettingsEnabled() ? QDir(profile->absolutePath()).absoluteFilePath("skyrim.ini") : m_LocalGameDir.absoluteFilePath("skyrim.ini"); + if (list.length() > 255) { + int splitIdx = list.lastIndexOf(",", 256); + setArchivesToKey(iniFile, "SResourceArchiveList", list.mid(0, splitIdx)); + setArchivesToKey(iniFile, "SResourceArchiveList2", list.mid(splitIdx + 2)); + } else { + setArchivesToKey(iniFile, "SResourceArchiveList", list); + } +} diff --git a/src/games/enderalse/src/enderalsedataarchives.h b/src/games/enderalse/src/enderalsedataarchives.h new file mode 100644 index 00000000..b6954db0 --- /dev/null +++ b/src/games/enderalse/src/enderalsedataarchives.h @@ -0,0 +1,29 @@ +#ifndef ENDERALSEDATAARCHIVES_H +#define ENDERALSEDATAARCHIVES_H + +#include "gamebryodataarchives.h" +#include +#include + +namespace MOBase { class IProfile; } + + +class EnderalSEDataArchives : public GamebryoDataArchives +{ + +public: + + EnderalSEDataArchives(const QDir &myGamesDir); + +public: + + 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 // _SKYRIMSEDATAARCHIVES_H diff --git a/src/games/enderalse/src/enderalsemoddatachecker.h b/src/games/enderalse/src/enderalsemoddatachecker.h new file mode 100644 index 00000000..1a2c8ff4 --- /dev/null +++ b/src/games/enderalse/src/enderalsemoddatachecker.h @@ -0,0 +1,30 @@ +#ifndef ENDERALSE_MODATACHECKER_H +#define ENDERALSE_MODATACHECKER_H + +#include + +class EnderalSEModDataChecker : 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", + "skse", "distantlod", "asi", "Tools", "MCM", "distantland", "mits", + "dllplugins", "CalienteTools", "NetScriptFramework", "shadersfx", + "Nemesis_Engine" + }; + return result; + } + virtual const FileNameSet& possibleFileExtensions() const override { + static FileNameSet result{ + "esp", "esm", "esl", "bsa", "modgroups" + }; + return result; + } +}; + +#endif // SKYRIMSE_MODATACHECKER_H diff --git a/src/games/enderalse/src/enderalsemoddatacontent.h b/src/games/enderalse/src/enderalsemoddatacontent.h new file mode 100644 index 00000000..d1582917 --- /dev/null +++ b/src/games/enderalse/src/enderalsemoddatacontent.h @@ -0,0 +1,20 @@ +#ifndef ENDERALSE_MODDATACONTENT_H +#define ENDERALSE_MODDATACONTENT_H + +#include +#include + +class EnderalSEModDataContent : public GamebryoModDataContent { +public: + + /** + * + */ + EnderalSEModDataContent(GameGamebryo const* gamePlugin) : GamebryoModDataContent(gamePlugin) { + // Just need to disable some contents: + m_Enabled[CONTENT_SKYPROC] = false; + } + +}; + +#endif // SKYRIMSE_MODDATACONTENT_H diff --git a/src/games/enderalse/src/enderalsesavegame.cpp b/src/games/enderalse/src/enderalsesavegame.cpp new file mode 100644 index 00000000..955c84a7 --- /dev/null +++ b/src/games/enderalse/src/enderalsesavegame.cpp @@ -0,0 +1,116 @@ +#include "enderalsesavegame.h" + +#include + +EnderalSESaveGame::EnderalSESaveGame(QString const &fileName, GameEnderalSE const *game) : + GamebryoSaveGame(fileName, game, true) +{ + FileWrapper file(fileName, "TESV_SAVEGAME"); //10bytes + + unsigned long version; + FILETIME ftime; + fetchInformationFields(file, version, m_PCName, m_PCLevel, m_PCLocation, m_SaveNumber, ftime); + + //A file time is a 64-bit value that represents the number of 100-nanosecond + //intervals that have elapsed since 12:00 A.M. January 1, 1601 Coordinated Universal Time (UTC). + //So we need to convert that to something useful + + //For some reason, the file time is off by about 6 hours. + //So we need to subtract those 6 hours from the filetime. + _ULARGE_INTEGER time; + time.LowPart = ftime.dwLowDateTime; + time.HighPart = ftime.dwHighDateTime; + time.QuadPart -= 2.16e11; + ftime.dwHighDateTime = time.HighPart; + ftime.dwLowDateTime = time.LowPart; + + SYSTEMTIME ctime; + ::FileTimeToSystemTime(&ftime, &ctime); + + setCreationTime(ctime); +} + +void EnderalSESaveGame::fetchInformationFields( + FileWrapper& file, + unsigned long& version, + QString& playerName, + unsigned short& playerLevel, + QString& playerLocation, + unsigned long& saveNumber, + FILETIME& creationTime) const +{ + unsigned long headerSize; + file.read(headerSize); // header size "TESV_SAVEGAME" + file.read(version); + file.read(saveNumber); + file.read(playerName); + + unsigned long temp; + file.read(temp); + playerLevel = static_cast(temp); + file.read(playerLocation); + + QString timeOfDay; + file.read(timeOfDay); + + QString race; + file.read(race); // race name (i.e. BretonRace) + + file.skip(); // Player gender (0 = male) + file.skip(2); // experience gathered, experience required + + file.read(creationTime); //filetime +} + +std::unique_ptr EnderalSESaveGame::fetchDataFields() const +{ + FileWrapper file(getFilepath(), "TESV_SAVEGAME"); //10bytes + + unsigned long version = 0; + { + QString dummyName, dummyLocation; + unsigned short dummyLevel; + unsigned long dummySaveNumber; + FILETIME dummyTime; + + fetchInformationFields(file, version, dummyName, dummyLevel, + dummyLocation, dummySaveNumber, dummyTime); + } + + std::unique_ptr fields = std::make_unique(); + + unsigned long width; + unsigned long height; + file.read(width); + file.read(height); + + bool alpha = false; + + // compatibility between LE and SE: + // SE has an additional uin16_t for compression + // SE uses an alpha channel, whereas LE does not + if (version == 12) { + uint16_t compressionType; + file.read(compressionType); + file.setCompressionType(compressionType); + alpha = true; + } + + fields->Screenshot = file.readImage(width, height, 320, alpha); + + file.openCompressedData(); + + uint8_t saveGameVersion = file.readChar(); + uint8_t pluginInfoSize = file.readChar(); + uint16_t other = file.readShort(); //Unknown + + fields->Plugins = file.readPlugins(1); // Just empty data + + if (saveGameVersion >= 78) { + fields->LightPlugins = file.readLightPlugins(); + } + + file.closeCompressedData(); + + return fields; +} \ No newline at end of file diff --git a/src/games/enderalse/src/enderalsesavegame.h b/src/games/enderalse/src/enderalsesavegame.h new file mode 100644 index 00000000..f92a12d5 --- /dev/null +++ b/src/games/enderalse/src/enderalsesavegame.h @@ -0,0 +1,29 @@ +#ifndef ENDERALSESAVEGAME_H +#define ENDERALSESAVEGAME_H + +#include "gamebryosavegame.h" +#include "gameenderalse.h" + +namespace MOBase { class IPluginGame; } + +class EnderalSESaveGame : public GamebryoSaveGame +{ +public: + EnderalSESaveGame(QString const &fileName, GameEnderalSE const *game); + +protected: + + // Fetch easy-to-access information. + void fetchInformationFields(FileWrapper& wrapper, + unsigned long& version, + QString& playerName, + unsigned short& playerLevel, + QString& playerLocation, + unsigned long& saveNumber, + FILETIME& creationTime) const; + + std::unique_ptr fetchDataFields() const override; + +}; + +#endif // _SKYRIMSESAVEGAME_H diff --git a/src/games/enderalse/src/enderalsescriptextender.cpp b/src/games/enderalse/src/enderalsescriptextender.cpp new file mode 100644 index 00000000..6c073f34 --- /dev/null +++ b/src/games/enderalse/src/enderalsescriptextender.cpp @@ -0,0 +1,19 @@ +#include "enderalsescriptextender.h" + +#include +#include + +EnderalSEScriptExtender::EnderalSEScriptExtender(GameGamebryo const *game) : + GamebryoScriptExtender(game) +{ +} + +QString EnderalSEScriptExtender::BinaryName() const +{ + return "skse64_loader.exe"; +} + +QString EnderalSEScriptExtender::PluginPath() const +{ + return "skse/plugins"; +} diff --git a/src/games/enderalse/src/enderalsescriptextender.h b/src/games/enderalse/src/enderalsescriptextender.h new file mode 100644 index 00000000..a410e5d1 --- /dev/null +++ b/src/games/enderalse/src/enderalsescriptextender.h @@ -0,0 +1,18 @@ +#ifndef ENDERALSESCRIPTEXTENDER_H +#define ENDERALESCRIPTEXTENDER_H + +#include "gamebryoscriptextender.h" + +class GameGamebryo; + +class EnderalSEScriptExtender : public GamebryoScriptExtender +{ +public: + EnderalSEScriptExtender(GameGamebryo const *game); + + virtual QString BinaryName() const override; + virtual QString PluginPath() const override; + +}; + +#endif // _SKYRIMSESCRIPTEXTENDER_H diff --git a/src/games/enderalse/src/enderalseunmanagedmods.cpp b/src/games/enderalse/src/enderalseunmanagedmods.cpp new file mode 100644 index 00000000..c6a4e710 --- /dev/null +++ b/src/games/enderalse/src/enderalseunmanagedmods.cpp @@ -0,0 +1,32 @@ +#include "enderalseunmanagedmods.h" + + +EnderalSEUnmangedMods::EnderalSEUnmangedMods(const GameGamebryo *game) + : GamebryoUnmangedMods(game) +{} + +EnderalSEUnmangedMods::~EnderalSEUnmangedMods() +{} + +QStringList EnderalSEUnmangedMods::mods(bool onlyOfficial) const { + QStringList result; + + QStringList pluginList = game()->primaryPlugins(); + QStringList otherPlugins = game()->DLCPlugins(); + otherPlugins.append(game()->CCPlugins()); + for (QString plugin : otherPlugins) { + pluginList.removeAll(plugin); + } + QDir dataDir(game()->dataDirectory()); + for (const QString &fileName : dataDir.entryList({ "*.esp", "*.esl", "*.esm" })) { + if (!pluginList.contains(fileName, Qt::CaseInsensitive)) { + if (!onlyOfficial || pluginList.contains(fileName, Qt::CaseInsensitive)) { + QFileInfo file(fileName); + result.append(file.baseName()); + } + } + } + + return result; +} + diff --git a/src/games/enderalse/src/enderalseunmanagedmods.h b/src/games/enderalse/src/enderalseunmanagedmods.h new file mode 100644 index 00000000..f8102d5d --- /dev/null +++ b/src/games/enderalse/src/enderalseunmanagedmods.h @@ -0,0 +1,19 @@ +#ifndef ENDERALSEUNMANAGEDMODS_H +#define ENDERALSEUNMANAGEDMODS_H + + +#include "gamebryounmanagedmods.h" +#include + + +class EnderalSEUnmangedMods : public GamebryoUnmangedMods { +public: + EnderalSEUnmangedMods(const GameGamebryo *game); + ~EnderalSEUnmangedMods(); + + virtual QStringList mods(bool onlyOfficial) const override; +}; + + + +#endif // _SKYRIMSEUNMANAGEDMODS_H diff --git a/src/games/enderalse/src/game_enderalse_en.ts b/src/games/enderalse/src/game_enderalse_en.ts new file mode 100644 index 00000000..4ec02c05 --- /dev/null +++ b/src/games/enderalse/src/game_enderalse_en.ts @@ -0,0 +1,17 @@ + + + + + GameEnderalSE + + + Enderal Special Edition Support Plugin + + + + + Adds support for the game Enderal Special Edition. + + + + diff --git a/src/games/enderalse/src/gameenderalse.cpp b/src/games/enderalse/src/gameenderalse.cpp new file mode 100644 index 00000000..d1e34c5f --- /dev/null +++ b/src/games/enderalse/src/gameenderalse.cpp @@ -0,0 +1,281 @@ +#include "gameenderalse.h" + +#include "enderalsebsainvalidation.h" +#include "enderalsedataarchives.h" +#include "enderalsescriptextender.h" +#include "enderalseunmanagedmods.h" +#include "enderalsemoddatachecker.h" +#include "enderalsemoddatacontent.h" +#include "enderalsesavegame.h" + +#include +#include +#include +#include +#include +#include "versioninfo.h" +#include + +#include +#include +#include +#include +#include +#include +#include + +#include +#include "scopeguard.h" + +using namespace MOBase; + +GameEnderalSE::GameEnderalSE() +{ +} + +void GameEnderalSE::setGamePath(const QString &path) +{ + m_GamePath = path; +} + +QDir GameEnderalSE::documentsDirectory() const +{ + return m_MyGamesPath; +} + +QString GameEnderalSE::identifyGamePath() const +{ + QString path = "Software\\Bethesda Softworks\\Skyrim Special Edition"; + return findInRegistry(HKEY_LOCAL_MACHINE, path.toStdWString().c_str(), L"Installed Path"); +} + +QDir GameEnderalSE::savesDirectory() const +{ + return QDir(m_MyGamesPath + "/Saves"); +} + +QString GameEnderalSE::myGamesPath() const +{ + return m_MyGamesPath; +} + +bool GameEnderalSE::isInstalled() const +{ + return !m_GamePath.isEmpty(); +} + +void GameEnderalSE::detectGame() +{ + m_GamePath = identifyGamePath(); + m_MyGamesPath = determineMyGamesPath("Skyrim Special Edition"); +} + +bool GameEnderalSE::init(IOrganizer *moInfo) +{ + if (!GameGamebryo::init(moInfo)) { + return false; + } + + registerFeature(new EnderalSEScriptExtender(this)); + registerFeature(new EnderalSEDataArchives(myGamesPath())); + registerFeature(new EnderalSEBSAInvalidation(feature(), this)); + registerFeature(new GamebryoLocalSavegames(myGamesPath(), "skyrimcustom.ini")); + registerFeature(new EnderalSEModDataChecker(this)); + registerFeature(new EnderalSEModDataContent(this)); + registerFeature(new GamebryoSaveGameInfo(this)); + registerFeature(new CreationGamePlugins(moInfo)); + registerFeature(new EnderalSEUnmangedMods(this)); + + return true; +} + +QString GameEnderalSE::gameName() const +{ + return "Enderal Special Edition"; +} + +QList GameEnderalSE::executables() const +{ + return QList() + << ExecutableInfo("Enderal Special Edition (SKSE)", findInGameFolder(feature()->loaderName())) + // << ExecutableInfo("Enderal Special Edition Launcher", findInGameFolder(getLauncherName())) + // << ExecutableInfo("LOOT", getLootPath()).withArgument("--game=\"Skyrim Special Edition\"") + << ExecutableInfo("Creation Kit", findInGameFolder("CreationKit.exe")) + ; +} + +QList GameEnderalSE::executableForcedLoads() const +{ + return QList(); +} + +QString GameEnderalSE::binaryName() const +{ + return "skse64_loader.exe"; +} + +QString GameEnderalSE::getLauncherName() const +{ + return ""; +} + + +QFileInfo GameEnderalSE::findInGameFolder(const QString &relativePath) const +{ + return QFileInfo(m_GamePath + "/" + relativePath); +} + +QString GameEnderalSE::name() const +{ + return "Enderal Special Edition Support Plugin"; +} + +QString GameEnderalSE::localizedName() const +{ + return tr("Enderal Special Edition Support Plugin"); +} + +QString GameEnderalSE::author() const +{ + return "Holt59 & Archost & ZachHaber"; +} + +QString GameEnderalSE::description() const +{ + return tr("Adds support for the game Enderal Special Edition."); +} + +MOBase::VersionInfo GameEnderalSE::version() const +{ + return VersionInfo(1, 0, 0, VersionInfo::RELEASE_BETA); +} + +QList GameEnderalSE::settings() const +{ + return QList(); +} + +void GameEnderalSE::initializeProfile(const QDir &path, ProfileSettings settings) const +{ + if (settings.testFlag(IPluginGame::MODS)) { + copyToProfile(localAppFolder() + "/Enderal Special Edition", path, "plugins.txt"); + copyToProfile(localAppFolder() + "/Enderal Special Edition", path, "loadorder.txt"); + } + + if (settings.testFlag(IPluginGame::CONFIGURATION)) { + if (settings.testFlag(IPluginGame::PREFER_DEFAULTS) + || !QFileInfo(myGamesPath() + "/skyrim.ini").exists()) { + copyToProfile(gameDirectory().absolutePath(), path, "skyrim_default.ini", "skyrim.ini"); + } + else { + copyToProfile(myGamesPath(), path, "skyrim.ini"); + } + + copyToProfile(myGamesPath(), path, "skyrimprefs.ini"); + copyToProfile(myGamesPath(), path, "skyrimcustom.ini"); + } +} + +QString GameEnderalSE::savegameExtension() const +{ + return "ess"; +} + +QString GameEnderalSE::savegameSEExtension() const +{ + return "skse"; +} + +std::shared_ptr GameEnderalSE::makeSaveGame(QString filePath) const +{ + return std::make_shared(filePath, this); +} + +QString GameEnderalSE::steamAPPId() const +{ + return "976620"; +} + +QStringList GameEnderalSE::primaryPlugins() const +{ + return { + "skyrim.esm", + "Enderal - Forgotten Stories.esm", + "update.esm" + }; +} + +QStringList GameEnderalSE::gameVariants() const +{ + return{ "Regular" }; +} + +QString GameEnderalSE::gameShortName() const +{ + return "EnderalSE"; +} + +QStringList GameEnderalSE::validShortNames() const +{ + return { "Skyrim", "SkyrimSE", "Enderal" }; +} + +QString GameEnderalSE::gameNexusName() const +{ + return "enderalspecialedition"; +} + +QStringList GameEnderalSE::iniFiles() const +{ + return{ "skyrim.ini", "skyrimprefs.ini", "skyrimcustom.ini" }; +} + +QStringList GameEnderalSE::DLCPlugins() const +{ + return {}; +} + +QStringList GameEnderalSE::CCPlugins() const +{ + return {}; +} + +MOBase::IPluginGame::SortMechanism GameEnderalSE::sortMechanism() const +{ + return SortMechanism::NONE; +} + +IPluginGame::LoadOrderMechanism GameEnderalSE::loadOrderMechanism() const +{ + return IPluginGame::LoadOrderMechanism::PluginsTxt; +} + +int GameEnderalSE::nexusModOrganizerID() const +{ + return 0; +} + +int GameEnderalSE::nexusGameID() const +{ + return 3685; +} + +QDir GameEnderalSE::gameDirectory() const +{ + return QDir(m_GamePath); +} + +// Not to delete all the spaces... +MappingType GameEnderalSE::mappings() const +{ + MappingType result; + + for (const QString &profileFile : { "plugins.txt", "loadorder.txt" }) { + result.push_back({ m_Organizer->profilePath() + "/" + profileFile, + localAppFolder() + "/" + gameName() + "/" + profileFile, + false }); + } + + return result; +} + diff --git a/src/games/enderalse/src/gameenderalse.h b/src/games/enderalse/src/gameenderalse.h new file mode 100644 index 00000000..2e56634e --- /dev/null +++ b/src/games/enderalse/src/gameenderalse.h @@ -0,0 +1,75 @@ +#ifndef GAMEENDERALSE_H +#define GAMEENDERALSE_H + + +#include "gamegamebryo.h" + +#include +#include + +class GameEnderalSE : public GameGamebryo +{ + Q_OBJECT + + Q_PLUGIN_METADATA(IID "com.soundcontactstudio.GameEnderalSE" FILE "gameenderalse.json") + +public: + + GameEnderalSE(); + + virtual bool init(MOBase::IOrganizer *moInfo) override; + +public: // IPluginGame interface + + virtual void detectGame() override; + virtual QString gameName() const override; + virtual QList executables() const override; + virtual QList 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 getLauncherName() const override; + virtual QString gameShortName() const override; + virtual QString gameNexusName() const override; + virtual QStringList validShortNames() const override; + virtual QStringList iniFiles() const override; + virtual QStringList DLCPlugins() const override; + virtual QStringList CCPlugins() const override; + SortMechanism sortMechanism() const override; + virtual LoadOrderMechanism loadOrderMechanism() const override; + virtual int nexusModOrganizerID() const override; + virtual int nexusGameID() 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 settings() const override; + virtual MappingType mappings() const override; + + +protected: + + std::shared_ptr makeSaveGame(QString filePath) const override; + QString savegameExtension() const override; + QString savegameSEExtension() const override; + + QDir documentsDirectory() const; + QDir savesDirectory() const; + QFileInfo findInGameFolder(const QString &relativePath) const; + QString myGamesPath() const; + + virtual QString identifyGamePath() const override; + +}; + +#endif // _GAMESKYRIMSE_H diff --git a/src/games/enderalse/src/gameenderalse.json b/src/games/enderalse/src/gameenderalse.json new file mode 100644 index 00000000..0967ef42 --- /dev/null +++ b/src/games/enderalse/src/gameenderalse.json @@ -0,0 +1 @@ +{} From 9bfa9dcab832c08eeb2e1271f09d929c6d7d5d92 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Mika=C3=ABl=20Capelle?= Date: Wed, 24 Feb 2021 22:52:46 +0100 Subject: [PATCH 1141/1544] [game_enderalse] Fix multiple issues. --- .../src/enderalsebsainvalidation.cpp | 16 --------- .../enderalse/src/enderalsebsainvalidation.h | 23 ------------ src/games/enderalse/src/game_enderalse_en.ts | 4 +-- src/games/enderalse/src/gameenderalse.cpp | 35 +++++++++++++------ src/games/enderalse/src/gameenderalse.h | 1 - 5 files changed, 27 insertions(+), 52 deletions(-) delete mode 100644 src/games/enderalse/src/enderalsebsainvalidation.cpp delete mode 100644 src/games/enderalse/src/enderalsebsainvalidation.h diff --git a/src/games/enderalse/src/enderalsebsainvalidation.cpp b/src/games/enderalse/src/enderalsebsainvalidation.cpp deleted file mode 100644 index 523c2de9..00000000 --- a/src/games/enderalse/src/enderalsebsainvalidation.cpp +++ /dev/null @@ -1,16 +0,0 @@ -#include "enderalsebsainvalidation.h" - -EnderalSEBSAInvalidation::EnderalSEBSAInvalidation(DataArchives* dataArchives, MOBase::IPluginGame const* game) - : GamebryoBSAInvalidation(dataArchives, "skyrim.ini", game) -{ -} - -QString EnderalSEBSAInvalidation::invalidationBSAName() const -{ - return "Enderal - Invalidation.bsa"; -} - -unsigned long EnderalSEBSAInvalidation::bsaVersion() const -{ - return 0x69; -} \ No newline at end of file diff --git a/src/games/enderalse/src/enderalsebsainvalidation.h b/src/games/enderalse/src/enderalsebsainvalidation.h deleted file mode 100644 index 0ce53613..00000000 --- a/src/games/enderalse/src/enderalsebsainvalidation.h +++ /dev/null @@ -1,23 +0,0 @@ -#ifndef ENDERALSEBSAINVALIDATION_H -#define ENDERALSEBSAINVALIDATION_H - - -#include "gamebryobsainvalidation.h" -#include "enderalsedataarchives.h" - -#include - -class EnderalSEBSAInvalidation : public GamebryoBSAInvalidation -{ -public: - - EnderalSEBSAInvalidation(DataArchives* dataArchives, MOBase::IPluginGame const* game); - -private: - - virtual QString invalidationBSAName() const override; - virtual unsigned long bsaVersion() const override; - -}; - -#endif // ENDERALSEBSAINVALIDATION_H \ No newline at end of file diff --git a/src/games/enderalse/src/game_enderalse_en.ts b/src/games/enderalse/src/game_enderalse_en.ts index 4ec02c05..6405fdd2 100644 --- a/src/games/enderalse/src/game_enderalse_en.ts +++ b/src/games/enderalse/src/game_enderalse_en.ts @@ -4,12 +4,12 @@ GameEnderalSE - + Enderal Special Edition Support Plugin - + Adds support for the game Enderal Special Edition. diff --git a/src/games/enderalse/src/gameenderalse.cpp b/src/games/enderalse/src/gameenderalse.cpp index d1e34c5f..4ec882d9 100644 --- a/src/games/enderalse/src/gameenderalse.cpp +++ b/src/games/enderalse/src/gameenderalse.cpp @@ -1,6 +1,5 @@ #include "gameenderalse.h" -#include "enderalsebsainvalidation.h" #include "enderalsedataarchives.h" #include "enderalsescriptextender.h" #include "enderalseunmanagedmods.h" @@ -14,6 +13,7 @@ #include #include #include "versioninfo.h" +#include #include #include @@ -78,7 +78,6 @@ bool GameEnderalSE::init(IOrganizer *moInfo) registerFeature(new EnderalSEScriptExtender(this)); registerFeature(new EnderalSEDataArchives(myGamesPath())); - registerFeature(new EnderalSEBSAInvalidation(feature(), this)); registerFeature(new GamebryoLocalSavegames(myGamesPath(), "skyrimcustom.ini")); registerFeature(new EnderalSEModDataChecker(this)); registerFeature(new EnderalSEModDataContent(this)); @@ -158,8 +157,8 @@ QList GameEnderalSE::settings() const void GameEnderalSE::initializeProfile(const QDir &path, ProfileSettings settings) const { if (settings.testFlag(IPluginGame::MODS)) { - copyToProfile(localAppFolder() + "/Enderal Special Edition", path, "plugins.txt"); - copyToProfile(localAppFolder() + "/Enderal Special Edition", path, "loadorder.txt"); + copyToProfile(localAppFolder() + "/Skyrim Special Edition", path, "plugins.txt"); + copyToProfile(localAppFolder() + "/Skyrim Special Edition", path, "loadorder.txt"); } if (settings.testFlag(IPluginGame::CONFIGURATION)) { @@ -200,8 +199,7 @@ QStringList GameEnderalSE::primaryPlugins() const { return { "skyrim.esm", - "Enderal - Forgotten Stories.esm", - "update.esm" + "update.esm", }; } @@ -227,17 +225,34 @@ QString GameEnderalSE::gameNexusName() const QStringList GameEnderalSE::iniFiles() const { - return{ "skyrim.ini", "skyrimprefs.ini", "skyrimcustom.ini" }; + return { "skyrim.ini", "skyrimprefs.ini", "skyrimcustom.ini" }; } QStringList GameEnderalSE::DLCPlugins() const { - return {}; + return { + "dawnguard.esm", + "hearthfires.esm", + "dragonborn.esm" + }; } QStringList GameEnderalSE::CCPlugins() const { - return {}; + QStringList plugins; + std::set pluginsLookup; + + const QString path = gameDirectory().filePath("Skyrim.ccc"); + + MOBase::forEachLineInFile(path, [&](QString s) { + const auto lc = s.toLower(); + if (!pluginsLookup.contains(lc)) { + pluginsLookup.insert(lc); + plugins.append(std::move(s)); + } + }); + + return plugins; } MOBase::IPluginGame::SortMechanism GameEnderalSE::sortMechanism() const @@ -272,7 +287,7 @@ MappingType GameEnderalSE::mappings() const for (const QString &profileFile : { "plugins.txt", "loadorder.txt" }) { result.push_back({ m_Organizer->profilePath() + "/" + profileFile, - localAppFolder() + "/" + gameName() + "/" + profileFile, + localAppFolder() + "/Skyrim Special Edition/" + profileFile, false }); } diff --git a/src/games/enderalse/src/gameenderalse.h b/src/games/enderalse/src/gameenderalse.h index 2e56634e..e115dd99 100644 --- a/src/games/enderalse/src/gameenderalse.h +++ b/src/games/enderalse/src/gameenderalse.h @@ -1,7 +1,6 @@ #ifndef GAMEENDERALSE_H #define GAMEENDERALSE_H - #include "gamegamebryo.h" #include From 773e8af62c187cc44a951d0e4b60b39c053176cb Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Mika=C3=ABl=20Capelle?= Date: Thu, 25 Feb 2021 18:38:10 +0100 Subject: [PATCH 1142/1544] [game_enderalse] Fix Enderal SE Nexus downloads. --- src/games/enderalse/src/gameenderalse.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/games/enderalse/src/gameenderalse.cpp b/src/games/enderalse/src/gameenderalse.cpp index 4ec882d9..7c259060 100644 --- a/src/games/enderalse/src/gameenderalse.cpp +++ b/src/games/enderalse/src/gameenderalse.cpp @@ -210,7 +210,7 @@ QStringList GameEnderalSE::gameVariants() const QString GameEnderalSE::gameShortName() const { - return "EnderalSE"; + return "enderalspecialedition"; } QStringList GameEnderalSE::validShortNames() const From c4ce8a532e6cac59de8a6ccf39f5123bf0c49028 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Mika=C3=ABl=20Capelle?= Date: Sun, 7 Mar 2021 14:29:14 +0100 Subject: [PATCH 1143/1544] [game_enderalse] Update plugin for Steam version. --- .../enderalse/src/enderalsedataarchives.cpp | 4 +- src/games/enderalse/src/game_enderalse_en.ts | 4 +- src/games/enderalse/src/gameenderalse.cpp | 85 ++++++++++--------- src/games/enderalse/src/gameenderalse.h | 2 +- 4 files changed, 52 insertions(+), 43 deletions(-) diff --git a/src/games/enderalse/src/enderalsedataarchives.cpp b/src/games/enderalse/src/enderalsedataarchives.cpp index dcb0b20f..63cbabc0 100644 --- a/src/games/enderalse/src/enderalsedataarchives.cpp +++ b/src/games/enderalse/src/enderalsedataarchives.cpp @@ -44,7 +44,7 @@ QStringList EnderalSEDataArchives::archives(const MOBase::IProfile *profile) con { QStringList result; - QString iniFile = profile->localSettingsEnabled() ? QDir(profile->absolutePath()).absoluteFilePath("skyrim.ini") : m_LocalGameDir.absoluteFilePath("skyrim.ini"); + QString iniFile = profile->localSettingsEnabled() ? QDir(profile->absolutePath()).absoluteFilePath("enderal.ini") : m_LocalGameDir.absoluteFilePath("enderal.ini"); result.append(getArchivesFromKey(iniFile, "SResourceArchiveList")); result.append(getArchivesFromKey(iniFile, "SResourceArchiveList2")); @@ -55,7 +55,7 @@ void EnderalSEDataArchives::writeArchiveList(MOBase::IProfile *profile, const QS { QString list = before.join(", "); - QString iniFile = profile->localSettingsEnabled() ? QDir(profile->absolutePath()).absoluteFilePath("skyrim.ini") : m_LocalGameDir.absoluteFilePath("skyrim.ini"); + QString iniFile = profile->localSettingsEnabled() ? QDir(profile->absolutePath()).absoluteFilePath("enderal.ini") : m_LocalGameDir.absoluteFilePath("enderal.ini"); if (list.length() > 255) { int splitIdx = list.lastIndexOf(",", 256); setArchivesToKey(iniFile, "SResourceArchiveList", list.mid(0, splitIdx)); diff --git a/src/games/enderalse/src/game_enderalse_en.ts b/src/games/enderalse/src/game_enderalse_en.ts index 6405fdd2..8c957c69 100644 --- a/src/games/enderalse/src/game_enderalse_en.ts +++ b/src/games/enderalse/src/game_enderalse_en.ts @@ -4,12 +4,12 @@ GameEnderalSE - + Enderal Special Edition Support Plugin - + Adds support for the game Enderal Special Edition. diff --git a/src/games/enderalse/src/gameenderalse.cpp b/src/games/enderalse/src/gameenderalse.cpp index 7c259060..43050871 100644 --- a/src/games/enderalse/src/gameenderalse.cpp +++ b/src/games/enderalse/src/gameenderalse.cpp @@ -6,6 +6,7 @@ #include "enderalsemoddatachecker.h" #include "enderalsemoddatacontent.h" #include "enderalsesavegame.h" +#include "steamutility.h" #include #include @@ -45,8 +46,15 @@ QDir GameEnderalSE::documentsDirectory() const QString GameEnderalSE::identifyGamePath() const { - QString path = "Software\\Bethesda Softworks\\Skyrim Special Edition"; - return findInRegistry(HKEY_LOCAL_MACHINE, path.toStdWString().c_str(), L"Installed Path"); + QString path = "Software\\SureAI\\EnderalSE"; + QString result; + try { + result = findInRegistry(HKEY_CURRENT_USER, path.toStdWString().c_str(), L"Install_Path"); + } + catch (MOBase::MyException) { + result = MOBase::findSteamGame("Enderal Special Edition", "Data\\Enderal - Forgotten Stories.esm"); + } + return result; } QDir GameEnderalSE::savesDirectory() const @@ -64,12 +72,6 @@ bool GameEnderalSE::isInstalled() const return !m_GamePath.isEmpty(); } -void GameEnderalSE::detectGame() -{ - m_GamePath = identifyGamePath(); - m_MyGamesPath = determineMyGamesPath("Skyrim Special Edition"); -} - bool GameEnderalSE::init(IOrganizer *moInfo) { if (!GameGamebryo::init(moInfo)) { @@ -78,7 +80,7 @@ bool GameEnderalSE::init(IOrganizer *moInfo) registerFeature(new EnderalSEScriptExtender(this)); registerFeature(new EnderalSEDataArchives(myGamesPath())); - registerFeature(new GamebryoLocalSavegames(myGamesPath(), "skyrimcustom.ini")); + registerFeature(new GamebryoLocalSavegames(myGamesPath(), "enderal.ini")); registerFeature(new EnderalSEModDataChecker(this)); registerFeature(new EnderalSEModDataContent(this)); registerFeature(new GamebryoSaveGameInfo(this)); @@ -93,14 +95,19 @@ QString GameEnderalSE::gameName() const return "Enderal Special Edition"; } +QIcon GameEnderalSE::gameIcon() const +{ + return MOBase::iconForExecutable(gameDirectory().absoluteFilePath(getLauncherName())); +} + QList GameEnderalSE::executables() const { - return QList() - << ExecutableInfo("Enderal Special Edition (SKSE)", findInGameFolder(feature()->loaderName())) - // << ExecutableInfo("Enderal Special Edition Launcher", findInGameFolder(getLauncherName())) - // << ExecutableInfo("LOOT", getLootPath()).withArgument("--game=\"Skyrim Special Edition\"") - << ExecutableInfo("Creation Kit", findInGameFolder("CreationKit.exe")) - ; + return { + ExecutableInfo("Enderal Special Edition (SKSE)", findInGameFolder(feature()->loaderName())), + ExecutableInfo("Enderal Special Edition Launcher", findInGameFolder(getLauncherName())), + // ExecutableInfo("LOOT", getLootPath()).withArgument("--game=\"Skyrim Special Edition\""), + ExecutableInfo("Creation Kit", findInGameFolder("CreationKit.exe")) + }; } QList GameEnderalSE::executableForcedLoads() const @@ -115,7 +122,7 @@ QString GameEnderalSE::binaryName() const QString GameEnderalSE::getLauncherName() const { - return ""; + return "Enderal Launcher.exe"; } @@ -136,7 +143,7 @@ QString GameEnderalSE::localizedName() const QString GameEnderalSE::author() const { - return "Holt59 & Archost & ZachHaber"; + return "Holt59, Archost & ZachHaber"; } QString GameEnderalSE::description() const @@ -157,21 +164,22 @@ QList GameEnderalSE::settings() const void GameEnderalSE::initializeProfile(const QDir &path, ProfileSettings settings) const { if (settings.testFlag(IPluginGame::MODS)) { - copyToProfile(localAppFolder() + "/Skyrim Special Edition", path, "plugins.txt"); - copyToProfile(localAppFolder() + "/Skyrim Special Edition", path, "loadorder.txt"); + copyToProfile(localAppFolder() + "/Enderal Special Edition", path, "plugins.txt"); + copyToProfile(localAppFolder() + "/Enderal Special Edition", path, "loadorder.txt"); } if (settings.testFlag(IPluginGame::CONFIGURATION)) { if (settings.testFlag(IPluginGame::PREFER_DEFAULTS) - || !QFileInfo(myGamesPath() + "/skyrim.ini").exists()) { - copyToProfile(gameDirectory().absolutePath(), path, "skyrim_default.ini", "skyrim.ini"); + || !QFileInfo(myGamesPath() + "/Enderal.ini").exists()) { + + //there is no default ini, actually they are going to put them in for us! + copyToProfile(gameDirectory().absolutePath(), path, "enderal_default.ini", "Enderal.ini"); + copyToProfile(gameDirectory().absolutePath(), path, "enderalprefs_default.ini", "EnderalPrefs.ini"); } else { - copyToProfile(myGamesPath(), path, "skyrim.ini"); + copyToProfile(myGamesPath(), path, "Enderal.ini"); + copyToProfile(myGamesPath(), path, "EnderalPrefs.ini"); } - - copyToProfile(myGamesPath(), path, "skyrimprefs.ini"); - copyToProfile(myGamesPath(), path, "skyrimcustom.ini"); } } @@ -199,10 +207,21 @@ QStringList GameEnderalSE::primaryPlugins() const { return { "skyrim.esm", + "dawnguard.esm", + "hearthfires.esm", + "dragonborn.esm", "update.esm", + "enderal - forgotten stories.esm", + "skyui_se.esp" }; } +QStringList GameEnderalSE::DLCPlugins() const +{ + return { }; +} + + QStringList GameEnderalSE::gameVariants() const { return{ "Regular" }; @@ -210,7 +229,7 @@ QStringList GameEnderalSE::gameVariants() const QString GameEnderalSE::gameShortName() const { - return "enderalspecialedition"; + return "EnderalSE"; } QStringList GameEnderalSE::validShortNames() const @@ -225,18 +244,8 @@ QString GameEnderalSE::gameNexusName() const QStringList GameEnderalSE::iniFiles() const { - return { "skyrim.ini", "skyrimprefs.ini", "skyrimcustom.ini" }; + return { "Enderal.ini", "EnderalPrefs.ini" }; } - -QStringList GameEnderalSE::DLCPlugins() const -{ - return { - "dawnguard.esm", - "hearthfires.esm", - "dragonborn.esm" - }; -} - QStringList GameEnderalSE::CCPlugins() const { QStringList plugins; @@ -287,7 +296,7 @@ MappingType GameEnderalSE::mappings() const for (const QString &profileFile : { "plugins.txt", "loadorder.txt" }) { result.push_back({ m_Organizer->profilePath() + "/" + profileFile, - localAppFolder() + "/Skyrim Special Edition/" + profileFile, + localAppFolder() + "/Enderal Special Edition/" + profileFile, false }); } diff --git a/src/games/enderalse/src/gameenderalse.h b/src/games/enderalse/src/gameenderalse.h index e115dd99..6018dac1 100644 --- a/src/games/enderalse/src/gameenderalse.h +++ b/src/games/enderalse/src/gameenderalse.h @@ -20,8 +20,8 @@ public: public: // IPluginGame interface - virtual void detectGame() override; virtual QString gameName() const override; + virtual QIcon gameIcon() const override; virtual QList executables() const override; virtual QList executableForcedLoads() const override; virtual void initializeProfile(const QDir &path, ProfileSettings settings) const override; From b62dcc7398bbf3704533e5829454de4c80f7fa14 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Mika=C3=ABl=20Capelle?= Date: Sun, 7 Mar 2021 15:46:36 +0100 Subject: [PATCH 1144/1544] [game_enderalse] Fix loading of main .esm and SkyUI. Fix reading archive list. --- .../enderalse/src/enderalsedataarchives.cpp | 10 +-- .../enderalse/src/enderalsegameplugins.cpp | 81 +++++++++++++++++++ .../enderalse/src/enderalsegameplugins.h | 22 +++++ src/games/enderalse/src/game_enderalse_en.ts | 8 ++ src/games/enderalse/src/gameenderalse.cpp | 8 +- 5 files changed, 122 insertions(+), 7 deletions(-) create mode 100644 src/games/enderalse/src/enderalsegameplugins.cpp create mode 100644 src/games/enderalse/src/enderalsegameplugins.h diff --git a/src/games/enderalse/src/enderalsedataarchives.cpp b/src/games/enderalse/src/enderalsedataarchives.cpp index 63cbabc0..6d50a216 100644 --- a/src/games/enderalse/src/enderalsedataarchives.cpp +++ b/src/games/enderalse/src/enderalsedataarchives.cpp @@ -45,19 +45,19 @@ QStringList EnderalSEDataArchives::archives(const MOBase::IProfile *profile) con QStringList result; QString iniFile = profile->localSettingsEnabled() ? QDir(profile->absolutePath()).absoluteFilePath("enderal.ini") : m_LocalGameDir.absoluteFilePath("enderal.ini"); - result.append(getArchivesFromKey(iniFile, "SResourceArchiveList")); - result.append(getArchivesFromKey(iniFile, "SResourceArchiveList2")); + result.append(getArchivesFromKey(iniFile, "SResourceArchiveList", 512)); + result.append(getArchivesFromKey(iniFile, "SResourceArchiveList2", 512)); return result; } void EnderalSEDataArchives::writeArchiveList(MOBase::IProfile *profile, const QStringList &before) { - QString list = before.join(", "); + QString list = before.join(","); QString iniFile = profile->localSettingsEnabled() ? QDir(profile->absolutePath()).absoluteFilePath("enderal.ini") : m_LocalGameDir.absoluteFilePath("enderal.ini"); - if (list.length() > 255) { - int splitIdx = list.lastIndexOf(",", 256); + if (list.length() > 511) { + int splitIdx = list.lastIndexOf(",", 512); setArchivesToKey(iniFile, "SResourceArchiveList", list.mid(0, splitIdx)); setArchivesToKey(iniFile, "SResourceArchiveList2", list.mid(splitIdx + 2)); } else { diff --git a/src/games/enderalse/src/enderalsegameplugins.cpp b/src/games/enderalse/src/enderalsegameplugins.cpp new file mode 100644 index 00000000..388c019d --- /dev/null +++ b/src/games/enderalse/src/enderalsegameplugins.cpp @@ -0,0 +1,81 @@ +#include "enderalsegameplugins.h" + +#include +#include +#include +#include + +using namespace MOBase; + +void EnderalSEGamePlugins::writePluginList(const MOBase::IPluginList* pluginList, const QString& filePath) +{ + SafeWriteFile file(filePath); + + QTextCodec* textCodec = localCodec(); + + file->resize(0); + + file->write(textCodec->fromUnicode( + "# This file was automatically generated by Mod Organizer.\r\n")); + + bool invalidFileNames = false; + int writtenCount = 0; + + QStringList plugins = pluginList->pluginNames(); + std::sort(plugins.begin(), plugins.end(), + [pluginList](const QString& lhs, const QString& rhs) { + return pluginList->priority(lhs) < pluginList->priority(rhs); + }); + + QStringList PrimaryPlugins = organizer()->managedGame()->primaryPlugins(); + QSet ManagedMods = PrimaryPlugins.toSet().subtract(organizer()->managedGame()->DLCPlugins().toSet()); + PrimaryPlugins.append(ManagedMods.toList()); + + // we need to force some plugins because those are not force-loaded + // by the game but are considered primary plugins for users + file->write("*Enderal - Forgotten Stories.esm\r\n"); + file->write("*SkyUI_SE.esp\r\n"); + + //TODO: do not write plugins in OFFICIAL_FILES container + for (const QString& pluginName : plugins) { + if (!PrimaryPlugins.contains(pluginName, Qt::CaseInsensitive)) { + if (pluginList->state(pluginName) == IPluginList::STATE_ACTIVE) { + if (!textCodec->canEncode(pluginName)) { + invalidFileNames = true; + qCritical("invalid plugin name %s", qUtf8Printable(pluginName)); + } + else + { + file->write("*"); + file->write(textCodec->fromUnicode(pluginName)); + + } + file->write("\r\n"); + ++writtenCount; + } + else + { + if (!textCodec->canEncode(pluginName)) { + invalidFileNames = true; + qCritical("invalid plugin name %s", qUtf8Printable(pluginName)); + } + else + { + file->write(textCodec->fromUnicode(pluginName)); + } + file->write("\r\n"); + ++writtenCount; + } + } + } + + if (invalidFileNames) { + reportError(QObject::tr("Some of your plugins have invalid names! These " + "plugins can not be loaded by the game. Please see " + "mo_interface.log for a list of affected plugins " + "and rename them.")); + } + + file.commitIfDifferent(m_LastSaveHash[filePath]); +} + diff --git a/src/games/enderalse/src/enderalsegameplugins.h b/src/games/enderalse/src/enderalsegameplugins.h new file mode 100644 index 00000000..560dc090 --- /dev/null +++ b/src/games/enderalse/src/enderalsegameplugins.h @@ -0,0 +1,22 @@ +#ifndef ENDERALSEGAMEPLUGINS_H +#define ENDERALSEGAMEPLUGINS_H + +#include +#include +#include +#include + +class EnderalSEGamePlugins : public CreationGamePlugins +{ +public: + using CreationGamePlugins::CreationGamePlugins; + +protected: + void writePluginList(const MOBase::IPluginList* pluginList, const QString& filePath) override; + +private: + std::map m_LastSaveHash; + +}; + +#endif // ENDERALSEGAMEPLUGINS_H \ No newline at end of file diff --git a/src/games/enderalse/src/game_enderalse_en.ts b/src/games/enderalse/src/game_enderalse_en.ts index 8c957c69..f8ff7fbd 100644 --- a/src/games/enderalse/src/game_enderalse_en.ts +++ b/src/games/enderalse/src/game_enderalse_en.ts @@ -14,4 +14,12 @@ + + QObject + + + Some of your plugins have invalid names! These plugins can not be loaded by the game. Please see mo_interface.log for a list of affected plugins and rename them. + + + diff --git a/src/games/enderalse/src/gameenderalse.cpp b/src/games/enderalse/src/gameenderalse.cpp index 43050871..6b400016 100644 --- a/src/games/enderalse/src/gameenderalse.cpp +++ b/src/games/enderalse/src/gameenderalse.cpp @@ -3,6 +3,7 @@ #include "enderalsedataarchives.h" #include "enderalsescriptextender.h" #include "enderalseunmanagedmods.h" +#include "enderalsegameplugins.h" #include "enderalsemoddatachecker.h" #include "enderalsemoddatacontent.h" #include "enderalsesavegame.h" @@ -12,7 +13,6 @@ #include #include #include -#include #include "versioninfo.h" #include #include @@ -84,7 +84,7 @@ bool GameEnderalSE::init(IOrganizer *moInfo) registerFeature(new EnderalSEModDataChecker(this)); registerFeature(new EnderalSEModDataContent(this)); registerFeature(new GamebryoSaveGameInfo(this)); - registerFeature(new CreationGamePlugins(moInfo)); + registerFeature(new EnderalSEGamePlugins(moInfo)); registerFeature(new EnderalSEUnmangedMods(this)); return true; @@ -211,6 +211,10 @@ QStringList GameEnderalSE::primaryPlugins() const "hearthfires.esm", "dragonborn.esm", "update.esm", + + // these two plugins are considered "primary" for users but are not + // automatically loaded by the game so we need to force-write them + // to the plugin list "enderal - forgotten stories.esm", "skyui_se.esp" }; From 6a6c149d441e0526b6d70ebe7ca00ee990ed34a0 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Mika=C3=ABl=20Capelle?= Date: Sun, 7 Mar 2021 16:00:21 +0100 Subject: [PATCH 1145/1544] [game_skyrimse] Add a setting to allow EnderalSE downloads. --- src/games/skyrimse/src/gameskyrimse.cpp | 10 ++++++++-- 1 file changed, 8 insertions(+), 2 deletions(-) diff --git a/src/games/skyrimse/src/gameskyrimse.cpp b/src/games/skyrimse/src/gameskyrimse.cpp index 8815f345..c224c537 100644 --- a/src/games/skyrimse/src/gameskyrimse.cpp +++ b/src/games/skyrimse/src/gameskyrimse.cpp @@ -136,7 +136,9 @@ MOBase::VersionInfo GameSkyrimSE::version() const QList GameSkyrimSE::settings() const { - return QList(); + return { + PluginSetting("enderal_downloads", "allow Enderal and Enderal SE downloads", QVariant(false)) + }; } void GameSkyrimSE::initializeProfile(const QDir &path, ProfileSettings settings) const @@ -207,7 +209,11 @@ QString GameSkyrimSE::gameShortName() const QStringList GameSkyrimSE::validShortNames() const { - return { "Skyrim" }; + QStringList shortNames{ "Skyrim" }; + if (m_Organizer->pluginSetting(name(), "enderal_downloads").toBool()) { + shortNames.append({ "Enderal", "EnderalSE" }); + } + return shortNames; } QString GameSkyrimSE::gameNexusName() const From eece41fcc47d6e922808a5296013effa622b8a6c Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Mika=C3=ABl=20Capelle?= Date: Fri, 12 Mar 2021 20:39:48 +0100 Subject: [PATCH 1146/1544] [game_enderalse] Fix local saves. --- .../enderalse/src/enderalselocalsavegames.cpp | 122 ++++++++++++++++++ .../enderalse/src/enderalselocalsavegames.h | 28 ++++ src/games/enderalse/src/game_enderalse_en.ts | 4 +- src/games/enderalse/src/gameenderalse.cpp | 34 +---- src/games/enderalse/src/gameenderalse.h | 7 - 5 files changed, 154 insertions(+), 41 deletions(-) create mode 100644 src/games/enderalse/src/enderalselocalsavegames.cpp create mode 100644 src/games/enderalse/src/enderalselocalsavegames.h diff --git a/src/games/enderalse/src/enderalselocalsavegames.cpp b/src/games/enderalse/src/enderalselocalsavegames.cpp new file mode 100644 index 00000000..839542b3 --- /dev/null +++ b/src/games/enderalse/src/enderalselocalsavegames.cpp @@ -0,0 +1,122 @@ +/* +Copyright (C) 2015 Sebastian Herbord. All rights reserved. + +This library is free software; you can redistribute it and/or +modify it under the terms of the GNU Lesser General Public +License as published by the Free Software Foundation; either +version 3 of the License, or (at your option) any later version. + +This library is distributed in the hope that it will be useful, +but WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +Lesser General Public License for more details. + +You should have received a copy of the GNU Lesser General Public +License along with this library; if not, write to the Free Software +Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA +*/ + + +#include "enderalselocalsavegames.h" +#include "registry.h" +#include +#include +#include +#include +#include + + +static const QString LocalSavesDummy = "..\\Enderal Special Edition\\__MO_Saves\\"; + + +EnderalSELocalSavegames::EnderalSELocalSavegames(const QDir& myGamesDir, + const QString& iniFileName) + : m_LocalSavesDir(myGamesDir.absoluteFilePath(LocalSavesDummy)) + , m_LocalGameDir(myGamesDir.absolutePath()) + , m_IniFileName(iniFileName) +{} + + +MappingType EnderalSELocalSavegames::mappings(const QDir& profileSaveDir) const +{ + return { { + profileSaveDir.absolutePath(), + m_LocalSavesDir.absolutePath(), + true, + true + } }; +} + + +bool EnderalSELocalSavegames::prepareProfile(MOBase::IProfile* profile) +{ + bool enable = profile->localSavesEnabled(); + + QString basePath + = profile->localSettingsEnabled() + ? profile->absolutePath() + : m_LocalGameDir.absolutePath(); + QString iniFilePath = basePath + "/" + m_IniFileName; + QString saveIni = profile->absolutePath() + "/" + "savepath.ini"; + + // Get the current sLocalSavePath + WCHAR currentPath[MAX_PATH]; + GetPrivateProfileStringW(L"General", L"sLocalSavePath", L"SKIP_ME", currentPath, MAX_PATH, iniFilePath.toStdWString().c_str()); + bool alreadyEnabled = wcscmp(currentPath, LocalSavesDummy.toStdWString().c_str()) == 0; + + // Get the current bUseMyGamesDirectory + WCHAR currentMyGames[MAX_PATH]; + GetPrivateProfileStringW(L"General", L"bUseMyGamesDirectory", L"SKIP_ME", currentMyGames, MAX_PATH, iniFilePath.toStdWString().c_str()); + + // Create the __MO_Saves directory if local saves are enabled and it doesn't exist + if (enable) { + QDir saves = QDir(m_LocalGameDir.absolutePath() + "/" + LocalSavesDummy); + if (!saves.exists()) { + saves.mkdir("."); + } + } + + // Set the path to __MO_Saves if it's not already + if (enable && !alreadyEnabled) { + // If the path is not blank, save it to savepath.ini + if (wcscmp(currentPath, L"SKIP_ME") != 0) { + MOBase::WriteRegistryValue(L"General", L"sLocalSavePath", currentPath, saveIni.toStdWString().c_str()); + } + if (wcscmp(currentMyGames, L"SKIP_ME") != 0) { + MOBase::WriteRegistryValue(L"General", L"bUseMyGamesDirectory", currentMyGames, saveIni.toStdWString().c_str()); + } + MOBase::WriteRegistryValue(L"General", L"sLocalSavePath", LocalSavesDummy.toStdWString().c_str(), iniFilePath.toStdWString().c_str()); + MOBase::WriteRegistryValue(L"General", L"bUseMyGamesDirectory", L"1", iniFilePath.toStdWString().c_str()); + } + + // Get rid of the local saves setting if it's still there + if (!enable && alreadyEnabled) { + // If savepath.ini exists, use it and delete it + if (QFile::exists(saveIni)) { + WCHAR savedPath[MAX_PATH]; + WCHAR savedMyGames[MAX_PATH]; + GetPrivateProfileStringW(L"General", L"sLocalSavePath", L"DELETE_ME", savedPath, MAX_PATH, saveIni.toStdWString().c_str()); + GetPrivateProfileStringW(L"General", L"bUseMyGamesDirectory", L"DELETE_ME", savedMyGames, MAX_PATH, saveIni.toStdWString().c_str()); + if (wcscmp(savedPath, L"DELETE_ME") != 0) { + MOBase::WriteRegistryValue(L"General", L"sLocalSavePath", savedPath, iniFilePath.toStdWString().c_str()); + } + else { + MOBase::WriteRegistryValue(L"General", L"sLocalSavePath", NULL, iniFilePath.toStdWString().c_str()); + } + if (wcscmp(savedMyGames, L"DELETE_ME") != 0) { + MOBase::WriteRegistryValue(L"General", L"bUseMyGamesDirectory", savedMyGames, iniFilePath.toStdWString().c_str()); + } + else { + MOBase::WriteRegistryValue(L"General", L"bUseMyGamesDirectory", NULL, iniFilePath.toStdWString().c_str()); + } + QFile::remove(saveIni); + } + // Otherwise just delete the setting + else { + MOBase::WriteRegistryValue(L"General", L"sLocalSavePath", NULL, iniFilePath.toStdWString().c_str()); + MOBase::WriteRegistryValue(L"General", L"bUseMyGamesDirectory", NULL, iniFilePath.toStdWString().c_str()); + } + } + + return enable != alreadyEnabled; +} diff --git a/src/games/enderalse/src/enderalselocalsavegames.h b/src/games/enderalse/src/enderalselocalsavegames.h new file mode 100644 index 00000000..b24cfe59 --- /dev/null +++ b/src/games/enderalse/src/enderalselocalsavegames.h @@ -0,0 +1,28 @@ +#ifndef ENDERALSELOCALSAVEGAMES_H +#define ENDERALSELOCALSAVEGAMES_H + + +#include + +#include +#include + +class EnderalSELocalSavegames : public LocalSavegames +{ + +public: + EnderalSELocalSavegames(const QDir& myGamesDir, const QString& iniFileName); + + virtual MappingType mappings(const QDir& profileSaveDir) const override; + virtual bool prepareProfile(MOBase::IProfile* profile) override; + +private: + + QDir m_LocalSavesDir; + QDir m_LocalGameDir; + QString m_IniFileName; + +}; + + +#endif // ENDERALSELOCALSAVEGAMES_H diff --git a/src/games/enderalse/src/game_enderalse_en.ts b/src/games/enderalse/src/game_enderalse_en.ts index f8ff7fbd..0aeeed59 100644 --- a/src/games/enderalse/src/game_enderalse_en.ts +++ b/src/games/enderalse/src/game_enderalse_en.ts @@ -4,12 +4,12 @@ GameEnderalSE - + Enderal Special Edition Support Plugin - + Adds support for the game Enderal Special Edition. diff --git a/src/games/enderalse/src/gameenderalse.cpp b/src/games/enderalse/src/gameenderalse.cpp index 6b400016..f0ad5457 100644 --- a/src/games/enderalse/src/gameenderalse.cpp +++ b/src/games/enderalse/src/gameenderalse.cpp @@ -4,6 +4,7 @@ #include "enderalsescriptextender.h" #include "enderalseunmanagedmods.h" #include "enderalsegameplugins.h" +#include "enderalselocalsavegames.h" #include "enderalsemoddatachecker.h" #include "enderalsemoddatacontent.h" #include "enderalsesavegame.h" @@ -12,7 +13,6 @@ #include #include #include -#include #include "versioninfo.h" #include #include @@ -34,16 +34,6 @@ GameEnderalSE::GameEnderalSE() { } -void GameEnderalSE::setGamePath(const QString &path) -{ - m_GamePath = path; -} - -QDir GameEnderalSE::documentsDirectory() const -{ - return m_MyGamesPath; -} - QString GameEnderalSE::identifyGamePath() const { QString path = "Software\\SureAI\\EnderalSE"; @@ -57,21 +47,6 @@ QString GameEnderalSE::identifyGamePath() const return result; } -QDir GameEnderalSE::savesDirectory() const -{ - return QDir(m_MyGamesPath + "/Saves"); -} - -QString GameEnderalSE::myGamesPath() const -{ - return m_MyGamesPath; -} - -bool GameEnderalSE::isInstalled() const -{ - return !m_GamePath.isEmpty(); -} - bool GameEnderalSE::init(IOrganizer *moInfo) { if (!GameGamebryo::init(moInfo)) { @@ -80,7 +55,7 @@ bool GameEnderalSE::init(IOrganizer *moInfo) registerFeature(new EnderalSEScriptExtender(this)); registerFeature(new EnderalSEDataArchives(myGamesPath())); - registerFeature(new GamebryoLocalSavegames(myGamesPath(), "enderal.ini")); + registerFeature(new EnderalSELocalSavegames(myGamesPath(), "Enderal.ini")); registerFeature(new EnderalSEModDataChecker(this)); registerFeature(new EnderalSEModDataContent(this)); registerFeature(new GamebryoSaveGameInfo(this)); @@ -288,11 +263,6 @@ int GameEnderalSE::nexusGameID() const return 3685; } -QDir GameEnderalSE::gameDirectory() const -{ - return QDir(m_GamePath); -} - // Not to delete all the spaces... MappingType GameEnderalSE::mappings() const { diff --git a/src/games/enderalse/src/gameenderalse.h b/src/games/enderalse/src/gameenderalse.h index 6018dac1..fd404dd5 100644 --- a/src/games/enderalse/src/gameenderalse.h +++ b/src/games/enderalse/src/gameenderalse.h @@ -41,10 +41,6 @@ public: // IPluginGame interface virtual int nexusModOrganizerID() const override; virtual int nexusGameID() 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; @@ -62,10 +58,7 @@ protected: QString savegameExtension() const override; QString savegameSEExtension() const override; - QDir documentsDirectory() const; - QDir savesDirectory() const; QFileInfo findInGameFolder(const QString &relativePath) const; - QString myGamesPath() const; virtual QString identifyGamePath() const override; From 12e92a98eca2a0edc46cf4f45762eafaa9f2c87e Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Mika=C3=ABl=20Capelle?= Date: Fri, 12 Mar 2021 20:58:21 +0100 Subject: [PATCH 1147/1544] [game_enderalse] Fix relative order of Update.esm and placeholder DLCs. --- src/games/enderalse/src/gameenderalse.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/games/enderalse/src/gameenderalse.cpp b/src/games/enderalse/src/gameenderalse.cpp index f0ad5457..4a4f8a6b 100644 --- a/src/games/enderalse/src/gameenderalse.cpp +++ b/src/games/enderalse/src/gameenderalse.cpp @@ -182,10 +182,10 @@ QStringList GameEnderalSE::primaryPlugins() const { return { "skyrim.esm", + "update.esm", "dawnguard.esm", "hearthfires.esm", "dragonborn.esm", - "update.esm", // these two plugins are considered "primary" for users but are not // automatically loaded by the game so we need to force-write them From 7b1c55104ef9d12ed37c03823d497ab7f87f416e Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Mika=C3=ABl=20Capelle?= Date: Mon, 15 Mar 2021 18:39:53 +0100 Subject: [PATCH 1148/1544] [game_enderalse] Override looksValid to check for launcher and binary. --- src/games/enderalse/src/game_enderalse_en.ts | 4 ++-- src/games/enderalse/src/gameenderalse.cpp | 6 ++++++ src/games/enderalse/src/gameenderalse.h | 1 + 3 files changed, 9 insertions(+), 2 deletions(-) diff --git a/src/games/enderalse/src/game_enderalse_en.ts b/src/games/enderalse/src/game_enderalse_en.ts index 0aeeed59..d9206476 100644 --- a/src/games/enderalse/src/game_enderalse_en.ts +++ b/src/games/enderalse/src/game_enderalse_en.ts @@ -4,12 +4,12 @@ GameEnderalSE - + Enderal Special Edition Support Plugin - + Adds support for the game Enderal Special Edition. diff --git a/src/games/enderalse/src/gameenderalse.cpp b/src/games/enderalse/src/gameenderalse.cpp index 4a4f8a6b..f7d4eaa3 100644 --- a/src/games/enderalse/src/gameenderalse.cpp +++ b/src/games/enderalse/src/gameenderalse.cpp @@ -100,6 +100,12 @@ QString GameEnderalSE::getLauncherName() const return "Enderal Launcher.exe"; } +bool GameEnderalSE::looksValid(const QDir& folder) const +{ + // we need to check both launcher and binary because the binary also exists for + // Skyrim SE and the launcher for Enderal LE + return folder.exists(getLauncherName()) && folder.exists(binaryName()); +} QFileInfo GameEnderalSE::findInGameFolder(const QString &relativePath) const { diff --git a/src/games/enderalse/src/gameenderalse.h b/src/games/enderalse/src/gameenderalse.h index fd404dd5..99b3578d 100644 --- a/src/games/enderalse/src/gameenderalse.h +++ b/src/games/enderalse/src/gameenderalse.h @@ -30,6 +30,7 @@ public: // IPluginGame interface virtual QStringList gameVariants() const override; virtual QString binaryName() const override; virtual QString getLauncherName() const override; + virtual bool looksValid(const QDir& folder) const override; virtual QString gameShortName() const override; virtual QString gameNexusName() const override; virtual QStringList validShortNames() const override; From b274fc1d61b25b08658087bd4e3548a5173f399c Mon Sep 17 00:00:00 2001 From: Al <26797547+Al12rs@users.noreply.github.com> Date: Thu, 8 Apr 2021 23:11:59 +0200 Subject: [PATCH 1149/1544] [game_falloutnv] Add ini as valid extension --- src/games/falloutnv/src/falloutnvmoddatachecker.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/games/falloutnv/src/falloutnvmoddatachecker.h b/src/games/falloutnv/src/falloutnvmoddatachecker.h index 9a43c3e7..8c070df2 100644 --- a/src/games/falloutnv/src/falloutnvmoddatachecker.h +++ b/src/games/falloutnv/src/falloutnvmoddatachecker.h @@ -20,7 +20,7 @@ protected: } virtual const FileNameSet& possibleFileExtensions() const override { static FileNameSet result{ - "esp", "esm", "bsa", "modgroups" + "esp", "esm", "bsa", "modgroups", "ini" }; return result; } From 686bf2bbda00e3d725231d1852eb391b44be6bbf Mon Sep 17 00:00:00 2001 From: Al <26797547+Al12rs@users.noreply.github.com> Date: Thu, 8 Apr 2021 23:13:12 +0200 Subject: [PATCH 1150/1544] [game_fallout4] Add ini as valid extension --- src/games/fallout4/src/fallout4moddatachecker.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/games/fallout4/src/fallout4moddatachecker.h b/src/games/fallout4/src/fallout4moddatachecker.h index 0482ac1a..5fe0e63c 100644 --- a/src/games/fallout4/src/fallout4moddatachecker.h +++ b/src/games/fallout4/src/fallout4moddatachecker.h @@ -20,7 +20,7 @@ protected: } virtual const FileNameSet& possibleFileExtensions() const override { static FileNameSet result{ - "esp", "esm", "esl", "ba2", "modgroups" + "esp", "esm", "esl", "ba2", "modgroups", "ini" }; return result; } From df1eb9bde160fffa4d96c482070420768574106f Mon Sep 17 00:00:00 2001 From: Al <26797547+Al12rs@users.noreply.github.com> Date: Thu, 8 Apr 2021 23:13:45 +0200 Subject: [PATCH 1151/1544] [game_fallout3] Add ini as valid extension --- src/games/fallout3/src/fallout3moddatachecker.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/games/fallout3/src/fallout3moddatachecker.h b/src/games/fallout3/src/fallout3moddatachecker.h index 8bdb824f..a91fdc60 100644 --- a/src/games/fallout3/src/fallout3moddatachecker.h +++ b/src/games/fallout3/src/fallout3moddatachecker.h @@ -20,7 +20,7 @@ protected: } virtual const FileNameSet& possibleFileExtensions() const override { static FileNameSet result{ - "esp", "esm", "bsa", "modgroups" + "esp", "esm", "bsa", "modgroups", "ini" }; return result; } From 6aefe98a9ff8f8a7b419f6aa645c1a7b8ac04ff2 Mon Sep 17 00:00:00 2001 From: Al <26797547+Al12rs@users.noreply.github.com> Date: Thu, 8 Apr 2021 23:14:16 +0200 Subject: [PATCH 1152/1544] [game_enderalse] Add ini as valid extension --- src/games/enderalse/src/enderalsemoddatachecker.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/games/enderalse/src/enderalsemoddatachecker.h b/src/games/enderalse/src/enderalsemoddatachecker.h index 1a2c8ff4..c2b48b69 100644 --- a/src/games/enderalse/src/enderalsemoddatachecker.h +++ b/src/games/enderalse/src/enderalsemoddatachecker.h @@ -21,7 +21,7 @@ protected: } virtual const FileNameSet& possibleFileExtensions() const override { static FileNameSet result{ - "esp", "esm", "esl", "bsa", "modgroups" + "esp", "esm", "esl", "bsa", "modgroups", "ini" }; return result; } From 68747c3353157fa3c3bed67888a602ceac5f948a Mon Sep 17 00:00:00 2001 From: Al <26797547+Al12rs@users.noreply.github.com> Date: Thu, 8 Apr 2021 23:15:13 +0200 Subject: [PATCH 1153/1544] [game_ttw] Add ini as valid extension --- src/games/ttw/src/falloutttwmoddatachecker.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/games/ttw/src/falloutttwmoddatachecker.h b/src/games/ttw/src/falloutttwmoddatachecker.h index 7499da31..66fe756b 100644 --- a/src/games/ttw/src/falloutttwmoddatachecker.h +++ b/src/games/ttw/src/falloutttwmoddatachecker.h @@ -20,7 +20,7 @@ protected: } virtual const FileNameSet& possibleFileExtensions() const override { static FileNameSet result{ - "esp", "esm", "bsa", "modgroups" + "esp", "esm", "bsa", "modgroups", "ini" }; return result; } From 91baad4e36f4478116f0d4b4e28cdb299d9c6c2f Mon Sep 17 00:00:00 2001 From: Al <26797547+Al12rs@users.noreply.github.com> Date: Thu, 8 Apr 2021 23:15:36 +0200 Subject: [PATCH 1154/1544] [game_skyrimvr] Add ini as valid extension --- src/games/skyrimvr/src/skyrimvrmoddatachecker.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/games/skyrimvr/src/skyrimvrmoddatachecker.h b/src/games/skyrimvr/src/skyrimvrmoddatachecker.h index 8cbdec5f..377e8ced 100644 --- a/src/games/skyrimvr/src/skyrimvrmoddatachecker.h +++ b/src/games/skyrimvr/src/skyrimvrmoddatachecker.h @@ -21,7 +21,7 @@ protected: } virtual const FileNameSet& possibleFileExtensions() const override { static FileNameSet result{ - "esp", "esm", "bsa", "modgroups" + "esp", "esm", "bsa", "modgroups", "ini" }; return result; } From 8642eebf06037672ffa3467d7eab640590761737 Mon Sep 17 00:00:00 2001 From: Al <26797547+Al12rs@users.noreply.github.com> Date: Thu, 8 Apr 2021 23:16:03 +0200 Subject: [PATCH 1155/1544] [game_skyrim] Add ini as valid extension --- src/games/skyrim/src/skyrimmoddatachecker.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/games/skyrim/src/skyrimmoddatachecker.h b/src/games/skyrim/src/skyrimmoddatachecker.h index d2b91d3c..a5c59392 100644 --- a/src/games/skyrim/src/skyrimmoddatachecker.h +++ b/src/games/skyrim/src/skyrimmoddatachecker.h @@ -21,7 +21,7 @@ protected: } virtual const FileNameSet& possibleFileExtensions() const override { static FileNameSet result{ - "esp", "esm", "bsa", "modgroups" + "esp", "esm", "bsa", "modgroups", "ini" }; return result; } From d3eff417209a7545b813412901c1cb2b9601d818 Mon Sep 17 00:00:00 2001 From: Al <26797547+Al12rs@users.noreply.github.com> Date: Thu, 8 Apr 2021 23:16:27 +0200 Subject: [PATCH 1156/1544] [game_oblivion] Add ini as valid extension --- src/games/oblivion/src/oblivionmoddatachecker.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/games/oblivion/src/oblivionmoddatachecker.h b/src/games/oblivion/src/oblivionmoddatachecker.h index f9b14e9a..5159dc09 100644 --- a/src/games/oblivion/src/oblivionmoddatachecker.h +++ b/src/games/oblivion/src/oblivionmoddatachecker.h @@ -23,7 +23,7 @@ protected: } virtual const FileNameSet& possibleFileExtensions() const override { static FileNameSet result{ - "esp", "esm", "bsa", "modgroups" + "esp", "esm", "bsa", "modgroups", "ini" }; return result; } From 849511f7c02f695af234134919856fad98b5e6ca Mon Sep 17 00:00:00 2001 From: Al <26797547+Al12rs@users.noreply.github.com> Date: Thu, 8 Apr 2021 23:16:52 +0200 Subject: [PATCH 1157/1544] Add ini as valid extension --- src/gamebryo/gamebryomoddatachecker.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/gamebryo/gamebryomoddatachecker.cpp b/src/gamebryo/gamebryomoddatachecker.cpp index ccda8eb9..224dc8ea 100644 --- a/src/gamebryo/gamebryomoddatachecker.cpp +++ b/src/gamebryo/gamebryomoddatachecker.cpp @@ -24,7 +24,7 @@ auto GamebryoModDataChecker::possibleFolderNames() const -> const FileNameSet& { */ auto GamebryoModDataChecker::possibleFileExtensions() const -> const FileNameSet& { static FileNameSet result{ - "esp", "esm", "esl", "bsa", "ba2", "modgroups" + "esp", "esm", "esl", "bsa", "ba2", "modgroups", "ini" }; return result; } From 28bb77886a3cbdf82f8c2cafbf8d629e39b8f967 Mon Sep 17 00:00:00 2001 From: Al <26797547+Al12rs@users.noreply.github.com> Date: Thu, 8 Apr 2021 23:17:13 +0200 Subject: [PATCH 1158/1544] [game_skyrimse] Add ini as valid extension --- src/games/skyrimse/src/skyrimsemoddatachecker.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/games/skyrimse/src/skyrimsemoddatachecker.h b/src/games/skyrimse/src/skyrimsemoddatachecker.h index ec530488..56203d3d 100644 --- a/src/games/skyrimse/src/skyrimsemoddatachecker.h +++ b/src/games/skyrimse/src/skyrimsemoddatachecker.h @@ -21,7 +21,7 @@ protected: } virtual const FileNameSet& possibleFileExtensions() const override { static FileNameSet result{ - "esp", "esm", "esl", "bsa", "modgroups" + "esp", "esm", "esl", "bsa", "modgroups", "ini" }; return result; } From 505f8741fb6ebcba040b1b9096e47e5ae67c82fc Mon Sep 17 00:00:00 2001 From: Al <26797547+Al12rs@users.noreply.github.com> Date: Wed, 14 Apr 2021 17:04:54 +0200 Subject: [PATCH 1159/1544] [game_fallout4vr] Add ini as valid extension (#20) --- src/games/fallout4vr/src/fallout4vrmoddatachecker.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/games/fallout4vr/src/fallout4vrmoddatachecker.h b/src/games/fallout4vr/src/fallout4vrmoddatachecker.h index 1fc75e73..8a4b4d8f 100644 --- a/src/games/fallout4vr/src/fallout4vrmoddatachecker.h +++ b/src/games/fallout4vr/src/fallout4vrmoddatachecker.h @@ -20,7 +20,7 @@ protected: } virtual const FileNameSet& possibleFileExtensions() const override { static FileNameSet result{ - "esp", "esm", "ba2", "modgroups" + "esp", "esm", "ba2", "modgroups", "ini" }; return result; } From bcf0e36205cfa6861fa30c2286174148d1625700 Mon Sep 17 00:00:00 2001 From: isanae <14251494+isanae@users.noreply.github.com> Date: Tue, 18 May 2021 11:45:28 -0400 Subject: [PATCH 1160/1544] [game_fallout3] fixed typo in description --- src/games/fallout3/src/gamefallout3.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/games/fallout3/src/gamefallout3.cpp b/src/games/fallout3/src/gamefallout3.cpp index 275dba6a..122efd0c 100644 --- a/src/games/fallout3/src/gamefallout3.cpp +++ b/src/games/fallout3/src/gamefallout3.cpp @@ -88,7 +88,7 @@ QString GameFallout3::author() const QString GameFallout3::description() const { - return tr("Adds support for the game Fallout 3s"); + return tr("Adds support for the game Fallout 3."); } MOBase::VersionInfo GameFallout3::version() const From df3282064ad9409878c7123e84d046662c2417fb Mon Sep 17 00:00:00 2001 From: Chris Bessent Date: Fri, 21 May 2021 19:02:23 -0700 Subject: [PATCH 1161/1544] [game_skyrimvr] Add a setting to allow Enderal and EnderalSE downloads. --- src/games/skyrimvr/src/gameskyrimvr.cpp | 10 ++++++++-- 1 file changed, 8 insertions(+), 2 deletions(-) diff --git a/src/games/skyrimvr/src/gameskyrimvr.cpp b/src/games/skyrimvr/src/gameskyrimvr.cpp index 3749c1ca..2ca3c245 100644 --- a/src/games/skyrimvr/src/gameskyrimvr.cpp +++ b/src/games/skyrimvr/src/gameskyrimvr.cpp @@ -134,7 +134,9 @@ MOBase::VersionInfo GameSkyrimVR::version() const QList GameSkyrimVR::settings() const { - return QList(); + return { + PluginSetting("enderal_downloads", "allow Enderal and Enderal SE downloads", QVariant(false)) + }; } void GameSkyrimVR::initializeProfile(const QDir &path, ProfileSettings settings) const @@ -202,7 +204,11 @@ QStringList GameSkyrimVR::primarySources() const QStringList GameSkyrimVR::validShortNames() const { - return { "Skyrim", "SkyrimSE" }; + QStringList shortNames{ "Skyrim", "SkyrimSE" }; + if (m_Organizer->pluginSetting(name(), "enderal_downloads").toBool()) { + shortNames.append({ "Enderal", "EnderalSE" }); + } + return shortNames; } QString GameSkyrimVR::gameNexusName() const From 5ad02e9e48b8765959942fc8ca6a2ea3c35d891e Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Mika=C3=ABl=20Capelle?= Date: Wed, 26 May 2021 19:46:25 +0200 Subject: [PATCH 1162/1544] Update after removal of boost in uibase. --- src/gamebryo/gamegamebryo.cpp | 2 +- src/gamebryo/gamegamebryo.h | 6 +++--- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/src/gamebryo/gamegamebryo.cpp b/src/gamebryo/gamegamebryo.cpp index bd2a80b7..841ae3b2 100644 --- a/src/gamebryo/gamegamebryo.cpp +++ b/src/gamebryo/gamegamebryo.cpp @@ -268,7 +268,7 @@ QString GameGamebryo::myGamesPath() const return findInRegistry(HKEY_LOCAL_MACHINE, L"Software\\LOOT", L"Installed Path") + "/Loot.exe"; } -std::map GameGamebryo::featureList() const +std::map GameGamebryo::featureList() const { return m_FeatureList; } diff --git a/src/gamebryo/gamegamebryo.h b/src/gamebryo/gamegamebryo.h index b27f4276..e126c29f 100644 --- a/src/gamebryo/gamegamebryo.h +++ b/src/gamebryo/gamegamebryo.h @@ -132,7 +132,7 @@ protected: protected: - std::map featureList() const override; + std::map featureList() const override; //These should be implemented by anything that uses gamebryo (I think) //(and if they don't, it'll be a null pointer and won't look implemented, @@ -150,7 +150,7 @@ protected: void registerFeature(T *type) { auto index = std::type_index(typeid(T)); if (m_FeatureList.find(index) != m_FeatureList.end()) { - delete boost::any_cast(m_FeatureList[index]); + delete std::any_cast(m_FeatureList[index]); } m_FeatureList[index] = type; } @@ -162,7 +162,7 @@ protected: QString m_GameVariant; MOBase::IOrganizer *m_Organizer; - std::map m_FeatureList; + std::map m_FeatureList; }; From 813835263392e821cb53e28c2d91f6d284b3ef47 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Mika=C3=ABl=20Capelle?= Date: Sat, 26 Jun 2021 17:14:22 +0200 Subject: [PATCH 1163/1544] [game_fallout76] Remove savegame support. Update for latest uibase. --- src/games/fallout76/src/fallout76savegame.cpp | 60 ++++++++++++++----- src/games/fallout76/src/fallout76savegame.h | 18 +++++- .../fallout76/src/fallout76savegameinfo.cpp | 6 -- .../fallout76/src/fallout76savegameinfo.h | 2 - .../fallout76/src/fallout76scriptextender.cpp | 5 -- .../fallout76/src/fallout76scriptextender.h | 3 - src/games/fallout76/src/game_fallout76_en.ts | 2 +- src/games/fallout76/src/gamefallout76.cpp | 19 +++--- src/games/fallout76/src/gamefallout76.h | 48 ++++++++------- 9 files changed, 97 insertions(+), 66 deletions(-) diff --git a/src/games/fallout76/src/fallout76savegame.cpp b/src/games/fallout76/src/fallout76savegame.cpp index 99141164..98da5a07 100644 --- a/src/games/fallout76/src/fallout76savegame.cpp +++ b/src/games/fallout76/src/fallout76savegame.cpp @@ -1,21 +1,41 @@ #include "fallout76savegame.h" -#include +#include "gamefallout76.h" -Fallout76SaveGame::Fallout76SaveGame(QString const &fileName, MOBase::IPluginGame const *game, bool const lightEnabled) : - GamebryoSaveGame(fileName, game, lightEnabled) +Fallout76SaveGame::Fallout76SaveGame(QString const& fileName, GameFallout76 const* game) : + GamebryoSaveGame(fileName, game, true) { - FileWrapper file(this, "FO76_SAVEGAME"); + FileWrapper file(fileName, "FO76_SAVEGAME"); + + FILETIME ftime; + fetchInformationFields(file, m_PCName, m_PCLevel, m_PCLocation, m_SaveNumber, ftime); + + //A file time is a 64-bit value that represents the number of 100-nanosecond + //intervals that have elapsed since 12:00 A.M. January 1, 1601 Coordinated Universal Time (UTC). + //So we need to convert that to something useful + SYSTEMTIME ctime; + ::FileTimeToSystemTime(&ftime, &ctime); + + setCreationTime(ctime); +} + +void Fallout76SaveGame::fetchInformationFields(FileWrapper& file, + QString& playerName, + unsigned short& playerLevel, + QString& playerLocation, + unsigned long& saveNumber, + FILETIME& creationTime) const { + file.skip(); // header size file.skip(); // header version - file.read(m_SaveNumber); + file.read(saveNumber); - file.read(m_PCName); + file.read(playerName); unsigned long temp; file.read(temp); - m_PCLevel = static_cast(temp); - file.read(m_PCLocation); + playerLevel = static_cast(temp); + file.read(playerLocation); QString ignore; file.read(ignore); // playtime as ascii hh.mm.ss @@ -26,13 +46,20 @@ Fallout76SaveGame::Fallout76SaveGame(QString const &fileName, MOBase::IPluginGam FILETIME ftime; file.read(ftime); - //A file time is a 64-bit value that represents the number of 100-nanosecond - //intervals that have elapsed since 12:00 A.M. January 1, 1601 Coordinated Universal Time (UTC). - //So we need to convert that to something useful - SYSTEMTIME ctime; - ::FileTimeToSystemTime(&ftime, &ctime); - setCreationTime(ctime); +} + +std::unique_ptr Fallout76SaveGame::fetchDataFields() const { + + FileWrapper file(getFilepath(), "TESV_SAVEGAME"); //10bytes + { + + FILETIME ftime; + fetchInformationFields(file, m_PCName, m_PCLevel, m_PCLocation, m_SaveNumber, ftime); + + } + + std::unique_ptr fields = std::make_unique(); file.readImage(384, true); @@ -41,6 +68,7 @@ Fallout76SaveGame::Fallout76SaveGame(QString const &fileName, MOBase::IPluginGam file.skip(); // plugin info size file.readPlugins(); - if (saveGameVersion >= 68) - file.readLightPlugins(); + if (saveGameVersion >= 68) { + file.readLightPlugins(); + } } diff --git a/src/games/fallout76/src/fallout76savegame.h b/src/games/fallout76/src/fallout76savegame.h index e015f18c..8de6cca9 100644 --- a/src/games/fallout76/src/fallout76savegame.h +++ b/src/games/fallout76/src/fallout76savegame.h @@ -1,14 +1,28 @@ #ifndef FALLOUT76SAVEGAME_H #define FALLOUT76SAVEGAME_H +#include fetchDataFields() const override; }; #endif // FALLOUT76SAVEGAME_H diff --git a/src/games/fallout76/src/fallout76savegameinfo.cpp b/src/games/fallout76/src/fallout76savegameinfo.cpp index e0417e84..9ba77dd8 100644 --- a/src/games/fallout76/src/fallout76savegameinfo.cpp +++ b/src/games/fallout76/src/fallout76savegameinfo.cpp @@ -11,9 +11,3 @@ Fallout76SaveGameInfo::Fallout76SaveGameInfo(GameGamebryo const *game) : Fallout76SaveGameInfo::~Fallout76SaveGameInfo() { } - -const MOBase::ISaveGame *Fallout76SaveGameInfo::getSaveGameInfo(const QString &file) const -{ - return new Fallout76SaveGame(file, m_Game); -} - diff --git a/src/games/fallout76/src/fallout76savegameinfo.h b/src/games/fallout76/src/fallout76savegameinfo.h index 9922b1de..3aa57e5b 100644 --- a/src/games/fallout76/src/fallout76savegameinfo.h +++ b/src/games/fallout76/src/fallout76savegameinfo.h @@ -10,8 +10,6 @@ class Fallout76SaveGameInfo : public GamebryoSaveGameInfo public: Fallout76SaveGameInfo(GameGamebryo const *game); ~Fallout76SaveGameInfo(); - - virtual MOBase::ISaveGame const *getSaveGameInfo(QString const &file) const override; }; #endif // FALLOUT76SAVEGAMEINFO_H diff --git a/src/games/fallout76/src/fallout76scriptextender.cpp b/src/games/fallout76/src/fallout76scriptextender.cpp index 90f0855a..11b0e0c5 100644 --- a/src/games/fallout76/src/fallout76scriptextender.cpp +++ b/src/games/fallout76/src/fallout76scriptextender.cpp @@ -17,8 +17,3 @@ QString Fallout76ScriptExtender::PluginPath() const { return "f76se/plugins"; } - -QStringList Fallout76ScriptExtender::saveGameAttachmentExtensions() const -{ - return { }; -} diff --git a/src/games/fallout76/src/fallout76scriptextender.h b/src/games/fallout76/src/fallout76scriptextender.h index 1a0e7c6d..b8c13799 100644 --- a/src/games/fallout76/src/fallout76scriptextender.h +++ b/src/games/fallout76/src/fallout76scriptextender.h @@ -12,9 +12,6 @@ public: virtual QString BinaryName() const override; virtual QString PluginPath() const override; - - virtual QStringList saveGameAttachmentExtensions() const override; - }; #endif // FALLOUT76SCRIPTEXTENDER_H diff --git a/src/games/fallout76/src/game_fallout76_en.ts b/src/games/fallout76/src/game_fallout76_en.ts index 397b03f6..451031f7 100644 --- a/src/games/fallout76/src/game_fallout76_en.ts +++ b/src/games/fallout76/src/game_fallout76_en.ts @@ -4,7 +4,7 @@ GameFallout76 - + Adds support for the game Fallout 76. Splash by %1 diff --git a/src/games/fallout76/src/gamefallout76.cpp b/src/games/fallout76/src/gamefallout76.cpp index 5727cbdb..52bb3647 100644 --- a/src/games/fallout76/src/gamefallout76.cpp +++ b/src/games/fallout76/src/gamefallout76.cpp @@ -39,10 +39,8 @@ bool GameFallout76::init(IOrganizer *moInfo) registerFeature(new Fallout76ScriptExtender(this)); registerFeature(new Fallout76DataArchives(myGamesPath())); - registerFeature(new GamebryoLocalSavegames(myGamesPath(), "Fallout76.ini")); registerFeature(new Fallout76ModDataChecker(this)); registerFeature(new Fallout76ModDataContent(this)); - registerFeature(new Fallout76SaveGameInfo(this)); registerFeature(new CreationGamePlugins(moInfo)); registerFeature(new Fallout76UnmangedMods(this)); @@ -87,12 +85,7 @@ QString GameFallout76::description() const MOBase::VersionInfo GameFallout76::version() const { - return VersionInfo(2, 0, 0, VersionInfo::RELEASE_ALPHA); -} - -bool GameFallout76::isActive() const -{ - return qApp->property("managed_game").value() == this; + return VersionInfo(3, 0, 0, VersionInfo::RELEASE_ALPHA); } QList GameFallout76::settings() const @@ -130,6 +123,16 @@ QString GameFallout76::savegameSEExtension() const return "f76se"; } +std::vector> GameFallout76::listSaves(QDir folder) const +{ + return {}; +} + +std::shared_ptr GameFallout76::makeSaveGame(QString) const +{ + return nullptr; +} + QString GameFallout76::steamAPPId() const { return "n/a"; diff --git a/src/games/fallout76/src/gamefallout76.h b/src/games/fallout76/src/gamefallout76.h index ce083d42..c21e29e1 100644 --- a/src/games/fallout76/src/gamefallout76.h +++ b/src/games/fallout76/src/gamefallout76.h @@ -21,33 +21,35 @@ public: public: // IPluginGame interface - virtual QString gameName() const override; - virtual QList executables() const override; - virtual QList executableForcedLoads() const override; - virtual void initializeProfile(const QDir &path, ProfileSettings settings) const override; - virtual QString savegameExtension() const override; - virtual QString savegameSEExtension() const override; - virtual QString steamAPPId() const override; - virtual QStringList primaryPlugins() const override; - virtual QStringList gameVariants() const override; - virtual QString gameShortName() const override; - virtual QString gameNexusName() const override; - virtual QStringList iniFiles() const override; - virtual QStringList DLCPlugins() const override; - virtual QStringList CCPlugins() const override; - virtual LoadOrderMechanism loadOrderMechanism() const override; - virtual int nexusModOrganizerID() const override; - virtual int nexusGameID() const override; + QString gameName() const override; + QList executables() const override; + QList executableForcedLoads() const override; + void initializeProfile(const QDir &path, ProfileSettings settings) const override; + QString steamAPPId() const override; + QStringList primaryPlugins() const override; + QStringList gameVariants() const override; + QString gameShortName() const override; + QString gameNexusName() const override; + QStringList iniFiles() const override; + QStringList DLCPlugins() const override; + QStringList CCPlugins() const override; + LoadOrderMechanism loadOrderMechanism() const override; + int nexusModOrganizerID() const override; + int nexusGameID() const override; + std::vector> listSaves(QDir folder) const override; public: // IPlugin interface - virtual QString name() const override; - virtual QString author() const override; - virtual QString description() const override; - virtual MOBase::VersionInfo version() const override; - virtual bool isActive() const override; - virtual QList settings() const override; + QString name() const override; + QString author() const override; + QString description() const override; + MOBase::VersionInfo version() const override; + QList settings() const override; +protected: + std::shared_ptr makeSaveGame(QString) const; + QString savegameExtension() const override; + QString savegameSEExtension() const override; }; #endif // GAMEFallout76_H From 19e66d50798a3b15e8f3bdc963491b0bc91a44f0 Mon Sep 17 00:00:00 2001 From: AL <26797547+Al12rs@users.noreply.github.com> Date: Fri, 16 Jul 2021 12:55:10 +0200 Subject: [PATCH 1164/1544] Added Facegendata content filter (without icon). --- src/gamebryo/gamebryomoddatacontent.cpp | 14 ++++++++++++++ src/gamebryo/gamebryomoddatacontent.h | 1 + 2 files changed, 15 insertions(+) diff --git a/src/gamebryo/gamebryomoddatacontent.cpp b/src/gamebryo/gamebryomoddatacontent.cpp index 620ae5ba..a434774c 100644 --- a/src/gamebryo/gamebryomoddatacontent.cpp +++ b/src/gamebryo/gamebryomoddatacontent.cpp @@ -22,6 +22,7 @@ std::vector GamebryoModDataContent::getAllConte {CONTENT_TEXTURE, QT_TR_NOOP("Textures"), ":/MO/gui/content/texture"}, {CONTENT_MCM, QT_TR_NOOP("MCM Configuration"), ":/MO/gui/content/menu"}, {CONTENT_INI, QT_TR_NOOP("INI Files"), ":/MO/gui/content/inifile"}, + {CONTENT_FACEGEN, QT_TR_NOOP("FaceGen Data"), "", true}, {CONTENT_MODGROUP, QT_TR_NOOP("ModGroup Files"), ":/MO/gui/content/modgroup"} }; @@ -79,6 +80,19 @@ std::vector GamebryoModDataContent::getContentsFor(std::shared_ptrfindDirectory("meshes/actors/character/facegendata"); + if (e1) { + contents.push_back(CONTENT_FACEGEN); + } + else { + auto e2 = fileTree->findDirectory("textures/actors/character/facegendata"); + if (e2) { + contents.push_back(CONTENT_FACEGEN); + } + } + } + ScriptExtender* extender = m_GamePlugin->feature(); if (extender != nullptr) { auto e = fileTree->findDirectory(extender->PluginPath()); diff --git a/src/gamebryo/gamebryomoddatacontent.h b/src/gamebryo/gamebryomoddatacontent.h index 17e6a0b7..55d8b857 100644 --- a/src/gamebryo/gamebryomoddatacontent.h +++ b/src/gamebryo/gamebryomoddatacontent.h @@ -31,6 +31,7 @@ protected: CONTENT_SKYPROC, CONTENT_MCM, CONTENT_INI, + CONTENT_FACEGEN, CONTENT_MODGROUP }; From a1b52e42e893a43e54b3bbafadb3af996f7e71cd Mon Sep 17 00:00:00 2001 From: AL <26797547+Al12rs@users.noreply.github.com> Date: Fri, 16 Jul 2021 14:34:09 +0200 Subject: [PATCH 1165/1544] Added content icon. --- src/gamebryo/gamebryomoddatacontent.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/gamebryo/gamebryomoddatacontent.cpp b/src/gamebryo/gamebryomoddatacontent.cpp index a434774c..5d8560fa 100644 --- a/src/gamebryo/gamebryomoddatacontent.cpp +++ b/src/gamebryo/gamebryomoddatacontent.cpp @@ -22,7 +22,7 @@ std::vector GamebryoModDataContent::getAllConte {CONTENT_TEXTURE, QT_TR_NOOP("Textures"), ":/MO/gui/content/texture"}, {CONTENT_MCM, QT_TR_NOOP("MCM Configuration"), ":/MO/gui/content/menu"}, {CONTENT_INI, QT_TR_NOOP("INI Files"), ":/MO/gui/content/inifile"}, - {CONTENT_FACEGEN, QT_TR_NOOP("FaceGen Data"), "", true}, + {CONTENT_FACEGEN, QT_TR_NOOP("FaceGen Data"), ":/MO/gui/content/facegen"}, {CONTENT_MODGROUP, QT_TR_NOOP("ModGroup Files"), ":/MO/gui/content/modgroup"} }; From 40bb229d57197122828e18ecfec292fce80c31dc Mon Sep 17 00:00:00 2001 From: Chris Bessent Date: Sat, 14 Aug 2021 04:00:24 -0700 Subject: [PATCH 1166/1544] [game_oblivion] Allow downloading Nehrim mods --- src/games/oblivion/src/gameoblivion.cpp | 15 +++++++++++++-- src/games/oblivion/src/gameoblivion.h | 1 + 2 files changed, 14 insertions(+), 2 deletions(-) diff --git a/src/games/oblivion/src/gameoblivion.cpp b/src/games/oblivion/src/gameoblivion.cpp index b775c41d..1b8fd952 100644 --- a/src/games/oblivion/src/gameoblivion.cpp +++ b/src/games/oblivion/src/gameoblivion.cpp @@ -92,12 +92,14 @@ QString GameOblivion::description() const MOBase::VersionInfo GameOblivion::version() const { - return VersionInfo(1, 4, 1, VersionInfo::RELEASE_FINAL); + return VersionInfo(1, 5, 0, VersionInfo::RELEASE_FINAL); } QList GameOblivion::settings() const { - return QList(); + return { + PluginSetting("nehrim_downloads", "allow Nehrim downloads", QVariant(false)) + }; } void GameOblivion::initializeProfile(const QDir &path, ProfileSettings settings) const @@ -149,6 +151,15 @@ QString GameOblivion::gameShortName() const return "Oblivion"; } +QStringList GameOblivion::validShortNames() const +{ + QStringList shortNames; + if (m_Organizer->pluginSetting(name(), "nehrim_downloads").toBool()) { + shortNames.append( "Nehrim" ); + } + return shortNames; +} + QString GameOblivion::gameNexusName() const { return "Oblivion"; diff --git a/src/games/oblivion/src/gameoblivion.h b/src/games/oblivion/src/gameoblivion.h index 5ab867f7..48b54f50 100644 --- a/src/games/oblivion/src/gameoblivion.h +++ b/src/games/oblivion/src/gameoblivion.h @@ -26,6 +26,7 @@ public: // IPluginGame interface virtual QString steamAPPId() const override; virtual QStringList primaryPlugins() 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; From 7546541cfc8b9e29afc80a74dab44b4a8897e1e4 Mon Sep 17 00:00:00 2001 From: Chris Bessent Date: Sun, 22 Aug 2021 09:05:55 -0700 Subject: [PATCH 1167/1544] [game_nehrim] Initial files copied from Oblivion and renamed --- src/games/nehrim/.gitignore | 5 + src/games/nehrim/CMakeLists.txt | 12 ++ src/games/nehrim/appveyor.yml | 40 ++++ src/games/nehrim/src/CMakeLists.txt | 7 + src/games/nehrim/src/SConscript | 13 ++ src/games/nehrim/src/gameNehrim.pro | 50 +++++ src/games/nehrim/src/game_nehrim_en.ts | 17 ++ src/games/nehrim/src/gamenehrim.h | 52 +++++ src/games/nehrim/src/gamenehrim.json | 1 + src/games/nehrim/src/gamenhrim.cpp | 179 ++++++++++++++++++ .../nehrim/src/nehrimbsainvalidation.cpp | 17 ++ src/games/nehrim/src/nehrimbsainvalidation.h | 23 +++ src/games/nehrim/src/nehrimdataarchives.cpp | 36 ++++ src/games/nehrim/src/nehrimdataarchives.h | 28 +++ src/games/nehrim/src/nehrimmoddatachecker.cpp | 30 +++ src/games/nehrim/src/nehrimmoddatachecker.h | 32 ++++ src/games/nehrim/src/nehrimmoddatacontent.h | 21 ++ src/games/nehrim/src/nehrimsavegame.cpp | 73 +++++++ src/games/nehrim/src/nehrimsavegame.h | 25 +++ src/games/nehrim/src/nehrimscriptextender.cpp | 23 +++ src/games/nehrim/src/nehrimscriptextender.h | 19 ++ 21 files changed, 703 insertions(+) create mode 100644 src/games/nehrim/.gitignore create mode 100644 src/games/nehrim/CMakeLists.txt create mode 100644 src/games/nehrim/appveyor.yml create mode 100644 src/games/nehrim/src/CMakeLists.txt create mode 100644 src/games/nehrim/src/SConscript create mode 100644 src/games/nehrim/src/gameNehrim.pro create mode 100644 src/games/nehrim/src/game_nehrim_en.ts create mode 100644 src/games/nehrim/src/gamenehrim.h create mode 100644 src/games/nehrim/src/gamenehrim.json create mode 100644 src/games/nehrim/src/gamenhrim.cpp create mode 100644 src/games/nehrim/src/nehrimbsainvalidation.cpp create mode 100644 src/games/nehrim/src/nehrimbsainvalidation.h create mode 100644 src/games/nehrim/src/nehrimdataarchives.cpp create mode 100644 src/games/nehrim/src/nehrimdataarchives.h create mode 100644 src/games/nehrim/src/nehrimmoddatachecker.cpp create mode 100644 src/games/nehrim/src/nehrimmoddatachecker.h create mode 100644 src/games/nehrim/src/nehrimmoddatacontent.h create mode 100644 src/games/nehrim/src/nehrimsavegame.cpp create mode 100644 src/games/nehrim/src/nehrimsavegame.h create mode 100644 src/games/nehrim/src/nehrimscriptextender.cpp create mode 100644 src/games/nehrim/src/nehrimscriptextender.h diff --git a/src/games/nehrim/.gitignore b/src/games/nehrim/.gitignore new file mode 100644 index 00000000..cf71be77 --- /dev/null +++ b/src/games/nehrim/.gitignore @@ -0,0 +1,5 @@ +edit +CMakeLists.txt.user +/msbuild.log +/*std*.log +/*build diff --git a/src/games/nehrim/CMakeLists.txt b/src/games/nehrim/CMakeLists.txt new file mode 100644 index 00000000..c9691dc0 --- /dev/null +++ b/src/games/nehrim/CMakeLists.txt @@ -0,0 +1,12 @@ +cmake_minimum_required(VERSION 3.16) + +project(game_oblivion) +set(project_type plugin) +set(enable_warnings OFF) + +if(DEFINED DEPENDENCIES_DIR) + include(${DEPENDENCIES_DIR}/modorganizer_super/cmake_common/project.cmake) +else() + include(../cmake_common/project.cmake) +endif() +add_subdirectory(src) diff --git a/src/games/nehrim/appveyor.yml b/src/games/nehrim/appveyor.yml new file mode 100644 index 00000000..998a5f8b --- /dev/null +++ b/src/games/nehrim/appveyor.yml @@ -0,0 +1,40 @@ +version: 1.0.{build} +skip_branch_with_pr: true +image: Visual Studio 2019 +environment: + WEBHOOK_URL: + secure: gOKbXaZM9ImtMD5XrYITvdyZUW/az082G9OIN1EC1Vbg57wBaeLhi49uGjxPw5GVujHku6kxN6ab89zhbS5GVeluR76GM83IbKV4Sh7udXzoYZZdg6YudtYHzdhCgUeiedpswbuczTq9ceIkkfSEWZuh/lMAAVVwvcGsJAnoPFw= +build_script: +- pwsh: >- + $ErrorActionPreference = 'Stop' + + git clone --depth=1 --no-single-branch https://github.com/ModOrganizer2/modorganizer-umbrella.git c:\projects\modorganizer-umbrella + + New-Item -ItemType Directory -Path c:\projects\modorganizer-build + + cd c:\projects\modorganizer-umbrella + + ($env:APPVEYOR_PULL_REQUEST_HEAD_REPO_BRANCH -eq $null) ? ($branch = $env:APPVEYOR_REPO_BRANCH) : ($branch = $env:APPVEYOR_PULL_REQUEST_HEAD_REPO_BRANCH) + + git checkout $(git show-ref --verify --quiet refs/remotes/origin/${branch} || echo '-b') ${branch} + + C:\Python37-x64\python.exe unimake.py -d c:\projects\modorganizer-build -s Appveyor_Build=True ${env:APPVEYOR_PROJECT_NAME} + + if($LastExitCode -ne 0) { $host.SetShouldExit($LastExitCode ) } +artifacts: +- path: vsbuild\src\RelWithDebInfo\game_oblivion.dll + name: game_oblivion_dll +- path: vsbuild\src\RelWithDebInfo\game_oblivion.pdb + name: game_oblivion_pdb +- path: vsbuild\src\RelWithDebInfo\game_oblivion.lib + name: game_oblivion_lib +on_success: + - ps: Set-Location -Path $env:APPVEYOR_BUILD_FOLDER + - ps: Invoke-RestMethod https://raw.githubusercontent.com/DiscordHooks/appveyor-discord-webhook/master/send.ps1 -o send.ps1 + - ps: ./send.ps1 success $env:WEBHOOK_URL +on_failure: + - ps: Set-Location -Path $env:APPVEYOR_BUILD_FOLDER + - ps: Push-AppveyorArtifact ${env:APPVEYOR_BUILD_FOLDER}\stdout.log + - ps: Push-AppveyorArtifact ${env:APPVEYOR_BUILD_FOLDER}\stderr.log + - ps: Invoke-RestMethod https://raw.githubusercontent.com/DiscordHooks/appveyor-discord-webhook/master/send.ps1 -o send.ps1 + - ps: ./send.ps1 failure $env:WEBHOOK_URL \ No newline at end of file diff --git a/src/games/nehrim/src/CMakeLists.txt b/src/games/nehrim/src/CMakeLists.txt new file mode 100644 index 00000000..1f12c529 --- /dev/null +++ b/src/games/nehrim/src/CMakeLists.txt @@ -0,0 +1,7 @@ +cmake_minimum_required(VERSION 3.16) +if(DEFINED DEPENDENCIES_DIR) + include(${DEPENDENCIES_DIR}/modorganizer_super/cmake_common/src.cmake) +else() + include(../../cmake_common/src.cmake) +endif() +requires_project(game_gamebryo game_features) diff --git a/src/games/nehrim/src/SConscript b/src/games/nehrim/src/SConscript new file mode 100644 index 00000000..8704fc23 --- /dev/null +++ b/src/games/nehrim/src/SConscript @@ -0,0 +1,13 @@ +Import('qt_env') + +env = qt_env.Clone() + +env.AppendUnique(CPPDEFINES = [ 'GAMEOBLIVION_LIBRARY' ]) + +env.RequiresGamebryo() + +lib = env.SharedLibrary('gameOblivion', env.Glob('*.cpp')) +env.InstallModule(lib) + +res = env['QT_USED_MODULES'] +Return('res') diff --git a/src/games/nehrim/src/gameNehrim.pro b/src/games/nehrim/src/gameNehrim.pro new file mode 100644 index 00000000..cab63216 --- /dev/null +++ b/src/games/nehrim/src/gameNehrim.pro @@ -0,0 +1,50 @@ +#------------------------------------------------- +# +# Project created by QtCreator 2014-11-15T15:36:33 +# +#------------------------------------------------- + + +TARGET = gameOblivion +TEMPLATE = lib + +CONFIG += plugins +CONFIG += dll + +DEFINES += GAMEOBLIVION_LIBRARY + +SOURCES += gameoblivion.cpp \ + oblivionbsainvalidation.cpp \ + oblivionscriptextender.cpp \ + obliviondataarchives.cpp \ + oblivionsavegame.cpp \ + oblivionsavegameinfo.cpp + +HEADERS += gameoblivion.h \ + oblivionbsainvalidation.h \ + oblivionscriptextender.h \ + obliviondataarchives.h \ + oblivionsavegame.h \ + oblivionsavegameinfo.h + +CONFIG(debug, debug|release) { + LIBS += -L"$${OUT_PWD}/../gameGamebryo/debug" + PRE_TARGETDEPS += \ + $$OUT_PWD/../gameGamebryo/debug/gameGamebryo.lib +} else { + LIBS += -L"$${OUT_PWD}/../gameGamebryo/release" + PRE_TARGETDEPS += \ + $$OUT_PWD/../gameGamebryo/release/gameGamebryo.lib +} + +include(../plugin_template.pri) + +INCLUDEPATH += "$${BOOSTPATH}" "$${PWD}/../gamefeatures" "$${PWD}/../gamegamebryo" + +LIBS += -ladvapi32 -lole32 -lgameGamebryo + +OTHER_FILES += \ + gameoblivion.json\ + SConscript \ + CMakeLists.txt + diff --git a/src/games/nehrim/src/game_nehrim_en.ts b/src/games/nehrim/src/game_nehrim_en.ts new file mode 100644 index 00000000..ad614a85 --- /dev/null +++ b/src/games/nehrim/src/game_nehrim_en.ts @@ -0,0 +1,17 @@ + + + + + GameOblivion + + + Oblivion Support Plugin + + + + + Adds support for the game Oblivion + + + + diff --git a/src/games/nehrim/src/gamenehrim.h b/src/games/nehrim/src/gamenehrim.h new file mode 100644 index 00000000..9ff6b259 --- /dev/null +++ b/src/games/nehrim/src/gamenehrim.h @@ -0,0 +1,52 @@ +#ifndef GAMEOBLIVION_H +#define GAMEOBLIVION_H + +#include "gamegamebryo.h" + +#include +#include + +class GameOblivion : public GameGamebryo +{ + Q_OBJECT + Q_PLUGIN_METADATA(IID "org.tannin.GameOblivion" FILE "gameoblivion.json") + +public: + + GameOblivion(); + + virtual bool init(MOBase::IOrganizer *moInfo) override; + +public: // IPluginGame interface + + virtual QString gameName() const override; + virtual QList executables() const override; + virtual QList executableForcedLoads() const override; + virtual void initializeProfile(const QDir &path, ProfileSettings settings) const override; + virtual QString steamAPPId() const override; + virtual QStringList primaryPlugins() const override; + virtual QString gameShortName() 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; + +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 settings() const override; + +protected: + + std::shared_ptr makeSaveGame(QString filePath) const override; + QString savegameExtension() const override; + QString savegameSEExtension() const override; + +}; + +#endif // GAMEOBLIVION_H diff --git a/src/games/nehrim/src/gamenehrim.json b/src/games/nehrim/src/gamenehrim.json new file mode 100644 index 00000000..0967ef42 --- /dev/null +++ b/src/games/nehrim/src/gamenehrim.json @@ -0,0 +1 @@ +{} diff --git a/src/games/nehrim/src/gamenhrim.cpp b/src/games/nehrim/src/gamenhrim.cpp new file mode 100644 index 00000000..81b21711 --- /dev/null +++ b/src/games/nehrim/src/gamenhrim.cpp @@ -0,0 +1,179 @@ +#include "gameoblivion.h" + +#include "oblivionbsainvalidation.h" +#include "obliviondataarchives.h" +#include "oblivionscriptextender.h" +#include "oblivionmoddatachecker.h" +#include "oblivionmoddatacontent.h" +#include "oblivionsavegame.h" + +#include "pluginsetting.h" +#include "executableinfo.h" +#include +#include +#include +#include + +#include +#include +#include + +#include + +using namespace MOBase; + +GameOblivion::GameOblivion() +{ +} + +bool GameOblivion::init(IOrganizer *moInfo) +{ + if (!GameGamebryo::init(moInfo)) { + return false; + } + registerFeature(new OblivionScriptExtender(this)); + registerFeature(new OblivionDataArchives(myGamesPath())); + registerFeature(new OblivionBSAInvalidation(feature(), this)); + registerFeature(new GamebryoSaveGameInfo(this)); + registerFeature(new GamebryoLocalSavegames(myGamesPath(), "oblivion.ini")); + registerFeature(new OblivionModDataChecker(this)); + registerFeature(new OblivionModDataContent(this)); + registerFeature(new GamebryoGamePlugins(moInfo)); + registerFeature(new GamebryoUnmangedMods(this)); + return true; +} + +QString GameOblivion::gameName() const +{ + return "Oblivion"; +} + +QList GameOblivion::executables() const +{ + return QList() + << ExecutableInfo("OBSE", findInGameFolder(feature()->loaderName())) + << ExecutableInfo("Oblivion", findInGameFolder(binaryName())) + << ExecutableInfo("Oblivion Launcher", findInGameFolder(getLauncherName())) + << ExecutableInfo("Oblivion Mod Manager", findInGameFolder("OblivionModManager.exe")) + << ExecutableInfo("BOSS", findInGameFolder("BOSS/BOSS.exe")) + << ExecutableInfo("LOOT", getLootPath()).withArgument("--game=\"Oblivion\"") + << ExecutableInfo("Construction Set", findInGameFolder("TESConstructionSet.exe")) + ; +} + +QList GameOblivion::executableForcedLoads() const +{ + //TODO Search game directory for OBSE DLLs + return QList() + << ExecutableForcedLoadSetting("Oblivion.exe", "obse_1_2_416.dll").withForced() + << ExecutableForcedLoadSetting("TESConstructionSet.exe", "obse_editor_1_2.dll").withForced() + ; +} + +QString GameOblivion::name() const +{ + return "Oblivion Support Plugin"; +} + +QString GameOblivion::localizedName() const +{ + return tr("Oblivion Support Plugin"); +} + +QString GameOblivion::author() const +{ + return "Tannin"; +} + +QString GameOblivion::description() const +{ + return tr("Adds support for the game Oblivion"); +} + +MOBase::VersionInfo GameOblivion::version() const +{ + return VersionInfo(1, 4, 1, VersionInfo::RELEASE_FINAL); +} + +QList GameOblivion::settings() const +{ + return QList(); +} + +void GameOblivion::initializeProfile(const QDir &path, ProfileSettings settings) const +{ + if (settings.testFlag(IPluginGame::MODS)) { + copyToProfile(localAppFolder() + "/Oblivion", path, "plugins.txt"); + copyToProfile(localAppFolder() + "/Oblivion", path, "loadorder.txt"); + } + + if (settings.testFlag(IPluginGame::CONFIGURATION)) { + if (settings.testFlag(IPluginGame::PREFER_DEFAULTS) + || !QFileInfo(myGamesPath() + "/oblivion.ini").exists()) { + copyToProfile(gameDirectory().absolutePath(), path, "oblivion_default.ini", "oblivion.ini"); + } else { + copyToProfile(myGamesPath(), path, "oblivion.ini"); + } + + copyToProfile(myGamesPath(), path, "oblivionprefs.ini"); + } +} + +QString GameOblivion::savegameExtension() const +{ + return "ess"; +} + +QString GameOblivion::savegameSEExtension() const +{ + return "obse"; +} + +std::shared_ptr GameOblivion::makeSaveGame(QString filePath) const +{ + return std::make_shared(filePath, this); +} + +QString GameOblivion::steamAPPId() const +{ + return "22330"; +} + +QStringList GameOblivion::primaryPlugins() const +{ + return { "oblivion.esm", "update.esm" }; +} + +QString GameOblivion::gameShortName() const +{ + return "Oblivion"; +} + +QString GameOblivion::gameNexusName() const +{ + return "Oblivion"; +} + + +QStringList GameOblivion::iniFiles() const +{ + return { "oblivion.ini", "oblivionprefs.ini" }; +} + +QStringList GameOblivion::DLCPlugins() const +{ + return { "DLCBattlehornCastle.esp", "DLCShiveringIsles.esp", "Knights.esp", "DLCFrostcrag.esp", + "DLCSpellTomes.esp", "DLCMehrunesRazor.esp", "DLCOrrery.esp", + "DLCThievesDen.esp", "DLCVileLair.esp", "DLCHorseArmor.esp" }; +} + + +int GameOblivion::nexusModOrganizerID() const +{ + return 38277; +} + +int GameOblivion::nexusGameID() const +{ + return 101; +} diff --git a/src/games/nehrim/src/nehrimbsainvalidation.cpp b/src/games/nehrim/src/nehrimbsainvalidation.cpp new file mode 100644 index 00000000..6426af0b --- /dev/null +++ b/src/games/nehrim/src/nehrimbsainvalidation.cpp @@ -0,0 +1,17 @@ +#include "oblivionbsainvalidation.h" + + +OblivionBSAInvalidation::OblivionBSAInvalidation(DataArchives *dataArchives, MOBase::IPluginGame const *game) + : GamebryoBSAInvalidation(dataArchives, "oblivion.ini", game) +{ +} + +QString OblivionBSAInvalidation::invalidationBSAName() const +{ + return "Oblivion - Invalidation.bsa"; +} + +unsigned long OblivionBSAInvalidation::bsaVersion() const +{ + return 0x67; +} diff --git a/src/games/nehrim/src/nehrimbsainvalidation.h b/src/games/nehrim/src/nehrimbsainvalidation.h new file mode 100644 index 00000000..8884517d --- /dev/null +++ b/src/games/nehrim/src/nehrimbsainvalidation.h @@ -0,0 +1,23 @@ +#ifndef OBLIVIONBSAINVALIDATION_H +#define OBLIVIONBSAINVALIDATION_H + + +#include "gamebryobsainvalidation.h" +#include "obliviondataarchives.h" + +#include + +class OblivionBSAInvalidation : public GamebryoBSAInvalidation +{ +public: + + OblivionBSAInvalidation(DataArchives *dataArchives, MOBase::IPluginGame const *game); + +private: + + virtual QString invalidationBSAName() const override; + virtual unsigned long bsaVersion() const override; + +}; + +#endif // OBLIVIONBSAINVALIDATION_H diff --git a/src/games/nehrim/src/nehrimdataarchives.cpp b/src/games/nehrim/src/nehrimdataarchives.cpp new file mode 100644 index 00000000..0d281eeb --- /dev/null +++ b/src/games/nehrim/src/nehrimdataarchives.cpp @@ -0,0 +1,36 @@ +#include "obliviondataarchives.h" +#include + +OblivionDataArchives::OblivionDataArchives(const QDir &myGamesDir) : + GamebryoDataArchives(myGamesDir) +{ +} + +QStringList OblivionDataArchives::vanillaArchives() const +{ + return { "Oblivion - Misc.bsa" + , "Oblivion - Textures - Compressed.bsa" + , "Oblivion - Meshes.bsa" + , "Oblivion - Sounds.bsa" + , "Oblivion - Voices1.bsa" + , "Oblivion - Voices2.bsa" + }; +} + +QStringList OblivionDataArchives::archives(const MOBase::IProfile *profile) const +{ + QStringList result; + + QString iniFile = profile->localSettingsEnabled() ? QDir(profile->absolutePath()).absoluteFilePath("oblivion.ini") : m_LocalGameDir.absoluteFilePath("oblivion.ini"); + result.append(getArchivesFromKey(iniFile, "SArchiveList")); + + return result; +} + +void OblivionDataArchives::writeArchiveList(MOBase::IProfile *profile, const QStringList &before) +{ + QString list = before.join(", "); + + QString iniFile = profile->localSettingsEnabled() ? QDir(profile->absolutePath()).absoluteFilePath("oblivion.ini") : m_LocalGameDir.absoluteFilePath("oblivion.ini"); + setArchivesToKey(iniFile, "SArchiveList", list); +} diff --git a/src/games/nehrim/src/nehrimdataarchives.h b/src/games/nehrim/src/nehrimdataarchives.h new file mode 100644 index 00000000..f1e9f0e2 --- /dev/null +++ b/src/games/nehrim/src/nehrimdataarchives.h @@ -0,0 +1,28 @@ +#ifndef OBLIVIONDATAARCHIVES_H +#define OBLIVIONDATAARCHIVES_H + + +#include +#include +#include +#include +#include + +class OblivionDataArchives : public GamebryoDataArchives +{ + +public: + OblivionDataArchives(const QDir &myGamesDir); + +public: + + 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 // OBLIVIONDATAARCHIVES_H diff --git a/src/games/nehrim/src/nehrimmoddatachecker.cpp b/src/games/nehrim/src/nehrimmoddatachecker.cpp new file mode 100644 index 00000000..0cc3546c --- /dev/null +++ b/src/games/nehrim/src/nehrimmoddatachecker.cpp @@ -0,0 +1,30 @@ +#include "oblivionmoddatachecker.h" + +ModDataChecker::CheckReturn OblivionModDataChecker::dataLooksValid( + std::shared_ptr fileTree) const +{ + // Check with Gamebryo stuff: + auto check = GamebryoModDataChecker::dataLooksValid(fileTree); + if (check == CheckReturn::VALID) { + return check; + } + + // Check for OBSE_ files: + for (auto const& entry : *fileTree) { + if (entry->isDir() || !entry->name().startsWith("OBSE", Qt::CaseInsensitive)) { + return CheckReturn::INVALID; + } + } + + return CheckReturn::FIXABLE; +} + +std::shared_ptr OblivionModDataChecker::fix( + std::shared_ptr fileTree) const +{ + // If we arrive here, it means all files starts with OBSE. + auto data = fileTree->createOrphanTree(); + auto obse = data->addDirectory("OBSE/Plugins"); + obse->merge(fileTree); + return data; +} \ No newline at end of file diff --git a/src/games/nehrim/src/nehrimmoddatachecker.h b/src/games/nehrim/src/nehrimmoddatachecker.h new file mode 100644 index 00000000..5159dc09 --- /dev/null +++ b/src/games/nehrim/src/nehrimmoddatachecker.h @@ -0,0 +1,32 @@ +#ifndef OBLIVION_MODATACHECKER_H +#define OBLIVION_MODATACHECKER_H + +#include + +class OblivionModDataChecker : public GamebryoModDataChecker +{ +public: + using GamebryoModDataChecker::GamebryoModDataChecker; + + CheckReturn dataLooksValid(std::shared_ptr fileTree) const override; + std::shared_ptr fix(std::shared_ptr fileTree) const override; + +protected: + virtual const FileNameSet& possibleFolderNames() const override { + static FileNameSet result{ + "fonts", "interface", "menus", "meshes", "music", "scripts", "shaders", + "sound", "strings", "textures", "trees", "video", "facegen", + "obse", "distantlod", "asi", "distantland", "mits", "dllplugins", "CalienteTools", + "NetScriptFramework" + }; + return result; + } + virtual const FileNameSet& possibleFileExtensions() const override { + static FileNameSet result{ + "esp", "esm", "bsa", "modgroups", "ini" + }; + return result; + } +}; + +#endif // OBLIVION_MODATACHECKER_H diff --git a/src/games/nehrim/src/nehrimmoddatacontent.h b/src/games/nehrim/src/nehrimmoddatacontent.h new file mode 100644 index 00000000..2e79a87f --- /dev/null +++ b/src/games/nehrim/src/nehrimmoddatacontent.h @@ -0,0 +1,21 @@ +#ifndef OBLIVION_MODDATACONTENT_H +#define OBLIVION_MODDATACONTENT_H + +#include +#include + +class OblivionModDataContent : public GamebryoModDataContent { +public: + + /** + * + */ + OblivionModDataContent(GameGamebryo const* gamePlugin) : GamebryoModDataContent(gamePlugin) { + // Just need to disable some contents: + m_Enabled[CONTENT_MCM] = false; + m_Enabled[CONTENT_SKYPROC] = false; + } + +}; + +#endif // OBLIVION_MODDATACONTENT_H diff --git a/src/games/nehrim/src/nehrimsavegame.cpp b/src/games/nehrim/src/nehrimsavegame.cpp new file mode 100644 index 00000000..52089e86 --- /dev/null +++ b/src/games/nehrim/src/nehrimsavegame.cpp @@ -0,0 +1,73 @@ +#include "oblivionsavegame.h" + +#include + +OblivionSaveGame::OblivionSaveGame(QString const &fileName, GameOblivion const *game) : + GamebryoSaveGame(fileName, game) +{ + FileWrapper file(getFilepath(), "TES4SAVEGAME"); + file.setPluginString(GamebryoSaveGame::StringType::TYPE_BSTRING); + + SYSTEMTIME creationTime; + fetchInformationFields(file, m_SaveNumber, m_PCName, m_PCLevel, m_PCLocation, creationTime); + setCreationTime(creationTime); +} + +void OblivionSaveGame::fetchInformationFields(FileWrapper& file, + unsigned long& saveNumber, + QString& playerName, + unsigned short& playerLevel, + QString& playerLocation, + SYSTEMTIME& creationTime) const +{ + file.skip(); //Major version + file.skip(); //Minor version + + file.skip(); // exe last modified (!) + + file.skip(); //Header version + file.skip(); //Header size + + file.read(saveNumber); + + file.read(playerName); + file.read(playerLevel); + file.read(playerLocation); + + file.skip(); //game days + file.skip(); //game ticks + + //there is a save time stored here. So use it rather than the file time, which + //could have been copied. + //Note: This says it uses getlocaltime api to obtain it which is u/s - if so + //we should ignore this. + file.read(creationTime); +} + +std::unique_ptr OblivionSaveGame::fetchDataFields() const +{ + FileWrapper file(getFilepath(), "TES4SAVEGAME"); + file.setPluginString(GamebryoSaveGame::StringType::TYPE_BSTRING); + + std::unique_ptr fields = std::make_unique(); + + { + QString dummyName, dummyLocation; + unsigned short dummyLevel; + unsigned long dummySaveNumber; + SYSTEMTIME dummyTime; + + fetchInformationFields(file, dummySaveNumber, dummyName, dummyLevel, + dummyLocation, dummyTime); + } + + //Note that screenshot size, width, height and data are apparently the same + //structure + file.skip(); //Screenshot size. + + fields->Screenshot = file.readImage(); + + fields->Plugins = file.readPlugins(); + + return fields; +} diff --git a/src/games/nehrim/src/nehrimsavegame.h b/src/games/nehrim/src/nehrimsavegame.h new file mode 100644 index 00000000..0c9de37d --- /dev/null +++ b/src/games/nehrim/src/nehrimsavegame.h @@ -0,0 +1,25 @@ +#ifndef OBLIVIONSAVEGAME_H +#define OBLIVIONSAVEGAME_H + +#include "gamebryosavegame.h" +#include "gameoblivion.h" + +class OblivionSaveGame : public GamebryoSaveGame +{ +public: + OblivionSaveGame(QString const &fileName, GameOblivion const *game); + +protected: + + // Fetch easy-to-access information. + void fetchInformationFields(FileWrapper& wrapper, + unsigned long& saveNumber, + QString& playerName, + unsigned short& playerLevel, + QString& playerLocation, + SYSTEMTIME& creationTime) const; + + std::unique_ptr fetchDataFields() const override; +}; + +#endif // OBLIVIONSAVEGAME_H diff --git a/src/games/nehrim/src/nehrimscriptextender.cpp b/src/games/nehrim/src/nehrimscriptextender.cpp new file mode 100644 index 00000000..defe9de9 --- /dev/null +++ b/src/games/nehrim/src/nehrimscriptextender.cpp @@ -0,0 +1,23 @@ +#include "oblivionscriptextender.h" + +#include +#include + +OblivionScriptExtender::OblivionScriptExtender(GameGamebryo const *game) : + GamebryoScriptExtender(game) +{ +} + +OblivionScriptExtender::~OblivionScriptExtender() +{ +} + +QString OblivionScriptExtender::BinaryName() const +{ + return "obse_loader.exe"; +} + +QString OblivionScriptExtender::PluginPath() const +{ + return "obse/plugins"; +} diff --git a/src/games/nehrim/src/nehrimscriptextender.h b/src/games/nehrim/src/nehrimscriptextender.h new file mode 100644 index 00000000..28e99035 --- /dev/null +++ b/src/games/nehrim/src/nehrimscriptextender.h @@ -0,0 +1,19 @@ +#ifndef OBLIVIONSCRIPTEXTENDER_H +#define OBLIVIONSCRIPTEXTENDER_H + +#include "gamebryoscriptextender.h" + +class GameGamebryo; + +class OblivionScriptExtender : public GamebryoScriptExtender +{ +public: + OblivionScriptExtender(const GameGamebryo *game); + ~OblivionScriptExtender(); + + virtual QString BinaryName() const override; + virtual QString PluginPath() const override; + +}; + +#endif // OBLIVIONSCRIPTEXTENDER_H From b898a82c2dd84388657fe232e3685e3cf25a3cc5 Mon Sep 17 00:00:00 2001 From: Chris Bessent Date: Sun, 22 Aug 2021 09:18:12 -0700 Subject: [PATCH 1168/1544] [game_nehrim] Renames and update info --- src/games/nehrim/CMakeLists.txt | 2 +- src/games/nehrim/appveyor.yml | 18 +-- src/games/nehrim/src/SConscript | 4 +- src/games/nehrim/src/gameNehrim.pro | 31 +++-- src/games/nehrim/src/game_nehrim_en.ts | 10 +- src/games/nehrim/src/gamenehrim.h | 12 +- src/games/nehrim/src/gamenhrim.cpp | 107 +++++++++--------- .../nehrim/src/nehrimbsainvalidation.cpp | 10 +- src/games/nehrim/src/nehrimbsainvalidation.h | 12 +- src/games/nehrim/src/nehrimdataarchives.cpp | 23 ++-- src/games/nehrim/src/nehrimdataarchives.h | 10 +- src/games/nehrim/src/nehrimmoddatachecker.cpp | 8 +- src/games/nehrim/src/nehrimmoddatachecker.h | 10 +- src/games/nehrim/src/nehrimmoddatacontent.h | 10 +- src/games/nehrim/src/nehrimsavegame.cpp | 8 +- src/games/nehrim/src/nehrimsavegame.h | 12 +- src/games/nehrim/src/nehrimscriptextender.cpp | 10 +- src/games/nehrim/src/nehrimscriptextender.h | 12 +- 18 files changed, 153 insertions(+), 156 deletions(-) diff --git a/src/games/nehrim/CMakeLists.txt b/src/games/nehrim/CMakeLists.txt index c9691dc0..83884282 100644 --- a/src/games/nehrim/CMakeLists.txt +++ b/src/games/nehrim/CMakeLists.txt @@ -1,6 +1,6 @@ cmake_minimum_required(VERSION 3.16) -project(game_oblivion) +project(game_nehrim) set(project_type plugin) set(enable_warnings OFF) diff --git a/src/games/nehrim/appveyor.yml b/src/games/nehrim/appveyor.yml index 998a5f8b..f9e8186a 100644 --- a/src/games/nehrim/appveyor.yml +++ b/src/games/nehrim/appveyor.yml @@ -13,21 +13,21 @@ build_script: New-Item -ItemType Directory -Path c:\projects\modorganizer-build cd c:\projects\modorganizer-umbrella - + ($env:APPVEYOR_PULL_REQUEST_HEAD_REPO_BRANCH -eq $null) ? ($branch = $env:APPVEYOR_REPO_BRANCH) : ($branch = $env:APPVEYOR_PULL_REQUEST_HEAD_REPO_BRANCH) git checkout $(git show-ref --verify --quiet refs/remotes/origin/${branch} || echo '-b') ${branch} C:\Python37-x64\python.exe unimake.py -d c:\projects\modorganizer-build -s Appveyor_Build=True ${env:APPVEYOR_PROJECT_NAME} - + if($LastExitCode -ne 0) { $host.SetShouldExit($LastExitCode ) } artifacts: -- path: vsbuild\src\RelWithDebInfo\game_oblivion.dll - name: game_oblivion_dll -- path: vsbuild\src\RelWithDebInfo\game_oblivion.pdb - name: game_oblivion_pdb -- path: vsbuild\src\RelWithDebInfo\game_oblivion.lib - name: game_oblivion_lib +- path: vsbuild\src\RelWithDebInfo\game_nehrim.dll + name: game_nehrim_dll +- path: vsbuild\src\RelWithDebInfo\game_nehrim.pdb + name: game_nehrim_pdb +- path: vsbuild\src\RelWithDebInfo\game_nehrim.lib + name: game_nehrim_lib on_success: - ps: Set-Location -Path $env:APPVEYOR_BUILD_FOLDER - ps: Invoke-RestMethod https://raw.githubusercontent.com/DiscordHooks/appveyor-discord-webhook/master/send.ps1 -o send.ps1 @@ -37,4 +37,4 @@ on_failure: - ps: Push-AppveyorArtifact ${env:APPVEYOR_BUILD_FOLDER}\stdout.log - ps: Push-AppveyorArtifact ${env:APPVEYOR_BUILD_FOLDER}\stderr.log - ps: Invoke-RestMethod https://raw.githubusercontent.com/DiscordHooks/appveyor-discord-webhook/master/send.ps1 -o send.ps1 - - ps: ./send.ps1 failure $env:WEBHOOK_URL \ No newline at end of file + - ps: ./send.ps1 failure $env:WEBHOOK_URL diff --git a/src/games/nehrim/src/SConscript b/src/games/nehrim/src/SConscript index 8704fc23..7abd3a4f 100644 --- a/src/games/nehrim/src/SConscript +++ b/src/games/nehrim/src/SConscript @@ -2,11 +2,11 @@ Import('qt_env') env = qt_env.Clone() -env.AppendUnique(CPPDEFINES = [ 'GAMEOBLIVION_LIBRARY' ]) +env.AppendUnique(CPPDEFINES = [ 'GAMENEHRIM_LIBRARY' ]) env.RequiresGamebryo() -lib = env.SharedLibrary('gameOblivion', env.Glob('*.cpp')) +lib = env.SharedLibrary('gameNehrim', env.Glob('*.cpp')) env.InstallModule(lib) res = env['QT_USED_MODULES'] diff --git a/src/games/nehrim/src/gameNehrim.pro b/src/games/nehrim/src/gameNehrim.pro index cab63216..e3fa2468 100644 --- a/src/games/nehrim/src/gameNehrim.pro +++ b/src/games/nehrim/src/gameNehrim.pro @@ -5,27 +5,27 @@ #------------------------------------------------- -TARGET = gameOblivion +TARGET = gameNehrim TEMPLATE = lib CONFIG += plugins CONFIG += dll -DEFINES += GAMEOBLIVION_LIBRARY +DEFINES += GAMENEHRIM_LIBRARY -SOURCES += gameoblivion.cpp \ - oblivionbsainvalidation.cpp \ - oblivionscriptextender.cpp \ - obliviondataarchives.cpp \ - oblivionsavegame.cpp \ - oblivionsavegameinfo.cpp +SOURCES += gamenehrim.cpp \ + nehrimbsainvalidation.cpp \ + nehrimscriptextender.cpp \ + nehrimdataarchives.cpp \ + nehrimsavegame.cpp \ + nehrimsavegameinfo.cpp -HEADERS += gameoblivion.h \ - oblivionbsainvalidation.h \ - oblivionscriptextender.h \ - obliviondataarchives.h \ - oblivionsavegame.h \ - oblivionsavegameinfo.h +HEADERS += gamenehrim.h \ + nehrimbsainvalidation.h \ + nehrimscriptextender.h \ + nehrimdataarchives.h \ + nehrimsavegame.h \ + nehrimsavegameinfo.h CONFIG(debug, debug|release) { LIBS += -L"$${OUT_PWD}/../gameGamebryo/debug" @@ -44,7 +44,6 @@ INCLUDEPATH += "$${BOOSTPATH}" "$${PWD}/../gamefeatures" "$${PWD}/../gamegamebry LIBS += -ladvapi32 -lole32 -lgameGamebryo OTHER_FILES += \ - gameoblivion.json\ + gamenehrim.json\ SConscript \ CMakeLists.txt - diff --git a/src/games/nehrim/src/game_nehrim_en.ts b/src/games/nehrim/src/game_nehrim_en.ts index ad614a85..fee5da54 100644 --- a/src/games/nehrim/src/game_nehrim_en.ts +++ b/src/games/nehrim/src/game_nehrim_en.ts @@ -2,15 +2,15 @@ - GameOblivion + GameNehrim - - Oblivion Support Plugin + + Nehrim Support Plugin - - Adds support for the game Oblivion + + Adds support for the game Nehrim diff --git a/src/games/nehrim/src/gamenehrim.h b/src/games/nehrim/src/gamenehrim.h index 9ff6b259..3a5142c9 100644 --- a/src/games/nehrim/src/gamenehrim.h +++ b/src/games/nehrim/src/gamenehrim.h @@ -1,19 +1,19 @@ -#ifndef GAMEOBLIVION_H -#define GAMEOBLIVION_H +#ifndef GAMENEHRIM_H +#define GAMENEHRIM_H #include "gamegamebryo.h" #include #include -class GameOblivion : public GameGamebryo +class GameNehrim : public GameGamebryo { Q_OBJECT - Q_PLUGIN_METADATA(IID "org.tannin.GameOblivion" FILE "gameoblivion.json") + Q_PLUGIN_METADATA(IID "org.tannin.GameNehrim" FILE "gamenehrim.json") public: - GameOblivion(); + GameNehrim(); virtual bool init(MOBase::IOrganizer *moInfo) override; @@ -49,4 +49,4 @@ protected: }; -#endif // GAMEOBLIVION_H +#endif // GAMENEHRIM_H diff --git a/src/games/nehrim/src/gamenhrim.cpp b/src/games/nehrim/src/gamenhrim.cpp index 81b21711..77f75a9c 100644 --- a/src/games/nehrim/src/gamenhrim.cpp +++ b/src/games/nehrim/src/gamenhrim.cpp @@ -1,11 +1,11 @@ -#include "gameoblivion.h" +#include "gamenehrim.h" -#include "oblivionbsainvalidation.h" -#include "obliviondataarchives.h" -#include "oblivionscriptextender.h" -#include "oblivionmoddatachecker.h" -#include "oblivionmoddatacontent.h" -#include "oblivionsavegame.h" +#include "nehrimbsainvalidation.h" +#include "nehrimdataarchives.h" +#include "nehrimscriptextender.h" +#include "nehrimmoddatachecker.h" +#include "nehrimmoddatacontent.h" +#include "nehrimsavegame.h" #include "pluginsetting.h" #include "executableinfo.h" @@ -22,38 +22,37 @@ using namespace MOBase; -GameOblivion::GameOblivion() +GameNehrim::GameNehrim() { } -bool GameOblivion::init(IOrganizer *moInfo) +bool GameNehrim::init(IOrganizer *moInfo) { if (!GameGamebryo::init(moInfo)) { return false; } - registerFeature(new OblivionScriptExtender(this)); - registerFeature(new OblivionDataArchives(myGamesPath())); - registerFeature(new OblivionBSAInvalidation(feature(), this)); + registerFeature(new NehrimScriptExtender(this)); + registerFeature(new NehrimDataArchives(myGamesPath())); + registerFeature(new NehrimBSAInvalidation(feature(), this)); registerFeature(new GamebryoSaveGameInfo(this)); registerFeature(new GamebryoLocalSavegames(myGamesPath(), "oblivion.ini")); - registerFeature(new OblivionModDataChecker(this)); - registerFeature(new OblivionModDataContent(this)); + registerFeature(new NehrimModDataChecker(this)); + registerFeature(new NehrimModDataContent(this)); registerFeature(new GamebryoGamePlugins(moInfo)); registerFeature(new GamebryoUnmangedMods(this)); return true; } -QString GameOblivion::gameName() const +QString GameNehrim::gameName() const { - return "Oblivion"; + return "Nehrim"; } -QList GameOblivion::executables() const +QList GameNehrim::executables() const { return QList() - << ExecutableInfo("OBSE", findInGameFolder(feature()->loaderName())) - << ExecutableInfo("Oblivion", findInGameFolder(binaryName())) - << ExecutableInfo("Oblivion Launcher", findInGameFolder(getLauncherName())) + << ExecutableInfo("Nehrim", findInGameFolder(binaryName())) + << ExecutableInfo("Nehrim Launcher", findInGameFolder(getLauncherName())) << ExecutableInfo("Oblivion Mod Manager", findInGameFolder("OblivionModManager.exe")) << ExecutableInfo("BOSS", findInGameFolder("BOSS/BOSS.exe")) << ExecutableInfo("LOOT", getLootPath()).withArgument("--game=\"Oblivion\"") @@ -61,50 +60,50 @@ QList GameOblivion::executables() const ; } -QList GameOblivion::executableForcedLoads() const +QList GameNehrim::executableForcedLoads() const { //TODO Search game directory for OBSE DLLs return QList() - << ExecutableForcedLoadSetting("Oblivion.exe", "obse_1_2_416.dll").withForced() + << ExecutableForcedLoadSetting("Oblvion.exe", "obse_1_2_416.dll").withForced() << ExecutableForcedLoadSetting("TESConstructionSet.exe", "obse_editor_1_2.dll").withForced() ; } -QString GameOblivion::name() const +QString GameNehrim::name() const { - return "Oblivion Support Plugin"; + return "Nehrim Support Plugin"; } -QString GameOblivion::localizedName() const +QString GameNehrim::localizedName() const { - return tr("Oblivion Support Plugin"); + return tr("Nehrim Support Plugin"); } -QString GameOblivion::author() const +QString GameNehrim::author() const { return "Tannin"; } -QString GameOblivion::description() const +QString GameNehrim::description() const { - return tr("Adds support for the game Oblivion"); + return tr("Adds support for the game Nehrim"); } -MOBase::VersionInfo GameOblivion::version() const +MOBase::VersionInfo GameNehrim::version() const { - return VersionInfo(1, 4, 1, VersionInfo::RELEASE_FINAL); + return VersionInfo(1, 0, 0, VersionInfo::RELEASE_FINAL); } -QList GameOblivion::settings() const +QList GameNehrim::settings() const { return QList(); } -void GameOblivion::initializeProfile(const QDir &path, ProfileSettings settings) const +void GameNehrim::initializeProfile(const QDir &path, ProfileSettings settings) const { if (settings.testFlag(IPluginGame::MODS)) { - copyToProfile(localAppFolder() + "/Oblivion", path, "plugins.txt"); - copyToProfile(localAppFolder() + "/Oblivion", path, "loadorder.txt"); + copyToProfile(localAppFolder() + "/Oblvion", path, "plugins.txt"); + copyToProfile(localAppFolder() + "/Oblvion", path, "loadorder.txt"); } if (settings.testFlag(IPluginGame::CONFIGURATION)) { @@ -119,61 +118,59 @@ void GameOblivion::initializeProfile(const QDir &path, ProfileSettings settings) } } -QString GameOblivion::savegameExtension() const +QString GameNehrim::savegameExtension() const { return "ess"; } -QString GameOblivion::savegameSEExtension() const +QString GameNehrim::savegameSEExtension() const { return "obse"; } -std::shared_ptr GameOblivion::makeSaveGame(QString filePath) const +std::shared_ptr GameNehrim::makeSaveGame(QString filePath) const { - return std::make_shared(filePath, this); + return std::make_shared(filePath, this); } -QString GameOblivion::steamAPPId() const +QString GameNehrim::steamAPPId() const { return "22330"; } -QStringList GameOblivion::primaryPlugins() const +QStringList GameNehrim::primaryPlugins() const { - return { "oblivion.esm", "update.esm" }; + return { "Nehrim.esm", "Translation.esp" }; } -QString GameOblivion::gameShortName() const +QString GameNehrim::gameShortName() const { - return "Oblivion"; + return "Nehrim"; } -QString GameOblivion::gameNexusName() const +QString GameNehrim::gameNexusName() const { - return "Oblivion"; + return "Nehrim"; } -QStringList GameOblivion::iniFiles() const +QStringList GameNehrim::iniFiles() const { return { "oblivion.ini", "oblivionprefs.ini" }; } -QStringList GameOblivion::DLCPlugins() const +QStringList GameNehrim::DLCPlugins() const { - return { "DLCBattlehornCastle.esp", "DLCShiveringIsles.esp", "Knights.esp", "DLCFrostcrag.esp", - "DLCSpellTomes.esp", "DLCMehrunesRazor.esp", "DLCOrrery.esp", - "DLCThievesDen.esp", "DLCVileLair.esp", "DLCHorseArmor.esp" }; + return {}; } -int GameOblivion::nexusModOrganizerID() const +int GameNehrim::nexusModOrganizerID() const { - return 38277; + return -1; } -int GameOblivion::nexusGameID() const +int GameNehrim::nexusGameID() const { - return 101; + return 3312; } diff --git a/src/games/nehrim/src/nehrimbsainvalidation.cpp b/src/games/nehrim/src/nehrimbsainvalidation.cpp index 6426af0b..0af89fc1 100644 --- a/src/games/nehrim/src/nehrimbsainvalidation.cpp +++ b/src/games/nehrim/src/nehrimbsainvalidation.cpp @@ -1,17 +1,17 @@ -#include "oblivionbsainvalidation.h" +#include "nehrimbsainvalidation.h" -OblivionBSAInvalidation::OblivionBSAInvalidation(DataArchives *dataArchives, MOBase::IPluginGame const *game) +NehrimBSAInvalidation::NehrimBSAInvalidation(DataArchives *dataArchives, MOBase::IPluginGame const *game) : GamebryoBSAInvalidation(dataArchives, "oblivion.ini", game) { } -QString OblivionBSAInvalidation::invalidationBSAName() const +QString NehrimBSAInvalidation::invalidationBSAName() const { - return "Oblivion - Invalidation.bsa"; + return "Nehrim - Invalidation.bsa"; } -unsigned long OblivionBSAInvalidation::bsaVersion() const +unsigned long NehrimBSAInvalidation::bsaVersion() const { return 0x67; } diff --git a/src/games/nehrim/src/nehrimbsainvalidation.h b/src/games/nehrim/src/nehrimbsainvalidation.h index 8884517d..59f471d6 100644 --- a/src/games/nehrim/src/nehrimbsainvalidation.h +++ b/src/games/nehrim/src/nehrimbsainvalidation.h @@ -1,17 +1,17 @@ -#ifndef OBLIVIONBSAINVALIDATION_H -#define OBLIVIONBSAINVALIDATION_H +#ifndef NEHRIMBSAINVALIDATION_H +#define NEHRIMBSAINVALIDATION_H #include "gamebryobsainvalidation.h" -#include "obliviondataarchives.h" +#include "nehrimdataarchives.h" #include -class OblivionBSAInvalidation : public GamebryoBSAInvalidation +class NehrimBSAInvalidation : public GamebryoBSAInvalidation { public: - OblivionBSAInvalidation(DataArchives *dataArchives, MOBase::IPluginGame const *game); + NehrimBSAInvalidation(DataArchives *dataArchives, MOBase::IPluginGame const *game); private: @@ -20,4 +20,4 @@ private: }; -#endif // OBLIVIONBSAINVALIDATION_H +#endif // NEHRIMBSAINVALIDATION_H diff --git a/src/games/nehrim/src/nehrimdataarchives.cpp b/src/games/nehrim/src/nehrimdataarchives.cpp index 0d281eeb..8d0fce47 100644 --- a/src/games/nehrim/src/nehrimdataarchives.cpp +++ b/src/games/nehrim/src/nehrimdataarchives.cpp @@ -1,23 +1,24 @@ -#include "obliviondataarchives.h" +#include "nehrimdataarchives.h" #include -OblivionDataArchives::OblivionDataArchives(const QDir &myGamesDir) : +NehrimDataArchives::NehrimDataArchives(const QDir &myGamesDir) : GamebryoDataArchives(myGamesDir) { } -QStringList OblivionDataArchives::vanillaArchives() const +QStringList NehrimDataArchives::vanillaArchives() const { - return { "Oblivion - Misc.bsa" - , "Oblivion - Textures - Compressed.bsa" - , "Oblivion - Meshes.bsa" - , "Oblivion - Sounds.bsa" - , "Oblivion - Voices1.bsa" - , "Oblivion - Voices2.bsa" + return { "N - Meshes.bsa" + , "N - Textures1.bsa" + , "N - Textures2.bsa" + , "N - Misc.bsa" + , "N - Sounds.bsa" + , "L - Voices.bsa" + , "L - Misc.bsa" }; } -QStringList OblivionDataArchives::archives(const MOBase::IProfile *profile) const +QStringList NehrimDataArchives::archives(const MOBase::IProfile *profile) const { QStringList result; @@ -27,7 +28,7 @@ QStringList OblivionDataArchives::archives(const MOBase::IProfile *profile) cons return result; } -void OblivionDataArchives::writeArchiveList(MOBase::IProfile *profile, const QStringList &before) +void NehrimDataArchives::writeArchiveList(MOBase::IProfile *profile, const QStringList &before) { QString list = before.join(", "); diff --git a/src/games/nehrim/src/nehrimdataarchives.h b/src/games/nehrim/src/nehrimdataarchives.h index f1e9f0e2..beed56e2 100644 --- a/src/games/nehrim/src/nehrimdataarchives.h +++ b/src/games/nehrim/src/nehrimdataarchives.h @@ -1,5 +1,5 @@ -#ifndef OBLIVIONDATAARCHIVES_H -#define OBLIVIONDATAARCHIVES_H +#ifndef NEHRIMDATAARCHIVES_H +#define NEHRIMDATAARCHIVES_H #include @@ -8,11 +8,11 @@ #include #include -class OblivionDataArchives : public GamebryoDataArchives +class NehrimDataArchives : public GamebryoDataArchives { public: - OblivionDataArchives(const QDir &myGamesDir); + NehrimDataArchives(const QDir &myGamesDir); public: @@ -25,4 +25,4 @@ private: }; -#endif // OBLIVIONDATAARCHIVES_H +#endif // NEHRIMDATAARCHIVES_H diff --git a/src/games/nehrim/src/nehrimmoddatachecker.cpp b/src/games/nehrim/src/nehrimmoddatachecker.cpp index 0cc3546c..45077822 100644 --- a/src/games/nehrim/src/nehrimmoddatachecker.cpp +++ b/src/games/nehrim/src/nehrimmoddatachecker.cpp @@ -1,6 +1,6 @@ -#include "oblivionmoddatachecker.h" +#include "nehrimmoddatachecker.h" -ModDataChecker::CheckReturn OblivionModDataChecker::dataLooksValid( +ModDataChecker::CheckReturn NehrimModDataChecker::dataLooksValid( std::shared_ptr fileTree) const { // Check with Gamebryo stuff: @@ -19,7 +19,7 @@ ModDataChecker::CheckReturn OblivionModDataChecker::dataLooksValid( return CheckReturn::FIXABLE; } -std::shared_ptr OblivionModDataChecker::fix( +std::shared_ptr NehrimModDataChecker::fix( std::shared_ptr fileTree) const { // If we arrive here, it means all files starts with OBSE. @@ -27,4 +27,4 @@ std::shared_ptr OblivionModDataChecker::fix( auto obse = data->addDirectory("OBSE/Plugins"); obse->merge(fileTree); return data; -} \ No newline at end of file +} diff --git a/src/games/nehrim/src/nehrimmoddatachecker.h b/src/games/nehrim/src/nehrimmoddatachecker.h index 5159dc09..ddf6a550 100644 --- a/src/games/nehrim/src/nehrimmoddatachecker.h +++ b/src/games/nehrim/src/nehrimmoddatachecker.h @@ -1,9 +1,9 @@ -#ifndef OBLIVION_MODATACHECKER_H -#define OBLIVION_MODATACHECKER_H +#ifndef NEHRIM_MODATACHECKER_H +#define NEHRIM_MODATACHECKER_H #include -class OblivionModDataChecker : public GamebryoModDataChecker +class NehrimModDataChecker : public GamebryoModDataChecker { public: using GamebryoModDataChecker::GamebryoModDataChecker; @@ -16,7 +16,7 @@ protected: static FileNameSet result{ "fonts", "interface", "menus", "meshes", "music", "scripts", "shaders", "sound", "strings", "textures", "trees", "video", "facegen", - "obse", "distantlod", "asi", "distantland", "mits", "dllplugins", "CalienteTools", + "obse", "distantlod", "asi", "distantland", "mits", "dllplugins", "CalienteTools", "NetScriptFramework" }; return result; @@ -29,4 +29,4 @@ protected: } }; -#endif // OBLIVION_MODATACHECKER_H +#endif // NEHRIM_MODATACHECKER_H diff --git a/src/games/nehrim/src/nehrimmoddatacontent.h b/src/games/nehrim/src/nehrimmoddatacontent.h index 2e79a87f..b6768d1a 100644 --- a/src/games/nehrim/src/nehrimmoddatacontent.h +++ b/src/games/nehrim/src/nehrimmoddatacontent.h @@ -1,16 +1,16 @@ -#ifndef OBLIVION_MODDATACONTENT_H -#define OBLIVION_MODDATACONTENT_H +#ifndef NEHRIM_MODDATACONTENT_H +#define NEHRIM_MODDATACONTENT_H #include #include -class OblivionModDataContent : public GamebryoModDataContent { +class NehrimModDataContent : public GamebryoModDataContent { public: /** * */ - OblivionModDataContent(GameGamebryo const* gamePlugin) : GamebryoModDataContent(gamePlugin) { + NehrimModDataContent(GameGamebryo const* gamePlugin) : GamebryoModDataContent(gamePlugin) { // Just need to disable some contents: m_Enabled[CONTENT_MCM] = false; m_Enabled[CONTENT_SKYPROC] = false; @@ -18,4 +18,4 @@ public: }; -#endif // OBLIVION_MODDATACONTENT_H +#endif // NEHRIM_MODDATACONTENT_H diff --git a/src/games/nehrim/src/nehrimsavegame.cpp b/src/games/nehrim/src/nehrimsavegame.cpp index 52089e86..1cb574da 100644 --- a/src/games/nehrim/src/nehrimsavegame.cpp +++ b/src/games/nehrim/src/nehrimsavegame.cpp @@ -1,8 +1,8 @@ -#include "oblivionsavegame.h" +#include "nehrimsavegame.h" #include -OblivionSaveGame::OblivionSaveGame(QString const &fileName, GameOblivion const *game) : +NehrimSaveGame::NehrimSaveGame(QString const &fileName, GameNehrim const *game) : GamebryoSaveGame(fileName, game) { FileWrapper file(getFilepath(), "TES4SAVEGAME"); @@ -13,7 +13,7 @@ OblivionSaveGame::OblivionSaveGame(QString const &fileName, GameOblivion const * setCreationTime(creationTime); } -void OblivionSaveGame::fetchInformationFields(FileWrapper& file, +void NehrimSaveGame::fetchInformationFields(FileWrapper& file, unsigned long& saveNumber, QString& playerName, unsigned short& playerLevel, @@ -44,7 +44,7 @@ void OblivionSaveGame::fetchInformationFields(FileWrapper& file, file.read(creationTime); } -std::unique_ptr OblivionSaveGame::fetchDataFields() const +std::unique_ptr NehrimSaveGame::fetchDataFields() const { FileWrapper file(getFilepath(), "TES4SAVEGAME"); file.setPluginString(GamebryoSaveGame::StringType::TYPE_BSTRING); diff --git a/src/games/nehrim/src/nehrimsavegame.h b/src/games/nehrim/src/nehrimsavegame.h index 0c9de37d..ef8c1afd 100644 --- a/src/games/nehrim/src/nehrimsavegame.h +++ b/src/games/nehrim/src/nehrimsavegame.h @@ -1,13 +1,13 @@ -#ifndef OBLIVIONSAVEGAME_H -#define OBLIVIONSAVEGAME_H +#ifndef NEHRIMSAVEGAME_H +#define NEHRIMSAVEGAME_H #include "gamebryosavegame.h" -#include "gameoblivion.h" +#include "gamenehrim.h" -class OblivionSaveGame : public GamebryoSaveGame +class NehrimSaveGame : public GamebryoSaveGame { public: - OblivionSaveGame(QString const &fileName, GameOblivion const *game); + NehrimSaveGame(QString const &fileName, GameNehrim const *game); protected: @@ -22,4 +22,4 @@ protected: std::unique_ptr fetchDataFields() const override; }; -#endif // OBLIVIONSAVEGAME_H +#endif // NEHRIMSAVEGAME_H diff --git a/src/games/nehrim/src/nehrimscriptextender.cpp b/src/games/nehrim/src/nehrimscriptextender.cpp index defe9de9..e1b7e7d0 100644 --- a/src/games/nehrim/src/nehrimscriptextender.cpp +++ b/src/games/nehrim/src/nehrimscriptextender.cpp @@ -1,23 +1,23 @@ -#include "oblivionscriptextender.h" +#include "nehrimscriptextender.h" #include #include -OblivionScriptExtender::OblivionScriptExtender(GameGamebryo const *game) : +NehrimScriptExtender::NehrimScriptExtender(GameGamebryo const *game) : GamebryoScriptExtender(game) { } -OblivionScriptExtender::~OblivionScriptExtender() +NehrimScriptExtender::~NehrimScriptExtender() { } -QString OblivionScriptExtender::BinaryName() const +QString NehrimScriptExtender::BinaryName() const { return "obse_loader.exe"; } -QString OblivionScriptExtender::PluginPath() const +QString NehrimScriptExtender::PluginPath() const { return "obse/plugins"; } diff --git a/src/games/nehrim/src/nehrimscriptextender.h b/src/games/nehrim/src/nehrimscriptextender.h index 28e99035..95977ee4 100644 --- a/src/games/nehrim/src/nehrimscriptextender.h +++ b/src/games/nehrim/src/nehrimscriptextender.h @@ -1,19 +1,19 @@ -#ifndef OBLIVIONSCRIPTEXTENDER_H -#define OBLIVIONSCRIPTEXTENDER_H +#ifndef NEHRIMSCRIPTEXTENDER_H +#define NEHRIMSCRIPTEXTENDER_H #include "gamebryoscriptextender.h" class GameGamebryo; -class OblivionScriptExtender : public GamebryoScriptExtender +class NehrimScriptExtender : public GamebryoScriptExtender { public: - OblivionScriptExtender(const GameGamebryo *game); - ~OblivionScriptExtender(); + NehrimScriptExtender(const GameGamebryo *game); + ~NehrimScriptExtender(); virtual QString BinaryName() const override; virtual QString PluginPath() const override; }; -#endif // OBLIVIONSCRIPTEXTENDER_H +#endif // NEHRIMSCRIPTEXTENDER_H From 147fb61393f96e17dd3daa5e304cd57a9c5fd6a5 Mon Sep 17 00:00:00 2001 From: Chris Bessent Date: Sun, 22 Aug 2021 10:50:41 -0700 Subject: [PATCH 1169/1544] [game_nehrim] Fix functionality --- src/games/nehrim/src/game_nehrim_en.ts | 4 +-- .../src/{gamenhrim.cpp => gamenehrim.cpp} | 27 ++++++++++++++++++- src/games/nehrim/src/gamenehrim.h | 8 ++++++ 3 files changed, 36 insertions(+), 3 deletions(-) rename src/games/nehrim/src/{gamenhrim.cpp => gamenehrim.cpp} (88%) diff --git a/src/games/nehrim/src/game_nehrim_en.ts b/src/games/nehrim/src/game_nehrim_en.ts index fee5da54..9b8f44c7 100644 --- a/src/games/nehrim/src/game_nehrim_en.ts +++ b/src/games/nehrim/src/game_nehrim_en.ts @@ -4,12 +4,12 @@ GameNehrim - + Nehrim Support Plugin - + Adds support for the game Nehrim diff --git a/src/games/nehrim/src/gamenhrim.cpp b/src/games/nehrim/src/gamenehrim.cpp similarity index 88% rename from src/games/nehrim/src/gamenhrim.cpp rename to src/games/nehrim/src/gamenehrim.cpp index 77f75a9c..969a98ae 100644 --- a/src/games/nehrim/src/gamenhrim.cpp +++ b/src/games/nehrim/src/gamenehrim.cpp @@ -153,7 +153,6 @@ QString GameNehrim::gameNexusName() const return "Nehrim"; } - QStringList GameNehrim::iniFiles() const { return { "oblivion.ini", "oblivionprefs.ini" }; @@ -174,3 +173,29 @@ int GameNehrim::nexusGameID() const { return 3312; } + +QStringList GameNehrim::primarySources() const +{ + return {"Oblivion"}; +} + +QStringList GameNehrim::validShortNames() const +{ + return {"Oblivion"}; +} + +QString GameNehrim::identifyGamePath() const +{ + QString path = "Software\\Bethesda Softworks\\Oblivion"; + return findInRegistry(HKEY_LOCAL_MACHINE, path.toStdWString().c_str(), L"Installed Path"); +} + +QString GameNehrim::binaryName() const +{ + return "Oblivion.exe"; +} + +QIcon GameNehrim::gameIcon() const +{ + return MOBase::iconForExecutable(gameDirectory().absoluteFilePath("NehrimLauncher.exe")); +} \ No newline at end of file diff --git a/src/games/nehrim/src/gamenehrim.h b/src/games/nehrim/src/gamenehrim.h index 3a5142c9..0dafdae3 100644 --- a/src/games/nehrim/src/gamenehrim.h +++ b/src/games/nehrim/src/gamenehrim.h @@ -31,6 +31,14 @@ public: // IPluginGame interface virtual QStringList DLCPlugins() const override; virtual int nexusModOrganizerID() const override; virtual int nexusGameID() const override; + virtual QStringList primarySources() const override; + virtual QStringList validShortNames() const override; + + // Weird stuff happens in these functions due to Nehrim + // technically being in the Oblivion folder + virtual QString identifyGamePath() const override; + virtual QString binaryName() const override; + virtual QIcon gameIcon() const override; public: // IPlugin interface From 0e78d127011616e0ed532e793115809f8d4ead92 Mon Sep 17 00:00:00 2001 From: Chris Bessent Date: Sun, 22 Aug 2021 10:57:28 -0700 Subject: [PATCH 1170/1544] [game_nehrim] Force OBSE to be enabled --- src/games/nehrim/src/gamenehrim.cpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/games/nehrim/src/gamenehrim.cpp b/src/games/nehrim/src/gamenehrim.cpp index 969a98ae..c2ca297f 100644 --- a/src/games/nehrim/src/gamenehrim.cpp +++ b/src/games/nehrim/src/gamenehrim.cpp @@ -64,8 +64,8 @@ QList GameNehrim::executableForcedLoads() const { //TODO Search game directory for OBSE DLLs return QList() - << ExecutableForcedLoadSetting("Oblvion.exe", "obse_1_2_416.dll").withForced() - << ExecutableForcedLoadSetting("TESConstructionSet.exe", "obse_editor_1_2.dll").withForced() + << ExecutableForcedLoadSetting("Oblvion.exe", "obse_1_2_416.dll").withForced().withEnabled() + << ExecutableForcedLoadSetting("TESConstructionSet.exe", "obse_editor_1_2.dll").withForced().withEnabled() ; } From 1bd1adf3d12cf5162455ba197074392f4fba29b5 Mon Sep 17 00:00:00 2001 From: Chris Bessent Date: Sun, 22 Aug 2021 11:46:54 -0700 Subject: [PATCH 1171/1544] [game_nehrim] Fix conflict between Oblivion and Nehrim --- src/games/nehrim/src/gamenehrim.cpp | 12 +++--------- src/games/nehrim/src/gamenehrim.h | 1 - 2 files changed, 3 insertions(+), 10 deletions(-) diff --git a/src/games/nehrim/src/gamenehrim.cpp b/src/games/nehrim/src/gamenehrim.cpp index c2ca297f..23f78fd6 100644 --- a/src/games/nehrim/src/gamenehrim.cpp +++ b/src/games/nehrim/src/gamenehrim.cpp @@ -51,8 +51,8 @@ QString GameNehrim::gameName() const QList GameNehrim::executables() const { return QList() - << ExecutableInfo("Nehrim", findInGameFolder(binaryName())) - << ExecutableInfo("Nehrim Launcher", findInGameFolder(getLauncherName())) + << ExecutableInfo("Nehrim", findInGameFolder("Oblivion.exe")) + << ExecutableInfo("Nehrim Launcher", findInGameFolder("NehrimLauncher.exe")) << ExecutableInfo("Oblivion Mod Manager", findInGameFolder("OblivionModManager.exe")) << ExecutableInfo("BOSS", findInGameFolder("BOSS/BOSS.exe")) << ExecutableInfo("LOOT", getLootPath()).withArgument("--game=\"Oblivion\"") @@ -163,7 +163,6 @@ QStringList GameNehrim::DLCPlugins() const return {}; } - int GameNehrim::nexusModOrganizerID() const { return -1; @@ -192,10 +191,5 @@ QString GameNehrim::identifyGamePath() const QString GameNehrim::binaryName() const { - return "Oblivion.exe"; -} - -QIcon GameNehrim::gameIcon() const -{ - return MOBase::iconForExecutable(gameDirectory().absoluteFilePath("NehrimLauncher.exe")); + return "NehrimLauncher.exe"; } \ No newline at end of file diff --git a/src/games/nehrim/src/gamenehrim.h b/src/games/nehrim/src/gamenehrim.h index 0dafdae3..f08447bc 100644 --- a/src/games/nehrim/src/gamenehrim.h +++ b/src/games/nehrim/src/gamenehrim.h @@ -38,7 +38,6 @@ public: // IPluginGame interface // technically being in the Oblivion folder virtual QString identifyGamePath() const override; virtual QString binaryName() const override; - virtual QIcon gameIcon() const override; public: // IPlugin interface From 18f6bd1b242025bdc74ac6d8b091367026284ee4 Mon Sep 17 00:00:00 2001 From: Chris Bessent Date: Sun, 22 Aug 2021 11:47:38 -0700 Subject: [PATCH 1172/1544] [game_oblivion] Force OBSE to be loaded always --- src/games/oblivion/src/gameoblivion.cpp | 6 ++---- 1 file changed, 2 insertions(+), 4 deletions(-) diff --git a/src/games/oblivion/src/gameoblivion.cpp b/src/games/oblivion/src/gameoblivion.cpp index 1b8fd952..93106af0 100644 --- a/src/games/oblivion/src/gameoblivion.cpp +++ b/src/games/oblivion/src/gameoblivion.cpp @@ -51,7 +51,6 @@ QString GameOblivion::gameName() const QList GameOblivion::executables() const { return QList() - << ExecutableInfo("OBSE", findInGameFolder(feature()->loaderName())) << ExecutableInfo("Oblivion", findInGameFolder(binaryName())) << ExecutableInfo("Oblivion Launcher", findInGameFolder(getLauncherName())) << ExecutableInfo("Oblivion Mod Manager", findInGameFolder("OblivionModManager.exe")) @@ -63,10 +62,9 @@ QList GameOblivion::executables() const QList GameOblivion::executableForcedLoads() const { - //TODO Search game directory for OBSE DLLs return QList() - << ExecutableForcedLoadSetting("Oblivion.exe", "obse_1_2_416.dll").withForced() - << ExecutableForcedLoadSetting("TESConstructionSet.exe", "obse_editor_1_2.dll").withForced() + << ExecutableForcedLoadSetting("Oblivion.exe", "obse_1_2_416.dll").withForced().withEnabled() + << ExecutableForcedLoadSetting("TESConstructionSet.exe", "obse_editor_1_2.dll").withForced().withEnabled() ; } From a037fd911438be2f11beb071926043f3a57fcc29 Mon Sep 17 00:00:00 2001 From: Chris Bessent Date: Sun, 22 Aug 2021 14:07:32 -0700 Subject: [PATCH 1173/1544] [game_nehrim] Update nehrimdataarchives.cpp --- src/games/nehrim/src/nehrimdataarchives.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/games/nehrim/src/nehrimdataarchives.cpp b/src/games/nehrim/src/nehrimdataarchives.cpp index 8d0fce47..28e09f03 100644 --- a/src/games/nehrim/src/nehrimdataarchives.cpp +++ b/src/games/nehrim/src/nehrimdataarchives.cpp @@ -14,7 +14,7 @@ QStringList NehrimDataArchives::vanillaArchives() const , "N - Misc.bsa" , "N - Sounds.bsa" , "L - Voices.bsa" - , "L - Misc.bsa" + , "L - Misc.bsa" }; } From 8aa335f2bca53b196379d083a8799ba0aa8f55a3 Mon Sep 17 00:00:00 2001 From: Chris Bessent Date: Fri, 27 Aug 2021 16:43:05 -0700 Subject: [PATCH 1174/1544] [game_fallout3] Remove ambiguity of which My Games folder to use --- src/games/fallout3/src/gamefallout3.cpp | 6 ++++++ src/games/fallout3/src/gamefallout3.h | 1 + 2 files changed, 7 insertions(+) diff --git a/src/games/fallout3/src/gamefallout3.cpp b/src/games/fallout3/src/gamefallout3.cpp index 122efd0c..16da524f 100644 --- a/src/games/fallout3/src/gamefallout3.cpp +++ b/src/games/fallout3/src/gamefallout3.cpp @@ -53,6 +53,12 @@ QString GameFallout3::gameName() const return "Fallout 3"; } +void GameFallout3::detectGame() +{ + m_GamePath = identifyGamePath(); + m_MyGamesPath = determineMyGamesPath("Fallout3"); +} + QList GameFallout3::executables() const { return QList() diff --git a/src/games/fallout3/src/gamefallout3.h b/src/games/fallout3/src/gamefallout3.h index e77c21fb..4712e035 100644 --- a/src/games/fallout3/src/gamefallout3.h +++ b/src/games/fallout3/src/gamefallout3.h @@ -20,6 +20,7 @@ public: public: // IPluginGame interface virtual QString gameName() const override; + virtual void detectGame() override; virtual QList executables() const override; virtual QList executableForcedLoads() const override; virtual void initializeProfile(const QDir &path, ProfileSettings settings) const override; From af66641ca9f1bcc9df1af34c32df35a4d6740a80 Mon Sep 17 00:00:00 2001 From: Chris Bessent Date: Fri, 27 Aug 2021 16:43:17 -0700 Subject: [PATCH 1175/1544] [game_fallout4] Remove ambiguity of which My Games folder to use --- src/games/fallout4/src/gamefallout4.cpp | 8 +++++++- src/games/fallout4/src/gamefallout4.h | 1 + 2 files changed, 8 insertions(+), 1 deletion(-) diff --git a/src/games/fallout4/src/gamefallout4.cpp b/src/games/fallout4/src/gamefallout4.cpp index f155976a..ac4f2c21 100644 --- a/src/games/fallout4/src/gamefallout4.cpp +++ b/src/games/fallout4/src/gamefallout4.cpp @@ -55,6 +55,12 @@ QString GameFallout4::gameName() const return "Fallout 4"; } +void GameFallout4::detectGame() +{ + m_GamePath = identifyGamePath(); + m_MyGamesPath = determineMyGamesPath("Fallout4"); +} + QList GameFallout4::executables() const { return QList() @@ -95,7 +101,7 @@ QString GameFallout4::description() const MOBase::VersionInfo GameFallout4::version() const { - return VersionInfo(1, 5, 0, VersionInfo::RELEASE_FINAL); + return VersionInfo(1, 6, 0, VersionInfo::RELEASE_FINAL); } QList GameFallout4::settings() const diff --git a/src/games/fallout4/src/gamefallout4.h b/src/games/fallout4/src/gamefallout4.h index 72a7af62..f80fc170 100644 --- a/src/games/fallout4/src/gamefallout4.h +++ b/src/games/fallout4/src/gamefallout4.h @@ -22,6 +22,7 @@ public: public: // IPluginGame interface virtual QString gameName() const override; + virtual void detectGame() override; virtual QList executables() const override; virtual QList executableForcedLoads() const override; virtual void initializeProfile(const QDir &path, ProfileSettings settings) const override; From 28d8a69565320430b5687931ebbe4a5504630223 Mon Sep 17 00:00:00 2001 From: Chris Bessent Date: Fri, 27 Aug 2021 16:43:28 -0700 Subject: [PATCH 1176/1544] [game_fallout4vr] Remove ambiguity of which My Games folder to use --- src/games/fallout4vr/src/gamefallout4vr.cpp | 8 +++++++- src/games/fallout4vr/src/gamefallout4vr.h | 1 + 2 files changed, 8 insertions(+), 1 deletion(-) diff --git a/src/games/fallout4vr/src/gamefallout4vr.cpp b/src/games/fallout4vr/src/gamefallout4vr.cpp index fef6c37e..5e96ed20 100644 --- a/src/games/fallout4vr/src/gamefallout4vr.cpp +++ b/src/games/fallout4vr/src/gamefallout4vr.cpp @@ -53,6 +53,12 @@ QString GameFallout4VR::gameName() const return "Fallout 4 VR"; } +void GameFallout4VR::detectGame() +{ + m_GamePath = identifyGamePath(); + m_MyGamesPath = determineMyGamesPath("Fallout4VR"); +} + QList GameFallout4VR::executables() const { return QList() @@ -91,7 +97,7 @@ QString GameFallout4VR::description() const MOBase::VersionInfo GameFallout4VR::version() const { - return VersionInfo(1, 4, 1, VersionInfo::RELEASE_FINAL); + return VersionInfo(1, 5, 0, VersionInfo::RELEASE_FINAL); } QList GameFallout4VR::settings() const diff --git a/src/games/fallout4vr/src/gamefallout4vr.h b/src/games/fallout4vr/src/gamefallout4vr.h index 15617b1a..6904cff7 100644 --- a/src/games/fallout4vr/src/gamefallout4vr.h +++ b/src/games/fallout4vr/src/gamefallout4vr.h @@ -22,6 +22,7 @@ public: public: // IPluginGame interface virtual QString gameName() const override; + virtual void detectGame() override; virtual QList executables() const override; virtual QList executableForcedLoads() const override; virtual void initializeProfile(const QDir &path, ProfileSettings settings) const override; From 3e1e3af7f63046aee8d9c52d4962c29d669781fb Mon Sep 17 00:00:00 2001 From: Chris Bessent Date: Fri, 27 Aug 2021 16:43:46 -0700 Subject: [PATCH 1177/1544] [game_falloutnv] Remove ambiguity of which My Games folder to use --- src/games/falloutnv/src/gamefalloutnv.cpp | 6 ++++++ src/games/falloutnv/src/gamefalloutnv.h | 1 + 2 files changed, 7 insertions(+) diff --git a/src/games/falloutnv/src/gamefalloutnv.cpp b/src/games/falloutnv/src/gamefalloutnv.cpp index 4db39428..307ade66 100644 --- a/src/games/falloutnv/src/gamefalloutnv.cpp +++ b/src/games/falloutnv/src/gamefalloutnv.cpp @@ -53,6 +53,12 @@ QString GameFalloutNV::gameName() const return "New Vegas"; } +void GameFalloutNV::detectGame() +{ + m_GamePath = identifyGamePath(); + m_MyGamesPath = determineMyGamesPath("FalloutNV"); +} + QList GameFalloutNV::executables() const { return QList() diff --git a/src/games/falloutnv/src/gamefalloutnv.h b/src/games/falloutnv/src/gamefalloutnv.h index d2ac8621..ee37ec2b 100644 --- a/src/games/falloutnv/src/gamefalloutnv.h +++ b/src/games/falloutnv/src/gamefalloutnv.h @@ -22,6 +22,7 @@ public: public: // IPluginGame interface virtual QString gameName() const override; + virtual void detectGame() override; virtual QList executables() const override; virtual QList executableForcedLoads() const override; virtual void initializeProfile(const QDir &path, ProfileSettings settings) const override; From bdc1a1d8d89962e9b02f16a892aedc07fd7a97bc Mon Sep 17 00:00:00 2001 From: Chris Bessent Date: Fri, 27 Aug 2021 16:44:04 -0700 Subject: [PATCH 1178/1544] Remove ambiguity of which My Games folder to use --- src/gamebryo/gamegamebryo.cpp | 11 ----------- 1 file changed, 11 deletions(-) diff --git a/src/gamebryo/gamegamebryo.cpp b/src/gamebryo/gamegamebryo.cpp index 841ae3b2..60c62bd8 100644 --- a/src/gamebryo/gamegamebryo.cpp +++ b/src/gamebryo/gamegamebryo.cpp @@ -40,18 +40,7 @@ GameGamebryo::GameGamebryo() void GameGamebryo::detectGame() { m_GamePath = identifyGamePath(); - - // some games have the same short and long names, such as "Skyrim"; others - // have different values, such as "SkyrimSE" and "Skyrim Special Edition" - // - // games with different short/long names typically use the long name in - // "My Games", so that's tried first; if it fails, the short name is tried m_MyGamesPath = determineMyGamesPath(gameName()); - if (m_MyGamesPath.isEmpty()) { - if (gameName() != gameShortName()) { - m_MyGamesPath = determineMyGamesPath(gameShortName()); - } - } } bool GameGamebryo::init(MOBase::IOrganizer *moInfo) From 1796a39783ebdccc979725559b6554dc155a2468 Mon Sep 17 00:00:00 2001 From: Chris Bessent Date: Tue, 23 Nov 2021 20:53:03 -0700 Subject: [PATCH 1179/1544] [game_fallout3] Update translations --- src/games/fallout3/src/game_fallout3_en.ts | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/src/games/fallout3/src/game_fallout3_en.ts b/src/games/fallout3/src/game_fallout3_en.ts index 39f10bc8..e931d28c 100644 --- a/src/games/fallout3/src/game_fallout3_en.ts +++ b/src/games/fallout3/src/game_fallout3_en.ts @@ -4,13 +4,13 @@ GameFallout3 - + Fallout 3 Support Plugin - - Adds support for the game Fallout 3s + + Adds support for the game Fallout 3. From 993ae8dbdd19529da46a3d3888f36e73471f92db Mon Sep 17 00:00:00 2001 From: Chris Bessent Date: Tue, 23 Nov 2021 20:53:17 -0700 Subject: [PATCH 1180/1544] [game_fallout4] Update translations --- src/games/fallout4/src/game_fallout4_en.ts | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/games/fallout4/src/game_fallout4_en.ts b/src/games/fallout4/src/game_fallout4_en.ts index addc4d66..08d66493 100644 --- a/src/games/fallout4/src/game_fallout4_en.ts +++ b/src/games/fallout4/src/game_fallout4_en.ts @@ -4,12 +4,12 @@ GameFallout4 - + Fallout 4 Support Plugin - + Adds support for the game Fallout 4. Splash by %1 From 9e2cc27a682425209e7dc4b6c4d969edd3d7d326 Mon Sep 17 00:00:00 2001 From: Chris Bessent Date: Tue, 23 Nov 2021 20:53:32 -0700 Subject: [PATCH 1181/1544] [game_fallout4vr] Update translations --- src/games/fallout4vr/src/game_fallout4vr_en.ts | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/games/fallout4vr/src/game_fallout4vr_en.ts b/src/games/fallout4vr/src/game_fallout4vr_en.ts index 6a642dfa..6823bb92 100644 --- a/src/games/fallout4vr/src/game_fallout4vr_en.ts +++ b/src/games/fallout4vr/src/game_fallout4vr_en.ts @@ -4,12 +4,12 @@ GameFallout4VR - + Fallout 4 VR Support Plugin - + Adds support for the game Fallout 4 VR. Splash by %1 From d9787cc82e9fc44516c39b8782c36af21f9b0863 Mon Sep 17 00:00:00 2001 From: Chris Bessent Date: Tue, 23 Nov 2021 20:53:49 -0700 Subject: [PATCH 1182/1544] [game_falloutnv] Update translations --- src/games/falloutnv/src/game_falloutNV_en.ts | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/games/falloutnv/src/game_falloutNV_en.ts b/src/games/falloutnv/src/game_falloutNV_en.ts index f100d146..866720f0 100644 --- a/src/games/falloutnv/src/game_falloutNV_en.ts +++ b/src/games/falloutnv/src/game_falloutNV_en.ts @@ -4,12 +4,12 @@ GameFalloutNV - + Fallout NV Support Plugin - + Adds support for the game Fallout New Vegas From 63d331f5e9b640f7fec8c86db98e553c14520fb5 Mon Sep 17 00:00:00 2001 From: Chris Bessent Date: Tue, 23 Nov 2021 20:54:21 -0700 Subject: [PATCH 1183/1544] Update translations --- src/game_gamebryo_en.ts | 9 +++++++-- 1 file changed, 7 insertions(+), 2 deletions(-) diff --git a/src/game_gamebryo_en.ts b/src/game_gamebryo_en.ts index e4ecb50c..e8a2af83 100644 --- a/src/game_gamebryo_en.ts +++ b/src/game_gamebryo_en.ts @@ -70,6 +70,11 @@ + FaceGen Data + + + + ModGroup Files @@ -146,12 +151,12 @@ - + failed to query registry path (preflight): %1 - + failed to query registry path (read): %1 From de805f98ec2ca98896a382e766a2efa6c040996f Mon Sep 17 00:00:00 2001 From: Chris Bessent Date: Tue, 23 Nov 2021 20:55:02 -0700 Subject: [PATCH 1184/1544] [game_oblivion] Update translations --- src/games/oblivion/src/game_oblivion_en.ts | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/games/oblivion/src/game_oblivion_en.ts b/src/games/oblivion/src/game_oblivion_en.ts index ad614a85..20bf34e4 100644 --- a/src/games/oblivion/src/game_oblivion_en.ts +++ b/src/games/oblivion/src/game_oblivion_en.ts @@ -4,12 +4,12 @@ GameOblivion - + Oblivion Support Plugin - + Adds support for the game Oblivion From 16ddff5e61fc2cc221ae5541bafbd9c4520e6b71 Mon Sep 17 00:00:00 2001 From: Chris Bessent Date: Fri, 26 Nov 2021 13:35:52 -0700 Subject: [PATCH 1185/1544] [game_enderalse] Fix parsing plugins with dots in name --- src/games/enderalse/src/enderalseunmanagedmods.cpp | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/src/games/enderalse/src/enderalseunmanagedmods.cpp b/src/games/enderalse/src/enderalseunmanagedmods.cpp index c6a4e710..7bf0c5d2 100644 --- a/src/games/enderalse/src/enderalseunmanagedmods.cpp +++ b/src/games/enderalse/src/enderalseunmanagedmods.cpp @@ -21,12 +21,10 @@ QStringList EnderalSEUnmangedMods::mods(bool onlyOfficial) const { for (const QString &fileName : dataDir.entryList({ "*.esp", "*.esl", "*.esm" })) { if (!pluginList.contains(fileName, Qt::CaseInsensitive)) { if (!onlyOfficial || pluginList.contains(fileName, Qt::CaseInsensitive)) { - QFileInfo file(fileName); - result.append(file.baseName()); + result.append(fileName.chopped(4)); // trims the extension off } } } return result; } - From d3975eb39344b39eaec42eedb2c08c7df5e02855 Mon Sep 17 00:00:00 2001 From: Chris Bessent Date: Fri, 26 Nov 2021 13:36:12 -0700 Subject: [PATCH 1186/1544] [game_fallout4] Fix parsing plugins with dots in name --- src/games/fallout4/src/fallout4unmanagedmods.cpp | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/src/games/fallout4/src/fallout4unmanagedmods.cpp b/src/games/fallout4/src/fallout4unmanagedmods.cpp index 5007c4f7..1d0d314a 100644 --- a/src/games/fallout4/src/fallout4unmanagedmods.cpp +++ b/src/games/fallout4/src/fallout4unmanagedmods.cpp @@ -21,8 +21,7 @@ QStringList Fallout4UnmangedMods::mods(bool onlyOfficial) const { for (const QString &fileName : dataDir.entryList({ "*.esp", "*.esl", "*.esm" })) { if (!pluginList.contains(fileName, Qt::CaseInsensitive)) { if (!onlyOfficial || pluginList.contains(fileName, Qt::CaseInsensitive)) { - QFileInfo file(fileName); - result.append(file.baseName()); + result.append(fileName.chopped(4)); // trims the extension off } } } From 87d2cfdefd85b7c7659432dc54d84f842f88a9ad Mon Sep 17 00:00:00 2001 From: Chris Bessent Date: Fri, 26 Nov 2021 13:36:27 -0700 Subject: [PATCH 1187/1544] [game_fallout4vr] Fix parsing plugins with dots in name --- src/games/fallout4vr/src/fallout4vrunmanagedmods.cpp | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/src/games/fallout4vr/src/fallout4vrunmanagedmods.cpp b/src/games/fallout4vr/src/fallout4vrunmanagedmods.cpp index 9c7a420c..ef9c0e50 100644 --- a/src/games/fallout4vr/src/fallout4vrunmanagedmods.cpp +++ b/src/games/fallout4vr/src/fallout4vrunmanagedmods.cpp @@ -21,8 +21,7 @@ QStringList Fallout4VRUnmangedMods::mods(bool onlyOfficial) const { for (const QString &fileName : dataDir.entryList({ "*.esp", "*.esl", "*.esm" })) { if (!pluginList.contains(fileName, Qt::CaseInsensitive)) { if (!onlyOfficial || pluginList.contains(fileName, Qt::CaseInsensitive)) { - QFileInfo file(fileName); - result.append(file.baseName()); + result.append(fileName.chopped(4)); // trims the extension off } } } From 4d0a32301d95b34dbae9ae178e0ff48766200c3b Mon Sep 17 00:00:00 2001 From: Chris Bessent Date: Fri, 26 Nov 2021 13:36:41 -0700 Subject: [PATCH 1188/1544] Fix parsing plugins with dots in name --- src/gamebryo/gamebryounmanagedmods.cpp | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/src/gamebryo/gamebryounmanagedmods.cpp b/src/gamebryo/gamebryounmanagedmods.cpp index 80806d60..025bb1e3 100644 --- a/src/gamebryo/gamebryounmanagedmods.cpp +++ b/src/gamebryo/gamebryounmanagedmods.cpp @@ -20,8 +20,7 @@ QStringList GamebryoUnmangedMods::mods(bool onlyOfficial) const { for (const QString &fileName : dataDir.entryList({ "*.esp", "*.esl", "*.esm"})) { if (!mainPlugins.contains(fileName, Qt::CaseInsensitive) && (!onlyOfficial || dlcPlugins.contains(fileName, Qt::CaseInsensitive))) { - QFileInfo file(fileName); - result.append(file.baseName()); + result.append(fileName.chopped(4)); // trims the extension off } } @@ -51,4 +50,3 @@ QStringList GamebryoUnmangedMods::secondaryFiles(const QString &modName) const { } return archives; } - From c30e8de4c1ca7610cef4da26313f2a5475f8df8c Mon Sep 17 00:00:00 2001 From: Chris Bessent Date: Fri, 26 Nov 2021 13:36:59 -0700 Subject: [PATCH 1189/1544] [game_skyrimse] Fix parsing plugins with dots in name --- src/games/skyrimse/src/skyrimseunmanagedmods.cpp | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/src/games/skyrimse/src/skyrimseunmanagedmods.cpp b/src/games/skyrimse/src/skyrimseunmanagedmods.cpp index 14fd3e43..c8d92c4c 100644 --- a/src/games/skyrimse/src/skyrimseunmanagedmods.cpp +++ b/src/games/skyrimse/src/skyrimseunmanagedmods.cpp @@ -21,12 +21,10 @@ QStringList SkyrimSEUnmangedMods::mods(bool onlyOfficial) const { for (const QString &fileName : dataDir.entryList({ "*.esp", "*.esl", "*.esm" })) { if (!pluginList.contains(fileName, Qt::CaseInsensitive)) { if (!onlyOfficial || pluginList.contains(fileName, Qt::CaseInsensitive)) { - QFileInfo file(fileName); - result.append(file.baseName()); + result.append(fileName.chopped(4)); // trims the extension off } } } return result; } - From c07b854a23d376311c95a49515a5b37230851852 Mon Sep 17 00:00:00 2001 From: Chris Bessent Date: Fri, 26 Nov 2021 13:37:10 -0700 Subject: [PATCH 1190/1544] [game_skyrimvr] Fix parsing plugins with dots in name --- src/games/skyrimvr/src/skyrimvrunmanagedmods.cpp | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/src/games/skyrimvr/src/skyrimvrunmanagedmods.cpp b/src/games/skyrimvr/src/skyrimvrunmanagedmods.cpp index a75a43db..e79472e2 100644 --- a/src/games/skyrimvr/src/skyrimvrunmanagedmods.cpp +++ b/src/games/skyrimvr/src/skyrimvrunmanagedmods.cpp @@ -20,8 +20,7 @@ QStringList SkyrimVRUnmangedMods::mods(bool onlyOfficial) const { for (const QString &fileName : dataDir.entryList({ "*.esp", "*.esl", "*.esm" })) { if (!pluginList.contains(fileName, Qt::CaseInsensitive)) { if (!onlyOfficial || pluginList.contains(fileName, Qt::CaseInsensitive)) { - QFileInfo file(fileName); - result.append(file.baseName()); + result.append(fileName.chopped(4)); // trims the extension off } } } From 88805d79b6b5b9247c8ffb760486ec33bbc486d8 Mon Sep 17 00:00:00 2001 From: Jeremy Rimpo Date: Sun, 5 Dec 2021 03:42:41 -0600 Subject: [PATCH 1191/1544] [game_fallout4vr] Changes to compile with Qt6 + Boost 1.77 --- src/games/fallout4vr/src/gamefallout4vr.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/games/fallout4vr/src/gamefallout4vr.cpp b/src/games/fallout4vr/src/gamefallout4vr.cpp index 5e96ed20..d1217173 100644 --- a/src/games/fallout4vr/src/gamefallout4vr.cpp +++ b/src/games/fallout4vr/src/gamefallout4vr.cpp @@ -64,7 +64,7 @@ QList GameFallout4VR::executables() const return QList() << ExecutableInfo("Fallout 4 VR", findInGameFolder(binaryName())) << ExecutableInfo("Creation Kit", findInGameFolder("CreationKit.exe")) - << ExecutableInfo("LOOT", getLootPath()).withArgument("--game=\"Fallout4VR\"") + << ExecutableInfo("LOOT", QFileInfo(getLootPath())).withArgument("--game=\"Fallout4VR\"") ; } From 934b85bedafd73702b2186fe6f4ff118c12eaa4e Mon Sep 17 00:00:00 2001 From: Jeremy Rimpo Date: Sun, 5 Dec 2021 03:42:42 -0600 Subject: [PATCH 1192/1544] [game_falloutnv] Changes to compile with Qt6 + Boost 1.77 --- src/games/falloutnv/src/gamefalloutnv.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/games/falloutnv/src/gamefalloutnv.cpp b/src/games/falloutnv/src/gamefalloutnv.cpp index 307ade66..6de7fbb2 100644 --- a/src/games/falloutnv/src/gamefalloutnv.cpp +++ b/src/games/falloutnv/src/gamefalloutnv.cpp @@ -68,7 +68,7 @@ QList GameFalloutNV::executables() const << ExecutableInfo("Construction Kit", findInGameFolder("geck.exe")) << ExecutableInfo("Fallout Launcher", findInGameFolder(getLauncherName())) << ExecutableInfo("BOSS", findInGameFolder("BOSS/BOSS.exe")) - << ExecutableInfo("LOOT", getLootPath()).withArgument("--game=\"FalloutNV\"") + << ExecutableInfo("LOOT", QFileInfo(getLootPath())).withArgument("--game=\"FalloutNV\"") ; } From f58b307e53e80b4fa39c211be7de2af1294a57e3 Mon Sep 17 00:00:00 2001 From: Jeremy Rimpo Date: Sun, 5 Dec 2021 03:42:43 -0600 Subject: [PATCH 1193/1544] [game_enderalse] Changes to compile with Qt6 + Boost 1.77 --- src/games/enderalse/src/enderalsegameplugins.cpp | 6 ++++-- src/games/enderalse/src/game_enderalse_en.ts | 2 +- src/games/enderalse/src/gameenderalse.cpp | 2 +- 3 files changed, 6 insertions(+), 4 deletions(-) diff --git a/src/games/enderalse/src/enderalsegameplugins.cpp b/src/games/enderalse/src/enderalsegameplugins.cpp index 388c019d..a7cef538 100644 --- a/src/games/enderalse/src/enderalsegameplugins.cpp +++ b/src/games/enderalse/src/enderalsegameplugins.cpp @@ -28,8 +28,10 @@ void EnderalSEGamePlugins::writePluginList(const MOBase::IPluginList* pluginList }); QStringList PrimaryPlugins = organizer()->managedGame()->primaryPlugins(); - QSet ManagedMods = PrimaryPlugins.toSet().subtract(organizer()->managedGame()->DLCPlugins().toSet()); - PrimaryPlugins.append(ManagedMods.toList()); + QSet ManagedMods = QSet(PrimaryPlugins.begin(), PrimaryPlugins.end()).subtract( + QSet(organizer()->managedGame()->DLCPlugins().begin(), organizer()->managedGame()->DLCPlugins().begin()) + ); + PrimaryPlugins.append(QList(ManagedMods.begin(), ManagedMods.end())); // we need to force some plugins because those are not force-loaded // by the game but are considered primary plugins for users diff --git a/src/games/enderalse/src/game_enderalse_en.ts b/src/games/enderalse/src/game_enderalse_en.ts index d9206476..258d293e 100644 --- a/src/games/enderalse/src/game_enderalse_en.ts +++ b/src/games/enderalse/src/game_enderalse_en.ts @@ -17,7 +17,7 @@ QObject - + Some of your plugins have invalid names! These plugins can not be loaded by the game. Please see mo_interface.log for a list of affected plugins and rename them. diff --git a/src/games/enderalse/src/gameenderalse.cpp b/src/games/enderalse/src/gameenderalse.cpp index f7d4eaa3..92a90c08 100644 --- a/src/games/enderalse/src/gameenderalse.cpp +++ b/src/games/enderalse/src/gameenderalse.cpp @@ -80,7 +80,7 @@ QList GameEnderalSE::executables() const return { ExecutableInfo("Enderal Special Edition (SKSE)", findInGameFolder(feature()->loaderName())), ExecutableInfo("Enderal Special Edition Launcher", findInGameFolder(getLauncherName())), - // ExecutableInfo("LOOT", getLootPath()).withArgument("--game=\"Skyrim Special Edition\""), + // ExecutableInfo("LOOT", QFileInfo(getLootPath())).withArgument("--game=\"Skyrim Special Edition\""), ExecutableInfo("Creation Kit", findInGameFolder("CreationKit.exe")) }; } From 9978b6823c876fd9dca0ad46df6a463eddf9219d Mon Sep 17 00:00:00 2001 From: Jeremy Rimpo Date: Sun, 5 Dec 2021 03:42:43 -0600 Subject: [PATCH 1194/1544] [game_morrowind] Changes to compile with Qt6 + Boost 1.77 --- src/games/morrowind/src/gamemorrowind.cpp | 2 +- src/games/morrowind/src/morrowindsavegame.cpp | 3 ++- src/games/morrowind/src/morrowindsavegameinfowidget.cpp | 6 +++--- 3 files changed, 6 insertions(+), 5 deletions(-) diff --git a/src/games/morrowind/src/gamemorrowind.cpp b/src/games/morrowind/src/gamemorrowind.cpp index dacb1d0c..62bf8a85 100644 --- a/src/games/morrowind/src/gamemorrowind.cpp +++ b/src/games/morrowind/src/gamemorrowind.cpp @@ -85,7 +85,7 @@ QList GameMorrowind::executables() const << ExecutableInfo("Morrowind", findInGameFolder(binaryName())) << ExecutableInfo("Morrowind Launcher", findInGameFolder(getLauncherName())) << ExecutableInfo("MGE XE", findInGameFolder("MGEXEgui.exe")) - << ExecutableInfo("LOOT", getLootPath()).withArgument("--game=\"Morrowind\"") + << ExecutableInfo("LOOT", QFileInfo(getLootPath())).withArgument("--game=\"Morrowind\"") ; } diff --git a/src/games/morrowind/src/morrowindsavegame.cpp b/src/games/morrowind/src/morrowindsavegame.cpp index f73d696f..79ea868c 100644 --- a/src/games/morrowind/src/morrowindsavegame.cpp +++ b/src/games/morrowind/src/morrowindsavegame.cpp @@ -2,6 +2,7 @@ #include #include +#include #include MorrowindSaveGame::MorrowindSaveGame(QString const &fileName, GameMorrowind const *game) : @@ -9,7 +10,7 @@ MorrowindSaveGame::MorrowindSaveGame(QString const &fileName, GameMorrowind cons { std::filesystem::path realFile(fileName.toStdWString()); QString realFileName = QString::fromStdWString(realFile.filename().wstring()); - m_SaveNumber = realFileName.mid(4, 5).remove(QRegExp("0+$")).toInt(); + m_SaveNumber = realFileName.mid(4, 5).remove(QRegularExpression("0+$")).toInt(); FileWrapper file(fileName, "TES3"); QStringList dummyPlugins; diff --git a/src/games/morrowind/src/morrowindsavegameinfowidget.cpp b/src/games/morrowind/src/morrowindsavegameinfowidget.cpp index 567096cc..e61ef392 100644 --- a/src/games/morrowind/src/morrowindsavegameinfowidget.cpp +++ b/src/games/morrowind/src/morrowindsavegameinfowidget.cpp @@ -34,7 +34,7 @@ MorrowindSaveGameInfoWidget::MorrowindSaveGameInfoWidget(MorrowindSaveGameInfo c ui->gameFrame->setStyleSheet("background-color: transparent;"); QVBoxLayout *gameLayout = new QVBoxLayout(); - gameLayout->setMargin(0); + gameLayout->setContentsMargins(0, 0, 0, 0); gameLayout->setSpacing(2); ui->gameFrame->setLayout(gameLayout); } @@ -56,8 +56,8 @@ void MorrowindSaveGameInfoWidget::setSave(MOBase::ISaveGame const& save) { //This somewhat contorted code is because on my system at least, the //old way of doing this appears to give short date and long time. QDateTime t = morrowindSave.getCreationTime(); - ui->dateLabel->setText(t.date().toString(Qt::DefaultLocaleShortDate) + " " + - t.time().toString(Qt::DefaultLocaleLongDate)); + ui->dateLabel->setText(QLocale::system().toString(t.date(), QLocale::FormatType::ShortFormat) + " " + + QLocale::system().toString(t.time(), QLocale::FormatType::ShortFormat)); ui->screenshotLabel->setPixmap(QPixmap::fromImage(morrowindSave.getScreenshot())); if (ui->gameFrame->layout() != nullptr) { QLayoutItem *item = nullptr; From 76de53a967e0d07c82283f56bb9f51093634e1a0 Mon Sep 17 00:00:00 2001 From: Jeremy Rimpo Date: Sun, 5 Dec 2021 03:42:44 -0600 Subject: [PATCH 1195/1544] Changes to compile with Qt6 + Boost 1.77 --- src/creation/creationgameplugins.cpp | 6 ++++-- src/gamebryo/gamebryosavegameinfowidget.cpp | 6 +++--- 2 files changed, 7 insertions(+), 5 deletions(-) diff --git a/src/creation/creationgameplugins.cpp b/src/creation/creationgameplugins.cpp index 45bedc30..e7153d5f 100644 --- a/src/creation/creationgameplugins.cpp +++ b/src/creation/creationgameplugins.cpp @@ -61,8 +61,10 @@ void CreationGamePlugins::writePluginList(const IPluginList *pluginList, }); QStringList PrimaryPlugins = organizer()->managedGame()->primaryPlugins(); - QSet ManagedMods = PrimaryPlugins.toSet().subtract(organizer()->managedGame()->DLCPlugins().toSet()); - PrimaryPlugins.append(ManagedMods.toList()); + QSet ManagedMods = QSet(PrimaryPlugins.begin(), PrimaryPlugins.end()).subtract( + QSet(organizer()->managedGame()->DLCPlugins().begin(), organizer()->managedGame()->DLCPlugins().begin()) + ); + PrimaryPlugins.append(QList(ManagedMods.begin(), ManagedMods.end())); //TODO: do not write plugins in OFFICIAL_FILES container for (const QString &pluginName : plugins) { diff --git a/src/gamebryo/gamebryosavegameinfowidget.cpp b/src/gamebryo/gamebryosavegameinfowidget.cpp index 85bdee02..57409498 100644 --- a/src/gamebryo/gamebryosavegameinfowidget.cpp +++ b/src/gamebryo/gamebryosavegameinfowidget.cpp @@ -34,7 +34,7 @@ GamebryoSaveGameInfoWidget::GamebryoSaveGameInfoWidget(GamebryoSaveGameInfo cons ui->gameFrame->setStyleSheet("background-color: transparent;"); QVBoxLayout *gameLayout = new QVBoxLayout(); - gameLayout->setMargin(0); + gameLayout->setContentsMargins(0, 0, 0, 0); gameLayout->setSpacing(2); ui->gameFrame->setLayout(gameLayout); } @@ -52,8 +52,8 @@ void GamebryoSaveGameInfoWidget::setSave(MOBase::ISaveGame const& save) { //This somewhat contorted code is because on my system at least, the //old way of doing this appears to give short date and long time. QDateTime t = gamebryoSave.getCreationTime(); - ui->dateLabel->setText(t.date().toString(Qt::DefaultLocaleShortDate) + " " + - t.time().toString(Qt::DefaultLocaleLongDate)); + ui->dateLabel->setText(QLocale::system().toString(t.date(), QLocale::FormatType::ShortFormat) + " " + + QLocale::system().toString(t.time())); ui->screenshotLabel->setPixmap(QPixmap::fromImage(gamebryoSave.getScreenshot())); if (ui->gameFrame->layout() != nullptr) { QLayoutItem *item = nullptr; From a15bc0699288a0f1caa604859232644f81fc9412 Mon Sep 17 00:00:00 2001 From: Jeremy Rimpo Date: Sun, 5 Dec 2021 03:42:45 -0600 Subject: [PATCH 1196/1544] [game_skyrimse] Changes to compile with Qt6 + Boost 1.77 --- src/games/skyrimse/src/gameskyrimse.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/games/skyrimse/src/gameskyrimse.cpp b/src/games/skyrimse/src/gameskyrimse.cpp index c224c537..4caa107b 100644 --- a/src/games/skyrimse/src/gameskyrimse.cpp +++ b/src/games/skyrimse/src/gameskyrimse.cpp @@ -95,7 +95,7 @@ QList GameSkyrimSE::executables() const << ExecutableInfo("Skyrim Special Edition", findInGameFolder(binaryName())) << ExecutableInfo("Skyrim Special Edition Launcher", findInGameFolder(getLauncherName())) << ExecutableInfo("Creation Kit", findInGameFolder("CreationKit.exe")) - << ExecutableInfo("LOOT", getLootPath()).withArgument("--game=\"Skyrim Special Edition\"") + << ExecutableInfo("LOOT", QFileInfo(getLootPath())).withArgument("--game=\"Skyrim Special Edition\"") ; } From 3b614e6ab7e1a6e4ecd04632bf0933d13dcd430d Mon Sep 17 00:00:00 2001 From: Jeremy Rimpo Date: Sun, 5 Dec 2021 03:42:45 -0600 Subject: [PATCH 1197/1544] [game_oblivion] Changes to compile with Qt6 + Boost 1.77 --- src/games/oblivion/src/gameoblivion.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/games/oblivion/src/gameoblivion.cpp b/src/games/oblivion/src/gameoblivion.cpp index 93106af0..26eae0c2 100644 --- a/src/games/oblivion/src/gameoblivion.cpp +++ b/src/games/oblivion/src/gameoblivion.cpp @@ -55,7 +55,7 @@ QList GameOblivion::executables() const << ExecutableInfo("Oblivion Launcher", findInGameFolder(getLauncherName())) << ExecutableInfo("Oblivion Mod Manager", findInGameFolder("OblivionModManager.exe")) << ExecutableInfo("BOSS", findInGameFolder("BOSS/BOSS.exe")) - << ExecutableInfo("LOOT", getLootPath()).withArgument("--game=\"Oblivion\"") + << ExecutableInfo("LOOT", QFileInfo(getLootPath())).withArgument("--game=\"Oblivion\"") << ExecutableInfo("Construction Set", findInGameFolder("TESConstructionSet.exe")) ; } From 7d376a3d52f84fc8341439ee383e9dad44417e05 Mon Sep 17 00:00:00 2001 From: Jeremy Rimpo Date: Sun, 5 Dec 2021 03:42:46 -0600 Subject: [PATCH 1198/1544] [game_skyrimvr] Changes to compile with Qt6 + Boost 1.77 --- src/games/skyrimvr/src/gameskyrimvr.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/games/skyrimvr/src/gameskyrimvr.cpp b/src/games/skyrimvr/src/gameskyrimvr.cpp index 2ca3c245..177f8ece 100644 --- a/src/games/skyrimvr/src/gameskyrimvr.cpp +++ b/src/games/skyrimvr/src/gameskyrimvr.cpp @@ -93,7 +93,7 @@ QList GameSkyrimVR::executables() const << ExecutableInfo("SKSE", findInGameFolder(feature()->loaderName())) << ExecutableInfo("Skyrim VR", findInGameFolder(binaryName())) << ExecutableInfo("Creation Kit", findInGameFolder("CreationKit.exe")) - << ExecutableInfo("LOOT", getLootPath()).withArgument("--game=\"Skyrim VR\"") + << ExecutableInfo("LOOT", QFileInfo(getLootPath())).withArgument("--game=\"Skyrim VR\"") ; } From 215831dd4546933e05e51d9ad4bc221346051fb4 Mon Sep 17 00:00:00 2001 From: Jeremy Rimpo Date: Sun, 5 Dec 2021 03:42:46 -0600 Subject: [PATCH 1199/1544] [game_fallout4] Changes to compile with Qt6 + Boost 1.77 --- src/games/fallout4/src/gamefallout4.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/games/fallout4/src/gamefallout4.cpp b/src/games/fallout4/src/gamefallout4.cpp index ac4f2c21..9db8e661 100644 --- a/src/games/fallout4/src/gamefallout4.cpp +++ b/src/games/fallout4/src/gamefallout4.cpp @@ -68,7 +68,7 @@ QList GameFallout4::executables() const << ExecutableInfo("Fallout 4", findInGameFolder(binaryName())) << ExecutableInfo("Fallout Launcher", findInGameFolder(getLauncherName())) << ExecutableInfo("Creation Kit", findInGameFolder("CreationKit.exe")) - << ExecutableInfo("LOOT", getLootPath()).withArgument("--game=\"Fallout4\"") + << ExecutableInfo("LOOT", QFileInfo(getLootPath())).withArgument("--game=\"Fallout4\"") ; } From 1f23a013c335bb3f5ee4f630206cab6cfcf64af2 Mon Sep 17 00:00:00 2001 From: Jeremy Rimpo Date: Sun, 5 Dec 2021 03:42:47 -0600 Subject: [PATCH 1200/1544] [game_fallout3] Changes to compile with Qt6 + Boost 1.77 --- src/games/fallout3/src/gamefallout3.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/games/fallout3/src/gamefallout3.cpp b/src/games/fallout3/src/gamefallout3.cpp index 16da524f..00d566d5 100644 --- a/src/games/fallout3/src/gamefallout3.cpp +++ b/src/games/fallout3/src/gamefallout3.cpp @@ -68,7 +68,7 @@ QList GameFallout3::executables() const << ExecutableInfo("Construction Kit", findInGameFolder("geck.exe")) << ExecutableInfo("Fallout Launcher", findInGameFolder(getLauncherName())) << ExecutableInfo("BOSS", findInGameFolder("BOSS/BOSS.exe")) - << ExecutableInfo("LOOT", getLootPath()).withArgument("--game=\"Fallout3\"") + << ExecutableInfo("LOOT", QFileInfo(getLootPath())).withArgument("--game=\"Fallout3\"") ; } From acba6cfe4c2c3b94979dcb2edd38587ef6ae782b Mon Sep 17 00:00:00 2001 From: Jeremy Rimpo Date: Sun, 5 Dec 2021 03:42:50 -0600 Subject: [PATCH 1201/1544] [game_skyrim] Changes to compile with Qt6 + Boost 1.77 --- src/games/skyrim/src/gameskyrim.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/games/skyrim/src/gameskyrim.cpp b/src/games/skyrim/src/gameskyrim.cpp index f68c5c40..662c9d24 100644 --- a/src/games/skyrim/src/gameskyrim.cpp +++ b/src/games/skyrim/src/gameskyrim.cpp @@ -67,7 +67,7 @@ QList GameSkyrim::executables() const << ExecutableInfo("Skyrim", findInGameFolder(binaryName())) << ExecutableInfo("Skyrim Launcher", findInGameFolder(getLauncherName())) << ExecutableInfo("BOSS", findInGameFolder("BOSS/BOSS.exe")) - << ExecutableInfo("LOOT", getLootPath()).withArgument("--game=\"Skyrim\"") + << ExecutableInfo("LOOT", QFileInfo(getLootPath())).withArgument("--game=\"Skyrim\"") << ExecutableInfo("Creation Kit", findInGameFolder("CreationKit.exe")).withSteamAppId("202480") ; } From 3fc557fc68fb32b3bbe705b662f3e00e930e27b0 Mon Sep 17 00:00:00 2001 From: Jeremy Rimpo Date: Sun, 5 Dec 2021 03:42:53 -0600 Subject: [PATCH 1202/1544] [game_ttw] Changes to compile with Qt6 + Boost 1.77 --- src/games/ttw/src/gamefalloutttw.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/games/ttw/src/gamefalloutttw.cpp b/src/games/ttw/src/gamefalloutttw.cpp index b32e92c5..cd6b2af0 100644 --- a/src/games/ttw/src/gamefalloutttw.cpp +++ b/src/games/ttw/src/gamefalloutttw.cpp @@ -69,7 +69,7 @@ QList GameFalloutTTW::executables() const << ExecutableInfo("Construction Kit", findInGameFolder("geck.exe")) << ExecutableInfo("Fallout Launcher", findInGameFolder(getLauncherName())) << ExecutableInfo("BOSS", findInGameFolder("BOSS/BOSS.exe")) - << ExecutableInfo("LOOT", getLootPath()).withArgument("--game=\"FalloutNV\"") + << ExecutableInfo("LOOT", QFileInfo(getLootPath())).withArgument("--game=\"FalloutNV\"") ; } From 7c086af126f963ebbc59a05be50bfc5091a536cb Mon Sep 17 00:00:00 2001 From: Jeremy Rimpo Date: Sun, 5 Dec 2021 19:14:58 -0600 Subject: [PATCH 1203/1544] [game_enderalse] Fix iterator --- src/games/enderalse/src/enderalsegameplugins.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/games/enderalse/src/enderalsegameplugins.cpp b/src/games/enderalse/src/enderalsegameplugins.cpp index a7cef538..f516e95c 100644 --- a/src/games/enderalse/src/enderalsegameplugins.cpp +++ b/src/games/enderalse/src/enderalsegameplugins.cpp @@ -29,7 +29,7 @@ void EnderalSEGamePlugins::writePluginList(const MOBase::IPluginList* pluginList QStringList PrimaryPlugins = organizer()->managedGame()->primaryPlugins(); QSet ManagedMods = QSet(PrimaryPlugins.begin(), PrimaryPlugins.end()).subtract( - QSet(organizer()->managedGame()->DLCPlugins().begin(), organizer()->managedGame()->DLCPlugins().begin()) + QSet(organizer()->managedGame()->DLCPlugins().begin(), organizer()->managedGame()->DLCPlugins().end()) ); PrimaryPlugins.append(QList(ManagedMods.begin(), ManagedMods.end())); From 798c0c030058b89ec9dd34144462e8a9f4b7e79e Mon Sep 17 00:00:00 2001 From: Jeremy Rimpo Date: Sun, 5 Dec 2021 19:14:59 -0600 Subject: [PATCH 1204/1544] Fix iterator --- src/creation/creationgameplugins.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/creation/creationgameplugins.cpp b/src/creation/creationgameplugins.cpp index e7153d5f..6f732da8 100644 --- a/src/creation/creationgameplugins.cpp +++ b/src/creation/creationgameplugins.cpp @@ -62,7 +62,7 @@ void CreationGamePlugins::writePluginList(const IPluginList *pluginList, QStringList PrimaryPlugins = organizer()->managedGame()->primaryPlugins(); QSet ManagedMods = QSet(PrimaryPlugins.begin(), PrimaryPlugins.end()).subtract( - QSet(organizer()->managedGame()->DLCPlugins().begin(), organizer()->managedGame()->DLCPlugins().begin()) + QSet(organizer()->managedGame()->DLCPlugins().begin(), organizer()->managedGame()->DLCPlugins().end()) ); PrimaryPlugins.append(QList(ManagedMods.begin(), ManagedMods.end())); From ea414af2d0bbf60cc57832c973162f922b5c6f13 Mon Sep 17 00:00:00 2001 From: Jeremy Rimpo Date: Mon, 6 Dec 2021 10:27:37 -0600 Subject: [PATCH 1205/1544] [game_enderalse] Fix iterator --- src/games/enderalse/src/enderalsegameplugins.cpp | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/src/games/enderalse/src/enderalsegameplugins.cpp b/src/games/enderalse/src/enderalsegameplugins.cpp index f516e95c..7722e75d 100644 --- a/src/games/enderalse/src/enderalsegameplugins.cpp +++ b/src/games/enderalse/src/enderalsegameplugins.cpp @@ -28,9 +28,10 @@ void EnderalSEGamePlugins::writePluginList(const MOBase::IPluginList* pluginList }); QStringList PrimaryPlugins = organizer()->managedGame()->primaryPlugins(); - QSet ManagedMods = QSet(PrimaryPlugins.begin(), PrimaryPlugins.end()).subtract( - QSet(organizer()->managedGame()->DLCPlugins().begin(), organizer()->managedGame()->DLCPlugins().end()) - ); + QStringList DLCPlugins = organizer()->managedGame()->DLCPlugins(); + QSet ManagedMods = QSet(PrimaryPlugins.begin(), PrimaryPlugins.end()); + QSet DLCSet = QSet(DLCPlugins.begin(), DLCPlugins.end()); + ManagedMods.subtract(DLCSet); PrimaryPlugins.append(QList(ManagedMods.begin(), ManagedMods.end())); // we need to force some plugins because those are not force-loaded From 6b69e44064a2d302198c64c27f05a0f2ebec3481 Mon Sep 17 00:00:00 2001 From: Jeremy Rimpo Date: Mon, 6 Dec 2021 10:27:37 -0600 Subject: [PATCH 1206/1544] Fix iterator --- src/creation/creationgameplugins.cpp | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/src/creation/creationgameplugins.cpp b/src/creation/creationgameplugins.cpp index 6f732da8..dce98860 100644 --- a/src/creation/creationgameplugins.cpp +++ b/src/creation/creationgameplugins.cpp @@ -61,9 +61,10 @@ void CreationGamePlugins::writePluginList(const IPluginList *pluginList, }); QStringList PrimaryPlugins = organizer()->managedGame()->primaryPlugins(); - QSet ManagedMods = QSet(PrimaryPlugins.begin(), PrimaryPlugins.end()).subtract( - QSet(organizer()->managedGame()->DLCPlugins().begin(), organizer()->managedGame()->DLCPlugins().end()) - ); + QStringList DLCPlugins = organizer()->managedGame()->DLCPlugins(); + QSet ManagedMods = QSet(PrimaryPlugins.begin(), PrimaryPlugins.end()); + QSet DLCSet = QSet(DLCPlugins.begin(), DLCPlugins.end()); + ManagedMods.subtract(DLCSet); PrimaryPlugins.append(QList(ManagedMods.begin(), ManagedMods.end())); //TODO: do not write plugins in OFFICIAL_FILES container From 610b8fe942c2d533450e43cfc34d483565acd3d1 Mon Sep 17 00:00:00 2001 From: Jeremy Rimpo Date: Mon, 6 Dec 2021 18:54:45 -0600 Subject: [PATCH 1207/1544] [game_morrowind] Remove dependency on Core5Compat --- src/games/morrowind/src/morrowindgameplugins.cpp | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/src/games/morrowind/src/morrowindgameplugins.cpp b/src/games/morrowind/src/morrowindgameplugins.cpp index 81ae28dc..0e8ae771 100644 --- a/src/games/morrowind/src/morrowindgameplugins.cpp +++ b/src/games/morrowind/src/morrowindgameplugins.cpp @@ -9,7 +9,6 @@ #include "registry.h" #include -#include #include #include #include @@ -83,7 +82,7 @@ void MorrowindGamePlugins::writePluginList(const MOBase::IPluginList *pluginList void MorrowindGamePlugins::writeList(const IPluginList *pluginList, const QString &filePath, bool loadOrder) { - QTextCodec *textCodec = loadOrder ? utf8Codec() : localCodec(); + QStringEncoder encoder = loadOrder ? QStringEncoder(QStringConverter::Encoding::Utf8) : QStringEncoder(QStringConverter::Encoding::System); ::WritePrivateProfileSectionW(L"Game Files", NULL, filePath.toStdWString().c_str()); @@ -99,7 +98,8 @@ void MorrowindGamePlugins::writeList(const IPluginList *pluginList, for (const QString &pluginName : plugins) { if (loadOrder || (pluginList->state(pluginName) == IPluginList::STATE_ACTIVE)) { - if (!textCodec->canEncode(pluginName)) { + auto result = encoder.encode(pluginName); + if (encoder.hasError()) { invalidFileNames = true; qCritical("invalid plugin name %s", qUtf8Printable(pluginName)); } else { From c76945280631df543a37dc44842f21631d8b9221 Mon Sep 17 00:00:00 2001 From: Jeremy Rimpo Date: Mon, 6 Dec 2021 18:54:45 -0600 Subject: [PATCH 1208/1544] [game_enderalse] Remove dependency on Core5Compat --- src/games/enderalse/src/enderalsegameplugins.cpp | 14 ++++++++------ 1 file changed, 8 insertions(+), 6 deletions(-) diff --git a/src/games/enderalse/src/enderalsegameplugins.cpp b/src/games/enderalse/src/enderalsegameplugins.cpp index 7722e75d..de8a377c 100644 --- a/src/games/enderalse/src/enderalsegameplugins.cpp +++ b/src/games/enderalse/src/enderalsegameplugins.cpp @@ -11,11 +11,11 @@ void EnderalSEGamePlugins::writePluginList(const MOBase::IPluginList* pluginList { SafeWriteFile file(filePath); - QTextCodec* textCodec = localCodec(); + QStringEncoder encoder(QStringConverter::Encoding::System); file->resize(0); - file->write(textCodec->fromUnicode( + file->write(encoder.encode( "# This file was automatically generated by Mod Organizer.\r\n")); bool invalidFileNames = false; @@ -43,14 +43,15 @@ void EnderalSEGamePlugins::writePluginList(const MOBase::IPluginList* pluginList for (const QString& pluginName : plugins) { if (!PrimaryPlugins.contains(pluginName, Qt::CaseInsensitive)) { if (pluginList->state(pluginName) == IPluginList::STATE_ACTIVE) { - if (!textCodec->canEncode(pluginName)) { + auto result = encoder.encode(pluginName); + if (encoder.hasError()) { invalidFileNames = true; qCritical("invalid plugin name %s", qUtf8Printable(pluginName)); } else { file->write("*"); - file->write(textCodec->fromUnicode(pluginName)); + file->write(result); } file->write("\r\n"); @@ -58,13 +59,14 @@ void EnderalSEGamePlugins::writePluginList(const MOBase::IPluginList* pluginList } else { - if (!textCodec->canEncode(pluginName)) { + auto result = encoder.encode(pluginName); + if (encoder.hasError()) { invalidFileNames = true; qCritical("invalid plugin name %s", qUtf8Printable(pluginName)); } else { - file->write(textCodec->fromUnicode(pluginName)); + file->write(result); } file->write("\r\n"); ++writtenCount; From 8d7f00cdafcd2b41ae63ae17319164e0c8bf6ca5 Mon Sep 17 00:00:00 2001 From: Jeremy Rimpo Date: Mon, 6 Dec 2021 18:54:46 -0600 Subject: [PATCH 1209/1544] Remove dependency on Core5Compat --- src/creation/creationgameplugins.cpp | 17 +++++++++-------- src/gamebryo/gamebryogameplugins.cpp | 19 +++++++++---------- src/gamebryo/gamebryogameplugins.h | 7 ------- 3 files changed, 18 insertions(+), 25 deletions(-) diff --git a/src/creation/creationgameplugins.cpp b/src/creation/creationgameplugins.cpp index dce98860..2c7f4f34 100644 --- a/src/creation/creationgameplugins.cpp +++ b/src/creation/creationgameplugins.cpp @@ -6,7 +6,6 @@ #include #include -#include #include #include @@ -44,11 +43,11 @@ void CreationGamePlugins::writePluginList(const IPluginList *pluginList, const QString &filePath) { SafeWriteFile file(filePath); - QTextCodec *textCodec = localCodec(); + QStringEncoder encoder(QStringConverter::Encoding::System); file->resize(0); - file->write(textCodec->fromUnicode( + file->write(encoder.encode( "# This file was automatically generated by Mod Organizer.\r\n")); bool invalidFileNames = false; @@ -71,14 +70,15 @@ void CreationGamePlugins::writePluginList(const IPluginList *pluginList, for (const QString &pluginName : plugins) { if (!PrimaryPlugins.contains(pluginName,Qt::CaseInsensitive)) { if (pluginList->state(pluginName) == IPluginList::STATE_ACTIVE) { - if (!textCodec->canEncode(pluginName)) { + auto result = encoder.encode(pluginName); + if (encoder.hasError()) { invalidFileNames = true; qCritical("invalid plugin name %s", qUtf8Printable(pluginName)); } else { file->write("*"); - file->write(textCodec->fromUnicode(pluginName)); + file->write(result); } file->write("\r\n"); @@ -86,13 +86,14 @@ void CreationGamePlugins::writePluginList(const IPluginList *pluginList, } else { - if (!textCodec->canEncode(pluginName)) { + auto result = encoder.encode(pluginName); + if (encoder.hasError()) { invalidFileNames = true; qCritical("invalid plugin name %s", qUtf8Printable(pluginName)); } else { - file->write(textCodec->fromUnicode(pluginName)); + file->write(result); } file->write("\r\n"); ++writtenCount; @@ -142,7 +143,7 @@ QStringList CreationGamePlugins::readPluginList(MOBase::IPluginList *pluginList) QByteArray line = file.readLine(); QString pluginName; if ((line.size() > 0) && (line.at(0) != '#')) { - pluginName = localCodec()->toUnicode(line.trimmed().constData()); + pluginName = QStringEncoder(QStringConverter::Encoding::System).encode(line.trimmed().constData()); } if (!primaryPlugins.contains(pluginName, Qt::CaseInsensitive)) { if (pluginName.startsWith('*')) { diff --git a/src/gamebryo/gamebryogameplugins.cpp b/src/gamebryo/gamebryogameplugins.cpp index 3c116a05..ead565ad 100644 --- a/src/gamebryo/gamebryogameplugins.cpp +++ b/src/gamebryo/gamebryogameplugins.cpp @@ -8,7 +8,6 @@ #include #include -#include #include #include #include @@ -19,10 +18,7 @@ using MOBase::SafeWriteFile; using MOBase::reportError; GamebryoGamePlugins::GamebryoGamePlugins(IOrganizer *organizer) - : m_Organizer(organizer) { - m_Utf8Codec = QTextCodec::codecForName("utf-8"); - m_LocalCodec = QTextCodec::codecForName("Windows-1252"); -} + : m_Organizer(organizer) {} void GamebryoGamePlugins::writePluginLists(const IPluginList *pluginList) { if (!m_LastRead.isValid()) { @@ -95,11 +91,12 @@ void GamebryoGamePlugins::writeList(const IPluginList *pluginList, const QString &filePath, bool loadOrder) { SafeWriteFile file(filePath); - QTextCodec *textCodec = loadOrder ? utf8Codec() : localCodec(); + QStringEncoder encoder = loadOrder ? QStringEncoder(QStringConverter::Encoding::Utf8) + : QStringEncoder(QStringConverter::Encoding::System); file->resize(0); - file->write(textCodec->fromUnicode( + file->write(encoder.encode( "# This file was automatically generated by Mod Organizer.\r\n")); bool invalidFileNames = false; @@ -114,11 +111,12 @@ void GamebryoGamePlugins::writeList(const IPluginList *pluginList, for (const QString &pluginName : plugins) { if (loadOrder || (pluginList->state(pluginName) == IPluginList::STATE_ACTIVE)) { - if (!textCodec->canEncode(pluginName)) { + auto result = encoder.encode(pluginName); + if (encoder.hasError()) { invalidFileNames = true; qCritical("invalid plugin name %s", qUtf8Printable(pluginName)); } else { - file->write(textCodec->fromUnicode(pluginName)); + file->write(result); } file->write("\r\n"); ++writtenCount; @@ -219,7 +217,8 @@ QStringList GamebryoGamePlugins::readPluginList(MOBase::IPluginList *pluginList) QByteArray line = file.readLine(); QString pluginName; if ((line.size() > 0) && (line.at(0) != '#')) { - pluginName = m_LocalCodec->toUnicode(line.trimmed().constData()); + QStringEncoder encoder(QStringConverter::Encoding::System); + pluginName = encoder.encode(line.trimmed().constData()); } if (pluginName.size() > 0) { pluginList->setState(pluginName, IPluginList::STATE_ACTIVE); diff --git a/src/gamebryo/gamebryogameplugins.h b/src/gamebryo/gamebryogameplugins.h index b97c5e00..58628d9b 100644 --- a/src/gamebryo/gamebryogameplugins.h +++ b/src/gamebryo/gamebryogameplugins.h @@ -4,7 +4,6 @@ #include #include -#include #include #include @@ -18,9 +17,6 @@ public: virtual bool lightPluginsAreSupported() override; protected: - QTextCodec *utf8Codec() const { return m_Utf8Codec; } - QTextCodec *localCodec() const { return m_LocalCodec; } - MOBase::IOrganizer *organizer() const { return m_Organizer; } virtual void writePluginList(const MOBase::IPluginList *pluginList, @@ -40,9 +36,6 @@ private: bool loadOrder); private: - QTextCodec *m_Utf8Codec; - QTextCodec *m_LocalCodec; - std::map m_LastSaveHash; }; From d945ba0a596727a71c416ef2ce91a2cc18ab83c2 Mon Sep 17 00:00:00 2001 From: Jeremy Rimpo Date: Mon, 6 Dec 2021 18:54:47 -0600 Subject: [PATCH 1210/1544] [game_skyrim] Remove dependency on Core5Compat --- src/games/skyrim/src/skyrimgameplugins.cpp | 7 ++----- src/games/skyrim/src/skyrimgameplugins.h | 3 --- 2 files changed, 2 insertions(+), 8 deletions(-) diff --git a/src/games/skyrim/src/skyrimgameplugins.cpp b/src/games/skyrim/src/skyrimgameplugins.cpp index 0b9ce583..524132e3 100644 --- a/src/games/skyrim/src/skyrimgameplugins.cpp +++ b/src/games/skyrim/src/skyrimgameplugins.cpp @@ -6,7 +6,6 @@ #include #include -#include #include @@ -18,9 +17,7 @@ using MOBase::reportError; SkyrimGamePlugins::SkyrimGamePlugins(IOrganizer *organizer) : GamebryoGamePlugins(organizer) -{ - m_LocalCodec = QTextCodec::codecForName("Windows-1252"); -} +{} void SkyrimGamePlugins::readPluginLists(MOBase::IPluginList *pluginList) { QString loadOrderPath = @@ -97,7 +94,7 @@ QStringList SkyrimGamePlugins::readPluginList(MOBase::IPluginList *pluginList) QByteArray line = file.readLine(); QString pluginName; if ((line.size() > 0) && (line.at(0) != '#')) { - pluginName = m_LocalCodec->toUnicode(line.trimmed().constData()); + pluginName = QStringEncoder(QStringConverter::Encoding::System).encode(line.trimmed().constData()); } if (pluginName.size() > 0) { pluginList->setState(pluginName, IPluginList::STATE_ACTIVE); diff --git a/src/games/skyrim/src/skyrimgameplugins.h b/src/games/skyrim/src/skyrimgameplugins.h index e61c1667..6fbdac91 100644 --- a/src/games/skyrim/src/skyrimgameplugins.h +++ b/src/games/skyrim/src/skyrimgameplugins.h @@ -20,9 +20,6 @@ protected: private: std::map m_LastSaveHash; - -private: - QTextCodec *m_LocalCodec; }; #endif // _SKYRIMSEGAMEPLUGINS_H From d7eeffec9bbaf26b99d2935af485e8331de9fde8 Mon Sep 17 00:00:00 2001 From: Jeremy Rimpo Date: Fri, 10 Dec 2021 09:30:14 -0600 Subject: [PATCH 1211/1544] [game_fallout4vr] Include gamebryo string in translations --- src/games/fallout4vr/src/CMakeLists.txt | 3 + .../fallout4vr/src/game_fallout4vr_en.ts | 161 ++++++++++++++++++ 2 files changed, 164 insertions(+) diff --git a/src/games/fallout4vr/src/CMakeLists.txt b/src/games/fallout4vr/src/CMakeLists.txt index 3b4e7319..c6059ae1 100644 --- a/src/games/fallout4vr/src/CMakeLists.txt +++ b/src/games/fallout4vr/src/CMakeLists.txt @@ -1,4 +1,7 @@ cmake_minimum_required(VERSION 3.16) + +set(additional_translations ${modorganizer_super_path}/game_gamebryo/src) + if(DEFINED DEPENDENCIES_DIR) include(${DEPENDENCIES_DIR}/modorganizer_super/cmake_common/src.cmake) else() diff --git a/src/games/fallout4vr/src/game_fallout4vr_en.ts b/src/games/fallout4vr/src/game_fallout4vr_en.ts index 6823bb92..066ae77f 100644 --- a/src/games/fallout4vr/src/game_fallout4vr_en.ts +++ b/src/games/fallout4vr/src/game_fallout4vr_en.ts @@ -15,4 +15,165 @@ Splash by %1 + + GamebryoModDataContent + + + Plugins (ESP/ESM/ESL) + + + + + Optional Plugins + + + + + Interface + + + + + Meshes + + + + + Bethesda Archive + + + + + Scripts (Papyrus) + + + + + Script Extender Plugin + + + + + Script Extender Files + + + + + SkyProc Patcher + + + + + Sound or Music + + + + + Textures + + + + + MCM Configuration + + + + + INI Files + + + + + FaceGen Data + + + + + ModGroup Files + + + + + GamebryoSaveGameInfoWidget + + + Save # + + + + + Character + + + + + Level + + + + + Location + + + + + Date + + + + + Has Script Extender Data + + + + + Missing ESPs + + + + + + None + + + + + Missing ESLs + + + + + QObject + + + + Some of your plugins have invalid names! These plugins can not be loaded by the game. Please see mo_interface.log for a list of affected plugins and rename them. + + + + + %1, #%2, Level %3, %4 + + + + + failed to open %1 + + + + + wrong file format - expected %1 got %2 + + + + + failed to query registry path (preflight): %1 + + + + + failed to query registry path (read): %1 + + + From 584f59a0a47927cd68f5be3118672ac05fd72851 Mon Sep 17 00:00:00 2001 From: Jeremy Rimpo Date: Fri, 10 Dec 2021 09:30:15 -0600 Subject: [PATCH 1212/1544] [game_falloutnv] Include gamebryo string in translations --- src/games/falloutnv/src/CMakeLists.txt | 3 + src/games/falloutnv/src/game_falloutNV_en.ts | 161 +++++++++++++++++++ 2 files changed, 164 insertions(+) diff --git a/src/games/falloutnv/src/CMakeLists.txt b/src/games/falloutnv/src/CMakeLists.txt index e17b5e89..3abb9467 100644 --- a/src/games/falloutnv/src/CMakeLists.txt +++ b/src/games/falloutnv/src/CMakeLists.txt @@ -1,4 +1,7 @@ cmake_minimum_required(VERSION 3.16) + +set(additional_translations ${modorganizer_super_path}/game_gamebryo/src) + if(DEFINED DEPENDENCIES_DIR) include(${DEPENDENCIES_DIR}/modorganizer_super/cmake_common/src.cmake) else() diff --git a/src/games/falloutnv/src/game_falloutNV_en.ts b/src/games/falloutnv/src/game_falloutNV_en.ts index 866720f0..f517b2db 100644 --- a/src/games/falloutnv/src/game_falloutNV_en.ts +++ b/src/games/falloutnv/src/game_falloutNV_en.ts @@ -14,4 +14,165 @@ + + GamebryoModDataContent + + + Plugins (ESP/ESM/ESL) + + + + + Optional Plugins + + + + + Interface + + + + + Meshes + + + + + Bethesda Archive + + + + + Scripts (Papyrus) + + + + + Script Extender Plugin + + + + + Script Extender Files + + + + + SkyProc Patcher + + + + + Sound or Music + + + + + Textures + + + + + MCM Configuration + + + + + INI Files + + + + + FaceGen Data + + + + + ModGroup Files + + + + + GamebryoSaveGameInfoWidget + + + Save # + + + + + Character + + + + + Level + + + + + Location + + + + + Date + + + + + Has Script Extender Data + + + + + Missing ESPs + + + + + + None + + + + + Missing ESLs + + + + + QObject + + + + Some of your plugins have invalid names! These plugins can not be loaded by the game. Please see mo_interface.log for a list of affected plugins and rename them. + + + + + %1, #%2, Level %3, %4 + + + + + failed to open %1 + + + + + wrong file format - expected %1 got %2 + + + + + failed to query registry path (preflight): %1 + + + + + failed to query registry path (read): %1 + + + From f91b63bf2feeb05d0d4ad087eea4ff64792454e9 Mon Sep 17 00:00:00 2001 From: Jeremy Rimpo Date: Fri, 10 Dec 2021 09:30:15 -0600 Subject: [PATCH 1213/1544] [game_morrowind] Include gamebryo string in translations --- src/games/morrowind/src/CMakeLists.txt | 3 + src/games/morrowind/src/game_morrowind_en.ts | 154 +++++++++++++++++++ 2 files changed, 157 insertions(+) diff --git a/src/games/morrowind/src/CMakeLists.txt b/src/games/morrowind/src/CMakeLists.txt index 1f12c529..d1fed507 100644 --- a/src/games/morrowind/src/CMakeLists.txt +++ b/src/games/morrowind/src/CMakeLists.txt @@ -1,4 +1,7 @@ cmake_minimum_required(VERSION 3.16) + +set(additional_translations ${modorganizer_super_path}/game_gamebryo/src) + if(DEFINED DEPENDENCIES_DIR) include(${DEPENDENCIES_DIR}/modorganizer_super/cmake_common/src.cmake) else() diff --git a/src/games/morrowind/src/game_morrowind_en.ts b/src/games/morrowind/src/game_morrowind_en.ts index 4b1afd58..65f7a2eb 100644 --- a/src/games/morrowind/src/game_morrowind_en.ts +++ b/src/games/morrowind/src/game_morrowind_en.ts @@ -15,6 +15,133 @@ Splash by %1 + + GamebryoModDataContent + + + Plugins (ESP/ESM/ESL) + + + + + Optional Plugins + + + + + Interface + + + + + Meshes + + + + + Bethesda Archive + + + + + Scripts (Papyrus) + + + + + Script Extender Plugin + + + + + Script Extender Files + + + + + SkyProc Patcher + + + + + Sound or Music + + + + + Textures + + + + + MCM Configuration + + + + + INI Files + + + + + FaceGen Data + + + + + ModGroup Files + + + + + GamebryoSaveGameInfoWidget + + + Save # + + + + + Character + + + + + Level + + + + + Location + + + + + Date + + + + + Has Script Extender Data + + + + + Missing ESPs + + + + + + None + + + + + Missing ESLs + + + MorrowindSaveGameInfoWidget @@ -62,8 +189,35 @@ Splash by %1 QObject + + Some of your plugins have invalid names! These plugins can not be loaded by the game. Please see mo_interface.log for a list of affected plugins and rename them. + + + %1, #%2, Level %3, %4 + + + + + failed to open %1 + + + + + wrong file format - expected %1 got %2 + + + + + failed to query registry path (preflight): %1 + + + + + failed to query registry path (read): %1 + + From 1d1684bc2fb56f588e7a6e491c0fa1c4e741e633 Mon Sep 17 00:00:00 2001 From: Jeremy Rimpo Date: Fri, 10 Dec 2021 09:30:16 -0600 Subject: [PATCH 1214/1544] [game_enderalse] Include gamebryo string in translations --- src/games/enderalse/src/CMakeLists.txt | 3 + src/games/enderalse/src/game_enderalse_en.ts | 156 ++++++++++++++++++- 2 files changed, 158 insertions(+), 1 deletion(-) diff --git a/src/games/enderalse/src/CMakeLists.txt b/src/games/enderalse/src/CMakeLists.txt index 1f12c529..d1fed507 100644 --- a/src/games/enderalse/src/CMakeLists.txt +++ b/src/games/enderalse/src/CMakeLists.txt @@ -1,4 +1,7 @@ cmake_minimum_required(VERSION 3.16) + +set(additional_translations ${modorganizer_super_path}/game_gamebryo/src) + if(DEFINED DEPENDENCIES_DIR) include(${DEPENDENCIES_DIR}/modorganizer_super/cmake_common/src.cmake) else() diff --git a/src/games/enderalse/src/game_enderalse_en.ts b/src/games/enderalse/src/game_enderalse_en.ts index 258d293e..db0ba6ef 100644 --- a/src/games/enderalse/src/game_enderalse_en.ts +++ b/src/games/enderalse/src/game_enderalse_en.ts @@ -14,12 +14,166 @@ + + GamebryoModDataContent + + + Plugins (ESP/ESM/ESL) + + + + + Optional Plugins + + + + + Interface + + + + + Meshes + + + + + Bethesda Archive + + + + + Scripts (Papyrus) + + + + + Script Extender Plugin + + + + + Script Extender Files + + + + + SkyProc Patcher + + + + + Sound or Music + + + + + Textures + + + + + MCM Configuration + + + + + INI Files + + + + + FaceGen Data + + + + + ModGroup Files + + + + + GamebryoSaveGameInfoWidget + + + Save # + + + + + Character + + + + + Level + + + + + Location + + + + + Date + + + + + Has Script Extender Data + + + + + Missing ESPs + + + + + + None + + + + + Missing ESLs + + + QObject - + + + Some of your plugins have invalid names! These plugins can not be loaded by the game. Please see mo_interface.log for a list of affected plugins and rename them. + + + %1, #%2, Level %3, %4 + + + + + failed to open %1 + + + + + wrong file format - expected %1 got %2 + + + + + failed to query registry path (preflight): %1 + + + + + failed to query registry path (read): %1 + + From b14d07683dc6cbac65977aaf99fc0e911cd43862 Mon Sep 17 00:00:00 2001 From: Jeremy Rimpo Date: Fri, 10 Dec 2021 09:30:16 -0600 Subject: [PATCH 1215/1544] [game_skyrimse] Include gamebryo string in translations --- src/games/skyrimse/src/CMakeLists.txt | 3 + src/games/skyrimse/src/game_skyrimse_en.ts | 161 +++++++++++++++++++++ 2 files changed, 164 insertions(+) diff --git a/src/games/skyrimse/src/CMakeLists.txt b/src/games/skyrimse/src/CMakeLists.txt index 1f12c529..d1fed507 100644 --- a/src/games/skyrimse/src/CMakeLists.txt +++ b/src/games/skyrimse/src/CMakeLists.txt @@ -1,4 +1,7 @@ cmake_minimum_required(VERSION 3.16) + +set(additional_translations ${modorganizer_super_path}/game_gamebryo/src) + if(DEFINED DEPENDENCIES_DIR) include(${DEPENDENCIES_DIR}/modorganizer_super/cmake_common/src.cmake) else() diff --git a/src/games/skyrimse/src/game_skyrimse_en.ts b/src/games/skyrimse/src/game_skyrimse_en.ts index d7f078f7..dcf4b5c6 100644 --- a/src/games/skyrimse/src/game_skyrimse_en.ts +++ b/src/games/skyrimse/src/game_skyrimse_en.ts @@ -14,4 +14,165 @@ + + GamebryoModDataContent + + + Plugins (ESP/ESM/ESL) + + + + + Optional Plugins + + + + + Interface + + + + + Meshes + + + + + Bethesda Archive + + + + + Scripts (Papyrus) + + + + + Script Extender Plugin + + + + + Script Extender Files + + + + + SkyProc Patcher + + + + + Sound or Music + + + + + Textures + + + + + MCM Configuration + + + + + INI Files + + + + + FaceGen Data + + + + + ModGroup Files + + + + + GamebryoSaveGameInfoWidget + + + Save # + + + + + Character + + + + + Level + + + + + Location + + + + + Date + + + + + Has Script Extender Data + + + + + Missing ESPs + + + + + + None + + + + + Missing ESLs + + + + + QObject + + + + Some of your plugins have invalid names! These plugins can not be loaded by the game. Please see mo_interface.log for a list of affected plugins and rename them. + + + + + %1, #%2, Level %3, %4 + + + + + failed to open %1 + + + + + wrong file format - expected %1 got %2 + + + + + failed to query registry path (preflight): %1 + + + + + failed to query registry path (read): %1 + + + From 78db2dafa4a6180e04e02bd5a375b48553bc98b7 Mon Sep 17 00:00:00 2001 From: Jeremy Rimpo Date: Fri, 10 Dec 2021 09:30:16 -0600 Subject: [PATCH 1216/1544] [game_skyrimvr] Include gamebryo string in translations --- src/games/skyrimvr/src/CMakeLists.txt | 3 + src/games/skyrimvr/src/game_skyrimvr_en.ts | 161 +++++++++++++++++++++ 2 files changed, 164 insertions(+) diff --git a/src/games/skyrimvr/src/CMakeLists.txt b/src/games/skyrimvr/src/CMakeLists.txt index 1f12c529..d1fed507 100644 --- a/src/games/skyrimvr/src/CMakeLists.txt +++ b/src/games/skyrimvr/src/CMakeLists.txt @@ -1,4 +1,7 @@ cmake_minimum_required(VERSION 3.16) + +set(additional_translations ${modorganizer_super_path}/game_gamebryo/src) + if(DEFINED DEPENDENCIES_DIR) include(${DEPENDENCIES_DIR}/modorganizer_super/cmake_common/src.cmake) else() diff --git a/src/games/skyrimvr/src/game_skyrimvr_en.ts b/src/games/skyrimvr/src/game_skyrimvr_en.ts index ecc3f2a7..cdffe986 100644 --- a/src/games/skyrimvr/src/game_skyrimvr_en.ts +++ b/src/games/skyrimvr/src/game_skyrimvr_en.ts @@ -14,4 +14,165 @@ + + GamebryoModDataContent + + + Plugins (ESP/ESM/ESL) + + + + + Optional Plugins + + + + + Interface + + + + + Meshes + + + + + Bethesda Archive + + + + + Scripts (Papyrus) + + + + + Script Extender Plugin + + + + + Script Extender Files + + + + + SkyProc Patcher + + + + + Sound or Music + + + + + Textures + + + + + MCM Configuration + + + + + INI Files + + + + + FaceGen Data + + + + + ModGroup Files + + + + + GamebryoSaveGameInfoWidget + + + Save # + + + + + Character + + + + + Level + + + + + Location + + + + + Date + + + + + Has Script Extender Data + + + + + Missing ESPs + + + + + + None + + + + + Missing ESLs + + + + + QObject + + + + Some of your plugins have invalid names! These plugins can not be loaded by the game. Please see mo_interface.log for a list of affected plugins and rename them. + + + + + %1, #%2, Level %3, %4 + + + + + failed to open %1 + + + + + wrong file format - expected %1 got %2 + + + + + failed to query registry path (preflight): %1 + + + + + failed to query registry path (read): %1 + + + From 7e7eb75a39c11ee4c912a261c0a24a57178cd758 Mon Sep 17 00:00:00 2001 From: Jeremy Rimpo Date: Fri, 10 Dec 2021 09:30:17 -0600 Subject: [PATCH 1217/1544] [game_fallout4] Include gamebryo string in translations --- src/games/fallout4/src/CMakeLists.txt | 3 + src/games/fallout4/src/game_fallout4_en.ts | 161 +++++++++++++++++++++ 2 files changed, 164 insertions(+) diff --git a/src/games/fallout4/src/CMakeLists.txt b/src/games/fallout4/src/CMakeLists.txt index 3b4e7319..c6059ae1 100644 --- a/src/games/fallout4/src/CMakeLists.txt +++ b/src/games/fallout4/src/CMakeLists.txt @@ -1,4 +1,7 @@ cmake_minimum_required(VERSION 3.16) + +set(additional_translations ${modorganizer_super_path}/game_gamebryo/src) + if(DEFINED DEPENDENCIES_DIR) include(${DEPENDENCIES_DIR}/modorganizer_super/cmake_common/src.cmake) else() diff --git a/src/games/fallout4/src/game_fallout4_en.ts b/src/games/fallout4/src/game_fallout4_en.ts index 08d66493..382f10fb 100644 --- a/src/games/fallout4/src/game_fallout4_en.ts +++ b/src/games/fallout4/src/game_fallout4_en.ts @@ -15,4 +15,165 @@ Splash by %1 + + GamebryoModDataContent + + + Plugins (ESP/ESM/ESL) + + + + + Optional Plugins + + + + + Interface + + + + + Meshes + + + + + Bethesda Archive + + + + + Scripts (Papyrus) + + + + + Script Extender Plugin + + + + + Script Extender Files + + + + + SkyProc Patcher + + + + + Sound or Music + + + + + Textures + + + + + MCM Configuration + + + + + INI Files + + + + + FaceGen Data + + + + + ModGroup Files + + + + + GamebryoSaveGameInfoWidget + + + Save # + + + + + Character + + + + + Level + + + + + Location + + + + + Date + + + + + Has Script Extender Data + + + + + Missing ESPs + + + + + + None + + + + + Missing ESLs + + + + + QObject + + + + Some of your plugins have invalid names! These plugins can not be loaded by the game. Please see mo_interface.log for a list of affected plugins and rename them. + + + + + %1, #%2, Level %3, %4 + + + + + failed to open %1 + + + + + wrong file format - expected %1 got %2 + + + + + failed to query registry path (preflight): %1 + + + + + failed to query registry path (read): %1 + + + From 5d995335280f7781d5508cbc3c0114b0efa66dfa Mon Sep 17 00:00:00 2001 From: Jeremy Rimpo Date: Fri, 10 Dec 2021 09:30:17 -0600 Subject: [PATCH 1218/1544] [game_fallout3] Include gamebryo string in translations --- src/games/fallout3/src/CMakeLists.txt | 3 + src/games/fallout3/src/game_fallout3_en.ts | 161 +++++++++++++++++++++ 2 files changed, 164 insertions(+) diff --git a/src/games/fallout3/src/CMakeLists.txt b/src/games/fallout3/src/CMakeLists.txt index 3b4e7319..c6059ae1 100644 --- a/src/games/fallout3/src/CMakeLists.txt +++ b/src/games/fallout3/src/CMakeLists.txt @@ -1,4 +1,7 @@ cmake_minimum_required(VERSION 3.16) + +set(additional_translations ${modorganizer_super_path}/game_gamebryo/src) + if(DEFINED DEPENDENCIES_DIR) include(${DEPENDENCIES_DIR}/modorganizer_super/cmake_common/src.cmake) else() diff --git a/src/games/fallout3/src/game_fallout3_en.ts b/src/games/fallout3/src/game_fallout3_en.ts index e931d28c..3b92898f 100644 --- a/src/games/fallout3/src/game_fallout3_en.ts +++ b/src/games/fallout3/src/game_fallout3_en.ts @@ -14,4 +14,165 @@ + + GamebryoModDataContent + + + Plugins (ESP/ESM/ESL) + + + + + Optional Plugins + + + + + Interface + + + + + Meshes + + + + + Bethesda Archive + + + + + Scripts (Papyrus) + + + + + Script Extender Plugin + + + + + Script Extender Files + + + + + SkyProc Patcher + + + + + Sound or Music + + + + + Textures + + + + + MCM Configuration + + + + + INI Files + + + + + FaceGen Data + + + + + ModGroup Files + + + + + GamebryoSaveGameInfoWidget + + + Save # + + + + + Character + + + + + Level + + + + + Location + + + + + Date + + + + + Has Script Extender Data + + + + + Missing ESPs + + + + + + None + + + + + Missing ESLs + + + + + QObject + + + + Some of your plugins have invalid names! These plugins can not be loaded by the game. Please see mo_interface.log for a list of affected plugins and rename them. + + + + + %1, #%2, Level %3, %4 + + + + + failed to open %1 + + + + + wrong file format - expected %1 got %2 + + + + + failed to query registry path (preflight): %1 + + + + + failed to query registry path (read): %1 + + + From fa30fb5c96005d83488b5d39a0e19e8207a60022 Mon Sep 17 00:00:00 2001 From: Jeremy Rimpo Date: Fri, 10 Dec 2021 09:30:18 -0600 Subject: [PATCH 1219/1544] [game_oblivion] Include gamebryo string in translations --- src/games/oblivion/src/CMakeLists.txt | 3 + src/games/oblivion/src/game_oblivion_en.ts | 161 +++++++++++++++++++++ 2 files changed, 164 insertions(+) diff --git a/src/games/oblivion/src/CMakeLists.txt b/src/games/oblivion/src/CMakeLists.txt index 1f12c529..d1fed507 100644 --- a/src/games/oblivion/src/CMakeLists.txt +++ b/src/games/oblivion/src/CMakeLists.txt @@ -1,4 +1,7 @@ cmake_minimum_required(VERSION 3.16) + +set(additional_translations ${modorganizer_super_path}/game_gamebryo/src) + if(DEFINED DEPENDENCIES_DIR) include(${DEPENDENCIES_DIR}/modorganizer_super/cmake_common/src.cmake) else() diff --git a/src/games/oblivion/src/game_oblivion_en.ts b/src/games/oblivion/src/game_oblivion_en.ts index 20bf34e4..1146a0bb 100644 --- a/src/games/oblivion/src/game_oblivion_en.ts +++ b/src/games/oblivion/src/game_oblivion_en.ts @@ -14,4 +14,165 @@ + + GamebryoModDataContent + + + Plugins (ESP/ESM/ESL) + + + + + Optional Plugins + + + + + Interface + + + + + Meshes + + + + + Bethesda Archive + + + + + Scripts (Papyrus) + + + + + Script Extender Plugin + + + + + Script Extender Files + + + + + SkyProc Patcher + + + + + Sound or Music + + + + + Textures + + + + + MCM Configuration + + + + + INI Files + + + + + FaceGen Data + + + + + ModGroup Files + + + + + GamebryoSaveGameInfoWidget + + + Save # + + + + + Character + + + + + Level + + + + + Location + + + + + Date + + + + + Has Script Extender Data + + + + + Missing ESPs + + + + + + None + + + + + Missing ESLs + + + + + QObject + + + + Some of your plugins have invalid names! These plugins can not be loaded by the game. Please see mo_interface.log for a list of affected plugins and rename them. + + + + + %1, #%2, Level %3, %4 + + + + + failed to open %1 + + + + + wrong file format - expected %1 got %2 + + + + + failed to query registry path (preflight): %1 + + + + + failed to query registry path (read): %1 + + + From 5e5b1d4f92b0c7f4956a935a0244c9de90049466 Mon Sep 17 00:00:00 2001 From: Jeremy Rimpo Date: Fri, 10 Dec 2021 09:30:19 -0600 Subject: [PATCH 1220/1544] [game_skyrim] Include gamebryo string in translations --- src/games/skyrim/src/CMakeLists.txt | 3 + src/games/skyrim/src/game_skyrim_en.ts | 161 +++++++++++++++++++++++++ 2 files changed, 164 insertions(+) diff --git a/src/games/skyrim/src/CMakeLists.txt b/src/games/skyrim/src/CMakeLists.txt index 1f12c529..d1fed507 100644 --- a/src/games/skyrim/src/CMakeLists.txt +++ b/src/games/skyrim/src/CMakeLists.txt @@ -1,4 +1,7 @@ cmake_minimum_required(VERSION 3.16) + +set(additional_translations ${modorganizer_super_path}/game_gamebryo/src) + if(DEFINED DEPENDENCIES_DIR) include(${DEPENDENCIES_DIR}/modorganizer_super/cmake_common/src.cmake) else() diff --git a/src/games/skyrim/src/game_skyrim_en.ts b/src/games/skyrim/src/game_skyrim_en.ts index 6a04abbd..315e0547 100644 --- a/src/games/skyrim/src/game_skyrim_en.ts +++ b/src/games/skyrim/src/game_skyrim_en.ts @@ -14,4 +14,165 @@ + + GamebryoModDataContent + + + Plugins (ESP/ESM/ESL) + + + + + Optional Plugins + + + + + Interface + + + + + Meshes + + + + + Bethesda Archive + + + + + Scripts (Papyrus) + + + + + Script Extender Plugin + + + + + Script Extender Files + + + + + SkyProc Patcher + + + + + Sound or Music + + + + + Textures + + + + + MCM Configuration + + + + + INI Files + + + + + FaceGen Data + + + + + ModGroup Files + + + + + GamebryoSaveGameInfoWidget + + + Save # + + + + + Character + + + + + Level + + + + + Location + + + + + Date + + + + + Has Script Extender Data + + + + + Missing ESPs + + + + + + None + + + + + Missing ESLs + + + + + QObject + + + + Some of your plugins have invalid names! These plugins can not be loaded by the game. Please see mo_interface.log for a list of affected plugins and rename them. + + + + + %1, #%2, Level %3, %4 + + + + + failed to open %1 + + + + + wrong file format - expected %1 got %2 + + + + + failed to query registry path (preflight): %1 + + + + + failed to query registry path (read): %1 + + + From c08791e958b7155504d59160478714845a980fdb Mon Sep 17 00:00:00 2001 From: Jeremy Rimpo Date: Fri, 10 Dec 2021 09:30:19 -0600 Subject: [PATCH 1221/1544] Include gamebryo string in translations --- src/game_gamebryo_en.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/game_gamebryo_en.ts b/src/game_gamebryo_en.ts index e8a2af83..b2e3f685 100644 --- a/src/game_gamebryo_en.ts +++ b/src/game_gamebryo_en.ts @@ -131,7 +131,7 @@ QObject - + Some of your plugins have invalid names! These plugins can not be loaded by the game. Please see mo_interface.log for a list of affected plugins and rename them. From 98b064fe5850823372e299554ecb78fdd9f90d68 Mon Sep 17 00:00:00 2001 From: Jeremy Rimpo Date: Fri, 10 Dec 2021 09:30:20 -0600 Subject: [PATCH 1222/1544] [game_ttw] Include gamebryo string in translations --- src/games/ttw/src/CMakeLists.txt | 3 + src/games/ttw/src/game_ttw_en.ts | 161 +++++++++++++++++++++++++++++++ 2 files changed, 164 insertions(+) diff --git a/src/games/ttw/src/CMakeLists.txt b/src/games/ttw/src/CMakeLists.txt index 1f12c529..d1fed507 100644 --- a/src/games/ttw/src/CMakeLists.txt +++ b/src/games/ttw/src/CMakeLists.txt @@ -1,4 +1,7 @@ cmake_minimum_required(VERSION 3.16) + +set(additional_translations ${modorganizer_super_path}/game_gamebryo/src) + if(DEFINED DEPENDENCIES_DIR) include(${DEPENDENCIES_DIR}/modorganizer_super/cmake_common/src.cmake) else() diff --git a/src/games/ttw/src/game_ttw_en.ts b/src/games/ttw/src/game_ttw_en.ts index 087ed480..477a00c3 100644 --- a/src/games/ttw/src/game_ttw_en.ts +++ b/src/games/ttw/src/game_ttw_en.ts @@ -14,4 +14,165 @@ + + GamebryoModDataContent + + + Plugins (ESP/ESM/ESL) + + + + + Optional Plugins + + + + + Interface + + + + + Meshes + + + + + Bethesda Archive + + + + + Scripts (Papyrus) + + + + + Script Extender Plugin + + + + + Script Extender Files + + + + + SkyProc Patcher + + + + + Sound or Music + + + + + Textures + + + + + MCM Configuration + + + + + INI Files + + + + + FaceGen Data + + + + + ModGroup Files + + + + + GamebryoSaveGameInfoWidget + + + Save # + + + + + Character + + + + + Level + + + + + Location + + + + + Date + + + + + Has Script Extender Data + + + + + Missing ESPs + + + + + + None + + + + + Missing ESLs + + + + + QObject + + + + Some of your plugins have invalid names! These plugins can not be loaded by the game. Please see mo_interface.log for a list of affected plugins and rename them. + + + + + %1, #%2, Level %3, %4 + + + + + failed to open %1 + + + + + wrong file format - expected %1 got %2 + + + + + failed to query registry path (preflight): %1 + + + + + failed to query registry path (read): %1 + + + From 9091e442d82055d040411b7dc9c4c5155ca1e7ce Mon Sep 17 00:00:00 2001 From: Lachlan Collins Date: Mon, 10 Jan 2022 23:53:47 +1100 Subject: [PATCH 1223/1544] [game_skyrimse] Add Skyrim Platform to recognised folder names Details of data structure available here: https://www.nexusmods.com/skyrimspecialedition/mods/54909 --- src/games/skyrimse/src/skyrimsemoddatachecker.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/games/skyrimse/src/skyrimsemoddatachecker.h b/src/games/skyrimse/src/skyrimsemoddatachecker.h index 56203d3d..b5abada7 100644 --- a/src/games/skyrimse/src/skyrimsemoddatachecker.h +++ b/src/games/skyrimse/src/skyrimsemoddatachecker.h @@ -15,7 +15,7 @@ protected: "sound", "strings", "textures", "trees", "video", "facegen", "materials", "skse", "distantlod", "asi", "Tools", "MCM", "distantland", "mits", "dllplugins", "CalienteTools", "NetScriptFramework", "shadersfx", - "Nemesis_Engine" + "Nemesis_Engine", "Platform" }; return result; } From 79a082d37027f458ead77cdfe2b3e185e1b0cd71 Mon Sep 17 00:00:00 2001 From: Chris Bessent Date: Sun, 23 Jan 2022 04:15:53 -0700 Subject: [PATCH 1224/1544] [game_enderalse] Do not create loadorder.txt when initializing profile The original intention behind loadorder.txt is to simply report the load order of plugins to other applications. If the file is not a known, good load order from MO2, it should not be used to change the load order. --- src/games/enderalse/src/gameenderalse.cpp | 2 -- 1 file changed, 2 deletions(-) diff --git a/src/games/enderalse/src/gameenderalse.cpp b/src/games/enderalse/src/gameenderalse.cpp index f7d4eaa3..14e01f9a 100644 --- a/src/games/enderalse/src/gameenderalse.cpp +++ b/src/games/enderalse/src/gameenderalse.cpp @@ -146,7 +146,6 @@ void GameEnderalSE::initializeProfile(const QDir &path, ProfileSettings settings { if (settings.testFlag(IPluginGame::MODS)) { copyToProfile(localAppFolder() + "/Enderal Special Edition", path, "plugins.txt"); - copyToProfile(localAppFolder() + "/Enderal Special Edition", path, "loadorder.txt"); } if (settings.testFlag(IPluginGame::CONFIGURATION)) { @@ -282,4 +281,3 @@ MappingType GameEnderalSE::mappings() const return result; } - From cbd901f4451b5076593b55df31699d4c3df67f4e Mon Sep 17 00:00:00 2001 From: Chris Bessent Date: Sun, 23 Jan 2022 04:17:27 -0700 Subject: [PATCH 1225/1544] [game_fallout4] Do not create loadorder.txt when initializing profile The original intention behind loadorder.txt is to simply report the load order of plugins to other applications. If the file is not a known, good load order from MO2, it should not be used to change the load order. --- src/games/fallout4/src/gamefallout4.cpp | 1 - 1 file changed, 1 deletion(-) diff --git a/src/games/fallout4/src/gamefallout4.cpp b/src/games/fallout4/src/gamefallout4.cpp index ac4f2c21..6087de0f 100644 --- a/src/games/fallout4/src/gamefallout4.cpp +++ b/src/games/fallout4/src/gamefallout4.cpp @@ -113,7 +113,6 @@ void GameFallout4::initializeProfile(const QDir &path, ProfileSettings settings) { if (settings.testFlag(IPluginGame::MODS)) { copyToProfile(localAppFolder() + "/Fallout4", path, "plugins.txt"); - copyToProfile(localAppFolder() + "/Fallout4", path, "loadorder.txt"); } if (settings.testFlag(IPluginGame::CONFIGURATION)) { From c5542c91cd1dd11ca3d5abc860bb32eb6c7ae139 Mon Sep 17 00:00:00 2001 From: Chris Bessent Date: Sun, 23 Jan 2022 04:18:06 -0700 Subject: [PATCH 1226/1544] [game_fallout4vr] Do not create loadorder.txt when initializing profile The original intention behind loadorder.txt is to simply report the load order of plugins to other applications. If the file is not a known, good load order from MO2, it should not be used to change the load order. --- src/games/fallout4vr/src/gamefallout4vr.cpp | 1 - 1 file changed, 1 deletion(-) diff --git a/src/games/fallout4vr/src/gamefallout4vr.cpp b/src/games/fallout4vr/src/gamefallout4vr.cpp index 5e96ed20..4eec6abc 100644 --- a/src/games/fallout4vr/src/gamefallout4vr.cpp +++ b/src/games/fallout4vr/src/gamefallout4vr.cpp @@ -109,7 +109,6 @@ void GameFallout4VR::initializeProfile(const QDir &path, ProfileSettings setting { if (settings.testFlag(IPluginGame::MODS)) { copyToProfile(localAppFolder() + "/Fallout4VR", path, "plugins.txt"); - copyToProfile(localAppFolder() + "/Fallout4VR", path, "loadorder.txt"); } if (settings.testFlag(IPluginGame::CONFIGURATION)) { From d0a295041056616de760b15727c0e78bbcfff287 Mon Sep 17 00:00:00 2001 From: Chris Bessent Date: Sun, 23 Jan 2022 04:18:53 -0700 Subject: [PATCH 1227/1544] [game_falloutnv] Do not create loadorder.txt when initializing profile The original intention behind loadorder.txt is to simply report the load order of plugins to other applications. If the file is not a known, good load order from MO2, it should not be used to change the load order. --- src/games/falloutnv/src/gamefalloutnv.cpp | 1 - 1 file changed, 1 deletion(-) diff --git a/src/games/falloutnv/src/gamefalloutnv.cpp b/src/games/falloutnv/src/gamefalloutnv.cpp index 307ade66..dc11b7b4 100644 --- a/src/games/falloutnv/src/gamefalloutnv.cpp +++ b/src/games/falloutnv/src/gamefalloutnv.cpp @@ -112,7 +112,6 @@ void GameFalloutNV::initializeProfile(const QDir &path, ProfileSettings settings { if (settings.testFlag(IPluginGame::MODS)) { copyToProfile(localAppFolder() + "/FalloutNV", path, "plugins.txt"); - copyToProfile(localAppFolder() + "/FalloutNV", path, "loadorder.txt"); } if (settings.testFlag(IPluginGame::CONFIGURATION)) { From b1ed9ab2418f3f2dcb335186eafae16976239300 Mon Sep 17 00:00:00 2001 From: Chris Bessent Date: Sun, 23 Jan 2022 04:19:50 -0700 Subject: [PATCH 1228/1544] [game_morrowind] Do not create loadorder.txt when initializing profile The original intention behind loadorder.txt is to simply report the load order of plugins to other applications. If the file is not a known, good load order from MO2, it should not be used to change the load order. --- src/games/morrowind/src/gamemorrowind.cpp | 1 - 1 file changed, 1 deletion(-) diff --git a/src/games/morrowind/src/gamemorrowind.cpp b/src/games/morrowind/src/gamemorrowind.cpp index dacb1d0c..96d47542 100644 --- a/src/games/morrowind/src/gamemorrowind.cpp +++ b/src/games/morrowind/src/gamemorrowind.cpp @@ -130,7 +130,6 @@ void GameMorrowind::initializeProfile(const QDir &path, ProfileSettings settings { if (settings.testFlag(IPluginGame::MODS)) { copyToProfile(localAppFolder() + "/Morrowind", path, "plugins.txt"); - copyToProfile(localAppFolder() + "/Morrowind", path, "loadorder.txt"); } if (settings.testFlag(IPluginGame::CONFIGURATION)) { From b1ded0a2f38c1f2c4723c849b60f7ac9510c8e49 Mon Sep 17 00:00:00 2001 From: Chris Bessent Date: Sun, 23 Jan 2022 04:20:43 -0700 Subject: [PATCH 1229/1544] [game_nehrim] Do not create loadorder.txt when initializing profile The original intention behind loadorder.txt is to simply report the load order of plugins to other applications. If the file is not a known, good load order from MO2, it should not be used to change the load order. --- src/games/nehrim/src/gamenehrim.cpp | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/src/games/nehrim/src/gamenehrim.cpp b/src/games/nehrim/src/gamenehrim.cpp index 23f78fd6..82e7102e 100644 --- a/src/games/nehrim/src/gamenehrim.cpp +++ b/src/games/nehrim/src/gamenehrim.cpp @@ -103,7 +103,6 @@ void GameNehrim::initializeProfile(const QDir &path, ProfileSettings settings) c { if (settings.testFlag(IPluginGame::MODS)) { copyToProfile(localAppFolder() + "/Oblvion", path, "plugins.txt"); - copyToProfile(localAppFolder() + "/Oblvion", path, "loadorder.txt"); } if (settings.testFlag(IPluginGame::CONFIGURATION)) { @@ -192,4 +191,4 @@ QString GameNehrim::identifyGamePath() const QString GameNehrim::binaryName() const { return "NehrimLauncher.exe"; -} \ No newline at end of file +} From a80e5941549ad167938ea18d9248d98852545933 Mon Sep 17 00:00:00 2001 From: Chris Bessent Date: Sun, 23 Jan 2022 04:21:09 -0700 Subject: [PATCH 1230/1544] [game_oblivion] Do not create loadorder.txt when initializing profile The original intention behind loadorder.txt is to simply report the load order of plugins to other applications. If the file is not a known, good load order from MO2, it should not be used to change the load order. --- src/games/oblivion/src/gameoblivion.cpp | 1 - 1 file changed, 1 deletion(-) diff --git a/src/games/oblivion/src/gameoblivion.cpp b/src/games/oblivion/src/gameoblivion.cpp index 93106af0..b6564776 100644 --- a/src/games/oblivion/src/gameoblivion.cpp +++ b/src/games/oblivion/src/gameoblivion.cpp @@ -104,7 +104,6 @@ void GameOblivion::initializeProfile(const QDir &path, ProfileSettings settings) { if (settings.testFlag(IPluginGame::MODS)) { copyToProfile(localAppFolder() + "/Oblivion", path, "plugins.txt"); - copyToProfile(localAppFolder() + "/Oblivion", path, "loadorder.txt"); } if (settings.testFlag(IPluginGame::CONFIGURATION)) { From 8d78f3d560b56d03290b2bf78bdc3d84b97e88c1 Mon Sep 17 00:00:00 2001 From: Chris Bessent Date: Sun, 23 Jan 2022 04:21:35 -0700 Subject: [PATCH 1231/1544] [game_skyrim] Do not create loadorder.txt when initializing profile The original intention behind loadorder.txt is to simply report the load order of plugins to other applications. If the file is not a known, good load order from MO2, it should not be used to change the load order. --- src/games/skyrim/src/gameskyrim.cpp | 1 - 1 file changed, 1 deletion(-) diff --git a/src/games/skyrim/src/gameskyrim.cpp b/src/games/skyrim/src/gameskyrim.cpp index f68c5c40..f28f8f61 100644 --- a/src/games/skyrim/src/gameskyrim.cpp +++ b/src/games/skyrim/src/gameskyrim.cpp @@ -113,7 +113,6 @@ void GameSkyrim::initializeProfile(const QDir &path, ProfileSettings settings) c { if (settings.testFlag(IPluginGame::MODS)) { copyToProfile(localAppFolder() + "/Skyrim", path, "plugins.txt"); - copyToProfile(localAppFolder() + "/Skyrim", path, "loadorder.txt"); } if (settings.testFlag(IPluginGame::CONFIGURATION)) { From 23cce9537ec3b1928cfca335724310988991b607 Mon Sep 17 00:00:00 2001 From: Chris Bessent Date: Sun, 23 Jan 2022 04:22:00 -0700 Subject: [PATCH 1232/1544] [game_skyrimse] Do not create loadorder.txt when initializing profile The original intention behind loadorder.txt is to simply report the load order of plugins to other applications. If the file is not a known, good load order from MO2, it should not be used to change the load order. --- src/games/skyrimse/src/gameskyrimse.cpp | 2 -- 1 file changed, 2 deletions(-) diff --git a/src/games/skyrimse/src/gameskyrimse.cpp b/src/games/skyrimse/src/gameskyrimse.cpp index c224c537..de173dd2 100644 --- a/src/games/skyrimse/src/gameskyrimse.cpp +++ b/src/games/skyrimse/src/gameskyrimse.cpp @@ -145,7 +145,6 @@ void GameSkyrimSE::initializeProfile(const QDir &path, ProfileSettings settings) { if (settings.testFlag(IPluginGame::MODS)) { copyToProfile(localAppFolder() + "/Skyrim Special Edition", path, "plugins.txt"); - copyToProfile(localAppFolder() + "/Skyrim Special Edition", path, "loadorder.txt"); } if (settings.testFlag(IPluginGame::CONFIGURATION)) { @@ -282,4 +281,3 @@ MappingType GameSkyrimSE::mappings() const return result; } - From 9a6694584140af3b709726554d410752289f8c0d Mon Sep 17 00:00:00 2001 From: Chris Bessent Date: Sun, 23 Jan 2022 04:22:52 -0700 Subject: [PATCH 1233/1544] [game_skyrimvr] Do not create loadorder.txt when initializing profile The original intention behind loadorder.txt is to simply report the load order of plugins to other applications. If the file is not a known, good load order from MO2, it should not be used to change the load order. --- src/games/skyrimvr/src/gameskyrimvr.cpp | 1 - 1 file changed, 1 deletion(-) diff --git a/src/games/skyrimvr/src/gameskyrimvr.cpp b/src/games/skyrimvr/src/gameskyrimvr.cpp index 2ca3c245..e2b59b31 100644 --- a/src/games/skyrimvr/src/gameskyrimvr.cpp +++ b/src/games/skyrimvr/src/gameskyrimvr.cpp @@ -143,7 +143,6 @@ void GameSkyrimVR::initializeProfile(const QDir &path, ProfileSettings settings) { if (settings.testFlag(IPluginGame::MODS)) { copyToProfile(localAppFolder() + "/Skyrim VR", path, "plugins.txt"); - copyToProfile(localAppFolder() + "/Skyrim VR", path, "loadorder.txt"); } if (settings.testFlag(IPluginGame::CONFIGURATION)) { From cc259937ca33dbff6b724946e2462f6daf248591 Mon Sep 17 00:00:00 2001 From: Chris Bessent Date: Sun, 23 Jan 2022 04:23:25 -0700 Subject: [PATCH 1234/1544] [game_ttw] Do not create loadorder.txt when initializing profile The original intention behind loadorder.txt is to simply report the load order of plugins to other applications. If the file is not a known, good load order from MO2, it should not be used to change the load order. --- src/games/ttw/src/gamefalloutttw.cpp | 1 - 1 file changed, 1 deletion(-) diff --git a/src/games/ttw/src/gamefalloutttw.cpp b/src/games/ttw/src/gamefalloutttw.cpp index b32e92c5..519662f2 100644 --- a/src/games/ttw/src/gamefalloutttw.cpp +++ b/src/games/ttw/src/gamefalloutttw.cpp @@ -112,7 +112,6 @@ void GameFalloutTTW::initializeProfile(const QDir &path, ProfileSettings setting { if (settings.testFlag(IPluginGame::MODS)) { copyToProfile(localAppFolder() + "/FalloutNV", path, "plugins.txt"); - copyToProfile(localAppFolder() + "/FalloutNV", path, "loadorder.txt"); } if (settings.testFlag(IPluginGame::CONFIGURATION)) { From 121394eb71fa6a7b3460e9a0c71e50c759df1613 Mon Sep 17 00:00:00 2001 From: Chris Bessent Date: Sun, 23 Jan 2022 04:28:08 -0700 Subject: [PATCH 1235/1544] [game_enderalse] Update to 1.1.0 --- src/games/enderalse/src/gameenderalse.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/games/enderalse/src/gameenderalse.cpp b/src/games/enderalse/src/gameenderalse.cpp index 14e01f9a..ab060665 100644 --- a/src/games/enderalse/src/gameenderalse.cpp +++ b/src/games/enderalse/src/gameenderalse.cpp @@ -134,7 +134,7 @@ QString GameEnderalSE::description() const MOBase::VersionInfo GameEnderalSE::version() const { - return VersionInfo(1, 0, 0, VersionInfo::RELEASE_BETA); + return VersionInfo(1, 1, 0, VersionInfo::RELEASE_FINAL); } QList GameEnderalSE::settings() const From 127ddc7e6f82f0bc60590f5f4c30d13a9a4432f7 Mon Sep 17 00:00:00 2001 From: Chris Bessent Date: Sun, 23 Jan 2022 04:29:33 -0700 Subject: [PATCH 1236/1544] [game_fallout4] Update version to 1.7.0 --- src/games/fallout4/src/gamefallout4.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/games/fallout4/src/gamefallout4.cpp b/src/games/fallout4/src/gamefallout4.cpp index 6087de0f..670c6bd6 100644 --- a/src/games/fallout4/src/gamefallout4.cpp +++ b/src/games/fallout4/src/gamefallout4.cpp @@ -101,7 +101,7 @@ QString GameFallout4::description() const MOBase::VersionInfo GameFallout4::version() const { - return VersionInfo(1, 6, 0, VersionInfo::RELEASE_FINAL); + return VersionInfo(1, 7, 0, VersionInfo::RELEASE_FINAL); } QList GameFallout4::settings() const From d66de87234566622694f54dcc57420fdbbda95d0 Mon Sep 17 00:00:00 2001 From: Chris Bessent Date: Sun, 23 Jan 2022 04:30:29 -0700 Subject: [PATCH 1237/1544] [game_fallout4vr] Update version to 1.6.0 --- src/games/fallout4vr/src/gamefallout4vr.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/games/fallout4vr/src/gamefallout4vr.cpp b/src/games/fallout4vr/src/gamefallout4vr.cpp index 4eec6abc..2a4be58a 100644 --- a/src/games/fallout4vr/src/gamefallout4vr.cpp +++ b/src/games/fallout4vr/src/gamefallout4vr.cpp @@ -97,7 +97,7 @@ QString GameFallout4VR::description() const MOBase::VersionInfo GameFallout4VR::version() const { - return VersionInfo(1, 5, 0, VersionInfo::RELEASE_FINAL); + return VersionInfo(1, 6, 0, VersionInfo::RELEASE_FINAL); } QList GameFallout4VR::settings() const From 56e22b8cb8b7fef2d655775ab223364ba6d5256d Mon Sep 17 00:00:00 2001 From: Chris Bessent Date: Sun, 23 Jan 2022 04:31:18 -0700 Subject: [PATCH 1238/1544] [game_falloutnv] Update version to 1.5.0 --- src/games/falloutnv/src/gamefalloutnv.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/games/falloutnv/src/gamefalloutnv.cpp b/src/games/falloutnv/src/gamefalloutnv.cpp index dc11b7b4..cad84c25 100644 --- a/src/games/falloutnv/src/gamefalloutnv.cpp +++ b/src/games/falloutnv/src/gamefalloutnv.cpp @@ -100,7 +100,7 @@ QString GameFalloutNV::description() const MOBase::VersionInfo GameFalloutNV::version() const { - return VersionInfo(1, 4, 1, VersionInfo::RELEASE_FINAL); + return VersionInfo(1, 5, 0, VersionInfo::RELEASE_FINAL); } QList GameFalloutNV::settings() const From 41e7e028b80da90960cb6b32505a81b31a11eb27 Mon Sep 17 00:00:00 2001 From: Chris Bessent Date: Sun, 23 Jan 2022 04:32:28 -0700 Subject: [PATCH 1239/1544] [game_morrowind] Update version to 1.5.0 --- src/games/morrowind/src/gamemorrowind.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/games/morrowind/src/gamemorrowind.cpp b/src/games/morrowind/src/gamemorrowind.cpp index 96d47542..dac90d6f 100644 --- a/src/games/morrowind/src/gamemorrowind.cpp +++ b/src/games/morrowind/src/gamemorrowind.cpp @@ -118,7 +118,7 @@ QString GameMorrowind::description() const MOBase::VersionInfo GameMorrowind::version() const { - return VersionInfo(1, 4, 0, VersionInfo::RELEASE_FINAL); + return VersionInfo(1, 5, 0, VersionInfo::RELEASE_FINAL); } QList GameMorrowind::settings() const From 9e8f93d2c8baac3efcdc5a6cd5cd0a56660757d7 Mon Sep 17 00:00:00 2001 From: Chris Bessent Date: Sun, 23 Jan 2022 04:32:51 -0700 Subject: [PATCH 1240/1544] [game_nehrim] Update version to 1.1.0 --- src/games/nehrim/src/gamenehrim.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/games/nehrim/src/gamenehrim.cpp b/src/games/nehrim/src/gamenehrim.cpp index 82e7102e..0a3ee6dc 100644 --- a/src/games/nehrim/src/gamenehrim.cpp +++ b/src/games/nehrim/src/gamenehrim.cpp @@ -91,7 +91,7 @@ QString GameNehrim::description() const MOBase::VersionInfo GameNehrim::version() const { - return VersionInfo(1, 0, 0, VersionInfo::RELEASE_FINAL); + return VersionInfo(1, 1, 0, VersionInfo::RELEASE_FINAL); } QList GameNehrim::settings() const From cce6a8840e6ed4a75a5f40fcccf8df7ab1f5cb0f Mon Sep 17 00:00:00 2001 From: Chris Bessent Date: Sun, 23 Jan 2022 04:33:16 -0700 Subject: [PATCH 1241/1544] [game_oblivion] Update version to 1.6.0 --- src/games/oblivion/src/gameoblivion.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/games/oblivion/src/gameoblivion.cpp b/src/games/oblivion/src/gameoblivion.cpp index b6564776..bdc06360 100644 --- a/src/games/oblivion/src/gameoblivion.cpp +++ b/src/games/oblivion/src/gameoblivion.cpp @@ -90,7 +90,7 @@ QString GameOblivion::description() const MOBase::VersionInfo GameOblivion::version() const { - return VersionInfo(1, 5, 0, VersionInfo::RELEASE_FINAL); + return VersionInfo(1, 6, 0, VersionInfo::RELEASE_FINAL); } QList GameOblivion::settings() const From 5a9de88ac483f263abdacea7711057d1e8030006 Mon Sep 17 00:00:00 2001 From: Chris Bessent Date: Sun, 23 Jan 2022 04:33:58 -0700 Subject: [PATCH 1242/1544] [game_skyrim] Update version to 1.6.0 --- src/games/skyrim/src/gameskyrim.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/games/skyrim/src/gameskyrim.cpp b/src/games/skyrim/src/gameskyrim.cpp index f28f8f61..60b665f2 100644 --- a/src/games/skyrim/src/gameskyrim.cpp +++ b/src/games/skyrim/src/gameskyrim.cpp @@ -99,7 +99,7 @@ QString GameSkyrim::description() const MOBase::VersionInfo GameSkyrim::version() const { - return VersionInfo(1, 5, 0, VersionInfo::RELEASE_FINAL); + return VersionInfo(1, 6, 0, VersionInfo::RELEASE_FINAL); } QList GameSkyrim::settings() const From ab2bec3231466a4df99e9e4373cd964d8a0fbddd Mon Sep 17 00:00:00 2001 From: Chris Bessent Date: Sun, 23 Jan 2022 04:34:22 -0700 Subject: [PATCH 1243/1544] [game_skyrimse] Update version to 1.6.0 --- src/games/skyrimse/src/gameskyrimse.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/games/skyrimse/src/gameskyrimse.cpp b/src/games/skyrimse/src/gameskyrimse.cpp index de173dd2..2f8ae097 100644 --- a/src/games/skyrimse/src/gameskyrimse.cpp +++ b/src/games/skyrimse/src/gameskyrimse.cpp @@ -131,7 +131,7 @@ QString GameSkyrimSE::description() const MOBase::VersionInfo GameSkyrimSE::version() const { - return VersionInfo(1, 5, 0, VersionInfo::RELEASE_FINAL); + return VersionInfo(1, 6, 0, VersionInfo::RELEASE_FINAL); } QList GameSkyrimSE::settings() const From 77e9286e2a57cd30a4c88fc9fcbbdb6969c1a7db Mon Sep 17 00:00:00 2001 From: Chris Bessent Date: Sun, 23 Jan 2022 04:34:59 -0700 Subject: [PATCH 1244/1544] [game_skyrimvr] Update version to 1.5.0 --- src/games/skyrimvr/src/gameskyrimvr.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/games/skyrimvr/src/gameskyrimvr.cpp b/src/games/skyrimvr/src/gameskyrimvr.cpp index e2b59b31..238dac8d 100644 --- a/src/games/skyrimvr/src/gameskyrimvr.cpp +++ b/src/games/skyrimvr/src/gameskyrimvr.cpp @@ -129,7 +129,7 @@ QString GameSkyrimVR::description() const MOBase::VersionInfo GameSkyrimVR::version() const { - return VersionInfo(1, 4, 1, VersionInfo::RELEASE_FINAL); + return VersionInfo(1, 5, 0, VersionInfo::RELEASE_FINAL); } QList GameSkyrimVR::settings() const From 56e5bce243ecd6d6862455bad6c26b30e8a5737e Mon Sep 17 00:00:00 2001 From: Chris Bessent Date: Sun, 23 Jan 2022 04:35:29 -0700 Subject: [PATCH 1245/1544] [game_ttw] Update version to 1.5.0 --- src/games/ttw/src/gamefalloutttw.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/games/ttw/src/gamefalloutttw.cpp b/src/games/ttw/src/gamefalloutttw.cpp index 519662f2..15cbd526 100644 --- a/src/games/ttw/src/gamefalloutttw.cpp +++ b/src/games/ttw/src/gamefalloutttw.cpp @@ -100,7 +100,7 @@ QString GameFalloutTTW::description() const MOBase::VersionInfo GameFalloutTTW::version() const { - return VersionInfo(1, 4, 1, VersionInfo::RELEASE_FINAL); + return VersionInfo(1, 5, 0, VersionInfo::RELEASE_FINAL); } QList GameFalloutTTW::settings() const From 462a7048e7b396b8de7f90aeb540e9e873b10bf7 Mon Sep 17 00:00:00 2001 From: Chris Bessent Date: Sun, 23 Jan 2022 05:03:01 -0700 Subject: [PATCH 1246/1544] [game_falloutnv] Set DLC as primary based on .NAM files The game force loads the DLC if an associated .NAM file exists. Replicate this in the MO2 GUI. --- src/games/falloutnv/src/gamefalloutnv.cpp | 14 +++++++++++++- 1 file changed, 13 insertions(+), 1 deletion(-) diff --git a/src/games/falloutnv/src/gamefalloutnv.cpp b/src/games/falloutnv/src/gamefalloutnv.cpp index cad84c25..b9ea39f4 100644 --- a/src/games/falloutnv/src/gamefalloutnv.cpp +++ b/src/games/falloutnv/src/gamefalloutnv.cpp @@ -153,7 +153,19 @@ QString GameFalloutNV::steamAPPId() const QStringList GameFalloutNV::primaryPlugins() const { - return { "falloutnv.esm" }; + QStringList plugins = { "falloutnv.esm" }; + + // DLC are force-loaded through .NAM files so look for those + for (QString dlcFile : DLCPlugins()) + { + QString namFile = dlcFile.toLower().replace(".esm", ".nam"); + if (dataDirectory().exists(namFile)) + { + plugins << dlcFile; + } + } + + return plugins; } QString GameFalloutNV::gameShortName() const From f7abe3e8cb2953ad4794f3e3e7e991acf131b816 Mon Sep 17 00:00:00 2001 From: Chris Bessent Date: Sun, 23 Jan 2022 21:57:29 -0700 Subject: [PATCH 1247/1544] [game_falloutnv] Revert "Set DLC as primary based on .NAM files" This reverts commit 462a7048e7b396b8de7f90aeb540e9e873b10bf7. --- src/games/falloutnv/src/gamefalloutnv.cpp | 14 +------------- 1 file changed, 1 insertion(+), 13 deletions(-) diff --git a/src/games/falloutnv/src/gamefalloutnv.cpp b/src/games/falloutnv/src/gamefalloutnv.cpp index b9ea39f4..cad84c25 100644 --- a/src/games/falloutnv/src/gamefalloutnv.cpp +++ b/src/games/falloutnv/src/gamefalloutnv.cpp @@ -153,19 +153,7 @@ QString GameFalloutNV::steamAPPId() const QStringList GameFalloutNV::primaryPlugins() const { - QStringList plugins = { "falloutnv.esm" }; - - // DLC are force-loaded through .NAM files so look for those - for (QString dlcFile : DLCPlugins()) - { - QString namFile = dlcFile.toLower().replace(".esm", ".nam"); - if (dataDirectory().exists(namFile)) - { - plugins << dlcFile; - } - } - - return plugins; + return { "falloutnv.esm" }; } QString GameFalloutNV::gameShortName() const From e34ab5b0cfc43d1755e9e9691170ec2f15a667c7 Mon Sep 17 00:00:00 2001 From: Chris Bessent Date: Sun, 23 Jan 2022 21:58:34 -0700 Subject: [PATCH 1248/1544] [game_falloutnv] Update version to 1.5.1 --- src/games/falloutnv/src/gamefalloutnv.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/games/falloutnv/src/gamefalloutnv.cpp b/src/games/falloutnv/src/gamefalloutnv.cpp index cad84c25..1a46ea9d 100644 --- a/src/games/falloutnv/src/gamefalloutnv.cpp +++ b/src/games/falloutnv/src/gamefalloutnv.cpp @@ -100,7 +100,7 @@ QString GameFalloutNV::description() const MOBase::VersionInfo GameFalloutNV::version() const { - return VersionInfo(1, 5, 0, VersionInfo::RELEASE_FINAL); + return VersionInfo(1, 5, 1, VersionInfo::RELEASE_FINAL); } QList GameFalloutNV::settings() const From ccf3f41e0adee113dfde69ff4dfd3121d559fc90 Mon Sep 17 00:00:00 2001 From: VishVadeva50 <92656695+VishVadeva50@users.noreply.github.com> Date: Fri, 18 Mar 2022 04:15:44 +0100 Subject: [PATCH 1249/1544] [game_ttw] Updated valid folders Removed "NETScriptFramework" because it isn't a thing on NV, added "Config" since NVSE plugins use it and is often packaged as standalone --- src/games/ttw/src/falloutttwmoddatachecker.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/games/ttw/src/falloutttwmoddatachecker.h b/src/games/ttw/src/falloutttwmoddatachecker.h index 66fe756b..744153c8 100644 --- a/src/games/ttw/src/falloutttwmoddatachecker.h +++ b/src/games/ttw/src/falloutttwmoddatachecker.h @@ -14,7 +14,7 @@ protected: "fonts", "interface", "menus", "meshes", "music", "scripts", "shaders", "sound", "strings", "textures", "trees", "video", "facegen", "materials", "nvse", "distantlod", "asi", "Tools", "MCM", "distantland", "mits", - "dllplugins", "CalienteTools", "NetScriptFramework", "shadersfx" + "dllplugins", "CalienteTools", "shadersfx", "config" }; return result; } From d57d161aa8fff4b4ffb421125324ba409e65e75f Mon Sep 17 00:00:00 2001 From: VishVadeva50 <92656695+VishVadeva50@users.noreply.github.com> Date: Sat, 19 Mar 2022 03:29:04 +0100 Subject: [PATCH 1250/1544] [game_falloutnv] Updated valid folders Removed "NETScriptFramework" because it isn't a thing on NV, added "Config" since NVSE plugins use it and is often packaged as standalone --- src/games/falloutnv/src/falloutnvmoddatachecker.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/games/falloutnv/src/falloutnvmoddatachecker.h b/src/games/falloutnv/src/falloutnvmoddatachecker.h index 8c070df2..35a6dbe8 100644 --- a/src/games/falloutnv/src/falloutnvmoddatachecker.h +++ b/src/games/falloutnv/src/falloutnvmoddatachecker.h @@ -14,7 +14,7 @@ protected: "fonts", "interface", "menus", "meshes", "music", "scripts", "shaders", "sound", "strings", "textures", "trees", "video", "facegen", "materials", "nvse", "distantlod", "asi", "Tools", "MCM", "distantland", "mits", - "dllplugins", "CalienteTools", "NetScriptFramework", "shadersfx" + "dllplugins", "CalienteTools", "shadersfx", "config" }; return result; } From 63fdf01aaa2edd75e54222c51a8e16e911ad1e93 Mon Sep 17 00:00:00 2001 From: VishVadeva50 <92656695+VishVadeva50@users.noreply.github.com> Date: Sat, 19 Mar 2022 03:31:44 +0100 Subject: [PATCH 1251/1544] [game_fallout4] Updated valid folders and files Removed "NETScriptFramework" because it isn't a thing on FO4, added "csg" and "cdx" since they are part of the precombines system in the game --- src/games/fallout4/src/fallout4moddatachecker.h | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/src/games/fallout4/src/fallout4moddatachecker.h b/src/games/fallout4/src/fallout4moddatachecker.h index 5fe0e63c..4dd2a2c5 100644 --- a/src/games/fallout4/src/fallout4moddatachecker.h +++ b/src/games/fallout4/src/fallout4moddatachecker.h @@ -13,14 +13,13 @@ protected: static FileNameSet result{ "interface", "meshes", "music", "scripts", "sound", "strings", "textures", "trees", "video", "materials", "f4se", "distantlod", "asi", "Tools", "MCM", - "distantland", "mits", "dllplugins", "CalienteTools", "NetScriptFramework", - "shadersfx", "aaf" + "distantland", "mits", "dllplugins", "CalienteTools", "shadersfx", "aaf" }; return result; } virtual const FileNameSet& possibleFileExtensions() const override { static FileNameSet result{ - "esp", "esm", "esl", "ba2", "modgroups", "ini" + "esp", "esm", "esl", "ba2", "modgroups", "ini", "csg", "cdx" }; return result; } From f722bfb5756c46b6fcf6f5534396b48639efac6d Mon Sep 17 00:00:00 2001 From: VishVadeva50 <92656695+VishVadeva50@users.noreply.github.com> Date: Tue, 22 Mar 2022 20:50:26 +0100 Subject: [PATCH 1252/1544] [game_skyrimse] Updated Valid Folders Added "grass" which is used by NGIO grass cache files --- src/games/skyrimse/src/skyrimsemoddatachecker.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/games/skyrimse/src/skyrimsemoddatachecker.h b/src/games/skyrimse/src/skyrimsemoddatachecker.h index b5abada7..dd81459f 100644 --- a/src/games/skyrimse/src/skyrimsemoddatachecker.h +++ b/src/games/skyrimse/src/skyrimsemoddatachecker.h @@ -15,7 +15,7 @@ protected: "sound", "strings", "textures", "trees", "video", "facegen", "materials", "skse", "distantlod", "asi", "Tools", "MCM", "distantland", "mits", "dllplugins", "CalienteTools", "NetScriptFramework", "shadersfx", - "Nemesis_Engine", "Platform" + "Nemesis_Engine", "Platform", "grass" }; return result; } From e55b7039803ae8db771619cbc6eeac40c7d80701 Mon Sep 17 00:00:00 2001 From: Jeremy Rimpo Date: Sun, 17 Apr 2022 20:24:21 -0500 Subject: [PATCH 1253/1544] [game_nehrim] Qt6 fix --- src/games/nehrim/src/gamenehrim.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/games/nehrim/src/gamenehrim.cpp b/src/games/nehrim/src/gamenehrim.cpp index 0a3ee6dc..b7e9e845 100644 --- a/src/games/nehrim/src/gamenehrim.cpp +++ b/src/games/nehrim/src/gamenehrim.cpp @@ -55,7 +55,7 @@ QList GameNehrim::executables() const << ExecutableInfo("Nehrim Launcher", findInGameFolder("NehrimLauncher.exe")) << ExecutableInfo("Oblivion Mod Manager", findInGameFolder("OblivionModManager.exe")) << ExecutableInfo("BOSS", findInGameFolder("BOSS/BOSS.exe")) - << ExecutableInfo("LOOT", getLootPath()).withArgument("--game=\"Oblivion\"") + << ExecutableInfo("LOOT", QFileInfo(getLootPath())).withArgument("--game=\"Oblivion\"") << ExecutableInfo("Construction Set", findInGameFolder("TESConstructionSet.exe")) ; } From b2101188ae7da915be3ed56ef3237bb60017c063 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Mika=C3=ABl=20Capelle?= Date: Sun, 17 Apr 2022 20:13:36 +0200 Subject: [PATCH 1254/1544] [game_nehrim] Update following cmake_common changes. --- src/games/nehrim/CMakeLists.txt | 10 ++++------ src/games/nehrim/src/CMakeLists.txt | 12 ++++++------ 2 files changed, 10 insertions(+), 12 deletions(-) diff --git a/src/games/nehrim/CMakeLists.txt b/src/games/nehrim/CMakeLists.txt index 83884282..b5425ae8 100644 --- a/src/games/nehrim/CMakeLists.txt +++ b/src/games/nehrim/CMakeLists.txt @@ -1,12 +1,10 @@ cmake_minimum_required(VERSION 3.16) -project(game_nehrim) -set(project_type plugin) -set(enable_warnings OFF) - if(DEFINED DEPENDENCIES_DIR) - include(${DEPENDENCIES_DIR}/modorganizer_super/cmake_common/project.cmake) + include(${DEPENDENCIES_DIR}/modorganizer_super/cmake_common/mo2.cmake) else() - include(../cmake_common/project.cmake) + include(${CMAKE_CURRENT_LIST_DIR}/cmake_common/mo2.cmake) endif() + +project(game_nehrim) add_subdirectory(src) diff --git a/src/games/nehrim/src/CMakeLists.txt b/src/games/nehrim/src/CMakeLists.txt index 1f12c529..3a0ab7ac 100644 --- a/src/games/nehrim/src/CMakeLists.txt +++ b/src/games/nehrim/src/CMakeLists.txt @@ -1,7 +1,7 @@ cmake_minimum_required(VERSION 3.16) -if(DEFINED DEPENDENCIES_DIR) - include(${DEPENDENCIES_DIR}/modorganizer_super/cmake_common/src.cmake) -else() - include(../../cmake_common/src.cmake) -endif() -requires_project(game_gamebryo game_features) + +add_library(game_nehrim SHARED) +mo2_configure_plugin(game_nehrim + WARNINGS OFF + PRIVATE_DEPENDS gamebryo) +mo2_install_target(game_nehrim) From be70e454b56b391eaa258b1644b28541ba3e1a48 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Mika=C3=ABl=20Capelle?= Date: Tue, 19 Apr 2022 22:51:04 +0200 Subject: [PATCH 1255/1544] Update following cmake_common changes. # Conflicts: # src/gamebryo/game_gamebryo_en.ts --- CMakeLists.txt | 13 ++-- src/creation/CMakeLists.txt | 23 ++----- src/gamebryo/CMakeLists.txt | 16 ++--- src/gamebryo/SConscript | 28 -------- src/gamebryo/gameGamebryo.pro | 42 ------------ src/{ => gamebryo}/game_gamebryo_en.ts | 94 +++++++++++++------------- 6 files changed, 67 insertions(+), 149 deletions(-) delete mode 100644 src/gamebryo/SConscript delete mode 100644 src/gamebryo/gameGamebryo.pro rename src/{ => gamebryo}/game_gamebryo_en.ts (63%) diff --git a/CMakeLists.txt b/CMakeLists.txt index dc380d25..5b7ffba9 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -1,15 +1,12 @@ cmake_minimum_required(VERSION 3.16) -project(game_gamebryo) -set(project_type lib) -set(enable_warnings OFF) - if(DEFINED DEPENDENCIES_DIR) - include(${DEPENDENCIES_DIR}/modorganizer_super/cmake_common/project.cmake) + include(${DEPENDENCIES_DIR}/modorganizer_super/cmake_common/mo2.cmake) else() - include(../cmake_common/project.cmake) + include(${CMAKE_CURRENT_LIST_DIR}/../cmake_common/mo2.cmake) endif() -add_subdirectory(src/gamebryo) -# note that this also creates a project +project(game_gamebryo) + +add_subdirectory(src/gamebryo) add_subdirectory(src/creation) diff --git a/src/creation/CMakeLists.txt b/src/creation/CMakeLists.txt index d1d094d8..5bb88e77 100644 --- a/src/creation/CMakeLists.txt +++ b/src/creation/CMakeLists.txt @@ -1,18 +1,9 @@ cmake_minimum_required(VERSION 3.16) -project(game_creation) -set(project_type lib) -set(enable_warnings OFF) -set(create_translations OFF) - -# appveyor does not build modorganizer in its standard location, so use -# DEPENDENCIES_DIR to find cmake_common -if(DEFINED DEPENDENCIES_DIR) - include(${DEPENDENCIES_DIR}/modorganizer_super/cmake_common/project.cmake) - include(${DEPENDENCIES_DIR}/modorganizer_super/cmake_common/src.cmake) -else() - include(../../../cmake_common/project.cmake) - include(../../../cmake_common/src.cmake) -endif() - -requires_project(game_gamebryo game_features) +add_library(game_creation STATIC) +mo2_configure_library(game_creation + WARNINGS OFF + PUBLIC_DEPENDS uibase + PRIVATE_DEPENDS lz4) +target_link_libraries(game_creation PUBLIC game_gamebryo) +mo2_install_target(game_creation) diff --git a/src/gamebryo/CMakeLists.txt b/src/gamebryo/CMakeLists.txt index c5e1b895..a3576a11 100644 --- a/src/gamebryo/CMakeLists.txt +++ b/src/gamebryo/CMakeLists.txt @@ -1,10 +1,10 @@ cmake_minimum_required(VERSION 3.16) -# appveyor does not build modorganizer in its standard location, so use -# DEPENDENCIES_DIR to find cmake_common -if(DEFINED DEPENDENCIES_DIR) - include(${DEPENDENCIES_DIR}/modorganizer_super/cmake_common/src.cmake) -else() - include(../../../cmake_common/src.cmake) -endif() -requires_project(game_features) +add_library(game_gamebryo STATIC) +mo2_configure_library(game_gamebryo + WARNINGS OFF + TRANSLATIONS ON + AUTOMOC ON + PUBLIC_DEPENDS uibase + PRIVATE_DEPENDS lz4) +mo2_install_target(game_gamebryo) diff --git a/src/gamebryo/SConscript b/src/gamebryo/SConscript deleted file mode 100644 index 8f2d66da..00000000 --- a/src/gamebryo/SConscript +++ /dev/null @@ -1,28 +0,0 @@ -import os - -Import('qt_env') - -env = qt_env.Clone() - -env.EnableQtModules('Widgets') - -env['CPPPATH'] += [ - '.', # Why is this necessary? - os.path.join('..', 'gamefeatures'), - '${BOOSTPATH}' -] - -env.Uic(env.Glob('*.ui')) - -#env.AppendUnique(LIBS = [ -# 'advapi32', -# 'ole32', -# 'shell32', -# 'version' -#]) - -lib = env.StaticLibrary('gameGamebryo', env.Glob('*.cpp')) -#env.InstallModule(lib) - -res = env['QT_USED_MODULES'] -Return('res') diff --git a/src/gamebryo/gameGamebryo.pro b/src/gamebryo/gameGamebryo.pro deleted file mode 100644 index 5ae81b94..00000000 --- a/src/gamebryo/gameGamebryo.pro +++ /dev/null @@ -1,42 +0,0 @@ -#------------------------------------------------- -# -# Project created by QtCreator 2015-01-26T19:47:42 -# -#------------------------------------------------- - -TARGET = gameGamebryo -TEMPLATE = lib -CONFIG += staticlib - -QT += widgets - -SOURCES += gamegamebryo.cpp \ - dummybsa.cpp \ - gamebryobsainvalidation.cpp \ - gamebryodataarchives.cpp \ - gamebryoscriptextender.cpp \ - gamebryosavegame.cpp \ - gamebryolocalsavegames.cpp - gamebryosavegameinfo.cpp \ - gamebryosavegameinfowidget.cpp - -HEADERS += gamegamebryo.h \ - dummybsa.h \ - gamebryobsainvalidation.h \ - gamebryodataarchives.h \ - gamebryoscriptextender.h \ - gamebryosavegame.h \ - gamebryolocalsavegames.h - gamebryosavegameinfo.h \ - gamebryosavegameinfowidget.h - -include(../plugin_template.pri) - -INCLUDEPATH += "$${BOOSTPATH}" "$${PWD}/../gamefeatures" - -OTHER_FILES +=\ - SConscript \ - CMakeLists.txt - -FORMS += \ - gamebryosavegameinfowidget.ui diff --git a/src/game_gamebryo_en.ts b/src/gamebryo/game_gamebryo_en.ts similarity index 63% rename from src/game_gamebryo_en.ts rename to src/gamebryo/game_gamebryo_en.ts index b2e3f685..9362444f 100644 --- a/src/game_gamebryo_en.ts +++ b/src/gamebryo/game_gamebryo_en.ts @@ -4,77 +4,77 @@ GamebryoModDataContent - + Plugins (ESP/ESM/ESL) - + Optional Plugins - + Interface - + Meshes - + Bethesda Archive - + Scripts (Papyrus) - + Script Extender Plugin - + Script Extender Files - + SkyProc Patcher - + Sound or Music - + Textures - + MCM Configuration - + INI Files - + FaceGen Data - + ModGroup Files @@ -82,48 +82,48 @@ GamebryoSaveGameInfoWidget - + Save # - + Character - + Level - + Location - + Date - + Has Script Extender Data - + Missing ESPs - - + + None - + Missing ESLs @@ -131,34 +131,34 @@ QObject - - Some of your plugins have invalid names! These plugins can not be loaded by the game. Please see mo_interface.log for a list of affected plugins and rename them. - - - - - %1, #%2, Level %3, %4 - - - - - failed to open %1 - - - - - wrong file format - expected %1 got %2 - - - - + failed to query registry path (preflight): %1 - + failed to query registry path (read): %1 + + + %1, #%2, Level %3, %4 + + + + + failed to open %1 + + + + + wrong file format - expected %1 got %2 + + + + + Some of your plugins have invalid names! These plugins can not be loaded by the game. Please see mo_interface.log for a list of affected plugins and rename them. + + From f52c74d8458dd4ccba5ac54a5bf06ff61ce118c6 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Mika=C3=ABl=20Capelle?= Date: Tue, 19 Apr 2022 22:57:56 +0200 Subject: [PATCH 1256/1544] Minor updates. --- src/creation/CMakeLists.txt | 1 + src/creation/game_gamebryo_en.ts | 12 ++++++++++++ src/gamebryo/game_gamebryo_en.ts | 18 +++++++++--------- 3 files changed, 22 insertions(+), 9 deletions(-) create mode 100644 src/creation/game_gamebryo_en.ts diff --git a/src/creation/CMakeLists.txt b/src/creation/CMakeLists.txt index 5bb88e77..f2dce976 100644 --- a/src/creation/CMakeLists.txt +++ b/src/creation/CMakeLists.txt @@ -3,6 +3,7 @@ cmake_minimum_required(VERSION 3.16) add_library(game_creation STATIC) mo2_configure_library(game_creation WARNINGS OFF + TRANSLATIONS ON PUBLIC_DEPENDS uibase PRIVATE_DEPENDS lz4) target_link_libraries(game_creation PUBLIC game_gamebryo) diff --git a/src/creation/game_gamebryo_en.ts b/src/creation/game_gamebryo_en.ts new file mode 100644 index 00000000..385668d9 --- /dev/null +++ b/src/creation/game_gamebryo_en.ts @@ -0,0 +1,12 @@ + + + + + QObject + + + Some of your plugins have invalid names! These plugins can not be loaded by the game. Please see mo_interface.log for a list of affected plugins and rename them. + + + + diff --git a/src/gamebryo/game_gamebryo_en.ts b/src/gamebryo/game_gamebryo_en.ts index 9362444f..116b63ae 100644 --- a/src/gamebryo/game_gamebryo_en.ts +++ b/src/gamebryo/game_gamebryo_en.ts @@ -131,13 +131,8 @@ QObject - - failed to query registry path (preflight): %1 - - - - - failed to query registry path (read): %1 + + Some of your plugins have invalid names! These plugins can not be loaded by the game. Please see mo_interface.log for a list of affected plugins and rename them. @@ -156,8 +151,13 @@ - - Some of your plugins have invalid names! These plugins can not be loaded by the game. Please see mo_interface.log for a list of affected plugins and rename them. + + failed to query registry path (preflight): %1 + + + + + failed to query registry path (read): %1 From 8a158199da904e86bb6a9d6800f2f5ad9753609f Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Mika=C3=ABl=20Capelle?= Date: Tue, 19 Apr 2022 23:28:02 +0200 Subject: [PATCH 1257/1544] [game_enderalse] Update following cmake_common changes. # Conflicts: # src/CMakeLists.txt --- src/games/enderalse/CMakeLists.txt | 10 ++++------ src/games/enderalse/src/CMakeLists.txt | 13 +++++-------- 2 files changed, 9 insertions(+), 14 deletions(-) diff --git a/src/games/enderalse/CMakeLists.txt b/src/games/enderalse/CMakeLists.txt index feaf7fdd..97dbe510 100644 --- a/src/games/enderalse/CMakeLists.txt +++ b/src/games/enderalse/CMakeLists.txt @@ -1,12 +1,10 @@ cmake_minimum_required(VERSION 3.16) -project(game_enderalse) -set(project_type plugin) -set(enable_warnings OFF) - if(DEFINED DEPENDENCIES_DIR) - include(${DEPENDENCIES_DIR}/modorganizer_super/cmake_common/project.cmake) + include(${DEPENDENCIES_DIR}/modorganizer_super/cmake_common/mo2.cmake) else() - include(../cmake_common/project.cmake) + include(${CMAKE_CURRENT_LIST_DIR}/../cmake_common/mo2.cmake) endif() + +project(game_enderalse) add_subdirectory(src) diff --git a/src/games/enderalse/src/CMakeLists.txt b/src/games/enderalse/src/CMakeLists.txt index d1fed507..ae2cd266 100644 --- a/src/games/enderalse/src/CMakeLists.txt +++ b/src/games/enderalse/src/CMakeLists.txt @@ -1,10 +1,7 @@ cmake_minimum_required(VERSION 3.16) -set(additional_translations ${modorganizer_super_path}/game_gamebryo/src) - -if(DEFINED DEPENDENCIES_DIR) - include(${DEPENDENCIES_DIR}/modorganizer_super/cmake_common/src.cmake) -else() - include(../../cmake_common/src.cmake) -endif() -requires_project(game_gamebryo game_features) +add_library(game_enderalse SHARED) +mo2_configure_plugin(game_enderalse + WARNINGS OFF + PRIVATE_DEPENDS creation) +mo2_install_target(game_enderalse) From f56ac7dc9b7001023be0eefe6b6628d9893778e4 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Mika=C3=ABl=20Capelle?= Date: Wed, 20 Apr 2022 00:00:57 +0200 Subject: [PATCH 1258/1544] [game_fallout3] Update following cmake_common changes. # Conflicts: # src/CMakeLists.txt --- src/games/fallout3/CMakeLists.txt | 10 ++++------ src/games/fallout3/src/CMakeLists.txt | 14 +++++--------- 2 files changed, 9 insertions(+), 15 deletions(-) diff --git a/src/games/fallout3/CMakeLists.txt b/src/games/fallout3/CMakeLists.txt index dc89ec22..ed7a20ca 100644 --- a/src/games/fallout3/CMakeLists.txt +++ b/src/games/fallout3/CMakeLists.txt @@ -1,12 +1,10 @@ cmake_minimum_required(VERSION 3.16) -project(game_fallout3) -set(project_type plugin) -set(enable_warnings OFF) - if(DEFINED DEPENDENCIES_DIR) - include(${DEPENDENCIES_DIR}/modorganizer_super/cmake_common/project.cmake) + include(${DEPENDENCIES_DIR}/modorganizer_super/cmake_common/mo2.cmake) else() - include(../cmake_common/project.cmake) + include(${CMAKE_CURRENT_LIST_DIR}/cmake_common/mo2.cmake) endif() + +project(game_fallout3) add_subdirectory(src) diff --git a/src/games/fallout3/src/CMakeLists.txt b/src/games/fallout3/src/CMakeLists.txt index c6059ae1..9c7f1b28 100644 --- a/src/games/fallout3/src/CMakeLists.txt +++ b/src/games/fallout3/src/CMakeLists.txt @@ -1,11 +1,7 @@ cmake_minimum_required(VERSION 3.16) -set(additional_translations ${modorganizer_super_path}/game_gamebryo/src) - -if(DEFINED DEPENDENCIES_DIR) - include(${DEPENDENCIES_DIR}/modorganizer_super/cmake_common/src.cmake) -else() - include(../../cmake_common/src.cmake) -endif() - -requires_project(game_features game_gamebryo) +add_library(game_fallout3 SHARED) +mo2_configure_plugin(game_fallout3 + WARNINGS OFF + PRIVATE_DEPENDS gamebryo) +mo2_install_target(game_fallout3) From 8980a5df7489b2b3c5b8abeea07a5ea925db8e03 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Mika=C3=ABl=20Capelle?= Date: Wed, 20 Apr 2022 00:02:08 +0200 Subject: [PATCH 1259/1544] [game_fallout4] Update following cmake_common changes. # Conflicts: # src/CMakeLists.txt --- src/games/fallout4/CMakeLists.txt | 10 ++++------ src/games/fallout4/src/CMakeLists.txt | 14 +++++--------- 2 files changed, 9 insertions(+), 15 deletions(-) diff --git a/src/games/fallout4/CMakeLists.txt b/src/games/fallout4/CMakeLists.txt index 15de22e1..1e0429a5 100644 --- a/src/games/fallout4/CMakeLists.txt +++ b/src/games/fallout4/CMakeLists.txt @@ -1,12 +1,10 @@ cmake_minimum_required(VERSION 3.16) -project(game_fallout4) -set(project_type plugin) -set(enable_warnings OFF) - if(DEFINED DEPENDENCIES_DIR) - include(${DEPENDENCIES_DIR}/modorganizer_super/cmake_common/project.cmake) + include(${DEPENDENCIES_DIR}/modorganizer_super/cmake_common/mo2.cmake) else() - include(../cmake_common/project.cmake) + include(${CMAKE_CURRENT_LIST_DIR}/cmake_common/mo2.cmake) endif() + +project(game_fallout4) add_subdirectory(src) diff --git a/src/games/fallout4/src/CMakeLists.txt b/src/games/fallout4/src/CMakeLists.txt index c6059ae1..42fc5582 100644 --- a/src/games/fallout4/src/CMakeLists.txt +++ b/src/games/fallout4/src/CMakeLists.txt @@ -1,11 +1,7 @@ cmake_minimum_required(VERSION 3.16) -set(additional_translations ${modorganizer_super_path}/game_gamebryo/src) - -if(DEFINED DEPENDENCIES_DIR) - include(${DEPENDENCIES_DIR}/modorganizer_super/cmake_common/src.cmake) -else() - include(../../cmake_common/src.cmake) -endif() - -requires_project(game_features game_gamebryo) +add_library(game_fallout4 SHARED) +mo2_configure_plugin(game_fallout4 + WARNINGS OFF + PRIVATE_DEPENDS creation) +mo2_install_target(game_fallout4) From 3271edfd80a1ed1f846c6fe6f595562cfb2468c2 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Mika=C3=ABl=20Capelle?= Date: Wed, 20 Apr 2022 00:02:45 +0200 Subject: [PATCH 1260/1544] [game_fallout4vr] Update following cmake_common changes. # Conflicts: # src/CMakeLists.txt --- src/games/fallout4vr/CMakeLists.txt | 10 ++++------ src/games/fallout4vr/src/CMakeLists.txt | 14 +++++--------- 2 files changed, 9 insertions(+), 15 deletions(-) diff --git a/src/games/fallout4vr/CMakeLists.txt b/src/games/fallout4vr/CMakeLists.txt index 5a0cd43f..b6c2f64e 100644 --- a/src/games/fallout4vr/CMakeLists.txt +++ b/src/games/fallout4vr/CMakeLists.txt @@ -1,12 +1,10 @@ cmake_minimum_required(VERSION 3.16) -project(game_fallout4vr) -set(project_type plugin) -set(enable_warnings OFF) - if(DEFINED DEPENDENCIES_DIR) - include(${DEPENDENCIES_DIR}/modorganizer_super/cmake_common/project.cmake) + include(${DEPENDENCIES_DIR}/modorganizer_super/cmake_common/mo2.cmake) else() - include(../cmake_common/project.cmake) + include(${CMAKE_CURRENT_LIST_DIR}/cmake_common/mo2.cmake) endif() + +project(game_fallout4vr) add_subdirectory(src) diff --git a/src/games/fallout4vr/src/CMakeLists.txt b/src/games/fallout4vr/src/CMakeLists.txt index c6059ae1..81d6ed0a 100644 --- a/src/games/fallout4vr/src/CMakeLists.txt +++ b/src/games/fallout4vr/src/CMakeLists.txt @@ -1,11 +1,7 @@ cmake_minimum_required(VERSION 3.16) -set(additional_translations ${modorganizer_super_path}/game_gamebryo/src) - -if(DEFINED DEPENDENCIES_DIR) - include(${DEPENDENCIES_DIR}/modorganizer_super/cmake_common/src.cmake) -else() - include(../../cmake_common/src.cmake) -endif() - -requires_project(game_features game_gamebryo) +add_library(game_fallout4vr SHARED) +mo2_configure_plugin(game_fallout4vr + WARNINGS OFF + PRIVATE_DEPENDS creation) +mo2_install_target(game_fallout4vr) From c9a972d32bb55fc27ad2c956c5f0c3e694aa432f Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Mika=C3=ABl=20Capelle?= Date: Wed, 20 Apr 2022 00:03:11 +0200 Subject: [PATCH 1261/1544] [game_falloutnv] Update following cmake_common changes. # Conflicts: # src/CMakeLists.txt --- src/games/falloutnv/CMakeLists.txt | 10 ++++------ src/games/falloutnv/src/CMakeLists.txt | 13 +++++-------- 2 files changed, 9 insertions(+), 14 deletions(-) diff --git a/src/games/falloutnv/CMakeLists.txt b/src/games/falloutnv/CMakeLists.txt index 693cf34b..1034de1f 100644 --- a/src/games/falloutnv/CMakeLists.txt +++ b/src/games/falloutnv/CMakeLists.txt @@ -1,12 +1,10 @@ cmake_minimum_required(VERSION 3.16) -project(game_falloutNV) -set(project_type plugin) -set(enable_warnings OFF) - if(DEFINED DEPENDENCIES_DIR) - include(${DEPENDENCIES_DIR}/modorganizer_super/cmake_common/project.cmake) + include(${DEPENDENCIES_DIR}/modorganizer_super/cmake_common/mo2.cmake) else() - include(../cmake_common/project.cmake) + include(${CMAKE_CURRENT_LIST_DIR}/cmake_common/mo2.cmake) endif() + +project(game_falloutNV) add_subdirectory(src) diff --git a/src/games/falloutnv/src/CMakeLists.txt b/src/games/falloutnv/src/CMakeLists.txt index 3abb9467..43cefd24 100644 --- a/src/games/falloutnv/src/CMakeLists.txt +++ b/src/games/falloutnv/src/CMakeLists.txt @@ -1,10 +1,7 @@ cmake_minimum_required(VERSION 3.16) -set(additional_translations ${modorganizer_super_path}/game_gamebryo/src) - -if(DEFINED DEPENDENCIES_DIR) - include(${DEPENDENCIES_DIR}/modorganizer_super/cmake_common/src.cmake) -else() - include(../../cmake_common/src.cmake) -endif() -requires_project(game_features game_gamebryo) +add_library(game_falloutNV SHARED) +mo2_configure_plugin(game_falloutNV + WARNINGS OFF + PRIVATE_DEPENDS gamebryo) +mo2_install_target(game_falloutNV) From 111817aa2f2f8edf5fcd1311a454a11225b1d2d3 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Mika=C3=ABl=20Capelle?= Date: Wed, 20 Apr 2022 00:03:41 +0200 Subject: [PATCH 1262/1544] [game_morrowind] Update following cmake_common changes. # Conflicts: # src/CMakeLists.txt --- src/games/morrowind/CMakeLists.txt | 10 ++++------ src/games/morrowind/src/CMakeLists.txt | 13 +++++-------- 2 files changed, 9 insertions(+), 14 deletions(-) diff --git a/src/games/morrowind/CMakeLists.txt b/src/games/morrowind/CMakeLists.txt index cf3cced3..188996d4 100644 --- a/src/games/morrowind/CMakeLists.txt +++ b/src/games/morrowind/CMakeLists.txt @@ -1,12 +1,10 @@ cmake_minimum_required(VERSION 3.16) -project(game_morrowind) -set(project_type plugin) -set(enable_warnings OFF) - if(DEFINED DEPENDENCIES_DIR) - include(${DEPENDENCIES_DIR}/modorganizer_super/cmake_common/project.cmake) + include(${DEPENDENCIES_DIR}/modorganizer_super/cmake_common/mo2.cmake) else() - include(../cmake_common/project.cmake) + include(${CMAKE_CURRENT_LIST_DIR}/cmake_common/mo2.cmake) endif() + +project(game_morrowind) add_subdirectory(src) diff --git a/src/games/morrowind/src/CMakeLists.txt b/src/games/morrowind/src/CMakeLists.txt index d1fed507..ffa7a6d1 100644 --- a/src/games/morrowind/src/CMakeLists.txt +++ b/src/games/morrowind/src/CMakeLists.txt @@ -1,10 +1,7 @@ cmake_minimum_required(VERSION 3.16) -set(additional_translations ${modorganizer_super_path}/game_gamebryo/src) - -if(DEFINED DEPENDENCIES_DIR) - include(${DEPENDENCIES_DIR}/modorganizer_super/cmake_common/src.cmake) -else() - include(../../cmake_common/src.cmake) -endif() -requires_project(game_gamebryo game_features) +add_library(game_morrowind SHARED) +mo2_configure_plugin(game_morrowind + WARNINGS OFF + PRIVATE_DEPENDS gamebryo) +mo2_install_target(game_morrowind) From 230814ca4b7d12f2c552a1c801ea37004ccc2a34 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Mika=C3=ABl=20Capelle?= Date: Wed, 20 Apr 2022 00:04:25 +0200 Subject: [PATCH 1263/1544] [game_oblivion] Update following cmake_common changes. # Conflicts: # src/CMakeLists.txt --- src/games/oblivion/CMakeLists.txt | 10 ++++------ src/games/oblivion/src/CMakeLists.txt | 13 +++++-------- 2 files changed, 9 insertions(+), 14 deletions(-) diff --git a/src/games/oblivion/CMakeLists.txt b/src/games/oblivion/CMakeLists.txt index c9691dc0..3f9ac55a 100644 --- a/src/games/oblivion/CMakeLists.txt +++ b/src/games/oblivion/CMakeLists.txt @@ -1,12 +1,10 @@ cmake_minimum_required(VERSION 3.16) -project(game_oblivion) -set(project_type plugin) -set(enable_warnings OFF) - if(DEFINED DEPENDENCIES_DIR) - include(${DEPENDENCIES_DIR}/modorganizer_super/cmake_common/project.cmake) + include(${DEPENDENCIES_DIR}/modorganizer_super/cmake_common/mo2.cmake) else() - include(../cmake_common/project.cmake) + include(${CMAKE_CURRENT_LIST_DIR}/cmake_common/mo2.cmake) endif() + +project(game_oblivion) add_subdirectory(src) diff --git a/src/games/oblivion/src/CMakeLists.txt b/src/games/oblivion/src/CMakeLists.txt index d1fed507..b6180c24 100644 --- a/src/games/oblivion/src/CMakeLists.txt +++ b/src/games/oblivion/src/CMakeLists.txt @@ -1,10 +1,7 @@ cmake_minimum_required(VERSION 3.16) -set(additional_translations ${modorganizer_super_path}/game_gamebryo/src) - -if(DEFINED DEPENDENCIES_DIR) - include(${DEPENDENCIES_DIR}/modorganizer_super/cmake_common/src.cmake) -else() - include(../../cmake_common/src.cmake) -endif() -requires_project(game_gamebryo game_features) +add_library(game_oblivion SHARED) +mo2_configure_plugin(game_oblivion + WARNINGS OFF + PRIVATE_DEPENDS gamebryo) +mo2_install_target(game_oblivion) From 7ded22b75304ea419b7a67edbc6788fd30f38348 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Mika=C3=ABl=20Capelle?= Date: Wed, 20 Apr 2022 00:04:42 +0200 Subject: [PATCH 1264/1544] [game_skyrim] Update following cmake_common changes. # Conflicts: # src/CMakeLists.txt --- src/games/skyrim/CMakeLists.txt | 10 ++++------ src/games/skyrim/src/CMakeLists.txt | 13 +++++-------- 2 files changed, 9 insertions(+), 14 deletions(-) diff --git a/src/games/skyrim/CMakeLists.txt b/src/games/skyrim/CMakeLists.txt index b4c1bb55..37a5b620 100644 --- a/src/games/skyrim/CMakeLists.txt +++ b/src/games/skyrim/CMakeLists.txt @@ -1,12 +1,10 @@ cmake_minimum_required(VERSION 3.16) -project(game_skyrim) -set(project_type plugin) -set(enable_warnings OFF) - if(DEFINED DEPENDENCIES_DIR) - include(${DEPENDENCIES_DIR}/modorganizer_super/cmake_common/project.cmake) + include(${DEPENDENCIES_DIR}/modorganizer_super/cmake_common/mo2.cmake) else() - include(../cmake_common/project.cmake) + include(${CMAKE_CURRENT_LIST_DIR}/cmake_common/mo2.cmake) endif() + +project(game_skyrim) add_subdirectory(src) diff --git a/src/games/skyrim/src/CMakeLists.txt b/src/games/skyrim/src/CMakeLists.txt index d1fed507..4d6af8ed 100644 --- a/src/games/skyrim/src/CMakeLists.txt +++ b/src/games/skyrim/src/CMakeLists.txt @@ -1,10 +1,7 @@ cmake_minimum_required(VERSION 3.16) -set(additional_translations ${modorganizer_super_path}/game_gamebryo/src) - -if(DEFINED DEPENDENCIES_DIR) - include(${DEPENDENCIES_DIR}/modorganizer_super/cmake_common/src.cmake) -else() - include(../../cmake_common/src.cmake) -endif() -requires_project(game_gamebryo game_features) +add_library(game_skyrim SHARED) +mo2_configure_plugin(game_skyrim + WARNINGS OFF + PRIVATE_DEPENDS gamebryo) +mo2_install_target(game_skyrim) From a6c71f2517b6eb5463db4da4d11be7072d472ac4 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Mika=C3=ABl=20Capelle?= Date: Wed, 20 Apr 2022 00:04:55 +0200 Subject: [PATCH 1265/1544] [game_skyrimse] Update following cmake_common changes. # Conflicts: # src/CMakeLists.txt --- src/games/skyrimse/CMakeLists.txt | 10 ++++------ src/games/skyrimse/src/CMakeLists.txt | 13 +++++-------- 2 files changed, 9 insertions(+), 14 deletions(-) diff --git a/src/games/skyrimse/CMakeLists.txt b/src/games/skyrimse/CMakeLists.txt index c64b65a3..e4564c51 100644 --- a/src/games/skyrimse/CMakeLists.txt +++ b/src/games/skyrimse/CMakeLists.txt @@ -1,12 +1,10 @@ cmake_minimum_required(VERSION 3.16) -project(game_skyrimse) -set(project_type plugin) -set(enable_warnings OFF) - if(DEFINED DEPENDENCIES_DIR) - include(${DEPENDENCIES_DIR}/modorganizer_super/cmake_common/project.cmake) + include(${DEPENDENCIES_DIR}/modorganizer_super/cmake_common/mo2.cmake) else() - include(../cmake_common/project.cmake) + include(${CMAKE_CURRENT_LIST_DIR}/cmake_common/mo2.cmake) endif() + +project(game_skyrimse) add_subdirectory(src) diff --git a/src/games/skyrimse/src/CMakeLists.txt b/src/games/skyrimse/src/CMakeLists.txt index d1fed507..9b410545 100644 --- a/src/games/skyrimse/src/CMakeLists.txt +++ b/src/games/skyrimse/src/CMakeLists.txt @@ -1,10 +1,7 @@ cmake_minimum_required(VERSION 3.16) -set(additional_translations ${modorganizer_super_path}/game_gamebryo/src) - -if(DEFINED DEPENDENCIES_DIR) - include(${DEPENDENCIES_DIR}/modorganizer_super/cmake_common/src.cmake) -else() - include(../../cmake_common/src.cmake) -endif() -requires_project(game_gamebryo game_features) +add_library(game_skyrimse SHARED) +mo2_configure_plugin(game_skyrimse + WARNINGS OFF + PRIVATE_DEPENDS creation) +mo2_install_target(game_skyrimse) From 127ae2c80cf375d60d03e39761d1c9167d5a61bd Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Mika=C3=ABl=20Capelle?= Date: Wed, 20 Apr 2022 00:05:03 +0200 Subject: [PATCH 1266/1544] [game_skyrimvr] Update following cmake_common changes. # Conflicts: # src/CMakeLists.txt --- src/games/skyrimvr/CMakeLists.txt | 10 ++++------ src/games/skyrimvr/src/CMakeLists.txt | 13 +++++-------- 2 files changed, 9 insertions(+), 14 deletions(-) diff --git a/src/games/skyrimvr/CMakeLists.txt b/src/games/skyrimvr/CMakeLists.txt index a6883a42..f0819cee 100644 --- a/src/games/skyrimvr/CMakeLists.txt +++ b/src/games/skyrimvr/CMakeLists.txt @@ -1,12 +1,10 @@ cmake_minimum_required(VERSION 3.16) -project(game_skyrimvr) -set(project_type plugin) -set(enable_warnings OFF) - if(DEFINED DEPENDENCIES_DIR) - include(${DEPENDENCIES_DIR}/modorganizer_super/cmake_common/project.cmake) + include(${DEPENDENCIES_DIR}/modorganizer_super/cmake_common/mo2.cmake) else() - include(../cmake_common/project.cmake) + include(${CMAKE_CURRENT_LIST_DIR}/cmake_common/mo2.cmake) endif() + +project(game_skyrimvr) add_subdirectory(src) diff --git a/src/games/skyrimvr/src/CMakeLists.txt b/src/games/skyrimvr/src/CMakeLists.txt index d1fed507..4c242e5e 100644 --- a/src/games/skyrimvr/src/CMakeLists.txt +++ b/src/games/skyrimvr/src/CMakeLists.txt @@ -1,10 +1,7 @@ cmake_minimum_required(VERSION 3.16) -set(additional_translations ${modorganizer_super_path}/game_gamebryo/src) - -if(DEFINED DEPENDENCIES_DIR) - include(${DEPENDENCIES_DIR}/modorganizer_super/cmake_common/src.cmake) -else() - include(../../cmake_common/src.cmake) -endif() -requires_project(game_gamebryo game_features) +add_library(game_skyrimvr SHARED) +mo2_configure_plugin(game_skyrimvr + WARNINGS OFF + PRIVATE_DEPENDS creation) +mo2_install_target(game_skyrimvr) From 6771eea113337d493c4faaac5fec7d14adf2faca Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Mika=C3=ABl=20Capelle?= Date: Wed, 20 Apr 2022 00:05:13 +0200 Subject: [PATCH 1267/1544] [game_ttw] Update following cmake_common changes. # Conflicts: # src/CMakeLists.txt --- src/games/ttw/CMakeLists.txt | 10 ++++------ src/games/ttw/src/CMakeLists.txt | 13 +++++-------- 2 files changed, 9 insertions(+), 14 deletions(-) diff --git a/src/games/ttw/CMakeLists.txt b/src/games/ttw/CMakeLists.txt index e8bdaaea..274f5bf2 100644 --- a/src/games/ttw/CMakeLists.txt +++ b/src/games/ttw/CMakeLists.txt @@ -1,12 +1,10 @@ cmake_minimum_required(VERSION 3.16) -project(game_ttw) -set(project_type plugin) -set(enable_warnings OFF) - if(DEFINED DEPENDENCIES_DIR) - include(${DEPENDENCIES_DIR}/modorganizer_super/cmake_common/project.cmake) + include(${DEPENDENCIES_DIR}/modorganizer_super/cmake_common/mo2.cmake) else() - include(../cmake_common/project.cmake) + include(${CMAKE_CURRENT_LIST_DIR}/cmake_common/mo2.cmake) endif() + +project(game_ttw) add_subdirectory(src) diff --git a/src/games/ttw/src/CMakeLists.txt b/src/games/ttw/src/CMakeLists.txt index d1fed507..6dda5bec 100644 --- a/src/games/ttw/src/CMakeLists.txt +++ b/src/games/ttw/src/CMakeLists.txt @@ -1,10 +1,7 @@ cmake_minimum_required(VERSION 3.16) -set(additional_translations ${modorganizer_super_path}/game_gamebryo/src) - -if(DEFINED DEPENDENCIES_DIR) - include(${DEPENDENCIES_DIR}/modorganizer_super/cmake_common/src.cmake) -else() - include(../../cmake_common/src.cmake) -endif() -requires_project(game_gamebryo game_features) +add_library(game_ttw SHARED) +mo2_configure_plugin(game_ttw + WARNINGS OFF + PRIVATE_DEPENDS gamebryo) +mo2_install_target(game_ttw) From 9394a4c57efedca996aa3082a3f5281787974ae1 Mon Sep 17 00:00:00 2001 From: Jeremy Rimpo Date: Thu, 6 Oct 2022 16:13:32 -0500 Subject: [PATCH 1268/1544] [game_skyrimse] Add GOG support / detection --- src/games/skyrimse/src/game_skyrimse_en.ts | 4 +- src/games/skyrimse/src/gameskyrimse.cpp | 53 ++++++++++++++++++---- src/games/skyrimse/src/gameskyrimse.h | 7 +++ 3 files changed, 52 insertions(+), 12 deletions(-) diff --git a/src/games/skyrimse/src/game_skyrimse_en.ts b/src/games/skyrimse/src/game_skyrimse_en.ts index d7f078f7..b35f2dcb 100644 --- a/src/games/skyrimse/src/game_skyrimse_en.ts +++ b/src/games/skyrimse/src/game_skyrimse_en.ts @@ -4,12 +4,12 @@ GameSkyrimSE - + Skyrim Special Edition Support Plugin - + Adds support for the game Skyrim Special Edition. diff --git a/src/games/skyrimse/src/gameskyrimse.cpp b/src/games/skyrimse/src/gameskyrimse.cpp index c224c537..db5d1f33 100644 --- a/src/games/skyrimse/src/gameskyrimse.cpp +++ b/src/games/skyrimse/src/gameskyrimse.cpp @@ -28,13 +28,15 @@ using namespace MOBase; -GameSkyrimSE::GameSkyrimSE() -{ -} +GameSkyrimSE::GameSkyrimSE() {} -void GameSkyrimSE::setGamePath(const QString &path) +void GameSkyrimSE::checkGog() { - m_GamePath = path; + QFileInfo check_file(m_GamePath + "\\Galaxy64.dll"); + if (check_file.exists()) + m_IsGog = true; + else + m_IsGog = false; } QDir GameSkyrimSE::documentsDirectory() const @@ -42,10 +44,35 @@ QDir GameSkyrimSE::documentsDirectory() const return m_MyGamesPath; } +void GameSkyrimSE::detectGame() +{ + m_GamePath = identifyGamePath(); + checkGog(); + m_MyGamesPath = determineMyGamesPath(gameDirectoryName()); +} + QString GameSkyrimSE::identifyGamePath() const { - QString path = "Software\\Bethesda Softworks\\" + gameName(); - return findInRegistry(HKEY_LOCAL_MACHINE, path.toStdWString().c_str(), L"Installed Path"); + QMap paths = { + {"Software\\Bethesda Softworks\\" + gameName(), "Installed Path"}, + {"Software\\GOG.com\\Games\\1162721350", "path"}, + {"Software\\GOG.com\\Games\\1711230643", "path"}, + }; + + QString result; + for (auto &path : paths.toStdMap()) { + result = findInRegistry(HKEY_LOCAL_MACHINE, path.first.toStdWString().c_str(), path.second.toStdWString().c_str()); + if (!result.isEmpty()) + break; + } + return result; +} + +void GameSkyrimSE::setGamePath(const QString& path) +{ + m_GamePath = path; + checkGog(); + m_MyGamesPath = determineMyGamesPath(gameDirectoryName()); } QDir GameSkyrimSE::savesDirectory() const @@ -81,13 +108,19 @@ bool GameSkyrimSE::init(IOrganizer *moInfo) return true; } - - QString GameSkyrimSE::gameName() const { return "Skyrim Special Edition"; } +QString GameSkyrimSE::gameDirectoryName() const +{ + if (m_IsGog) + return "Skyrim Special Edition GOG"; + else + return "Skyrim Special Edition"; +} + QList GameSkyrimSE::executables() const { return QList() @@ -276,7 +309,7 @@ MappingType GameSkyrimSE::mappings() const for (const QString &profileFile : { "plugins.txt", "loadorder.txt" }) { result.push_back({ m_Organizer->profilePath() + "/" + profileFile, - localAppFolder() + "/" + gameName() + "/" + profileFile, + localAppFolder() + "/" + gameDirectoryName() + "/" + profileFile, false }); } diff --git a/src/games/skyrimse/src/gameskyrimse.h b/src/games/skyrimse/src/gameskyrimse.h index 625cae9c..5fe20920 100644 --- a/src/games/skyrimse/src/gameskyrimse.h +++ b/src/games/skyrimse/src/gameskyrimse.h @@ -21,6 +21,7 @@ public: public: // IPluginGame interface + virtual void detectGame() override; virtual QString gameName() const override; virtual QList executables() const override; @@ -60,13 +61,19 @@ protected: QString savegameExtension() const override; QString savegameSEExtension() const override; + QString gameDirectoryName() const; QDir documentsDirectory() const; QDir savesDirectory() const; QFileInfo findInGameFolder(const QString &relativePath) const; QString myGamesPath() const; + void checkGog(); + virtual QString identifyGamePath() const override; +private: + bool m_IsGog = false; + }; #endif // _GAMESKYRIMSE_H From e62650055e518a679c6c37e7df43a3a5345a02cd Mon Sep 17 00:00:00 2001 From: Jeremy Rimpo Date: Thu, 6 Oct 2022 17:24:35 -0500 Subject: [PATCH 1269/1544] [game_skyrimse] Reregister data archive and savegame features when the game path is changed --- src/games/skyrimse/src/game_skyrimse_en.ts | 4 ++-- src/games/skyrimse/src/gameskyrimse.cpp | 2 ++ 2 files changed, 4 insertions(+), 2 deletions(-) diff --git a/src/games/skyrimse/src/game_skyrimse_en.ts b/src/games/skyrimse/src/game_skyrimse_en.ts index b35f2dcb..74cd07be 100644 --- a/src/games/skyrimse/src/game_skyrimse_en.ts +++ b/src/games/skyrimse/src/game_skyrimse_en.ts @@ -4,12 +4,12 @@ GameSkyrimSE - + Skyrim Special Edition Support Plugin - + Adds support for the game Skyrim Special Edition. diff --git a/src/games/skyrimse/src/gameskyrimse.cpp b/src/games/skyrimse/src/gameskyrimse.cpp index db5d1f33..a2bce9af 100644 --- a/src/games/skyrimse/src/gameskyrimse.cpp +++ b/src/games/skyrimse/src/gameskyrimse.cpp @@ -73,6 +73,8 @@ void GameSkyrimSE::setGamePath(const QString& path) m_GamePath = path; checkGog(); m_MyGamesPath = determineMyGamesPath(gameDirectoryName()); + registerFeature(new SkyrimSEDataArchives(myGamesPath())); + registerFeature(new GamebryoLocalSavegames(myGamesPath(), "Skyrimcustom.ini")); } QDir GameSkyrimSE::savesDirectory() const From 9a96c93ec8a57a55067ddc26e4478883357a838d Mon Sep 17 00:00:00 2001 From: Jeremy Rimpo Date: Fri, 7 Oct 2022 00:51:41 -0500 Subject: [PATCH 1270/1544] Add missing include --- src/creation/creationgameplugins.cpp | 1 + src/gamebryo/gamebryogameplugins.cpp | 1 + 2 files changed, 2 insertions(+) diff --git a/src/creation/creationgameplugins.cpp b/src/creation/creationgameplugins.cpp index 2c7f4f34..2c388dbc 100644 --- a/src/creation/creationgameplugins.cpp +++ b/src/creation/creationgameplugins.cpp @@ -7,6 +7,7 @@ #include #include +#include #include using MOBase::IPluginGame; diff --git a/src/gamebryo/gamebryogameplugins.cpp b/src/gamebryo/gamebryogameplugins.cpp index ead565ad..e56724fd 100644 --- a/src/gamebryo/gamebryogameplugins.cpp +++ b/src/gamebryo/gamebryogameplugins.cpp @@ -10,6 +10,7 @@ #include #include #include +#include #include using MOBase::IOrganizer; From ba66fcce3bb022b6d4a99705bdac4bd00aaca9ad Mon Sep 17 00:00:00 2001 From: Jeremy Rimpo Date: Fri, 7 Oct 2022 00:57:36 -0500 Subject: [PATCH 1271/1544] [game_morrowind] Add missing include --- src/games/morrowind/src/morrowindgameplugins.cpp | 1 + 1 file changed, 1 insertion(+) diff --git a/src/games/morrowind/src/morrowindgameplugins.cpp b/src/games/morrowind/src/morrowindgameplugins.cpp index 0e8ae771..ddf64b29 100644 --- a/src/games/morrowind/src/morrowindgameplugins.cpp +++ b/src/games/morrowind/src/morrowindgameplugins.cpp @@ -11,6 +11,7 @@ #include #include #include +#include #include using MOBase::IOrganizer; From 593b96031b21165e14e5506b4ff150b1ac282ce0 Mon Sep 17 00:00:00 2001 From: Jeremy Rimpo Date: Fri, 7 Oct 2022 00:58:22 -0500 Subject: [PATCH 1272/1544] [game_enderalse] Add missing include --- src/games/enderalse/src/enderalsegameplugins.cpp | 2 ++ 1 file changed, 2 insertions(+) diff --git a/src/games/enderalse/src/enderalsegameplugins.cpp b/src/games/enderalse/src/enderalsegameplugins.cpp index de8a377c..55682b90 100644 --- a/src/games/enderalse/src/enderalsegameplugins.cpp +++ b/src/games/enderalse/src/enderalsegameplugins.cpp @@ -5,6 +5,8 @@ #include #include +#include + using namespace MOBase; void EnderalSEGamePlugins::writePluginList(const MOBase::IPluginList* pluginList, const QString& filePath) From d61a9ba262db00f5775b635ba00929d04ff7cc36 Mon Sep 17 00:00:00 2001 From: Jeremy Rimpo Date: Fri, 7 Oct 2022 00:58:56 -0500 Subject: [PATCH 1273/1544] [game_skyrim] Add missing include --- src/games/skyrim/src/skyrimgameplugins.cpp | 1 + 1 file changed, 1 insertion(+) diff --git a/src/games/skyrim/src/skyrimgameplugins.cpp b/src/games/skyrim/src/skyrimgameplugins.cpp index 524132e3..562fff8e 100644 --- a/src/games/skyrim/src/skyrimgameplugins.cpp +++ b/src/games/skyrim/src/skyrimgameplugins.cpp @@ -7,6 +7,7 @@ #include #include +#include using MOBase::IPluginGame; From a7ae797f2b8d0d1f571525fd42dc62a5a4b617c4 Mon Sep 17 00:00:00 2001 From: Jeremy Rimpo Date: Fri, 7 Oct 2022 02:59:18 -0500 Subject: [PATCH 1274/1544] [game_skyrimse] Preliminary Epic Games support --- src/games/skyrimse/src/gameskyrimse.cpp | 54 +++++++++++++++++++++---- src/games/skyrimse/src/gameskyrimse.h | 3 +- 2 files changed, 49 insertions(+), 8 deletions(-) diff --git a/src/games/skyrimse/src/gameskyrimse.cpp b/src/games/skyrimse/src/gameskyrimse.cpp index 24da93db..53700bc4 100644 --- a/src/games/skyrimse/src/gameskyrimse.cpp +++ b/src/games/skyrimse/src/gameskyrimse.cpp @@ -22,6 +22,8 @@ #include #include #include +#include +#include #include #include "scopeguard.h" @@ -30,13 +32,16 @@ using namespace MOBase; GameSkyrimSE::GameSkyrimSE() {} -void GameSkyrimSE::checkGog() +void GameSkyrimSE::checkVariants() { - QFileInfo check_file(m_GamePath + "\\Galaxy64.dll"); - if (check_file.exists()) + m_IsGog = false; + m_IsEpic = false; + QFileInfo gog_dll(m_GamePath + "\\Galaxy64.dll"); + QFileInfo epic_dll(m_GamePath + "\\EOSSDK-Win64-Shipping.dll"); + if (gog_dll.exists()) m_IsGog = true; - else - m_IsGog = false; + else if (epic_dll.exists()) + m_IsEpic = true; } QDir GameSkyrimSE::documentsDirectory() const @@ -47,7 +52,7 @@ QDir GameSkyrimSE::documentsDirectory() const void GameSkyrimSE::detectGame() { m_GamePath = identifyGamePath(); - checkGog(); + checkVariants(); m_MyGamesPath = determineMyGamesPath(gameDirectoryName()); } @@ -65,13 +70,46 @@ QString GameSkyrimSE::identifyGamePath() const if (!result.isEmpty()) break; } + + // Check Epic Games Manifests + // AppName: ac82db5035584c7f8a2c548d98c86b2c + // AE Update: 5d600e4f59974aeba0259c7734134e27 + if (result.isEmpty()) + { + QString manifestDir(getKnownFolderPath(FOLDERID_ProgramData, false)); + QDir epicManifests(manifestDir, "*.item", QDir::SortFlags(QDir::Name | QDir::IgnoreCase), QDir::Files); + if (epicManifests.exists()) { + QDirIterator it(epicManifests); + while (it.hasNext()) { + QString manifestFile = it.next(); + QFile manifest(manifestFile); + + if (!manifest.open(QIODevice::ReadOnly)) { + qWarning("Couldn't open manifest file."); + continue; + } + + QByteArray manifestData = manifest.readAll(); + + QJsonDocument manifestJson(QJsonDocument::fromJson(manifestData)); + + if (manifestJson["AppName"] == "ac82db5035584c7f8a2c548d98c86b2c" || + manifestJson["AppName"] == "5d600e4f59974aeba0259c7734134e27") { + result = manifestJson["InstallLocation"].toString(); + break; + } + } + } + + } + return result; } void GameSkyrimSE::setGamePath(const QString& path) { m_GamePath = path; - checkGog(); + checkVariants(); m_MyGamesPath = determineMyGamesPath(gameDirectoryName()); registerFeature(new SkyrimSEDataArchives(myGamesPath())); registerFeature(new GamebryoLocalSavegames(myGamesPath(), "Skyrimcustom.ini")); @@ -119,6 +157,8 @@ QString GameSkyrimSE::gameDirectoryName() const { if (m_IsGog) return "Skyrim Special Edition GOG"; + else if (m_IsEpic) + return "Skyrim Special Edition EPIC"; else return "Skyrim Special Edition"; } diff --git a/src/games/skyrimse/src/gameskyrimse.h b/src/games/skyrimse/src/gameskyrimse.h index 5fe20920..0727d746 100644 --- a/src/games/skyrimse/src/gameskyrimse.h +++ b/src/games/skyrimse/src/gameskyrimse.h @@ -67,12 +67,13 @@ protected: QFileInfo findInGameFolder(const QString &relativePath) const; QString myGamesPath() const; - void checkGog(); + void checkVariants(); virtual QString identifyGamePath() const override; private: bool m_IsGog = false; + bool m_IsEpic = false; }; From 96a364df48408fb867273e52126444db3c5386c5 Mon Sep 17 00:00:00 2001 From: Jeremy Rimpo Date: Fri, 7 Oct 2022 02:59:18 -0500 Subject: [PATCH 1275/1544] [game_skyrimse] Preliminary Epic Games support --- src/games/skyrimse/src/gameskyrimse.cpp | 54 +++++++++++++++++++++---- src/games/skyrimse/src/gameskyrimse.h | 3 +- 2 files changed, 49 insertions(+), 8 deletions(-) diff --git a/src/games/skyrimse/src/gameskyrimse.cpp b/src/games/skyrimse/src/gameskyrimse.cpp index c83f1742..53a49243 100644 --- a/src/games/skyrimse/src/gameskyrimse.cpp +++ b/src/games/skyrimse/src/gameskyrimse.cpp @@ -22,6 +22,8 @@ #include #include #include +#include +#include #include #include "scopeguard.h" @@ -30,13 +32,16 @@ using namespace MOBase; GameSkyrimSE::GameSkyrimSE() {} -void GameSkyrimSE::checkGog() +void GameSkyrimSE::checkVariants() { - QFileInfo check_file(m_GamePath + "\\Galaxy64.dll"); - if (check_file.exists()) + m_IsGog = false; + m_IsEpic = false; + QFileInfo gog_dll(m_GamePath + "\\Galaxy64.dll"); + QFileInfo epic_dll(m_GamePath + "\\EOSSDK-Win64-Shipping.dll"); + if (gog_dll.exists()) m_IsGog = true; - else - m_IsGog = false; + else if (epic_dll.exists()) + m_IsEpic = true; } QDir GameSkyrimSE::documentsDirectory() const @@ -47,7 +52,7 @@ QDir GameSkyrimSE::documentsDirectory() const void GameSkyrimSE::detectGame() { m_GamePath = identifyGamePath(); - checkGog(); + checkVariants(); m_MyGamesPath = determineMyGamesPath(gameDirectoryName()); } @@ -65,13 +70,46 @@ QString GameSkyrimSE::identifyGamePath() const if (!result.isEmpty()) break; } + + // Check Epic Games Manifests + // AppName: ac82db5035584c7f8a2c548d98c86b2c + // AE Update: 5d600e4f59974aeba0259c7734134e27 + if (result.isEmpty()) + { + QString manifestDir(getKnownFolderPath(FOLDERID_ProgramData, false)); + QDir epicManifests(manifestDir, "*.item", QDir::SortFlags(QDir::Name | QDir::IgnoreCase), QDir::Files); + if (epicManifests.exists()) { + QDirIterator it(epicManifests); + while (it.hasNext()) { + QString manifestFile = it.next(); + QFile manifest(manifestFile); + + if (!manifest.open(QIODevice::ReadOnly)) { + qWarning("Couldn't open manifest file."); + continue; + } + + QByteArray manifestData = manifest.readAll(); + + QJsonDocument manifestJson(QJsonDocument::fromJson(manifestData)); + + if (manifestJson["AppName"] == "ac82db5035584c7f8a2c548d98c86b2c" || + manifestJson["AppName"] == "5d600e4f59974aeba0259c7734134e27") { + result = manifestJson["InstallLocation"].toString(); + break; + } + } + } + + } + return result; } void GameSkyrimSE::setGamePath(const QString& path) { m_GamePath = path; - checkGog(); + checkVariants(); m_MyGamesPath = determineMyGamesPath(gameDirectoryName()); registerFeature(new SkyrimSEDataArchives(myGamesPath())); registerFeature(new GamebryoLocalSavegames(myGamesPath(), "Skyrimcustom.ini")); @@ -119,6 +157,8 @@ QString GameSkyrimSE::gameDirectoryName() const { if (m_IsGog) return "Skyrim Special Edition GOG"; + else if (m_IsEpic) + return "Skyrim Special Edition EPIC"; else return "Skyrim Special Edition"; } diff --git a/src/games/skyrimse/src/gameskyrimse.h b/src/games/skyrimse/src/gameskyrimse.h index 5fe20920..0727d746 100644 --- a/src/games/skyrimse/src/gameskyrimse.h +++ b/src/games/skyrimse/src/gameskyrimse.h @@ -67,12 +67,13 @@ protected: QFileInfo findInGameFolder(const QString &relativePath) const; QString myGamesPath() const; - void checkGog(); + void checkVariants(); virtual QString identifyGamePath() const override; private: bool m_IsGog = false; + bool m_IsEpic = false; }; From 293eca16073fe784f0489d8b33646b9f66b4b840 Mon Sep 17 00:00:00 2001 From: Jeremy Rimpo Date: Fri, 7 Oct 2022 14:57:14 -0500 Subject: [PATCH 1276/1544] [game_skyrimse] Check the registry for th EG Manifest location - Also fixes some missing paths --- src/games/skyrimse/src/gameskyrimse.cpp | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) diff --git a/src/games/skyrimse/src/gameskyrimse.cpp b/src/games/skyrimse/src/gameskyrimse.cpp index 53700bc4..060eb05e 100644 --- a/src/games/skyrimse/src/gameskyrimse.cpp +++ b/src/games/skyrimse/src/gameskyrimse.cpp @@ -76,7 +76,11 @@ QString GameSkyrimSE::identifyGamePath() const // AE Update: 5d600e4f59974aeba0259c7734134e27 if (result.isEmpty()) { - QString manifestDir(getKnownFolderPath(FOLDERID_ProgramData, false)); + // Use the registry entry to find the EGL Data dir first, just in case something changes + QString manifestDir = findInRegistry(HKEY_LOCAL_MACHINE, L"SOFTWARE\\WOW6432Node\\Epic Games\\EpicGamesLauncher", L"AppDataPath"); + if (manifestDir.isEmpty()) + manifestDir = getKnownFolderPath(FOLDERID_ProgramData, false) + "\\Epic\\EpicGamesLauncher\\Data\\"; + manifestDir += "Manifests"; QDir epicManifests(manifestDir, "*.item", QDir::SortFlags(QDir::Name | QDir::IgnoreCase), QDir::Files); if (epicManifests.exists()) { QDirIterator it(epicManifests); @@ -85,7 +89,7 @@ QString GameSkyrimSE::identifyGamePath() const QFile manifest(manifestFile); if (!manifest.open(QIODevice::ReadOnly)) { - qWarning("Couldn't open manifest file."); + qWarning("Couldn't open Epic Games manifest file."); continue; } From cce40cd935b652da99be114bcaab360854701b4d Mon Sep 17 00:00:00 2001 From: Jeremy Rimpo Date: Fri, 7 Oct 2022 14:57:14 -0500 Subject: [PATCH 1277/1544] [game_skyrimse] Check the registry for th EG Manifest location - Also fixes some missing paths --- src/games/skyrimse/src/gameskyrimse.cpp | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) diff --git a/src/games/skyrimse/src/gameskyrimse.cpp b/src/games/skyrimse/src/gameskyrimse.cpp index 53a49243..a54db272 100644 --- a/src/games/skyrimse/src/gameskyrimse.cpp +++ b/src/games/skyrimse/src/gameskyrimse.cpp @@ -76,7 +76,11 @@ QString GameSkyrimSE::identifyGamePath() const // AE Update: 5d600e4f59974aeba0259c7734134e27 if (result.isEmpty()) { - QString manifestDir(getKnownFolderPath(FOLDERID_ProgramData, false)); + // Use the registry entry to find the EGL Data dir first, just in case something changes + QString manifestDir = findInRegistry(HKEY_LOCAL_MACHINE, L"SOFTWARE\\WOW6432Node\\Epic Games\\EpicGamesLauncher", L"AppDataPath"); + if (manifestDir.isEmpty()) + manifestDir = getKnownFolderPath(FOLDERID_ProgramData, false) + "\\Epic\\EpicGamesLauncher\\Data\\"; + manifestDir += "Manifests"; QDir epicManifests(manifestDir, "*.item", QDir::SortFlags(QDir::Name | QDir::IgnoreCase), QDir::Files); if (epicManifests.exists()) { QDirIterator it(epicManifests); @@ -85,7 +89,7 @@ QString GameSkyrimSE::identifyGamePath() const QFile manifest(manifestFile); if (!manifest.open(QIODevice::ReadOnly)) { - qWarning("Couldn't open manifest file."); + qWarning("Couldn't open Epic Games manifest file."); continue; } From daba3a22b56d71eed3da38426355f81e9089cd04 Mon Sep 17 00:00:00 2001 From: Jeremy Rimpo Date: Fri, 7 Oct 2022 16:11:42 -0500 Subject: [PATCH 1278/1544] [game_skyrimse] Migrate to variant system --- src/games/skyrimse/src/gameskyrimse.cpp | 28 +++++++++++++++---------- src/games/skyrimse/src/gameskyrimse.h | 5 +---- 2 files changed, 18 insertions(+), 15 deletions(-) diff --git a/src/games/skyrimse/src/gameskyrimse.cpp b/src/games/skyrimse/src/gameskyrimse.cpp index 060eb05e..c8872858 100644 --- a/src/games/skyrimse/src/gameskyrimse.cpp +++ b/src/games/skyrimse/src/gameskyrimse.cpp @@ -32,16 +32,21 @@ using namespace MOBase; GameSkyrimSE::GameSkyrimSE() {} +void GameSkyrimSE::setVariant(QString variant) +{ + m_GameVariant = variant; +} + void GameSkyrimSE::checkVariants() { - m_IsGog = false; - m_IsEpic = false; QFileInfo gog_dll(m_GamePath + "\\Galaxy64.dll"); QFileInfo epic_dll(m_GamePath + "\\EOSSDK-Win64-Shipping.dll"); if (gog_dll.exists()) - m_IsGog = true; + setVariant("GOG"); else if (epic_dll.exists()) - m_IsEpic = true; + setVariant("Epic Games"); + else + setVariant("Steam"); } QDir GameSkyrimSE::documentsDirectory() const @@ -104,7 +109,6 @@ QString GameSkyrimSE::identifyGamePath() const } } } - } return result; @@ -159,9 +163,9 @@ QString GameSkyrimSE::gameName() const QString GameSkyrimSE::gameDirectoryName() const { - if (m_IsGog) + if (selectedVariant() == "GOG") return "Skyrim Special Edition GOG"; - else if (m_IsEpic) + else if (selectedVariant() == "Epic Games") return "Skyrim Special Edition EPIC"; else return "Skyrim Special Edition"; @@ -210,7 +214,7 @@ QString GameSkyrimSE::description() const MOBase::VersionInfo GameSkyrimSE::version() const { - return VersionInfo(1, 6, 0, VersionInfo::RELEASE_FINAL); + return VersionInfo(1, 7, 0, VersionInfo::RELEASE_CANDIDATE); } QList GameSkyrimSE::settings() const @@ -223,7 +227,7 @@ QList GameSkyrimSE::settings() const void GameSkyrimSE::initializeProfile(const QDir &path, ProfileSettings settings) const { if (settings.testFlag(IPluginGame::MODS)) { - copyToProfile(localAppFolder() + "/Skyrim Special Edition", path, "plugins.txt"); + copyToProfile(localAppFolder() + "/" + gameDirectoryName(), path, "plugins.txt"); } if (settings.testFlag(IPluginGame::CONFIGURATION)) { @@ -257,7 +261,9 @@ std::shared_ptr GameSkyrimSE::makeSaveGame(QString fileP QString GameSkyrimSE::steamAPPId() const { - return "489830"; + if (selectedVariant() == "Steam") + return "489830"; + return QString(); } QStringList GameSkyrimSE::primaryPlugins() const @@ -277,7 +283,7 @@ QStringList GameSkyrimSE::primaryPlugins() const QStringList GameSkyrimSE::gameVariants() const { - return{ "Regular" }; + return{ "Steam", "GOG", "Epic Games" }; } QString GameSkyrimSE::gameShortName() const diff --git a/src/games/skyrimse/src/gameskyrimse.h b/src/games/skyrimse/src/gameskyrimse.h index 0727d746..2a757f85 100644 --- a/src/games/skyrimse/src/gameskyrimse.h +++ b/src/games/skyrimse/src/gameskyrimse.h @@ -68,13 +68,10 @@ protected: QString myGamesPath() const; void checkVariants(); + void setVariant(QString variant); virtual QString identifyGamePath() const override; -private: - bool m_IsGog = false; - bool m_IsEpic = false; - }; #endif // _GAMESKYRIMSE_H From 3c870dfe63face487f12cd49e72f50a2d277e0cf Mon Sep 17 00:00:00 2001 From: Jeremy Rimpo Date: Fri, 7 Oct 2022 16:11:42 -0500 Subject: [PATCH 1279/1544] [game_skyrimse] Migrate to variant system --- src/games/skyrimse/src/gameskyrimse.cpp | 28 +++++++++++++++---------- src/games/skyrimse/src/gameskyrimse.h | 5 +---- 2 files changed, 18 insertions(+), 15 deletions(-) diff --git a/src/games/skyrimse/src/gameskyrimse.cpp b/src/games/skyrimse/src/gameskyrimse.cpp index a54db272..a18c3731 100644 --- a/src/games/skyrimse/src/gameskyrimse.cpp +++ b/src/games/skyrimse/src/gameskyrimse.cpp @@ -32,16 +32,21 @@ using namespace MOBase; GameSkyrimSE::GameSkyrimSE() {} +void GameSkyrimSE::setVariant(QString variant) +{ + m_GameVariant = variant; +} + void GameSkyrimSE::checkVariants() { - m_IsGog = false; - m_IsEpic = false; QFileInfo gog_dll(m_GamePath + "\\Galaxy64.dll"); QFileInfo epic_dll(m_GamePath + "\\EOSSDK-Win64-Shipping.dll"); if (gog_dll.exists()) - m_IsGog = true; + setVariant("GOG"); else if (epic_dll.exists()) - m_IsEpic = true; + setVariant("Epic Games"); + else + setVariant("Steam"); } QDir GameSkyrimSE::documentsDirectory() const @@ -104,7 +109,6 @@ QString GameSkyrimSE::identifyGamePath() const } } } - } return result; @@ -159,9 +163,9 @@ QString GameSkyrimSE::gameName() const QString GameSkyrimSE::gameDirectoryName() const { - if (m_IsGog) + if (selectedVariant() == "GOG") return "Skyrim Special Edition GOG"; - else if (m_IsEpic) + else if (selectedVariant() == "Epic Games") return "Skyrim Special Edition EPIC"; else return "Skyrim Special Edition"; @@ -210,7 +214,7 @@ QString GameSkyrimSE::description() const MOBase::VersionInfo GameSkyrimSE::version() const { - return VersionInfo(1, 6, 0, VersionInfo::RELEASE_FINAL); + return VersionInfo(1, 7, 0, VersionInfo::RELEASE_CANDIDATE); } QList GameSkyrimSE::settings() const @@ -223,7 +227,7 @@ QList GameSkyrimSE::settings() const void GameSkyrimSE::initializeProfile(const QDir &path, ProfileSettings settings) const { if (settings.testFlag(IPluginGame::MODS)) { - copyToProfile(localAppFolder() + "/Skyrim Special Edition", path, "plugins.txt"); + copyToProfile(localAppFolder() + "/" + gameDirectoryName(), path, "plugins.txt"); } if (settings.testFlag(IPluginGame::CONFIGURATION)) { @@ -257,7 +261,9 @@ std::shared_ptr GameSkyrimSE::makeSaveGame(QString fileP QString GameSkyrimSE::steamAPPId() const { - return "489830"; + if (selectedVariant() == "Steam") + return "489830"; + return QString(); } QStringList GameSkyrimSE::primaryPlugins() const @@ -277,7 +283,7 @@ QStringList GameSkyrimSE::primaryPlugins() const QStringList GameSkyrimSE::gameVariants() const { - return{ "Regular" }; + return{ "Steam", "GOG", "Epic Games" }; } QString GameSkyrimSE::gameShortName() const diff --git a/src/games/skyrimse/src/gameskyrimse.h b/src/games/skyrimse/src/gameskyrimse.h index 0727d746..2a757f85 100644 --- a/src/games/skyrimse/src/gameskyrimse.h +++ b/src/games/skyrimse/src/gameskyrimse.h @@ -68,13 +68,10 @@ protected: QString myGamesPath() const; void checkVariants(); + void setVariant(QString variant); virtual QString identifyGamePath() const override; -private: - bool m_IsGog = false; - bool m_IsEpic = false; - }; #endif // _GAMESKYRIMSE_H From adf0342beed1d40ce497672f92a5f30f208a931c Mon Sep 17 00:00:00 2001 From: Jeremy Rimpo Date: Sat, 8 Oct 2022 00:16:30 -0500 Subject: [PATCH 1280/1544] [game_skyrimse] Bump version, update authors --- src/games/skyrimse/src/gameskyrimse.cpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/games/skyrimse/src/gameskyrimse.cpp b/src/games/skyrimse/src/gameskyrimse.cpp index a18c3731..dad013d4 100644 --- a/src/games/skyrimse/src/gameskyrimse.cpp +++ b/src/games/skyrimse/src/gameskyrimse.cpp @@ -204,7 +204,7 @@ QString GameSkyrimSE::localizedName() const QString GameSkyrimSE::author() const { - return "Archost & ZachHaber"; + return "MO2 Team, Orig: Archost & ZachHaber"; } QString GameSkyrimSE::description() const @@ -214,7 +214,7 @@ QString GameSkyrimSE::description() const MOBase::VersionInfo GameSkyrimSE::version() const { - return VersionInfo(1, 7, 0, VersionInfo::RELEASE_CANDIDATE); + return VersionInfo(1, 7, 0, VersionInfo::RELEASE_FINAL); } QList GameSkyrimSE::settings() const From 9b74dd49ce1a1f8f416ace0191fe4bf08629feef Mon Sep 17 00:00:00 2001 From: Jeremy Rimpo Date: Sat, 8 Oct 2022 00:16:30 -0500 Subject: [PATCH 1281/1544] [game_skyrimse] Bump version, update authors (cherry picked from commit adf0342beed1d40ce497672f92a5f30f208a931c) --- src/games/skyrimse/src/gameskyrimse.cpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/games/skyrimse/src/gameskyrimse.cpp b/src/games/skyrimse/src/gameskyrimse.cpp index c8872858..10a98c15 100644 --- a/src/games/skyrimse/src/gameskyrimse.cpp +++ b/src/games/skyrimse/src/gameskyrimse.cpp @@ -204,7 +204,7 @@ QString GameSkyrimSE::localizedName() const QString GameSkyrimSE::author() const { - return "Archost & ZachHaber"; + return "MO2 Team, Orig: Archost & ZachHaber"; } QString GameSkyrimSE::description() const @@ -214,7 +214,7 @@ QString GameSkyrimSE::description() const MOBase::VersionInfo GameSkyrimSE::version() const { - return VersionInfo(1, 7, 0, VersionInfo::RELEASE_CANDIDATE); + return VersionInfo(1, 7, 0, VersionInfo::RELEASE_FINAL); } QList GameSkyrimSE::settings() const From 6e63ae6b9f807387a1f712681650ec8c12ebb3d3 Mon Sep 17 00:00:00 2001 From: Jeremy Rimpo Date: Sat, 22 Oct 2022 18:48:12 -0500 Subject: [PATCH 1282/1544] [game_skyrimvr] VR does not support light plugins --- src/games/skyrimvr/src/game_skyrimvr_en.ts | 161 ------------------ .../skyrimvr/src/skyrimvrgameplugins.cpp | 12 ++ src/games/skyrimvr/src/skyrimvrgameplugins.h | 22 +++ 3 files changed, 34 insertions(+), 161 deletions(-) create mode 100644 src/games/skyrimvr/src/skyrimvrgameplugins.cpp create mode 100644 src/games/skyrimvr/src/skyrimvrgameplugins.h diff --git a/src/games/skyrimvr/src/game_skyrimvr_en.ts b/src/games/skyrimvr/src/game_skyrimvr_en.ts index cdffe986..ecc3f2a7 100644 --- a/src/games/skyrimvr/src/game_skyrimvr_en.ts +++ b/src/games/skyrimvr/src/game_skyrimvr_en.ts @@ -14,165 +14,4 @@ - - GamebryoModDataContent - - - Plugins (ESP/ESM/ESL) - - - - - Optional Plugins - - - - - Interface - - - - - Meshes - - - - - Bethesda Archive - - - - - Scripts (Papyrus) - - - - - Script Extender Plugin - - - - - Script Extender Files - - - - - SkyProc Patcher - - - - - Sound or Music - - - - - Textures - - - - - MCM Configuration - - - - - INI Files - - - - - FaceGen Data - - - - - ModGroup Files - - - - - GamebryoSaveGameInfoWidget - - - Save # - - - - - Character - - - - - Level - - - - - Location - - - - - Date - - - - - Has Script Extender Data - - - - - Missing ESPs - - - - - - None - - - - - Missing ESLs - - - - - QObject - - - - Some of your plugins have invalid names! These plugins can not be loaded by the game. Please see mo_interface.log for a list of affected plugins and rename them. - - - - - %1, #%2, Level %3, %4 - - - - - failed to open %1 - - - - - wrong file format - expected %1 got %2 - - - - - failed to query registry path (preflight): %1 - - - - - failed to query registry path (read): %1 - - - diff --git a/src/games/skyrimvr/src/skyrimvrgameplugins.cpp b/src/games/skyrimvr/src/skyrimvrgameplugins.cpp new file mode 100644 index 00000000..f310f82e --- /dev/null +++ b/src/games/skyrimvr/src/skyrimvrgameplugins.cpp @@ -0,0 +1,12 @@ +#include "skyrimvrgameplugins.h" + +using namespace MOBase; + +SkyrimVRGamePlugins::SkyrimVRGamePlugins(MOBase::IOrganizer* organizer) : CreationGamePlugins(organizer) +{ +} + +bool SkyrimVRGamePlugins::lightPluginsAreSupported() +{ + return false; +} \ No newline at end of file diff --git a/src/games/skyrimvr/src/skyrimvrgameplugins.h b/src/games/skyrimvr/src/skyrimvrgameplugins.h new file mode 100644 index 00000000..97ee0fe7 --- /dev/null +++ b/src/games/skyrimvr/src/skyrimvrgameplugins.h @@ -0,0 +1,22 @@ +#ifndef _SKYRIMVRGAMEPLUGINS_H +#define _SKYRIMVRGAMEPLUGINS_H + +#include + +#include +#include + +class SkyrimVRGamePlugins : public CreationGamePlugins +{ + +public: + + SkyrimVRGamePlugins(MOBase::IOrganizer* organizer); + +protected: + + virtual bool lightPluginsAreSupported() override; + +}; + +#endif // _SKYRIMVRGAMEPLUGINS_H \ No newline at end of file From 49dea9d1a5d70332e453a897a38e8532446030dd Mon Sep 17 00:00:00 2001 From: Jeremy Rimpo Date: Sat, 22 Oct 2022 18:48:12 -0500 Subject: [PATCH 1283/1544] [game_fallout4vr] VR does not support light plugins --- .../fallout4vr/src/fallout4vrgameplugins.cpp | 12 ++++++++++ .../fallout4vr/src/fallout4vrgameplugins.h | 22 +++++++++++++++++++ src/games/fallout4vr/src/gamefallout4vr.cpp | 4 ++-- 3 files changed, 36 insertions(+), 2 deletions(-) create mode 100644 src/games/fallout4vr/src/fallout4vrgameplugins.cpp create mode 100644 src/games/fallout4vr/src/fallout4vrgameplugins.h diff --git a/src/games/fallout4vr/src/fallout4vrgameplugins.cpp b/src/games/fallout4vr/src/fallout4vrgameplugins.cpp new file mode 100644 index 00000000..8db9e372 --- /dev/null +++ b/src/games/fallout4vr/src/fallout4vrgameplugins.cpp @@ -0,0 +1,12 @@ +#include "fallout4vrgameplugins.h" + +using namespace MOBase; + +Fallout4VRGamePlugins::Fallout4VRGamePlugins(MOBase::IOrganizer* organizer) : CreationGamePlugins(organizer) +{ +} + +bool Fallout4VRGamePlugins::lightPluginsAreSupported() +{ + return false; +} \ No newline at end of file diff --git a/src/games/fallout4vr/src/fallout4vrgameplugins.h b/src/games/fallout4vr/src/fallout4vrgameplugins.h new file mode 100644 index 00000000..1909a844 --- /dev/null +++ b/src/games/fallout4vr/src/fallout4vrgameplugins.h @@ -0,0 +1,22 @@ +#ifndef _FALLOUT4VRGAMEPLUGINS_H +#define _FALLOUT4VRGAMEPLUGINS_H + +#include + +#include +#include + +class Fallout4VRGamePlugins : public CreationGamePlugins +{ + +public: + + Fallout4VRGamePlugins(MOBase::IOrganizer* organizer); + +protected: + + virtual bool lightPluginsAreSupported() override; + +}; + +#endif // _FALLOUT4VRGAMEPLUGINS_H \ No newline at end of file diff --git a/src/games/fallout4vr/src/gamefallout4vr.cpp b/src/games/fallout4vr/src/gamefallout4vr.cpp index fcf8a36d..f9c4ad8e 100644 --- a/src/games/fallout4vr/src/gamefallout4vr.cpp +++ b/src/games/fallout4vr/src/gamefallout4vr.cpp @@ -5,12 +5,12 @@ #include "fallout4vrmoddatachecker.h" #include "fallout4vrmoddatacontent.h" #include "fallout4vrsavegame.h" +#include "fallout4vrgameplugins.h" #include #include #include #include -#include #include "versioninfo.h" #include @@ -42,7 +42,7 @@ bool GameFallout4VR::init(IOrganizer *moInfo) registerFeature(new Fallout4VRModDataChecker(this)); registerFeature(new Fallout4VRModDataContent(this)); registerFeature(new GamebryoSaveGameInfo(this)); - registerFeature(new CreationGamePlugins(moInfo)); + registerFeature(new Fallout4VRGamePlugins(moInfo)); registerFeature(new Fallout4VRUnmangedMods(this)); return true; From e0e655f0eff4d8fd650d853864fb8e75c6b0ec57 Mon Sep 17 00:00:00 2001 From: Jeremy Rimpo Date: Sun, 23 Oct 2022 02:17:53 -0500 Subject: [PATCH 1284/1544] [game_skyrimvr] VR does not support light plugins --- src/games/skyrimvr/src/gameskyrimvr.cpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/games/skyrimvr/src/gameskyrimvr.cpp b/src/games/skyrimvr/src/gameskyrimvr.cpp index f849db52..995d6604 100644 --- a/src/games/skyrimvr/src/gameskyrimvr.cpp +++ b/src/games/skyrimvr/src/gameskyrimvr.cpp @@ -6,12 +6,12 @@ #include "skyrimvrmoddatachecker.h" #include "skyrimvrmoddatacontent.h" #include "skyrimvrsavegame.h" +#include "skyrimvrgameplugins.h" #include #include #include #include -#include #include "versioninfo.h" #include @@ -74,7 +74,7 @@ bool GameSkyrimVR::init(IOrganizer *moInfo) registerFeature(new SkyrimVRModDataChecker(this)); registerFeature(new GamebryoSaveGameInfo(this)); registerFeature(new SkyrimVRModDataContent(this)); - registerFeature(new CreationGamePlugins(moInfo)); + registerFeature(new SkyrimVRGamePlugins(moInfo)); registerFeature(new SkyrimVRUnmangedMods(this)); return true; From 7a087c43739fce59a02b8a1bcb4198fc4a251742 Mon Sep 17 00:00:00 2001 From: Jeremy Rimpo Date: Sun, 23 Oct 2022 02:18:44 -0500 Subject: [PATCH 1285/1544] [game_fallout76] Updates for Qt6 / MO 2.5 --- src/games/fallout76/CMakeLists.txt | 10 ++++------ src/games/fallout76/src/CMakeLists.txt | 11 +++++------ src/games/fallout76/src/fallout76dataarchives.cpp | 14 ++++++++------ src/games/fallout76/src/fallout76savegame.cpp | 9 +++++---- src/games/fallout76/src/fallout76savegame.h | 10 +++++----- src/games/fallout76/src/gamefallout76.cpp | 6 +++--- 6 files changed, 30 insertions(+), 30 deletions(-) diff --git a/src/games/fallout76/CMakeLists.txt b/src/games/fallout76/CMakeLists.txt index 503b6ae0..4d895af7 100644 --- a/src/games/fallout76/CMakeLists.txt +++ b/src/games/fallout76/CMakeLists.txt @@ -1,12 +1,10 @@ cmake_minimum_required(VERSION 3.16) -project(game_fallout76) -set(project_type plugin) -set(enable_warnings OFF) - if(DEFINED DEPENDENCIES_DIR) - include(${DEPENDENCIES_DIR}/modorganizer_super/cmake_common/project.cmake) + include(${DEPENDENCIES_DIR}/modorganizer_super/cmake_common/mo2.cmake) else() - include(../cmake_common/project.cmake) + include(${CMAKE_CURRENT_LIST_DIR}/cmake_common/mo2.cmake) endif() + +project(game_fallout76) add_subdirectory(src) diff --git a/src/games/fallout76/src/CMakeLists.txt b/src/games/fallout76/src/CMakeLists.txt index 3b4e7319..ece6b723 100644 --- a/src/games/fallout76/src/CMakeLists.txt +++ b/src/games/fallout76/src/CMakeLists.txt @@ -1,8 +1,7 @@ cmake_minimum_required(VERSION 3.16) -if(DEFINED DEPENDENCIES_DIR) - include(${DEPENDENCIES_DIR}/modorganizer_super/cmake_common/src.cmake) -else() - include(../../cmake_common/src.cmake) -endif() -requires_project(game_features game_gamebryo) +add_library(game_fallout76 SHARED) +mo2_configure_plugin(game_fallout76 + WARNINGS OFF + PRIVATE_DEPENDS creation) +mo2_install_target(game_fallout76) diff --git a/src/games/fallout76/src/fallout76dataarchives.cpp b/src/games/fallout76/src/fallout76dataarchives.cpp index e00bce76..3148f034 100644 --- a/src/games/fallout76/src/fallout76dataarchives.cpp +++ b/src/games/fallout76/src/fallout76dataarchives.cpp @@ -3,6 +3,8 @@ #include "iprofile.h" #include +#include + Fallout76DataArchives::Fallout76DataArchives(const QDir &myGamesDir) : GamebryoDataArchives(myGamesDir) {} @@ -117,17 +119,17 @@ void Fallout76DataArchives::writeArchiveList(MOBase::IProfile *profile, const QS for (int i = 0; i < before.size(); ++i) { QString archive = before[i]; - if (archive.contains(QRegExp(" - Textures(\\d{2})\\.ba2$"))) { + if (archive.contains(QRegularExpression(" - Textures(\\d{2})\\.ba2$"))) { sResourceIndexFileList.append(archive); - } else if (archive.contains(QRegExp(" - (Interface|Localization|Shaders|Startup)\\.ba2$"))) { + } else if (archive.contains(QRegularExpression(" - (Interface|Localization|Shaders|Startup)\\.ba2$"))) { sResourceStartUpArchiveList.append(archive); - } else if (archive.contains(QRegExp(" - (Interface|Materials|MiscClient|Shaders)\\.ba2$"))) { + } else if (archive.contains(QRegularExpression(" - (Interface|Materials|MiscClient|Shaders)\\.ba2$"))) { SResourceArchiveMemoryCacheList.append(archive); - } else if (archive.contains(QRegExp(" - (GeneratedMeshes|Materials|Meshes(\\d{2}|\\w+)?|MiscClient|Sounds\\d{2}|Startup|Voices)\\.ba2$"))) { + } else if (archive.contains(QRegularExpression(" - (GeneratedMeshes|Materials|Meshes(\\d{2}|\\w+)?|MiscClient|Sounds\\d{2}|Startup|Voices)\\.ba2$"))) { SResourceArchiveList.append(archive); - } else if (archive.contains(QRegExp(" - (Animations|Enlighten(Interiors|Exteriors\\d{2})|GeneratedTextures)\\.ba2$"))) { + } else if (archive.contains(QRegularExpression(" - (Animations|Enlighten(Interiors|Exteriors\\d{2})|GeneratedTextures)\\.ba2$"))) { SResourceArchiveList2.append(archive); - } else if (archive.contains(QRegExp(" - ATX_.*\\.ba2$"))) { + } else if (archive.contains(QRegularExpression(" - ATX_.*\\.ba2$"))) { // if it is named after DLC, it has to go here sResourceArchive2List.append(archive); } else { diff --git a/src/games/fallout76/src/fallout76savegame.cpp b/src/games/fallout76/src/fallout76savegame.cpp index 98da5a07..ee332747 100644 --- a/src/games/fallout76/src/fallout76savegame.cpp +++ b/src/games/fallout76/src/fallout76savegame.cpp @@ -20,10 +20,10 @@ Fallout76SaveGame::Fallout76SaveGame(QString const& fileName, GameFallout76 cons } void Fallout76SaveGame::fetchInformationFields(FileWrapper& file, - QString& playerName, - unsigned short& playerLevel, - QString& playerLocation, - unsigned long& saveNumber, + QString playerName, + unsigned short playerLevel, + QString playerLocation, + unsigned long saveNumber, FILETIME& creationTime) const { file.skip(); // header size @@ -64,6 +64,7 @@ std::unique_ptr Fallout76SaveGame::fetchDataFields file.readImage(384, true); uint8_t saveGameVersion = file.readChar(); + QString ignore; file.read(ignore); // game version file.skip(); // plugin info size diff --git a/src/games/fallout76/src/fallout76savegame.h b/src/games/fallout76/src/fallout76savegame.h index 8de6cca9..7358c3f5 100644 --- a/src/games/fallout76/src/fallout76savegame.h +++ b/src/games/fallout76/src/fallout76savegame.h @@ -1,7 +1,7 @@ #ifndef FALLOUT76SAVEGAME_H #define FALLOUT76SAVEGAME_H -#include #include "gamebryosavegame.h" @@ -16,10 +16,10 @@ protected: // Fetch easy-to-access information. void fetchInformationFields(FileWrapper& wrapper, - QString& playerName, - unsigned short& playerLevel, - QString& playerLocation, - unsigned long& saveNumber, + QString playerName, + unsigned short playerLevel, + QString playerLocation, + unsigned long saveNumber, FILETIME& creationTime) const; std::unique_ptr fetchDataFields() const override; diff --git a/src/games/fallout76/src/gamefallout76.cpp b/src/games/fallout76/src/gamefallout76.cpp index 52bb3647..3a8f9331 100644 --- a/src/games/fallout76/src/gamefallout76.cpp +++ b/src/games/fallout76/src/gamefallout76.cpp @@ -59,7 +59,7 @@ QList GameFallout76::executables() const << ExecutableInfo("Fallout 76", findInGameFolder(binaryName())) << ExecutableInfo("Fallout Launcher", findInGameFolder(getLauncherName())) << ExecutableInfo("Creation Kit", findInGameFolder("CreationKit.exe")) - << ExecutableInfo("LOOT", getLootPath()).withArgument("--game=\"Fallout76\"") + << ExecutableInfo("LOOT", QFileInfo(getLootPath())).withArgument("--game=\"Fallout76\"") ; } @@ -74,7 +74,7 @@ QString GameFallout76::name() const QString GameFallout76::author() const { - return "EntranceJew & Holt59"; + return "Mod Organizer Team; EntranceJew"; } QString GameFallout76::description() const @@ -85,7 +85,7 @@ QString GameFallout76::description() const MOBase::VersionInfo GameFallout76::version() const { - return VersionInfo(3, 0, 0, VersionInfo::RELEASE_ALPHA); + return VersionInfo(3, 0, 1, VersionInfo::RELEASE_ALPHA); } QList GameFallout76::settings() const From 899f3333b6a700ef601341d250662d75a99988fd Mon Sep 17 00:00:00 2001 From: Jeremy Rimpo Date: Wed, 26 Oct 2022 03:10:50 -0500 Subject: [PATCH 1286/1544] [game_skyrimse] Add steam appid for Creation Kit --- src/games/skyrimse/src/gameskyrimse.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/games/skyrimse/src/gameskyrimse.cpp b/src/games/skyrimse/src/gameskyrimse.cpp index 10a98c15..24f28552 100644 --- a/src/games/skyrimse/src/gameskyrimse.cpp +++ b/src/games/skyrimse/src/gameskyrimse.cpp @@ -177,7 +177,7 @@ QList GameSkyrimSE::executables() const << ExecutableInfo("SKSE", findInGameFolder(feature()->loaderName())) << ExecutableInfo("Skyrim Special Edition", findInGameFolder(binaryName())) << ExecutableInfo("Skyrim Special Edition Launcher", findInGameFolder(getLauncherName())) - << ExecutableInfo("Creation Kit", findInGameFolder("CreationKit.exe")) + << ExecutableInfo("Creation Kit", findInGameFolder("CreationKit.exe")).withSteamAppId("1946180") << ExecutableInfo("LOOT", QFileInfo(getLootPath())).withArgument("--game=\"Skyrim Special Edition\"") ; } From a81649b79c2fe59519dac4e916875b1079d34159 Mon Sep 17 00:00:00 2001 From: Jeremy Rimpo Date: Wed, 26 Oct 2022 03:10:50 -0500 Subject: [PATCH 1287/1544] [game_fallout4] Add steam appid for Creation Kit --- src/games/fallout4/src/gamefallout4.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/games/fallout4/src/gamefallout4.cpp b/src/games/fallout4/src/gamefallout4.cpp index 1fb92a17..8482c04e 100644 --- a/src/games/fallout4/src/gamefallout4.cpp +++ b/src/games/fallout4/src/gamefallout4.cpp @@ -67,7 +67,7 @@ QList GameFallout4::executables() const << ExecutableInfo("F4SE", findInGameFolder(feature()->loaderName())) << ExecutableInfo("Fallout 4", findInGameFolder(binaryName())) << ExecutableInfo("Fallout Launcher", findInGameFolder(getLauncherName())) - << ExecutableInfo("Creation Kit", findInGameFolder("CreationKit.exe")) + << ExecutableInfo("Creation Kit", findInGameFolder("CreationKit.exe")).withSteamAppId("1946160") << ExecutableInfo("LOOT", QFileInfo(getLootPath())).withArgument("--game=\"Fallout4\"") ; } From 6daa22bb1ccbb8e9c8d779001ff714f8d8c8418c Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Mika=C3=ABl=20Capelle?= Date: Thu, 13 Jul 2023 20:27:52 +0200 Subject: [PATCH 1288/1544] Apply clang-format. --- .clang-format | 41 +++ .gitattributes | 7 + src/creation/creationgameplugins.cpp | 120 +++++---- src/creation/creationgameplugins.h | 14 +- ...ame_gamebryo_en.ts => game_creation_en.ts} | 2 +- src/gamebryo/dummybsa.cpp | 105 ++++---- src/gamebryo/dummybsa.h | 19 +- src/gamebryo/game_gamebryo_en.ts | 52 ++-- src/gamebryo/gamebryobsainvalidation.cpp | 83 +++--- src/gamebryo/gamebryobsainvalidation.h | 32 ++- src/gamebryo/gamebryodataarchives.cpp | 33 ++- src/gamebryo/gamebryodataarchives.h | 25 +- src/gamebryo/gamebryogameplugins.cpp | 142 ++++++----- src/gamebryo/gamebryogameplugins.h | 36 +-- src/gamebryo/gamebryolocalsavegames.cpp | 84 ++++--- src/gamebryo/gamebryolocalsavegames.h | 13 +- src/gamebryo/gamebryomoddatachecker.cpp | 66 +++-- src/gamebryo/gamebryomoddatachecker.h | 22 +- src/gamebryo/gamebryomoddatacontent.cpp | 111 ++++---- src/gamebryo/gamebryomoddatacontent.h | 17 +- src/gamebryo/gamebryosavegame.cpp | 161 ++++++------ src/gamebryo/gamebryosavegame.h | 65 ++--- src/gamebryo/gamebryosavegameinfo.cpp | 77 +++--- src/gamebryo/gamebryosavegameinfo.h | 8 +- src/gamebryo/gamebryosavegameinfowidget.cpp | 238 +++++++++--------- src/gamebryo/gamebryosavegameinfowidget.h | 15 +- src/gamebryo/gamebryoscriptextender.cpp | 20 +- src/gamebryo/gamebryoscriptextender.h | 6 +- src/gamebryo/gamebryounmanagedmods.cpp | 29 ++- src/gamebryo/gamebryounmanagedmods.h | 25 +- src/gamebryo/gamegamebryo.cpp | 187 +++++++------- src/gamebryo/gamegamebryo.h | 99 ++++---- 32 files changed, 1030 insertions(+), 924 deletions(-) create mode 100644 .clang-format create mode 100644 .gitattributes rename src/creation/{game_gamebryo_en.ts => game_creation_en.ts} (86%) diff --git a/.clang-format b/.clang-format new file mode 100644 index 00000000..6098e1f5 --- /dev/null +++ b/.clang-format @@ -0,0 +1,41 @@ +--- +# We'll use defaults from the LLVM style, but with 4 columns indentation. +BasedOnStyle: LLVM +IndentWidth: 2 +--- +Language: Cpp +DeriveLineEnding: false +UseCRLF: true +DerivePointerAlignment: false +PointerAlignment: Left +AlignConsecutiveAssignments: true +AllowShortFunctionsOnASingleLine: Inline +AllowShortIfStatementsOnASingleLine: Never +AllowShortLambdasOnASingleLine: Empty +AlwaysBreakTemplateDeclarations: Yes +AccessModifierOffset: -2 +AlignTrailingComments: true +SpacesBeforeTrailingComments: 2 +NamespaceIndentation: Inner +MaxEmptyLinesToKeep: 1 +BreakBeforeBraces: Custom +BraceWrapping: + AfterCaseLabel: false + AfterClass: true + AfterControlStatement: false + AfterEnum: true + AfterFunction: true + AfterNamespace: true + AfterStruct: true + AfterUnion: true + AfterExternBlock: true + BeforeCatch: false + BeforeElse: false + BeforeLambdaBody: false + BeforeWhile: false + IndentBraces: false + SplitEmptyFunction: false + SplitEmptyRecord: false + SplitEmptyNamespace: true +ColumnLimit: 88 +ForEachMacros: ['Q_FOREACH', 'foreach'] diff --git a/.gitattributes b/.gitattributes new file mode 100644 index 00000000..f8697127 --- /dev/null +++ b/.gitattributes @@ -0,0 +1,7 @@ +# Set the default behavior, in case people don't have core.autocrlf set. +* text=auto + +# Explicitly declare text files you want to always be normalized and converted +# to native line endings on checkout. +*.cpp text eol=crlf +*.h text eol=crlf diff --git a/src/creation/creationgameplugins.cpp b/src/creation/creationgameplugins.cpp index 2c388dbc..8c3c3a16 100644 --- a/src/creation/creationgameplugins.cpp +++ b/src/creation/creationgameplugins.cpp @@ -1,104 +1,95 @@ -#include "creationgameplugins.h" -#include -#include +#include "creationgameplugins.h" #include #include +#include #include #include -#include -#include #include +#include +#include +using MOBase::IOrganizer; using MOBase::IPluginGame; using MOBase::IPluginList; -using MOBase::IOrganizer; -using MOBase::SafeWriteFile; using MOBase::reportError; +using MOBase::SafeWriteFile; -CreationGamePlugins::CreationGamePlugins(IOrganizer *organizer) - : GamebryoGamePlugins(organizer) +CreationGamePlugins::CreationGamePlugins(IOrganizer* organizer) + : GamebryoGamePlugins(organizer) +{} + +QStringList CreationGamePlugins::getLoadOrder() { -} + QString loadOrderPath = organizer()->profile()->absolutePath() + "/loadorder.txt"; + QString pluginsPath = organizer()->profile()->absolutePath() + "/plugins.txt"; -QStringList CreationGamePlugins::getLoadOrder() { - QString loadOrderPath = - organizer()->profile()->absolutePath() + "/loadorder.txt"; - QString pluginsPath = organizer()->profile()->absolutePath() + "/plugins.txt"; - - bool loadOrderIsNew = !m_LastRead.isValid() || - !QFileInfo(loadOrderPath).exists() || - QFileInfo(loadOrderPath).lastModified() > m_LastRead; - bool pluginsIsNew = !m_LastRead.isValid() || - QFileInfo(pluginsPath).lastModified() > m_LastRead; + bool loadOrderIsNew = !m_LastRead.isValid() || !QFileInfo(loadOrderPath).exists() || + QFileInfo(loadOrderPath).lastModified() > m_LastRead; + bool pluginsIsNew = + !m_LastRead.isValid() || QFileInfo(pluginsPath).lastModified() > m_LastRead; if (loadOrderIsNew || !pluginsIsNew) { return readLoadOrderList(m_Organizer->pluginList(), loadOrderPath); - } - else { + } else { return readPluginList(m_Organizer->pluginList()); } } -void CreationGamePlugins::writePluginList(const IPluginList *pluginList, - const QString &filePath) { +void CreationGamePlugins::writePluginList(const IPluginList* pluginList, + const QString& filePath) +{ SafeWriteFile file(filePath); QStringEncoder encoder(QStringConverter::Encoding::System); file->resize(0); - file->write(encoder.encode( - "# This file was automatically generated by Mod Organizer.\r\n")); + file->write( + encoder.encode("# This file was automatically generated by Mod Organizer.\r\n")); bool invalidFileNames = false; - int writtenCount = 0; + int writtenCount = 0; QStringList plugins = pluginList->pluginNames(); std::sort(plugins.begin(), plugins.end(), - [pluginList](const QString &lhs, const QString &rhs) { + [pluginList](const QString& lhs, const QString& rhs) { return pluginList->priority(lhs) < pluginList->priority(rhs); }); QStringList PrimaryPlugins = organizer()->managedGame()->primaryPlugins(); - QStringList DLCPlugins = organizer()->managedGame()->DLCPlugins(); - QSet ManagedMods = QSet(PrimaryPlugins.begin(), PrimaryPlugins.end()); + QStringList DLCPlugins = organizer()->managedGame()->DLCPlugins(); + QSet ManagedMods = + QSet(PrimaryPlugins.begin(), PrimaryPlugins.end()); QSet DLCSet = QSet(DLCPlugins.begin(), DLCPlugins.end()); ManagedMods.subtract(DLCSet); PrimaryPlugins.append(QList(ManagedMods.begin(), ManagedMods.end())); - //TODO: do not write plugins in OFFICIAL_FILES container - for (const QString &pluginName : plugins) { - if (!PrimaryPlugins.contains(pluginName,Qt::CaseInsensitive)) { - if (pluginList->state(pluginName) == IPluginList::STATE_ACTIVE) { - auto result = encoder.encode(pluginName); - if (encoder.hasError()) { - invalidFileNames = true; - qCritical("invalid plugin name %s", qUtf8Printable(pluginName)); - } - else - { - file->write("*"); - file->write(result); - - } - file->write("\r\n"); - ++writtenCount; - } - else - { + // TODO: do not write plugins in OFFICIAL_FILES container + for (const QString& pluginName : plugins) { + if (!PrimaryPlugins.contains(pluginName, Qt::CaseInsensitive)) { + if (pluginList->state(pluginName) == IPluginList::STATE_ACTIVE) { auto result = encoder.encode(pluginName); if (encoder.hasError()) { invalidFileNames = true; qCritical("invalid plugin name %s", qUtf8Printable(pluginName)); - } - else - { + } else { + file->write("*"); file->write(result); } file->write("\r\n"); ++writtenCount; - } + } else { + auto result = encoder.encode(pluginName); + if (encoder.hasError()) { + invalidFileNames = true; + qCritical("invalid plugin name %s", qUtf8Printable(pluginName)); + } else { + file->write(result); + } + file->write("\r\n"); + ++writtenCount; + } } } @@ -112,13 +103,13 @@ void CreationGamePlugins::writePluginList(const IPluginList *pluginList, file.commitIfDifferent(m_LastSaveHash[filePath]); } -QStringList CreationGamePlugins::readPluginList(MOBase::IPluginList *pluginList) +QStringList CreationGamePlugins::readPluginList(MOBase::IPluginList* pluginList) { - const auto plugins = pluginList->pluginNames(); + const auto plugins = pluginList->pluginNames(); const auto primaryPlugins = organizer()->managedGame()->primaryPlugins(); QStringList loadOrder(primaryPlugins); - for (const QString &pluginName : loadOrder) { + for (const QString& pluginName : loadOrder) { if (pluginList->state(pluginName) != IPluginList::STATE_MISSING) { pluginList->setState(pluginName, IPluginList::STATE_ACTIVE); } @@ -130,7 +121,9 @@ QStringList CreationGamePlugins::readPluginList(MOBase::IPluginList *pluginList) qWarning("%s not found", qUtf8Printable(filePath)); return loadOrder; } - ON_BLOCK_EXIT([&]() { file.close(); }); + ON_BLOCK_EXIT([&]() { + file.close(); + }); if (file.size() == 0) { // MO stores at least a header in the file. if it's completely empty the @@ -144,7 +137,8 @@ QStringList CreationGamePlugins::readPluginList(MOBase::IPluginList *pluginList) QByteArray line = file.readLine(); QString pluginName; if ((line.size() > 0) && (line.at(0) != '#')) { - pluginName = QStringEncoder(QStringConverter::Encoding::System).encode(line.trimmed().constData()); + pluginName = QStringEncoder(QStringConverter::Encoding::System) + .encode(line.trimmed().constData()); } if (!primaryPlugins.contains(pluginName, Qt::CaseInsensitive)) { if (pluginName.startsWith('*')) { @@ -156,8 +150,7 @@ QStringList CreationGamePlugins::readPluginList(MOBase::IPluginList *pluginList) loadOrder.append(pluginName); } } - } - else { + } else { if (pluginName.size() > 0) { pluginList->setState(pluginName, IPluginList::STATE_INACTIVE); pluginsFound.append(pluginName); @@ -166,8 +159,7 @@ QStringList CreationGamePlugins::readPluginList(MOBase::IPluginList *pluginList) } } } - } - else { + } else { pluginName.remove(0, 1); pluginsFound.append(pluginName); } @@ -188,4 +180,4 @@ QStringList CreationGamePlugins::readPluginList(MOBase::IPluginList *pluginList) bool CreationGamePlugins::lightPluginsAreSupported() { return true; -} \ No newline at end of file +} diff --git a/src/creation/creationgameplugins.h b/src/creation/creationgameplugins.h index 47a7d176..26dc805b 100644 --- a/src/creation/creationgameplugins.h +++ b/src/creation/creationgameplugins.h @@ -1,20 +1,20 @@ -#ifndef CREATIONGAMEPLUGINS_H +#ifndef CREATIONGAMEPLUGINS_H #define CREATIONGAMEPLUGINS_H #include -#include #include +#include #include class CreationGamePlugins : public GamebryoGamePlugins { public: - CreationGamePlugins(MOBase::IOrganizer *organizer); + CreationGamePlugins(MOBase::IOrganizer* organizer); protected: - virtual void writePluginList(const MOBase::IPluginList *pluginList, - const QString &filePath) override; - virtual QStringList readPluginList(MOBase::IPluginList *pluginList) override; + virtual void writePluginList(const MOBase::IPluginList* pluginList, + const QString& filePath) override; + virtual QStringList readPluginList(MOBase::IPluginList* pluginList) override; virtual QStringList getLoadOrder() override; virtual bool lightPluginsAreSupported() override; @@ -22,4 +22,4 @@ private: std::map m_LastSaveHash; }; -#endif // CREATIONGAMEPLUGINS_H \ No newline at end of file +#endif // CREATIONGAMEPLUGINS_H diff --git a/src/creation/game_gamebryo_en.ts b/src/creation/game_creation_en.ts similarity index 86% rename from src/creation/game_gamebryo_en.ts rename to src/creation/game_creation_en.ts index 385668d9..f2174487 100644 --- a/src/creation/game_gamebryo_en.ts +++ b/src/creation/game_creation_en.ts @@ -4,7 +4,7 @@ QObject - + Some of your plugins have invalid names! These plugins can not be loaded by the game. Please see mo_interface.log for a list of affected plugins and rename them. diff --git a/src/gamebryo/dummybsa.cpp b/src/gamebryo/dummybsa.cpp index 290be3ae..ba6f7669 100644 --- a/src/gamebryo/dummybsa.cpp +++ b/src/gamebryo/dummybsa.cpp @@ -22,10 +22,10 @@ along with Mod Organizer. If not, see . #define WIN32_LEAN_AND_MEAN #include - static void writeUlong(unsigned char* buffer, int offset, unsigned long value) { - union { + union + { unsigned long ulValue; unsigned char cValue[4]; }; @@ -35,7 +35,8 @@ static void writeUlong(unsigned char* buffer, int offset, unsigned long value) static void writeUlonglong(unsigned char* buffer, int offset, unsigned long long value) { - union { + union + { unsigned long long ullValue; unsigned char cValue[8]; }; @@ -43,7 +44,7 @@ static void writeUlonglong(unsigned char* buffer, int offset, unsigned long long memcpy(buffer + offset, cValue, 8); } -static unsigned long genHashInt(const unsigned char *pos, const unsigned char *end) +static unsigned long genHashInt(const unsigned char* pos, const unsigned char* end) { unsigned long hash = 0; for (; pos < end; ++pos) { @@ -65,22 +66,20 @@ static unsigned long long genHash(const char* fileName) } fileNameLower[i] = '\0'; - unsigned char *fileNameLowerU = reinterpret_cast(fileNameLower); + unsigned char* fileNameLowerU = reinterpret_cast(fileNameLower); char* ext = strrchr(fileNameLower, '.'); if (ext == nullptr) { ext = fileNameLower + strlen(fileNameLower); } - unsigned char *extU = reinterpret_cast(ext); + unsigned char* extU = reinterpret_cast(ext); int length = ext - fileNameLower; unsigned long long hash = 0ULL; if (length > 0) { - hash = *(extU - 1) | - ((length > 2 ? *(ext - 2) : 0) << 8) | - (length << 16) | + hash = *(extU - 1) | ((length > 2 ? *(ext - 2) : 0) << 8) | (length << 16) | (fileNameLowerU[0] << 24); } @@ -95,10 +94,9 @@ static unsigned long long genHash(const char* fileName) hash |= 0x80000000; } - unsigned long long temp = static_cast(genHashInt( - fileNameLowerU + 1, extU - 2)); - temp += static_cast(genHashInt( - extU, extU + strlen(ext))); + unsigned long long temp = + static_cast(genHashInt(fileNameLowerU + 1, extU - 2)); + temp += static_cast(genHashInt(extU, extU + strlen(ext))); hash |= (temp & 0xFFFFFFFF) << 32; } @@ -106,75 +104,78 @@ static unsigned long long genHash(const char* fileName) } DummyBSA::DummyBSA(unsigned long bsaVersion) - : m_Version(bsaVersion) - , m_FolderName("") - , m_FileName("dummy.dds") - , m_TotalFileNameLength(0) -{ -} + : m_Version(bsaVersion), m_FolderName(""), m_FileName("dummy.dds"), + m_TotalFileNameLength(0) +{} -void DummyBSA::writeHeader(QFile &file) +void DummyBSA::writeHeader(QFile& file) { unsigned char header[] = { - 'B', 'S', 'A', '\0', // magic string - 0xDE, 0xAD, 0xBE, 0xEF, // version - insert later - 0x24, 0x00, 0x00, 0x00, // offset to folder recors. header size is static - 0xDE, 0xAD, 0xBE, 0xEF, // archive flags - insert later - 0x01, 0x00, 0x00, 0x00, // folder count - 0x01, 0x00, 0x00, 0x00, // file count - 0xDE, 0xAD, 0xBE, 0xEF, // total folder names length - insert later - 0xDE, 0xAD, 0xBE, 0xEF, // total file names length - insert later - 0xDE, 0xAD, 0xBE, 0xEF // file flags - insert later - }; + 'B', 'S', 'A', '\0', // magic string + 0xDE, 0xAD, 0xBE, 0xEF, // version - insert later + 0x24, 0x00, 0x00, 0x00, // offset to folder recors. header size is static + 0xDE, 0xAD, 0xBE, 0xEF, // archive flags - insert later + 0x01, 0x00, 0x00, 0x00, // folder count + 0x01, 0x00, 0x00, 0x00, // file count + 0xDE, 0xAD, 0xBE, 0xEF, // total folder names length - insert later + 0xDE, 0xAD, 0xBE, 0xEF, // total file names length - insert later + 0xDE, 0xAD, 0xBE, 0xEF // file flags - insert later + }; writeUlong(header, 4, m_Version); - writeUlong(header, 12, 0x01 | 0x02); // has directories and has files. - writeUlong(header, 24, static_cast(m_FolderName.length()) + 1); // empty folder name - writeUlong(header, 28, m_TotalFileNameLength); // single character file name + writeUlong(header, 12, 0x01 | 0x02); // has directories and has files. + writeUlong(header, 24, + static_cast(m_FolderName.length()) + + 1); // empty folder name + writeUlong(header, 28, m_TotalFileNameLength); // single character file name - writeUlong(header, 32, 2); // has dds + writeUlong(header, 32, 2); // has dds file.write(reinterpret_cast(header), sizeof(header)); } -void DummyBSA::writeFolderRecord(QFile &file, const std::string &folderName) +void DummyBSA::writeFolderRecord(QFile& file, const std::string& folderName) { unsigned char folderRecord[] = { - 0xDE, 0xAD, 0xBE, 0xEF, 0xDE, 0xAD, 0xBE, 0xEF, // folder hash - 0x01, 0x00, 0x00, 0x00, // file count - 0xDE, 0xAD, 0xBE, 0xEF, // offset to folder name - }; + 0xDE, 0xAD, 0xBE, 0xEF, 0xDE, 0xAD, 0xBE, 0xEF, // folder hash + 0x01, 0x00, 0x00, 0x00, // file count + 0xDE, 0xAD, 0xBE, 0xEF, // offset to folder name + }; // we'd usually have to sort folders be the hash value generated here writeUlonglong(folderRecord, 0, genHash(folderName.c_str())); - writeUlong( folderRecord, 12, 0x34 + m_TotalFileNameLength); // TODO: this should be calculated properly + writeUlong(folderRecord, 12, + 0x34 + m_TotalFileNameLength); // TODO: this should be calculated properly file.write(reinterpret_cast(folderRecord), sizeof(folderRecord)); } -void DummyBSA::writeFileRecord(QFile &file, const std::string &fileName) +void DummyBSA::writeFileRecord(QFile& file, const std::string& fileName) { unsigned char fileRecord[] = { - 0xDE, 0xAD, 0xBE, 0xEF, 0xDE, 0xAD, 0xBE, 0xEF, // file name hash - 0xDE, 0xAD, 0xBE, 0xEF, // size - 0xDE, 0xAD, 0xBE, 0xEF, // offset to file data - }; + 0xDE, 0xAD, 0xBE, 0xEF, 0xDE, 0xAD, 0xBE, 0xEF, // file name hash + 0xDE, 0xAD, 0xBE, 0xEF, // size + 0xDE, 0xAD, 0xBE, 0xEF, // offset to file data + }; // we'd usually have to sort files by the value generated here - writeUlonglong(fileRecord, 0, genHash(fileName.c_str())); - writeUlong( fileRecord, 8, 0); - writeUlong( fileRecord, 12, 0x44 + static_cast(fileName.length() + 1) + 4); // after this record we expect the filename and 4 bytes of file size + writeUlonglong(fileRecord, 0, genHash(fileName.c_str())); + writeUlong(fileRecord, 8, 0); + writeUlong( + fileRecord, 12, + 0x44 + static_cast(fileName.length() + 1) + + 4); // after this record we expect the filename and 4 bytes of file size file.write(reinterpret_cast(fileRecord), sizeof(fileRecord)); } -void DummyBSA::writeFileRecordBlocks(QFile &file, const std::string &folderName) +void DummyBSA::writeFileRecordBlocks(QFile& file, const std::string& folderName) { file.write(folderName.c_str(), folderName.length() + 1); writeFileRecord(file, m_FileName); } -void DummyBSA::write(const QString &fileName) +void DummyBSA::write(const QString& fileName) { QFile file(fileName); file.open(QIODevice::WriteOnly); @@ -184,8 +185,8 @@ void DummyBSA::write(const QString &fileName) writeHeader(file); writeFolderRecord(file, m_FolderName); writeFileRecordBlocks(file, m_FolderName); - file.write(m_FileName.c_str() , m_FileName.length() + 1); - char fileSize[] = { 0x00, 0x00, 0x00, 0x00 }; + file.write(m_FileName.c_str(), m_FileName.length() + 1); + char fileSize[] = {0x00, 0x00, 0x00, 0x00}; file.write(fileSize, sizeof(fileSize)); file.close(); } diff --git a/src/gamebryo/dummybsa.h b/src/gamebryo/dummybsa.h index ba82b059..8ea071b5 100644 --- a/src/gamebryo/dummybsa.h +++ b/src/gamebryo/dummybsa.h @@ -20,8 +20,8 @@ along with Mod Organizer. If not, see . #ifndef DUMMYBSA_H #define DUMMYBSA_H -#include #include +#include /** * @brief Class for creating a dummy bsa used for archive invalidation @@ -30,7 +30,6 @@ class DummyBSA { public: - /** * @brief constructor * @@ -42,23 +41,19 @@ public: * * @param fileName name of the file to write to **/ - void write(const QString &fileName); + void write(const QString& fileName); private: - - void writeHeader(QFile &file); - void writeFolderRecord(QFile &file, const std::string &folderName); - void writeFileRecord(QFile &file, const std::string &fileName); - void writeFileRecordBlocks(QFile &file, const std::string &folderName); + void writeHeader(QFile& file); + void writeFolderRecord(QFile& file, const std::string& folderName); + void writeFileRecord(QFile& file, const std::string& fileName); + void writeFileRecordBlocks(QFile& file, const std::string& folderName); private: - unsigned long m_Version; std::string m_FolderName; std::string m_FileName; unsigned long m_TotalFileNameLength; - }; - -#endif // DUMMYBSA_H +#endif // DUMMYBSA_H diff --git a/src/gamebryo/game_gamebryo_en.ts b/src/gamebryo/game_gamebryo_en.ts index 116b63ae..7ee873eb 100644 --- a/src/gamebryo/game_gamebryo_en.ts +++ b/src/gamebryo/game_gamebryo_en.ts @@ -4,77 +4,77 @@ GamebryoModDataContent - + Plugins (ESP/ESM/ESL) - + Optional Plugins - + Interface - + Meshes - + Bethesda Archive - + Scripts (Papyrus) - + Script Extender Plugin - + Script Extender Files - + SkyProc Patcher - + Sound or Music - + Textures - + MCM Configuration - + INI Files - + FaceGen Data - + ModGroup Files @@ -107,23 +107,23 @@ - + Has Script Extender Data - + Missing ESPs - - + + None - + Missing ESLs @@ -131,32 +131,32 @@ QObject - + Some of your plugins have invalid names! These plugins can not be loaded by the game. Please see mo_interface.log for a list of affected plugins and rename them. - + %1, #%2, Level %3, %4 - + failed to open %1 - + wrong file format - expected %1 got %2 - + failed to query registry path (preflight): %1 - + failed to query registry path (read): %1 diff --git a/src/gamebryo/gamebryobsainvalidation.cpp b/src/gamebryo/gamebryobsainvalidation.cpp index 9db2b857..c1ba7e64 100644 --- a/src/gamebryo/gamebryobsainvalidation.cpp +++ b/src/gamebryo/gamebryobsainvalidation.cpp @@ -3,31 +3,26 @@ #include "dummybsa.h" #include "iplugingame.h" #include "iprofile.h" -#include +#include "registry.h" #include #include -#include "registry.h" -#include #include +#include #include +GamebryoBSAInvalidation::GamebryoBSAInvalidation(DataArchives* dataArchives, + const QString& iniFilename, + MOBase::IPluginGame const* game) + : m_DataArchives(dataArchives), m_IniFileName(iniFilename), m_Game(game) +{} -GamebryoBSAInvalidation::GamebryoBSAInvalidation(DataArchives *dataArchives - , const QString &iniFilename - , MOBase::IPluginGame const *game) - : m_DataArchives(dataArchives) - , m_IniFileName(iniFilename) - , m_Game(game) +bool GamebryoBSAInvalidation::isInvalidationBSA(const QString& bsaName) { -} + static QStringList invalidation{invalidationBSAName()}; -bool GamebryoBSAInvalidation::isInvalidationBSA(const QString &bsaName) -{ - static QStringList invalidation { invalidationBSAName() }; - - for (const QString &file : invalidation) { + for (const QString& file : invalidation) { if (file.compare(bsaName, Qt::CaseInsensitive) == 0) { return true; } @@ -35,41 +30,43 @@ bool GamebryoBSAInvalidation::isInvalidationBSA(const QString &bsaName) return false; } -void GamebryoBSAInvalidation::deactivate(MOBase::IProfile *profile) +void GamebryoBSAInvalidation::deactivate(MOBase::IProfile* profile) { prepareProfile(profile); } -void GamebryoBSAInvalidation::activate(MOBase::IProfile *profile) +void GamebryoBSAInvalidation::activate(MOBase::IProfile* profile) { prepareProfile(profile); } -bool GamebryoBSAInvalidation::prepareProfile(MOBase::IProfile *profile) +bool GamebryoBSAInvalidation::prepareProfile(MOBase::IProfile* profile) { - bool dirty = false; - QString basePath - = profile->localSettingsEnabled() - ? profile->absolutePath() - : m_Game->documentsDirectory().absolutePath(); + bool dirty = false; + QString basePath = profile->localSettingsEnabled() + ? profile->absolutePath() + : m_Game->documentsDirectory().absolutePath(); QString iniFilePath = basePath + "/" + m_IniFileName; WCHAR setting[MAX_PATH]; // write bInvalidateOlderFiles = 1, if needed - if (!::GetPrivateProfileStringW(L"Archive", L"bInvalidateOlderFiles", L"0", setting, MAX_PATH, iniFilePath.toStdWString().c_str()) - || wcstol(setting, nullptr, 10) != 1) { + if (!::GetPrivateProfileStringW(L"Archive", L"bInvalidateOlderFiles", L"0", setting, + MAX_PATH, iniFilePath.toStdWString().c_str()) || + wcstol(setting, nullptr, 10) != 1) { dirty = true; - if (!MOBase::WriteRegistryValue(L"Archive", L"bInvalidateOlderFiles", L"1", iniFilePath.toStdWString().c_str())) { - qWarning("failed to activate BSA invalidation in \"%s\"", qUtf8Printable(m_IniFileName)); + if (!MOBase::WriteRegistryValue(L"Archive", L"bInvalidateOlderFiles", L"1", + iniFilePath.toStdWString().c_str())) { + qWarning("failed to activate BSA invalidation in \"%s\"", + qUtf8Printable(m_IniFileName)); } } - if (profile->invalidationActive(nullptr)){ + if (profile->invalidationActive(nullptr)) { // add the dummy bsa to the archive string, if needed QStringList archives = m_DataArchives->archives(profile); - bool bsaInstalled = false; - for (const QString &archive : archives) { + bool bsaInstalled = false; + for (const QString& archive : archives) { if (isInvalidationBSA(archive)) { bsaInstalled = true; break; @@ -89,18 +86,22 @@ bool GamebryoBSAInvalidation::prepareProfile(MOBase::IProfile *profile) } // write SInvalidationFile = "", if needed - if (::GetPrivateProfileStringW(L"Archive", L"SInvalidationFile", L"ArchiveInvalidation.txt", setting, MAX_PATH, iniFilePath.toStdWString().c_str()) - || wcscmp(setting, L"") != 0) { + if (::GetPrivateProfileStringW(L"Archive", L"SInvalidationFile", + L"ArchiveInvalidation.txt", setting, MAX_PATH, + iniFilePath.toStdWString().c_str()) || + wcscmp(setting, L"") != 0) { dirty = true; - if (!MOBase::WriteRegistryValue(L"Archive", L"SInvalidationFile", L"", iniFilePath.toStdWString().c_str())) { - qWarning("failed to activate BSA invalidation in \"%s\"", qUtf8Printable(m_IniFileName)); + if (!MOBase::WriteRegistryValue(L"Archive", L"SInvalidationFile", L"", + iniFilePath.toStdWString().c_str())) { + qWarning("failed to activate BSA invalidation in \"%s\"", + qUtf8Printable(m_IniFileName)); } } } else { // remove the dummy bsa from the archive string, if needed QStringList archivesBefore = m_DataArchives->archives(profile); - for (const QString &archive : archivesBefore) { + for (const QString& archive : archivesBefore) { if (isInvalidationBSA(archive)) { m_DataArchives->removeArchive(profile, archive); dirty = true; @@ -115,11 +116,15 @@ bool GamebryoBSAInvalidation::prepareProfile(MOBase::IProfile *profile) } // write SInvalidationFile = "ArchiveInvalidation.txt", if needed - if (!::GetPrivateProfileStringW(L"Archive", L"SInvalidationFile", L"", setting, MAX_PATH, iniFilePath.toStdWString().c_str()) - || wcscmp(setting, L"ArchiveInvalidation.txt") != 0) { + if (!::GetPrivateProfileStringW(L"Archive", L"SInvalidationFile", L"", setting, + MAX_PATH, iniFilePath.toStdWString().c_str()) || + wcscmp(setting, L"ArchiveInvalidation.txt") != 0) { dirty = true; - if (!MOBase::WriteRegistryValue(L"Archive", L"SInvalidationFile", L"ArchiveInvalidation.txt", iniFilePath.toStdWString().c_str())) { - qWarning("failed to activate BSA invalidation in \"%s\"", qUtf8Printable(m_IniFileName)); + if (!MOBase::WriteRegistryValue(L"Archive", L"SInvalidationFile", + L"ArchiveInvalidation.txt", + iniFilePath.toStdWString().c_str())) { + qWarning("failed to activate BSA invalidation in \"%s\"", + qUtf8Printable(m_IniFileName)); } } } diff --git a/src/gamebryo/gamebryobsainvalidation.h b/src/gamebryo/gamebryobsainvalidation.h index 7b8e3a35..33d81f2c 100644 --- a/src/gamebryo/gamebryobsainvalidation.h +++ b/src/gamebryo/gamebryobsainvalidation.h @@ -1,40 +1,36 @@ #ifndef GAMEBRYOBSAINVALIDATION_H #define GAMEBRYOBSAINVALIDATION_H - #include #include #include #include -namespace MOBase { - class IPluginGame; +namespace MOBase +{ +class IPluginGame; } class GamebryoBSAInvalidation : public BSAInvalidation { public: + GamebryoBSAInvalidation(DataArchives* dataArchives, const QString& iniFilename, + MOBase::IPluginGame const* game); - GamebryoBSAInvalidation(DataArchives *dataArchives, - const QString &iniFilename, - MOBase::IPluginGame const *game); - - virtual bool isInvalidationBSA(const QString &bsaName) override; - virtual void deactivate(MOBase::IProfile *profile) override; - virtual void activate(MOBase::IProfile *profile) override; - virtual bool prepareProfile(MOBase::IProfile *profile) override; + virtual bool isInvalidationBSA(const QString& bsaName) override; + virtual void deactivate(MOBase::IProfile* profile) override; + virtual void activate(MOBase::IProfile* profile) override; + virtual bool prepareProfile(MOBase::IProfile* profile) override; private: - virtual QString invalidationBSAName() const = 0; - virtual unsigned long bsaVersion() const = 0; // 0x67 for oblivion, 0x68 for everything else + virtual unsigned long + bsaVersion() const = 0; // 0x67 for oblivion, 0x68 for everything else private: - - DataArchives *m_DataArchives; + DataArchives* m_DataArchives; QString m_IniFileName; - MOBase::IPluginGame const *m_Game; - + MOBase::IPluginGame const* m_Game; }; -#endif // GAMEBRYOBSAINVALIDATION_H +#endif // GAMEBRYOBSAINVALIDATION_H diff --git a/src/gamebryo/gamebryodataarchives.cpp b/src/gamebryo/gamebryodataarchives.cpp index cdeb4ea5..c24242dd 100644 --- a/src/gamebryo/gamebryodataarchives.cpp +++ b/src/gamebryo/gamebryodataarchives.cpp @@ -3,23 +3,25 @@ #include #include - -GamebryoDataArchives::GamebryoDataArchives(const QDir &myGamesDir): - m_LocalGameDir(myGamesDir.absolutePath()) +GamebryoDataArchives::GamebryoDataArchives(const QDir& myGamesDir) + : m_LocalGameDir(myGamesDir.absolutePath()) {} -QStringList GamebryoDataArchives::getArchivesFromKey(const QString &iniFile, const QString &key, const int size) const +QStringList GamebryoDataArchives::getArchivesFromKey(const QString& iniFile, + const QString& key, + const int size) const { - wchar_t * buffer = new wchar_t[size]; + wchar_t* buffer = new wchar_t[size]; QStringList result; std::wstring iniFileW = QDir::toNativeSeparators(iniFile).toStdWString(); - // epic ms fail: GetPrivateProfileString uses errno (for whatever reason) to signal a fail since the return value - // has a different meaning (number of bytes copied). HOWEVER, it will not set errno to 0 if NO error occured + // epic ms fail: GetPrivateProfileString uses errno (for whatever reason) to signal a + // fail since the return value has a different meaning (number of bytes copied). + // HOWEVER, it will not set errno to 0 if NO error occured errno = 0; - if (::GetPrivateProfileStringW(L"Archive", key.toStdWString().c_str(), - L"", buffer, size, iniFileW.c_str()) != 0) { + if (::GetPrivateProfileStringW(L"Archive", key.toStdWString().c_str(), L"", buffer, + size, iniFileW.c_str()) != 0) { result.append(QString::fromStdWString(buffer).split(',')); } @@ -30,14 +32,18 @@ QStringList GamebryoDataArchives::getArchivesFromKey(const QString &iniFile, con return result; } -void GamebryoDataArchives::setArchivesToKey(const QString &iniFile, const QString &key, const QString &value) +void GamebryoDataArchives::setArchivesToKey(const QString& iniFile, const QString& key, + const QString& value) { - if (!MOBase::WriteRegistryValue(L"Archive", key.toStdWString().c_str(), value.toStdWString().c_str(), iniFile.toStdWString().c_str())) { + if (!MOBase::WriteRegistryValue(L"Archive", key.toStdWString().c_str(), + value.toStdWString().c_str(), + iniFile.toStdWString().c_str())) { qWarning("failed to set archives in \"%s\"", qUtf8Printable(iniFile)); } } -void GamebryoDataArchives::addArchive(MOBase::IProfile *profile, int index, const QString &archiveName) +void GamebryoDataArchives::addArchive(MOBase::IProfile* profile, int index, + const QString& archiveName) { QStringList current = archives(profile); if (current.contains(archiveName, Qt::CaseInsensitive)) { @@ -49,7 +55,8 @@ void GamebryoDataArchives::addArchive(MOBase::IProfile *profile, int index, cons writeArchiveList(profile, current); } -void GamebryoDataArchives::removeArchive(MOBase::IProfile *profile, const QString &archiveName) +void GamebryoDataArchives::removeArchive(MOBase::IProfile* profile, + const QString& archiveName) { QStringList current = archives(profile); if (!current.contains(archiveName, Qt::CaseInsensitive)) { diff --git a/src/gamebryo/gamebryodataarchives.h b/src/gamebryo/gamebryodataarchives.h index b07b251f..93383f64 100644 --- a/src/gamebryo/gamebryodataarchives.h +++ b/src/gamebryo/gamebryodataarchives.h @@ -1,7 +1,6 @@ #ifndef GAMEBRYODATAARCHIVES_H #define GAMEBRYODATAARCHIVES_H - #include "dataarchives.h" #include @@ -9,21 +8,23 @@ class GamebryoDataArchives : public DataArchives { public: - GamebryoDataArchives(const QDir &myGamesDir); + GamebryoDataArchives(const QDir& myGamesDir); - virtual void addArchive(MOBase::IProfile *profile, int index, const QString &archiveName) override; - virtual void removeArchive(MOBase::IProfile *profile, const QString &archiveName) override; + virtual void addArchive(MOBase::IProfile* profile, int index, + const QString& archiveName) override; + virtual void removeArchive(MOBase::IProfile* profile, + const QString& archiveName) override; protected: - QDir m_LocalGameDir; - QStringList getArchivesFromKey(const QString &iniFile, const QString &key, int size=256) const; - void setArchivesToKey(const QString &iniFile, const QString &key, const QString &value); - + QStringList getArchivesFromKey(const QString& iniFile, const QString& key, + int size = 256) const; + void setArchivesToKey(const QString& iniFile, const QString& key, + const QString& value); + private: - - virtual void writeArchiveList(MOBase::IProfile *profile, const QStringList &before) = 0; - + virtual void writeArchiveList(MOBase::IProfile* profile, + const QStringList& before) = 0; }; -#endif // GAMEBRYODATAARCHIVES_H +#endif // GAMEBRYODATAARCHIVES_H diff --git a/src/gamebryo/gamebryogameplugins.cpp b/src/gamebryo/gamebryogameplugins.cpp index e56724fd..7139aaa8 100644 --- a/src/gamebryo/gamebryogameplugins.cpp +++ b/src/gamebryo/gamebryogameplugins.cpp @@ -1,50 +1,49 @@ #include "gamebryogameplugins.h" -#include -#include -#include -#include #include +#include +#include +#include +#include #include #include +#include #include -#include #include #include -#include +#include using MOBase::IOrganizer; using MOBase::IPluginList; -using MOBase::SafeWriteFile; using MOBase::reportError; +using MOBase::SafeWriteFile; -GamebryoGamePlugins::GamebryoGamePlugins(IOrganizer *organizer) - : m_Organizer(organizer) {} +GamebryoGamePlugins::GamebryoGamePlugins(IOrganizer* organizer) : m_Organizer(organizer) +{} -void GamebryoGamePlugins::writePluginLists(const IPluginList *pluginList) { +void GamebryoGamePlugins::writePluginLists(const IPluginList* pluginList) +{ if (!m_LastRead.isValid()) { // attempt to write uninitialized plugin lists return; } - writePluginList(pluginList, - m_Organizer->profile()->absolutePath() + "/plugins.txt"); + writePluginList(pluginList, m_Organizer->profile()->absolutePath() + "/plugins.txt"); writeLoadOrderList(pluginList, m_Organizer->profile()->absolutePath() + "/loadorder.txt"); m_LastRead = QDateTime::currentDateTime(); } -void GamebryoGamePlugins::readPluginLists(MOBase::IPluginList *pluginList) { - QString loadOrderPath = - organizer()->profile()->absolutePath() + "/loadorder.txt"; - QString pluginsPath = organizer()->profile()->absolutePath() + "/plugins.txt"; +void GamebryoGamePlugins::readPluginLists(MOBase::IPluginList* pluginList) +{ + QString loadOrderPath = organizer()->profile()->absolutePath() + "/loadorder.txt"; + QString pluginsPath = organizer()->profile()->absolutePath() + "/plugins.txt"; - bool loadOrderIsNew = !m_LastRead.isValid() || - !QFileInfo(loadOrderPath).exists() || - QFileInfo(loadOrderPath).lastModified() > m_LastRead; - bool pluginsIsNew = !m_LastRead.isValid() || - QFileInfo(pluginsPath).lastModified() > m_LastRead; + bool loadOrderIsNew = !m_LastRead.isValid() || !QFileInfo(loadOrderPath).exists() || + QFileInfo(loadOrderPath).lastModified() > m_LastRead; + bool pluginsIsNew = + !m_LastRead.isValid() || QFileInfo(pluginsPath).lastModified() > m_LastRead; if (loadOrderIsNew || !pluginsIsNew) { // read both files if they are both new or both older than the last read @@ -52,7 +51,8 @@ void GamebryoGamePlugins::readPluginLists(MOBase::IPluginList *pluginList) { pluginList->setLoadOrder(loadOrder); readPluginList(pluginList); } else { - // If the plugins is new but not loadorder, we must reparse the load order from the plugin files + // If the plugins is new but not loadorder, we must reparse the load order from the + // plugin files QStringList loadOrder = readPluginList(pluginList); pluginList->setLoadOrder(loadOrder); } @@ -60,16 +60,15 @@ void GamebryoGamePlugins::readPluginLists(MOBase::IPluginList *pluginList) { m_LastRead = QDateTime::currentDateTime(); } -QStringList GamebryoGamePlugins::getLoadOrder() { - QString loadOrderPath = - organizer()->profile()->absolutePath() + "/loadorder.txt"; - QString pluginsPath = organizer()->profile()->absolutePath() + "/plugins.txt"; +QStringList GamebryoGamePlugins::getLoadOrder() +{ + QString loadOrderPath = organizer()->profile()->absolutePath() + "/loadorder.txt"; + QString pluginsPath = organizer()->profile()->absolutePath() + "/plugins.txt"; - bool loadOrderIsNew = !m_LastRead.isValid() || - !QFileInfo(loadOrderPath).exists() || - QFileInfo(loadOrderPath).lastModified() > m_LastRead; - bool pluginsIsNew = !m_LastRead.isValid() || - QFileInfo(pluginsPath).lastModified() > m_LastRead; + bool loadOrderIsNew = !m_LastRead.isValid() || !QFileInfo(loadOrderPath).exists() || + QFileInfo(loadOrderPath).lastModified() > m_LastRead; + bool pluginsIsNew = + !m_LastRead.isValid() || QFileInfo(pluginsPath).lastModified() > m_LastRead; if (loadOrderIsNew || !pluginsIsNew) { return readLoadOrderList(m_Organizer->pluginList(), loadOrderPath); @@ -78,40 +77,43 @@ QStringList GamebryoGamePlugins::getLoadOrder() { } } -void GamebryoGamePlugins::writePluginList(const MOBase::IPluginList *pluginList, - const QString &filePath) { +void GamebryoGamePlugins::writePluginList(const MOBase::IPluginList* pluginList, + const QString& filePath) +{ return writeList(pluginList, filePath, false); } -void GamebryoGamePlugins::writeLoadOrderList( - const MOBase::IPluginList *pluginList, const QString &filePath) { +void GamebryoGamePlugins::writeLoadOrderList(const MOBase::IPluginList* pluginList, + const QString& filePath) +{ return writeList(pluginList, filePath, true); } -void GamebryoGamePlugins::writeList(const IPluginList *pluginList, - const QString &filePath, bool loadOrder) { +void GamebryoGamePlugins::writeList(const IPluginList* pluginList, + const QString& filePath, bool loadOrder) +{ SafeWriteFile file(filePath); - QStringEncoder encoder = loadOrder ? QStringEncoder(QStringConverter::Encoding::Utf8) - : QStringEncoder(QStringConverter::Encoding::System); + QStringEncoder encoder = loadOrder + ? QStringEncoder(QStringConverter::Encoding::Utf8) + : QStringEncoder(QStringConverter::Encoding::System); file->resize(0); - file->write(encoder.encode( - "# This file was automatically generated by Mod Organizer.\r\n")); + file->write( + encoder.encode("# This file was automatically generated by Mod Organizer.\r\n")); bool invalidFileNames = false; - int writtenCount = 0; + int writtenCount = 0; QStringList plugins = pluginList->pluginNames(); std::sort(plugins.begin(), plugins.end(), - [pluginList](const QString &lhs, const QString &rhs) { + [pluginList](const QString& lhs, const QString& rhs) { return pluginList->priority(lhs) < pluginList->priority(rhs); }); - for (const QString &pluginName : plugins) { - if (loadOrder || - (pluginList->state(pluginName) == IPluginList::STATE_ACTIVE)) { + for (const QString& pluginName : plugins) { + if (loadOrder || (pluginList->state(pluginName) == IPluginList::STATE_ACTIVE)) { auto result = encoder.encode(pluginName); if (encoder.hasError()) { invalidFileNames = true; @@ -139,8 +141,8 @@ void GamebryoGamePlugins::writeList(const IPluginList *pluginList, } } -QStringList GamebryoGamePlugins::readLoadOrderList( - MOBase::IPluginList *pluginList, const QString &filePath) +QStringList GamebryoGamePlugins::readLoadOrderList(MOBase::IPluginList* pluginList, + const QString& filePath) { QStringList pluginNames = organizer()->managedGame()->primaryPlugins(); @@ -163,40 +165,44 @@ QStringList GamebryoGamePlugins::readLoadOrderList( return pluginNames; } -QStringList GamebryoGamePlugins::readPluginList(MOBase::IPluginList *pluginList) { +QStringList GamebryoGamePlugins::readPluginList(MOBase::IPluginList* pluginList) +{ QStringList primary = organizer()->managedGame()->primaryPlugins(); - for (const QString &pluginName : primary) { + for (const QString& pluginName : primary) { if (pluginList->state(pluginName) != IPluginList::STATE_MISSING) { pluginList->setState(pluginName, IPluginList::STATE_ACTIVE); } } QStringList plugins = pluginList->pluginNames(); QStringList pluginsClone(plugins); - // Do not sort the primary plugins. Their load order should be locked as defined in "primaryPlugins". + // Do not sort the primary plugins. Their load order should be locked as defined in + // "primaryPlugins". for (const auto& plugin : pluginsClone) { if (primary.contains(plugin, Qt::CaseInsensitive)) plugins.removeAll(plugin); } // Always use filetime loadorder to get the actual load order - std::sort(plugins.begin(), plugins.end(), [&](const QString &lhs, const QString &rhs) { - MOBase::IModInterface *lhm = organizer()->modList()->getMod(pluginList->origin(lhs)); - MOBase::IModInterface *rhm = organizer()->modList()->getMod(pluginList->origin(rhs)); - QDir lhd = organizer()->managedGame()->dataDirectory(); - QDir rhd = organizer()->managedGame()->dataDirectory(); - if (lhm != nullptr) - lhd = lhm->absolutePath(); - if (rhm != nullptr) - rhd = rhm->absolutePath(); - QString lhp = lhd.absoluteFilePath(lhs); - QString rhp = rhd.absoluteFilePath(rhs); - return QFileInfo(lhp).lastModified() < - QFileInfo(rhp).lastModified(); - }); + std::sort(plugins.begin(), plugins.end(), + [&](const QString& lhs, const QString& rhs) { + MOBase::IModInterface* lhm = + organizer()->modList()->getMod(pluginList->origin(lhs)); + MOBase::IModInterface* rhm = + organizer()->modList()->getMod(pluginList->origin(rhs)); + QDir lhd = organizer()->managedGame()->dataDirectory(); + QDir rhd = organizer()->managedGame()->dataDirectory(); + if (lhm != nullptr) + lhd = lhm->absolutePath(); + if (rhm != nullptr) + rhd = rhm->absolutePath(); + QString lhp = lhd.absoluteFilePath(lhs); + QString rhp = rhd.absoluteFilePath(rhs); + return QFileInfo(lhp).lastModified() < QFileInfo(rhp).lastModified(); + }); // Determine plugin active state by the plugins.txt file. bool pluginsTxtExists = true; - QString filePath = organizer()->profile()->absolutePath() + "/plugins.txt"; + QString filePath = organizer()->profile()->absolutePath() + "/plugins.txt"; QFile file(filePath); if (!file.open(QIODevice::ReadOnly)) { pluginsTxtExists = false; @@ -233,7 +239,7 @@ QStringList GamebryoGamePlugins::readPluginList(MOBase::IPluginList *pluginList) } } } else { - for (const QString &pluginName : plugins) { + for (const QString& pluginName : plugins) { pluginList->setState(pluginName, IPluginList::STATE_INACTIVE); } } @@ -244,4 +250,4 @@ QStringList GamebryoGamePlugins::readPluginList(MOBase::IPluginList *pluginList) bool GamebryoGamePlugins::lightPluginsAreSupported() { return false; -} \ No newline at end of file +} diff --git a/src/gamebryo/gamebryogameplugins.h b/src/gamebryo/gamebryogameplugins.h index 58628d9b..5766bf50 100644 --- a/src/gamebryo/gamebryogameplugins.h +++ b/src/gamebryo/gamebryogameplugins.h @@ -1,42 +1,42 @@ #ifndef GAMEBRYOGAMEPLUGINS_H #define GAMEBRYOGAMEPLUGINS_H - -#include -#include #include #include +#include +#include -class GamebryoGamePlugins : public GamePlugins { +class GamebryoGamePlugins : public GamePlugins +{ public: - GamebryoGamePlugins(MOBase::IOrganizer *organizer); + GamebryoGamePlugins(MOBase::IOrganizer* organizer); - virtual void writePluginLists(const MOBase::IPluginList *pluginList) override; - virtual void readPluginLists(MOBase::IPluginList *pluginList) override; + virtual void writePluginLists(const MOBase::IPluginList* pluginList) override; + virtual void readPluginLists(MOBase::IPluginList* pluginList) override; virtual QStringList getLoadOrder() override; virtual bool lightPluginsAreSupported() override; protected: - MOBase::IOrganizer *organizer() const { return m_Organizer; } + MOBase::IOrganizer* organizer() const { return m_Organizer; } - virtual void writePluginList(const MOBase::IPluginList *pluginList, - const QString &filePath); - virtual void writeLoadOrderList(const MOBase::IPluginList *pluginList, - const QString &filePath); - virtual QStringList readLoadOrderList(MOBase::IPluginList *pluginList, - const QString &filePath); - virtual QStringList readPluginList(MOBase::IPluginList *pluginList); + virtual void writePluginList(const MOBase::IPluginList* pluginList, + const QString& filePath); + virtual void writeLoadOrderList(const MOBase::IPluginList* pluginList, + const QString& filePath); + virtual QStringList readLoadOrderList(MOBase::IPluginList* pluginList, + const QString& filePath); + virtual QStringList readPluginList(MOBase::IPluginList* pluginList); protected: - MOBase::IOrganizer *m_Organizer; + MOBase::IOrganizer* m_Organizer; QDateTime m_LastRead; private: - void writeList(const MOBase::IPluginList *pluginList, const QString &filePath, + void writeList(const MOBase::IPluginList* pluginList, const QString& filePath, bool loadOrder); private: std::map m_LastSaveHash; }; -#endif // GAMEBRYOGAMEPLUGINS_H +#endif // GAMEBRYOGAMEPLUGINS_H diff --git a/src/gamebryo/gamebryolocalsavegames.cpp b/src/gamebryo/gamebryolocalsavegames.cpp index 90ad93f1..142cbf4f 100644 --- a/src/gamebryo/gamebryolocalsavegames.cpp +++ b/src/gamebryo/gamebryolocalsavegames.cpp @@ -16,57 +16,48 @@ License along with this library; if not, write to the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA */ - #include "gamebryolocalsavegames.h" #include "registry.h" -#include #include -#include +#include #include #include - +#include static const QString LocalSavesDummy = "__MO_Saves\\"; - GamebryoLocalSavegames::GamebryoLocalSavegames(const QDir& myGamesDir, - const QString& iniFileName) - : m_LocalSavesDir(myGamesDir.absoluteFilePath(LocalSavesDummy)) - , m_LocalGameDir(myGamesDir.absolutePath()) - , m_IniFileName(iniFileName) + const QString& iniFileName) + : m_LocalSavesDir(myGamesDir.absoluteFilePath(LocalSavesDummy)), + m_LocalGameDir(myGamesDir.absolutePath()), m_IniFileName(iniFileName) {} - MappingType GamebryoLocalSavegames::mappings(const QDir& profileSaveDir) const { - return { { - profileSaveDir.absolutePath(), - m_LocalSavesDir.absolutePath(), - true, - true - } }; + return {{profileSaveDir.absolutePath(), m_LocalSavesDir.absolutePath(), true, true}}; } - bool GamebryoLocalSavegames::prepareProfile(MOBase::IProfile* profile) { bool enable = profile->localSavesEnabled(); - QString basePath - = profile->localSettingsEnabled() - ? profile->absolutePath() - : m_LocalGameDir.absolutePath(); + QString basePath = profile->localSettingsEnabled() ? profile->absolutePath() + : m_LocalGameDir.absolutePath(); QString iniFilePath = basePath + "/" + m_IniFileName; - QString saveIni = profile->absolutePath() + "/" + "savepath.ini"; + QString saveIni = profile->absolutePath() + "/" + "savepath.ini"; // Get the current sLocalSavePath WCHAR currentPath[MAX_PATH]; - GetPrivateProfileStringW(L"General", L"sLocalSavePath", L"SKIP_ME", currentPath, MAX_PATH, iniFilePath.toStdWString().c_str()); - bool alreadyEnabled = wcscmp(currentPath, LocalSavesDummy.toStdWString().c_str()) == 0; + GetPrivateProfileStringW(L"General", L"sLocalSavePath", L"SKIP_ME", currentPath, + MAX_PATH, iniFilePath.toStdWString().c_str()); + bool alreadyEnabled = + wcscmp(currentPath, LocalSavesDummy.toStdWString().c_str()) == 0; // Get the current bUseMyGamesDirectory WCHAR currentMyGames[MAX_PATH]; - GetPrivateProfileStringW(L"General", L"bUseMyGamesDirectory", L"SKIP_ME", currentMyGames, MAX_PATH, iniFilePath.toStdWString().c_str()); + GetPrivateProfileStringW(L"General", L"bUseMyGamesDirectory", L"SKIP_ME", + currentMyGames, MAX_PATH, + iniFilePath.toStdWString().c_str()); // Create the __MO_Saves directory if local saves are enabled and it doesn't exist if (enable) { @@ -80,13 +71,18 @@ bool GamebryoLocalSavegames::prepareProfile(MOBase::IProfile* profile) if (enable && !alreadyEnabled) { // If the path is not blank, save it to savepath.ini if (wcscmp(currentPath, L"SKIP_ME") != 0) { - MOBase::WriteRegistryValue(L"General", L"sLocalSavePath", currentPath, saveIni.toStdWString().c_str()); + MOBase::WriteRegistryValue(L"General", L"sLocalSavePath", currentPath, + saveIni.toStdWString().c_str()); } if (wcscmp(currentMyGames, L"SKIP_ME") != 0) { - MOBase::WriteRegistryValue(L"General", L"bUseMyGamesDirectory", currentMyGames, saveIni.toStdWString().c_str()); + MOBase::WriteRegistryValue(L"General", L"bUseMyGamesDirectory", currentMyGames, + saveIni.toStdWString().c_str()); } - MOBase::WriteRegistryValue(L"General", L"sLocalSavePath", LocalSavesDummy.toStdWString().c_str(), iniFilePath.toStdWString().c_str()); - MOBase::WriteRegistryValue(L"General", L"bUseMyGamesDirectory", L"1", iniFilePath.toStdWString().c_str()); + MOBase::WriteRegistryValue(L"General", L"sLocalSavePath", + LocalSavesDummy.toStdWString().c_str(), + iniFilePath.toStdWString().c_str()); + MOBase::WriteRegistryValue(L"General", L"bUseMyGamesDirectory", L"1", + iniFilePath.toStdWString().c_str()); } // Get rid of the local saves setting if it's still there @@ -95,26 +91,32 @@ bool GamebryoLocalSavegames::prepareProfile(MOBase::IProfile* profile) if (QFile::exists(saveIni)) { WCHAR savedPath[MAX_PATH]; WCHAR savedMyGames[MAX_PATH]; - GetPrivateProfileStringW(L"General", L"sLocalSavePath", L"DELETE_ME", savedPath, MAX_PATH, saveIni.toStdWString().c_str()); - GetPrivateProfileStringW(L"General", L"bUseMyGamesDirectory", L"DELETE_ME", savedMyGames, MAX_PATH, saveIni.toStdWString().c_str()); + GetPrivateProfileStringW(L"General", L"sLocalSavePath", L"DELETE_ME", savedPath, + MAX_PATH, saveIni.toStdWString().c_str()); + GetPrivateProfileStringW(L"General", L"bUseMyGamesDirectory", L"DELETE_ME", + savedMyGames, MAX_PATH, saveIni.toStdWString().c_str()); if (wcscmp(savedPath, L"DELETE_ME") != 0) { - MOBase::WriteRegistryValue(L"General", L"sLocalSavePath", savedPath, iniFilePath.toStdWString().c_str()); - } - else { - MOBase::WriteRegistryValue(L"General", L"sLocalSavePath", NULL, iniFilePath.toStdWString().c_str()); + MOBase::WriteRegistryValue(L"General", L"sLocalSavePath", savedPath, + iniFilePath.toStdWString().c_str()); + } else { + MOBase::WriteRegistryValue(L"General", L"sLocalSavePath", NULL, + iniFilePath.toStdWString().c_str()); } if (wcscmp(savedMyGames, L"DELETE_ME") != 0) { - MOBase::WriteRegistryValue(L"General", L"bUseMyGamesDirectory", savedMyGames, iniFilePath.toStdWString().c_str()); - } - else { - MOBase::WriteRegistryValue(L"General", L"bUseMyGamesDirectory", NULL, iniFilePath.toStdWString().c_str()); + MOBase::WriteRegistryValue(L"General", L"bUseMyGamesDirectory", savedMyGames, + iniFilePath.toStdWString().c_str()); + } else { + MOBase::WriteRegistryValue(L"General", L"bUseMyGamesDirectory", NULL, + iniFilePath.toStdWString().c_str()); } QFile::remove(saveIni); } // Otherwise just delete the setting else { - MOBase::WriteRegistryValue(L"General", L"sLocalSavePath", NULL, iniFilePath.toStdWString().c_str()); - MOBase::WriteRegistryValue(L"General", L"bUseMyGamesDirectory", NULL, iniFilePath.toStdWString().c_str()); + MOBase::WriteRegistryValue(L"General", L"sLocalSavePath", NULL, + iniFilePath.toStdWString().c_str()); + MOBase::WriteRegistryValue(L"General", L"bUseMyGamesDirectory", NULL, + iniFilePath.toStdWString().c_str()); } } diff --git a/src/gamebryo/gamebryolocalsavegames.h b/src/gamebryo/gamebryolocalsavegames.h index e2f0bb48..7b1dd738 100644 --- a/src/gamebryo/gamebryolocalsavegames.h +++ b/src/gamebryo/gamebryolocalsavegames.h @@ -16,11 +16,9 @@ License along with this library; if not, write to the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA */ - #ifndef GAMEBRYOLOCALSAVEGAMES_H #define GAMEBRYOLOCALSAVEGAMES_H - #include #include @@ -30,18 +28,15 @@ class GamebryoLocalSavegames : public LocalSavegames { public: - GamebryoLocalSavegames(const QDir &myGamesDir, const QString &iniFileName); + GamebryoLocalSavegames(const QDir& myGamesDir, const QString& iniFileName); - virtual MappingType mappings(const QDir &profileSaveDir) const override; - virtual bool prepareProfile(MOBase::IProfile *profile) override; + virtual MappingType mappings(const QDir& profileSaveDir) const override; + virtual bool prepareProfile(MOBase::IProfile* profile) override; private: - QDir m_LocalSavesDir; QDir m_LocalGameDir; QString m_IniFileName; - }; - -#endif // GAMEBRYOLOCALSAVEGAMES_H +#endif // GAMEBRYOLOCALSAVEGAMES_H diff --git a/src/gamebryo/gamebryomoddatachecker.cpp b/src/gamebryo/gamebryomoddatachecker.cpp index 224dc8ea..b5bace63 100644 --- a/src/gamebryo/gamebryomoddatachecker.cpp +++ b/src/gamebryo/gamebryomoddatachecker.cpp @@ -2,45 +2,71 @@ #include "gamebryomoddatachecker.h" - - /** * @return the list of possible folder names in data. */ -auto GamebryoModDataChecker::possibleFolderNames() const -> const FileNameSet& { - static FileNameSet result{ - "fonts", "interface", "menus", "meshes", "music", "scripts", "shaders", - "sound", "strings", "textures", "trees", "video", "facegen", "materials", - "skse", "obse", "mwse", "nvse", "fose", "f4se", "distantlod", "asi", - "SkyProc Patchers", "Tools", "MCM", "icons", "bookart", "distantland", - "mits", "splash", "dllplugins", "CalienteTools", "NetScriptFramework", - "shadersfx" - }; +auto GamebryoModDataChecker::possibleFolderNames() const -> const FileNameSet& +{ + static FileNameSet result{"fonts", + "interface", + "menus", + "meshes", + "music", + "scripts", + "shaders", + "sound", + "strings", + "textures", + "trees", + "video", + "facegen", + "materials", + "skse", + "obse", + "mwse", + "nvse", + "fose", + "f4se", + "distantlod", + "asi", + "SkyProc Patchers", + "Tools", + "MCM", + "icons", + "bookart", + "distantland", + "mits", + "splash", + "dllplugins", + "CalienteTools", + "NetScriptFramework", + "shadersfx"}; return result; } /** * @return the extensions of possible files in data. */ -auto GamebryoModDataChecker::possibleFileExtensions() const -> const FileNameSet& { - static FileNameSet result{ - "esp", "esm", "esl", "bsa", "ba2", "modgroups", "ini" - }; +auto GamebryoModDataChecker::possibleFileExtensions() const -> const FileNameSet& +{ + static FileNameSet result{"esp", "esm", "esl", "bsa", "ba2", "modgroups", "ini"}; return result; } -GamebryoModDataChecker::GamebryoModDataChecker(const GameGamebryo* game) : m_Game(game) { } +GamebryoModDataChecker::GamebryoModDataChecker(const GameGamebryo* game) : m_Game(game) +{} -GamebryoModDataChecker::CheckReturn GamebryoModDataChecker::dataLooksValid(std::shared_ptr fileTree) const { - auto& folders = possibleFolderNames(); +GamebryoModDataChecker::CheckReturn GamebryoModDataChecker::dataLooksValid( + std::shared_ptr fileTree) const +{ + auto& folders = possibleFolderNames(); auto& suffixes = possibleFileExtensions(); for (auto entry : *fileTree) { if (entry->isDir()) { if (folders.count(entry->name()) > 0) { return CheckReturn::VALID; } - } - else { + } else { if (suffixes.count(entry->suffix()) > 0) { return CheckReturn::VALID; } diff --git a/src/gamebryo/gamebryomoddatachecker.h b/src/gamebryo/gamebryomoddatachecker.h index 56a54e35..9a648bdd 100644 --- a/src/gamebryo/gamebryomoddatachecker.h +++ b/src/gamebryo/gamebryomoddatachecker.h @@ -1,8 +1,8 @@ #ifndef GAMEBRYO_MODATACHECKER_H #define GAMEBRYO_MODATACHECKER_H -#include #include +#include class GameGamebryo; @@ -10,24 +10,23 @@ class GameGamebryo; * @brief ModDataChecker for GameBryo games that look at folder and files in the "data" * directory. * - * The default implementation is game-agnostic and uses the list of folders and file extensions - * that were used before the ModDataChecker feature was added. It is possible to inherit the class - * to provide custom list of folders or filenames. + * The default implementation is game-agnostic and uses the list of folders and file + * extensions that were used before the ModDataChecker feature was added. It is possible + * to inherit the class to provide custom list of folders or filenames. */ -class GamebryoModDataChecker: public ModDataChecker { +class GamebryoModDataChecker : public ModDataChecker +{ public: - - /** * @brief Construct a new mod-data checker for GameBryo games. */ GamebryoModDataChecker(const GameGamebryo* game); - virtual CheckReturn dataLooksValid(std::shared_ptr fileTree) const override; + virtual CheckReturn + dataLooksValid(std::shared_ptr fileTree) const override; protected: - - GameGamebryo const * const m_Game; + GameGamebryo const* const m_Game; using FileNameSet = std::set; @@ -42,7 +41,6 @@ protected: * @return the extensions of possible files in data. */ virtual const FileNameSet& possibleFileExtensions() const; - }; -#endif // GAMEBRYO_MODATACHECKER_H +#endif // GAMEBRYO_MODATACHECKER_H diff --git a/src/gamebryo/gamebryomoddatacontent.cpp b/src/gamebryo/gamebryomoddatacontent.cpp index 5d8560fa..85ded01d 100644 --- a/src/gamebryo/gamebryomoddatacontent.cpp +++ b/src/gamebryo/gamebryomoddatacontent.cpp @@ -4,93 +4,94 @@ #include "gamegamebryo.h" -GamebryoModDataContent::GamebryoModDataContent(GameGamebryo const* gamePlugin) : - m_GamePlugin(gamePlugin), m_Enabled(CONTENT_MODGROUP + 1, true) { } +GamebryoModDataContent::GamebryoModDataContent(GameGamebryo const* gamePlugin) + : m_GamePlugin(gamePlugin), m_Enabled(CONTENT_MODGROUP + 1, true) +{} -std::vector GamebryoModDataContent::getAllContents() const { +std::vector +GamebryoModDataContent::getAllContents() const +{ static std::vector GAMEBRYO_CONTENTS{ - {CONTENT_PLUGIN, QT_TR_NOOP("Plugins (ESP/ESM/ESL)"), ":/MO/gui/content/plugin"}, - {CONTENT_OPTIONAL, QT_TR_NOOP("Optional Plugins"), "", true}, - {CONTENT_INTERFACE, QT_TR_NOOP("Interface"), ":/MO/gui/content/interface"}, - {CONTENT_MESH, QT_TR_NOOP("Meshes"), ":/MO/gui/content/mesh"}, - {CONTENT_BSA, QT_TR_NOOP("Bethesda Archive"), ":/MO/gui/content/bsa"}, - {CONTENT_SCRIPT, QT_TR_NOOP("Scripts (Papyrus)"), ":/MO/gui/content/script"}, - {CONTENT_SKSE, QT_TR_NOOP("Script Extender Plugin"), ":/MO/gui/content/skse"}, - {CONTENT_SKSE_FILES, QT_TR_NOOP("Script Extender Files"), "", true}, - {CONTENT_SKYPROC, QT_TR_NOOP("SkyProc Patcher"), ":/MO/gui/content/skyproc"}, - {CONTENT_SOUND, QT_TR_NOOP("Sound or Music"), ":/MO/gui/content/sound"}, - {CONTENT_TEXTURE, QT_TR_NOOP("Textures"), ":/MO/gui/content/texture"}, - {CONTENT_MCM, QT_TR_NOOP("MCM Configuration"), ":/MO/gui/content/menu"}, - {CONTENT_INI, QT_TR_NOOP("INI Files"), ":/MO/gui/content/inifile"}, - {CONTENT_FACEGEN, QT_TR_NOOP("FaceGen Data"), ":/MO/gui/content/facegen"}, - {CONTENT_MODGROUP, QT_TR_NOOP("ModGroup Files"), ":/MO/gui/content/modgroup"} - }; + {CONTENT_PLUGIN, QT_TR_NOOP("Plugins (ESP/ESM/ESL)"), ":/MO/gui/content/plugin"}, + {CONTENT_OPTIONAL, QT_TR_NOOP("Optional Plugins"), "", true}, + {CONTENT_INTERFACE, QT_TR_NOOP("Interface"), ":/MO/gui/content/interface"}, + {CONTENT_MESH, QT_TR_NOOP("Meshes"), ":/MO/gui/content/mesh"}, + {CONTENT_BSA, QT_TR_NOOP("Bethesda Archive"), ":/MO/gui/content/bsa"}, + {CONTENT_SCRIPT, QT_TR_NOOP("Scripts (Papyrus)"), ":/MO/gui/content/script"}, + {CONTENT_SKSE, QT_TR_NOOP("Script Extender Plugin"), ":/MO/gui/content/skse"}, + {CONTENT_SKSE_FILES, QT_TR_NOOP("Script Extender Files"), "", true}, + {CONTENT_SKYPROC, QT_TR_NOOP("SkyProc Patcher"), ":/MO/gui/content/skyproc"}, + {CONTENT_SOUND, QT_TR_NOOP("Sound or Music"), ":/MO/gui/content/sound"}, + {CONTENT_TEXTURE, QT_TR_NOOP("Textures"), ":/MO/gui/content/texture"}, + {CONTENT_MCM, QT_TR_NOOP("MCM Configuration"), ":/MO/gui/content/menu"}, + {CONTENT_INI, QT_TR_NOOP("INI Files"), ":/MO/gui/content/inifile"}, + {CONTENT_FACEGEN, QT_TR_NOOP("FaceGen Data"), ":/MO/gui/content/facegen"}, + {CONTENT_MODGROUP, QT_TR_NOOP("ModGroup Files"), ":/MO/gui/content/modgroup"}}; // Copy the list of enabled contents: std::vector contents; std::copy_if(std::begin(GAMEBRYO_CONTENTS), std::end(GAMEBRYO_CONTENTS), - std::back_inserter(contents), [this](auto e) { return m_Enabled[e.id()]; }); + std::back_inserter(contents), [this](auto e) { + return m_Enabled[e.id()]; + }); return contents; } -std::vector GamebryoModDataContent::getContentsFor(std::shared_ptr fileTree) const { +std::vector GamebryoModDataContent::getContentsFor( + std::shared_ptr fileTree) const +{ std::vector contents; for (auto e : *fileTree) { if (e->isFile()) { auto suffix = e->suffix().toLower(); - if (m_Enabled[CONTENT_PLUGIN] && (suffix == "esp" || suffix == "esm" || suffix == "esl")) { + if (m_Enabled[CONTENT_PLUGIN] && + (suffix == "esp" || suffix == "esm" || suffix == "esl")) { contents.push_back(CONTENT_PLUGIN); - } - else if (m_Enabled[CONTENT_BSA] && (suffix == "bsa" || suffix == "ba2")) { + } else if (m_Enabled[CONTENT_BSA] && (suffix == "bsa" || suffix == "ba2")) { contents.push_back(CONTENT_BSA); - } - else if (m_Enabled[CONTENT_INI] && suffix == "ini" && e->compare("meta.ini") != 0) { + } else if (m_Enabled[CONTENT_INI] && suffix == "ini" && + e->compare("meta.ini") != 0) { contents.push_back(CONTENT_INI); - } - else if (m_Enabled[CONTENT_MODGROUP] && suffix == "modgroups") { + } else if (m_Enabled[CONTENT_MODGROUP] && suffix == "modgroups") { contents.push_back(CONTENT_MODGROUP); } - } - else { - if (m_Enabled[CONTENT_TEXTURE] && (e->compare("textures") == 0 || e->compare("icons") == 0 || e->compare("bookart") == 0)) { + } else { + if (m_Enabled[CONTENT_TEXTURE] && + (e->compare("textures") == 0 || e->compare("icons") == 0 || + e->compare("bookart") == 0)) { contents.push_back(CONTENT_TEXTURE); - } - else if (m_Enabled[CONTENT_MESH] && e->compare("meshes") == 0) { + } else if (m_Enabled[CONTENT_MESH] && e->compare("meshes") == 0) { contents.push_back(CONTENT_MESH); - } - else if (m_Enabled[CONTENT_INTERFACE] && (e->compare("interface") == 0 || e->compare("menus") == 0)) { + } else if (m_Enabled[CONTENT_INTERFACE] && + (e->compare("interface") == 0 || e->compare("menus") == 0)) { contents.push_back(CONTENT_INTERFACE); - } - else if (m_Enabled[CONTENT_SOUND] && e->compare("music") == 0 || e->compare("sound") == 0) { + } else if (m_Enabled[CONTENT_SOUND] && e->compare("music") == 0 || + e->compare("sound") == 0) { contents.push_back(CONTENT_SOUND); - } - else if (m_Enabled[CONTENT_SCRIPT] && e->compare("scripts") == 0) { + } else if (m_Enabled[CONTENT_SCRIPT] && e->compare("scripts") == 0) { contents.push_back(CONTENT_SCRIPT); - } - else if (m_Enabled[CONTENT_SKYPROC] && e->compare("SkyProc Patchers") == 0) { + } else if (m_Enabled[CONTENT_SKYPROC] && e->compare("SkyProc Patchers") == 0) { contents.push_back(CONTENT_SKYPROC); - } - else if (m_Enabled[CONTENT_MCM] && e->compare("MCM") == 0) { + } else if (m_Enabled[CONTENT_MCM] && e->compare("MCM") == 0) { contents.push_back(CONTENT_MCM); - } - else if (m_Enabled[CONTENT_OPTIONAL] && e->compare("Optional") == 0 && e->astree()->size() > 0) { + } else if (m_Enabled[CONTENT_OPTIONAL] && e->compare("Optional") == 0 && + e->astree()->size() > 0) { contents.push_back(CONTENT_OPTIONAL); } } } if (m_Enabled[CONTENT_FACEGEN]) { - auto e1 = fileTree->findDirectory("meshes/actors/character/facegendata"); - if (e1) { - contents.push_back(CONTENT_FACEGEN); - } - else { - auto e2 = fileTree->findDirectory("textures/actors/character/facegendata"); - if (e2) { - contents.push_back(CONTENT_FACEGEN); - } + auto e1 = fileTree->findDirectory("meshes/actors/character/facegendata"); + if (e1) { + contents.push_back(CONTENT_FACEGEN); + } else { + auto e2 = fileTree->findDirectory("textures/actors/character/facegendata"); + if (e2) { + contents.push_back(CONTENT_FACEGEN); } + } } ScriptExtender* extender = m_GamePlugin->feature(); @@ -112,4 +113,4 @@ std::vector GamebryoModDataContent::getContentsFor(std::shared_ptr #include +#include class GameGamebryo; @@ -10,14 +10,15 @@ class GameGamebryo; * @brief ModDataContent for GameBryo games. * */ -class GamebryoModDataContent : public ModDataContent { +class GamebryoModDataContent : public ModDataContent +{ protected: - /** * Note: These are used to index m_Enabled so should have standard * enum values, not custom ones. */ - enum EContent { + enum EContent + { CONTENT_PLUGIN, CONTENT_OPTIONAL, CONTENT_TEXTURE, @@ -41,7 +42,6 @@ protected: constexpr static auto CONTENT_NEXT_VALUE = CONTENT_MODGROUP + 1; public: - /** * */ @@ -59,15 +59,14 @@ public: * * @return the IDs of the content in the given tree. */ - virtual std::vector getContentsFor(std::shared_ptr fileTree) const override; + virtual std::vector + getContentsFor(std::shared_ptr fileTree) const override; protected: - GameGamebryo const* const m_GamePlugin; // List of enabled contents: std::vector m_Enabled; - }; -#endif // GAMEBRYO_MODDATACONTENT_H +#endif // GAMEBRYO_MODDATACONTENT_H diff --git a/src/gamebryo/gamebryosavegame.cpp b/src/gamebryo/gamebryosavegame.cpp index 2227eb0d..c8534783 100644 --- a/src/gamebryo/gamebryosavegame.cpp +++ b/src/gamebryo/gamebryosavegame.cpp @@ -1,8 +1,8 @@ #include "gamebryosavegame.h" #include "iplugingame.h" -#include "scriptextender.h" #include "log.h" +#include "scriptextender.h" #include #include @@ -16,21 +16,17 @@ #include #include - #include "gamegamebryo.h" -GamebryoSaveGame::GamebryoSaveGame(QString const &file, GameGamebryo const *game, bool const lightEnabled) : - m_FileName(file), - m_CreationTime(QFileInfo(file).lastModified()), - m_Game(game), - m_LightEnabled(lightEnabled), - m_DataFields([this]() { return fetchDataFields(); }) -{ -} +GamebryoSaveGame::GamebryoSaveGame(QString const& file, GameGamebryo const* game, + bool const lightEnabled) + : m_FileName(file), m_CreationTime(QFileInfo(file).lastModified()), m_Game(game), + m_LightEnabled(lightEnabled), m_DataFields([this]() { + return fetchDataFields(); + }) +{} -GamebryoSaveGame::~GamebryoSaveGame() -{ -} +GamebryoSaveGame::~GamebryoSaveGame() {} QString GamebryoSaveGame::getFilepath() const { @@ -45,10 +41,10 @@ QDateTime GamebryoSaveGame::getCreationTime() const QString GamebryoSaveGame::getName() const { return QObject::tr("%1, #%2, Level %3, %4") - .arg(m_PCName) - .arg(m_SaveNumber) - .arg(m_PCLevel) - .arg(m_PCLocation); + .arg(m_PCName) + .arg(m_SaveNumber) + .arg(m_PCLevel) + .arg(m_PCLocation); } QString GamebryoSaveGame::getSaveGroupIdentifier() const @@ -58,12 +54,13 @@ QString GamebryoSaveGame::getSaveGroupIdentifier() const QStringList GamebryoSaveGame::allFiles() const { - //This returns all valid files associated with this game - QStringList res = { m_FileName }; - ScriptExtender const *e = m_Game->feature(); + // This returns all valid files associated with this game + QStringList res = {m_FileName}; + ScriptExtender const* e = m_Game->feature(); if (e != nullptr) { QFileInfo file(m_FileName); - QFileInfo SEfile(file.absolutePath() + "/" + file.completeBaseName() + "." + m_Game->savegameSEExtension()); + QFileInfo SEfile(file.absolutePath() + "/" + file.completeBaseName() + "." + + m_Game->savegameSEExtension()); if (SEfile.exists()) { res.push_back(SEfile.absoluteFilePath()); } @@ -74,11 +71,12 @@ QStringList GamebryoSaveGame::allFiles() const bool GamebryoSaveGame::hasScriptExtenderFile() const { QFileInfo file(m_FileName); - QFileInfo SEfile(file.absolutePath() + "/" + file.completeBaseName() + "." + m_Game->savegameSEExtension()); + QFileInfo SEfile(file.absolutePath() + "/" + file.completeBaseName() + "." + + m_Game->savegameSEExtension()); return SEfile.exists(); } -void GamebryoSaveGame::setCreationTime(_SYSTEMTIME const &ctime) +void GamebryoSaveGame::setCreationTime(_SYSTEMTIME const& ctime) { QDate date; date.setDate(ctime.wYear, ctime.wMonth, ctime.wDay); @@ -88,13 +86,14 @@ void GamebryoSaveGame::setCreationTime(_SYSTEMTIME const &ctime) m_CreationTime = QDateTime(date, time, Qt::UTC); } -GamebryoSaveGame::FileWrapper::FileWrapper(QString const& filepath, QString const &expected) : - m_File(filepath), - m_HasFieldMarkers(false), - m_PluginString(StringType::TYPE_WSTRING) +GamebryoSaveGame::FileWrapper::FileWrapper(QString const& filepath, + QString const& expected) + : m_File(filepath), m_HasFieldMarkers(false), + m_PluginString(StringType::TYPE_WSTRING) { if (!m_File.open(QIODevice::ReadOnly)) { - throw std::runtime_error(QObject::tr("failed to open %1").arg(filepath).toUtf8().constData()); + throw std::runtime_error( + QObject::tr("failed to open %1").arg(filepath).toUtf8().constData()); } std::vector fileID(expected.length() + 1); @@ -103,8 +102,11 @@ GamebryoSaveGame::FileWrapper::FileWrapper(QString const& filepath, QString cons QString id(fileID.data()); if (expected != id) { - throw std::runtime_error( - QObject::tr("wrong file format - expected %1 got %2").arg(expected).arg(id).toUtf8().constData()); + throw std::runtime_error(QObject::tr("wrong file format - expected %1 got %2") + .arg(expected) + .arg(id) + .toUtf8() + .constData()); } } @@ -118,10 +120,12 @@ void GamebryoSaveGame::FileWrapper::setPluginString(StringType type) m_PluginString = type; } -template <> void GamebryoSaveGame::FileWrapper::read(QString &value) +template <> +void GamebryoSaveGame::FileWrapper::read(QString& value) { unsigned short length; - if (m_PluginString == StringType::TYPE_BSTRING || m_PluginString == StringType::TYPE_BZSTRING) { + if (m_PluginString == StringType::TYPE_BSTRING || + m_PluginString == StringType::TYPE_BZSTRING) { unsigned char len; read(len); length = m_PluginString == StringType::TYPE_BZSTRING ? len + 1 : len; @@ -136,7 +140,8 @@ template <> void GamebryoSaveGame::FileWrapper::read(QString &value) QByteArray buffer; buffer.resize(length); - read(buffer.data(), m_PluginString == StringType::TYPE_BZSTRING ? length - 1 : length); + read(buffer.data(), + m_PluginString == StringType::TYPE_BZSTRING ? length - 1 : length); if (m_PluginString == StringType::TYPE_BZSTRING) buffer[length - 1] = '\0'; @@ -148,9 +153,9 @@ template <> void GamebryoSaveGame::FileWrapper::read(QString &value) value = QString::fromUtf8(buffer.constData()); } -void GamebryoSaveGame::FileWrapper::read(void *buff, std::size_t length) +void GamebryoSaveGame::FileWrapper::read(void* buff, std::size_t length) { - int read = m_File.read(static_cast(buff), length); + int read = m_File.read(static_cast(buff), length); if (read != length) { throw std::runtime_error("unexpected end of file"); } @@ -165,13 +170,15 @@ QImage GamebryoSaveGame::FileWrapper::readImage(int scale, bool alpha) return readImage(width, height, scale, alpha); } -QImage GamebryoSaveGame::FileWrapper::readImage(unsigned long width, unsigned long height, int scale, bool alpha) +QImage GamebryoSaveGame::FileWrapper::readImage(unsigned long width, + unsigned long height, int scale, + bool alpha) { int bpp = alpha ? 4 : 3; QScopedArrayPointer buffer(new unsigned char[width * height * bpp]); read(buffer.data(), width * height * bpp); - QImage image(buffer.data(), width, height, alpha ? QImage::Format_RGBA8888_Premultiplied - : QImage::Format_RGB888); + QImage image(buffer.data(), width, height, + alpha ? QImage::Format_RGBA8888_Premultiplied : QImage::Format_RGB888); // We need to copy the image here because QImage does not make a copy of the // buffer when constructed. @@ -181,20 +188,24 @@ QImage GamebryoSaveGame::FileWrapper::readImage(unsigned long width, unsigned lo return image.copy(); } } -void readQDataStream(QDataStream &data, void *buff, std::size_t length) { - int read = data.readRawData(static_cast(buff), static_cast(length)); +void readQDataStream(QDataStream& data, void* buff, std::size_t length) +{ + int read = data.readRawData(static_cast(buff), static_cast(length)); if (read != length) { throw std::runtime_error("unexpected end of file"); } } -template void readQDataStream(QDataStream &data, T &value) { +template +void readQDataStream(QDataStream& data, T& value) +{ int read = data.readRawData(reinterpret_cast(&value), sizeof(T)); if (read != sizeof(T)) { throw std::runtime_error("unexpected end of file"); } } -template <> void readQDataStream(QDataStream &data, QString &value) +template <> +void readQDataStream(QDataStream& data, QString& value) { unsigned short length; readQDataStream(data, length); @@ -214,26 +225,26 @@ void GamebryoSaveGame::FileWrapper::setCompressionType(uint16_t compressionType) void GamebryoSaveGame::FileWrapper::closeCompressedData() { if (m_CompressionType == 0) { - } - else if (m_CompressionType == 1) { - MOBase::log::warn("Please create an issue on the MO github labeled \"Found zlib Compressed\" with your savefile attached"); - } - else if (m_CompressionType == 2) { + } else if (m_CompressionType == 1) { + MOBase::log::warn("Please create an issue on the MO github labeled \"Found zlib " + "Compressed\" with your savefile attached"); + } else if (m_CompressionType == 2) { m_Data->device()->close(); delete m_Data; - } - else - MOBase::log::warn("Please create an issue on the MO github labeled \"Found unknown Compressed\" with your savefile attached"); + } else + MOBase::log::warn("Please create an issue on the MO github labeled \"Found unknown " + "Compressed\" with your savefile attached"); } bool GamebryoSaveGame::FileWrapper::openCompressedData(int bytesToIgnore) { if (m_CompressionType == 0) { - if (bytesToIgnore>0)//Just to make certain + if (bytesToIgnore > 0) // Just to make certain skip(bytesToIgnore); return false; } else if (m_CompressionType == 1) { - MOBase::log::warn("Please create an issue on the MO github labeled \"Found zlib Compressed\" with your savefile attached"); + MOBase::log::warn("Please create an issue on the MO github labeled \"Found zlib " + "Compressed\" with your savefile attached"); return false; } else if (m_CompressionType == 2) { uint32_t uncompressedSize; @@ -245,7 +256,8 @@ bool GamebryoSaveGame::FileWrapper::openCompressedData(int bytesToIgnore) read(compressed.data(), compressedSize); QByteArray decompressed; decompressed.resize(uncompressedSize); - LZ4_decompress_safe_partial(compressed.data(), decompressed.data(), compressedSize, uncompressedSize, uncompressedSize); + LZ4_decompress_safe_partial(compressed.data(), decompressed.data(), compressedSize, + uncompressedSize, uncompressedSize); compressed.clear(); m_Data = new QDataStream(decompressed); @@ -253,7 +265,8 @@ bool GamebryoSaveGame::FileWrapper::openCompressedData(int bytesToIgnore) return true; } else { - MOBase::log::warn("Please create an issue on the MO github labeled \"Found unknown Compressed\" with your savefile attached"); + MOBase::log::warn("Please create an issue on the MO github labeled \"Found unknown " + "Compressed\" with your savefile attached"); return false; } } @@ -261,13 +274,14 @@ bool GamebryoSaveGame::FileWrapper::openCompressedData(int bytesToIgnore) uint8_t GamebryoSaveGame::FileWrapper::readChar(int bytesToIgnore) { if (m_CompressionType == 0) { - if (bytesToIgnore>0)//Just to make certain + if (bytesToIgnore > 0) // Just to make certain skip(bytesToIgnore); uint8_t version; read(version); return version; } else if (m_CompressionType == 1) { - MOBase::log::warn("Please create an issue on the MO github labeled \"Found zlib Compressed\" with your savefile attached"); + MOBase::log::warn("Please create an issue on the MO github labeled \"Found zlib " + "Compressed\" with your savefile attached"); return 0; } else if (m_CompressionType == 2) { // decompression already done by readSaveGameVersion @@ -278,7 +292,8 @@ uint8_t GamebryoSaveGame::FileWrapper::readChar(int bytesToIgnore) return version; } else { - MOBase::log::warn("Please create an issue on the MO github labeled \"Found unknown Compressed\" with your savefile attached"); + MOBase::log::warn("Please create an issue on the MO github labeled \"Found unknown " + "Compressed\" with your savefile attached"); return 0; } } @@ -286,13 +301,14 @@ uint8_t GamebryoSaveGame::FileWrapper::readChar(int bytesToIgnore) uint16_t GamebryoSaveGame::FileWrapper::readShort(int bytesToIgnore) { if (m_CompressionType == 0) { - if (bytesToIgnore>0)//Just to make certain + if (bytesToIgnore > 0) // Just to make certain skip(bytesToIgnore); uint16_t size; read(size); return size; } else if (m_CompressionType == 1) { - MOBase::log::warn("Please create an issue on the MO github labeled \"Found zlib Compressed\" with your savefile attached"); + MOBase::log::warn("Please create an issue on the MO github labeled \"Found zlib " + "Compressed\" with your savefile attached"); return 0; } else if (m_CompressionType == 2) { // decompression already done by readSaveGameVersion @@ -302,7 +318,8 @@ uint16_t GamebryoSaveGame::FileWrapper::readShort(int bytesToIgnore) readQDataStream(*m_Data, size); return size; } else { - MOBase::log::warn("Please create an issue on the MO github labeled \"Found unknown Compressed\" with your savefile attached"); + MOBase::log::warn("Please create an issue on the MO github labeled \"Found unknown " + "Compressed\" with your savefile attached"); return 0; } } @@ -310,13 +327,14 @@ uint16_t GamebryoSaveGame::FileWrapper::readShort(int bytesToIgnore) uint32_t GamebryoSaveGame::FileWrapper::readInt(int bytesToIgnore) { if (m_CompressionType == 0) { - if (bytesToIgnore>0)//Just to make certain + if (bytesToIgnore > 0) // Just to make certain skip(bytesToIgnore); uint32_t size; read(size); return size; } else if (m_CompressionType == 1) { - MOBase::log::warn("Please create an issue on the MO github labeled \"Found zlib Compressed\" with your savefile attached"); + MOBase::log::warn("Please create an issue on the MO github labeled \"Found zlib " + "Compressed\" with your savefile attached"); return 0; } else if (m_CompressionType == 2) { // decompression already done by readSaveGameVersion @@ -326,7 +344,8 @@ uint32_t GamebryoSaveGame::FileWrapper::readInt(int bytesToIgnore) readQDataStream(*m_Data, size); return size; } else { - MOBase::log::warn("Please create an issue on the MO github labeled \"Found unknown Compressed\" with your savefile attached"); + MOBase::log::warn("Please create an issue on the MO github labeled \"Found unknown " + "Compressed\" with your savefile attached"); return 0; } } @@ -335,7 +354,7 @@ QStringList GamebryoSaveGame::FileWrapper::readPlugins(int bytesToIgnore) { QStringList plugins; if (m_CompressionType == 0) { - if (bytesToIgnore>0)//Just to make certain + if (bytesToIgnore > 0) // Just to make certain skip(bytesToIgnore); uint8_t count; read(count); @@ -347,14 +366,15 @@ QStringList GamebryoSaveGame::FileWrapper::readPlugins(int bytesToIgnore) plugins.push_back(name); } } else if (m_CompressionType == 1) { - MOBase::log::warn("Please create an issue on the MO github labeled \"Found zlib Compressed\" with your savefile attached"); + MOBase::log::warn("Please create an issue on the MO github labeled \"Found zlib " + "Compressed\" with your savefile attached"); } else if (m_CompressionType == 2) { m_Data->skipRawData(bytesToIgnore); uint8_t count; readQDataStream(*m_Data, count); uint16_t finalCount = count; plugins.reserve(finalCount); - for (std::size_t i = 0; i0)//Just to make certain + if (bytesToIgnore > 0) // Just to make certain skip(bytesToIgnore); uint16_t count; read(count); @@ -378,14 +398,15 @@ QStringList GamebryoSaveGame::FileWrapper::readLightPlugins(int bytesToIgnore) plugins.push_back(name); } } else if (m_CompressionType == 1) { - MOBase::log::warn("Please create an issue on the MO github labeled \"Found zlib Compressed\" with your savefile attached"); + MOBase::log::warn("Please create an issue on the MO github labeled \"Found zlib " + "Compressed\" with your savefile attached"); } else if (m_CompressionType == 2) { m_Data->skipRawData(bytesToIgnore); uint16_t count; readQDataStream(*m_Data, count); plugins.reserve(count); - for (std::size_t i = 0; iPlugins; } - QStringList const &getLightPlugins() const { return m_DataFields.value()->LightPlugins; } - QImage const &getScreenshot() const { return m_DataFields.value()->Screenshot; } + QStringList const& getPlugins() const { return m_DataFields.value()->Plugins; } + QStringList const& getLightPlugins() const + { + return m_DataFields.value()->LightPlugins; + } + QImage const& getScreenshot() const { return m_DataFields.value()->Screenshot; } bool isLightEnabled() const { return m_LightEnabled; } @@ -58,7 +63,6 @@ public: }; protected: - friend class FileWrapper; class FileWrapper @@ -71,25 +75,27 @@ protected: * @params expected Expecte bytes at start of file. * **/ - FileWrapper(QString const& filepath, QString const &expected); + FileWrapper(QString const& filepath, QString const& expected); /** Set this for save games that have a marker at the end of each - * field. Specifically fallout - **/ + * field. Specifically fallout + **/ void setHasFieldMarkers(bool); /** Set bz string mode (1 byte length, null terminated) - **/ + **/ void setPluginString(StringType); - template void skip(int count = 1) + template + void skip(int count = 1) { if (!m_File.seek(m_File.pos() + count * sizeof(T))) { throw std::runtime_error("unexpected end of file"); } } - template void read(T &value) + template + void read(T& value) { int read = m_File.read(reinterpret_cast(&value), sizeof(T)); if (read != sizeof(T)) { @@ -107,15 +113,16 @@ protected: } } - void read(void *buff, std::size_t length); + void read(void* buff, std::size_t length); /* Reads RGB image from save - * Assumes picture dimentions come immediately before the save - */ + * Assumes picture dimentions come immediately before the save + */ QImage readImage(int scale = 0, bool alpha = false); /* Reads RGB image from save */ - QImage readImage(unsigned long width, unsigned long height, int scale = 0, bool alpha = false); + QImage readImage(unsigned long width, unsigned long height, int scale = 0, + bool alpha = false); /* Sets the compression type. */ void setCompressionType(uint16_t type); @@ -145,11 +152,11 @@ protected: QFile m_File; bool m_HasFieldMarkers; StringType m_PluginString; - QDataStream *m_Data; + QDataStream* m_Data; uint16_t m_CompressionType = 0; }; - void setCreationTime(_SYSTEMTIME const &time); + void setCreationTime(_SYSTEMTIME const& time); GameGamebryo const* m_Game; bool m_LightEnabled; @@ -166,23 +173,23 @@ protected: // // This is virtual so child class can add fields if those are // hard to access. - struct DataFields { + struct DataFields + { QStringList Plugins; QStringList LightPlugins; QImage Screenshot; // We need this constructor. - DataFields() { } - virtual ~DataFields() { } + DataFields() {} + virtual ~DataFields() {} }; MOBase::MemoizedLocked> m_DataFields; // Fetch the field. virtual std::unique_ptr fetchDataFields() const = 0; - }; +template <> +void GamebryoSaveGame::FileWrapper::read(QString&); -template <> void GamebryoSaveGame::FileWrapper::read(QString &); - -#endif // GAMEBRYOSAVEGAME_H +#endif // GAMEBRYOSAVEGAME_H diff --git a/src/gamebryo/gamebryosavegameinfo.cpp b/src/gamebryo/gamebryosavegameinfo.cpp index a165ad1b..6d1289af 100644 --- a/src/gamebryo/gamebryosavegameinfo.cpp +++ b/src/gamebryo/gamebryosavegameinfo.cpp @@ -3,8 +3,8 @@ #include "gamebryosavegame.h" #include "gamebryosavegameinfowidget.h" #include "gamegamebryo.h" -#include "imoinfo.h" #include "imodinterface.h" +#include "imoinfo.h" #include "iplugingame.h" #include "ipluginlist.h" @@ -12,60 +12,58 @@ #include #include -GamebryoSaveGameInfo::GamebryoSaveGameInfo(GameGamebryo const *game) : - m_Game(game) -{ -} +GamebryoSaveGameInfo::GamebryoSaveGameInfo(GameGamebryo const* game) : m_Game(game) {} -GamebryoSaveGameInfo::~GamebryoSaveGameInfo() -{ -} +GamebryoSaveGameInfo::~GamebryoSaveGameInfo() {} -GamebryoSaveGameInfo::MissingAssets GamebryoSaveGameInfo::getMissingAssets(MOBase::ISaveGame const& save) const +GamebryoSaveGameInfo::MissingAssets +GamebryoSaveGameInfo::getMissingAssets(MOBase::ISaveGame const& save) const { - GamebryoSaveGame const &gamebryoSave = dynamic_cast(save); - MOBase::IOrganizer *organizerCore = m_Game->m_Organizer; + GamebryoSaveGame const& gamebryoSave = dynamic_cast(save); + MOBase::IOrganizer* organizerCore = m_Game->m_Organizer; // collect the list of missing plugins MissingAssets missingAssets; - for (QString const &pluginName : gamebryoSave.getPlugins()) { + for (QString const& pluginName : gamebryoSave.getPlugins()) { switch (organizerCore->pluginList()->state(pluginName)) { - case MOBase::IPluginList::STATE_INACTIVE: - missingAssets[pluginName] = ProvidingModules { organizerCore->pluginList()->origin(pluginName) }; - break; - case MOBase::IPluginList::STATE_MISSING: - missingAssets[pluginName] = ProvidingModules(); - break; + case MOBase::IPluginList::STATE_INACTIVE: + missingAssets[pluginName] = + ProvidingModules{organizerCore->pluginList()->origin(pluginName)}; + break; + case MOBase::IPluginList::STATE_MISSING: + missingAssets[pluginName] = ProvidingModules(); + break; } } - for (QString const &pluginName : gamebryoSave.getLightPlugins()) { - switch (organizerCore->pluginList()->state(pluginName)) { - case MOBase::IPluginList::STATE_INACTIVE: - missingAssets[pluginName] = ProvidingModules{ organizerCore->pluginList()->origin(pluginName) }; - break; - case MOBase::IPluginList::STATE_MISSING: - missingAssets[pluginName] = ProvidingModules(); - break; - } + for (QString const& pluginName : gamebryoSave.getLightPlugins()) { + switch (organizerCore->pluginList()->state(pluginName)) { + case MOBase::IPluginList::STATE_INACTIVE: + missingAssets[pluginName] = + ProvidingModules{organizerCore->pluginList()->origin(pluginName)}; + break; + case MOBase::IPluginList::STATE_MISSING: + missingAssets[pluginName] = ProvidingModules(); + break; + } } - //Find out any other mods that might contain the esp/esm - QStringList espFilter( { "*.esp", "*.esl", "*.esm" } ); + // Find out any other mods that might contain the esp/esm + QStringList espFilter({"*.esp", "*.esl", "*.esm"}); QString dataDir(organizerCore->managedGame()->dataDirectory().absolutePath()); - //Search normal mods. A note: This will also find mods in data. - for (QString const &mod : organizerCore->modList()->allModsByProfilePriority()) { - MOBase::IModInterface *modInfo = organizerCore->modList()->getMod(mod); - QStringList esps = QDir(modInfo->absolutePath()).entryList(espFilter); - for (QString const &esp : esps) { + // Search normal mods. A note: This will also find mods in data. + for (QString const& mod : organizerCore->modList()->allModsByProfilePriority()) { + MOBase::IModInterface* modInfo = organizerCore->modList()->getMod(mod); + QStringList esps = QDir(modInfo->absolutePath()).entryList(espFilter); + for (QString const& esp : esps) { MissingAssets::iterator iter = missingAssets.find(esp); if (modInfo->absolutePath() == dataDir) { - //We have to prune esps that reside in the data directory, otherwise - //you get all the unmanaged mods listed as potential candidates for - //enabling + // We have to prune esps that reside in the data directory, otherwise + // you get all the unmanaged mods listed as potential candidates for + // enabling if (modInfo->name() != organizerCore->pluginList()->origin(esp)) { continue; } @@ -82,7 +80,7 @@ GamebryoSaveGameInfo::MissingAssets GamebryoSaveGameInfo::getMissingAssets(MOBas { QDir overwriteDir(organizerCore->overwritePath()); QStringList esps = overwriteDir.entryList(espFilter); - for (const QString &esp : esps) { + for (const QString& esp : esps) { MissingAssets::iterator iter = missingAssets.find(esp); if (iter != missingAssets.end()) { if (!iter->contains("")) { @@ -95,7 +93,8 @@ GamebryoSaveGameInfo::MissingAssets GamebryoSaveGameInfo::getMissingAssets(MOBas return missingAssets; } -MOBase::ISaveGameInfoWidget *GamebryoSaveGameInfo::getSaveGameWidget(QWidget *parent) const +MOBase::ISaveGameInfoWidget* +GamebryoSaveGameInfo::getSaveGameWidget(QWidget* parent) const { return new GamebryoSaveGameInfoWidget(this, parent); } diff --git a/src/gamebryo/gamebryosavegameinfo.h b/src/gamebryo/gamebryosavegameinfo.h index 55bc6655..0521cc7a 100644 --- a/src/gamebryo/gamebryosavegameinfo.h +++ b/src/gamebryo/gamebryosavegameinfo.h @@ -8,16 +8,16 @@ class GameGamebryo; class GamebryoSaveGameInfo : public SaveGameInfo { public: - GamebryoSaveGameInfo(GameGamebryo const *game); + GamebryoSaveGameInfo(GameGamebryo const* game); ~GamebryoSaveGameInfo(); virtual MissingAssets getMissingAssets(MOBase::ISaveGame const& save) const override; - virtual MOBase::ISaveGameInfoWidget *getSaveGameWidget(QWidget *) const override; + virtual MOBase::ISaveGameInfoWidget* getSaveGameWidget(QWidget*) const override; protected: friend class GamebryoSaveGameInfoWidget; - GameGamebryo const *m_Game; + GameGamebryo const* m_Game; }; -#endif // GAMEBRYOSAVEGAMEINFO_H +#endif // GAMEBRYOSAVEGAMEINFO_H diff --git a/src/gamebryo/gamebryosavegameinfowidget.cpp b/src/gamebryo/gamebryosavegameinfowidget.cpp index 57409498..46354695 100644 --- a/src/gamebryo/gamebryosavegameinfowidget.cpp +++ b/src/gamebryo/gamebryosavegameinfowidget.cpp @@ -1,16 +1,16 @@ #include "gamebryosavegameinfowidget.h" #include "ui_gamebryosavegameinfowidget.h" -#include "gamegamebryo.h" #include "gamebryosavegame.h" #include "gamebryosavegameinfo.h" +#include "gamegamebryo.h" #include "imoinfo.h" #include "ipluginlist.h" #include #include -#include #include +#include #include #include #include @@ -25,130 +25,136 @@ #include -GamebryoSaveGameInfoWidget::GamebryoSaveGameInfoWidget(GamebryoSaveGameInfo const *info, - QWidget *parent) - : MOBase::ISaveGameInfoWidget(parent), ui(new Ui::GamebryoSaveGameInfoWidget), m_Info(info) { - ui->setupUi(this); - this->setWindowFlags(Qt::ToolTip | Qt::BypassGraphicsProxyWidget); - setWindowOpacity(style()->styleHint(QStyle::SH_ToolTipLabel_Opacity, 0, this) / qreal(255.0)); - ui->gameFrame->setStyleSheet("background-color: transparent;"); +GamebryoSaveGameInfoWidget::GamebryoSaveGameInfoWidget(GamebryoSaveGameInfo const* info, + QWidget* parent) + : MOBase::ISaveGameInfoWidget(parent), ui(new Ui::GamebryoSaveGameInfoWidget), + m_Info(info) +{ + ui->setupUi(this); + this->setWindowFlags(Qt::ToolTip | Qt::BypassGraphicsProxyWidget); + setWindowOpacity(style()->styleHint(QStyle::SH_ToolTipLabel_Opacity, 0, this) / + qreal(255.0)); + ui->gameFrame->setStyleSheet("background-color: transparent;"); - QVBoxLayout *gameLayout = new QVBoxLayout(); - gameLayout->setContentsMargins(0, 0, 0, 0); - gameLayout->setSpacing(2); - ui->gameFrame->setLayout(gameLayout); + QVBoxLayout* gameLayout = new QVBoxLayout(); + gameLayout->setContentsMargins(0, 0, 0, 0); + gameLayout->setSpacing(2); + ui->gameFrame->setLayout(gameLayout); } -GamebryoSaveGameInfoWidget::~GamebryoSaveGameInfoWidget() { - delete ui; +GamebryoSaveGameInfoWidget::~GamebryoSaveGameInfoWidget() +{ + delete ui; } -void GamebryoSaveGameInfoWidget::setSave(MOBase::ISaveGame const& save) { - auto& gamebryoSave = dynamic_cast(save); - ui->saveNumLabel->setText(QString("%1").arg(gamebryoSave.getSaveNumber())); - ui->characterLabel->setText(gamebryoSave.getPCName()); - ui->locationLabel->setText(gamebryoSave.getPCLocation()); - ui->levelLabel->setText(QString("%1").arg(gamebryoSave.getPCLevel())); - //This somewhat contorted code is because on my system at least, the - //old way of doing this appears to give short date and long time. - QDateTime t = gamebryoSave.getCreationTime(); - ui->dateLabel->setText(QLocale::system().toString(t.date(), QLocale::FormatType::ShortFormat) + " " + - QLocale::system().toString(t.time())); - ui->screenshotLabel->setPixmap(QPixmap::fromImage(gamebryoSave.getScreenshot())); - if (ui->gameFrame->layout() != nullptr) { - QLayoutItem *item = nullptr; - while ((item = ui->gameFrame->layout()->takeAt(0)) != nullptr) { - delete item->widget(); - delete item; - } - ui->gameFrame->layout()->setSizeConstraint(QLayout::SetFixedSize); +void GamebryoSaveGameInfoWidget::setSave(MOBase::ISaveGame const& save) +{ + auto& gamebryoSave = dynamic_cast(save); + ui->saveNumLabel->setText(QString("%1").arg(gamebryoSave.getSaveNumber())); + ui->characterLabel->setText(gamebryoSave.getPCName()); + ui->locationLabel->setText(gamebryoSave.getPCLocation()); + ui->levelLabel->setText(QString("%1").arg(gamebryoSave.getPCLevel())); + // This somewhat contorted code is because on my system at least, the + // old way of doing this appears to give short date and long time. + QDateTime t = gamebryoSave.getCreationTime(); + ui->dateLabel->setText( + QLocale::system().toString(t.date(), QLocale::FormatType::ShortFormat) + " " + + QLocale::system().toString(t.time())); + ui->screenshotLabel->setPixmap(QPixmap::fromImage(gamebryoSave.getScreenshot())); + if (ui->gameFrame->layout() != nullptr) { + QLayoutItem* item = nullptr; + while ((item = ui->gameFrame->layout()->takeAt(0)) != nullptr) { + delete item->widget(); + delete item; + } + ui->gameFrame->layout()->setSizeConstraint(QLayout::SetFixedSize); + } + + // Resize box to new content + this->resize(0, 0); + + QLayout* layout = ui->gameFrame->layout(); + if (gamebryoSave.hasScriptExtenderFile()) { + QLabel* scriptExtender = new QLabel(tr("Has Script Extender Data")); + QFont headerFont = scriptExtender->font(); + headerFont.setBold(true); + layout->addWidget(scriptExtender); + } + QLabel* header = new QLabel(tr("Missing ESPs")); + QFont headerFont = header->font(); + QFont contentFont = headerFont; + headerFont.setItalic(true); + contentFont.setBold(true); + contentFont.setPointSize(7); + header->setFont(headerFont); + layout->addWidget(header); + int count = 0; + MOBase::IPluginList* pluginList = m_Info->m_Game->m_Organizer->pluginList(); + for (QString const& pluginName : gamebryoSave.getPlugins()) { + if (pluginList->state(pluginName) == MOBase::IPluginList::STATE_ACTIVE) { + continue; } - // Resize box to new content - this->resize(0, 0); + ++count; - QLayout *layout = ui->gameFrame->layout(); - if (gamebryoSave.hasScriptExtenderFile()) { - QLabel *scriptExtender = new QLabel(tr("Has Script Extender Data")); - QFont headerFont = scriptExtender->font(); - headerFont.setBold(true); - layout->addWidget(scriptExtender); - } - QLabel *header = new QLabel(tr("Missing ESPs")); - QFont headerFont = header->font(); - QFont contentFont = headerFont; - headerFont.setItalic(true); - contentFont.setBold(true); - contentFont.setPointSize(7); - header->setFont(headerFont); - layout->addWidget(header); - int count = 0; - MOBase::IPluginList *pluginList = m_Info->m_Game->m_Organizer->pluginList(); - for (QString const &pluginName : gamebryoSave.getPlugins()) { - if (pluginList->state(pluginName) == MOBase::IPluginList::STATE_ACTIVE) { - continue; - } - - ++count; - - if (count > 7) { - break; - } - - QLabel *pluginLabel = new QLabel(pluginName); - pluginLabel->setIndent(10); - pluginLabel->setFont(contentFont); - layout->addWidget(pluginLabel); - } if (count > 7) { - QLabel *dotDotLabel = new QLabel("..."); - dotDotLabel->setIndent(10); - dotDotLabel->setFont(contentFont); - layout->addWidget(dotDotLabel); + break; } - if (count == 0) { - QLabel *dotDotLabel = new QLabel(tr("None")); - dotDotLabel->setIndent(10); - dotDotLabel->setFont(contentFont); - layout->addWidget(dotDotLabel); + + QLabel* pluginLabel = new QLabel(pluginName); + pluginLabel->setIndent(10); + pluginLabel->setFont(contentFont); + layout->addWidget(pluginLabel); + } + if (count > 7) { + QLabel* dotDotLabel = new QLabel("..."); + dotDotLabel->setIndent(10); + dotDotLabel->setFont(contentFont); + layout->addWidget(dotDotLabel); + } + if (count == 0) { + QLabel* dotDotLabel = new QLabel(tr("None")); + dotDotLabel->setIndent(10); + dotDotLabel->setFont(contentFont); + layout->addWidget(dotDotLabel); + } + if (gamebryoSave.isLightEnabled()) { + QLabel* headerEsl = new QLabel(tr("Missing ESLs")); + QFont headerEslFont = headerEsl->font(); + QFont contentEslFont = headerEslFont; + headerEslFont.setItalic(true); + contentEslFont.setBold(true); + contentEslFont.setPointSize(7); + headerEsl->setFont(headerEslFont); + layout->addWidget(headerEsl); + int countEsl = 0; + for (QString const& pluginName : gamebryoSave.getLightPlugins()) { + if (pluginList->state(pluginName) == MOBase::IPluginList::STATE_ACTIVE) { + continue; + } + + ++countEsl; + + if (countEsl > 7) { + break; + } + + QLabel* pluginLabel = new QLabel(pluginName); + pluginLabel->setIndent(10); + pluginLabel->setFont(contentFont); + layout->addWidget(pluginLabel); } - if (gamebryoSave.isLightEnabled()) { - QLabel *headerEsl = new QLabel(tr("Missing ESLs")); - QFont headerEslFont = headerEsl->font(); - QFont contentEslFont = headerEslFont; - headerEslFont.setItalic(true); - contentEslFont.setBold(true); - contentEslFont.setPointSize(7); - headerEsl->setFont(headerEslFont); - layout->addWidget(headerEsl); - int countEsl = 0; - for (QString const &pluginName : gamebryoSave.getLightPlugins()) { - if (pluginList->state(pluginName) == MOBase::IPluginList::STATE_ACTIVE) { - continue; - } - - ++countEsl; - - if (countEsl > 7) { - break; - } - - QLabel *pluginLabel = new QLabel(pluginName); - pluginLabel->setIndent(10); - pluginLabel->setFont(contentFont); - layout->addWidget(pluginLabel); - } - if (countEsl > 7) { - QLabel *dotDotLabel = new QLabel("..."); - dotDotLabel->setIndent(10); - dotDotLabel->setFont(contentFont); - layout->addWidget(dotDotLabel); - } - if (countEsl == 0) { - QLabel *dotDotLabel = new QLabel(tr("None")); - dotDotLabel->setIndent(10); - dotDotLabel->setFont(contentFont); - layout->addWidget(dotDotLabel); - } + if (countEsl > 7) { + QLabel* dotDotLabel = new QLabel("..."); + dotDotLabel->setIndent(10); + dotDotLabel->setFont(contentFont); + layout->addWidget(dotDotLabel); } + if (countEsl == 0) { + QLabel* dotDotLabel = new QLabel(tr("None")); + dotDotLabel->setIndent(10); + dotDotLabel->setFont(contentFont); + layout->addWidget(dotDotLabel); + } + } } diff --git a/src/gamebryo/gamebryosavegameinfowidget.h b/src/gamebryo/gamebryosavegameinfowidget.h index 665a0aba..66428637 100644 --- a/src/gamebryo/gamebryosavegameinfowidget.h +++ b/src/gamebryo/gamebryosavegameinfowidget.h @@ -7,21 +7,24 @@ class GamebryoSaveGameInfo; -namespace Ui { class GamebryoSaveGameInfoWidget; } +namespace Ui +{ +class GamebryoSaveGameInfoWidget; +} class GamebryoSaveGameInfoWidget : public MOBase::ISaveGameInfoWidget { Q_OBJECT public: - GamebryoSaveGameInfoWidget(GamebryoSaveGameInfo const *info, QWidget *parent); + GamebryoSaveGameInfoWidget(GamebryoSaveGameInfo const* info, QWidget* parent); ~GamebryoSaveGameInfoWidget(); - virtual void setSave(MOBase::ISaveGame const &) override; + virtual void setSave(MOBase::ISaveGame const&) override; private: - Ui::GamebryoSaveGameInfoWidget *ui; - GamebryoSaveGameInfo const *m_Info; + Ui::GamebryoSaveGameInfoWidget* ui; + GamebryoSaveGameInfo const* m_Info; }; -#endif // GAMEBRYOSAVEGAMEINFOWIDGET_H +#endif // GAMEBRYOSAVEGAMEINFOWIDGET_H diff --git a/src/gamebryo/gamebryoscriptextender.cpp b/src/gamebryo/gamebryoscriptextender.cpp index a7d6016d..e3f709a6 100644 --- a/src/gamebryo/gamebryoscriptextender.cpp +++ b/src/gamebryo/gamebryoscriptextender.cpp @@ -7,14 +7,10 @@ #include #include -GamebryoScriptExtender::GamebryoScriptExtender(const GameGamebryo *game) : - m_Game(game) -{ -} +GamebryoScriptExtender::GamebryoScriptExtender(const GameGamebryo* game) : m_Game(game) +{} -GamebryoScriptExtender::~GamebryoScriptExtender() -{ -} +GamebryoScriptExtender::~GamebryoScriptExtender() {} QString GamebryoScriptExtender::loaderName() const { @@ -33,11 +29,10 @@ QString GamebryoScriptExtender::savegameExtension() const bool GamebryoScriptExtender::isInstalled() const { - //A note: It is possibly also OK if xxse_steam_loader.dll exists, but it's - //not clear why that would exist and the exe not if you'd installed it per - //instructions, and it'd mess up NCC installs a treat. + // A note: It is possibly also OK if xxse_steam_loader.dll exists, but it's + // not clear why that would exist and the exe not if you'd installed it per + // instructions, and it'd mess up NCC installs a treat. return m_Game->gameDirectory().exists(loaderName()); - } QString GamebryoScriptExtender::getExtenderVersion() const @@ -47,6 +42,5 @@ QString GamebryoScriptExtender::getExtenderVersion() const WORD GamebryoScriptExtender::getArch() const { - return m_Game->getArch(loaderName()); + return m_Game->getArch(loaderName()); } - diff --git a/src/gamebryo/gamebryoscriptextender.h b/src/gamebryo/gamebryoscriptextender.h index c11328c0..10bad1e6 100644 --- a/src/gamebryo/gamebryoscriptextender.h +++ b/src/gamebryo/gamebryoscriptextender.h @@ -8,7 +8,7 @@ class GameGamebryo; class GamebryoScriptExtender : public ScriptExtender { public: - GamebryoScriptExtender(GameGamebryo const *game); + GamebryoScriptExtender(GameGamebryo const* game); virtual ~GamebryoScriptExtender(); @@ -25,7 +25,7 @@ public: virtual WORD getArch() const override; protected: - GameGamebryo const * const m_Game; + GameGamebryo const* const m_Game; }; -#endif // GAMEBRYOSCRIPTEXTENDER_H +#endif // GAMEBRYOSCRIPTEXTENDER_H diff --git a/src/gamebryo/gamebryounmanagedmods.cpp b/src/gamebryo/gamebryounmanagedmods.cpp index 025bb1e3..e5c76085 100644 --- a/src/gamebryo/gamebryounmanagedmods.cpp +++ b/src/gamebryo/gamebryounmanagedmods.cpp @@ -2,36 +2,35 @@ #include "gamegamebryo.h" #include +GamebryoUnmangedMods::GamebryoUnmangedMods(const GameGamebryo* game) : m_Game(game) {} -GamebryoUnmangedMods::GamebryoUnmangedMods(const GameGamebryo *game) - : m_Game(game) -{} +GamebryoUnmangedMods::~GamebryoUnmangedMods() {} -GamebryoUnmangedMods::~GamebryoUnmangedMods() -{} - -QStringList GamebryoUnmangedMods::mods(bool onlyOfficial) const { +QStringList GamebryoUnmangedMods::mods(bool onlyOfficial) const +{ QStringList result; - QStringList dlcPlugins = m_Game->DLCPlugins(); + QStringList dlcPlugins = m_Game->DLCPlugins(); QStringList mainPlugins = m_Game->primaryPlugins(); QDir dataDir(m_Game->dataDirectory()); - for (const QString &fileName : dataDir.entryList({ "*.esp", "*.esl", "*.esm"})) { + for (const QString& fileName : dataDir.entryList({"*.esp", "*.esl", "*.esm"})) { if (!mainPlugins.contains(fileName, Qt::CaseInsensitive) && (!onlyOfficial || dlcPlugins.contains(fileName, Qt::CaseInsensitive))) { - result.append(fileName.chopped(4)); // trims the extension off + result.append(fileName.chopped(4)); // trims the extension off } } return result; } -QString GamebryoUnmangedMods::displayName(const QString &modName) const { +QString GamebryoUnmangedMods::displayName(const QString& modName) const +{ return modName; } -QFileInfo GamebryoUnmangedMods::referenceFile(const QString &modName) const { +QFileInfo GamebryoUnmangedMods::referenceFile(const QString& modName) const +{ QFileInfoList files = m_Game->dataDirectory().entryInfoList(QStringList() << modName + ".es*"); if (files.size() > 0) { @@ -41,11 +40,11 @@ QFileInfo GamebryoUnmangedMods::referenceFile(const QString &modName) const { } } -QStringList GamebryoUnmangedMods::secondaryFiles(const QString &modName) const { +QStringList GamebryoUnmangedMods::secondaryFiles(const QString& modName) const +{ QStringList archives; QDir dataDir = m_Game->dataDirectory(); - for (const QString &archiveName : - dataDir.entryList({modName + "*.bsa"})) { + for (const QString& archiveName : dataDir.entryList({modName + "*.bsa"})) { archives.append(dataDir.absoluteFilePath(archiveName)); } return archives; diff --git a/src/gamebryo/gamebryounmanagedmods.h b/src/gamebryo/gamebryounmanagedmods.h index 86a7334a..a9585b0d 100644 --- a/src/gamebryo/gamebryounmanagedmods.h +++ b/src/gamebryo/gamebryounmanagedmods.h @@ -1,27 +1,26 @@ #ifndef GAMEBRYOUNMANAGEDMODS_H #define GAMEBRYOUNMANAGEDMODS_H - #include class GameGamebryo; -class GamebryoUnmangedMods : public UnmanagedMods { +class GamebryoUnmangedMods : public UnmanagedMods +{ public: - GamebryoUnmangedMods(const GameGamebryo *game); + GamebryoUnmangedMods(const GameGamebryo* game); ~GamebryoUnmangedMods(); virtual QStringList mods(bool onlyOfficial) const override; - virtual QString displayName(const QString &modName) const override; - virtual QFileInfo referenceFile(const QString &modName) const override; - virtual QStringList secondaryFiles(const QString &modName) const override; -protected: - const GameGamebryo *game() const { return m_Game; } -private: - const GameGamebryo *m_Game; + virtual QString displayName(const QString& modName) const override; + virtual QFileInfo referenceFile(const QString& modName) const override; + virtual QStringList secondaryFiles(const QString& modName) const override; +protected: + const GameGamebryo* game() const { return m_Game; } + +private: + const GameGamebryo* m_Game; }; - - -#endif // GAMEBRYOUNMANAGEDMODS_H +#endif // GAMEBRYOUNMANAGEDMODS_H diff --git a/src/gamebryo/gamegamebryo.cpp b/src/gamebryo/gamegamebryo.cpp index 60c62bd8..65628ceb 100644 --- a/src/gamebryo/gamegamebryo.cpp +++ b/src/gamebryo/gamegamebryo.cpp @@ -3,20 +3,20 @@ #include "bsainvalidation.h" #include "dataarchives.h" #include "gamebryomoddatacontent.h" +#include "gamebryosavegame.h" +#include "gameplugins.h" #include "iprofile.h" #include "registry.h" #include "savegameinfo.h" #include "scopeguard.h" #include "scriptextender.h" #include "utility.h" -#include "gamebryosavegame.h" -#include "gameplugins.h" #include #include -#include #include #include +#include #include #include @@ -27,23 +27,21 @@ #include #include +#include #include #include -#include #include -GameGamebryo::GameGamebryo() -{ -} +GameGamebryo::GameGamebryo() {} void GameGamebryo::detectGame() { - m_GamePath = identifyGamePath(); + m_GamePath = identifyGamePath(); m_MyGamesPath = determineMyGamesPath(gameName()); } -bool GameGamebryo::init(MOBase::IOrganizer *moInfo) +bool GameGamebryo::init(MOBase::IOrganizer* moInfo) { using namespace std::placeholders; m_Organizer = moInfo; @@ -71,7 +69,7 @@ QDir GameGamebryo::dataDirectory() const return gameDirectory().absoluteFilePath("data"); } -void GameGamebryo::setGamePath(const QString &path) +void GameGamebryo::setGamePath(const QString& path) { m_GamePath = path; } @@ -105,7 +103,7 @@ QStringList GameGamebryo::gameVariants() const return QStringList(); } -void GameGamebryo::setGameVariant(const QString &variant) +void GameGamebryo::setGameVariant(const QString& variant) { m_GameVariant = variant; } @@ -140,9 +138,9 @@ MOBase::IPluginGame::SortMechanism GameGamebryo::sortMechanism() const return SortMechanism::LOOT; } -bool GameGamebryo::looksValid(QDir const &path) const +bool GameGamebryo::looksValid(QDir const& path) const { - //Check for .exe for now. + // Check for .exe for now. return path.exists(binaryName()); } @@ -152,7 +150,7 @@ QString GameGamebryo::gameVersion() const // version), we look the product version instead. If the product version is // not empty, we use it. QString binaryAbsPath = gameDirectory().absoluteFilePath(binaryName()); - QString version = MOBase::getFileVersion(binaryAbsPath); + QString version = MOBase::getFileVersion(binaryAbsPath); if (version.startsWith(FALLBACK_GAME_VERSION)) { QString pversion = MOBase::getProductVersion(binaryAbsPath); if (!pversion.isEmpty()) { @@ -167,48 +165,57 @@ QString GameGamebryo::getLauncherName() const return gameShortName() + "Launcher.exe"; } -WORD GameGamebryo::getArch(QString const &program) const +WORD GameGamebryo::getArch(QString const& program) const { - WORD arch = 0; - //This *really* needs to be factored out - std::wstring app_name = - L"\\\\?\\" + QDir::toNativeSeparators(this->gameDirectory().absoluteFilePath(program)).toStdWString(); + WORD arch = 0; + // This *really* needs to be factored out + std::wstring app_name = + L"\\\\?\\" + + QDir::toNativeSeparators(this->gameDirectory().absoluteFilePath(program)) + .toStdWString(); - WIN32_FIND_DATAW FindFileData; - HANDLE hFind = ::FindFirstFileW(app_name.c_str(), &FindFileData); + WIN32_FIND_DATAW FindFileData; + HANDLE hFind = ::FindFirstFileW(app_name.c_str(), &FindFileData); - //exit if the binary was not found - if (hFind == INVALID_HANDLE_VALUE) return arch; + // exit if the binary was not found + if (hFind == INVALID_HANDLE_VALUE) + return arch; - HANDLE hFile = INVALID_HANDLE_VALUE; - HANDLE hMapping = INVALID_HANDLE_VALUE; - LPVOID addrHeader = nullptr; + HANDLE hFile = INVALID_HANDLE_VALUE; + HANDLE hMapping = INVALID_HANDLE_VALUE; + LPVOID addrHeader = nullptr; PIMAGE_NT_HEADERS peHdr = nullptr; - hFile = CreateFileW(app_name.c_str(), GENERIC_READ, FILE_SHARE_READ, NULL, OPEN_EXISTING, FILE_ATTRIBUTE_READONLY, NULL); - if (hFile == INVALID_HANDLE_VALUE) goto cleanup; + hFile = CreateFileW(app_name.c_str(), GENERIC_READ, FILE_SHARE_READ, NULL, + OPEN_EXISTING, FILE_ATTRIBUTE_READONLY, NULL); + if (hFile == INVALID_HANDLE_VALUE) + goto cleanup; - hMapping = CreateFileMappingW(hFile, NULL, PAGE_READONLY | SEC_IMAGE, 0, 0, program.toStdWString().c_str()); - if (hMapping == INVALID_HANDLE_VALUE) goto cleanup; + hMapping = CreateFileMappingW(hFile, NULL, PAGE_READONLY | SEC_IMAGE, 0, 0, + program.toStdWString().c_str()); + if (hMapping == INVALID_HANDLE_VALUE) + goto cleanup; - addrHeader = MapViewOfFile(hMapping, FILE_MAP_READ, 0, 0, 0); - if (addrHeader == NULL) goto cleanup; //couldn't memory map the file + addrHeader = MapViewOfFile(hMapping, FILE_MAP_READ, 0, 0, 0); + if (addrHeader == NULL) + goto cleanup; // couldn't memory map the file - peHdr = ImageNtHeader(addrHeader); - if (peHdr == NULL) goto cleanup; //couldn't read the header + peHdr = ImageNtHeader(addrHeader); + if (peHdr == NULL) + goto cleanup; // couldn't read the header - arch = peHdr->FileHeader.Machine; + arch = peHdr->FileHeader.Machine; -cleanup: //release all of our handles - FindClose(hFind); - if (hFile != INVALID_HANDLE_VALUE) - CloseHandle(hFile); - if (hMapping != INVALID_HANDLE_VALUE) - CloseHandle(hMapping); - return arch; +cleanup: // release all of our handles + FindClose(hFind); + if (hFile != INVALID_HANDLE_VALUE) + CloseHandle(hFile); + if (hMapping != INVALID_HANDLE_VALUE) + CloseHandle(hMapping); + return arch; } -QFileInfo GameGamebryo::findInGameFolder(const QString &relativePath) const +QFileInfo GameGamebryo::findInGameFolder(const QString& relativePath) const { return QFileInfo(m_GamePath + "/" + relativePath); } @@ -216,26 +223,28 @@ QFileInfo GameGamebryo::findInGameFolder(const QString &relativePath) const QString GameGamebryo::identifyGamePath() const { QString path = "Software\\Bethesda Softworks\\" + gameShortName(); - return findInRegistry(HKEY_LOCAL_MACHINE, path.toStdWString().c_str(), L"Installed Path"); + return findInRegistry(HKEY_LOCAL_MACHINE, path.toStdWString().c_str(), + L"Installed Path"); } bool GameGamebryo::prepareIni(const QString& exec) { - MOBase::IProfile *profile = m_Organizer->profile(); + MOBase::IProfile* profile = m_Organizer->profile(); - QString basePath - = profile->localSettingsEnabled() - ? profile->absolutePath() - : documentsDirectory().absolutePath(); + QString basePath = profile->localSettingsEnabled() + ? profile->absolutePath() + : documentsDirectory().absolutePath(); if (!iniFiles().isEmpty()) { QString profileIni = basePath + "/" + iniFiles()[0]; WCHAR setting[512]; - if (!GetPrivateProfileStringW(L"Launcher", L"bEnableFileSelection", L"0", setting, 512, profileIni.toStdWString().c_str()) - || wcstol(setting, nullptr, 10) != 1) { - MOBase::WriteRegistryValue(L"Launcher", L"bEnableFileSelection", L"1", profileIni.toStdWString().c_str()); + if (!GetPrivateProfileStringW(L"Launcher", L"bEnableFileSelection", L"0", setting, + 512, profileIni.toStdWString().c_str()) || + wcstol(setting, nullptr, 10) != 1) { + MOBase::WriteRegistryValue(L"Launcher", L"bEnableFileSelection", L"1", + profileIni.toStdWString().c_str()); } } @@ -254,7 +263,8 @@ QString GameGamebryo::myGamesPath() const /*static*/ QString GameGamebryo::getLootPath() { - return findInRegistry(HKEY_LOCAL_MACHINE, L"Software\\LOOT", L"Installed Path") + "/Loot.exe"; + return findInRegistry(HKEY_LOCAL_MACHINE, L"Software\\LOOT", L"Installed Path") + + "/Loot.exe"; } std::map GameGamebryo::featureList() const @@ -272,17 +282,18 @@ QString GameGamebryo::localAppFolder() return result; } -void GameGamebryo::copyToProfile(QString const &sourcePath, - QDir const &destinationDirectory, - QString const &sourceFileName) { - copyToProfile(sourcePath, destinationDirectory, sourceFileName, - sourceFileName); +void GameGamebryo::copyToProfile(QString const& sourcePath, + QDir const& destinationDirectory, + QString const& sourceFileName) +{ + copyToProfile(sourcePath, destinationDirectory, sourceFileName, sourceFileName); } -void GameGamebryo::copyToProfile(QString const &sourcePath, - QDir const &destinationDirectory, - QString const &sourceFileName, - QString const &destinationFileName) { +void GameGamebryo::copyToProfile(QString const& sourcePath, + QDir const& destinationDirectory, + QString const& sourceFileName, + QString const& destinationFileName) +{ QString filePath = destinationDirectory.absoluteFilePath(destinationFileName); if (!QFileInfo(filePath).exists()) { if (!MOBase::shellCopy(sourcePath + "/" + sourceFileName, filePath)) { @@ -296,22 +307,21 @@ MappingType GameGamebryo::mappings() const { MappingType result; - for (const QString &profileFile : { "plugins.txt", "loadorder.txt" }) { - result.push_back({ m_Organizer->profilePath() + "/" + profileFile, - localAppFolder() + "/" + gameShortName() + "/" + profileFile, - false }); + for (const QString& profileFile : {"plugins.txt", "loadorder.txt"}) { + result.push_back({m_Organizer->profilePath() + "/" + profileFile, + localAppFolder() + "/" + gameShortName() + "/" + profileFile, + false}); } return result; } std::unique_ptr GameGamebryo::getRegValue(HKEY key, LPCWSTR path, LPCWSTR value, - DWORD flags, LPDWORD type = nullptr) + DWORD flags, LPDWORD type = nullptr) { DWORD size = 0; HKEY subKey; - LONG res = ::RegOpenKeyExW(key, path, 0, - KEY_QUERY_VALUE | KEY_WOW64_32KEY, &subKey); + LONG res = ::RegOpenKeyExW(key, path, 0, KEY_QUERY_VALUE | KEY_WOW64_32KEY, &subKey); if (res != ERROR_SUCCESS) { return std::unique_ptr(); } @@ -320,14 +330,16 @@ std::unique_ptr GameGamebryo::getRegValue(HKEY key, LPCWSTR path, LPCWST return std::unique_ptr(); } if (res != ERROR_SUCCESS && res != ERROR_MORE_DATA) { - throw MOBase::MyException(QObject::tr("failed to query registry path (preflight): %1").arg(res, 0, 16)); + throw MOBase::MyException( + QObject::tr("failed to query registry path (preflight): %1").arg(res, 0, 16)); } std::unique_ptr result(new BYTE[size]); res = ::RegGetValueW(subKey, L"", value, flags, type, result.get(), &size); if (res != ERROR_SUCCESS) { - throw MOBase::MyException(QObject::tr("failed to query registry path (read): %1").arg(res, 0, 16)); + throw MOBase::MyException( + QObject::tr("failed to query registry path (read): %1").arg(res, 0, 16)); } return result; @@ -335,7 +347,8 @@ std::unique_ptr GameGamebryo::getRegValue(HKEY key, LPCWSTR path, LPCWST QString GameGamebryo::findInRegistry(HKEY baseKey, LPCWSTR path, LPCWSTR value) { - std::unique_ptr buffer = getRegValue(baseKey, path, value, RRF_RT_REG_SZ | RRF_NOEXPAND); + std::unique_ptr buffer = + getRegValue(baseKey, path, value, RRF_RT_REG_SZ | RRF_NOEXPAND); return QString::fromUtf16(reinterpret_cast(buffer.get())); } @@ -344,33 +357,34 @@ QString GameGamebryo::getKnownFolderPath(REFKNOWNFOLDERID folderId, bool useDefa { PWSTR path = nullptr; ON_BLOCK_EXIT([&]() { - if (path != nullptr) ::CoTaskMemFree(path); + if (path != nullptr) + ::CoTaskMemFree(path); }); - if (::SHGetKnownFolderPath(folderId, useDefault ? KF_FLAG_DEFAULT_PATH : 0, NULL, &path) == S_OK) { + if (::SHGetKnownFolderPath(folderId, useDefault ? KF_FLAG_DEFAULT_PATH : 0, NULL, + &path) == S_OK) { return QDir::fromNativeSeparators(QString::fromWCharArray(path)); - } - else { + } else { return QString(); } } -QString GameGamebryo::getSpecialPath(const QString &name) +QString GameGamebryo::getSpecialPath(const QString& name) { - QString base = findInRegistry(HKEY_CURRENT_USER, - L"Software\\Microsoft\\Windows\\CurrentVersion\\Explorer\\User Shell Folders", - name.toStdWString().c_str()); + QString base = findInRegistry( + HKEY_CURRENT_USER, + L"Software\\Microsoft\\Windows\\CurrentVersion\\Explorer\\User Shell Folders", + name.toStdWString().c_str()); WCHAR temp[MAX_PATH]; if (::ExpandEnvironmentStringsW(base.toStdWString().c_str(), temp, MAX_PATH) != 0) { return QString::fromWCharArray(temp); - } - else { + } else { return base; } } -QString GameGamebryo::determineMyGamesPath(const QString &gameName) +QString GameGamebryo::determineMyGamesPath(const QString& gameName) { const QString pattern = "%1/My Games/" + gameName; @@ -387,19 +401,18 @@ QString GameGamebryo::determineMyGamesPath(const QString &gameName) return path; }; - // a) this is the way it should work. get the configured My Documents directory - if (auto d=tryDir(getKnownFolderPath(FOLDERID_Documents, false))) { + if (auto d = tryDir(getKnownFolderPath(FOLDERID_Documents, false))) { return *d; } // b) if there is no directory there, look in the default directory - if (auto d=tryDir(getKnownFolderPath(FOLDERID_Documents, true))) { + if (auto d = tryDir(getKnownFolderPath(FOLDERID_Documents, true))) { return *d; } // c) finally, look in the registry. This is discouraged - if (auto d=tryDir(getSpecialPath("Personal"))) { + if (auto d = tryDir(getSpecialPath("Personal"))) { return *d; } diff --git a/src/gamebryo/gamegamebryo.h b/src/gamebryo/gamegamebryo.h index e126c29f..7a7aa5ce 100644 --- a/src/gamebryo/gamegamebryo.h +++ b/src/gamebryo/gamegamebryo.h @@ -15,16 +15,15 @@ class UnmanagedMods; #include #include -#include -#include -#include #include #include +#include +#include +#include #include "gamebryosavegame.h" -class GameGamebryo : public MOBase::IPluginGame, - public MOBase::IPluginFileMapper +class GameGamebryo : public MOBase::IPluginGame, public MOBase::IPluginFileMapper { Q_OBJECT Q_INTERFACES(MOBase::IPlugin MOBase::IPluginGame MOBase::IPluginFileMapper) @@ -42,101 +41,96 @@ class GameGamebryo : public MOBase::IPluginGame, static constexpr const char* FALLBACK_GAME_VERSION = "1.0.0"; public: - GameGamebryo(); void detectGame() override; - bool init(MOBase::IOrganizer *moInfo) override; + bool init(MOBase::IOrganizer* moInfo) override; -public: // IPluginGame interface - - //getName - //initializeProfile - virtual std::vector> listSaves(QDir folder) const override; +public: // IPluginGame interface + // getName + // initializeProfile + virtual std::vector> + listSaves(QDir folder) const override; virtual bool isInstalled() const override; virtual QIcon gameIcon() const override; virtual QDir gameDirectory() const override; virtual QDir dataDirectory() const override; - virtual void setGamePath(const QString &path) override; + virtual void setGamePath(const QString& path) override; virtual QDir documentsDirectory() const override; virtual QDir savesDirectory() const override; - //executables - //steamAPPId - //primaryPlugins + // executables + // steamAPPId + // primaryPlugins virtual QStringList gameVariants() const override; - virtual void setGameVariant(const QString &variant) override; + virtual void setGameVariant(const QString& variant) override; virtual QString binaryName() const override; - //gameShortName + // gameShortName virtual QStringList primarySources() const override; virtual QStringList validShortNames() const override; - //iniFiles - //DLCPlugins + // iniFiles + // DLCPlugins virtual QStringList CCPlugins() const override; virtual LoadOrderMechanism loadOrderMechanism() const override; virtual SortMechanism sortMechanism() const override; - //nexusModOrganizerID - //nexusGameID - virtual bool looksValid(QDir const &) const override; + // nexusModOrganizerID + // nexusGameID + virtual bool looksValid(QDir const&) const override; virtual QString gameVersion() const override; virtual QString getLauncherName() const override; -public: // IPluginFileMapper interface - +public: // IPluginFileMapper interface virtual MappingType mappings() const; protected: - // Retrieve the saves extension for the game. - virtual QString savegameExtension() const = 0; + virtual QString savegameExtension() const = 0; virtual QString savegameSEExtension() const = 0; // Create a save game. - virtual std::shared_ptr makeSaveGame(QString filepath) const = 0; + virtual std::shared_ptr + makeSaveGame(QString filepath) const = 0; - - QFileInfo findInGameFolder(const QString &relativePath) const; + QFileInfo findInGameFolder(const QString& relativePath) const; QString myGamesPath() const; QString selectedVariant() const; - WORD getArch(QString const &program) const; + WORD getArch(QString const& program) const; static QString localAppFolder(); - //Arguably this shouldn't really be here but every gamebryo program seems to - //use it + // Arguably this shouldn't really be here but every gamebryo program seems to + // use it static QString getLootPath(); - //This function is not terribly well named as it copies exactly where it's told - //to, irrespective of whether it's in the profile... - static void copyToProfile(const QString &sourcePath, - const QDir &destinationDirectory, - const QString &sourceFileName); + // This function is not terribly well named as it copies exactly where it's told + // to, irrespective of whether it's in the profile... + static void copyToProfile(const QString& sourcePath, const QDir& destinationDirectory, + const QString& sourceFileName); - static void copyToProfile(const QString &sourcePath, - const QDir &destinationDirectory, - const QString &sourceFileName, - const QString &destinationFileName); + static void copyToProfile(const QString& sourcePath, const QDir& destinationDirectory, + const QString& sourceFileName, + const QString& destinationFileName); virtual QString identifyGamePath() const; virtual bool prepareIni(const QString& exec); - static std::unique_ptr getRegValue(HKEY key, LPCWSTR path, LPCWSTR value, DWORD flags, LPDWORD type); + static std::unique_ptr getRegValue(HKEY key, LPCWSTR path, LPCWSTR value, + DWORD flags, LPDWORD type); static QString findInRegistry(HKEY baseKey, LPCWSTR path, LPCWSTR value); static QString getKnownFolderPath(REFKNOWNFOLDERID folderId, bool useDefault); - static QString getSpecialPath(const QString &name); + static QString getSpecialPath(const QString& name); - static QString determineMyGamesPath(const QString &gameName); + static QString determineMyGamesPath(const QString& gameName); protected: - std::map featureList() const override; - //These should be implemented by anything that uses gamebryo (I think) + // These should be implemented by anything that uses gamebryo (I think) //(and if they don't, it'll be a null pointer and won't look implemented, - //so that's fine too). + // so that's fine too). /* std::shared_ptr m_ScriptExtender { nullptr }; std::shared_ptr m_DataArchives { nullptr }; @@ -147,7 +141,8 @@ protected: std::shared_ptr m_UnmanagedMods { nullptr };*/ template - void registerFeature(T *type) { + void registerFeature(T* type) + { auto index = std::type_index(typeid(T)); if (m_FeatureList.find(index) != m_FeatureList.end()) { delete std::any_cast(m_FeatureList[index]); @@ -156,14 +151,12 @@ protected: } protected: - QString m_GamePath; QString m_MyGamesPath; QString m_GameVariant; - MOBase::IOrganizer *m_Organizer; + MOBase::IOrganizer* m_Organizer; std::map m_FeatureList; - }; -#endif // GAMEGAMEBRYO_H +#endif // GAMEGAMEBRYO_H From 79b2d168d443c3cb31c3b33f3e014a18f32fdf2a Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Mika=C3=ABl=20Capelle?= Date: Thu, 13 Jul 2023 20:28:12 +0200 Subject: [PATCH 1289/1544] Add .git-blame-ignore-revs. --- .git-blame-ignore-revs | 1 + 1 file changed, 1 insertion(+) create mode 100644 .git-blame-ignore-revs diff --git a/.git-blame-ignore-revs b/.git-blame-ignore-revs new file mode 100644 index 00000000..7db87556 --- /dev/null +++ b/.git-blame-ignore-revs @@ -0,0 +1 @@ +f4c5c5535551ed085bd65cb02058dcab2c9eb110 From 4d5bf18cb10ad23e8d65ea863f5a8a30b9600412 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Mika=C3=ABl=20Capelle?= Date: Thu, 13 Jul 2023 20:30:55 +0200 Subject: [PATCH 1290/1544] [game_skyrimse] Apply clang-format. --- src/games/skyrimse/.clang-format | 41 +++ src/games/skyrimse/.gitattributes | 7 + src/games/skyrimse/src/SConscript | 13 - src/games/skyrimse/src/game_skyrimse_en.ts | 165 +-------- src/games/skyrimse/src/gameskyrimse.cpp | 325 +++++++++--------- src/games/skyrimse/src/gameskyrimse.h | 27 +- src/games/skyrimse/src/gameskyrimse.json | 1 - src/games/skyrimse/src/gameskyrimse.pro | 50 --- .../skyrimse/src/skyrimsedataarchives.cpp | 41 +-- src/games/skyrimse/src/skyrimsedataarchives.h | 21 +- .../skyrimse/src/skyrimsemoddatachecker.h | 25 +- .../skyrimse/src/skyrimsemoddatacontent.h | 11 +- src/games/skyrimse/src/skyrimsesavegame.cpp | 61 ++-- src/games/skyrimse/src/skyrimsesavegame.h | 22 +- .../skyrimse/src/skyrimsescriptextender.cpp | 7 +- .../skyrimse/src/skyrimsescriptextender.h | 5 +- .../skyrimse/src/skyrimseunmanagedmods.cpp | 17 +- .../skyrimse/src/skyrimseunmanagedmods.h | 11 +- 18 files changed, 329 insertions(+), 521 deletions(-) create mode 100644 src/games/skyrimse/.clang-format create mode 100644 src/games/skyrimse/.gitattributes delete mode 100644 src/games/skyrimse/src/SConscript delete mode 100644 src/games/skyrimse/src/gameskyrimse.json delete mode 100644 src/games/skyrimse/src/gameskyrimse.pro diff --git a/src/games/skyrimse/.clang-format b/src/games/skyrimse/.clang-format new file mode 100644 index 00000000..6098e1f5 --- /dev/null +++ b/src/games/skyrimse/.clang-format @@ -0,0 +1,41 @@ +--- +# We'll use defaults from the LLVM style, but with 4 columns indentation. +BasedOnStyle: LLVM +IndentWidth: 2 +--- +Language: Cpp +DeriveLineEnding: false +UseCRLF: true +DerivePointerAlignment: false +PointerAlignment: Left +AlignConsecutiveAssignments: true +AllowShortFunctionsOnASingleLine: Inline +AllowShortIfStatementsOnASingleLine: Never +AllowShortLambdasOnASingleLine: Empty +AlwaysBreakTemplateDeclarations: Yes +AccessModifierOffset: -2 +AlignTrailingComments: true +SpacesBeforeTrailingComments: 2 +NamespaceIndentation: Inner +MaxEmptyLinesToKeep: 1 +BreakBeforeBraces: Custom +BraceWrapping: + AfterCaseLabel: false + AfterClass: true + AfterControlStatement: false + AfterEnum: true + AfterFunction: true + AfterNamespace: true + AfterStruct: true + AfterUnion: true + AfterExternBlock: true + BeforeCatch: false + BeforeElse: false + BeforeLambdaBody: false + BeforeWhile: false + IndentBraces: false + SplitEmptyFunction: false + SplitEmptyRecord: false + SplitEmptyNamespace: true +ColumnLimit: 88 +ForEachMacros: ['Q_FOREACH', 'foreach'] diff --git a/src/games/skyrimse/.gitattributes b/src/games/skyrimse/.gitattributes new file mode 100644 index 00000000..f8697127 --- /dev/null +++ b/src/games/skyrimse/.gitattributes @@ -0,0 +1,7 @@ +# Set the default behavior, in case people don't have core.autocrlf set. +* text=auto + +# Explicitly declare text files you want to always be normalized and converted +# to native line endings on checkout. +*.cpp text eol=crlf +*.h text eol=crlf diff --git a/src/games/skyrimse/src/SConscript b/src/games/skyrimse/src/SConscript deleted file mode 100644 index 287c3242..00000000 --- a/src/games/skyrimse/src/SConscript +++ /dev/null @@ -1,13 +0,0 @@ -Import('qt_env') - -env = qt_env.Clone() - -env.AppendUnique(CPPDEFINES = [ 'GAMESKYRIMSE_LIBRARY' ]) - -env.RequiresGamebryo() - -lib = env.SharedLibrary('gameSkyrimSE', env.Glob('*.cpp')) -env.InstallModule(lib) - -res = env['QT_USED_MODULES'] -Return('res') diff --git a/src/games/skyrimse/src/game_skyrimse_en.ts b/src/games/skyrimse/src/game_skyrimse_en.ts index 361f11c2..9a725db7 100644 --- a/src/games/skyrimse/src/game_skyrimse_en.ts +++ b/src/games/skyrimse/src/game_skyrimse_en.ts @@ -4,175 +4,14 @@ GameSkyrimSE - + Skyrim Special Edition Support Plugin - + Adds support for the game Skyrim Special Edition. - - GamebryoModDataContent - - - Plugins (ESP/ESM/ESL) - - - - - Optional Plugins - - - - - Interface - - - - - Meshes - - - - - Bethesda Archive - - - - - Scripts (Papyrus) - - - - - Script Extender Plugin - - - - - Script Extender Files - - - - - SkyProc Patcher - - - - - Sound or Music - - - - - Textures - - - - - MCM Configuration - - - - - INI Files - - - - - FaceGen Data - - - - - ModGroup Files - - - - - GamebryoSaveGameInfoWidget - - - Save # - - - - - Character - - - - - Level - - - - - Location - - - - - Date - - - - - Has Script Extender Data - - - - - Missing ESPs - - - - - - None - - - - - Missing ESLs - - - - - QObject - - - - Some of your plugins have invalid names! These plugins can not be loaded by the game. Please see mo_interface.log for a list of affected plugins and rename them. - - - - - %1, #%2, Level %3, %4 - - - - - failed to open %1 - - - - - wrong file format - expected %1 got %2 - - - - - failed to query registry path (preflight): %1 - - - - - failed to query registry path (read): %1 - - - diff --git a/src/games/skyrimse/src/gameskyrimse.cpp b/src/games/skyrimse/src/gameskyrimse.cpp index 24f28552..194c7446 100644 --- a/src/games/skyrimse/src/gameskyrimse.cpp +++ b/src/games/skyrimse/src/gameskyrimse.cpp @@ -1,32 +1,32 @@ #include "gameskyrimse.h" #include "skyrimsedataarchives.h" -#include "skyrimsescriptextender.h" -#include "skyrimseunmanagedmods.h" #include "skyrimsemoddatachecker.h" #include "skyrimsemoddatacontent.h" #include "skyrimsesavegame.h" +#include "skyrimsescriptextender.h" +#include "skyrimseunmanagedmods.h" -#include -#include -#include -#include -#include #include "versioninfo.h" +#include +#include +#include +#include +#include #include #include #include +#include #include +#include #include #include #include #include -#include -#include -#include #include "scopeguard.h" +#include using namespace MOBase; @@ -34,167 +34,177 @@ GameSkyrimSE::GameSkyrimSE() {} void GameSkyrimSE::setVariant(QString variant) { - m_GameVariant = variant; + m_GameVariant = variant; } void GameSkyrimSE::checkVariants() { - QFileInfo gog_dll(m_GamePath + "\\Galaxy64.dll"); - QFileInfo epic_dll(m_GamePath + "\\EOSSDK-Win64-Shipping.dll"); - if (gog_dll.exists()) - setVariant("GOG"); - else if (epic_dll.exists()) - setVariant("Epic Games"); - else - setVariant("Steam"); + QFileInfo gog_dll(m_GamePath + "\\Galaxy64.dll"); + QFileInfo epic_dll(m_GamePath + "\\EOSSDK-Win64-Shipping.dll"); + if (gog_dll.exists()) + setVariant("GOG"); + else if (epic_dll.exists()) + setVariant("Epic Games"); + else + setVariant("Steam"); } QDir GameSkyrimSE::documentsDirectory() const { - return m_MyGamesPath; + return m_MyGamesPath; } void GameSkyrimSE::detectGame() { - m_GamePath = identifyGamePath(); - checkVariants(); - m_MyGamesPath = determineMyGamesPath(gameDirectoryName()); + m_GamePath = identifyGamePath(); + checkVariants(); + m_MyGamesPath = determineMyGamesPath(gameDirectoryName()); } QString GameSkyrimSE::identifyGamePath() const { - QMap paths = { - {"Software\\Bethesda Softworks\\" + gameName(), "Installed Path"}, - {"Software\\GOG.com\\Games\\1162721350", "path"}, - {"Software\\GOG.com\\Games\\1711230643", "path"}, - }; + QMap paths = { + {"Software\\Bethesda Softworks\\" + gameName(), "Installed Path"}, + {"Software\\GOG.com\\Games\\1162721350", "path"}, + {"Software\\GOG.com\\Games\\1711230643", "path"}, + }; - QString result; - for (auto &path : paths.toStdMap()) { - result = findInRegistry(HKEY_LOCAL_MACHINE, path.first.toStdWString().c_str(), path.second.toStdWString().c_str()); - if (!result.isEmpty()) - break; - } + QString result; + for (auto& path : paths.toStdMap()) { + result = findInRegistry(HKEY_LOCAL_MACHINE, path.first.toStdWString().c_str(), + path.second.toStdWString().c_str()); + if (!result.isEmpty()) + break; + } - // Check Epic Games Manifests - // AppName: ac82db5035584c7f8a2c548d98c86b2c - // AE Update: 5d600e4f59974aeba0259c7734134e27 - if (result.isEmpty()) - { - // Use the registry entry to find the EGL Data dir first, just in case something changes - QString manifestDir = findInRegistry(HKEY_LOCAL_MACHINE, L"SOFTWARE\\WOW6432Node\\Epic Games\\EpicGamesLauncher", L"AppDataPath"); - if (manifestDir.isEmpty()) - manifestDir = getKnownFolderPath(FOLDERID_ProgramData, false) + "\\Epic\\EpicGamesLauncher\\Data\\"; - manifestDir += "Manifests"; - QDir epicManifests(manifestDir, "*.item", QDir::SortFlags(QDir::Name | QDir::IgnoreCase), QDir::Files); - if (epicManifests.exists()) { - QDirIterator it(epicManifests); - while (it.hasNext()) { - QString manifestFile = it.next(); - QFile manifest(manifestFile); + // Check Epic Games Manifests + // AppName: ac82db5035584c7f8a2c548d98c86b2c + // AE Update: 5d600e4f59974aeba0259c7734134e27 + if (result.isEmpty()) { + // Use the registry entry to find the EGL Data dir first, just in case something + // changes + QString manifestDir = findInRegistry( + HKEY_LOCAL_MACHINE, L"SOFTWARE\\WOW6432Node\\Epic Games\\EpicGamesLauncher", + L"AppDataPath"); + if (manifestDir.isEmpty()) + manifestDir = getKnownFolderPath(FOLDERID_ProgramData, false) + + "\\Epic\\EpicGamesLauncher\\Data\\"; + manifestDir += "Manifests"; + QDir epicManifests(manifestDir, "*.item", + QDir::SortFlags(QDir::Name | QDir::IgnoreCase), QDir::Files); + if (epicManifests.exists()) { + QDirIterator it(epicManifests); + while (it.hasNext()) { + QString manifestFile = it.next(); + QFile manifest(manifestFile); - if (!manifest.open(QIODevice::ReadOnly)) { - qWarning("Couldn't open Epic Games manifest file."); - continue; - } - - QByteArray manifestData = manifest.readAll(); - - QJsonDocument manifestJson(QJsonDocument::fromJson(manifestData)); - - if (manifestJson["AppName"] == "ac82db5035584c7f8a2c548d98c86b2c" || - manifestJson["AppName"] == "5d600e4f59974aeba0259c7734134e27") { - result = manifestJson["InstallLocation"].toString(); - break; - } - } + if (!manifest.open(QIODevice::ReadOnly)) { + qWarning("Couldn't open Epic Games manifest file."); + continue; } - } - return result; + QByteArray manifestData = manifest.readAll(); + + QJsonDocument manifestJson(QJsonDocument::fromJson(manifestData)); + + if (manifestJson["AppName"] == "ac82db5035584c7f8a2c548d98c86b2c" || + manifestJson["AppName"] == "5d600e4f59974aeba0259c7734134e27") { + result = manifestJson["InstallLocation"].toString(); + break; + } + } + } + } + + return result; } void GameSkyrimSE::setGamePath(const QString& path) { - m_GamePath = path; - checkVariants(); - m_MyGamesPath = determineMyGamesPath(gameDirectoryName()); - registerFeature(new SkyrimSEDataArchives(myGamesPath())); - registerFeature(new GamebryoLocalSavegames(myGamesPath(), "Skyrimcustom.ini")); + m_GamePath = path; + checkVariants(); + m_MyGamesPath = determineMyGamesPath(gameDirectoryName()); + registerFeature(new SkyrimSEDataArchives(myGamesPath())); + registerFeature( + new GamebryoLocalSavegames(myGamesPath(), "Skyrimcustom.ini")); } QDir GameSkyrimSE::savesDirectory() const { - return QDir(m_MyGamesPath + "/Saves"); + return QDir(m_MyGamesPath + "/Saves"); } QString GameSkyrimSE::myGamesPath() const { - return m_MyGamesPath; + return m_MyGamesPath; } bool GameSkyrimSE::isInstalled() const { - return !m_GamePath.isEmpty(); + return !m_GamePath.isEmpty(); } -bool GameSkyrimSE::init(IOrganizer *moInfo) +bool GameSkyrimSE::init(IOrganizer* moInfo) { - if (!GameGamebryo::init(moInfo)) { - return false; - } + if (!GameGamebryo::init(moInfo)) { + return false; + } - registerFeature(new SkyrimSEScriptExtender(this)); - registerFeature(new SkyrimSEDataArchives(myGamesPath())); - registerFeature(new GamebryoLocalSavegames(myGamesPath(), "Skyrimcustom.ini")); - registerFeature(new SkyrimSEModDataChecker(this)); - registerFeature(new SkyrimSEModDataContent(this)); - registerFeature(new GamebryoSaveGameInfo(this)); - registerFeature(new CreationGamePlugins(moInfo)); - registerFeature(new SkyrimSEUnmangedMods(this)); + registerFeature(new SkyrimSEScriptExtender(this)); + registerFeature(new SkyrimSEDataArchives(myGamesPath())); + registerFeature( + new GamebryoLocalSavegames(myGamesPath(), "Skyrimcustom.ini")); + registerFeature(new SkyrimSEModDataChecker(this)); + registerFeature(new SkyrimSEModDataContent(this)); + registerFeature(new GamebryoSaveGameInfo(this)); + registerFeature(new CreationGamePlugins(moInfo)); + registerFeature(new SkyrimSEUnmangedMods(this)); - return true; + return true; } QString GameSkyrimSE::gameName() const { - return "Skyrim Special Edition"; + return "Skyrim Special Edition"; } QString GameSkyrimSE::gameDirectoryName() const { - if (selectedVariant() == "GOG") - return "Skyrim Special Edition GOG"; - else if (selectedVariant() == "Epic Games") - return "Skyrim Special Edition EPIC"; - else - return "Skyrim Special Edition"; + if (selectedVariant() == "GOG") + return "Skyrim Special Edition GOG"; + else if (selectedVariant() == "Epic Games") + return "Skyrim Special Edition EPIC"; + else + return "Skyrim Special Edition"; } QList GameSkyrimSE::executables() const { - return QList() - << ExecutableInfo("SKSE", findInGameFolder(feature()->loaderName())) - << ExecutableInfo("Skyrim Special Edition", findInGameFolder(binaryName())) - << ExecutableInfo("Skyrim Special Edition Launcher", findInGameFolder(getLauncherName())) - << ExecutableInfo("Creation Kit", findInGameFolder("CreationKit.exe")).withSteamAppId("1946180") - << ExecutableInfo("LOOT", QFileInfo(getLootPath())).withArgument("--game=\"Skyrim Special Edition\"") - ; + return QList() + << ExecutableInfo("SKSE", + findInGameFolder(feature()->loaderName())) + << ExecutableInfo("Skyrim Special Edition", findInGameFolder(binaryName())) + << ExecutableInfo("Skyrim Special Edition Launcher", + findInGameFolder(getLauncherName())) + << ExecutableInfo("Creation Kit", findInGameFolder("CreationKit.exe")) + .withSteamAppId("1946180") + << ExecutableInfo("LOOT", QFileInfo(getLootPath())) + .withArgument("--game=\"Skyrim Special Edition\""); } QList GameSkyrimSE::executableForcedLoads() const { - return QList(); + return QList(); } -QFileInfo GameSkyrimSE::findInGameFolder(const QString &relativePath) const +QFileInfo GameSkyrimSE::findInGameFolder(const QString& relativePath) const { - return QFileInfo(m_GamePath + "/" + relativePath); + return QFileInfo(m_GamePath + "/" + relativePath); } QString GameSkyrimSE::name() const { - return "Skyrim Special Edition Support Plugin"; + return "Skyrim Special Edition Support Plugin"; } QString GameSkyrimSE::localizedName() const @@ -204,115 +214,110 @@ QString GameSkyrimSE::localizedName() const QString GameSkyrimSE::author() const { - return "MO2 Team, Orig: Archost & ZachHaber"; + return "MO2 Team, Orig: Archost & ZachHaber"; } QString GameSkyrimSE::description() const { - return tr("Adds support for the game Skyrim Special Edition."); + return tr("Adds support for the game Skyrim Special Edition."); } MOBase::VersionInfo GameSkyrimSE::version() const { - return VersionInfo(1, 7, 0, VersionInfo::RELEASE_FINAL); + return VersionInfo(1, 7, 0, VersionInfo::RELEASE_FINAL); } QList GameSkyrimSE::settings() const { - return { - PluginSetting("enderal_downloads", "allow Enderal and Enderal SE downloads", QVariant(false)) - }; + return {PluginSetting("enderal_downloads", "allow Enderal and Enderal SE downloads", + QVariant(false))}; } -void GameSkyrimSE::initializeProfile(const QDir &path, ProfileSettings settings) const +void GameSkyrimSE::initializeProfile(const QDir& path, ProfileSettings settings) const { - if (settings.testFlag(IPluginGame::MODS)) { - copyToProfile(localAppFolder() + "/" + gameDirectoryName(), path, "plugins.txt"); + if (settings.testFlag(IPluginGame::MODS)) { + copyToProfile(localAppFolder() + "/" + gameDirectoryName(), path, "plugins.txt"); + } + + if (settings.testFlag(IPluginGame::CONFIGURATION)) { + if (settings.testFlag(IPluginGame::PREFER_DEFAULTS) || + !QFileInfo(myGamesPath() + "/skyrim.ini").exists()) { + copyToProfile(gameDirectory().absolutePath(), path, "skyrim_default.ini", + "skyrim.ini"); + } else { + copyToProfile(myGamesPath(), path, "skyrim.ini"); } - if (settings.testFlag(IPluginGame::CONFIGURATION)) { - if (settings.testFlag(IPluginGame::PREFER_DEFAULTS) - || !QFileInfo(myGamesPath() + "/skyrim.ini").exists()) { - copyToProfile(gameDirectory().absolutePath(), path, "skyrim_default.ini", "skyrim.ini"); - } - else { - copyToProfile(myGamesPath(), path, "skyrim.ini"); - } - - copyToProfile(myGamesPath(), path, "skyrimprefs.ini"); - copyToProfile(myGamesPath(), path, "skyrimcustom.ini"); - } + copyToProfile(myGamesPath(), path, "skyrimprefs.ini"); + copyToProfile(myGamesPath(), path, "skyrimcustom.ini"); + } } QString GameSkyrimSE::savegameExtension() const { - return "ess"; + return "ess"; } QString GameSkyrimSE::savegameSEExtension() const { - return "skse"; + return "skse"; } -std::shared_ptr GameSkyrimSE::makeSaveGame(QString filePath) const +std::shared_ptr +GameSkyrimSE::makeSaveGame(QString filePath) const { return std::make_shared(filePath, this); } QString GameSkyrimSE::steamAPPId() const { - if (selectedVariant() == "Steam") - return "489830"; - return QString(); + if (selectedVariant() == "Steam") + return "489830"; + return QString(); } QStringList GameSkyrimSE::primaryPlugins() const { - QStringList plugins = { - "skyrim.esm", - "update.esm", - "dawnguard.esm", - "hearthfires.esm", - "dragonborn.esm" - }; + QStringList plugins = {"skyrim.esm", "update.esm", "dawnguard.esm", "hearthfires.esm", + "dragonborn.esm"}; - plugins.append(CCPlugins()); + plugins.append(CCPlugins()); - return plugins; + return plugins; } QStringList GameSkyrimSE::gameVariants() const { - return{ "Steam", "GOG", "Epic Games" }; + return {"Steam", "GOG", "Epic Games"}; } QString GameSkyrimSE::gameShortName() const { - return "SkyrimSE"; + return "SkyrimSE"; } QStringList GameSkyrimSE::validShortNames() const { - QStringList shortNames{ "Skyrim" }; + QStringList shortNames{"Skyrim"}; if (m_Organizer->pluginSetting(name(), "enderal_downloads").toBool()) { - shortNames.append({ "Enderal", "EnderalSE" }); + shortNames.append({"Enderal", "EnderalSE"}); } return shortNames; } QString GameSkyrimSE::gameNexusName() const { - return "skyrimspecialedition"; + return "skyrimspecialedition"; } QStringList GameSkyrimSE::iniFiles() const { - return{ "skyrim.ini", "skyrimprefs.ini", "skyrimcustom.ini" }; + return {"skyrim.ini", "skyrimprefs.ini", "skyrimcustom.ini"}; } QStringList GameSkyrimSE::DLCPlugins() const { - return{ "dawnguard.esm", "hearthfires.esm", "dragonborn.esm" }; + return {"dawnguard.esm", "hearthfires.esm", "dragonborn.esm"}; } QStringList GameSkyrimSE::CCPlugins() const @@ -335,34 +340,34 @@ QStringList GameSkyrimSE::CCPlugins() const IPluginGame::LoadOrderMechanism GameSkyrimSE::loadOrderMechanism() const { - return IPluginGame::LoadOrderMechanism::PluginsTxt; + return IPluginGame::LoadOrderMechanism::PluginsTxt; } int GameSkyrimSE::nexusModOrganizerID() const { - return 6194; //... Should be 0? + return 6194; //... Should be 0? } int GameSkyrimSE::nexusGameID() const { - return 1704; //1704 + return 1704; // 1704 } QDir GameSkyrimSE::gameDirectory() const { - return QDir(m_GamePath); + return QDir(m_GamePath); } // Not to delete all the spaces... MappingType GameSkyrimSE::mappings() const { - MappingType result; + MappingType result; - for (const QString &profileFile : { "plugins.txt", "loadorder.txt" }) { - result.push_back({ m_Organizer->profilePath() + "/" + profileFile, - localAppFolder() + "/" + gameDirectoryName() + "/" + profileFile, - false }); - } + for (const QString& profileFile : {"plugins.txt", "loadorder.txt"}) { + result.push_back({m_Organizer->profilePath() + "/" + profileFile, + localAppFolder() + "/" + gameDirectoryName() + "/" + profileFile, + false}); + } - return result; + return result; } diff --git a/src/games/skyrimse/src/gameskyrimse.h b/src/games/skyrimse/src/gameskyrimse.h index 2a757f85..52964646 100644 --- a/src/games/skyrimse/src/gameskyrimse.h +++ b/src/games/skyrimse/src/gameskyrimse.h @@ -1,7 +1,6 @@ #ifndef _GAMESKYRIMSE_H #define _GAMESKYRIMSE_H - #include "gamegamebryo.h" #include @@ -11,22 +10,22 @@ class GameSkyrimSE : public GameGamebryo { Q_OBJECT - Q_PLUGIN_METADATA(IID "com.soundcontactstudio.GameSkyrimSE" FILE "gameskyrimse.json") + Q_PLUGIN_METADATA(IID "com.soundcontactstudio.GameSkyrimSE") public: - GameSkyrimSE(); - virtual bool init(MOBase::IOrganizer *moInfo) override; - -public: // IPluginGame interface + virtual bool init(MOBase::IOrganizer* moInfo) override; +public: // IPluginGame interface virtual void detectGame() override; virtual QString gameName() const override; virtual QList executables() const override; - virtual QList executableForcedLoads() const override; - virtual void initializeProfile(const QDir &path, ProfileSettings settings) const override; + virtual QList + 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; @@ -41,11 +40,10 @@ public: // IPluginGame interface virtual int nexusGameID() const override; virtual bool isInstalled() const override; - virtual void setGamePath(const QString &path) override; + virtual void setGamePath(const QString& path) override; virtual QDir gameDirectory() const override; -public: // IPlugin interface - +public: // IPlugin interface virtual QString name() const override; virtual QString localizedName() const override; virtual QString author() const override; @@ -54,9 +52,7 @@ public: // IPlugin interface virtual QList settings() const override; virtual MappingType mappings() const override; - protected: - std::shared_ptr makeSaveGame(QString filePath) const override; QString savegameExtension() const override; QString savegameSEExtension() const override; @@ -64,14 +60,13 @@ protected: QString gameDirectoryName() const; QDir documentsDirectory() const; QDir savesDirectory() const; - QFileInfo findInGameFolder(const QString &relativePath) const; + QFileInfo findInGameFolder(const QString& relativePath) const; QString myGamesPath() const; void checkVariants(); void setVariant(QString variant); virtual QString identifyGamePath() const override; - }; -#endif // _GAMESKYRIMSE_H +#endif // _GAMESKYRIMSE_H diff --git a/src/games/skyrimse/src/gameskyrimse.json b/src/games/skyrimse/src/gameskyrimse.json deleted file mode 100644 index 0967ef42..00000000 --- a/src/games/skyrimse/src/gameskyrimse.json +++ /dev/null @@ -1 +0,0 @@ -{} diff --git a/src/games/skyrimse/src/gameskyrimse.pro b/src/games/skyrimse/src/gameskyrimse.pro deleted file mode 100644 index 8636c0fd..00000000 --- a/src/games/skyrimse/src/gameskyrimse.pro +++ /dev/null @@ -1,50 +0,0 @@ -#------------------------------------------------- -# -# Project created by QtCreator 2016-10-28T12:24:19 -# -#------------------------------------------------- - - -TARGET = gameSkyrimSE -TEMPLATE = lib - -CONFIG += plugins -CONFIG += dll - -DEFINES += GAMESKYRIMSE_LIBRARY - -SOURCES += gameskyrimse.cpp \ - skyrimsebsainvalidation.cpp \ - skyrimsescriptextender.cpp \ - skyrimsedataarchives.cpp \ - skyrimsesavegame.cpp \ - skyrimsesavegameinfo.cpp - -HEADERS += gameskyrimse.h \ - skyrimsebsainvalidation.h \ - skyrimsescriptextender.h \ - skyrimsedataarchives.h \ - skyrimsesavegame.h \ - skyrimsesavegameinfo.h - -CONFIG(debug, debug|release) { - LIBS += -L"$${OUT_PWD}/../gameGamebryo/debug" - PRE_TARGETDEPS += \ - $$OUT_PWD/../gameGamebryo/debug/gameGamebryo.lib -} else { - LIBS += -L"$${OUT_PWD}/../gameGamebryo/release" - PRE_TARGETDEPS += \ - $$OUT_PWD/../gameGamebryo/release/gameGamebryo.lib -} - -include(../plugin_template.pri) - -INCLUDEPATH += "$${BOOSTPATH}" "$${PWD}/../gamefeatures" "$${PWD}/../gamegamebryo" - -LIBS += -ladvapi32 -lole32 -lgameGamebryo - -OTHER_FILES += \ - gameskyrimse.json\ - SConscript \ - CMakeLists.txt - diff --git a/src/games/skyrimse/src/skyrimsedataarchives.cpp b/src/games/skyrimse/src/skyrimsedataarchives.cpp index 91921ea4..b4d338fc 100644 --- a/src/games/skyrimse/src/skyrimsedataarchives.cpp +++ b/src/games/skyrimse/src/skyrimsedataarchives.cpp @@ -3,48 +3,41 @@ #include "iprofile.h" #include -SkyrimSEDataArchives::SkyrimSEDataArchives(const QDir &myGamesDir) : - GamebryoDataArchives(myGamesDir) +SkyrimSEDataArchives::SkyrimSEDataArchives(const QDir& myGamesDir) + : GamebryoDataArchives(myGamesDir) {} QStringList SkyrimSEDataArchives::vanillaArchives() const { - return{ "Skyrim - Textures0.bsa" - , "Skyrim - Textures1.bsa" - , "Skyrim - Textures2.bsa" - , "Skyrim - Textures3.bsa" - , "Skyrim - Textures4.bsa" - , "Skyrim - Textures5.bsa" - , "Skyrim - Textures6.bsa" - , "Skyrim - Textures7.bsa" - , "Skyrim - Textures8.bsa" - , "Skyrim - Meshes0.bsa" - , "Skyrim - Meshes1.bsa" - , "Skyrim - Voices_en0.bsa" - , "Skyrim - Sounds.bsa" - , "Skyrim - Interface.bsa" - , "Skyrim - Animations.bsa" - , "Skyrim - Shaders.bsa" - , "Skyrim - Misc.bsa" }; + return {"Skyrim - Textures0.bsa", "Skyrim - Textures1.bsa", "Skyrim - Textures2.bsa", + "Skyrim - Textures3.bsa", "Skyrim - Textures4.bsa", "Skyrim - Textures5.bsa", + "Skyrim - Textures6.bsa", "Skyrim - Textures7.bsa", "Skyrim - Textures8.bsa", + "Skyrim - Meshes0.bsa", "Skyrim - Meshes1.bsa", "Skyrim - Voices_en0.bsa", + "Skyrim - Sounds.bsa", "Skyrim - Interface.bsa", "Skyrim - Animations.bsa", + "Skyrim - Shaders.bsa", "Skyrim - Misc.bsa"}; } - -QStringList SkyrimSEDataArchives::archives(const MOBase::IProfile *profile) const +QStringList SkyrimSEDataArchives::archives(const MOBase::IProfile* profile) const { QStringList result; - QString iniFile = profile->localSettingsEnabled() ? QDir(profile->absolutePath()).absoluteFilePath("skyrim.ini") : m_LocalGameDir.absoluteFilePath("skyrim.ini"); + QString iniFile = profile->localSettingsEnabled() + ? QDir(profile->absolutePath()).absoluteFilePath("skyrim.ini") + : m_LocalGameDir.absoluteFilePath("skyrim.ini"); result.append(getArchivesFromKey(iniFile, "SResourceArchiveList")); result.append(getArchivesFromKey(iniFile, "SResourceArchiveList2")); return result; } -void SkyrimSEDataArchives::writeArchiveList(MOBase::IProfile *profile, const QStringList &before) +void SkyrimSEDataArchives::writeArchiveList(MOBase::IProfile* profile, + const QStringList& before) { QString list = before.join(", "); - QString iniFile = profile->localSettingsEnabled() ? QDir(profile->absolutePath()).absoluteFilePath("skyrim.ini") : m_LocalGameDir.absoluteFilePath("skyrim.ini"); + QString iniFile = profile->localSettingsEnabled() + ? QDir(profile->absolutePath()).absoluteFilePath("skyrim.ini") + : m_LocalGameDir.absoluteFilePath("skyrim.ini"); if (list.length() > 255) { int splitIdx = list.lastIndexOf(",", 256); setArchivesToKey(iniFile, "SResourceArchiveList", list.mid(0, splitIdx)); diff --git a/src/games/skyrimse/src/skyrimsedataarchives.h b/src/games/skyrimse/src/skyrimsedataarchives.h index 5f4fbef7..edd58381 100644 --- a/src/games/skyrimse/src/skyrimsedataarchives.h +++ b/src/games/skyrimse/src/skyrimsedataarchives.h @@ -2,28 +2,27 @@ #define _SKYRIMSEDATAARCHIVES_H #include "gamebryodataarchives.h" -#include #include +#include -namespace MOBase { class IProfile; } - +namespace MOBase +{ +class IProfile; +} class SkyrimSEDataArchives : public GamebryoDataArchives { public: - - SkyrimSEDataArchives(const QDir &myGamesDir); + SkyrimSEDataArchives(const QDir& myGamesDir); public: - virtual QStringList vanillaArchives() const override; - virtual QStringList archives(const MOBase::IProfile *profile) const override; + virtual QStringList archives(const MOBase::IProfile* profile) const override; private: - - virtual void writeArchiveList(MOBase::IProfile *profile, const QStringList &before) override; - + virtual void writeArchiveList(MOBase::IProfile* profile, + const QStringList& before) override; }; -#endif // _SKYRIMSEDATAARCHIVES_H +#endif // _SKYRIMSEDATAARCHIVES_H diff --git a/src/games/skyrimse/src/skyrimsemoddatachecker.h b/src/games/skyrimse/src/skyrimsemoddatachecker.h index dd81459f..d93a7894 100644 --- a/src/games/skyrimse/src/skyrimsemoddatachecker.h +++ b/src/games/skyrimse/src/skyrimsemoddatachecker.h @@ -9,22 +9,23 @@ public: using GamebryoModDataChecker::GamebryoModDataChecker; protected: - virtual const FileNameSet& possibleFolderNames() const override { + virtual const FileNameSet& possibleFolderNames() const override + { static FileNameSet result{ - "fonts", "interface", "menus", "meshes", "music", "scripts", "shaders", - "sound", "strings", "textures", "trees", "video", "facegen", "materials", - "skse", "distantlod", "asi", "Tools", "MCM", "distantland", "mits", - "dllplugins", "CalienteTools", "NetScriptFramework", "shadersfx", - "Nemesis_Engine", "Platform", "grass" - }; + "fonts", "interface", "menus", "meshes", + "music", "scripts", "shaders", "sound", + "strings", "textures", "trees", "video", + "facegen", "materials", "skse", "distantlod", + "asi", "Tools", "MCM", "distantland", + "mits", "dllplugins", "CalienteTools", "NetScriptFramework", + "shadersfx", "Nemesis_Engine", "Platform", "grass"}; return result; } - virtual const FileNameSet& possibleFileExtensions() const override { - static FileNameSet result{ - "esp", "esm", "esl", "bsa", "modgroups", "ini" - }; + virtual const FileNameSet& possibleFileExtensions() const override + { + static FileNameSet result{"esp", "esm", "esl", "bsa", "modgroups", "ini"}; return result; } }; -#endif // SKYRIMSE_MODATACHECKER_H +#endif // SKYRIMSE_MODATACHECKER_H diff --git a/src/games/skyrimse/src/skyrimsemoddatacontent.h b/src/games/skyrimse/src/skyrimsemoddatacontent.h index deb34653..b7571720 100644 --- a/src/games/skyrimse/src/skyrimsemoddatacontent.h +++ b/src/games/skyrimse/src/skyrimsemoddatacontent.h @@ -4,17 +4,18 @@ #include #include -class SkyrimSEModDataContent : public GamebryoModDataContent { +class SkyrimSEModDataContent : public GamebryoModDataContent +{ public: - /** * */ - SkyrimSEModDataContent(GameGamebryo const* gamePlugin) : GamebryoModDataContent(gamePlugin) { + SkyrimSEModDataContent(GameGamebryo const* gamePlugin) + : GamebryoModDataContent(gamePlugin) + { // Just need to disable some contents: m_Enabled[CONTENT_SKYPROC] = false; } - }; -#endif // SKYRIMSE_MODDATACONTENT_H +#endif // SKYRIMSE_MODDATACONTENT_H diff --git a/src/games/skyrimse/src/skyrimsesavegame.cpp b/src/games/skyrimse/src/skyrimsesavegame.cpp index ca727afe..94753005 100644 --- a/src/games/skyrimse/src/skyrimsesavegame.cpp +++ b/src/games/skyrimse/src/skyrimsesavegame.cpp @@ -2,27 +2,28 @@ #include -SkyrimSESaveGame::SkyrimSESaveGame(QString const &fileName, GameSkyrimSE const *game) : - GamebryoSaveGame(fileName, game, true) +SkyrimSESaveGame::SkyrimSESaveGame(QString const& fileName, GameSkyrimSE const* game) + : GamebryoSaveGame(fileName, game, true) { - FileWrapper file(fileName, "TESV_SAVEGAME"); //10bytes + FileWrapper file(fileName, "TESV_SAVEGAME"); // 10bytes unsigned long version; FILETIME ftime; - fetchInformationFields(file, version, m_PCName, m_PCLevel, m_PCLocation, m_SaveNumber, ftime); + fetchInformationFields(file, version, m_PCName, m_PCLevel, m_PCLocation, m_SaveNumber, + ftime); - //A file time is a 64-bit value that represents the number of 100-nanosecond - //intervals that have elapsed since 12:00 A.M. January 1, 1601 Coordinated Universal Time (UTC). - //So we need to convert that to something useful + // A file time is a 64-bit value that represents the number of 100-nanosecond + // intervals that have elapsed since 12:00 A.M. January 1, 1601 Coordinated Universal + // Time (UTC). So we need to convert that to something useful - //For some reason, the file time is off by about 6 hours. - //So we need to subtract those 6 hours from the filetime. + // For some reason, the file time is off by about 6 hours. + // So we need to subtract those 6 hours from the filetime. _ULARGE_INTEGER time; - time.LowPart = ftime.dwLowDateTime; + time.LowPart = ftime.dwLowDateTime; time.HighPart = ftime.dwHighDateTime; time.QuadPart -= 2.16e11; ftime.dwHighDateTime = time.HighPart; - ftime.dwLowDateTime = time.LowPart; + ftime.dwLowDateTime = time.LowPart; SYSTEMTIME ctime; ::FileTimeToSystemTime(&ftime, &ctime); @@ -30,17 +31,15 @@ SkyrimSESaveGame::SkyrimSESaveGame(QString const &fileName, GameSkyrimSE const * setCreationTime(ctime); } -void SkyrimSESaveGame::fetchInformationFields( - FileWrapper& file, - unsigned long& version, - QString& playerName, - unsigned short& playerLevel, - QString& playerLocation, - unsigned long& saveNumber, - FILETIME& creationTime) const +void SkyrimSESaveGame::fetchInformationFields(FileWrapper& file, unsigned long& version, + QString& playerName, + unsigned short& playerLevel, + QString& playerLocation, + unsigned long& saveNumber, + FILETIME& creationTime) const { unsigned long headerSize; - file.read(headerSize); // header size "TESV_SAVEGAME" + file.read(headerSize); // header size "TESV_SAVEGAME" file.read(version); file.read(saveNumber); file.read(playerName); @@ -54,17 +53,17 @@ void SkyrimSESaveGame::fetchInformationFields( file.read(timeOfDay); QString race; - file.read(race); // race name (i.e. BretonRace) + file.read(race); // race name (i.e. BretonRace) - file.skip(); // Player gender (0 = male) - file.skip(2); // experience gathered, experience required + file.skip(); // Player gender (0 = male) + file.skip(2); // experience gathered, experience required - file.read(creationTime); //filetime + file.read(creationTime); // filetime } std::unique_ptr SkyrimSESaveGame::fetchDataFields() const { - FileWrapper file(getFilepath(), "TESV_SAVEGAME"); //10bytes + FileWrapper file(getFilepath(), "TESV_SAVEGAME"); // 10bytes unsigned long version = 0; { @@ -73,8 +72,8 @@ std::unique_ptr SkyrimSESaveGame::fetchDataFields( unsigned long dummySaveNumber; FILETIME dummyTime; - fetchInformationFields(file, version, dummyName, dummyLevel, - dummyLocation, dummySaveNumber, dummyTime); + fetchInformationFields(file, version, dummyName, dummyLevel, dummyLocation, + dummySaveNumber, dummyTime); } std::unique_ptr fields = std::make_unique(); @@ -101,10 +100,10 @@ std::unique_ptr SkyrimSESaveGame::fetchDataFields( file.openCompressedData(); uint8_t saveGameVersion = file.readChar(); - uint8_t pluginInfoSize = file.readChar(); - uint16_t other = file.readShort(); //Unknown + uint8_t pluginInfoSize = file.readChar(); + uint16_t other = file.readShort(); // Unknown - fields->Plugins = file.readPlugins(1); // Just empty data + fields->Plugins = file.readPlugins(1); // Just empty data if (saveGameVersion >= 78) { fields->LightPlugins = file.readLightPlugins(); @@ -113,4 +112,4 @@ std::unique_ptr SkyrimSESaveGame::fetchDataFields( file.closeCompressedData(); return fields; -} \ No newline at end of file +} diff --git a/src/games/skyrimse/src/skyrimsesavegame.h b/src/games/skyrimse/src/skyrimsesavegame.h index ec2f1549..9fbe9b5d 100644 --- a/src/games/skyrimse/src/skyrimsesavegame.h +++ b/src/games/skyrimse/src/skyrimsesavegame.h @@ -4,26 +4,24 @@ #include "gamebryosavegame.h" #include "gameskyrimse.h" -namespace MOBase { class IPluginGame; } +namespace MOBase +{ +class IPluginGame; +} class SkyrimSESaveGame : public GamebryoSaveGame { public: - SkyrimSESaveGame(QString const &fileName, GameSkyrimSE const *game); + SkyrimSESaveGame(QString const& fileName, GameSkyrimSE const* game); protected: - // Fetch easy-to-access information. - void fetchInformationFields(FileWrapper& wrapper, - unsigned long& version, - QString& playerName, - unsigned short& playerLevel, - QString& playerLocation, - unsigned long& saveNumber, - FILETIME& creationTime) const; + void fetchInformationFields(FileWrapper& wrapper, unsigned long& version, + QString& playerName, unsigned short& playerLevel, + QString& playerLocation, unsigned long& saveNumber, + FILETIME& creationTime) const; std::unique_ptr fetchDataFields() const override; - }; -#endif // _SKYRIMSESAVEGAME_H +#endif // _SKYRIMSESAVEGAME_H diff --git a/src/games/skyrimse/src/skyrimsescriptextender.cpp b/src/games/skyrimse/src/skyrimsescriptextender.cpp index 1fc5a30a..482751fa 100644 --- a/src/games/skyrimse/src/skyrimsescriptextender.cpp +++ b/src/games/skyrimse/src/skyrimsescriptextender.cpp @@ -3,10 +3,9 @@ #include #include -SkyrimSEScriptExtender::SkyrimSEScriptExtender(GameGamebryo const *game) : - GamebryoScriptExtender(game) -{ -} +SkyrimSEScriptExtender::SkyrimSEScriptExtender(GameGamebryo const* game) + : GamebryoScriptExtender(game) +{} QString SkyrimSEScriptExtender::BinaryName() const { diff --git a/src/games/skyrimse/src/skyrimsescriptextender.h b/src/games/skyrimse/src/skyrimsescriptextender.h index b8f7ee9c..9b5f78c4 100644 --- a/src/games/skyrimse/src/skyrimsescriptextender.h +++ b/src/games/skyrimse/src/skyrimsescriptextender.h @@ -8,11 +8,10 @@ class GameGamebryo; class SkyrimSEScriptExtender : public GamebryoScriptExtender { public: - SkyrimSEScriptExtender(GameGamebryo const *game); + SkyrimSEScriptExtender(GameGamebryo const* game); virtual QString BinaryName() const override; virtual QString PluginPath() const override; - }; -#endif // _SKYRIMSESCRIPTEXTENDER_H +#endif // _SKYRIMSESCRIPTEXTENDER_H diff --git a/src/games/skyrimse/src/skyrimseunmanagedmods.cpp b/src/games/skyrimse/src/skyrimseunmanagedmods.cpp index c8d92c4c..d1e406cf 100644 --- a/src/games/skyrimse/src/skyrimseunmanagedmods.cpp +++ b/src/games/skyrimse/src/skyrimseunmanagedmods.cpp @@ -1,27 +1,26 @@ #include "skyrimSEunmanagedmods.h" - -SkyrimSEUnmangedMods::SkyrimSEUnmangedMods(const GameGamebryo *game) - : GamebryoUnmangedMods(game) +SkyrimSEUnmangedMods::SkyrimSEUnmangedMods(const GameGamebryo* game) + : GamebryoUnmangedMods(game) {} -SkyrimSEUnmangedMods::~SkyrimSEUnmangedMods() -{} +SkyrimSEUnmangedMods::~SkyrimSEUnmangedMods() {} -QStringList SkyrimSEUnmangedMods::mods(bool onlyOfficial) const { +QStringList SkyrimSEUnmangedMods::mods(bool onlyOfficial) const +{ QStringList result; - QStringList pluginList = game()->primaryPlugins(); + QStringList pluginList = game()->primaryPlugins(); QStringList otherPlugins = game()->DLCPlugins(); otherPlugins.append(game()->CCPlugins()); for (QString plugin : otherPlugins) { pluginList.removeAll(plugin); } QDir dataDir(game()->dataDirectory()); - for (const QString &fileName : dataDir.entryList({ "*.esp", "*.esl", "*.esm" })) { + for (const QString& fileName : dataDir.entryList({"*.esp", "*.esl", "*.esm"})) { if (!pluginList.contains(fileName, Qt::CaseInsensitive)) { if (!onlyOfficial || pluginList.contains(fileName, Qt::CaseInsensitive)) { - result.append(fileName.chopped(4)); // trims the extension off + result.append(fileName.chopped(4)); // trims the extension off } } } diff --git a/src/games/skyrimse/src/skyrimseunmanagedmods.h b/src/games/skyrimse/src/skyrimseunmanagedmods.h index c9be0379..27938caa 100644 --- a/src/games/skyrimse/src/skyrimseunmanagedmods.h +++ b/src/games/skyrimse/src/skyrimseunmanagedmods.h @@ -1,19 +1,16 @@ #ifndef _SKYRIMSEUNMANAGEDMODS_H #define _SKYRIMSEUNMANAGEDMODS_H - #include "gamebryounmanagedmods.h" #include - -class SkyrimSEUnmangedMods : public GamebryoUnmangedMods { +class SkyrimSEUnmangedMods : public GamebryoUnmangedMods +{ public: - SkyrimSEUnmangedMods(const GameGamebryo *game); + SkyrimSEUnmangedMods(const GameGamebryo* game); ~SkyrimSEUnmangedMods(); virtual QStringList mods(bool onlyOfficial) const override; }; - - -#endif // _SKYRIMSEUNMANAGEDMODS_H +#endif // _SKYRIMSEUNMANAGEDMODS_H From 98aef6344ee0540f2a2cb9c2e7d348cd21fda30c Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Mika=C3=ABl=20Capelle?= Date: Thu, 13 Jul 2023 20:31:09 +0200 Subject: [PATCH 1291/1544] [game_skyrimse] Add .git-blame-ignore-revs. --- src/games/skyrimse/.git-blame-ignore-revs | 1 + 1 file changed, 1 insertion(+) create mode 100644 src/games/skyrimse/.git-blame-ignore-revs diff --git a/src/games/skyrimse/.git-blame-ignore-revs b/src/games/skyrimse/.git-blame-ignore-revs new file mode 100644 index 00000000..f1d853c5 --- /dev/null +++ b/src/games/skyrimse/.git-blame-ignore-revs @@ -0,0 +1 @@ +fec29b9e7620110c08502e2d9f89c268e9d723a0 From f763ae16d69962e6f0116da8c2f662df1efdf675 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Mika=C3=ABl=20Capelle?= Date: Thu, 13 Jul 2023 20:24:12 +0200 Subject: [PATCH 1292/1544] Add Github workflows. --- .github/workflows/build.yml | 17 +++++++++++++++++ .github/workflows/linting.yml | 17 +++++++++++++++++ 2 files changed, 34 insertions(+) create mode 100644 .github/workflows/build.yml create mode 100644 .github/workflows/linting.yml diff --git a/.github/workflows/build.yml b/.github/workflows/build.yml new file mode 100644 index 00000000..8bb44a2d --- /dev/null +++ b/.github/workflows/build.yml @@ -0,0 +1,17 @@ +name: Build GameBryo Library + +on: + push: + branches: master + pull_request: + types: [opened, synchronize, reopened] + +jobs: + build: + runs-on: windows-2022 + steps: + - name: Build GameBryo Library + uses: ModOrganizer2/build-with-mob-action@master + with: + mo2-third-parties: fmt gtest spdlog boost lz4 + mo2-dependencies: cmake_common uibase diff --git a/.github/workflows/linting.yml b/.github/workflows/linting.yml new file mode 100644 index 00000000..78ee0417 --- /dev/null +++ b/.github/workflows/linting.yml @@ -0,0 +1,17 @@ +name: Lint GameBryo Library + +on: + push: + pull_request: + types: [opened, synchronize, reopened] + +jobs: + lint: + runs-on: ubuntu-latest + steps: + - uses: actions/checkout@v3 + - name: Run clang-format + uses: jidicula/clang-format-action@v4.11.0 + with: + clang-format-version: "15" + check-path: "." From b29553b44dff11cfd3bb848fbd44e66d5e2dc668 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Mika=C3=ABl=20Capelle?= Date: Thu, 13 Jul 2023 20:32:01 +0200 Subject: [PATCH 1293/1544] [game_skyrimse] Add Github workflows. --- src/games/skyrimse/.github/workflows/build.yml | 17 +++++++++++++++++ .../skyrimse/.github/workflows/linting.yml | 17 +++++++++++++++++ 2 files changed, 34 insertions(+) create mode 100644 src/games/skyrimse/.github/workflows/build.yml create mode 100644 src/games/skyrimse/.github/workflows/linting.yml diff --git a/src/games/skyrimse/.github/workflows/build.yml b/src/games/skyrimse/.github/workflows/build.yml new file mode 100644 index 00000000..0e51ab70 --- /dev/null +++ b/src/games/skyrimse/.github/workflows/build.yml @@ -0,0 +1,17 @@ +name: Build Skyrim SE Plugin + +on: + push: + branches: master + pull_request: + types: [opened, synchronize, reopened] + +jobs: + build: + runs-on: windows-2022 + steps: + - name: Build Skyrim SE Plugin + uses: ModOrganizer2/build-with-mob-action@master + with: + mo2-third-parties: fmt gtest spdlog boost lz4 + mo2-dependencies: cmake_common uibase game_gamebryo diff --git a/src/games/skyrimse/.github/workflows/linting.yml b/src/games/skyrimse/.github/workflows/linting.yml new file mode 100644 index 00000000..d1c601ca --- /dev/null +++ b/src/games/skyrimse/.github/workflows/linting.yml @@ -0,0 +1,17 @@ +name: Lint Skyrim SE Plugin + +on: + push: + pull_request: + types: [opened, synchronize, reopened] + +jobs: + lint: + runs-on: ubuntu-latest + steps: + - uses: actions/checkout@v3 + - name: Run clang-format + uses: jidicula/clang-format-action@v4.11.0 + with: + clang-format-version: "15" + check-path: "." From 0a45a28d98583f88a90bfdcbbc40c20a2027e051 Mon Sep 17 00:00:00 2001 From: Jeremy Rimpo Date: Sat, 2 Sep 2023 01:37:01 -0500 Subject: [PATCH 1294/1544] [game_starfield] Initial commit --- src/games/starfield/.gitignore | 5 + src/games/starfield/CMakeLists.txt | 10 + src/games/starfield/appveyor.yml | 40 ++++ src/games/starfield/src/CMakeLists.txt | 7 + src/games/starfield/src/SConscript | 14 ++ src/games/starfield/src/gameStarfield.pro | 50 +++++ src/games/starfield/src/game_starfield_en.ts | 18 ++ src/games/starfield/src/gamestarfield.cpp | 197 ++++++++++++++++++ src/games/starfield/src/gamestarfield.h | 58 ++++++ src/games/starfield/src/gamestarfield.json | 1 + .../starfield/src/starfielddataarchives.cpp | 96 +++++++++ .../starfield/src/starfielddataarchives.h | 29 +++ .../starfield/src/starfieldmoddatachecker.h | 28 +++ .../starfield/src/starfieldmoddatacontent.h | 41 ++++ src/games/starfield/src/starfieldsavegame.cpp | 82 ++++++++ src/games/starfield/src/starfieldsavegame.h | 30 +++ .../starfield/src/starfieldscriptextender.cpp | 19 ++ .../starfield/src/starfieldscriptextender.h | 18 ++ .../starfield/src/starfieldunmanagedmods.cpp | 63 ++++++ .../starfield/src/starfieldunmanagedmods.h | 21 ++ 20 files changed, 827 insertions(+) create mode 100644 src/games/starfield/.gitignore create mode 100644 src/games/starfield/CMakeLists.txt create mode 100644 src/games/starfield/appveyor.yml create mode 100644 src/games/starfield/src/CMakeLists.txt create mode 100644 src/games/starfield/src/SConscript create mode 100644 src/games/starfield/src/gameStarfield.pro create mode 100644 src/games/starfield/src/game_starfield_en.ts create mode 100644 src/games/starfield/src/gamestarfield.cpp create mode 100644 src/games/starfield/src/gamestarfield.h create mode 100644 src/games/starfield/src/gamestarfield.json create mode 100644 src/games/starfield/src/starfielddataarchives.cpp create mode 100644 src/games/starfield/src/starfielddataarchives.h create mode 100644 src/games/starfield/src/starfieldmoddatachecker.h create mode 100644 src/games/starfield/src/starfieldmoddatacontent.h create mode 100644 src/games/starfield/src/starfieldsavegame.cpp create mode 100644 src/games/starfield/src/starfieldsavegame.h create mode 100644 src/games/starfield/src/starfieldscriptextender.cpp create mode 100644 src/games/starfield/src/starfieldscriptextender.h create mode 100644 src/games/starfield/src/starfieldunmanagedmods.cpp create mode 100644 src/games/starfield/src/starfieldunmanagedmods.h diff --git a/src/games/starfield/.gitignore b/src/games/starfield/.gitignore new file mode 100644 index 00000000..cf71be77 --- /dev/null +++ b/src/games/starfield/.gitignore @@ -0,0 +1,5 @@ +edit +CMakeLists.txt.user +/msbuild.log +/*std*.log +/*build diff --git a/src/games/starfield/CMakeLists.txt b/src/games/starfield/CMakeLists.txt new file mode 100644 index 00000000..1e0429a5 --- /dev/null +++ b/src/games/starfield/CMakeLists.txt @@ -0,0 +1,10 @@ +cmake_minimum_required(VERSION 3.16) + +if(DEFINED DEPENDENCIES_DIR) + include(${DEPENDENCIES_DIR}/modorganizer_super/cmake_common/mo2.cmake) +else() + include(${CMAKE_CURRENT_LIST_DIR}/cmake_common/mo2.cmake) +endif() + +project(game_fallout4) +add_subdirectory(src) diff --git a/src/games/starfield/appveyor.yml b/src/games/starfield/appveyor.yml new file mode 100644 index 00000000..1e625dd0 --- /dev/null +++ b/src/games/starfield/appveyor.yml @@ -0,0 +1,40 @@ +version: 1.0.{build} +skip_branch_with_pr: true +image: Visual Studio 2019 +environment: + WEBHOOK_URL: + secure: gOKbXaZM9ImtMD5XrYITvdyZUW/az082G9OIN1EC1Vbg57wBaeLhi49uGjxPw5GVujHku6kxN6ab89zhbS5GVeluR76GM83IbKV4Sh7udXzoYZZdg6YudtYHzdhCgUeiedpswbuczTq9ceIkkfSEWZuh/lMAAVVwvcGsJAnoPFw= +build_script: +- pwsh: >- + $ErrorActionPreference = 'Stop' + + git clone --depth=1 --no-single-branch https://github.com/ModOrganizer2/modorganizer-umbrella.git c:\projects\modorganizer-umbrella + + New-Item -ItemType Directory -Path c:\projects\modorganizer-build + + cd c:\projects\modorganizer-umbrella + + ($env:APPVEYOR_PULL_REQUEST_HEAD_REPO_BRANCH -eq $null) ? ($branch = $env:APPVEYOR_REPO_BRANCH) : ($branch = $env:APPVEYOR_PULL_REQUEST_HEAD_REPO_BRANCH) + + git checkout $(git show-ref --verify --quiet refs/remotes/origin/${branch} || echo '-b') ${branch} + + C:\Python37-x64\python.exe unimake.py -d c:\projects\modorganizer-build -s Appveyor_Build=True ${env:APPVEYOR_PROJECT_NAME} + + if($LastExitCode -ne 0) { $host.SetShouldExit($LastExitCode ) } +artifacts: +- path: vsbuild\src\RelWithDebInfo\game_fallout4.dll + name: game_fallout4_dll +- path: vsbuild\src\RelWithDebInfo\game_fallout4.pdb + name: game_fallout4_pdb +- path: vsbuild\src\RelWithDebInfo\game_fallout4.lib + name: game_fallout4_lib +on_success: + - ps: Set-Location -Path $env:APPVEYOR_BUILD_FOLDER + - ps: Invoke-RestMethod https://raw.githubusercontent.com/DiscordHooks/appveyor-discord-webhook/master/send.ps1 -o send.ps1 + - ps: ./send.ps1 success $env:WEBHOOK_URL +on_failure: + - ps: Set-Location -Path $env:APPVEYOR_BUILD_FOLDER + - ps: Push-AppveyorArtifact ${env:APPVEYOR_BUILD_FOLDER}\stdout.log + - ps: Push-AppveyorArtifact ${env:APPVEYOR_BUILD_FOLDER}\stderr.log + - ps: Invoke-RestMethod https://raw.githubusercontent.com/DiscordHooks/appveyor-discord-webhook/master/send.ps1 -o send.ps1 + - ps: ./send.ps1 failure $env:WEBHOOK_URL \ No newline at end of file diff --git a/src/games/starfield/src/CMakeLists.txt b/src/games/starfield/src/CMakeLists.txt new file mode 100644 index 00000000..2c15f453 --- /dev/null +++ b/src/games/starfield/src/CMakeLists.txt @@ -0,0 +1,7 @@ +cmake_minimum_required(VERSION 3.16) + +add_library(game_starfield SHARED) +mo2_configure_plugin(game_starfield + WARNINGS OFF + PRIVATE_DEPENDS creation) +mo2_install_target(game_starfield) diff --git a/src/games/starfield/src/SConscript b/src/games/starfield/src/SConscript new file mode 100644 index 00000000..d9018b9d --- /dev/null +++ b/src/games/starfield/src/SConscript @@ -0,0 +1,14 @@ +Import('qt_env') + +env = qt_env.Clone() + +# Shouldn't this be GAMEFALLOUT3_LIBRARY +env.AppendUnique(CPPDEFINES = [ 'GAMESTARFIELD_LIBRARY' ]) + +env.RequiresGamebryo() + +lib = env.SharedLibrary('gamestarfield', env.Glob('*.cpp')) +env.InstallModule(lib) + +res = env['QT_USED_MODULES'] +Return('res') diff --git a/src/games/starfield/src/gameStarfield.pro b/src/games/starfield/src/gameStarfield.pro new file mode 100644 index 00000000..433b08ae --- /dev/null +++ b/src/games/starfield/src/gameStarfield.pro @@ -0,0 +1,50 @@ +#------------------------------------------------- +# +# Project created by QtCreator 2014-11-15T15:36:33 +# +#------------------------------------------------- + + +TARGET = gameStarfield +TEMPLATE = lib + +CONFIG += plugins +CONFIG += dll + +DEFINES += GAMESTARFIELD_LIBRARY + +SOURCES += gamestarfield.cpp \ + starfieldbsainvalidation.cpp \ + starfieldscriptextender.cpp \ + starfielddataarchives.cpp \ + starfieldsavegame.cpp \ + starfieldsavegameinfo.cpp + +HEADERS += gamestarfield.h \ + starfieldbsainvalidation.h \ + starfieldscriptextender.h \ + starfielddataarchives.h \ + starfieldsavegame.h \ + starfieldsavegameinfo.h + +CONFIG(debug, debug|release) { + LIBS += -L"$${OUT_PWD}/../gameGamebryo/debug" + PRE_TARGETDEPS += \ + $$OUT_PWD/../gameGamebryo/debug/gameGamebryo.lib +} else { + LIBS += -L"$${OUT_PWD}/../gameGamebryo/release" + PRE_TARGETDEPS += \ + $$OUT_PWD/../gameGamebryo/release/gameGamebryo.lib +} + +include(../plugin_template.pri) + +INCLUDEPATH += "$${BOOSTPATH}" "$${PWD}/../gamefeatures" "$${PWD}/../gamegamebryo" + +LIBS += -ladvapi32 -lole32 -lgameGamebryo + +OTHER_FILES += \ + gamestarfield.json\ + SConscript \ + CMakeLists.txt + diff --git a/src/games/starfield/src/game_starfield_en.ts b/src/games/starfield/src/game_starfield_en.ts new file mode 100644 index 00000000..b6f10d5b --- /dev/null +++ b/src/games/starfield/src/game_starfield_en.ts @@ -0,0 +1,18 @@ + + + + + GameStarfield + + + Starfield Support Plugin + + + + + Adds support for the game Starfield. +Splash by %1 + + + + diff --git a/src/games/starfield/src/gamestarfield.cpp b/src/games/starfield/src/gamestarfield.cpp new file mode 100644 index 00000000..76970a0d --- /dev/null +++ b/src/games/starfield/src/gamestarfield.cpp @@ -0,0 +1,197 @@ +#include "gamestarfield.h" + +#include "starfielddataarchives.h" +#include "starfieldscriptextender.h" +#include "starfieldunmanagedmods.h" +#include "starfieldmoddatachecker.h" +#include "starfieldmoddatacontent.h" +#include "starfieldsavegame.h" + +#include +#include +#include +#include +#include +#include "versioninfo.h" + +#include +#include +#include +#include +#include +#include +#include + +#include + +#include "scopeguard.h" + +using namespace MOBase; + +GameStarfield::GameStarfield() +{ +} + +bool GameStarfield::init(IOrganizer *moInfo) +{ + if (!GameGamebryo::init(moInfo)) { + return false; + } + + registerFeature(new StarfieldScriptExtender(this)); + registerFeature(new StarfieldDataArchives(myGamesPath())); + registerFeature(new GamebryoLocalSavegames(myGamesPath(), "starfieldcustom.ini")); + registerFeature(new StarfieldModDataChecker(this)); + registerFeature(new StarfieldModDataContent(this)); + registerFeature(new GamebryoSaveGameInfo(this)); + registerFeature(new CreationGamePlugins(moInfo)); + registerFeature(new StarfieldUnmangedMods(this)); + + return true; +} + +QString GameStarfield::gameName() const +{ + return "Starfield"; +} + +void GameStarfield::detectGame() +{ + m_GamePath = identifyGamePath(); + m_MyGamesPath = determineMyGamesPath("Starfield"); +} + +QList GameStarfield::executables() const +{ + return QList() + << ExecutableInfo("Starfield", findInGameFolder(binaryName())) + ; +} + +QList GameStarfield::executableForcedLoads() const +{ + return QList(); +} + +QString GameStarfield::name() const +{ + return "Starfield Support Plugin"; +} + +QString GameStarfield::localizedName() const +{ + return tr("Starfield Support Plugin"); +} + + +QString GameStarfield::author() const +{ + return "Silarn"; +} + +QString GameStarfield::description() const +{ + return tr("Adds support for the game Starfield."); +} + +MOBase::VersionInfo GameStarfield::version() const +{ + return VersionInfo(0, 0, 1, VersionInfo::RELEASE_PREALPHA); +} + +QList GameStarfield::settings() const +{ + return QList(); +} + +void GameStarfield::initializeProfile(const QDir &path, ProfileSettings settings) const +{ + if (settings.testFlag(IPluginGame::MODS)) { + copyToProfile(localAppFolder() + "/Starfield", path, "plugins.txt"); + } + + if (settings.testFlag(IPluginGame::CONFIGURATION)) { + if (settings.testFlag(IPluginGame::PREFER_DEFAULTS) + || !QFileInfo(myGamesPath() + "/Starfield.ini").exists()) { + copyToProfile(gameDirectory().absolutePath(), path, "StarfieldDefault.ini", "Starfield.ini"); + } else { + copyToProfile(myGamesPath(), path, "Starfield.ini"); + } + + copyToProfile(myGamesPath(), path, "StarfieldPrefs.ini"); + copyToProfile(myGamesPath(), path, "StarfieldCustom.ini"); + } +} + +QString GameStarfield::savegameExtension() const +{ + return "sfs"; +} + +QString GameStarfield::savegameSEExtension() const +{ + return "sfse"; +} + +std::shared_ptr GameStarfield::makeSaveGame(QString filePath) const +{ + return std::make_shared(filePath, this); +} + +QString GameStarfield::steamAPPId() const +{ + return "1716740"; +} + +QStringList GameStarfield::primaryPlugins() const { + QStringList plugins = {"Starfield.esm", "Constellation.esm", "OldMars.esm", "BlueprintShips-Starfield.esm"}; + + plugins.append(CCPlugins()); + + return plugins; +} + +QStringList GameStarfield::gameVariants() const +{ + return { "Regular" }; +} + +QString GameStarfield::gameShortName() const +{ + return "Starfield"; +} + +QString GameStarfield::gameNexusName() const +{ + return "starfield"; +} + +QStringList GameStarfield::iniFiles() const +{ + return { "Starfield.ini", "StarfieldPrefs.ini", "StarfieldCustom.ini" }; +} + +QStringList GameStarfield::DLCPlugins() const +{ + return {}; +} + +QStringList GameStarfield::CCPlugins() const +{ + return {}; +} + +IPluginGame::LoadOrderMechanism GameStarfield::loadOrderMechanism() const +{ + return IPluginGame::LoadOrderMechanism::PluginsTxt; +} + +int GameStarfield::nexusModOrganizerID() const +{ + return 28715; +} + +int GameStarfield::nexusGameID() const +{ + return 1151; +} diff --git a/src/games/starfield/src/gamestarfield.h b/src/games/starfield/src/gamestarfield.h new file mode 100644 index 00000000..5ff34cb3 --- /dev/null +++ b/src/games/starfield/src/gamestarfield.h @@ -0,0 +1,58 @@ +#ifndef GAMESTARFIELD_H +#define GAMESTARFIELD_H + + +#include "gamegamebryo.h" + +#include +#include + +class GameStarfield : public GameGamebryo +{ + Q_OBJECT + + Q_PLUGIN_METADATA(IID "org.modorganizer.GameStarfield" FILE "gamestarfield.json") + +public: + + GameStarfield(); + + virtual bool init(MOBase::IOrganizer *moInfo) override; + +public: // IPluginGame interface + + virtual QString gameName() const override; + virtual void detectGame() override; + virtual QList executables() const override; + virtual QList 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 gameShortName() const override; + virtual QString gameNexusName() const override; + virtual QStringList iniFiles() const override; + virtual QStringList DLCPlugins() const override; + virtual QStringList CCPlugins() const override; + virtual LoadOrderMechanism loadOrderMechanism() const override; + virtual int nexusModOrganizerID() const override; + virtual int nexusGameID() 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 settings() const override; + +protected: + + std::shared_ptr makeSaveGame(QString filePath) const override; + QString savegameExtension() const override; + QString savegameSEExtension() const override; + +}; + +#endif // GAMEStarfield_H diff --git a/src/games/starfield/src/gamestarfield.json b/src/games/starfield/src/gamestarfield.json new file mode 100644 index 00000000..0967ef42 --- /dev/null +++ b/src/games/starfield/src/gamestarfield.json @@ -0,0 +1 @@ +{} diff --git a/src/games/starfield/src/starfielddataarchives.cpp b/src/games/starfield/src/starfielddataarchives.cpp new file mode 100644 index 00000000..f90d19b6 --- /dev/null +++ b/src/games/starfield/src/starfielddataarchives.cpp @@ -0,0 +1,96 @@ +#include "starfielddataarchives.h" + +#include "iprofile.h" +#include + +StarfieldDataArchives::StarfieldDataArchives(const QDir &myGamesDir) : + GamebryoDataArchives(myGamesDir) +{} + +QStringList StarfieldDataArchives::vanillaArchives() const +{ + return { "Starfield - Animations.ba2" + , "Starfield - DensityMaps.ba2" + , "Starfield - FaceAnimation01.ba2" + , "Starfield - FaceAnimation02.ba2" + , "Starfield - FaceAnimation03.ba2" + , "Starfield - FaceAnimation04.ba2" + , "Starfield - FaceAnimationPatch.ba2" + , "Starfield - FaceMeshes.ba2" + , "Starfield - GeneratedTextures.ba2" + , "Starfield - Interface.ba2" + , "Starfield - Localization.ba2" + , "Starfield - LODMeshes.ba2" + , "Starfield - LODMeshesPatch.ba2" + , "Starfield - LODTextures.ba2" + , "Starfield - Materials.ba2" + , "Starfield - Meshes01.ba2" + , "Starfield - Meshes02.ba2" + , "Starfield - MeshesPatch.ba2" + , "Starfield - Misc.ba2" + , "Starfield - Particles.ba2" + , "Starfield - ParticlesTestData.ba2" + , "Starfield - PlanetData.ba2" + , "Starfield - Shaders.ba2" + , "Starfield - ShadersBeta.ba2" + , "Starfield - Terrain01.ba2" + , "Starfield - Terrain02.ba2" + , "Starfield - Terrain03.ba2" + , "Starfield - Terrain04.ba2" + , "Starfield - TerrainPatch.ba2" + , "Starfield - Textures01.ba2" + , "Starfield - Textures02.ba2" + , "Starfield - Textures03.ba2" + , "Starfield - Textures04.ba2" + , "Starfield - Textures05.ba2" + , "Starfield - Textures06.ba2" + , "Starfield - Textures07.ba2" + , "Starfield - Textures08.ba2" + , "Starfield - Textures09.ba2" + , "Starfield - Textures10.ba2" + , "Starfield - Textures11.ba2" + , "Starfield - TexturesPatch.ba2" + , "Starfield - Voices01.ba2" + , "Starfield - Voices02.ba2" + , "Starfield - VoicesPatch.ba2" + , "Starfield - WwiseSounds01.ba2" + , "Starfield - WwiseSounds02.ba2" + , "Starfield - WwiseSounds03.ba2" + , "Starfield - WwiseSounds04.ba2" + , "Starfield - WwiseSounds05.ba2" + , "Starfield - WwiseSoundsPatch.ba2" + , "Constellation - Localization.ba2" + , "Constellation - Textures.ba2" + , "OldMars - Localization.ba2" + , "OldMars - Textures.ba2" + , "BlueprintShips-Starfield - Localization.ba2" }; +} + + +QStringList StarfieldDataArchives::archives(const MOBase::IProfile *profile) const +{ + QStringList result; + + QString iniFile = profile->localSettingsEnabled() ? QDir(profile->absolutePath()).absoluteFilePath("Starfield.ini") : m_LocalGameDir.absoluteFilePath("Starfield.ini"); + result.append(getArchivesFromKey(iniFile, "SResourceArchiveList")); + result.append(getArchivesFromKey(iniFile, "sResourceIndexFileList")); + result.append(getArchivesFromKey(iniFile, "SResourceArchiveMemoryCacheList")); + result.append(getArchivesFromKey(iniFile, "sResourceStartUpArchiveList")); + result.append(getArchivesFromKey(iniFile, "sResourceEnglishVoiceList")); + + return result; +} + +void StarfieldDataArchives::writeArchiveList(MOBase::IProfile *profile, const QStringList &before) +{ + QString list = before.join(", "); + + QString iniFile = profile->localSettingsEnabled() ? QDir(profile->absolutePath()).absoluteFilePath("Starfield.ini") : m_LocalGameDir.absoluteFilePath("Starfield.ini"); + if (list.length() > 255) { + int splitIdx = list.lastIndexOf(",", 256); + setArchivesToKey(iniFile, "SResourceArchiveList", list.mid(0, splitIdx)); + setArchivesToKey(iniFile, "SResourceArchiveList2", list.mid(splitIdx + 2)); + } else { + setArchivesToKey(iniFile, "SResourceArchiveList", list); + } +} diff --git a/src/games/starfield/src/starfielddataarchives.h b/src/games/starfield/src/starfielddataarchives.h new file mode 100644 index 00000000..7738085a --- /dev/null +++ b/src/games/starfield/src/starfielddataarchives.h @@ -0,0 +1,29 @@ +#ifndef STARFIELDDATAARCHIVES_H +#define STARFIELDDATAARCHIVES_H + +#include "gamebryodataarchives.h" + +namespace MOBase { class IProfile; } + +#include +#include + +class StarfieldDataArchives : public GamebryoDataArchives +{ + +public: + + StarfieldDataArchives(const QDir &myGamesDir); + +public: + + 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 // STARFIELDDATAARCHIVES_H diff --git a/src/games/starfield/src/starfieldmoddatachecker.h b/src/games/starfield/src/starfieldmoddatachecker.h new file mode 100644 index 00000000..e4752c9c --- /dev/null +++ b/src/games/starfield/src/starfieldmoddatachecker.h @@ -0,0 +1,28 @@ +#ifndef STARFIELD_MODATACHECKER_H +#define STARFIELD_MODATACHECKER_H + +#include + +class StarfieldModDataChecker : public GamebryoModDataChecker +{ +public: + using GamebryoModDataChecker::GamebryoModDataChecker; + +protected: + virtual const FileNameSet& possibleFolderNames() const override { + static FileNameSet result{ + "interface", "meshes", "music", "scripts", "sound", "strings", "textures", + "trees", "video", "materials", "f4se", "distantlod", "asi", "Tools", "MCM", + "distantland", "mits", "dllplugins", "CalienteTools", "shadersfx", "aaf" + }; + return result; + } + virtual const FileNameSet& possibleFileExtensions() const override { + static FileNameSet result{ + "esp", "esm", "esl", "ba2", "modgroups", "ini", "csg", "cdx" + }; + return result; + } +}; + +#endif // STARFIELD_MODATACHECKER_H diff --git a/src/games/starfield/src/starfieldmoddatacontent.h b/src/games/starfield/src/starfieldmoddatacontent.h new file mode 100644 index 00000000..1e6930bd --- /dev/null +++ b/src/games/starfield/src/starfieldmoddatacontent.h @@ -0,0 +1,41 @@ +#ifndef STARFIELD_MODDATACONTENT_H +#define STARFIELD_MODDATACONTENT_H + +#include +#include + +class StarfieldModDataContent : public GamebryoModDataContent { +protected: + enum StarfieldContent { + CONTENT_MATERIAL = CONTENT_NEXT_VALUE + }; + +public: + StarfieldModDataContent(GameGamebryo const* gamePlugin) : + GamebryoModDataContent(gamePlugin) + { + m_Enabled[CONTENT_SKYPROC] = false; + } + + std::vector getAllContents() const override + { + auto contents = GamebryoModDataContent::getAllContents(); + contents.push_back(Content(CONTENT_MATERIAL, "Materials", ":/MO/gui/content/material")); + return contents; + } + + std::vector getContentsFor( + std::shared_ptr fileTree) const override + { + auto contents = GamebryoModDataContent::getContentsFor(fileTree); + for (auto e : *fileTree) { + if (e->compare("materials") == 0) { + contents.push_back(CONTENT_MATERIAL); + break; // Early break if you have nothing else to check. + } + } + return contents; + } +}; + +#endif // STARFIELD_MODDATACONTENT_H \ No newline at end of file diff --git a/src/games/starfield/src/starfieldsavegame.cpp b/src/games/starfield/src/starfieldsavegame.cpp new file mode 100644 index 00000000..30af4304 --- /dev/null +++ b/src/games/starfield/src/starfieldsavegame.cpp @@ -0,0 +1,82 @@ +#include "starfieldsavegame.h" + +#include + +#include "gamestarfield.h" + +StarfieldSaveGame::StarfieldSaveGame(QString const &fileName, GameStarfield const* game) : + GamebryoSaveGame(fileName, game, true) +{ + FileWrapper file(getFilepath(), "BCPS"); + + FILETIME creationTime; + fetchInformationFields(file, m_SaveNumber, m_PCName, m_PCLevel, m_PCLocation, creationTime); + + //A file time is a 64-bit value that represents the number of 100-nanosecond + //intervals that have elapsed since 12:00 A.M. January 1, 1601 Coordinated Universal Time (UTC). + //So we need to convert that to something useful + SYSTEMTIME ctime; + ::FileTimeToSystemTime(&creationTime, &ctime); + + setCreationTime(ctime); +} + +void StarfieldSaveGame::fetchInformationFields( + FileWrapper& file, + unsigned long& saveNumber, + QString& playerName, + unsigned short& playerLevel, + QString& playerLocation, + FILETIME& creationTime) const +{ + file.skip(); // header size + file.skip(); // header version + file.read(saveNumber); + + file.read(playerName); + + unsigned long temp; + file.read(temp); + playerLevel = static_cast(temp); + file.read(playerLocation); + + QString ignore; + file.read(ignore); // playtime as ascii hh.mm.ss + file.read(ignore); // race name (i.e. BretonRace) + + file.skip(); // Player gender (0 = male) + file.skip(2); // experience gathered, experience required + + file.read(creationTime); +} + +std::unique_ptr StarfieldSaveGame::fetchDataFields() const +{ + FileWrapper file(getFilepath(), "FO4_SAVEGAME"); //10bytes + + { + QString dummyName, dummyLocation; + unsigned short dummyLevel; + unsigned long dummySaveNumber; + FILETIME dummyTime; + + fetchInformationFields(file, dummySaveNumber, dummyName, dummyLevel, + dummyLocation, dummyTime); + } + + QString ignore; + std::unique_ptr fields = std::make_unique(); + + fields->Screenshot = file.readImage(384, true); + + uint8_t saveGameVersion = file.readChar(); + file.read(ignore); // game version + file.skip(); // plugin info size + + fields->Plugins = file.readPlugins(); + if (saveGameVersion >= 68) { + fields->LightPlugins = file.readLightPlugins(); + } + + return fields; +} \ No newline at end of file diff --git a/src/games/starfield/src/starfieldsavegame.h b/src/games/starfield/src/starfieldsavegame.h new file mode 100644 index 00000000..d8cb45b2 --- /dev/null +++ b/src/games/starfield/src/starfieldsavegame.h @@ -0,0 +1,30 @@ +#ifndef STARFIELDSAVEGAME_H +#define STARFIELDSAVEGAME_H + +#include "gamebryosavegame.h" +#include "zlib.h" + +#include + +class GameStarfield; + +class StarfieldSaveGame : public GamebryoSaveGame +{ +public: + StarfieldSaveGame(QString const &fileName, GameStarfield const* game); + +protected: + + // Fetch easy-to-access information. + void fetchInformationFields( + FileWrapper& file, + unsigned long& saveNumber, + QString& playerName, + unsigned short& playerLevel, + QString& playerLocation, + FILETIME& creationTime) const; + + std::unique_ptr fetchDataFields() const override; +}; + +#endif // STARFIELDSAVEGAME_H diff --git a/src/games/starfield/src/starfieldscriptextender.cpp b/src/games/starfield/src/starfieldscriptextender.cpp new file mode 100644 index 00000000..8fd6477c --- /dev/null +++ b/src/games/starfield/src/starfieldscriptextender.cpp @@ -0,0 +1,19 @@ +#include "starfieldscriptextender.h" + +#include +#include + +StarfieldScriptExtender::StarfieldScriptExtender(GameGamebryo const *game) : + GamebryoScriptExtender(game) +{ +} + +QString StarfieldScriptExtender::BinaryName() const +{ + return "f4se_loader.exe"; +} + +QString StarfieldScriptExtender::PluginPath() const +{ + return "f4se/plugins"; +} diff --git a/src/games/starfield/src/starfieldscriptextender.h b/src/games/starfield/src/starfieldscriptextender.h new file mode 100644 index 00000000..fa29317b --- /dev/null +++ b/src/games/starfield/src/starfieldscriptextender.h @@ -0,0 +1,18 @@ +#ifndef STARFIELDSCRIPTEXTENDER_H +#define STARFIELDSCRIPTEXTENDER_H + +#include "gamebryoscriptextender.h" + +class GameGamebryo; + +class StarfieldScriptExtender : public GamebryoScriptExtender +{ +public: + StarfieldScriptExtender(GameGamebryo const *game); + + virtual QString BinaryName() const override; + virtual QString PluginPath() const override; + +}; + +#endif // STARFIELDSCRIPTEXTENDER_H diff --git a/src/games/starfield/src/starfieldunmanagedmods.cpp b/src/games/starfield/src/starfieldunmanagedmods.cpp new file mode 100644 index 00000000..14fab23f --- /dev/null +++ b/src/games/starfield/src/starfieldunmanagedmods.cpp @@ -0,0 +1,63 @@ +#include "starfieldunmanagedmods.h" + + +StarfieldUnmangedMods::StarfieldUnmangedMods(const GameGamebryo *game) + : GamebryoUnmangedMods(game) +{} + +StarfieldUnmangedMods::~StarfieldUnmangedMods() +{} + +QStringList StarfieldUnmangedMods::mods(bool onlyOfficial) const { + QStringList result; + + QStringList pluginList = game()->primaryPlugins(); + QStringList otherPlugins = game()->DLCPlugins(); + otherPlugins.append(game()->CCPlugins()); + for (QString plugin : otherPlugins) { + pluginList.removeAll(plugin); + } + QDir dataDir(game()->dataDirectory()); + for (const QString &fileName : dataDir.entryList({ "*.esp", "*.esl", "*.esm" })) { + if (!pluginList.contains(fileName, Qt::CaseInsensitive)) { + if (!onlyOfficial || pluginList.contains(fileName, Qt::CaseInsensitive)) { + result.append(fileName.chopped(4)); // trims the extension off + } + } + } + + return result; +} + +QStringList StarfieldUnmangedMods::secondaryFiles(const QString &modName) const { + // file extension in FO4 is .ba2 instead of bsa + QStringList archives; + QDir dataDir = game()->dataDirectory(); + for (const QString &archiveName : dataDir.entryList({modName + "*.ba2"})) { + archives.append(dataDir.absoluteFilePath(archiveName)); + } + return archives; +} + +QString StarfieldUnmangedMods::displayName(const QString &modName) const +{ + // unlike in earlier games, in fallout 4 the file name doesn't correspond to + // the public name + if (modName.compare("dlcrobot", Qt::CaseInsensitive) == 0) { + return "Automatron"; + } else if (modName.compare("dlcworkshop01", Qt::CaseInsensitive) == 0) { + return "Wasteland Workshop"; + } else if (modName.compare("dlccoast", Qt::CaseInsensitive) == 0) { + return "Far Harbor"; + } else if (modName.compare("dlcworkshop02", Qt::CaseInsensitive) == 0) { + return "Contraptions Workshop"; + } else if (modName.compare("dlcworkshop03", Qt::CaseInsensitive) == 0) { + return "Vault-Tec Workshop"; + } else if (modName.compare("dlcnukaworld", Qt::CaseInsensitive) == 0) { + return "Nuka-World"; + } else if (modName.compare("dlcultrahighresolution", Qt::CaseInsensitive) == 0) { + return "Ultra High Resolution Texture Pack"; + } else { + return modName; + } +} diff --git a/src/games/starfield/src/starfieldunmanagedmods.h b/src/games/starfield/src/starfieldunmanagedmods.h new file mode 100644 index 00000000..bea9be89 --- /dev/null +++ b/src/games/starfield/src/starfieldunmanagedmods.h @@ -0,0 +1,21 @@ +#ifndef STARFIELDUNMANAGEDMODS_H +#define STARFIELDUNMANAGEDMODS_H + + +#include "gamebryounmanagedmods.h" +#include + + +class StarfieldUnmangedMods : public GamebryoUnmangedMods { +public: + StarfieldUnmangedMods(const GameGamebryo *game); + ~StarfieldUnmangedMods(); + + virtual QStringList mods(bool onlyOfficial) const override; + virtual QStringList secondaryFiles(const QString &modName) const override; + virtual QString displayName(const QString &modName) const override; +}; + + + +#endif // STARFIELDUNMANAGEDMODS_H From f0c33c6e610ede41116679d736847c6f79ad58bb Mon Sep 17 00:00:00 2001 From: Jeremy Rimpo Date: Sat, 2 Sep 2023 02:16:28 -0500 Subject: [PATCH 1295/1544] [game_starfield] Fix cmakelists --- src/games/starfield/CMakeLists.txt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/games/starfield/CMakeLists.txt b/src/games/starfield/CMakeLists.txt index 1e0429a5..2ce9ac19 100644 --- a/src/games/starfield/CMakeLists.txt +++ b/src/games/starfield/CMakeLists.txt @@ -6,5 +6,5 @@ else() include(${CMAKE_CURRENT_LIST_DIR}/cmake_common/mo2.cmake) endif() -project(game_fallout4) +project(game_starfield) add_subdirectory(src) From 787f24190425cb5d971fbb0eadad5b0201d6cc31 Mon Sep 17 00:00:00 2001 From: Jeremy Rimpo Date: Sun, 3 Sep 2023 22:26:07 -0500 Subject: [PATCH 1296/1544] Add zlib to depends due to gamebryo updates --- src/gamebryo/CMakeLists.txt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/gamebryo/CMakeLists.txt b/src/gamebryo/CMakeLists.txt index a3576a11..cff88fc9 100644 --- a/src/gamebryo/CMakeLists.txt +++ b/src/gamebryo/CMakeLists.txt @@ -6,5 +6,5 @@ mo2_configure_library(game_gamebryo TRANSLATIONS ON AUTOMOC ON PUBLIC_DEPENDS uibase - PRIVATE_DEPENDS lz4) + PRIVATE_DEPENDS zlib lz4) mo2_install_target(game_gamebryo) From 453f5df89ad96a736b5ebfe43bff46f44309d48d Mon Sep 17 00:00:00 2001 From: Jeremy Rimpo Date: Sun, 3 Sep 2023 22:26:09 -0500 Subject: [PATCH 1297/1544] [game_skyrimse] Add zlib to depends due to gamebryo updates --- src/games/skyrimse/src/CMakeLists.txt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/games/skyrimse/src/CMakeLists.txt b/src/games/skyrimse/src/CMakeLists.txt index 9b410545..a3532b3d 100644 --- a/src/games/skyrimse/src/CMakeLists.txt +++ b/src/games/skyrimse/src/CMakeLists.txt @@ -3,5 +3,5 @@ cmake_minimum_required(VERSION 3.16) add_library(game_skyrimse SHARED) mo2_configure_plugin(game_skyrimse WARNINGS OFF - PRIVATE_DEPENDS creation) + PRIVATE_DEPENDS zlib creation) mo2_install_target(game_skyrimse) From 832e49f324663194186b753e9405c4c49bcea85e Mon Sep 17 00:00:00 2001 From: Jeremy Rimpo Date: Sun, 3 Sep 2023 22:27:31 -0500 Subject: [PATCH 1298/1544] Add zlib decompression support for saves (Starfield) --- src/gamebryo/gamebryosavegame.cpp | 244 ++++++++++++++++++++---------- src/gamebryo/gamebryosavegame.h | 6 +- src/gamebryo/gamegamebryo.cpp | 2 +- 3 files changed, 174 insertions(+), 78 deletions(-) diff --git a/src/gamebryo/gamebryosavegame.cpp b/src/gamebryo/gamebryosavegame.cpp index 2227eb0d..732b28b7 100644 --- a/src/gamebryo/gamebryosavegame.cpp +++ b/src/gamebryo/gamebryosavegame.cpp @@ -12,6 +12,7 @@ #include #include +#include #include #include @@ -19,6 +20,8 @@ #include "gamegamebryo.h" +#define CHUNK 16384 + GamebryoSaveGame::GamebryoSaveGame(QString const &file, GameGamebryo const *game, bool const lightEnabled) : m_FileName(file), m_CreationTime(QFileInfo(file).lastModified()), @@ -118,41 +121,79 @@ void GamebryoSaveGame::FileWrapper::setPluginString(StringType type) m_PluginString = type; } -template <> void GamebryoSaveGame::FileWrapper::read(QString &value) +void readQDataStream(QDataStream& data, void* buff, std::size_t length) { + int read = data.readRawData(static_cast(buff), static_cast(length)); + if (read != length) { + throw std::runtime_error("unexpected end of file"); + } +} + +template void readQDataStream(QDataStream& data, T& value) { + int read = data.readRawData(reinterpret_cast(&value), sizeof(T)); + if (read != sizeof(T)) { + throw std::runtime_error("unexpected end of file"); + } +} + +template <> void readQDataStream(QDataStream& data, QString& value) { unsigned short length; - if (m_PluginString == StringType::TYPE_BSTRING || m_PluginString == StringType::TYPE_BZSTRING) { - unsigned char len; - read(len); - length = m_PluginString == StringType::TYPE_BZSTRING ? len + 1 : len; + readQDataStream(data, length); + + std::vector buffer(length); + + readQDataStream(data, buffer.data(), length); + + value = QString::fromLatin1(buffer.data(), length); +} + +template <> void GamebryoSaveGame::FileWrapper::read(QString &value) +{ + if (m_CompressionType == 0) { + unsigned short length; + if (m_PluginString == StringType::TYPE_BSTRING || m_PluginString == StringType::TYPE_BZSTRING) { + unsigned char len; + read(len); + length = m_PluginString == StringType::TYPE_BZSTRING ? len + 1 : len; + } else { + read(length); + } + + if (m_HasFieldMarkers) { + skip(); + } + + QByteArray buffer; + buffer.resize(length); + + read(buffer.data(), m_PluginString == StringType::TYPE_BZSTRING ? length - 1 : length); + + if (m_PluginString == StringType::TYPE_BZSTRING) + buffer[length - 1] = '\0'; + + if (m_HasFieldMarkers) { + skip(); + } + + value = QString::fromUtf8(buffer.constData()); + } else if (m_CompressionType == 1 || m_CompressionType == 2) { + readQDataStream(*m_Data, value); } else { - read(length); + MOBase::log::warn("Please create an issue on the MO github labeled \"Found unknown Compressed\" with your savefile attached"); } - - if (m_HasFieldMarkers) { - skip(); - } - - QByteArray buffer; - buffer.resize(length); - - read(buffer.data(), m_PluginString == StringType::TYPE_BZSTRING ? length - 1 : length); - - if (m_PluginString == StringType::TYPE_BZSTRING) - buffer[length - 1] = '\0'; - - if (m_HasFieldMarkers) { - skip(); - } - - value = QString::fromUtf8(buffer.constData()); } void GamebryoSaveGame::FileWrapper::read(void *buff, std::size_t length) { - int read = m_File.read(static_cast(buff), length); - if (read != length) { - throw std::runtime_error("unexpected end of file"); + if (m_CompressionType == 0) { + int read = m_File.read(static_cast(buff), length); + if (read != length) { + throw std::runtime_error("unexpected end of file"); + } + } else if (m_CompressionType == 1 || m_CompressionType == 2) { + readQDataStream(*m_Data, buff, length); + } else { + MOBase::log::warn("Please create an issue on the MO github labeled \"Found unknown Compressed\" with your savefile attached"); } } @@ -181,30 +222,6 @@ QImage GamebryoSaveGame::FileWrapper::readImage(unsigned long width, unsigned lo return image.copy(); } } -void readQDataStream(QDataStream &data, void *buff, std::size_t length) { - int read = data.readRawData(static_cast(buff), static_cast(length)); - if (read != length) { - throw std::runtime_error("unexpected end of file"); - } -} -template void readQDataStream(QDataStream &data, T &value) { - int read = data.readRawData(reinterpret_cast(&value), sizeof(T)); - if (read != sizeof(T)) { - throw std::runtime_error("unexpected end of file"); - } -} - -template <> void readQDataStream(QDataStream &data, QString &value) -{ - unsigned short length; - readQDataStream(data, length); - - std::vector buffer(length); - - readQDataStream(data, buffer.data(), length); - - value = QString::fromLatin1(buffer.data(), length); -} void GamebryoSaveGame::FileWrapper::setCompressionType(uint16_t compressionType) { @@ -214,11 +231,7 @@ void GamebryoSaveGame::FileWrapper::setCompressionType(uint16_t compressionType) void GamebryoSaveGame::FileWrapper::closeCompressedData() { if (m_CompressionType == 0) { - } - else if (m_CompressionType == 1) { - MOBase::log::warn("Please create an issue on the MO github labeled \"Found zlib Compressed\" with your savefile attached"); - } - else if (m_CompressionType == 2) { + } else if (m_CompressionType == 1 || m_CompressionType == 2) { m_Data->device()->close(); delete m_Data; } @@ -233,8 +246,56 @@ bool GamebryoSaveGame::FileWrapper::openCompressedData(int bytesToIgnore) skip(bytesToIgnore); return false; } else if (m_CompressionType == 1) { - MOBase::log::warn("Please create an issue on the MO github labeled \"Found zlib Compressed\" with your savefile attached"); - return false; + uint64_t location; + read(location); + uint64_t uncompressedSize; + read(uncompressedSize); + seek(location); + uInt have; + uInt size = 0; + std::unique_ptr inBuffer(new unsigned char[CHUNK]); + std::unique_ptr outBuffer(new unsigned char[CHUNK]); + QByteArray finalData; + z_stream stream; + try { + stream.zalloc = Z_NULL; + stream.zfree = Z_NULL; + stream.opaque = Z_NULL; + stream.avail_in = 0; + stream.next_in = Z_NULL; + int zlibRet = inflateInit2(&stream, 15 + 32); + if (zlibRet != Z_OK) { + return false; + } + do { + stream.avail_in = m_File.read(reinterpret_cast(inBuffer.get()), CHUNK); + if (!m_File.isReadable()) { + (void)inflateEnd(&stream); + return false; + } + if (stream.avail_in == 0) + break; + stream.next_in = static_cast(inBuffer.get()); + do { + stream.avail_out = CHUNK; + stream.next_out = reinterpret_cast(outBuffer.get()); + zlibRet = inflate(&stream, Z_NO_FLUSH); + if ((zlibRet != Z_OK) && (zlibRet != Z_STREAM_END) && (zlibRet != Z_BUF_ERROR)) { + return false; + } + have = CHUNK - stream.avail_out; + size += have; + finalData += QByteArray::fromRawData(reinterpret_cast(outBuffer.get()), have); + } while (stream.avail_out == 0); + } while (zlibRet != Z_STREAM_END); + inflateEnd(&stream); + } catch (const std::exception&) { + inflateEnd(&stream); + return false; + } + m_Data = new QDataStream(finalData); + m_Data->skipRawData(bytesToIgnore); + return true; } else if (m_CompressionType == 2) { uint32_t uncompressedSize; read(uncompressedSize); @@ -266,10 +327,7 @@ uint8_t GamebryoSaveGame::FileWrapper::readChar(int bytesToIgnore) uint8_t version; read(version); return version; - } else if (m_CompressionType == 1) { - MOBase::log::warn("Please create an issue on the MO github labeled \"Found zlib Compressed\" with your savefile attached"); - return 0; - } else if (m_CompressionType == 2) { + } else if (m_CompressionType == 1 || m_CompressionType == 2) { // decompression already done by readSaveGameVersion m_Data->skipRawData(bytesToIgnore); @@ -291,10 +349,7 @@ uint16_t GamebryoSaveGame::FileWrapper::readShort(int bytesToIgnore) uint16_t size; read(size); return size; - } else if (m_CompressionType == 1) { - MOBase::log::warn("Please create an issue on the MO github labeled \"Found zlib Compressed\" with your savefile attached"); - return 0; - } else if (m_CompressionType == 2) { + } else if (m_CompressionType == 1 || m_CompressionType == 2) { // decompression already done by readSaveGameVersion m_Data->skipRawData(bytesToIgnore); @@ -315,10 +370,7 @@ uint32_t GamebryoSaveGame::FileWrapper::readInt(int bytesToIgnore) uint32_t size; read(size); return size; - } else if (m_CompressionType == 1) { - MOBase::log::warn("Please create an issue on the MO github labeled \"Found zlib Compressed\" with your savefile attached"); - return 0; - } else if (m_CompressionType == 2) { + } else if (m_CompressionType == 1 || m_CompressionType == 2) { // decompression already done by readSaveGameVersion m_Data->skipRawData(bytesToIgnore); @@ -331,6 +383,50 @@ uint32_t GamebryoSaveGame::FileWrapper::readInt(int bytesToIgnore) } } +uint64_t GamebryoSaveGame::FileWrapper::readLong(int bytesToIgnore) +{ + if (m_CompressionType == 0) { + if (bytesToIgnore > 0)//Just to make certain + skip(bytesToIgnore); + uint64_t size; + read(size); + return size; + } else if (m_CompressionType == 1 || m_CompressionType == 2) { + // decompression already done by readSaveGameVersion + m_Data->skipRawData(bytesToIgnore); + + uint64_t size; + readQDataStream(*m_Data, size); + return size; + } else { + MOBase::log::warn("Please create an issue on the MO github labeled \"Found unknown Compressed\" with your savefile attached"); + return 0; + } +} + +float_t GamebryoSaveGame::FileWrapper::readFloat(int bytesToIgnore) +{ + if (m_CompressionType == 0) { + if (bytesToIgnore > 0)//Just to make certain + skip(bytesToIgnore); + float_t value; + read(value); + return value; + } + else if (m_CompressionType == 1 || m_CompressionType == 2) { + // decompression already done by readSaveGameVersion + m_Data->skipRawData(bytesToIgnore); + + float_t value; + readQDataStream(*m_Data, value); + return value; + } + else { + MOBase::log::warn("Please create an issue on the MO github labeled \"Found unknown Compressed\" with your savefile attached"); + return 0; + } +} + QStringList GamebryoSaveGame::FileWrapper::readPlugins(int bytesToIgnore) { QStringList plugins; @@ -346,9 +442,7 @@ QStringList GamebryoSaveGame::FileWrapper::readPlugins(int bytesToIgnore) read(name); plugins.push_back(name); } - } else if (m_CompressionType == 1) { - MOBase::log::warn("Please create an issue on the MO github labeled \"Found zlib Compressed\" with your savefile attached"); - } else if (m_CompressionType == 2) { + } else if (m_CompressionType == 1 || m_CompressionType == 2) { m_Data->skipRawData(bytesToIgnore); uint8_t count; readQDataStream(*m_Data, count); @@ -377,9 +471,7 @@ QStringList GamebryoSaveGame::FileWrapper::readLightPlugins(int bytesToIgnore) read(name); plugins.push_back(name); } - } else if (m_CompressionType == 1) { - MOBase::log::warn("Please create an issue on the MO github labeled \"Found zlib Compressed\" with your savefile attached"); - } else if (m_CompressionType == 2) { + } else if (m_CompressionType == 1 || m_CompressionType == 2) { m_Data->skipRawData(bytesToIgnore); uint16_t count; diff --git a/src/gamebryo/gamebryosavegame.h b/src/gamebryo/gamebryosavegame.h index 1d92182b..9f29fb28 100644 --- a/src/gamebryo/gamebryosavegame.h +++ b/src/gamebryo/gamebryosavegame.h @@ -102,7 +102,7 @@ protected: void seek(unsigned long pos) { - if (!m_File.seek(pos - m_File.pos())) { + if (!m_File.seek(pos)) { throw std::runtime_error("unexpected end of file"); } } @@ -133,6 +133,10 @@ protected: uint32_t readInt(int bytesToIgnore = 0); + uint64_t readLong(int bytesToIgnore = 0); + + float_t readFloat(int bytesToIgnore = 0); + /* Read the plugin list */ QStringList readPlugins(int bytesToIgnore = 0); diff --git a/src/gamebryo/gamegamebryo.cpp b/src/gamebryo/gamegamebryo.cpp index 60c62bd8..b98c30fb 100644 --- a/src/gamebryo/gamegamebryo.cpp +++ b/src/gamebryo/gamegamebryo.cpp @@ -311,7 +311,7 @@ std::unique_ptr GameGamebryo::getRegValue(HKEY key, LPCWSTR path, LPCWST DWORD size = 0; HKEY subKey; LONG res = ::RegOpenKeyExW(key, path, 0, - KEY_QUERY_VALUE | KEY_WOW64_32KEY, &subKey); + KEY_QUERY_VALUE | KEY_WOW64_32KEY | KEY_WOW64_64KEY, &subKey); if (res != ERROR_SUCCESS) { return std::unique_ptr(); } From 093455c5eb22ddc9eb1beab03cb276a1a77d945c Mon Sep 17 00:00:00 2001 From: Jeremy Rimpo Date: Sun, 3 Sep 2023 22:30:41 -0500 Subject: [PATCH 1299/1544] [game_starfield] Updates for save parsing, various cleanup, etc. TODO: Game detection --- src/games/starfield/src/CMakeLists.txt | 2 +- src/games/starfield/src/SConscript | 14 --- src/games/starfield/src/gameStarfield.pro | 50 --------- src/games/starfield/src/game_starfield_en.ts | 7 +- src/games/starfield/src/gamestarfield.cpp | 32 +++++- src/games/starfield/src/gamestarfield.h | 1 + .../starfield/src/starfieldmoddatachecker.h | 2 +- src/games/starfield/src/starfieldsavegame.cpp | 103 ++++++++++++------ src/games/starfield/src/starfieldsavegame.h | 19 ++-- .../starfield/src/starfieldscriptextender.cpp | 4 +- .../starfield/src/starfieldunmanagedmods.cpp | 18 +-- 11 files changed, 118 insertions(+), 134 deletions(-) delete mode 100644 src/games/starfield/src/SConscript delete mode 100644 src/games/starfield/src/gameStarfield.pro diff --git a/src/games/starfield/src/CMakeLists.txt b/src/games/starfield/src/CMakeLists.txt index 2c15f453..6ac31454 100644 --- a/src/games/starfield/src/CMakeLists.txt +++ b/src/games/starfield/src/CMakeLists.txt @@ -3,5 +3,5 @@ cmake_minimum_required(VERSION 3.16) add_library(game_starfield SHARED) mo2_configure_plugin(game_starfield WARNINGS OFF - PRIVATE_DEPENDS creation) + PRIVATE_DEPENDS zlib creation) mo2_install_target(game_starfield) diff --git a/src/games/starfield/src/SConscript b/src/games/starfield/src/SConscript deleted file mode 100644 index d9018b9d..00000000 --- a/src/games/starfield/src/SConscript +++ /dev/null @@ -1,14 +0,0 @@ -Import('qt_env') - -env = qt_env.Clone() - -# Shouldn't this be GAMEFALLOUT3_LIBRARY -env.AppendUnique(CPPDEFINES = [ 'GAMESTARFIELD_LIBRARY' ]) - -env.RequiresGamebryo() - -lib = env.SharedLibrary('gamestarfield', env.Glob('*.cpp')) -env.InstallModule(lib) - -res = env['QT_USED_MODULES'] -Return('res') diff --git a/src/games/starfield/src/gameStarfield.pro b/src/games/starfield/src/gameStarfield.pro deleted file mode 100644 index 433b08ae..00000000 --- a/src/games/starfield/src/gameStarfield.pro +++ /dev/null @@ -1,50 +0,0 @@ -#------------------------------------------------- -# -# Project created by QtCreator 2014-11-15T15:36:33 -# -#------------------------------------------------- - - -TARGET = gameStarfield -TEMPLATE = lib - -CONFIG += plugins -CONFIG += dll - -DEFINES += GAMESTARFIELD_LIBRARY - -SOURCES += gamestarfield.cpp \ - starfieldbsainvalidation.cpp \ - starfieldscriptextender.cpp \ - starfielddataarchives.cpp \ - starfieldsavegame.cpp \ - starfieldsavegameinfo.cpp - -HEADERS += gamestarfield.h \ - starfieldbsainvalidation.h \ - starfieldscriptextender.h \ - starfielddataarchives.h \ - starfieldsavegame.h \ - starfieldsavegameinfo.h - -CONFIG(debug, debug|release) { - LIBS += -L"$${OUT_PWD}/../gameGamebryo/debug" - PRE_TARGETDEPS += \ - $$OUT_PWD/../gameGamebryo/debug/gameGamebryo.lib -} else { - LIBS += -L"$${OUT_PWD}/../gameGamebryo/release" - PRE_TARGETDEPS += \ - $$OUT_PWD/../gameGamebryo/release/gameGamebryo.lib -} - -include(../plugin_template.pri) - -INCLUDEPATH += "$${BOOSTPATH}" "$${PWD}/../gamefeatures" "$${PWD}/../gamegamebryo" - -LIBS += -ladvapi32 -lole32 -lgameGamebryo - -OTHER_FILES += \ - gamestarfield.json\ - SConscript \ - CMakeLists.txt - diff --git a/src/games/starfield/src/game_starfield_en.ts b/src/games/starfield/src/game_starfield_en.ts index b6f10d5b..f218dbd0 100644 --- a/src/games/starfield/src/game_starfield_en.ts +++ b/src/games/starfield/src/game_starfield_en.ts @@ -4,14 +4,13 @@ GameStarfield - + Starfield Support Plugin - - Adds support for the game Starfield. -Splash by %1 + + Adds support for the game Starfield. diff --git a/src/games/starfield/src/gamestarfield.cpp b/src/games/starfield/src/gamestarfield.cpp index 76970a0d..9e8ba984 100644 --- a/src/games/starfield/src/gamestarfield.cpp +++ b/src/games/starfield/src/gamestarfield.cpp @@ -61,6 +61,12 @@ void GameStarfield::detectGame() m_MyGamesPath = determineMyGamesPath("Starfield"); } +QString GameStarfield::identifyGamePath() const +{ + QString path = "SOFTWARE\\Microsoft\\Windows\\CurrentVersion\\Uninstall\\Steam App 1716740"; + return findInRegistry(HKEY_LOCAL_MACHINE, path.toStdWString().c_str(), L"InstallLocation"); +} + QList GameStarfield::executables() const { return QList() @@ -144,7 +150,7 @@ QString GameStarfield::steamAPPId() const } QStringList GameStarfield::primaryPlugins() const { - QStringList plugins = {"Starfield.esm", "Constellation.esm", "OldMars.esm", "BlueprintShips-Starfield.esm"}; + QStringList plugins = {"Starfield.esm", "BlueprintShips-Starfield.esm", "Constellation.esm", "OldMars.esm"}; plugins.append(CCPlugins()); @@ -178,7 +184,29 @@ QStringList GameStarfield::DLCPlugins() const QStringList GameStarfield::CCPlugins() const { - return {}; + QStringList plugins = {}; + QFile file(gameDirectory().absoluteFilePath("Starfield.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::LoadOrderMechanism GameStarfield::loadOrderMechanism() const diff --git a/src/games/starfield/src/gamestarfield.h b/src/games/starfield/src/gamestarfield.h index 5ff34cb3..fae0b18e 100644 --- a/src/games/starfield/src/gamestarfield.h +++ b/src/games/starfield/src/gamestarfield.h @@ -49,6 +49,7 @@ public: // IPlugin interface protected: + virtual QString identifyGamePath() const override; std::shared_ptr makeSaveGame(QString filePath) const override; QString savegameExtension() const override; QString savegameSEExtension() const override; diff --git a/src/games/starfield/src/starfieldmoddatachecker.h b/src/games/starfield/src/starfieldmoddatachecker.h index e4752c9c..31136c6d 100644 --- a/src/games/starfield/src/starfieldmoddatachecker.h +++ b/src/games/starfield/src/starfieldmoddatachecker.h @@ -12,7 +12,7 @@ protected: virtual const FileNameSet& possibleFolderNames() const override { static FileNameSet result{ "interface", "meshes", "music", "scripts", "sound", "strings", "textures", - "trees", "video", "materials", "f4se", "distantlod", "asi", "Tools", "MCM", + "trees", "video", "materials", "sfse", "distantlod", "asi", "Tools", "MCM", "distantland", "mits", "dllplugins", "CalienteTools", "shadersfx", "aaf" }; return result; diff --git a/src/games/starfield/src/starfieldsavegame.cpp b/src/games/starfield/src/starfieldsavegame.cpp index 30af4304..a76ee0ac 100644 --- a/src/games/starfield/src/starfieldsavegame.cpp +++ b/src/games/starfield/src/starfieldsavegame.cpp @@ -9,6 +9,7 @@ StarfieldSaveGame::StarfieldSaveGame(QString const &fileName, GameStarfield cons { FileWrapper file(getFilepath(), "BCPS"); + getData(file); FILETIME creationTime; fetchInformationFields(file, m_SaveNumber, m_PCName, m_PCLevel, m_PCLocation, creationTime); @@ -21,22 +22,43 @@ StarfieldSaveGame::StarfieldSaveGame(QString const &fileName, GameStarfield cons setCreationTime(ctime); } -void StarfieldSaveGame::fetchInformationFields( - FileWrapper& file, - unsigned long& saveNumber, - QString& playerName, - unsigned short& playerLevel, - QString& playerLocation, - FILETIME& creationTime) const +void StarfieldSaveGame::getData( + FileWrapper& file) const { - file.skip(); // header size - file.skip(); // header version - file.read(saveNumber); + file.skip(); // header version + file.skip(); // zip start location + file.skip(); // unknown + file.setCompressionType(1); + file.openCompressedData(); // long = start, long = size + // double + // float + // long + // long + // short + return; +} +void StarfieldSaveGame::fetchInformationFields( + FileWrapper& file, + unsigned long& saveNumber, + QString& playerName, + unsigned short& playerLevel, + QString& playerLocation, + FILETIME& creationTime) const +{ + char fileID[12]; // SFS_SAVEGAME + unsigned int headerSize; + unsigned int version; + unsigned char unknown; + file.read(fileID, 12); + headerSize = file.readInt(); + version = file.readInt(); + unknown = file.readChar(); + saveNumber = file.readInt(); file.read(playerName); - unsigned long temp; - file.read(temp); + unsigned int temp; + temp = file.readInt(); playerLevel = static_cast(temp); file.read(playerLocation); @@ -44,39 +66,48 @@ void StarfieldSaveGame::fetchInformationFields( file.read(ignore); // playtime as ascii hh.mm.ss file.read(ignore); // race name (i.e. BretonRace) - file.skip(); // Player gender (0 = male) - file.skip(2); // experience gathered, experience required + unsigned short gender; + gender = file.readShort(); // Player gender (0 = male) + float experience, experienceRequired; + experience = file.readFloat(); + experienceRequired = file.readFloat(); - file.read(creationTime); + unsigned long long time = file.readLong(); + creationTime.dwLowDateTime = (DWORD)time; + creationTime.dwHighDateTime = time >> 32; } std::unique_ptr StarfieldSaveGame::fetchDataFields() const { - FileWrapper file(getFilepath(), "FO4_SAVEGAME"); //10bytes + FileWrapper file(getFilepath(), "BCPS"); //10bytes - { - QString dummyName, dummyLocation; - unsigned short dummyLevel; - unsigned long dummySaveNumber; - FILETIME dummyTime; + getData(file); + FILETIME creationTime; - fetchInformationFields(file, dummySaveNumber, dummyName, dummyLevel, - dummyLocation, dummyTime); - } + { + QString dummyName, dummyLocation; + unsigned short dummyLevel; + unsigned long dummySaveNumber; + FILETIME dummyTime; - QString ignore; - std::unique_ptr fields = std::make_unique(); + fetchInformationFields(file, dummySaveNumber, dummyName, dummyLevel, + dummyLocation, dummyTime); + } - fields->Screenshot = file.readImage(384, true); + QString ignore; + std::unique_ptr fields = std::make_unique(); - uint8_t saveGameVersion = file.readChar(); - file.read(ignore); // game version - file.skip(); // plugin info size + //fields->Screenshot = file.readImage(384, true); - fields->Plugins = file.readPlugins(); - if (saveGameVersion >= 68) { - fields->LightPlugins = file.readLightPlugins(); - } + uint8_t saveGameVersion = file.readChar(12); + file.read(ignore); // game version + file.read(ignore); // game version again? + file.readInt(); // plugin info size - return fields; -} \ No newline at end of file + fields->Plugins = file.readPlugins(); + if (saveGameVersion >= 82) { + fields->LightPlugins = file.readLightPlugins(); + } + + return fields; +} diff --git a/src/games/starfield/src/starfieldsavegame.h b/src/games/starfield/src/starfieldsavegame.h index d8cb45b2..a4159f1b 100644 --- a/src/games/starfield/src/starfieldsavegame.h +++ b/src/games/starfield/src/starfieldsavegame.h @@ -2,7 +2,7 @@ #define STARFIELDSAVEGAME_H #include "gamebryosavegame.h" -#include "zlib.h" +#include #include @@ -16,13 +16,18 @@ public: protected: // Fetch easy-to-access information. + void getData( + FileWrapper& file + ) const; + void fetchInformationFields( - FileWrapper& file, - unsigned long& saveNumber, - QString& playerName, - unsigned short& playerLevel, - QString& playerLocation, - FILETIME& creationTime) const; + FileWrapper& file, + unsigned long& saveNumber, + QString& playerName, + unsigned short& playerLevel, + QString& playerLocation, + FILETIME& creationTime + ) const; std::unique_ptr fetchDataFields() const override; }; diff --git a/src/games/starfield/src/starfieldscriptextender.cpp b/src/games/starfield/src/starfieldscriptextender.cpp index 8fd6477c..25ebcf9a 100644 --- a/src/games/starfield/src/starfieldscriptextender.cpp +++ b/src/games/starfield/src/starfieldscriptextender.cpp @@ -10,10 +10,10 @@ StarfieldScriptExtender::StarfieldScriptExtender(GameGamebryo const *game) : QString StarfieldScriptExtender::BinaryName() const { - return "f4se_loader.exe"; + return "sfse_loader.exe"; } QString StarfieldScriptExtender::PluginPath() const { - return "f4se/plugins"; + return "sfse/plugins"; } diff --git a/src/games/starfield/src/starfieldunmanagedmods.cpp b/src/games/starfield/src/starfieldunmanagedmods.cpp index 14fab23f..ce7dcbbc 100644 --- a/src/games/starfield/src/starfieldunmanagedmods.cpp +++ b/src/games/starfield/src/starfieldunmanagedmods.cpp @@ -43,21 +43,5 @@ QString StarfieldUnmangedMods::displayName(const QString &modName) const { // unlike in earlier games, in fallout 4 the file name doesn't correspond to // the public name - if (modName.compare("dlcrobot", Qt::CaseInsensitive) == 0) { - return "Automatron"; - } else if (modName.compare("dlcworkshop01", Qt::CaseInsensitive) == 0) { - return "Wasteland Workshop"; - } else if (modName.compare("dlccoast", Qt::CaseInsensitive) == 0) { - return "Far Harbor"; - } else if (modName.compare("dlcworkshop02", Qt::CaseInsensitive) == 0) { - return "Contraptions Workshop"; - } else if (modName.compare("dlcworkshop03", Qt::CaseInsensitive) == 0) { - return "Vault-Tec Workshop"; - } else if (modName.compare("dlcnukaworld", Qt::CaseInsensitive) == 0) { - return "Nuka-World"; - } else if (modName.compare("dlcultrahighresolution", Qt::CaseInsensitive) == 0) { - return "Ultra High Resolution Texture Pack"; - } else { - return modName; - } + return modName; } From fcf09b44e5a4dbcb2f86ecd852ff7fd41d436a6a Mon Sep 17 00:00:00 2001 From: Jeremy Rimpo Date: Sun, 3 Sep 2023 23:38:31 -0500 Subject: [PATCH 1300/1544] Remove compression from the read function TODO: Clean up the compressed vs uncompressed code --- src/gamebryo/gamebryosavegame.cpp | 12 +++--------- 1 file changed, 3 insertions(+), 9 deletions(-) diff --git a/src/gamebryo/gamebryosavegame.cpp b/src/gamebryo/gamebryosavegame.cpp index 732b28b7..cbac4221 100644 --- a/src/gamebryo/gamebryosavegame.cpp +++ b/src/gamebryo/gamebryosavegame.cpp @@ -185,15 +185,9 @@ template <> void GamebryoSaveGame::FileWrapper::read(QString &value) void GamebryoSaveGame::FileWrapper::read(void *buff, std::size_t length) { - if (m_CompressionType == 0) { - int read = m_File.read(static_cast(buff), length); - if (read != length) { - throw std::runtime_error("unexpected end of file"); - } - } else if (m_CompressionType == 1 || m_CompressionType == 2) { - readQDataStream(*m_Data, buff, length); - } else { - MOBase::log::warn("Please create an issue on the MO github labeled \"Found unknown Compressed\" with your savefile attached"); + int read = m_File.read(static_cast(buff), length); + if (read != length) { + throw std::runtime_error("unexpected end of file"); } } From 9a03f622b86f9b0c8cb84beff3dca614ea906be1 Mon Sep 17 00:00:00 2001 From: Jeremy Rimpo Date: Sun, 3 Sep 2023 23:39:00 -0500 Subject: [PATCH 1301/1544] [game_skyrimse] Some fixes to deal with new compression code --- src/games/skyrimse/src/skyrimsesavegame.cpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/games/skyrimse/src/skyrimsesavegame.cpp b/src/games/skyrimse/src/skyrimsesavegame.cpp index ca727afe..6cb74464 100644 --- a/src/games/skyrimse/src/skyrimsesavegame.cpp +++ b/src/games/skyrimse/src/skyrimsesavegame.cpp @@ -89,15 +89,15 @@ std::unique_ptr SkyrimSESaveGame::fetchDataFields( // compatibility between LE and SE: // SE has an additional uin16_t for compression // SE uses an alpha channel, whereas LE does not + uint16_t compressionType = 0; if (version == 12) { - uint16_t compressionType; file.read(compressionType); - file.setCompressionType(compressionType); alpha = true; } fields->Screenshot = file.readImage(width, height, 320, alpha); + file.setCompressionType(compressionType); file.openCompressedData(); uint8_t saveGameVersion = file.readChar(); From 58a136e4cdd6523177e4ee879b304cfd1c323cff Mon Sep 17 00:00:00 2001 From: Jeremy Rimpo Date: Sun, 3 Sep 2023 23:39:55 -0500 Subject: [PATCH 1302/1544] [game_starfield] Close file handles, fix issue compression conflicts --- src/games/starfield/src/starfieldsavegame.cpp | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) diff --git a/src/games/starfield/src/starfieldsavegame.cpp b/src/games/starfield/src/starfieldsavegame.cpp index a76ee0ac..f15729c9 100644 --- a/src/games/starfield/src/starfieldsavegame.cpp +++ b/src/games/starfield/src/starfieldsavegame.cpp @@ -12,6 +12,8 @@ StarfieldSaveGame::StarfieldSaveGame(QString const &fileName, GameStarfield cons getData(file); FILETIME creationTime; fetchInformationFields(file, m_SaveNumber, m_PCName, m_PCLevel, m_PCLocation, creationTime); + file.closeCompressedData(); + file.close(); //A file time is a 64-bit value that represents the number of 100-nanosecond //intervals that have elapsed since 12:00 A.M. January 1, 1601 Coordinated Universal Time (UTC). @@ -50,8 +52,8 @@ void StarfieldSaveGame::fetchInformationFields( unsigned int headerSize; unsigned int version; unsigned char unknown; - file.read(fileID, 12); - headerSize = file.readInt(); + //file.read(fileID, 12); + headerSize = file.readInt(12); version = file.readInt(); unknown = file.readChar(); saveNumber = file.readInt(); @@ -108,6 +110,8 @@ std::unique_ptr StarfieldSaveGame::fetchDataFields if (saveGameVersion >= 82) { fields->LightPlugins = file.readLightPlugins(); } + file.closeCompressedData(); + file.close(); return fields; } From 7b7e425e01796c3abd48be37de5a35ea92d82792 Mon Sep 17 00:00:00 2001 From: Jeremy Rimpo Date: Mon, 4 Sep 2023 01:07:22 -0500 Subject: [PATCH 1303/1544] [game_starfield] Add SFSE to automatic executables --- src/games/starfield/src/gamestarfield.cpp | 13 +++++++------ 1 file changed, 7 insertions(+), 6 deletions(-) diff --git a/src/games/starfield/src/gamestarfield.cpp b/src/games/starfield/src/gamestarfield.cpp index 9e8ba984..d6a46242 100644 --- a/src/games/starfield/src/gamestarfield.cpp +++ b/src/games/starfield/src/gamestarfield.cpp @@ -63,15 +63,16 @@ void GameStarfield::detectGame() QString GameStarfield::identifyGamePath() const { - QString path = "SOFTWARE\\Microsoft\\Windows\\CurrentVersion\\Uninstall\\Steam App 1716740"; - return findInRegistry(HKEY_LOCAL_MACHINE, path.toStdWString().c_str(), L"InstallLocation"); + QString path = "SOFTWARE\\Microsoft\\Windows\\CurrentVersion\\Uninstall\\Steam App 1716740"; + return findInRegistry(HKEY_LOCAL_MACHINE, path.toStdWString().c_str(), L"InstallLocation"); } QList GameStarfield::executables() const { return QList() - << ExecutableInfo("Starfield", findInGameFolder(binaryName())) - ; + << ExecutableInfo("SFSE", findInGameFolder(feature()->loaderName())) + << ExecutableInfo("Starfield", findInGameFolder(binaryName())) + ; } QList GameStarfield::executableForcedLoads() const @@ -125,7 +126,7 @@ void GameStarfield::initializeProfile(const QDir &path, ProfileSettings settings } copyToProfile(myGamesPath(), path, "StarfieldPrefs.ini"); - copyToProfile(myGamesPath(), path, "StarfieldCustom.ini"); + copyToProfile(myGamesPath(), path, "StarfieldCustom.ini"); } } @@ -150,7 +151,7 @@ QString GameStarfield::steamAPPId() const } QStringList GameStarfield::primaryPlugins() const { - QStringList plugins = {"Starfield.esm", "BlueprintShips-Starfield.esm", "Constellation.esm", "OldMars.esm"}; + QStringList plugins = { "Starfield.esm", "BlueprintShips-Starfield.esm", "Constellation.esm", "OldMars.esm" }; plugins.append(CCPlugins()); From 2c9dee04e736152ea12f7ebbd17daafcadda6919 Mon Sep 17 00:00:00 2001 From: Jeremy Rimpo Date: Mon, 4 Sep 2023 15:52:03 -0500 Subject: [PATCH 1304/1544] Revert change and cleanup imports --- src/gamebryo/gamebryobsainvalidation.cpp | 1 - src/gamebryo/gamegamebryo.cpp | 2 +- 2 files changed, 1 insertion(+), 2 deletions(-) diff --git a/src/gamebryo/gamebryobsainvalidation.cpp b/src/gamebryo/gamebryobsainvalidation.cpp index 9db2b857..80f0da99 100644 --- a/src/gamebryo/gamebryobsainvalidation.cpp +++ b/src/gamebryo/gamebryobsainvalidation.cpp @@ -3,7 +3,6 @@ #include "dummybsa.h" #include "iplugingame.h" #include "iprofile.h" -#include #include #include #include "registry.h" diff --git a/src/gamebryo/gamegamebryo.cpp b/src/gamebryo/gamegamebryo.cpp index b98c30fb..60c62bd8 100644 --- a/src/gamebryo/gamegamebryo.cpp +++ b/src/gamebryo/gamegamebryo.cpp @@ -311,7 +311,7 @@ std::unique_ptr GameGamebryo::getRegValue(HKEY key, LPCWSTR path, LPCWST DWORD size = 0; HKEY subKey; LONG res = ::RegOpenKeyExW(key, path, 0, - KEY_QUERY_VALUE | KEY_WOW64_32KEY | KEY_WOW64_64KEY, &subKey); + KEY_QUERY_VALUE | KEY_WOW64_32KEY, &subKey); if (res != ERROR_SUCCESS) { return std::unique_ptr(); } From 2b999144c8f81641bd2610587163d9ae5dc1f7d6 Mon Sep 17 00:00:00 2001 From: Jeremy Rimpo Date: Mon, 4 Sep 2023 16:32:35 -0500 Subject: [PATCH 1305/1544] [game_starfield] Game detection and INI edits - Utilize 'archive invalidation' mechanism to make necessary INI edits for texture mods in the game Data directory - Use the Steam library config file to locate the Starfield installation --- src/games/starfield/src/game_starfield_en.ts | 4 +- src/games/starfield/src/gamestarfield.cpp | 29 +- .../src/starfieldbsainvalidation.cpp | 86 +++ .../starfield/src/starfieldbsainvalidation.h | 36 + src/games/starfield/src/vdf_parser.h | 730 ++++++++++++++++++ 5 files changed, 880 insertions(+), 5 deletions(-) create mode 100644 src/games/starfield/src/starfieldbsainvalidation.cpp create mode 100644 src/games/starfield/src/starfieldbsainvalidation.h create mode 100644 src/games/starfield/src/vdf_parser.h diff --git a/src/games/starfield/src/game_starfield_en.ts b/src/games/starfield/src/game_starfield_en.ts index f218dbd0..03ee3836 100644 --- a/src/games/starfield/src/game_starfield_en.ts +++ b/src/games/starfield/src/game_starfield_en.ts @@ -4,12 +4,12 @@ GameStarfield - + Starfield Support Plugin - + Adds support for the game Starfield. diff --git a/src/games/starfield/src/gamestarfield.cpp b/src/games/starfield/src/gamestarfield.cpp index d6a46242..65ce319c 100644 --- a/src/games/starfield/src/gamestarfield.cpp +++ b/src/games/starfield/src/gamestarfield.cpp @@ -6,6 +6,7 @@ #include "starfieldmoddatachecker.h" #include "starfieldmoddatacontent.h" #include "starfieldsavegame.h" +#include "starfieldbsainvalidation.h" #include #include @@ -25,6 +26,7 @@ #include #include "scopeguard.h" +#include "vdf_parser.h" using namespace MOBase; @@ -40,12 +42,13 @@ bool GameStarfield::init(IOrganizer *moInfo) registerFeature(new StarfieldScriptExtender(this)); registerFeature(new StarfieldDataArchives(myGamesPath())); - registerFeature(new GamebryoLocalSavegames(myGamesPath(), "starfieldcustom.ini")); + registerFeature(new GamebryoLocalSavegames(myGamesPath(), "StarfieldCustom.ini")); registerFeature(new StarfieldModDataChecker(this)); registerFeature(new StarfieldModDataContent(this)); registerFeature(new GamebryoSaveGameInfo(this)); registerFeature(new CreationGamePlugins(moInfo)); registerFeature(new StarfieldUnmangedMods(this)); + registerFeature(new StarfieldBSAInvalidation(feature(), this)); return true; } @@ -63,8 +66,28 @@ void GameStarfield::detectGame() QString GameStarfield::identifyGamePath() const { - QString path = "SOFTWARE\\Microsoft\\Windows\\CurrentVersion\\Uninstall\\Steam App 1716740"; - return findInRegistry(HKEY_LOCAL_MACHINE, path.toStdWString().c_str(), L"InstallLocation"); + QString path = "Software\\Valve\\Steam"; + QString steamLocation = findInRegistry(HKEY_CURRENT_USER, path.toStdWString().c_str(), L"SteamPath"); + if (!steamLocation.isEmpty()) { + QString steamLibraryLocation; + QString steamLibraries(steamLocation + "\\" + "config" + "\\" + "libraryfolders.vdf"); + if (QFile(steamLibraries).exists()) { + std::ifstream file(steamLibraries.toStdString()); + auto root = tyti::vdf::read(file); + for (auto child : root.childs) { + tyti::vdf::object *library = child.second.get(); + auto apps = library->childs["apps"]; + if (apps->attribs.contains(steamAPPId().toStdString())) { + steamLibraryLocation = QString::fromStdString(library->attribs["path"]); + break; + } + } + } + if (!steamLibraryLocation.isEmpty()) { + return steamLibraryLocation + "\\" + "steamapps" + "\\" + "Starfield"; + } + } + return ""; } QList GameStarfield::executables() const diff --git a/src/games/starfield/src/starfieldbsainvalidation.cpp b/src/games/starfield/src/starfieldbsainvalidation.cpp new file mode 100644 index 00000000..e23a0160 --- /dev/null +++ b/src/games/starfield/src/starfieldbsainvalidation.cpp @@ -0,0 +1,86 @@ +#include "starfieldbsainvalidation.h" + +#include "dummybsa.h" +#include "iplugingame.h" +#include "iprofile.h" +#include +#include +#include "registry.h" + +StarfieldBSAInvalidation::StarfieldBSAInvalidation(DataArchives *dataArchives, MOBase::IPluginGame const *game) + : GamebryoBSAInvalidation(dataArchives, "StarfieldCustom.ini", game) +{ + m_IniFileName = "StarfieldCustom.ini"; + m_Game = game; +} + +bool StarfieldBSAInvalidation::isInvalidationBSA(const QString& bsaName) +{ + return true; +} + +QString StarfieldBSAInvalidation::invalidationBSAName() const +{ + return ""; +} + +unsigned long StarfieldBSAInvalidation::bsaVersion() const +{ + return 0x68; +} + +bool StarfieldBSAInvalidation::prepareProfile(MOBase::IProfile* profile) +{ + bool dirty = false; + QString basePath + = profile->localSettingsEnabled() + ? profile->absolutePath() + : m_Game->documentsDirectory().absolutePath(); + QString iniFilePath = basePath + "/" + m_IniFileName; + WCHAR setting[MAX_PATH]; + + // write bInvalidateOlderFiles = 1, if needed + if (!::GetPrivateProfileStringW(L"General", L"bEnableMessageOfTheDay", L"1", setting, MAX_PATH, iniFilePath.toStdWString().c_str()) + || wcstol(setting, nullptr, 10) != 0) { + dirty = true; + if (!MOBase::WriteRegistryValue(L"General", L"bEnableMessageOfTheDay", L"0", iniFilePath.toStdWString().c_str())) { + qWarning("failed to override data directory in \"%s\"", qUtf8Printable(m_IniFileName)); + } + } + + QString dataDirName(m_Game->documentsDirectory().absolutePath() + "/" + "Data"); + QString dataDirBackupName(profile->absolutePath() + "/" + "DocsData"); + QDir dataDir(dataDirName); + QDir dataDirBackup(dataDirBackupName); + if (profile->invalidationActive(nullptr)) { + if (!::GetPrivateProfileStringW(L"Display", L"sPhotoModeFolder", L"Data\\Textures\\Photos", setting, MAX_PATH, iniFilePath.toStdWString().c_str()) + || wcscmp(setting, L"Photos") != 0) { + dirty = true; + if (!MOBase::WriteRegistryValue(L"Display", L"sPhotoModeFolder", L"Photos", iniFilePath.toStdWString().c_str())) { + qWarning("failed to redirect photo directory in in \"%s\"", qUtf8Printable(m_IniFileName)); + } + } + if (dataDir.exists()) { + if (dataDirBackup.exists()) { + dataDirBackup.removeRecursively(); + } + dataDir.rename(dataDirName, dataDirBackupName); + } + } else { + if (::GetPrivateProfileStringW(L"Display", L"sPhotoModeFolder", L"Photos", setting, MAX_PATH, iniFilePath.toStdWString().c_str()) + || wcscmp(setting, L"Data\\Textures\\Photos") != 0) { + dirty = true; + if (!MOBase::WriteRegistryValue(L"Display", L"sPhotoModeFolder", L"Data\\Textures\\Photos", iniFilePath.toStdWString().c_str())) { + qWarning("failed to redirect photo directory in \"%s\"", qUtf8Printable(m_IniFileName)); + } + } + if (dataDirBackup.exists()) { + if (dataDir.exists()) { + dataDir.removeRecursively(); + } + dataDir.rename(dataDirName, dataDirBackupName); + } + } + + return dirty; +} \ No newline at end of file diff --git a/src/games/starfield/src/starfieldbsainvalidation.h b/src/games/starfield/src/starfieldbsainvalidation.h new file mode 100644 index 00000000..b530634e --- /dev/null +++ b/src/games/starfield/src/starfieldbsainvalidation.h @@ -0,0 +1,36 @@ +#ifndef STARFIELDBSAINVALIDATION_H +#define STARFIELDBSAINVALIDATION_H + + +#include +#include +#include "gamebryobsainvalidation.h" +#include "starfielddataarchives.h" + +#include + +namespace MOBase { + class IPluginGame; +} + +class StarfieldBSAInvalidation : public GamebryoBSAInvalidation +{ +public: + + StarfieldBSAInvalidation(DataArchives *dataArchives, MOBase::IPluginGame const *game); + virtual bool isInvalidationBSA(const QString& bsaName) override; + virtual bool prepareProfile(MOBase::IProfile* profile) override; + +private: + + virtual QString invalidationBSAName() const override; + virtual unsigned long bsaVersion() const override; + +private: + + QString m_IniFileName; + MOBase::IPluginGame const* m_Game; + +}; + +#endif // STARFIELDBSAINVALIDATION_H diff --git a/src/games/starfield/src/vdf_parser.h b/src/games/starfield/src/vdf_parser.h new file mode 100644 index 00000000..415e49fe --- /dev/null +++ b/src/games/starfield/src/vdf_parser.h @@ -0,0 +1,730 @@ +//MIT License +// +//Copyright(c) 2016 Matthias Moeller +// +//Permission is hereby granted, free of charge, to any person obtaining a copy +//of this software and associated documentation files(the "Software"), to deal +//in the Software without restriction, including without limitation the rights +//to use, copy, modify, merge, publish, distribute, sublicense, and / or sell +//copies of the Software, and to permit persons to whom the Software is +//furnished to do so, subject to the following conditions : +// +//The above copyright notice and this permission notice shall be included in all +//copies or substantial portions of the Software. +// +//THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +//IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +//FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.IN NO EVENT SHALL THE +//AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +//LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +//OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +//SOFTWARE. + +#ifndef __TYTI_STEAM_VDF_PARSER_H__ +#define __TYTI_STEAM_VDF_PARSER_H__ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include + +//for wstring support +#include +#include + +// internal +#include + +//VS < 2015 has only partial C++11 support +#if defined(_MSC_VER) && _MSC_VER < 1900 +#ifndef CONSTEXPR +#define CONSTEXPR +#endif + +#ifndef NOEXCEPT +#define NOEXCEPT +#endif +#else +#ifndef CONSTEXPR +#define CONSTEXPR constexpr +#define TYTI_UNDEF_CONSTEXPR +#endif + +#ifndef NOEXCEPT +#define NOEXCEPT noexcept +#define TYTI_UNDEF_NOEXCEPT +#endif + +#endif + +namespace tyti +{ + namespace vdf + { + namespace detail + { + /////////////////////////////////////////////////////////////////////////// + // Helper functions selecting the right encoding (char/wchar_T) + /////////////////////////////////////////////////////////////////////////// + + template + struct literal_macro_help + { + static CONSTEXPR const char* result(const char* c, const wchar_t*) NOEXCEPT + { + return c; + } + static CONSTEXPR const char result(const char c, const wchar_t) NOEXCEPT + { + return c; + } + }; + + template <> + struct literal_macro_help + { + static CONSTEXPR const wchar_t* result(const char*, const wchar_t* wc) NOEXCEPT + { + return wc; + } + static CONSTEXPR const wchar_t result(const char, const wchar_t wc) NOEXCEPT + { + return wc; + } + }; +#define TYTI_L(type, text) vdf::detail::literal_macro_help::result(text, L##text) + + inline std::string string_converter(const std::string& w) NOEXCEPT + { + return w; + } + + // utility wrapper to adapt locale-bound facets for wstring/wbuffer convert + // from cppreference + template + struct deletable_facet : Facet + { + template + deletable_facet(Args &&... args) : Facet(std::forward(args)...) {} + ~deletable_facet() {} + }; + + inline std::string string_converter(const std::wstring& w) //todo: use us-locale + { + std::wstring_convert>> conv1; + return conv1.to_bytes(w); + } + + /////////////////////////////////////////////////////////////////////////// + // Writer helper functions + /////////////////////////////////////////////////////////////////////////// + + template + class tabs + { + const size_t t; + + public: + explicit CONSTEXPR tabs(size_t i) NOEXCEPT : t(i) {} + std::basic_string print() const { return std::basic_string(t, TYTI_L(charT, '\t')); } + inline CONSTEXPR tabs operator+(size_t i) const NOEXCEPT + { + return tabs(t + i); + } + }; + + template + oStreamT& operator<<(oStreamT& s, const tabs t) + { + s << t.print(); + return s; + } + } // end namespace detail + + /////////////////////////////////////////////////////////////////////////// + // Interface + /////////////////////////////////////////////////////////////////////////// + + /// custom objects and their corresponding write functions + + /// basic object node. Every object has a name and can contains attributes saved as key_value pairs or childrens + template + struct basic_object + { + typedef CharT char_type; + std::basic_string name; + std::unordered_map, std::basic_string> attribs; + std::unordered_map, std::shared_ptr>> childs; + + void add_attribute(std::basic_string key, std::basic_string value) + { + attribs.emplace(std::move(key), std::move(value)); + } + void add_child(std::unique_ptr> child) + { + std::shared_ptr> obj{ child.release() }; + childs.emplace(obj->name, obj); + } + void set_name(std::basic_string n) + { + name = std::move(n); + } + }; + + template + struct basic_multikey_object + { + typedef CharT char_type; + std::basic_string name; + std::unordered_multimap, std::basic_string> attribs; + std::unordered_multimap, std::shared_ptr>> childs; + + void add_attribute(std::basic_string key, std::basic_string value) + { + attribs.emplace(std::move(key), std::move(value)); + } + void add_child(std::unique_ptr> child) + { + std::shared_ptr> obj{ child.release() }; + childs.emplace(obj->name, obj); + } + void set_name(std::basic_string n) + { + name = std::move(n); + } + }; + + typedef basic_object object; + typedef basic_object wobject; + typedef basic_multikey_object multikey_object; + typedef basic_multikey_object wmultikey_object; + + struct Options + { + bool strip_escape_symbols; + bool ignore_all_platform_conditionals; + bool ignore_includes; + + Options() : strip_escape_symbols(true), ignore_all_platform_conditionals(false), ignore_includes(false) {} + }; + + //forward decls + //forward decl + template + OutputT read(iStreamT& inStream, const Options& opt = Options{}); + + /** \brief writes given object tree in vdf format to given stream. + Output is prettyfied, using tabs + */ + template + void write(oStreamT& s, const T& r, + const detail::tabs tab = detail::tabs(0)) + { + typedef typename oStreamT::char_type charT; + using namespace detail; + s << tab << TYTI_L(charT, '"') << r.name << TYTI_L(charT, "\"\n") << tab << TYTI_L(charT, "{\n"); + for (const auto& i : r.attribs) + s << tab + 1 << TYTI_L(charT, '"') << i.first << TYTI_L(charT, "\"\t\t\"") << i.second << TYTI_L(charT, "\"\n"); + for (const auto& i : r.childs) + if (i.second) + write(s, *i.second, tab + 1); + s << tab << TYTI_L(charT, "}\n"); + } + + namespace detail + { + template + std::basic_string read_file(iStreamT& inStream) + { + // cache the file + typedef typename iStreamT::char_type charT; + std::basic_string str; + inStream.seekg(0, std::ios::end); + str.resize(static_cast(inStream.tellg())); + if (str.empty()) + return str; + + inStream.seekg(0, std::ios::beg); + inStream.read(&str[0], str.size()); + return str; + } + + /** \brief Read VDF formatted sequences defined by the range [first, last). + If the file is mailformatted, parser will try to read it until it can. + @param first begin iterator + @param end end iterator + @param exclude_files list of files which cant be included anymore. + prevents circular includes + + can thow: + - "std::runtime_error" if a parsing error occured + - "std::bad_alloc" if not enough memory coup be allocated + */ + template + std::vector> read_internal(IterT first, const IterT last, + std::unordered_set::value_type>>& exclude_files, + const Options& opt) + { + static_assert(std::is_default_constructible::value, + "Output Type must be default constructible (provide constructor without arguments)"); + static_assert(std::is_move_constructible::value, + "Output Type must be move constructible"); + + typedef typename std::iterator_traits::value_type charT; + + const std::basic_string comment_end_str = TYTI_L(charT, "*/"); + const std::basic_string whitespaces = TYTI_L(charT, " \n\v\f\r\t"); + +#ifdef WIN32 + std::function&)> is_platform_str = [](const std::basic_string& in) { + return in == TYTI_L(charT, "$WIN32") || in == TYTI_L(charT, "$WINDOWS"); + }; +#elif __APPLE__ + // WIN32 stands for pc in general + std::function&)> is_platform_str = [](const std::basic_string& in) { + return in == TYTI_L(charT, "$WIN32") || in == TYTI_L(charT, "$POSIX") || in == TYTI_L(charT, "$OSX"); + }; + +#elif __linux__ + // WIN32 stands for pc in general + std::function&)> is_platform_str = [](const std::basic_string& in) { + return in == TYTI_L(charT, "$WIN32") || in == TYTI_L(charT, "$POSIX") || in == TYTI_L(charT, "$LINUX"); + }; +#else + std::function&)> is_platform_str = [](const std::basic_string& in) { + return false; + }; +#endif + + if (opt.ignore_all_platform_conditionals) + is_platform_str = [](const std::basic_string&) { + return false; + }; + + // function for skipping a comment block + // iter: iterator poition to the position after a '/' + auto skip_comments = [&comment_end_str](IterT iter, const IterT& last) -> IterT { + ++iter; + if (iter != last) + { + if (*iter == TYTI_L(charT, '/')) + { + // line comment, skip whole line + iter = std::find(iter + 1, last, TYTI_L(charT, '\n')); + } + + if (*iter == '*') + { + // block comment, skip until next occurance of "*\" + iter = std::search(iter + 1, last, std::begin(comment_end_str), std::end(comment_end_str)); + iter += 2; + } + } + return iter; + }; + + auto end_quote = [](IterT iter, const IterT& last) -> IterT { + const auto begin = iter; + auto last_esc = iter; + do + { + ++iter; + iter = std::find(iter, last, TYTI_L(charT, '\"')); + if (iter == last) + break; + + last_esc = std::prev(iter); + while (last_esc != begin && *last_esc == '\\') + --last_esc; + } while (!(std::distance(last_esc, iter) % 2)); + if (iter == last) + throw std::runtime_error{ "quote was opened but not closed." }; + return iter; + }; + + auto end_word = [&whitespaces](IterT iter, const IterT& last) -> IterT { + const auto begin = iter; + auto last_esc = iter; + do + { + ++iter; + iter = std::find_first_of(iter, last, std::begin(whitespaces), std::end(whitespaces)); + if (iter == last) + break; + + last_esc = std::prev(iter); + while (last_esc != begin && *last_esc == '\\') + --last_esc; + } while (!(std::distance(last_esc, iter) % 2)); + //if (iter == last) + // throw std::runtime_error{ "word wasnt properly ended" }; + return iter; + }; + + auto skip_whitespaces = [&whitespaces](IterT iter, const IterT& last) -> IterT { + iter = std::find_if_not(iter, last, [&whitespaces](charT c) { + // return true if whitespace + return std::any_of(std::begin(whitespaces), std::end(whitespaces), [c](charT pc) { return pc == c; }); + }); + return iter; + }; + + std::function&)> strip_escape_symbols = [](std::basic_string& s) { + auto quote_searcher = [&s](size_t pos) { return s.find(TYTI_L(charT, "\\\""), pos); }; + auto p = quote_searcher(0); + while (p != s.npos) + { + s.replace(p, 2, TYTI_L(charT, "\"")); + p = quote_searcher(p); + } + auto searcher = [&s](size_t pos) { return s.find(TYTI_L(charT, "\\\\"), pos); }; + p = searcher(0); + while (p != s.npos) + { + s.replace(p, 2, TYTI_L(charT, "\\")); + p = searcher(p); + } + }; + + if (!opt.strip_escape_symbols) + strip_escape_symbols = [](std::basic_string&) {}; + + auto conditional_fullfilled = [&skip_whitespaces, &is_platform_str](IterT& iter, const IterT& last) { + iter = skip_whitespaces(iter, last); + if (*iter == '[') + { + ++iter; + const auto end = std::find(iter, last, ']'); + const bool negate = *iter == '!'; + if (negate) + ++iter; + auto conditional = std::basic_string(iter, end); + + const bool is_platform = is_platform_str(conditional); + iter = end + 1; + + return static_cast(is_platform ^ negate); + } + return true; + }; + + //read header + // first, quoted name + std::unique_ptr curObj = nullptr; + std::vector> roots; + std::stack> lvls; + auto curIter = first; + + while (curIter != last && *curIter != '\0') + { + //find first starting attrib/child, or ending + curIter = skip_whitespaces(curIter, last); + if (curIter == last || *curIter == '\0') + break; + if (*curIter == TYTI_L(charT, '/')) + { + curIter = skip_comments(curIter, last); + } + else if (*curIter != TYTI_L(charT, '}')) + { + + // get key + const auto keyEnd = (*curIter == TYTI_L(charT, '\"')) ? end_quote(curIter, last) : end_word(curIter, last); + if (*curIter == TYTI_L(charT, '\"')) + ++curIter; + std::basic_string key(curIter, keyEnd); + strip_escape_symbols(key); + curIter = keyEnd + ((*keyEnd == TYTI_L(charT, '\"')) ? 1 : 0); + + curIter = skip_whitespaces(curIter, last); + + auto conditional = conditional_fullfilled(curIter, last); + if (!conditional) + continue; + + while (*curIter == TYTI_L(charT, '/')) + { + + curIter = skip_comments(curIter, last); + if (curIter == last || *curIter == '}') + throw std::runtime_error{ "key declared, but no value" }; + curIter = skip_whitespaces(curIter, last); + if (curIter == last || *curIter == '}') + throw std::runtime_error{ "key declared, but no value" }; + } + // get value + if (*curIter != '{') + { + const auto valueEnd = (*curIter == TYTI_L(charT, '\"')) ? end_quote(curIter, last) : end_word(curIter, last); + if (*curIter == TYTI_L(charT, '\"')) + ++curIter; + + auto value = std::basic_string(curIter, valueEnd); + strip_escape_symbols(value); + curIter = valueEnd + ((*valueEnd == TYTI_L(charT, '\"')) ? 1 : 0); + + auto conditional = conditional_fullfilled(curIter, last); + if (!conditional) + continue; + + // process value + if (key != TYTI_L(charT, "#include") && key != TYTI_L(charT, "#base")) + { + if (curObj) + { + curObj->add_attribute(std::move(key), std::move(value)); + } + else + { + throw std::runtime_error{ "unexpected key without object" }; + } + } + else + { + if (!opt.ignore_includes && exclude_files.find(value) == exclude_files.end()) + { + exclude_files.insert(value); + std::basic_ifstream i(detail::string_converter(value)); + auto str = read_file(i); + auto file_objs = read_internal(str.begin(), str.end(), exclude_files, opt); + for (auto& n : file_objs) + { + if (curObj) + curObj->add_child(std::move(n)); + else + roots.push_back(std::move(n)); + } + exclude_files.erase(value); + } + } + } + else if (*curIter == '{') + { + if (curObj) + lvls.push(std::move(curObj)); + curObj = std::make_unique(); + curObj->set_name(std::move(key)); + ++curIter; + } + } + //end of new object + else if (curObj && *curIter == TYTI_L(charT, '}')) + { + if (!lvls.empty()) + { + //get object before + std::unique_ptr prev{ std::move(lvls.top()) }; + lvls.pop(); + + // add finished obj to obj before and release it from processing + prev->add_child(std::move(curObj)); + curObj = std::move(prev); + } + else + { + roots.push_back(std::move(curObj)); + curObj.reset(); + } + ++curIter; + } + else + { + throw std::runtime_error{ "unexpected '}'" }; + } + } + if (curObj != nullptr || !lvls.empty()) + { + throw std::runtime_error{ "object is not closed with '}'" }; + } + + return roots; + } + + } // namespace detail + + /** \brief Read VDF formatted sequences defined by the range [first, last). + If the file is mailformatted, parser will try to read it until it can. + @param first begin iterator + @param end end iterator + + can thow: + - "std::runtime_error" if a parsing error occured + - "std::bad_alloc" if not enough memory coup be allocated + */ + template + OutputT read(IterT first, const IterT last, const Options& opt = Options{}) + { + auto exclude_files = std::unordered_set::value_type>>{}; + auto roots = detail::read_internal(first, last, exclude_files, opt); + + OutputT result; + if (roots.size() > 1) + { + for (auto& i : roots) + result.add_child(std::move(i)); + } + else if (roots.size() == 1) + result = std::move(*roots[0]); + + return result; + } + + /** \brief Read VDF formatted sequences defined by the range [first, last). + If the file is mailformatted, parser will try to read it until it can. + @param first begin iterator + @param end end iterator + @param ec output bool. 0 if ok, otherwise, holds an system error code + + Possible error codes: + std::errc::protocol_error: file is mailformatted + std::errc::not_enough_memory: not enough space + std::errc::invalid_argument: iterators throws e.g. out of range + */ + template + OutputT read(IterT first, IterT last, std::error_code& ec, const Options& opt = Options{}) NOEXCEPT + + { + ec.clear(); + OutputT r{}; + try + { + r = read(first, last, opt); + } + catch (std::runtime_error&) + { + ec = std::make_error_code(std::errc::protocol_error); + } + catch (std::bad_alloc&) + { + ec = std::make_error_code(std::errc::not_enough_memory); + } + catch (...) + { + ec = std::make_error_code(std::errc::invalid_argument); + } + return r; + } + + /** \brief Read VDF formatted sequences defined by the range [first, last). + If the file is mailformatted, parser will try to read it until it can. + @param first begin iterator + @param end end iterator + @param ok output bool. true, if parser successed, false, if parser failed + */ + template + OutputT read(IterT first, const IterT last, bool* ok, const Options& opt = Options{}) NOEXCEPT + { + std::error_code ec; + auto r = read(first, last, ec, opt); + if (ok) + *ok = !ec; + return r; + } + + template + inline auto read(IterT first, const IterT last, bool* ok, const Options& opt = Options{}) NOEXCEPT -> basic_object::value_type> + { + return read::value_type>>(first, last, ok, opt); + } + + template + inline auto read(IterT first, IterT last, std::error_code& ec, const Options& opt = Options{}) NOEXCEPT + -> basic_object::value_type> + { + return read::value_type>>(first, last, ec, opt); + } + + template + inline auto read(IterT first, const IterT last, const Options& opt = Options{}) + -> basic_object::value_type> + { + return read::value_type>>(first, last, opt); + } + + /** \brief Loads a stream (e.g. filestream) into the memory and parses the vdf formatted data. + throws "std::bad_alloc" if file buffer could not be allocated + */ + template + OutputT read(iStreamT& inStream, std::error_code& ec, const Options& opt = Options{}) + { + // cache the file + typedef typename iStreamT::char_type charT; + std::basic_string str = detail::read_file(inStream); + + // parse it + return read(str.begin(), str.end(), ec, opt); + } + + template + inline basic_object read(iStreamT& inStream, std::error_code& ec, const Options& opt = Options{}) + { + return read>(inStream, ec, opt); + } + + /** \brief Loads a stream (e.g. filestream) into the memory and parses the vdf formatted data. + throws "std::bad_alloc" if file buffer could not be allocated + ok == false, if a parsing error occured + */ + template + OutputT read(iStreamT& inStream, bool* ok, const Options& opt = Options{}) + { + std::error_code ec; + const auto r = read(inStream, ec, opt); + if (ok) + *ok = !ec; + return r; + } + + template + inline basic_object read(iStreamT& inStream, bool* ok, const Options& opt = Options{}) + { + return read>(inStream, ok, opt); + } + + /** \brief Loads a stream (e.g. filestream) into the memory and parses the vdf formatted data. + throws "std::bad_alloc" if file buffer could not be allocated + throws "std::runtime_error" if a parsing error occured + */ + template + OutputT read(iStreamT& inStream, const Options& opt) + { + + // cache the file + typedef typename iStreamT::char_type charT; + std::basic_string str = detail::read_file(inStream); + // parse it + return read(str.begin(), str.end(), opt); + } + + template + inline basic_object read(iStreamT& inStream, const Options& opt = Options{}) + { + return read>(inStream, opt); + } + + } // namespace vdf +} // namespace tyti +#ifndef TYTI_NO_L_UNDEF +#undef TYTI_L +#endif + +#ifdef TYTI_UNDEF_CONSTEXPR +#undef CONSTEXPR +#undef TYTI_NO_L_UNDEF +#endif + +#ifdef TYTI_UNDEF_NOTHROW +#undef NOTHROW +#undef TYTI_UNDEF_NOTHROW +#endif + +#endif //__TYTI_STEAM_VDF_PARSER_H__ \ No newline at end of file From 33e35c401b9c8dd552bf2b4c7310d1596dbf37b9 Mon Sep 17 00:00:00 2001 From: Jeremy Rimpo Date: Mon, 4 Sep 2023 18:02:55 -0500 Subject: [PATCH 1306/1544] Preliminary secondary data directory support --- src/gamebryo/gamegamebryo.cpp | 6 ++++++ src/gamebryo/gamegamebryo.h | 1 + 2 files changed, 7 insertions(+) diff --git a/src/gamebryo/gamegamebryo.cpp b/src/gamebryo/gamegamebryo.cpp index 60c62bd8..eb8b82ff 100644 --- a/src/gamebryo/gamegamebryo.cpp +++ b/src/gamebryo/gamegamebryo.cpp @@ -14,6 +14,7 @@ #include #include +#include #include #include #include @@ -71,6 +72,11 @@ QDir GameGamebryo::dataDirectory() const return gameDirectory().absoluteFilePath("data"); } +QList GameGamebryo::secondaryDataDirectories() const +{ + return QList(); +} + void GameGamebryo::setGamePath(const QString &path) { m_GamePath = path; diff --git a/src/gamebryo/gamegamebryo.h b/src/gamebryo/gamegamebryo.h index e126c29f..53a2cede 100644 --- a/src/gamebryo/gamegamebryo.h +++ b/src/gamebryo/gamegamebryo.h @@ -58,6 +58,7 @@ public: // IPluginGame interface virtual QIcon gameIcon() const override; virtual QDir gameDirectory() const override; virtual QDir dataDirectory() const override; + virtual QList secondaryDataDirectories() const override; virtual void setGamePath(const QString &path) override; virtual QDir documentsDirectory() const override; virtual QDir savesDirectory() const override; From 49219e7e6595d144725d6748ea49f024a8936c5b Mon Sep 17 00:00:00 2001 From: Jeremy Rimpo Date: Mon, 4 Sep 2023 18:25:36 -0500 Subject: [PATCH 1307/1544] [game_starfield] Updating data directories --- src/games/starfield/src/game_starfield_en.ts | 4 ++-- src/games/starfield/src/gamestarfield.cpp | 12 ++++++++++++ src/games/starfield/src/gamestarfield.h | 2 ++ 3 files changed, 16 insertions(+), 2 deletions(-) diff --git a/src/games/starfield/src/game_starfield_en.ts b/src/games/starfield/src/game_starfield_en.ts index 03ee3836..649ba0a9 100644 --- a/src/games/starfield/src/game_starfield_en.ts +++ b/src/games/starfield/src/game_starfield_en.ts @@ -4,12 +4,12 @@ GameStarfield - + Starfield Support Plugin - + Adds support for the game Starfield. diff --git a/src/games/starfield/src/gamestarfield.cpp b/src/games/starfield/src/gamestarfield.cpp index 65ce319c..569e9fae 100644 --- a/src/games/starfield/src/gamestarfield.cpp +++ b/src/games/starfield/src/gamestarfield.cpp @@ -90,6 +90,18 @@ QString GameStarfield::identifyGamePath() const return ""; } +QDir GameStarfield::dataDirectory() const +{ + return documentsDirectory().absoluteFilePath("Data"); +} + +QList GameStarfield::secondaryDataDirectories() const +{ + QList directories; + directories.append(gameDirectory().absoluteFilePath("Data")); + return directories; +} + QList GameStarfield::executables() const { return QList() diff --git a/src/games/starfield/src/gamestarfield.h b/src/games/starfield/src/gamestarfield.h index fae0b18e..6c8c222c 100644 --- a/src/games/starfield/src/gamestarfield.h +++ b/src/games/starfield/src/gamestarfield.h @@ -23,6 +23,8 @@ public: // IPluginGame interface virtual QString gameName() const override; virtual void detectGame() override; + virtual QDir dataDirectory() const override; + virtual QList secondaryDataDirectories() const override; virtual QList executables() const override; virtual QList executableForcedLoads() const override; virtual void initializeProfile(const QDir &path, ProfileSettings settings) const override; From a4f914a900577025ccc8853b54b1c2d8c26da969 Mon Sep 17 00:00:00 2001 From: Jeremy Rimpo Date: Mon, 4 Sep 2023 19:39:39 -0500 Subject: [PATCH 1308/1544] [game_starfield] Use map so we can set an origin name --- src/games/starfield/src/gamestarfield.cpp | 8 +++----- src/games/starfield/src/gamestarfield.h | 2 +- 2 files changed, 4 insertions(+), 6 deletions(-) diff --git a/src/games/starfield/src/gamestarfield.cpp b/src/games/starfield/src/gamestarfield.cpp index 569e9fae..dd9b9a68 100644 --- a/src/games/starfield/src/gamestarfield.cpp +++ b/src/games/starfield/src/gamestarfield.cpp @@ -6,7 +6,6 @@ #include "starfieldmoddatachecker.h" #include "starfieldmoddatacontent.h" #include "starfieldsavegame.h" -#include "starfieldbsainvalidation.h" #include #include @@ -48,7 +47,6 @@ bool GameStarfield::init(IOrganizer *moInfo) registerFeature(new GamebryoSaveGameInfo(this)); registerFeature(new CreationGamePlugins(moInfo)); registerFeature(new StarfieldUnmangedMods(this)); - registerFeature(new StarfieldBSAInvalidation(feature(), this)); return true; } @@ -95,10 +93,10 @@ QDir GameStarfield::dataDirectory() const return documentsDirectory().absoluteFilePath("Data"); } -QList GameStarfield::secondaryDataDirectories() const +QMap GameStarfield::secondaryDataDirectories() const { - QList directories; - directories.append(gameDirectory().absoluteFilePath("Data")); + QMap directories; + directories.insert("game_data", gameDirectory().absoluteFilePath("Data")); return directories; } diff --git a/src/games/starfield/src/gamestarfield.h b/src/games/starfield/src/gamestarfield.h index 6c8c222c..1c36adde 100644 --- a/src/games/starfield/src/gamestarfield.h +++ b/src/games/starfield/src/gamestarfield.h @@ -24,7 +24,7 @@ public: // IPluginGame interface virtual QString gameName() const override; virtual void detectGame() override; virtual QDir dataDirectory() const override; - virtual QList secondaryDataDirectories() const override; + virtual QMap secondaryDataDirectories() const override; virtual QList executables() const override; virtual QList executableForcedLoads() const override; virtual void initializeProfile(const QDir &path, ProfileSettings settings) const override; From 7d39dced61f78076b6fe49cb75cac386e5c5e14b Mon Sep 17 00:00:00 2001 From: Jeremy Rimpo Date: Mon, 4 Sep 2023 19:39:39 -0500 Subject: [PATCH 1309/1544] Use map so we can set an origin name --- src/gamebryo/gamegamebryo.cpp | 4 ++-- src/gamebryo/gamegamebryo.h | 2 +- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/src/gamebryo/gamegamebryo.cpp b/src/gamebryo/gamegamebryo.cpp index eb8b82ff..e9ec6cb0 100644 --- a/src/gamebryo/gamegamebryo.cpp +++ b/src/gamebryo/gamegamebryo.cpp @@ -72,9 +72,9 @@ QDir GameGamebryo::dataDirectory() const return gameDirectory().absoluteFilePath("data"); } -QList GameGamebryo::secondaryDataDirectories() const +QMap GameGamebryo::secondaryDataDirectories() const { - return QList(); + return QMap(); } void GameGamebryo::setGamePath(const QString &path) diff --git a/src/gamebryo/gamegamebryo.h b/src/gamebryo/gamegamebryo.h index 53a2cede..47423af7 100644 --- a/src/gamebryo/gamegamebryo.h +++ b/src/gamebryo/gamegamebryo.h @@ -58,7 +58,7 @@ public: // IPluginGame interface virtual QIcon gameIcon() const override; virtual QDir gameDirectory() const override; virtual QDir dataDirectory() const override; - virtual QList secondaryDataDirectories() const override; + virtual QMap secondaryDataDirectories() const override; virtual void setGamePath(const QString &path) override; virtual QDir documentsDirectory() const override; virtual QDir savesDirectory() const override; From 9c29a2910e286e06147434854f8c9cb1129c7a71 Mon Sep 17 00:00:00 2001 From: Jeremy Rimpo Date: Mon, 4 Sep 2023 22:20:00 -0500 Subject: [PATCH 1310/1544] [game_starfield] Restore archive invalidation and fix game detection --- src/games/starfield/src/gamestarfield.cpp | 6 ++- .../src/starfieldbsainvalidation.cpp | 48 ++++++++----------- 2 files changed, 24 insertions(+), 30 deletions(-) diff --git a/src/games/starfield/src/gamestarfield.cpp b/src/games/starfield/src/gamestarfield.cpp index dd9b9a68..d791e0c6 100644 --- a/src/games/starfield/src/gamestarfield.cpp +++ b/src/games/starfield/src/gamestarfield.cpp @@ -6,6 +6,7 @@ #include "starfieldmoddatachecker.h" #include "starfieldmoddatacontent.h" #include "starfieldsavegame.h" +#include "starfieldbsainvalidation.h" #include #include @@ -47,6 +48,7 @@ bool GameStarfield::init(IOrganizer *moInfo) registerFeature(new GamebryoSaveGameInfo(this)); registerFeature(new CreationGamePlugins(moInfo)); registerFeature(new StarfieldUnmangedMods(this)); + registerFeature(new StarfieldBSAInvalidation(feature(), this)); return true; } @@ -82,7 +84,9 @@ QString GameStarfield::identifyGamePath() const } } if (!steamLibraryLocation.isEmpty()) { - return steamLibraryLocation + "\\" + "steamapps" + "\\" + "Starfield"; + QString gameLocation = steamLibraryLocation + "\\" + "steamapps" + "\\" + "common" + "\\" + "Starfield"; + if (QDir(gameLocation).exists() && QFile(gameLocation + "\\" + "Starfield.exe").exists()) + return gameLocation; } } return ""; diff --git a/src/games/starfield/src/starfieldbsainvalidation.cpp b/src/games/starfield/src/starfieldbsainvalidation.cpp index e23a0160..7985ca88 100644 --- a/src/games/starfield/src/starfieldbsainvalidation.cpp +++ b/src/games/starfield/src/starfieldbsainvalidation.cpp @@ -39,46 +39,36 @@ bool StarfieldBSAInvalidation::prepareProfile(MOBase::IProfile* profile) QString iniFilePath = basePath + "/" + m_IniFileName; WCHAR setting[MAX_PATH]; - // write bInvalidateOlderFiles = 1, if needed - if (!::GetPrivateProfileStringW(L"General", L"bEnableMessageOfTheDay", L"1", setting, MAX_PATH, iniFilePath.toStdWString().c_str()) - || wcstol(setting, nullptr, 10) != 0) { - dirty = true; - if (!MOBase::WriteRegistryValue(L"General", L"bEnableMessageOfTheDay", L"0", iniFilePath.toStdWString().c_str())) { - qWarning("failed to override data directory in \"%s\"", qUtf8Printable(m_IniFileName)); - } - } - - QString dataDirName(m_Game->documentsDirectory().absolutePath() + "/" + "Data"); - QString dataDirBackupName(profile->absolutePath() + "/" + "DocsData"); - QDir dataDir(dataDirName); - QDir dataDirBackup(dataDirBackupName); if (profile->invalidationActive(nullptr)) { - if (!::GetPrivateProfileStringW(L"Display", L"sPhotoModeFolder", L"Data\\Textures\\Photos", setting, MAX_PATH, iniFilePath.toStdWString().c_str()) - || wcscmp(setting, L"Photos") != 0) { + // write bInvalidateOlderFiles = 1, if needed + if (!::GetPrivateProfileStringW(L"Archive", L"bInvalidateOlderFiles", L"0", setting, MAX_PATH, iniFilePath.toStdWString().c_str()) + || wcstol(setting, nullptr, 10) != 1) { dirty = true; - if (!MOBase::WriteRegistryValue(L"Display", L"sPhotoModeFolder", L"Photos", iniFilePath.toStdWString().c_str())) { - qWarning("failed to redirect photo directory in in \"%s\"", qUtf8Printable(m_IniFileName)); + if (!MOBase::WriteRegistryValue(L"Archive", L"bInvalidateOlderFiles", L"1", iniFilePath.toStdWString().c_str())) { + qWarning("failed to override data directory in \"%s\"", qUtf8Printable(m_IniFileName)); } } - if (dataDir.exists()) { - if (dataDirBackup.exists()) { - dataDirBackup.removeRecursively(); + if (!::GetPrivateProfileStringW(L"Archive", L"sResourceDataDirsFinal", L"STRINGS\\", setting, MAX_PATH, iniFilePath.toStdWString().c_str()) + || wcscmp(setting, L"") != 0) { + dirty = true; + if (!MOBase::WriteRegistryValue(L"Archive", L"sResourceDataDirsFinal", L"", iniFilePath.toStdWString().c_str())) { + qWarning("failed to override data directory in \"%s\"", qUtf8Printable(m_IniFileName)); } - dataDir.rename(dataDirName, dataDirBackupName); } } else { - if (::GetPrivateProfileStringW(L"Display", L"sPhotoModeFolder", L"Photos", setting, MAX_PATH, iniFilePath.toStdWString().c_str()) - || wcscmp(setting, L"Data\\Textures\\Photos") != 0) { + if (!::GetPrivateProfileStringW(L"Archive", L"bInvalidateOlderFiles", L"1", setting, MAX_PATH, iniFilePath.toStdWString().c_str()) + || wcstol(setting, nullptr, 10) != 0) { dirty = true; - if (!MOBase::WriteRegistryValue(L"Display", L"sPhotoModeFolder", L"Data\\Textures\\Photos", iniFilePath.toStdWString().c_str())) { - qWarning("failed to redirect photo directory in \"%s\"", qUtf8Printable(m_IniFileName)); + if (!MOBase::WriteRegistryValue(L"Archive", L"bInvalidateOlderFiles", L"0", iniFilePath.toStdWString().c_str())) { + qWarning("failed to override data directory in \"%s\"", qUtf8Printable(m_IniFileName)); } } - if (dataDirBackup.exists()) { - if (dataDir.exists()) { - dataDir.removeRecursively(); + if (!::GetPrivateProfileStringW(L"Archive", L"sResourceDataDirsFinal", L"", setting, MAX_PATH, iniFilePath.toStdWString().c_str()) + || wcscmp(setting, L"STRINGS\\") != 0) { + dirty = true; + if (!MOBase::WriteRegistryValue(L"Archive", L"sResourceDataDirsFinal", L"STRINGS\\", iniFilePath.toStdWString().c_str())) { + qWarning("failed to override data directory in \"%s\"", qUtf8Printable(m_IniFileName)); } - dataDir.rename(dataDirName, dataDirBackupName); } } From 01d7b0a49e7d786a4159b407985d596781975295 Mon Sep 17 00:00:00 2001 From: Jeremy Rimpo Date: Tue, 5 Sep 2023 00:09:37 -0500 Subject: [PATCH 1311/1544] [game_starfield] Update translation files --- src/games/starfield/src/game_starfield_en.ts | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/games/starfield/src/game_starfield_en.ts b/src/games/starfield/src/game_starfield_en.ts index 649ba0a9..0cffb90c 100644 --- a/src/games/starfield/src/game_starfield_en.ts +++ b/src/games/starfield/src/game_starfield_en.ts @@ -4,12 +4,12 @@ GameStarfield - + Starfield Support Plugin - + Adds support for the game Starfield. From 62c1d46ffa8aeb9fd0dc029380ee85a26e84cf1d Mon Sep 17 00:00:00 2001 From: Jeremy Rimpo Date: Tue, 5 Sep 2023 00:09:39 -0500 Subject: [PATCH 1312/1544] Update translation files --- src/gamebryo/game_gamebryo_en.ts | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/src/gamebryo/game_gamebryo_en.ts b/src/gamebryo/game_gamebryo_en.ts index 7ee873eb..d875a0fc 100644 --- a/src/gamebryo/game_gamebryo_en.ts +++ b/src/gamebryo/game_gamebryo_en.ts @@ -136,27 +136,27 @@ - + %1, #%2, Level %3, %4 - + failed to open %1 - + wrong file format - expected %1 got %2 - + failed to query registry path (preflight): %1 - + failed to query registry path (read): %1 From 0c26bc09548d6c67a4d952bfe973c79d49be8f71 Mon Sep 17 00:00:00 2001 From: Jeremy Rimpo Date: Tue, 5 Sep 2023 03:16:20 -0500 Subject: [PATCH 1313/1544] [game_starfield] Don't revert archive invalidation INI settings * Just write the correct settings when enabled * It's confusing people * It's probably best this way --- .../starfield/src/starfieldbsainvalidation.cpp | 15 --------------- 1 file changed, 15 deletions(-) diff --git a/src/games/starfield/src/starfieldbsainvalidation.cpp b/src/games/starfield/src/starfieldbsainvalidation.cpp index 7985ca88..cb091b92 100644 --- a/src/games/starfield/src/starfieldbsainvalidation.cpp +++ b/src/games/starfield/src/starfieldbsainvalidation.cpp @@ -55,21 +55,6 @@ bool StarfieldBSAInvalidation::prepareProfile(MOBase::IProfile* profile) qWarning("failed to override data directory in \"%s\"", qUtf8Printable(m_IniFileName)); } } - } else { - if (!::GetPrivateProfileStringW(L"Archive", L"bInvalidateOlderFiles", L"1", setting, MAX_PATH, iniFilePath.toStdWString().c_str()) - || wcstol(setting, nullptr, 10) != 0) { - dirty = true; - if (!MOBase::WriteRegistryValue(L"Archive", L"bInvalidateOlderFiles", L"0", iniFilePath.toStdWString().c_str())) { - qWarning("failed to override data directory in \"%s\"", qUtf8Printable(m_IniFileName)); - } - } - if (!::GetPrivateProfileStringW(L"Archive", L"sResourceDataDirsFinal", L"", setting, MAX_PATH, iniFilePath.toStdWString().c_str()) - || wcscmp(setting, L"STRINGS\\") != 0) { - dirty = true; - if (!MOBase::WriteRegistryValue(L"Archive", L"sResourceDataDirsFinal", L"STRINGS\\", iniFilePath.toStdWString().c_str())) { - qWarning("failed to override data directory in \"%s\"", qUtf8Printable(m_IniFileName)); - } - } } return dirty; From f7bdd8f278206896447ae1999f2a5bb37f822875 Mon Sep 17 00:00:00 2001 From: Jeremy Rimpo Date: Tue, 5 Sep 2023 13:24:59 -0500 Subject: [PATCH 1314/1544] [game_starfield] Implement 'override' plugin support --- src/games/starfield/src/gamestarfield.cpp | 4 ++-- .../starfield/src/starfieldgameplugins.cpp | 12 ++++++++++ .../starfield/src/starfieldgameplugins.h | 22 +++++++++++++++++++ 3 files changed, 36 insertions(+), 2 deletions(-) create mode 100644 src/games/starfield/src/starfieldgameplugins.cpp create mode 100644 src/games/starfield/src/starfieldgameplugins.h diff --git a/src/games/starfield/src/gamestarfield.cpp b/src/games/starfield/src/gamestarfield.cpp index d791e0c6..3214815d 100644 --- a/src/games/starfield/src/gamestarfield.cpp +++ b/src/games/starfield/src/gamestarfield.cpp @@ -5,6 +5,7 @@ #include "starfieldunmanagedmods.h" #include "starfieldmoddatachecker.h" #include "starfieldmoddatacontent.h" +#include "starfieldgameplugins.h" #include "starfieldsavegame.h" #include "starfieldbsainvalidation.h" @@ -12,7 +13,6 @@ #include #include #include -#include #include "versioninfo.h" #include @@ -46,7 +46,7 @@ bool GameStarfield::init(IOrganizer *moInfo) registerFeature(new StarfieldModDataChecker(this)); registerFeature(new StarfieldModDataContent(this)); registerFeature(new GamebryoSaveGameInfo(this)); - registerFeature(new CreationGamePlugins(moInfo)); + registerFeature(new StarfieldGamePlugins(moInfo)); registerFeature(new StarfieldUnmangedMods(this)); registerFeature(new StarfieldBSAInvalidation(feature(), this)); diff --git a/src/games/starfield/src/starfieldgameplugins.cpp b/src/games/starfield/src/starfieldgameplugins.cpp new file mode 100644 index 00000000..204b4cd0 --- /dev/null +++ b/src/games/starfield/src/starfieldgameplugins.cpp @@ -0,0 +1,12 @@ +#include "starfieldgameplugins.h" + +using namespace MOBase; + +StarfieldGamePlugins::StarfieldGamePlugins(MOBase::IOrganizer* organizer) : CreationGamePlugins(organizer) +{ +} + +bool StarfieldGamePlugins::overridePluginsAreSupported() +{ + return true; +} \ No newline at end of file diff --git a/src/games/starfield/src/starfieldgameplugins.h b/src/games/starfield/src/starfieldgameplugins.h new file mode 100644 index 00000000..1f298bed --- /dev/null +++ b/src/games/starfield/src/starfieldgameplugins.h @@ -0,0 +1,22 @@ +#ifndef _STARFIELDGAMEPLUGINS_H +#define _STARFIELDGAMEPLUGINS_H + +#include + +#include +#include + +class StarfieldGamePlugins : public CreationGamePlugins +{ + +public: + + StarfieldGamePlugins(MOBase::IOrganizer* organizer); + +protected: + + virtual bool overridePluginsAreSupported() override; + +}; + +#endif // _STARFIELDGAMEPLUGINS_H \ No newline at end of file From 7c746d9bafcd42cc71d9c94aa07e179ba70dcd47 Mon Sep 17 00:00:00 2001 From: Jeremy Rimpo Date: Tue, 5 Sep 2023 13:25:00 -0500 Subject: [PATCH 1315/1544] Implement 'override' plugin support --- src/gamebryo/gamebryogameplugins.cpp | 5 +++++ src/gamebryo/gamebryogameplugins.h | 1 + 2 files changed, 6 insertions(+) diff --git a/src/gamebryo/gamebryogameplugins.cpp b/src/gamebryo/gamebryogameplugins.cpp index 7139aaa8..8b4cd053 100644 --- a/src/gamebryo/gamebryogameplugins.cpp +++ b/src/gamebryo/gamebryogameplugins.cpp @@ -251,3 +251,8 @@ bool GamebryoGamePlugins::lightPluginsAreSupported() { return false; } + +bool GamebryoGamePlugins::overridePluginsAreSupported() +{ + return false; +} diff --git a/src/gamebryo/gamebryogameplugins.h b/src/gamebryo/gamebryogameplugins.h index 5766bf50..80d09057 100644 --- a/src/gamebryo/gamebryogameplugins.h +++ b/src/gamebryo/gamebryogameplugins.h @@ -15,6 +15,7 @@ public: virtual void readPluginLists(MOBase::IPluginList* pluginList) override; virtual QStringList getLoadOrder() override; virtual bool lightPluginsAreSupported() override; + virtual bool overridePluginsAreSupported() override; protected: MOBase::IOrganizer* organizer() const { return m_Organizer; } From 86cf90efb563f7b95e5a37b1988c525e1e8195b4 Mon Sep 17 00:00:00 2001 From: Jeremy Rimpo Date: Tue, 5 Sep 2023 13:25:43 -0500 Subject: [PATCH 1316/1544] [game_starfield] Correct base plugin load order --- src/games/starfield/src/gamestarfield.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/games/starfield/src/gamestarfield.cpp b/src/games/starfield/src/gamestarfield.cpp index 3214815d..d72ef7ef 100644 --- a/src/games/starfield/src/gamestarfield.cpp +++ b/src/games/starfield/src/gamestarfield.cpp @@ -188,7 +188,7 @@ QString GameStarfield::steamAPPId() const } QStringList GameStarfield::primaryPlugins() const { - QStringList plugins = { "Starfield.esm", "BlueprintShips-Starfield.esm", "Constellation.esm", "OldMars.esm" }; + QStringList plugins = { "Starfield.esm", "Constellation.esm", "OldMars.esm", "BlueprintShips-Starfield.esm" }; plugins.append(CCPlugins()); From c41e65ec2986811bbb659e2159f5395b542f170e Mon Sep 17 00:00:00 2001 From: Jeremy Rimpo Date: Tue, 5 Sep 2023 15:05:30 -0500 Subject: [PATCH 1317/1544] [game_starfield] Move zlib to cmake_common --- src/games/starfield/src/CMakeLists.txt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/games/starfield/src/CMakeLists.txt b/src/games/starfield/src/CMakeLists.txt index 6ac31454..2c15f453 100644 --- a/src/games/starfield/src/CMakeLists.txt +++ b/src/games/starfield/src/CMakeLists.txt @@ -3,5 +3,5 @@ cmake_minimum_required(VERSION 3.16) add_library(game_starfield SHARED) mo2_configure_plugin(game_starfield WARNINGS OFF - PRIVATE_DEPENDS zlib creation) + PRIVATE_DEPENDS creation) mo2_install_target(game_starfield) From f5280f4194908b877ba4d3a0c9f8a0d4b9d7cb07 Mon Sep 17 00:00:00 2001 From: Jeremy Rimpo Date: Tue, 5 Sep 2023 15:05:31 -0500 Subject: [PATCH 1318/1544] [game_skyrimse] Move zlib to cmake_common --- src/games/skyrimse/src/CMakeLists.txt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/games/skyrimse/src/CMakeLists.txt b/src/games/skyrimse/src/CMakeLists.txt index a3532b3d..9b410545 100644 --- a/src/games/skyrimse/src/CMakeLists.txt +++ b/src/games/skyrimse/src/CMakeLists.txt @@ -3,5 +3,5 @@ cmake_minimum_required(VERSION 3.16) add_library(game_skyrimse SHARED) mo2_configure_plugin(game_skyrimse WARNINGS OFF - PRIVATE_DEPENDS zlib creation) + PRIVATE_DEPENDS creation) mo2_install_target(game_skyrimse) From 0594b55209aa4e92f4d9466e12b084e666c5d0ee Mon Sep 17 00:00:00 2001 From: Jeremy Rimpo Date: Tue, 5 Sep 2023 15:06:39 -0500 Subject: [PATCH 1319/1544] [game_starfield] Create the My Games data directory if it doesn't exist --- src/games/starfield/src/game_starfield_en.ts | 4 ++-- src/games/starfield/src/gamestarfield.cpp | 3 +++ 2 files changed, 5 insertions(+), 2 deletions(-) diff --git a/src/games/starfield/src/game_starfield_en.ts b/src/games/starfield/src/game_starfield_en.ts index 0cffb90c..25f56fce 100644 --- a/src/games/starfield/src/game_starfield_en.ts +++ b/src/games/starfield/src/game_starfield_en.ts @@ -4,12 +4,12 @@ GameStarfield - + Starfield Support Plugin - + Adds support for the game Starfield. diff --git a/src/games/starfield/src/gamestarfield.cpp b/src/games/starfield/src/gamestarfield.cpp index d72ef7ef..1adddb0a 100644 --- a/src/games/starfield/src/gamestarfield.cpp +++ b/src/games/starfield/src/gamestarfield.cpp @@ -94,6 +94,9 @@ QString GameStarfield::identifyGamePath() const QDir GameStarfield::dataDirectory() const { + QDir dataDir = documentsDirectory().absoluteFilePath("Data"); + if (!dataDir.exists()) + dataDir.mkdir(dataDir.path()); return documentsDirectory().absoluteFilePath("Data"); } From fc89fb303d9aa6f4ba4f9be83d2814762b797b88 Mon Sep 17 00:00:00 2001 From: Jeremy Rimpo Date: Wed, 6 Sep 2023 04:06:08 -0500 Subject: [PATCH 1320/1544] Reformat code --- src/gamebryo/gamebryosavegame.cpp | 73 +++++++++++++++++-------------- 1 file changed, 41 insertions(+), 32 deletions(-) diff --git a/src/gamebryo/gamebryosavegame.cpp b/src/gamebryo/gamebryosavegame.cpp index 3deabd6c..0ab84c5a 100644 --- a/src/gamebryo/gamebryosavegame.cpp +++ b/src/gamebryo/gamebryosavegame.cpp @@ -21,14 +21,13 @@ #define CHUNK 16384 -GamebryoSaveGame::GamebryoSaveGame(QString const &file, GameGamebryo const *game, bool const lightEnabled) : - m_FileName(file), - m_CreationTime(QFileInfo(file).lastModified()), - m_Game(game), - m_LightEnabled(lightEnabled), - m_DataFields([this]() { return fetchDataFields(); }) -{ -} +GamebryoSaveGame::GamebryoSaveGame(QString const& file, GameGamebryo const* game, + bool const lightEnabled) + : m_FileName(file), m_CreationTime(QFileInfo(file).lastModified()), m_Game(game), + m_LightEnabled(lightEnabled), m_DataFields([this]() { + return fetchDataFields(); + }) +{} GamebryoSaveGame::~GamebryoSaveGame() {} @@ -124,21 +123,25 @@ void GamebryoSaveGame::FileWrapper::setPluginString(StringType type) m_PluginString = type; } -void readQDataStream(QDataStream& data, void* buff, std::size_t length) { +void readQDataStream(QDataStream& data, void* buff, std::size_t length) +{ int read = data.readRawData(static_cast(buff), static_cast(length)); if (read != length) { throw std::runtime_error("unexpected end of file"); } } -template void readQDataStream(QDataStream& data, T& value) { +template +void readQDataStream(QDataStream& data, T& value) +{ int read = data.readRawData(reinterpret_cast(&value), sizeof(T)); if (read != sizeof(T)) { throw std::runtime_error("unexpected end of file"); } } -template <> void readQDataStream(QDataStream& data, QString& value) +template <> +void readQDataStream(QDataStream& data, QString& value) { unsigned short length; readQDataStream(data, length); @@ -150,11 +153,13 @@ template <> void readQDataStream(QDataStream& data, QString& value) value = QString::fromLatin1(buffer.data(), length); } -template <> void GamebryoSaveGame::FileWrapper::read(QString &value) +template <> +void GamebryoSaveGame::FileWrapper::read(QString& value) { if (m_CompressionType == 0) { unsigned short length; - if (m_PluginString == StringType::TYPE_BSTRING || m_PluginString == StringType::TYPE_BZSTRING) { + if (m_PluginString == StringType::TYPE_BSTRING || + m_PluginString == StringType::TYPE_BZSTRING) { unsigned char len; read(len); length = m_PluginString == StringType::TYPE_BZSTRING ? len + 1 : len; @@ -169,7 +174,8 @@ template <> void GamebryoSaveGame::FileWrapper::read(QString &value) QByteArray buffer; buffer.resize(length); - read(buffer.data(), m_PluginString == StringType::TYPE_BZSTRING ? length - 1 : length); + read(buffer.data(), + m_PluginString == StringType::TYPE_BZSTRING ? length - 1 : length); if (m_PluginString == StringType::TYPE_BZSTRING) buffer[length - 1] = '\0'; @@ -182,7 +188,8 @@ template <> void GamebryoSaveGame::FileWrapper::read(QString &value) } else if (m_CompressionType == 1 || m_CompressionType == 2) { readQDataStream(*m_Data, value); } else { - MOBase::log::warn("Please create an issue on the MO github labeled \"Found unknown Compressed\" with your savefile attached"); + MOBase::log::warn("Please create an issue on the MO github labeled \"Found unknown " + "Compressed\" with your savefile attached"); } } @@ -257,12 +264,12 @@ bool GamebryoSaveGame::FileWrapper::openCompressedData(int bytesToIgnore) QByteArray finalData; z_stream stream; try { - stream.zalloc = Z_NULL; - stream.zfree = Z_NULL; - stream.opaque = Z_NULL; + stream.zalloc = Z_NULL; + stream.zfree = Z_NULL; + stream.opaque = Z_NULL; stream.avail_in = 0; - stream.next_in = Z_NULL; - int zlibRet = inflateInit2(&stream, 15 + 32); + stream.next_in = Z_NULL; + int zlibRet = inflateInit2(&stream, 15 + 32); if (zlibRet != Z_OK) { return false; } @@ -277,14 +284,16 @@ bool GamebryoSaveGame::FileWrapper::openCompressedData(int bytesToIgnore) stream.next_in = static_cast(inBuffer.get()); do { stream.avail_out = CHUNK; - stream.next_out = reinterpret_cast(outBuffer.get()); - zlibRet = inflate(&stream, Z_NO_FLUSH); - if ((zlibRet != Z_OK) && (zlibRet != Z_STREAM_END) && (zlibRet != Z_BUF_ERROR)) { + stream.next_out = reinterpret_cast(outBuffer.get()); + zlibRet = inflate(&stream, Z_NO_FLUSH); + if ((zlibRet != Z_OK) && (zlibRet != Z_STREAM_END) && + (zlibRet != Z_BUF_ERROR)) { return false; } have = CHUNK - stream.avail_out; size += have; - finalData += QByteArray::fromRawData(reinterpret_cast(outBuffer.get()), have); + finalData += QByteArray::fromRawData( + reinterpret_cast(outBuffer.get()), have); } while (stream.avail_out == 0); } while (zlibRet != Z_STREAM_END); inflateEnd(&stream); @@ -390,7 +399,7 @@ uint32_t GamebryoSaveGame::FileWrapper::readInt(int bytesToIgnore) uint64_t GamebryoSaveGame::FileWrapper::readLong(int bytesToIgnore) { if (m_CompressionType == 0) { - if (bytesToIgnore > 0)//Just to make certain + if (bytesToIgnore > 0) // Just to make certain skip(bytesToIgnore); uint64_t size; read(size); @@ -403,7 +412,8 @@ uint64_t GamebryoSaveGame::FileWrapper::readLong(int bytesToIgnore) readQDataStream(*m_Data, size); return size; } else { - MOBase::log::warn("Please create an issue on the MO github labeled \"Found unknown Compressed\" with your savefile attached"); + MOBase::log::warn("Please create an issue on the MO github labeled \"Found unknown " + "Compressed\" with your savefile attached"); return 0; } } @@ -411,22 +421,21 @@ uint64_t GamebryoSaveGame::FileWrapper::readLong(int bytesToIgnore) float_t GamebryoSaveGame::FileWrapper::readFloat(int bytesToIgnore) { if (m_CompressionType == 0) { - if (bytesToIgnore > 0)//Just to make certain + if (bytesToIgnore > 0) // Just to make certain skip(bytesToIgnore); float_t value; read(value); return value; - } - else if (m_CompressionType == 1 || m_CompressionType == 2) { + } else if (m_CompressionType == 1 || m_CompressionType == 2) { // decompression already done by readSaveGameVersion m_Data->skipRawData(bytesToIgnore); float_t value; readQDataStream(*m_Data, value); return value; - } - else { - MOBase::log::warn("Please create an issue on the MO github labeled \"Found unknown Compressed\" with your savefile attached"); + } else { + MOBase::log::warn("Please create an issue on the MO github labeled \"Found unknown " + "Compressed\" with your savefile attached"); return 0; } } From b6744df6f0f144709157d7ebc89910c628a66d8f Mon Sep 17 00:00:00 2001 From: Jeremy Rimpo Date: Wed, 6 Sep 2023 04:12:26 -0500 Subject: [PATCH 1321/1544] [game_starfield] Apply clang-format --- src/games/starfield/.clang-format | 41 + src/games/starfield/src/game_starfield_en.ts | 4 +- src/games/starfield/src/gamestarfield.cpp | 75 +- src/games/starfield/src/gamestarfield.h | 20 +- .../src/starfieldbsainvalidation.cpp | 41 +- .../starfield/src/starfieldbsainvalidation.h | 18 +- .../starfield/src/starfielddataarchives.cpp | 130 +- .../starfield/src/starfielddataarchives.h | 20 +- .../starfield/src/starfieldgameplugins.cpp | 8 +- .../starfield/src/starfieldgameplugins.h | 9 +- .../starfield/src/starfieldmoddatachecker.h | 21 +- .../starfield/src/starfieldmoddatacontent.h | 21 +- src/games/starfield/src/starfieldsavegame.cpp | 118 +- src/games/starfield/src/starfieldsavegame.h | 20 +- .../starfield/src/starfieldscriptextender.cpp | 7 +- .../starfield/src/starfieldscriptextender.h | 5 +- .../starfield/src/starfieldunmanagedmods.cpp | 24 +- .../starfield/src/starfieldunmanagedmods.h | 15 +- src/games/starfield/src/vdf_parser.h | 1205 +++++++++-------- 19 files changed, 925 insertions(+), 877 deletions(-) create mode 100644 src/games/starfield/.clang-format diff --git a/src/games/starfield/.clang-format b/src/games/starfield/.clang-format new file mode 100644 index 00000000..6098e1f5 --- /dev/null +++ b/src/games/starfield/.clang-format @@ -0,0 +1,41 @@ +--- +# We'll use defaults from the LLVM style, but with 4 columns indentation. +BasedOnStyle: LLVM +IndentWidth: 2 +--- +Language: Cpp +DeriveLineEnding: false +UseCRLF: true +DerivePointerAlignment: false +PointerAlignment: Left +AlignConsecutiveAssignments: true +AllowShortFunctionsOnASingleLine: Inline +AllowShortIfStatementsOnASingleLine: Never +AllowShortLambdasOnASingleLine: Empty +AlwaysBreakTemplateDeclarations: Yes +AccessModifierOffset: -2 +AlignTrailingComments: true +SpacesBeforeTrailingComments: 2 +NamespaceIndentation: Inner +MaxEmptyLinesToKeep: 1 +BreakBeforeBraces: Custom +BraceWrapping: + AfterCaseLabel: false + AfterClass: true + AfterControlStatement: false + AfterEnum: true + AfterFunction: true + AfterNamespace: true + AfterStruct: true + AfterUnion: true + AfterExternBlock: true + BeforeCatch: false + BeforeElse: false + BeforeLambdaBody: false + BeforeWhile: false + IndentBraces: false + SplitEmptyFunction: false + SplitEmptyRecord: false + SplitEmptyNamespace: true +ColumnLimit: 88 +ForEachMacros: ['Q_FOREACH', 'foreach'] diff --git a/src/games/starfield/src/game_starfield_en.ts b/src/games/starfield/src/game_starfield_en.ts index 25f56fce..df8298c6 100644 --- a/src/games/starfield/src/game_starfield_en.ts +++ b/src/games/starfield/src/game_starfield_en.ts @@ -4,12 +4,12 @@ GameStarfield - + Starfield Support Plugin - + Adds support for the game Starfield. diff --git a/src/games/starfield/src/gamestarfield.cpp b/src/games/starfield/src/gamestarfield.cpp index 1adddb0a..b6aaf2ef 100644 --- a/src/games/starfield/src/gamestarfield.cpp +++ b/src/games/starfield/src/gamestarfield.cpp @@ -1,19 +1,19 @@ #include "gamestarfield.h" +#include "starfieldbsainvalidation.h" #include "starfielddataarchives.h" -#include "starfieldscriptextender.h" -#include "starfieldunmanagedmods.h" +#include "starfieldgameplugins.h" #include "starfieldmoddatachecker.h" #include "starfieldmoddatacontent.h" -#include "starfieldgameplugins.h" #include "starfieldsavegame.h" -#include "starfieldbsainvalidation.h" +#include "starfieldscriptextender.h" +#include "starfieldunmanagedmods.h" -#include +#include "versioninfo.h" #include #include #include -#include "versioninfo.h" +#include #include #include @@ -30,11 +30,9 @@ using namespace MOBase; -GameStarfield::GameStarfield() -{ -} +GameStarfield::GameStarfield() {} -bool GameStarfield::init(IOrganizer *moInfo) +bool GameStarfield::init(IOrganizer* moInfo) { if (!GameGamebryo::init(moInfo)) { return false; @@ -42,13 +40,15 @@ bool GameStarfield::init(IOrganizer *moInfo) registerFeature(new StarfieldScriptExtender(this)); registerFeature(new StarfieldDataArchives(myGamesPath())); - registerFeature(new GamebryoLocalSavegames(myGamesPath(), "StarfieldCustom.ini")); + registerFeature( + new GamebryoLocalSavegames(myGamesPath(), "StarfieldCustom.ini")); registerFeature(new StarfieldModDataChecker(this)); registerFeature(new StarfieldModDataContent(this)); registerFeature(new GamebryoSaveGameInfo(this)); registerFeature(new StarfieldGamePlugins(moInfo)); registerFeature(new StarfieldUnmangedMods(this)); - registerFeature(new StarfieldBSAInvalidation(feature(), this)); + registerFeature( + new StarfieldBSAInvalidation(feature(), this)); return true; } @@ -60,23 +60,25 @@ QString GameStarfield::gameName() const void GameStarfield::detectGame() { - m_GamePath = identifyGamePath(); + m_GamePath = identifyGamePath(); m_MyGamesPath = determineMyGamesPath("Starfield"); } QString GameStarfield::identifyGamePath() const { QString path = "Software\\Valve\\Steam"; - QString steamLocation = findInRegistry(HKEY_CURRENT_USER, path.toStdWString().c_str(), L"SteamPath"); + QString steamLocation = + findInRegistry(HKEY_CURRENT_USER, path.toStdWString().c_str(), L"SteamPath"); if (!steamLocation.isEmpty()) { QString steamLibraryLocation; - QString steamLibraries(steamLocation + "\\" + "config" + "\\" + "libraryfolders.vdf"); + QString steamLibraries(steamLocation + "\\" + "config" + "\\" + + "libraryfolders.vdf"); if (QFile(steamLibraries).exists()) { std::ifstream file(steamLibraries.toStdString()); auto root = tyti::vdf::read(file); for (auto child : root.childs) { - tyti::vdf::object *library = child.second.get(); - auto apps = library->childs["apps"]; + tyti::vdf::object* library = child.second.get(); + auto apps = library->childs["apps"]; if (apps->attribs.contains(steamAPPId().toStdString())) { steamLibraryLocation = QString::fromStdString(library->attribs["path"]); break; @@ -84,8 +86,10 @@ QString GameStarfield::identifyGamePath() const } } if (!steamLibraryLocation.isEmpty()) { - QString gameLocation = steamLibraryLocation + "\\" + "steamapps" + "\\" + "common" + "\\" + "Starfield"; - if (QDir(gameLocation).exists() && QFile(gameLocation + "\\" + "Starfield.exe").exists()) + QString gameLocation = steamLibraryLocation + "\\" + "steamapps" + "\\" + + "common" + "\\" + "Starfield"; + if (QDir(gameLocation).exists() && + QFile(gameLocation + "\\" + "Starfield.exe").exists()) return gameLocation; } } @@ -110,9 +114,9 @@ QMap GameStarfield::secondaryDataDirectories() const QList GameStarfield::executables() const { return QList() - << ExecutableInfo("SFSE", findInGameFolder(feature()->loaderName())) - << ExecutableInfo("Starfield", findInGameFolder(binaryName())) - ; + << ExecutableInfo("SFSE", + findInGameFolder(feature()->loaderName())) + << ExecutableInfo("Starfield", findInGameFolder(binaryName())); } QList GameStarfield::executableForcedLoads() const @@ -130,7 +134,6 @@ QString GameStarfield::localizedName() const return tr("Starfield Support Plugin"); } - QString GameStarfield::author() const { return "Silarn"; @@ -151,16 +154,17 @@ QList GameStarfield::settings() const return QList(); } -void GameStarfield::initializeProfile(const QDir &path, ProfileSettings settings) const +void GameStarfield::initializeProfile(const QDir& path, ProfileSettings settings) const { if (settings.testFlag(IPluginGame::MODS)) { copyToProfile(localAppFolder() + "/Starfield", path, "plugins.txt"); } if (settings.testFlag(IPluginGame::CONFIGURATION)) { - if (settings.testFlag(IPluginGame::PREFER_DEFAULTS) - || !QFileInfo(myGamesPath() + "/Starfield.ini").exists()) { - copyToProfile(gameDirectory().absolutePath(), path, "StarfieldDefault.ini", "Starfield.ini"); + if (settings.testFlag(IPluginGame::PREFER_DEFAULTS) || + !QFileInfo(myGamesPath() + "/Starfield.ini").exists()) { + copyToProfile(gameDirectory().absolutePath(), path, "StarfieldDefault.ini", + "Starfield.ini"); } else { copyToProfile(myGamesPath(), path, "Starfield.ini"); } @@ -180,7 +184,8 @@ QString GameStarfield::savegameSEExtension() const return "sfse"; } -std::shared_ptr GameStarfield::makeSaveGame(QString filePath) const +std::shared_ptr +GameStarfield::makeSaveGame(QString filePath) const { return std::make_shared(filePath, this); } @@ -190,8 +195,10 @@ QString GameStarfield::steamAPPId() const return "1716740"; } -QStringList GameStarfield::primaryPlugins() const { - QStringList plugins = { "Starfield.esm", "Constellation.esm", "OldMars.esm", "BlueprintShips-Starfield.esm" }; +QStringList GameStarfield::primaryPlugins() const +{ + QStringList plugins = {"Starfield.esm", "Constellation.esm", "OldMars.esm", + "BlueprintShips-Starfield.esm"}; plugins.append(CCPlugins()); @@ -200,7 +207,7 @@ QStringList GameStarfield::primaryPlugins() const { QStringList GameStarfield::gameVariants() const { - return { "Regular" }; + return {"Regular"}; } QString GameStarfield::gameShortName() const @@ -215,7 +222,7 @@ QString GameStarfield::gameNexusName() const QStringList GameStarfield::iniFiles() const { - return { "Starfield.ini", "StarfieldPrefs.ini", "StarfieldCustom.ini" }; + return {"Starfield.ini", "StarfieldPrefs.ini", "StarfieldCustom.ini"}; } QStringList GameStarfield::DLCPlugins() const @@ -228,7 +235,9 @@ QStringList GameStarfield::CCPlugins() const QStringList plugins = {}; QFile file(gameDirectory().absoluteFilePath("Starfield.ccc")); if (file.open(QIODevice::ReadOnly)) { - ON_BLOCK_EXIT([&file]() { file.close(); }); + ON_BLOCK_EXIT([&file]() { + file.close(); + }); if (file.size() == 0) { return plugins; diff --git a/src/games/starfield/src/gamestarfield.h b/src/games/starfield/src/gamestarfield.h index 1c36adde..4b04d7f8 100644 --- a/src/games/starfield/src/gamestarfield.h +++ b/src/games/starfield/src/gamestarfield.h @@ -1,7 +1,6 @@ #ifndef GAMESTARFIELD_H #define GAMESTARFIELD_H - #include "gamegamebryo.h" #include @@ -14,20 +13,20 @@ class GameStarfield : public GameGamebryo Q_PLUGIN_METADATA(IID "org.modorganizer.GameStarfield" FILE "gamestarfield.json") public: - GameStarfield(); - virtual bool init(MOBase::IOrganizer *moInfo) override; - -public: // IPluginGame interface + virtual bool init(MOBase::IOrganizer* moInfo) override; +public: // IPluginGame interface virtual QString gameName() const override; virtual void detectGame() override; virtual QDir dataDirectory() const override; virtual QMap secondaryDataDirectories() const override; virtual QList executables() const override; - virtual QList executableForcedLoads() const override; - virtual void initializeProfile(const QDir &path, ProfileSettings settings) const override; + virtual QList + 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; @@ -40,8 +39,7 @@ public: // IPluginGame interface virtual int nexusModOrganizerID() const override; virtual int nexusGameID() const override; -public: // IPlugin interface - +public: // IPlugin interface virtual QString name() const override; virtual QString localizedName() const override; virtual QString author() const override; @@ -50,12 +48,10 @@ public: // IPlugin interface virtual QList settings() const override; protected: - virtual QString identifyGamePath() const override; std::shared_ptr makeSaveGame(QString filePath) const override; QString savegameExtension() const override; QString savegameSEExtension() const override; - }; -#endif // GAMEStarfield_H +#endif // GAMEStarfield_H diff --git a/src/games/starfield/src/starfieldbsainvalidation.cpp b/src/games/starfield/src/starfieldbsainvalidation.cpp index cb091b92..a0c2d105 100644 --- a/src/games/starfield/src/starfieldbsainvalidation.cpp +++ b/src/games/starfield/src/starfieldbsainvalidation.cpp @@ -3,15 +3,16 @@ #include "dummybsa.h" #include "iplugingame.h" #include "iprofile.h" +#include "registry.h" #include #include -#include "registry.h" -StarfieldBSAInvalidation::StarfieldBSAInvalidation(DataArchives *dataArchives, MOBase::IPluginGame const *game) - : GamebryoBSAInvalidation(dataArchives, "StarfieldCustom.ini", game) +StarfieldBSAInvalidation::StarfieldBSAInvalidation(DataArchives* dataArchives, + MOBase::IPluginGame const* game) + : GamebryoBSAInvalidation(dataArchives, "StarfieldCustom.ini", game) { m_IniFileName = "StarfieldCustom.ini"; - m_Game = game; + m_Game = game; } bool StarfieldBSAInvalidation::isInvalidationBSA(const QString& bsaName) @@ -31,28 +32,34 @@ unsigned long StarfieldBSAInvalidation::bsaVersion() const bool StarfieldBSAInvalidation::prepareProfile(MOBase::IProfile* profile) { - bool dirty = false; - QString basePath - = profile->localSettingsEnabled() - ? profile->absolutePath() - : m_Game->documentsDirectory().absolutePath(); + bool dirty = false; + QString basePath = profile->localSettingsEnabled() + ? profile->absolutePath() + : m_Game->documentsDirectory().absolutePath(); QString iniFilePath = basePath + "/" + m_IniFileName; WCHAR setting[MAX_PATH]; if (profile->invalidationActive(nullptr)) { // write bInvalidateOlderFiles = 1, if needed - if (!::GetPrivateProfileStringW(L"Archive", L"bInvalidateOlderFiles", L"0", setting, MAX_PATH, iniFilePath.toStdWString().c_str()) - || wcstol(setting, nullptr, 10) != 1) { + if (!::GetPrivateProfileStringW(L"Archive", L"bInvalidateOlderFiles", L"0", setting, + MAX_PATH, iniFilePath.toStdWString().c_str()) || + wcstol(setting, nullptr, 10) != 1) { dirty = true; - if (!MOBase::WriteRegistryValue(L"Archive", L"bInvalidateOlderFiles", L"1", iniFilePath.toStdWString().c_str())) { - qWarning("failed to override data directory in \"%s\"", qUtf8Printable(m_IniFileName)); + if (!MOBase::WriteRegistryValue(L"Archive", L"bInvalidateOlderFiles", L"1", + iniFilePath.toStdWString().c_str())) { + qWarning("failed to override data directory in \"%s\"", + qUtf8Printable(m_IniFileName)); } } - if (!::GetPrivateProfileStringW(L"Archive", L"sResourceDataDirsFinal", L"STRINGS\\", setting, MAX_PATH, iniFilePath.toStdWString().c_str()) - || wcscmp(setting, L"") != 0) { + if (!::GetPrivateProfileStringW(L"Archive", L"sResourceDataDirsFinal", L"STRINGS\\", + setting, MAX_PATH, + iniFilePath.toStdWString().c_str()) || + wcscmp(setting, L"") != 0) { dirty = true; - if (!MOBase::WriteRegistryValue(L"Archive", L"sResourceDataDirsFinal", L"", iniFilePath.toStdWString().c_str())) { - qWarning("failed to override data directory in \"%s\"", qUtf8Printable(m_IniFileName)); + if (!MOBase::WriteRegistryValue(L"Archive", L"sResourceDataDirsFinal", L"", + iniFilePath.toStdWString().c_str())) { + qWarning("failed to override data directory in \"%s\"", + qUtf8Printable(m_IniFileName)); } } } diff --git a/src/games/starfield/src/starfieldbsainvalidation.h b/src/games/starfield/src/starfieldbsainvalidation.h index b530634e..36d3637a 100644 --- a/src/games/starfield/src/starfieldbsainvalidation.h +++ b/src/games/starfield/src/starfieldbsainvalidation.h @@ -1,36 +1,32 @@ #ifndef STARFIELDBSAINVALIDATION_H #define STARFIELDBSAINVALIDATION_H - -#include -#include #include "gamebryobsainvalidation.h" #include "starfielddataarchives.h" +#include +#include #include -namespace MOBase { - class IPluginGame; +namespace MOBase +{ +class IPluginGame; } class StarfieldBSAInvalidation : public GamebryoBSAInvalidation { public: - - StarfieldBSAInvalidation(DataArchives *dataArchives, MOBase::IPluginGame const *game); + StarfieldBSAInvalidation(DataArchives* dataArchives, MOBase::IPluginGame const* game); virtual bool isInvalidationBSA(const QString& bsaName) override; virtual bool prepareProfile(MOBase::IProfile* profile) override; private: - virtual QString invalidationBSAName() const override; virtual unsigned long bsaVersion() const override; private: - QString m_IniFileName; MOBase::IPluginGame const* m_Game; - }; -#endif // STARFIELDBSAINVALIDATION_H +#endif // STARFIELDBSAINVALIDATION_H diff --git a/src/games/starfield/src/starfielddataarchives.cpp b/src/games/starfield/src/starfielddataarchives.cpp index f90d19b6..713ede18 100644 --- a/src/games/starfield/src/starfielddataarchives.cpp +++ b/src/games/starfield/src/starfielddataarchives.cpp @@ -3,75 +3,77 @@ #include "iprofile.h" #include -StarfieldDataArchives::StarfieldDataArchives(const QDir &myGamesDir) : - GamebryoDataArchives(myGamesDir) +StarfieldDataArchives::StarfieldDataArchives(const QDir& myGamesDir) + : GamebryoDataArchives(myGamesDir) {} QStringList StarfieldDataArchives::vanillaArchives() const { - return { "Starfield - Animations.ba2" - , "Starfield - DensityMaps.ba2" - , "Starfield - FaceAnimation01.ba2" - , "Starfield - FaceAnimation02.ba2" - , "Starfield - FaceAnimation03.ba2" - , "Starfield - FaceAnimation04.ba2" - , "Starfield - FaceAnimationPatch.ba2" - , "Starfield - FaceMeshes.ba2" - , "Starfield - GeneratedTextures.ba2" - , "Starfield - Interface.ba2" - , "Starfield - Localization.ba2" - , "Starfield - LODMeshes.ba2" - , "Starfield - LODMeshesPatch.ba2" - , "Starfield - LODTextures.ba2" - , "Starfield - Materials.ba2" - , "Starfield - Meshes01.ba2" - , "Starfield - Meshes02.ba2" - , "Starfield - MeshesPatch.ba2" - , "Starfield - Misc.ba2" - , "Starfield - Particles.ba2" - , "Starfield - ParticlesTestData.ba2" - , "Starfield - PlanetData.ba2" - , "Starfield - Shaders.ba2" - , "Starfield - ShadersBeta.ba2" - , "Starfield - Terrain01.ba2" - , "Starfield - Terrain02.ba2" - , "Starfield - Terrain03.ba2" - , "Starfield - Terrain04.ba2" - , "Starfield - TerrainPatch.ba2" - , "Starfield - Textures01.ba2" - , "Starfield - Textures02.ba2" - , "Starfield - Textures03.ba2" - , "Starfield - Textures04.ba2" - , "Starfield - Textures05.ba2" - , "Starfield - Textures06.ba2" - , "Starfield - Textures07.ba2" - , "Starfield - Textures08.ba2" - , "Starfield - Textures09.ba2" - , "Starfield - Textures10.ba2" - , "Starfield - Textures11.ba2" - , "Starfield - TexturesPatch.ba2" - , "Starfield - Voices01.ba2" - , "Starfield - Voices02.ba2" - , "Starfield - VoicesPatch.ba2" - , "Starfield - WwiseSounds01.ba2" - , "Starfield - WwiseSounds02.ba2" - , "Starfield - WwiseSounds03.ba2" - , "Starfield - WwiseSounds04.ba2" - , "Starfield - WwiseSounds05.ba2" - , "Starfield - WwiseSoundsPatch.ba2" - , "Constellation - Localization.ba2" - , "Constellation - Textures.ba2" - , "OldMars - Localization.ba2" - , "OldMars - Textures.ba2" - , "BlueprintShips-Starfield - Localization.ba2" }; + return {"Starfield - Animations.ba2", + "Starfield - DensityMaps.ba2", + "Starfield - FaceAnimation01.ba2", + "Starfield - FaceAnimation02.ba2", + "Starfield - FaceAnimation03.ba2", + "Starfield - FaceAnimation04.ba2", + "Starfield - FaceAnimationPatch.ba2", + "Starfield - FaceMeshes.ba2", + "Starfield - GeneratedTextures.ba2", + "Starfield - Interface.ba2", + "Starfield - Localization.ba2", + "Starfield - LODMeshes.ba2", + "Starfield - LODMeshesPatch.ba2", + "Starfield - LODTextures.ba2", + "Starfield - Materials.ba2", + "Starfield - Meshes01.ba2", + "Starfield - Meshes02.ba2", + "Starfield - MeshesPatch.ba2", + "Starfield - Misc.ba2", + "Starfield - Particles.ba2", + "Starfield - ParticlesTestData.ba2", + "Starfield - PlanetData.ba2", + "Starfield - Shaders.ba2", + "Starfield - ShadersBeta.ba2", + "Starfield - Terrain01.ba2", + "Starfield - Terrain02.ba2", + "Starfield - Terrain03.ba2", + "Starfield - Terrain04.ba2", + "Starfield - TerrainPatch.ba2", + "Starfield - Textures01.ba2", + "Starfield - Textures02.ba2", + "Starfield - Textures03.ba2", + "Starfield - Textures04.ba2", + "Starfield - Textures05.ba2", + "Starfield - Textures06.ba2", + "Starfield - Textures07.ba2", + "Starfield - Textures08.ba2", + "Starfield - Textures09.ba2", + "Starfield - Textures10.ba2", + "Starfield - Textures11.ba2", + "Starfield - TexturesPatch.ba2", + "Starfield - Voices01.ba2", + "Starfield - Voices02.ba2", + "Starfield - VoicesPatch.ba2", + "Starfield - WwiseSounds01.ba2", + "Starfield - WwiseSounds02.ba2", + "Starfield - WwiseSounds03.ba2", + "Starfield - WwiseSounds04.ba2", + "Starfield - WwiseSounds05.ba2", + "Starfield - WwiseSoundsPatch.ba2", + "Constellation - Localization.ba2", + "Constellation - Textures.ba2", + "OldMars - Localization.ba2", + "OldMars - Textures.ba2", + "BlueprintShips-Starfield - Localization.ba2"}; } - -QStringList StarfieldDataArchives::archives(const MOBase::IProfile *profile) const +QStringList StarfieldDataArchives::archives(const MOBase::IProfile* profile) const { QStringList result; - QString iniFile = profile->localSettingsEnabled() ? QDir(profile->absolutePath()).absoluteFilePath("Starfield.ini") : m_LocalGameDir.absoluteFilePath("Starfield.ini"); + QString iniFile = + profile->localSettingsEnabled() + ? QDir(profile->absolutePath()).absoluteFilePath("Starfield.ini") + : m_LocalGameDir.absoluteFilePath("Starfield.ini"); result.append(getArchivesFromKey(iniFile, "SResourceArchiveList")); result.append(getArchivesFromKey(iniFile, "sResourceIndexFileList")); result.append(getArchivesFromKey(iniFile, "SResourceArchiveMemoryCacheList")); @@ -81,11 +83,15 @@ QStringList StarfieldDataArchives::archives(const MOBase::IProfile *profile) con return result; } -void StarfieldDataArchives::writeArchiveList(MOBase::IProfile *profile, const QStringList &before) +void StarfieldDataArchives::writeArchiveList(MOBase::IProfile* profile, + const QStringList& before) { QString list = before.join(", "); - QString iniFile = profile->localSettingsEnabled() ? QDir(profile->absolutePath()).absoluteFilePath("Starfield.ini") : m_LocalGameDir.absoluteFilePath("Starfield.ini"); + QString iniFile = + profile->localSettingsEnabled() + ? QDir(profile->absolutePath()).absoluteFilePath("Starfield.ini") + : m_LocalGameDir.absoluteFilePath("Starfield.ini"); if (list.length() > 255) { int splitIdx = list.lastIndexOf(",", 256); setArchivesToKey(iniFile, "SResourceArchiveList", list.mid(0, splitIdx)); diff --git a/src/games/starfield/src/starfielddataarchives.h b/src/games/starfield/src/starfielddataarchives.h index 7738085a..613127f3 100644 --- a/src/games/starfield/src/starfielddataarchives.h +++ b/src/games/starfield/src/starfielddataarchives.h @@ -3,27 +3,27 @@ #include "gamebryodataarchives.h" -namespace MOBase { class IProfile; } +namespace MOBase +{ +class IProfile; +} -#include #include +#include class StarfieldDataArchives : public GamebryoDataArchives { public: - - StarfieldDataArchives(const QDir &myGamesDir); + StarfieldDataArchives(const QDir& myGamesDir); public: - virtual QStringList vanillaArchives() const override; - virtual QStringList archives(const MOBase::IProfile *profile) const override; + virtual QStringList archives(const MOBase::IProfile* profile) const override; private: - - virtual void writeArchiveList(MOBase::IProfile *profile, const QStringList &before) override; - + virtual void writeArchiveList(MOBase::IProfile* profile, + const QStringList& before) override; }; -#endif // STARFIELDDATAARCHIVES_H +#endif // STARFIELDDATAARCHIVES_H diff --git a/src/games/starfield/src/starfieldgameplugins.cpp b/src/games/starfield/src/starfieldgameplugins.cpp index 204b4cd0..b346e872 100644 --- a/src/games/starfield/src/starfieldgameplugins.cpp +++ b/src/games/starfield/src/starfieldgameplugins.cpp @@ -2,11 +2,11 @@ using namespace MOBase; -StarfieldGamePlugins::StarfieldGamePlugins(MOBase::IOrganizer* organizer) : CreationGamePlugins(organizer) -{ -} +StarfieldGamePlugins::StarfieldGamePlugins(MOBase::IOrganizer* organizer) + : CreationGamePlugins(organizer) +{} bool StarfieldGamePlugins::overridePluginsAreSupported() { - return true; + return true; } \ No newline at end of file diff --git a/src/games/starfield/src/starfieldgameplugins.h b/src/games/starfield/src/starfieldgameplugins.h index 1f298bed..1f21bd55 100644 --- a/src/games/starfield/src/starfieldgameplugins.h +++ b/src/games/starfield/src/starfieldgameplugins.h @@ -10,13 +10,10 @@ class StarfieldGamePlugins : public CreationGamePlugins { public: - - StarfieldGamePlugins(MOBase::IOrganizer* organizer); + StarfieldGamePlugins(MOBase::IOrganizer* organizer); protected: - - virtual bool overridePluginsAreSupported() override; - + virtual bool overridePluginsAreSupported() override; }; -#endif // _STARFIELDGAMEPLUGINS_H \ No newline at end of file +#endif // _STARFIELDGAMEPLUGINS_H \ No newline at end of file diff --git a/src/games/starfield/src/starfieldmoddatachecker.h b/src/games/starfield/src/starfieldmoddatachecker.h index 31136c6d..1fa1c5e3 100644 --- a/src/games/starfield/src/starfieldmoddatachecker.h +++ b/src/games/starfield/src/starfieldmoddatachecker.h @@ -9,20 +9,21 @@ public: using GamebryoModDataChecker::GamebryoModDataChecker; protected: - virtual const FileNameSet& possibleFolderNames() const override { + virtual const FileNameSet& possibleFolderNames() const override + { static FileNameSet result{ - "interface", "meshes", "music", "scripts", "sound", "strings", "textures", - "trees", "video", "materials", "sfse", "distantlod", "asi", "Tools", "MCM", - "distantland", "mits", "dllplugins", "CalienteTools", "shadersfx", "aaf" - }; + "interface", "meshes", "music", "scripts", "sound", "strings", + "textures", "trees", "video", "materials", "sfse", "distantlod", + "asi", "Tools", "MCM", "distantland", "mits", "dllplugins", + "CalienteTools", "shadersfx", "aaf"}; return result; } - virtual const FileNameSet& possibleFileExtensions() const override { - static FileNameSet result{ - "esp", "esm", "esl", "ba2", "modgroups", "ini", "csg", "cdx" - }; + virtual const FileNameSet& possibleFileExtensions() const override + { + static FileNameSet result{"esp", "esm", "esl", "ba2", + "modgroups", "ini", "csg", "cdx"}; return result; } }; -#endif // STARFIELD_MODATACHECKER_H +#endif // STARFIELD_MODATACHECKER_H diff --git a/src/games/starfield/src/starfieldmoddatacontent.h b/src/games/starfield/src/starfieldmoddatacontent.h index 1e6930bd..325c64f3 100644 --- a/src/games/starfield/src/starfieldmoddatacontent.h +++ b/src/games/starfield/src/starfieldmoddatacontent.h @@ -4,15 +4,17 @@ #include #include -class StarfieldModDataContent : public GamebryoModDataContent { +class StarfieldModDataContent : public GamebryoModDataContent +{ protected: - enum StarfieldContent { + enum StarfieldContent + { CONTENT_MATERIAL = CONTENT_NEXT_VALUE }; public: - StarfieldModDataContent(GameGamebryo const* gamePlugin) : - GamebryoModDataContent(gamePlugin) + StarfieldModDataContent(GameGamebryo const* gamePlugin) + : GamebryoModDataContent(gamePlugin) { m_Enabled[CONTENT_SKYPROC] = false; } @@ -20,22 +22,23 @@ public: std::vector getAllContents() const override { auto contents = GamebryoModDataContent::getAllContents(); - contents.push_back(Content(CONTENT_MATERIAL, "Materials", ":/MO/gui/content/material")); + contents.push_back( + Content(CONTENT_MATERIAL, "Materials", ":/MO/gui/content/material")); return contents; } - std::vector getContentsFor( - std::shared_ptr fileTree) const override + std::vector + getContentsFor(std::shared_ptr fileTree) const override { auto contents = GamebryoModDataContent::getContentsFor(fileTree); for (auto e : *fileTree) { if (e->compare("materials") == 0) { contents.push_back(CONTENT_MATERIAL); - break; // Early break if you have nothing else to check. + break; // Early break if you have nothing else to check. } } return contents; } }; -#endif // STARFIELD_MODDATACONTENT_H \ No newline at end of file +#endif // STARFIELD_MODDATACONTENT_H \ No newline at end of file diff --git a/src/games/starfield/src/starfieldsavegame.cpp b/src/games/starfield/src/starfieldsavegame.cpp index f15729c9..f5a27102 100644 --- a/src/games/starfield/src/starfieldsavegame.cpp +++ b/src/games/starfield/src/starfieldsavegame.cpp @@ -4,114 +4,110 @@ #include "gamestarfield.h" -StarfieldSaveGame::StarfieldSaveGame(QString const &fileName, GameStarfield const* game) : - GamebryoSaveGame(fileName, game, true) +StarfieldSaveGame::StarfieldSaveGame(QString const& fileName, GameStarfield const* game) + : GamebryoSaveGame(fileName, game, true) { FileWrapper file(getFilepath(), "BCPS"); getData(file); FILETIME creationTime; - fetchInformationFields(file, m_SaveNumber, m_PCName, m_PCLevel, m_PCLocation, creationTime); + fetchInformationFields(file, m_SaveNumber, m_PCName, m_PCLevel, m_PCLocation, + creationTime); file.closeCompressedData(); file.close(); - //A file time is a 64-bit value that represents the number of 100-nanosecond - //intervals that have elapsed since 12:00 A.M. January 1, 1601 Coordinated Universal Time (UTC). - //So we need to convert that to something useful + // A file time is a 64-bit value that represents the number of 100-nanosecond + // intervals that have elapsed since 12:00 A.M. January 1, 1601 Coordinated Universal + // Time (UTC). So we need to convert that to something useful SYSTEMTIME ctime; ::FileTimeToSystemTime(&creationTime, &ctime); setCreationTime(ctime); } -void StarfieldSaveGame::getData( - FileWrapper& file) const +void StarfieldSaveGame::getData(FileWrapper& file) const { - file.skip(); // header version - file.skip(); // zip start location - file.skip(); // unknown - file.setCompressionType(1); - file.openCompressedData(); // long = start, long = size - // double - // float - // long - // long - // short - return; + file.skip(); // header version + file.skip(); // zip start location + file.skip(); // unknown + file.setCompressionType(1); + file.openCompressedData(); // long = start, long = size + // double + // float + // long + // long + // short + return; } void StarfieldSaveGame::fetchInformationFields( - FileWrapper& file, - unsigned long& saveNumber, - QString& playerName, - unsigned short& playerLevel, - QString& playerLocation, - FILETIME& creationTime) const + FileWrapper& file, unsigned long& saveNumber, QString& playerName, + unsigned short& playerLevel, QString& playerLocation, FILETIME& creationTime) const { - char fileID[12]; // SFS_SAVEGAME + char fileID[12]; // SFS_SAVEGAME unsigned int headerSize; unsigned int version; unsigned char unknown; - //file.read(fileID, 12); + // file.read(fileID, 12); headerSize = file.readInt(12); - version = file.readInt(); - unknown = file.readChar(); + version = file.readInt(); + unknown = file.readChar(); saveNumber = file.readInt(); file.read(playerName); unsigned int temp; - temp = file.readInt(); + temp = file.readInt(); playerLevel = static_cast(temp); file.read(playerLocation); QString ignore; - file.read(ignore); // playtime as ascii hh.mm.ss - file.read(ignore); // race name (i.e. BretonRace) + file.read(ignore); // playtime as ascii hh.mm.ss + file.read(ignore); // race name (i.e. BretonRace) unsigned short gender; - gender = file.readShort(); // Player gender (0 = male) + gender = file.readShort(); // Player gender (0 = male) float experience, experienceRequired; - experience = file.readFloat(); + experience = file.readFloat(); experienceRequired = file.readFloat(); - unsigned long long time = file.readLong(); - creationTime.dwLowDateTime = (DWORD)time; + unsigned long long time = file.readLong(); + creationTime.dwLowDateTime = (DWORD)time; creationTime.dwHighDateTime = time >> 32; } std::unique_ptr StarfieldSaveGame::fetchDataFields() const { - FileWrapper file(getFilepath(), "BCPS"); //10bytes + FileWrapper file(getFilepath(), "BCPS"); // 10bytes - getData(file); - FILETIME creationTime; + getData(file); + FILETIME creationTime; - { - QString dummyName, dummyLocation; - unsigned short dummyLevel; - unsigned long dummySaveNumber; - FILETIME dummyTime; + { + QString dummyName, dummyLocation; + unsigned short dummyLevel; + unsigned long dummySaveNumber; + FILETIME dummyTime; - fetchInformationFields(file, dummySaveNumber, dummyName, dummyLevel, - dummyLocation, dummyTime); - } + fetchInformationFields(file, dummySaveNumber, dummyName, dummyLevel, dummyLocation, + dummyTime); + } - QString ignore; - std::unique_ptr fields = std::make_unique(); + QString ignore; + std::unique_ptr fields = std::make_unique(); - //fields->Screenshot = file.readImage(384, true); + // fields->Screenshot = file.readImage(384, true); - uint8_t saveGameVersion = file.readChar(12); - file.read(ignore); // game version - file.read(ignore); // game version again? - file.readInt(); // plugin info size + uint8_t saveGameVersion = file.readChar(12); + file.read(ignore); // game version + file.read(ignore); // game version again? + file.readInt(); // plugin info size - fields->Plugins = file.readPlugins(); - if (saveGameVersion >= 82) { - fields->LightPlugins = file.readLightPlugins(); - } - file.closeCompressedData(); - file.close(); + fields->Plugins = file.readPlugins(); + if (saveGameVersion >= 82) { + fields->LightPlugins = file.readLightPlugins(); + } + file.closeCompressedData(); + file.close(); - return fields; + return fields; } diff --git a/src/games/starfield/src/starfieldsavegame.h b/src/games/starfield/src/starfieldsavegame.h index a4159f1b..d8189bfe 100644 --- a/src/games/starfield/src/starfieldsavegame.h +++ b/src/games/starfield/src/starfieldsavegame.h @@ -11,25 +11,17 @@ class GameStarfield; class StarfieldSaveGame : public GamebryoSaveGame { public: - StarfieldSaveGame(QString const &fileName, GameStarfield const* game); + StarfieldSaveGame(QString const& fileName, GameStarfield const* game); protected: - // Fetch easy-to-access information. - void getData( - FileWrapper& file - ) const; + void getData(FileWrapper& file) const; - void fetchInformationFields( - FileWrapper& file, - unsigned long& saveNumber, - QString& playerName, - unsigned short& playerLevel, - QString& playerLocation, - FILETIME& creationTime - ) const; + void fetchInformationFields(FileWrapper& file, unsigned long& saveNumber, + QString& playerName, unsigned short& playerLevel, + QString& playerLocation, FILETIME& creationTime) const; std::unique_ptr fetchDataFields() const override; }; -#endif // STARFIELDSAVEGAME_H +#endif // STARFIELDSAVEGAME_H diff --git a/src/games/starfield/src/starfieldscriptextender.cpp b/src/games/starfield/src/starfieldscriptextender.cpp index 25ebcf9a..15cf6cdd 100644 --- a/src/games/starfield/src/starfieldscriptextender.cpp +++ b/src/games/starfield/src/starfieldscriptextender.cpp @@ -3,10 +3,9 @@ #include #include -StarfieldScriptExtender::StarfieldScriptExtender(GameGamebryo const *game) : - GamebryoScriptExtender(game) -{ -} +StarfieldScriptExtender::StarfieldScriptExtender(GameGamebryo const* game) + : GamebryoScriptExtender(game) +{} QString StarfieldScriptExtender::BinaryName() const { diff --git a/src/games/starfield/src/starfieldscriptextender.h b/src/games/starfield/src/starfieldscriptextender.h index fa29317b..b7c27f13 100644 --- a/src/games/starfield/src/starfieldscriptextender.h +++ b/src/games/starfield/src/starfieldscriptextender.h @@ -8,11 +8,10 @@ class GameGamebryo; class StarfieldScriptExtender : public GamebryoScriptExtender { public: - StarfieldScriptExtender(GameGamebryo const *game); + StarfieldScriptExtender(GameGamebryo const* game); virtual QString BinaryName() const override; virtual QString PluginPath() const override; - }; -#endif // STARFIELDSCRIPTEXTENDER_H +#endif // STARFIELDSCRIPTEXTENDER_H diff --git a/src/games/starfield/src/starfieldunmanagedmods.cpp b/src/games/starfield/src/starfieldunmanagedmods.cpp index ce7dcbbc..6b42b226 100644 --- a/src/games/starfield/src/starfieldunmanagedmods.cpp +++ b/src/games/starfield/src/starfieldunmanagedmods.cpp @@ -1,27 +1,26 @@ #include "starfieldunmanagedmods.h" - -StarfieldUnmangedMods::StarfieldUnmangedMods(const GameGamebryo *game) - : GamebryoUnmangedMods(game) +StarfieldUnmangedMods::StarfieldUnmangedMods(const GameGamebryo* game) + : GamebryoUnmangedMods(game) {} -StarfieldUnmangedMods::~StarfieldUnmangedMods() -{} +StarfieldUnmangedMods::~StarfieldUnmangedMods() {} -QStringList StarfieldUnmangedMods::mods(bool onlyOfficial) const { +QStringList StarfieldUnmangedMods::mods(bool onlyOfficial) const +{ QStringList result; - QStringList pluginList = game()->primaryPlugins(); + QStringList pluginList = game()->primaryPlugins(); QStringList otherPlugins = game()->DLCPlugins(); otherPlugins.append(game()->CCPlugins()); for (QString plugin : otherPlugins) { pluginList.removeAll(plugin); } QDir dataDir(game()->dataDirectory()); - for (const QString &fileName : dataDir.entryList({ "*.esp", "*.esl", "*.esm" })) { + for (const QString& fileName : dataDir.entryList({"*.esp", "*.esl", "*.esm"})) { if (!pluginList.contains(fileName, Qt::CaseInsensitive)) { if (!onlyOfficial || pluginList.contains(fileName, Qt::CaseInsensitive)) { - result.append(fileName.chopped(4)); // trims the extension off + result.append(fileName.chopped(4)); // trims the extension off } } } @@ -29,17 +28,18 @@ QStringList StarfieldUnmangedMods::mods(bool onlyOfficial) const { return result; } -QStringList StarfieldUnmangedMods::secondaryFiles(const QString &modName) const { +QStringList StarfieldUnmangedMods::secondaryFiles(const QString& modName) const +{ // file extension in FO4 is .ba2 instead of bsa QStringList archives; QDir dataDir = game()->dataDirectory(); - for (const QString &archiveName : dataDir.entryList({modName + "*.ba2"})) { + for (const QString& archiveName : dataDir.entryList({modName + "*.ba2"})) { archives.append(dataDir.absoluteFilePath(archiveName)); } return archives; } -QString StarfieldUnmangedMods::displayName(const QString &modName) const +QString StarfieldUnmangedMods::displayName(const QString& modName) const { // unlike in earlier games, in fallout 4 the file name doesn't correspond to // the public name diff --git a/src/games/starfield/src/starfieldunmanagedmods.h b/src/games/starfield/src/starfieldunmanagedmods.h index bea9be89..3b9f2e2d 100644 --- a/src/games/starfield/src/starfieldunmanagedmods.h +++ b/src/games/starfield/src/starfieldunmanagedmods.h @@ -1,21 +1,18 @@ #ifndef STARFIELDUNMANAGEDMODS_H #define STARFIELDUNMANAGEDMODS_H - #include "gamebryounmanagedmods.h" #include - -class StarfieldUnmangedMods : public GamebryoUnmangedMods { +class StarfieldUnmangedMods : public GamebryoUnmangedMods +{ public: - StarfieldUnmangedMods(const GameGamebryo *game); + StarfieldUnmangedMods(const GameGamebryo* game); ~StarfieldUnmangedMods(); virtual QStringList mods(bool onlyOfficial) const override; - virtual QStringList secondaryFiles(const QString &modName) const override; - virtual QString displayName(const QString &modName) const override; + virtual QStringList secondaryFiles(const QString& modName) const override; + virtual QString displayName(const QString& modName) const override; }; - - -#endif // STARFIELDUNMANAGEDMODS_H +#endif // STARFIELDUNMANAGEDMODS_H diff --git a/src/games/starfield/src/vdf_parser.h b/src/games/starfield/src/vdf_parser.h index 415e49fe..771ba828 100644 --- a/src/games/starfield/src/vdf_parser.h +++ b/src/games/starfield/src/vdf_parser.h @@ -1,50 +1,50 @@ -//MIT License +// MIT License // -//Copyright(c) 2016 Matthias Moeller +// Copyright(c) 2016 Matthias Moeller // -//Permission is hereby granted, free of charge, to any person obtaining a copy -//of this software and associated documentation files(the "Software"), to deal -//in the Software without restriction, including without limitation the rights -//to use, copy, modify, merge, publish, distribute, sublicense, and / or sell -//copies of the Software, and to permit persons to whom the Software is -//furnished to do so, subject to the following conditions : +// Permission is hereby granted, free of charge, to any person obtaining a copy +// of this software and associated documentation files(the "Software"), to deal +// in the Software without restriction, including without limitation the rights +// to use, copy, modify, merge, publish, distribute, sublicense, and / or sell +// copies of the Software, and to permit persons to whom the Software is +// furnished to do so, subject to the following conditions : // -//The above copyright notice and this permission notice shall be included in all -//copies or substantial portions of the Software. +// The above copyright notice and this permission notice shall be included in all +// copies or substantial portions of the Software. // -//THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -//IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -//FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.IN NO EVENT SHALL THE -//AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER -//LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, -//OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE -//SOFTWARE. +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.IN NO EVENT SHALL THE +// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +// SOFTWARE. #ifndef __TYTI_STEAM_VDF_PARSER_H__ #define __TYTI_STEAM_VDF_PARSER_H__ -#include -#include -#include -#include -#include -#include -#include #include -#include +#include #include +#include +#include +#include +#include +#include +#include +#include -#include #include +#include -//for wstring support +// for wstring support #include #include // internal #include -//VS < 2015 has only partial C++11 support +// VS < 2015 has only partial C++11 support #if defined(_MSC_VER) && _MSC_VER < 1900 #ifndef CONSTEXPR #define CONSTEXPR @@ -68,651 +68,660 @@ namespace tyti { - namespace vdf +namespace vdf +{ + namespace detail + { + /////////////////////////////////////////////////////////////////////////// + // Helper functions selecting the right encoding (char/wchar_T) + /////////////////////////////////////////////////////////////////////////// + + template + struct literal_macro_help { - namespace detail - { - /////////////////////////////////////////////////////////////////////////// - // Helper functions selecting the right encoding (char/wchar_T) - /////////////////////////////////////////////////////////////////////////// + static CONSTEXPR const char* result(const char* c, const wchar_t*) NOEXCEPT + { + return c; + } + static CONSTEXPR const char result(const char c, const wchar_t) NOEXCEPT + { + return c; + } + }; - template - struct literal_macro_help - { - static CONSTEXPR const char* result(const char* c, const wchar_t*) NOEXCEPT - { - return c; - } - static CONSTEXPR const char result(const char c, const wchar_t) NOEXCEPT - { - return c; - } - }; - - template <> - struct literal_macro_help - { - static CONSTEXPR const wchar_t* result(const char*, const wchar_t* wc) NOEXCEPT - { - return wc; - } - static CONSTEXPR const wchar_t result(const char, const wchar_t wc) NOEXCEPT - { - return wc; - } - }; + template <> + struct literal_macro_help + { + static CONSTEXPR const wchar_t* result(const char*, const wchar_t* wc) NOEXCEPT + { + return wc; + } + static CONSTEXPR const wchar_t result(const char, const wchar_t wc) NOEXCEPT + { + return wc; + } + }; #define TYTI_L(type, text) vdf::detail::literal_macro_help::result(text, L##text) - inline std::string string_converter(const std::string& w) NOEXCEPT - { - return w; - } + inline std::string string_converter(const std::string& w) NOEXCEPT + { + return w; + } - // utility wrapper to adapt locale-bound facets for wstring/wbuffer convert - // from cppreference - template - struct deletable_facet : Facet - { - template - deletable_facet(Args &&... args) : Facet(std::forward(args)...) {} - ~deletable_facet() {} - }; + // utility wrapper to adapt locale-bound facets for wstring/wbuffer convert + // from cppreference + template + struct deletable_facet : Facet + { + template + deletable_facet(Args&&... args) : Facet(std::forward(args)...) + {} + ~deletable_facet() {} + }; - inline std::string string_converter(const std::wstring& w) //todo: use us-locale - { - std::wstring_convert>> conv1; - return conv1.to_bytes(w); - } + inline std::string string_converter(const std::wstring& w) // todo: use us-locale + { + std::wstring_convert>> + conv1; + return conv1.to_bytes(w); + } - /////////////////////////////////////////////////////////////////////////// - // Writer helper functions - /////////////////////////////////////////////////////////////////////////// + /////////////////////////////////////////////////////////////////////////// + // Writer helper functions + /////////////////////////////////////////////////////////////////////////// - template - class tabs - { - const size_t t; + template + class tabs + { + const size_t t; - public: - explicit CONSTEXPR tabs(size_t i) NOEXCEPT : t(i) {} - std::basic_string print() const { return std::basic_string(t, TYTI_L(charT, '\t')); } - inline CONSTEXPR tabs operator+(size_t i) const NOEXCEPT - { - return tabs(t + i); - } - }; + public: + explicit CONSTEXPR tabs(size_t i) NOEXCEPT : t(i) {} + std::basic_string print() const + { + return std::basic_string(t, TYTI_L(charT, '\t')); + } + inline CONSTEXPR tabs operator+(size_t i) const NOEXCEPT { return tabs(t + i); } + }; - template - oStreamT& operator<<(oStreamT& s, const tabs t) - { - s << t.print(); - return s; - } - } // end namespace detail + template + oStreamT& operator<<(oStreamT& s, const tabs t) + { + s << t.print(); + return s; + } + } // end namespace detail - /////////////////////////////////////////////////////////////////////////// - // Interface - /////////////////////////////////////////////////////////////////////////// + /////////////////////////////////////////////////////////////////////////// + // Interface + /////////////////////////////////////////////////////////////////////////// - /// custom objects and their corresponding write functions + /// custom objects and their corresponding write functions - /// basic object node. Every object has a name and can contains attributes saved as key_value pairs or childrens - template - struct basic_object - { - typedef CharT char_type; - std::basic_string name; - std::unordered_map, std::basic_string> attribs; - std::unordered_map, std::shared_ptr>> childs; + /// basic object node. Every object has a name and can contains attributes saved as + /// key_value pairs or childrens + template + struct basic_object + { + typedef CharT char_type; + std::basic_string name; + std::unordered_map, std::basic_string> + attribs; + std::unordered_map, + std::shared_ptr>> + childs; - void add_attribute(std::basic_string key, std::basic_string value) - { - attribs.emplace(std::move(key), std::move(value)); - } - void add_child(std::unique_ptr> child) - { - std::shared_ptr> obj{ child.release() }; - childs.emplace(obj->name, obj); - } - void set_name(std::basic_string n) - { - name = std::move(n); - } - }; + void add_attribute(std::basic_string key, + std::basic_string value) + { + attribs.emplace(std::move(key), std::move(value)); + } + void add_child(std::unique_ptr> child) + { + std::shared_ptr> obj{child.release()}; + childs.emplace(obj->name, obj); + } + void set_name(std::basic_string n) { name = std::move(n); } + }; - template - struct basic_multikey_object - { - typedef CharT char_type; - std::basic_string name; - std::unordered_multimap, std::basic_string> attribs; - std::unordered_multimap, std::shared_ptr>> childs; + template + struct basic_multikey_object + { + typedef CharT char_type; + std::basic_string name; + std::unordered_multimap, std::basic_string> + attribs; + std::unordered_multimap, + std::shared_ptr>> + childs; - void add_attribute(std::basic_string key, std::basic_string value) - { - attribs.emplace(std::move(key), std::move(value)); - } - void add_child(std::unique_ptr> child) - { - std::shared_ptr> obj{ child.release() }; - childs.emplace(obj->name, obj); - } - void set_name(std::basic_string n) - { - name = std::move(n); - } - }; + void add_attribute(std::basic_string key, + std::basic_string value) + { + attribs.emplace(std::move(key), std::move(value)); + } + void add_child(std::unique_ptr> child) + { + std::shared_ptr> obj{child.release()}; + childs.emplace(obj->name, obj); + } + void set_name(std::basic_string n) { name = std::move(n); } + }; - typedef basic_object object; - typedef basic_object wobject; - typedef basic_multikey_object multikey_object; - typedef basic_multikey_object wmultikey_object; + typedef basic_object object; + typedef basic_object wobject; + typedef basic_multikey_object multikey_object; + typedef basic_multikey_object wmultikey_object; - struct Options - { - bool strip_escape_symbols; - bool ignore_all_platform_conditionals; - bool ignore_includes; + struct Options + { + bool strip_escape_symbols; + bool ignore_all_platform_conditionals; + bool ignore_includes; - Options() : strip_escape_symbols(true), ignore_all_platform_conditionals(false), ignore_includes(false) {} - }; + Options() + : strip_escape_symbols(true), ignore_all_platform_conditionals(false), + ignore_includes(false) + {} + }; - //forward decls - //forward decl - template - OutputT read(iStreamT& inStream, const Options& opt = Options{}); + // forward decls + // forward decl + template + OutputT read(iStreamT& inStream, const Options& opt = Options{}); - /** \brief writes given object tree in vdf format to given stream. - Output is prettyfied, using tabs - */ - template - void write(oStreamT& s, const T& r, - const detail::tabs tab = detail::tabs(0)) - { - typedef typename oStreamT::char_type charT; - using namespace detail; - s << tab << TYTI_L(charT, '"') << r.name << TYTI_L(charT, "\"\n") << tab << TYTI_L(charT, "{\n"); - for (const auto& i : r.attribs) - s << tab + 1 << TYTI_L(charT, '"') << i.first << TYTI_L(charT, "\"\t\t\"") << i.second << TYTI_L(charT, "\"\n"); - for (const auto& i : r.childs) - if (i.second) - write(s, *i.second, tab + 1); - s << tab << TYTI_L(charT, "}\n"); - } + /** \brief writes given object tree in vdf format to given stream. + Output is prettyfied, using tabs + */ + template + void write(oStreamT& s, const T& r, + const detail::tabs tab = + detail::tabs(0)) + { + typedef typename oStreamT::char_type charT; + using namespace detail; + s << tab << TYTI_L(charT, '"') << r.name << TYTI_L(charT, "\"\n") << tab + << TYTI_L(charT, "{\n"); + for (const auto& i : r.attribs) + s << tab + 1 << TYTI_L(charT, '"') << i.first << TYTI_L(charT, "\"\t\t\"") + << i.second << TYTI_L(charT, "\"\n"); + for (const auto& i : r.childs) + if (i.second) + write(s, *i.second, tab + 1); + s << tab << TYTI_L(charT, "}\n"); + } - namespace detail - { - template - std::basic_string read_file(iStreamT& inStream) - { - // cache the file - typedef typename iStreamT::char_type charT; - std::basic_string str; - inStream.seekg(0, std::ios::end); - str.resize(static_cast(inStream.tellg())); - if (str.empty()) - return str; + namespace detail + { + template + std::basic_string read_file(iStreamT& inStream) + { + // cache the file + typedef typename iStreamT::char_type charT; + std::basic_string str; + inStream.seekg(0, std::ios::end); + str.resize(static_cast(inStream.tellg())); + if (str.empty()) + return str; - inStream.seekg(0, std::ios::beg); - inStream.read(&str[0], str.size()); - return str; - } + inStream.seekg(0, std::ios::beg); + inStream.read(&str[0], str.size()); + return str; + } - /** \brief Read VDF formatted sequences defined by the range [first, last). - If the file is mailformatted, parser will try to read it until it can. - @param first begin iterator - @param end end iterator - @param exclude_files list of files which cant be included anymore. - prevents circular includes + /** \brief Read VDF formatted sequences defined by the range [first, last). + If the file is mailformatted, parser will try to read it until it can. + @param first begin iterator + @param end end iterator + @param exclude_files list of files which cant be included anymore. + prevents circular includes - can thow: - - "std::runtime_error" if a parsing error occured - - "std::bad_alloc" if not enough memory coup be allocated - */ - template - std::vector> read_internal(IterT first, const IterT last, - std::unordered_set::value_type>>& exclude_files, - const Options& opt) - { - static_assert(std::is_default_constructible::value, - "Output Type must be default constructible (provide constructor without arguments)"); - static_assert(std::is_move_constructible::value, + can thow: + - "std::runtime_error" if a parsing error occured + - "std::bad_alloc" if not enough memory coup be allocated + */ + template + std::vector> + read_internal(IterT first, const IterT last, + std::unordered_set::value_type>>& exclude_files, + const Options& opt) + { + static_assert(std::is_default_constructible::value, + "Output Type must be default constructible (provide constructor " + "without arguments)"); + static_assert(std::is_move_constructible::value, "Output Type must be move constructible"); - typedef typename std::iterator_traits::value_type charT; + typedef typename std::iterator_traits::value_type charT; - const std::basic_string comment_end_str = TYTI_L(charT, "*/"); - const std::basic_string whitespaces = TYTI_L(charT, " \n\v\f\r\t"); + const std::basic_string comment_end_str = TYTI_L(charT, "*/"); + const std::basic_string whitespaces = TYTI_L(charT, " \n\v\f\r\t"); #ifdef WIN32 - std::function&)> is_platform_str = [](const std::basic_string& in) { - return in == TYTI_L(charT, "$WIN32") || in == TYTI_L(charT, "$WINDOWS"); - }; + std::function&)> is_platform_str = + [](const std::basic_string& in) { + return in == TYTI_L(charT, "$WIN32") || in == TYTI_L(charT, "$WINDOWS"); + }; #elif __APPLE__ - // WIN32 stands for pc in general - std::function&)> is_platform_str = [](const std::basic_string& in) { - return in == TYTI_L(charT, "$WIN32") || in == TYTI_L(charT, "$POSIX") || in == TYTI_L(charT, "$OSX"); - }; + // WIN32 stands for pc in general + std::function&)> is_platform_str = + [](const std::basic_string& in) { + return in == TYTI_L(charT, "$WIN32") || in == TYTI_L(charT, "$POSIX") || + in == TYTI_L(charT, "$OSX"); + }; #elif __linux__ - // WIN32 stands for pc in general - std::function&)> is_platform_str = [](const std::basic_string& in) { - return in == TYTI_L(charT, "$WIN32") || in == TYTI_L(charT, "$POSIX") || in == TYTI_L(charT, "$LINUX"); - }; + // WIN32 stands for pc in general + std::function&)> is_platform_str = + [](const std::basic_string& in) { + return in == TYTI_L(charT, "$WIN32") || in == TYTI_L(charT, "$POSIX") || + in == TYTI_L(charT, "$LINUX"); + }; #else - std::function&)> is_platform_str = [](const std::basic_string& in) { - return false; - }; + std::function&)> is_platform_str = + [](const std::basic_string& in) { + return false; + }; #endif - if (opt.ignore_all_platform_conditionals) - is_platform_str = [](const std::basic_string&) { - return false; - }; + if (opt.ignore_all_platform_conditionals) + is_platform_str = [](const std::basic_string&) { + return false; + }; - // function for skipping a comment block - // iter: iterator poition to the position after a '/' - auto skip_comments = [&comment_end_str](IterT iter, const IterT& last) -> IterT { - ++iter; - if (iter != last) - { - if (*iter == TYTI_L(charT, '/')) - { - // line comment, skip whole line - iter = std::find(iter + 1, last, TYTI_L(charT, '\n')); - } + // function for skipping a comment block + // iter: iterator poition to the position after a '/' + auto skip_comments = [&comment_end_str](IterT iter, const IterT& last) -> IterT { + ++iter; + if (iter != last) { + if (*iter == TYTI_L(charT, '/')) { + // line comment, skip whole line + iter = std::find(iter + 1, last, TYTI_L(charT, '\n')); + } - if (*iter == '*') - { - // block comment, skip until next occurance of "*\" - iter = std::search(iter + 1, last, std::begin(comment_end_str), std::end(comment_end_str)); - iter += 2; - } - } - return iter; - }; + if (*iter == '*') { + // block comment, skip until next occurance of "*\" + iter = std::search(iter + 1, last, std::begin(comment_end_str), + std::end(comment_end_str)); + iter += 2; + } + } + return iter; + }; - auto end_quote = [](IterT iter, const IterT& last) -> IterT { - const auto begin = iter; - auto last_esc = iter; - do - { - ++iter; - iter = std::find(iter, last, TYTI_L(charT, '\"')); - if (iter == last) - break; + auto end_quote = [](IterT iter, const IterT& last) -> IterT { + const auto begin = iter; + auto last_esc = iter; + do { + ++iter; + iter = std::find(iter, last, TYTI_L(charT, '\"')); + if (iter == last) + break; - last_esc = std::prev(iter); - while (last_esc != begin && *last_esc == '\\') - --last_esc; - } while (!(std::distance(last_esc, iter) % 2)); - if (iter == last) - throw std::runtime_error{ "quote was opened but not closed." }; - return iter; - }; + last_esc = std::prev(iter); + while (last_esc != begin && *last_esc == '\\') + --last_esc; + } while (!(std::distance(last_esc, iter) % 2)); + if (iter == last) + throw std::runtime_error{"quote was opened but not closed."}; + return iter; + }; - auto end_word = [&whitespaces](IterT iter, const IterT& last) -> IterT { - const auto begin = iter; - auto last_esc = iter; - do - { - ++iter; - iter = std::find_first_of(iter, last, std::begin(whitespaces), std::end(whitespaces)); - if (iter == last) - break; + auto end_word = [&whitespaces](IterT iter, const IterT& last) -> IterT { + const auto begin = iter; + auto last_esc = iter; + do { + ++iter; + iter = std::find_first_of(iter, last, std::begin(whitespaces), + std::end(whitespaces)); + if (iter == last) + break; - last_esc = std::prev(iter); - while (last_esc != begin && *last_esc == '\\') - --last_esc; - } while (!(std::distance(last_esc, iter) % 2)); - //if (iter == last) - // throw std::runtime_error{ "word wasnt properly ended" }; - return iter; - }; + last_esc = std::prev(iter); + while (last_esc != begin && *last_esc == '\\') + --last_esc; + } while (!(std::distance(last_esc, iter) % 2)); + // if (iter == last) + // throw std::runtime_error{ "word wasnt properly ended" }; + return iter; + }; - auto skip_whitespaces = [&whitespaces](IterT iter, const IterT& last) -> IterT { - iter = std::find_if_not(iter, last, [&whitespaces](charT c) { - // return true if whitespace - return std::any_of(std::begin(whitespaces), std::end(whitespaces), [c](charT pc) { return pc == c; }); - }); - return iter; - }; + auto skip_whitespaces = [&whitespaces](IterT iter, const IterT& last) -> IterT { + iter = std::find_if_not(iter, last, [&whitespaces](charT c) { + // return true if whitespace + return std::any_of(std::begin(whitespaces), std::end(whitespaces), + [c](charT pc) { + return pc == c; + }); + }); + return iter; + }; - std::function&)> strip_escape_symbols = [](std::basic_string& s) { - auto quote_searcher = [&s](size_t pos) { return s.find(TYTI_L(charT, "\\\""), pos); }; - auto p = quote_searcher(0); - while (p != s.npos) - { - s.replace(p, 2, TYTI_L(charT, "\"")); - p = quote_searcher(p); - } - auto searcher = [&s](size_t pos) { return s.find(TYTI_L(charT, "\\\\"), pos); }; - p = searcher(0); - while (p != s.npos) - { - s.replace(p, 2, TYTI_L(charT, "\\")); - p = searcher(p); - } - }; + std::function&)> strip_escape_symbols = + [](std::basic_string& s) { + auto quote_searcher = [&s](size_t pos) { + return s.find(TYTI_L(charT, "\\\""), pos); + }; + auto p = quote_searcher(0); + while (p != s.npos) { + s.replace(p, 2, TYTI_L(charT, "\"")); + p = quote_searcher(p); + } + auto searcher = [&s](size_t pos) { + return s.find(TYTI_L(charT, "\\\\"), pos); + }; + p = searcher(0); + while (p != s.npos) { + s.replace(p, 2, TYTI_L(charT, "\\")); + p = searcher(p); + } + }; - if (!opt.strip_escape_symbols) - strip_escape_symbols = [](std::basic_string&) {}; + if (!opt.strip_escape_symbols) + strip_escape_symbols = [](std::basic_string&) {}; - auto conditional_fullfilled = [&skip_whitespaces, &is_platform_str](IterT& iter, const IterT& last) { - iter = skip_whitespaces(iter, last); - if (*iter == '[') - { - ++iter; - const auto end = std::find(iter, last, ']'); - const bool negate = *iter == '!'; - if (negate) - ++iter; - auto conditional = std::basic_string(iter, end); + auto conditional_fullfilled = [&skip_whitespaces, + &is_platform_str](IterT& iter, const IterT& last) { + iter = skip_whitespaces(iter, last); + if (*iter == '[') { + ++iter; + const auto end = std::find(iter, last, ']'); + const bool negate = *iter == '!'; + if (negate) + ++iter; + auto conditional = std::basic_string(iter, end); - const bool is_platform = is_platform_str(conditional); - iter = end + 1; + const bool is_platform = is_platform_str(conditional); + iter = end + 1; - return static_cast(is_platform ^ negate); - } - return true; - }; + return static_cast(is_platform ^ negate); + } + return true; + }; - //read header - // first, quoted name - std::unique_ptr curObj = nullptr; - std::vector> roots; - std::stack> lvls; - auto curIter = first; + // read header + // first, quoted name + std::unique_ptr curObj = nullptr; + std::vector> roots; + std::stack> lvls; + auto curIter = first; - while (curIter != last && *curIter != '\0') - { - //find first starting attrib/child, or ending - curIter = skip_whitespaces(curIter, last); - if (curIter == last || *curIter == '\0') - break; - if (*curIter == TYTI_L(charT, '/')) - { - curIter = skip_comments(curIter, last); - } - else if (*curIter != TYTI_L(charT, '}')) - { + while (curIter != last && *curIter != '\0') { + // find first starting attrib/child, or ending + curIter = skip_whitespaces(curIter, last); + if (curIter == last || *curIter == '\0') + break; + if (*curIter == TYTI_L(charT, '/')) { + curIter = skip_comments(curIter, last); + } else if (*curIter != TYTI_L(charT, '}')) { - // get key - const auto keyEnd = (*curIter == TYTI_L(charT, '\"')) ? end_quote(curIter, last) : end_word(curIter, last); - if (*curIter == TYTI_L(charT, '\"')) - ++curIter; - std::basic_string key(curIter, keyEnd); - strip_escape_symbols(key); - curIter = keyEnd + ((*keyEnd == TYTI_L(charT, '\"')) ? 1 : 0); + // get key + const auto keyEnd = (*curIter == TYTI_L(charT, '\"')) + ? end_quote(curIter, last) + : end_word(curIter, last); + if (*curIter == TYTI_L(charT, '\"')) + ++curIter; + std::basic_string key(curIter, keyEnd); + strip_escape_symbols(key); + curIter = keyEnd + ((*keyEnd == TYTI_L(charT, '\"')) ? 1 : 0); - curIter = skip_whitespaces(curIter, last); + curIter = skip_whitespaces(curIter, last); - auto conditional = conditional_fullfilled(curIter, last); - if (!conditional) - continue; + auto conditional = conditional_fullfilled(curIter, last); + if (!conditional) + continue; - while (*curIter == TYTI_L(charT, '/')) - { + while (*curIter == TYTI_L(charT, '/')) { - curIter = skip_comments(curIter, last); - if (curIter == last || *curIter == '}') - throw std::runtime_error{ "key declared, but no value" }; - curIter = skip_whitespaces(curIter, last); - if (curIter == last || *curIter == '}') - throw std::runtime_error{ "key declared, but no value" }; - } - // get value - if (*curIter != '{') - { - const auto valueEnd = (*curIter == TYTI_L(charT, '\"')) ? end_quote(curIter, last) : end_word(curIter, last); - if (*curIter == TYTI_L(charT, '\"')) - ++curIter; + curIter = skip_comments(curIter, last); + if (curIter == last || *curIter == '}') + throw std::runtime_error{"key declared, but no value"}; + curIter = skip_whitespaces(curIter, last); + if (curIter == last || *curIter == '}') + throw std::runtime_error{"key declared, but no value"}; + } + // get value + if (*curIter != '{') { + const auto valueEnd = (*curIter == TYTI_L(charT, '\"')) + ? end_quote(curIter, last) + : end_word(curIter, last); + if (*curIter == TYTI_L(charT, '\"')) + ++curIter; - auto value = std::basic_string(curIter, valueEnd); - strip_escape_symbols(value); - curIter = valueEnd + ((*valueEnd == TYTI_L(charT, '\"')) ? 1 : 0); + auto value = std::basic_string(curIter, valueEnd); + strip_escape_symbols(value); + curIter = valueEnd + ((*valueEnd == TYTI_L(charT, '\"')) ? 1 : 0); - auto conditional = conditional_fullfilled(curIter, last); - if (!conditional) - continue; + auto conditional = conditional_fullfilled(curIter, last); + if (!conditional) + continue; - // process value - if (key != TYTI_L(charT, "#include") && key != TYTI_L(charT, "#base")) - { - if (curObj) - { - curObj->add_attribute(std::move(key), std::move(value)); - } - else - { - throw std::runtime_error{ "unexpected key without object" }; - } - } - else - { - if (!opt.ignore_includes && exclude_files.find(value) == exclude_files.end()) - { - exclude_files.insert(value); - std::basic_ifstream i(detail::string_converter(value)); - auto str = read_file(i); - auto file_objs = read_internal(str.begin(), str.end(), exclude_files, opt); - for (auto& n : file_objs) - { - if (curObj) - curObj->add_child(std::move(n)); - else - roots.push_back(std::move(n)); - } - exclude_files.erase(value); - } - } - } - else if (*curIter == '{') - { - if (curObj) - lvls.push(std::move(curObj)); - curObj = std::make_unique(); - curObj->set_name(std::move(key)); - ++curIter; - } - } - //end of new object - else if (curObj && *curIter == TYTI_L(charT, '}')) - { - if (!lvls.empty()) - { - //get object before - std::unique_ptr prev{ std::move(lvls.top()) }; - lvls.pop(); - - // add finished obj to obj before and release it from processing - prev->add_child(std::move(curObj)); - curObj = std::move(prev); - } - else - { - roots.push_back(std::move(curObj)); - curObj.reset(); - } - ++curIter; - } - else - { - throw std::runtime_error{ "unexpected '}'" }; - } + // process value + if (key != TYTI_L(charT, "#include") && key != TYTI_L(charT, "#base")) { + if (curObj) { + curObj->add_attribute(std::move(key), std::move(value)); + } else { + throw std::runtime_error{"unexpected key without object"}; + } + } else { + if (!opt.ignore_includes && + exclude_files.find(value) == exclude_files.end()) { + exclude_files.insert(value); + std::basic_ifstream i(detail::string_converter(value)); + auto str = read_file(i); + auto file_objs = + read_internal(str.begin(), str.end(), exclude_files, opt); + for (auto& n : file_objs) { + if (curObj) + curObj->add_child(std::move(n)); + else + roots.push_back(std::move(n)); } - if (curObj != nullptr || !lvls.empty()) - { - throw std::runtime_error{ "object is not closed with '}'" }; - } - - return roots; + exclude_files.erase(value); + } } - - } // namespace detail - - /** \brief Read VDF formatted sequences defined by the range [first, last). - If the file is mailformatted, parser will try to read it until it can. - @param first begin iterator - @param end end iterator - - can thow: - - "std::runtime_error" if a parsing error occured - - "std::bad_alloc" if not enough memory coup be allocated - */ - template - OutputT read(IterT first, const IterT last, const Options& opt = Options{}) - { - auto exclude_files = std::unordered_set::value_type>>{}; - auto roots = detail::read_internal(first, last, exclude_files, opt); - - OutputT result; - if (roots.size() > 1) - { - for (auto& i : roots) - result.add_child(std::move(i)); - } - else if (roots.size() == 1) - result = std::move(*roots[0]); - - return result; + } else if (*curIter == '{') { + if (curObj) + lvls.push(std::move(curObj)); + curObj = std::make_unique(); + curObj->set_name(std::move(key)); + ++curIter; + } } + // end of new object + else if (curObj && *curIter == TYTI_L(charT, '}')) { + if (!lvls.empty()) { + // get object before + std::unique_ptr prev{std::move(lvls.top())}; + lvls.pop(); - /** \brief Read VDF formatted sequences defined by the range [first, last). - If the file is mailformatted, parser will try to read it until it can. - @param first begin iterator - @param end end iterator - @param ec output bool. 0 if ok, otherwise, holds an system error code - - Possible error codes: - std::errc::protocol_error: file is mailformatted - std::errc::not_enough_memory: not enough space - std::errc::invalid_argument: iterators throws e.g. out of range - */ - template - OutputT read(IterT first, IterT last, std::error_code& ec, const Options& opt = Options{}) NOEXCEPT - - { - ec.clear(); - OutputT r{}; - try - { - r = read(first, last, opt); - } - catch (std::runtime_error&) - { - ec = std::make_error_code(std::errc::protocol_error); - } - catch (std::bad_alloc&) - { - ec = std::make_error_code(std::errc::not_enough_memory); - } - catch (...) - { - ec = std::make_error_code(std::errc::invalid_argument); - } - return r; + // add finished obj to obj before and release it from processing + prev->add_child(std::move(curObj)); + curObj = std::move(prev); + } else { + roots.push_back(std::move(curObj)); + curObj.reset(); + } + ++curIter; + } else { + throw std::runtime_error{"unexpected '}'"}; } + } + if (curObj != nullptr || !lvls.empty()) { + throw std::runtime_error{"object is not closed with '}'"}; + } - /** \brief Read VDF formatted sequences defined by the range [first, last). - If the file is mailformatted, parser will try to read it until it can. - @param first begin iterator - @param end end iterator - @param ok output bool. true, if parser successed, false, if parser failed - */ - template - OutputT read(IterT first, const IterT last, bool* ok, const Options& opt = Options{}) NOEXCEPT - { - std::error_code ec; - auto r = read(first, last, ec, opt); - if (ok) - *ok = !ec; - return r; - } + return roots; + } - template - inline auto read(IterT first, const IterT last, bool* ok, const Options& opt = Options{}) NOEXCEPT -> basic_object::value_type> - { - return read::value_type>>(first, last, ok, opt); - } + } // namespace detail - template - inline auto read(IterT first, IterT last, std::error_code& ec, const Options& opt = Options{}) NOEXCEPT - -> basic_object::value_type> - { - return read::value_type>>(first, last, ec, opt); - } + /** \brief Read VDF formatted sequences defined by the range [first, last). + If the file is mailformatted, parser will try to read it until it can. + @param first begin iterator + @param end end iterator - template - inline auto read(IterT first, const IterT last, const Options& opt = Options{}) - -> basic_object::value_type> - { - return read::value_type>>(first, last, opt); - } + can thow: + - "std::runtime_error" if a parsing error occured + - "std::bad_alloc" if not enough memory coup be allocated + */ + template + OutputT read(IterT first, const IterT last, const Options& opt = Options{}) + { + auto exclude_files = std::unordered_set< + std::basic_string::value_type>>{}; + auto roots = detail::read_internal(first, last, exclude_files, opt); - /** \brief Loads a stream (e.g. filestream) into the memory and parses the vdf formatted data. - throws "std::bad_alloc" if file buffer could not be allocated - */ - template - OutputT read(iStreamT& inStream, std::error_code& ec, const Options& opt = Options{}) - { - // cache the file - typedef typename iStreamT::char_type charT; - std::basic_string str = detail::read_file(inStream); + OutputT result; + if (roots.size() > 1) { + for (auto& i : roots) + result.add_child(std::move(i)); + } else if (roots.size() == 1) + result = std::move(*roots[0]); - // parse it - return read(str.begin(), str.end(), ec, opt); - } + return result; + } - template - inline basic_object read(iStreamT& inStream, std::error_code& ec, const Options& opt = Options{}) - { - return read>(inStream, ec, opt); - } + /** \brief Read VDF formatted sequences defined by the range [first, last). + If the file is mailformatted, parser will try to read it until it can. + @param first begin iterator + @param end end iterator + @param ec output bool. 0 if ok, otherwise, holds an system error code - /** \brief Loads a stream (e.g. filestream) into the memory and parses the vdf formatted data. - throws "std::bad_alloc" if file buffer could not be allocated - ok == false, if a parsing error occured - */ - template - OutputT read(iStreamT& inStream, bool* ok, const Options& opt = Options{}) - { - std::error_code ec; - const auto r = read(inStream, ec, opt); - if (ok) - *ok = !ec; - return r; - } + Possible error codes: + std::errc::protocol_error: file is mailformatted + std::errc::not_enough_memory: not enough space + std::errc::invalid_argument: iterators throws e.g. out of range + */ + template + OutputT read(IterT first, IterT last, std::error_code& ec, + const Options& opt = Options{}) NOEXCEPT - template - inline basic_object read(iStreamT& inStream, bool* ok, const Options& opt = Options{}) - { - return read>(inStream, ok, opt); - } + { + ec.clear(); + OutputT r{}; + try { + r = read(first, last, opt); + } catch (std::runtime_error&) { + ec = std::make_error_code(std::errc::protocol_error); + } catch (std::bad_alloc&) { + ec = std::make_error_code(std::errc::not_enough_memory); + } catch (...) { + ec = std::make_error_code(std::errc::invalid_argument); + } + return r; + } - /** \brief Loads a stream (e.g. filestream) into the memory and parses the vdf formatted data. - throws "std::bad_alloc" if file buffer could not be allocated - throws "std::runtime_error" if a parsing error occured - */ - template - OutputT read(iStreamT& inStream, const Options& opt) - { + /** \brief Read VDF formatted sequences defined by the range [first, last). + If the file is mailformatted, parser will try to read it until it can. + @param first begin iterator + @param end end iterator + @param ok output bool. true, if parser successed, false, if parser failed + */ + template + OutputT read(IterT first, const IterT last, bool* ok, + const Options& opt = Options{}) NOEXCEPT + { + std::error_code ec; + auto r = read(first, last, ec, opt); + if (ok) + *ok = !ec; + return r; + } - // cache the file - typedef typename iStreamT::char_type charT; - std::basic_string str = detail::read_file(inStream); - // parse it - return read(str.begin(), str.end(), opt); - } + template + inline auto read(IterT first, const IterT last, bool* ok, + const Options& opt = Options{}) NOEXCEPT + ->basic_object::value_type> + { + return read::value_type>>( + first, last, ok, opt); + } - template - inline basic_object read(iStreamT& inStream, const Options& opt = Options{}) - { - return read>(inStream, opt); - } + template + inline auto read(IterT first, IterT last, std::error_code& ec, + const Options& opt = Options{}) NOEXCEPT + ->basic_object::value_type> + { + return read::value_type>>( + first, last, ec, opt); + } - } // namespace vdf -} // namespace tyti + template + inline auto read(IterT first, const IterT last, const Options& opt = Options{}) + -> basic_object::value_type> + { + return read::value_type>>( + first, last, opt); + } + + /** \brief Loads a stream (e.g. filestream) into the memory and parses the vdf + formatted data. throws "std::bad_alloc" if file buffer could not be allocated + */ + template + OutputT read(iStreamT& inStream, std::error_code& ec, const Options& opt = Options{}) + { + // cache the file + typedef typename iStreamT::char_type charT; + std::basic_string str = detail::read_file(inStream); + + // parse it + return read(str.begin(), str.end(), ec, opt); + } + + template + inline basic_object + read(iStreamT& inStream, std::error_code& ec, const Options& opt = Options{}) + { + return read>(inStream, ec, opt); + } + + /** \brief Loads a stream (e.g. filestream) into the memory and parses the vdf + formatted data. throws "std::bad_alloc" if file buffer could not be allocated ok == + false, if a parsing error occured + */ + template + OutputT read(iStreamT& inStream, bool* ok, const Options& opt = Options{}) + { + std::error_code ec; + const auto r = read(inStream, ec, opt); + if (ok) + *ok = !ec; + return r; + } + + template + inline basic_object read(iStreamT& inStream, bool* ok, + const Options& opt = Options{}) + { + return read>(inStream, ok, opt); + } + + /** \brief Loads a stream (e.g. filestream) into the memory and parses the vdf + formatted data. throws "std::bad_alloc" if file buffer could not be allocated + throws "std::runtime_error" if a parsing error occured + */ + template + OutputT read(iStreamT& inStream, const Options& opt) + { + + // cache the file + typedef typename iStreamT::char_type charT; + std::basic_string str = detail::read_file(inStream); + // parse it + return read(str.begin(), str.end(), opt); + } + + template + inline basic_object read(iStreamT& inStream, + const Options& opt = Options{}) + { + return read>(inStream, opt); + } + +} // namespace vdf +} // namespace tyti #ifndef TYTI_NO_L_UNDEF #undef TYTI_L #endif @@ -727,4 +736,4 @@ namespace tyti #undef TYTI_UNDEF_NOTHROW #endif -#endif //__TYTI_STEAM_VDF_PARSER_H__ \ No newline at end of file +#endif //__TYTI_STEAM_VDF_PARSER_H__ \ No newline at end of file From 5f1c6fb3edce9222b4f203e9944ca7bc97365023 Mon Sep 17 00:00:00 2001 From: Jeremy Rimpo Date: Wed, 6 Sep 2023 12:43:52 -0500 Subject: [PATCH 1322/1544] Display save time in local time --- src/gamebryo/gamebryosavegameinfowidget.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/gamebryo/gamebryosavegameinfowidget.cpp b/src/gamebryo/gamebryosavegameinfowidget.cpp index 46354695..853f2c2b 100644 --- a/src/gamebryo/gamebryosavegameinfowidget.cpp +++ b/src/gamebryo/gamebryosavegameinfowidget.cpp @@ -56,7 +56,7 @@ void GamebryoSaveGameInfoWidget::setSave(MOBase::ISaveGame const& save) ui->levelLabel->setText(QString("%1").arg(gamebryoSave.getPCLevel())); // This somewhat contorted code is because on my system at least, the // old way of doing this appears to give short date and long time. - QDateTime t = gamebryoSave.getCreationTime(); + QDateTime t = gamebryoSave.getCreationTime().toLocalTime(); ui->dateLabel->setText( QLocale::system().toString(t.date(), QLocale::FormatType::ShortFormat) + " " + QLocale::system().toString(t.time())); From f569a6789782871c35df5f59ddbd89d24b3cb004 Mon Sep 17 00:00:00 2001 From: Jeremy Rimpo Date: Wed, 6 Sep 2023 12:45:56 -0500 Subject: [PATCH 1323/1544] Fixes to read compressed strings as UTF and read entire compressed data block --- src/gamebryo/gamebryosavegame.cpp | 111 ++++++++++++++++++------------ 1 file changed, 68 insertions(+), 43 deletions(-) diff --git a/src/gamebryo/gamebryosavegame.cpp b/src/gamebryo/gamebryosavegame.cpp index 0ab84c5a..66029b6f 100644 --- a/src/gamebryo/gamebryosavegame.cpp +++ b/src/gamebryo/gamebryosavegame.cpp @@ -140,19 +140,6 @@ void readQDataStream(QDataStream& data, T& value) } } -template <> -void readQDataStream(QDataStream& data, QString& value) -{ - unsigned short length; - readQDataStream(data, length); - - std::vector buffer(length); - - readQDataStream(data, buffer.data(), length); - - value = QString::fromLatin1(buffer.data(), length); -} - template <> void GamebryoSaveGame::FileWrapper::read(QString& value) { @@ -186,7 +173,34 @@ void GamebryoSaveGame::FileWrapper::read(QString& value) value = QString::fromUtf8(buffer.constData()); } else if (m_CompressionType == 1 || m_CompressionType == 2) { - readQDataStream(*m_Data, value); + unsigned short length; + if (m_PluginString == StringType::TYPE_BSTRING || + m_PluginString == StringType::TYPE_BZSTRING) { + unsigned char len; + readQDataStream(*m_Data, len); + length = m_PluginString == StringType::TYPE_BZSTRING ? len + 1 : len; + } else { + readQDataStream(*m_Data, length); + } + + if (m_HasFieldMarkers) { + skip(); + } + + QByteArray buffer; + buffer.resize(length); + + readQDataStream(*m_Data, buffer.data(), + m_PluginString == StringType::TYPE_BZSTRING ? length - 1 : length); + + if (m_PluginString == StringType::TYPE_BZSTRING) + buffer[length - 1] = '\0'; + + if (m_HasFieldMarkers) { + m_Data->skipRawData(1); + } + + value = QString::fromUtf8(buffer.constData()); } else { MOBase::log::warn("Please create an issue on the MO github labeled \"Found unknown " "Compressed\" with your savefile attached"); @@ -254,11 +268,10 @@ bool GamebryoSaveGame::FileWrapper::openCompressedData(int bytesToIgnore) } else if (m_CompressionType == 1) { uint64_t location; read(location); - uint64_t uncompressedSize; - read(uncompressedSize); - seek(location); - uInt have; - uInt size = 0; + uint64_t totalSize; + read(totalSize); + uint32_t have; + uint64_t read = 0; std::unique_ptr inBuffer(new unsigned char[CHUNK]); std::unique_ptr outBuffer(new unsigned char[CHUNK]); QByteArray finalData; @@ -269,34 +282,46 @@ bool GamebryoSaveGame::FileWrapper::openCompressedData(int bytesToIgnore) stream.opaque = Z_NULL; stream.avail_in = 0; stream.next_in = Z_NULL; - int zlibRet = inflateInit2(&stream, 15 + 32); - if (zlibRet != Z_OK) { - return false; - } do { - stream.avail_in = m_File.read(reinterpret_cast(inBuffer.get()), CHUNK); - if (!m_File.isReadable()) { - (void)inflateEnd(&stream); + uint64_t remainder = (location + read) % 16; + uint64_t next = location + read + 16 - (remainder == 0 ? 16 : remainder); + location = next; + read = 0; + if (next >= m_File.size()) + break; + m_File.seek(next); + int zlibRet = inflateInit2(&stream, 15 + 32); + if (zlibRet != Z_OK) { return false; } - if (stream.avail_in == 0) - break; - stream.next_in = static_cast(inBuffer.get()); do { - stream.avail_out = CHUNK; - stream.next_out = reinterpret_cast(outBuffer.get()); - zlibRet = inflate(&stream, Z_NO_FLUSH); - if ((zlibRet != Z_OK) && (zlibRet != Z_STREAM_END) && - (zlibRet != Z_BUF_ERROR)) { + stream.avail_in = m_File.read(reinterpret_cast(inBuffer.get()), CHUNK); + read += stream.avail_in; + if (!m_File.isReadable()) { + (void)inflateEnd(&stream); return false; } - have = CHUNK - stream.avail_out; - size += have; - finalData += QByteArray::fromRawData( - reinterpret_cast(outBuffer.get()), have); - } while (stream.avail_out == 0); - } while (zlibRet != Z_STREAM_END); - inflateEnd(&stream); + if (stream.avail_in == 0) + break; + stream.next_in = static_cast(inBuffer.get()); + do { + stream.avail_out = CHUNK; + stream.next_out = reinterpret_cast(outBuffer.get()); + zlibRet = inflate(&stream, Z_NO_FLUSH); + if ((zlibRet != Z_OK) && (zlibRet != Z_STREAM_END) && + (zlibRet != Z_BUF_ERROR)) { + return false; + } + have = CHUNK - stream.avail_out; + finalData += QByteArray::fromRawData( + reinterpret_cast(outBuffer.get()), have); + } while (stream.avail_out == 0); + read -= stream.avail_in; + } while (zlibRet != Z_STREAM_END); + inflateEnd(&stream); + if (finalData.size() == totalSize) + break; + } while (m_File.size() > location + read); } catch (const std::exception&) { inflateEnd(&stream); return false; @@ -463,7 +488,7 @@ QStringList GamebryoSaveGame::FileWrapper::readPlugins(int bytesToIgnore) plugins.reserve(finalCount); for (std::size_t i = 0; i < finalCount; ++i) { QString name; - readQDataStream(*m_Data, name); + read(name); plugins.push_back(name); } } @@ -492,7 +517,7 @@ QStringList GamebryoSaveGame::FileWrapper::readLightPlugins(int bytesToIgnore) plugins.reserve(count); for (std::size_t i = 0; i < count; ++i) { QString name; - readQDataStream(*m_Data, name); + read(name); plugins.push_back(name); } } From 5bde86091ea953ebce75ca450eee7f9cb40da92b Mon Sep 17 00:00:00 2001 From: Jeremy Rimpo Date: Sat, 9 Sep 2023 04:35:24 -0500 Subject: [PATCH 1324/1544] [game_starfield] Plugin loading updates * Add INI parsing for manually loaded plugins * Add 'None' load type which disables plugin management --- src/games/starfield/src/gamestarfield.cpp | 21 ++++++++++++++++++++- 1 file changed, 20 insertions(+), 1 deletion(-) diff --git a/src/games/starfield/src/gamestarfield.cpp b/src/games/starfield/src/gamestarfield.cpp index b6aaf2ef..c4af9430 100644 --- a/src/games/starfield/src/gamestarfield.cpp +++ b/src/games/starfield/src/gamestarfield.cpp @@ -202,6 +202,25 @@ QStringList GameStarfield::primaryPlugins() const plugins.append(CCPlugins()); + if (m_Organizer != nullptr && m_Organizer->profile() != nullptr) { + QString customIni( + m_Organizer->profile()->absoluteIniFilePath("StarfieldCustom.ini")); + if (QFile(customIni).exists()) { + for (int i = 1; i <= 10; ++i) { + QString setting("sTestFile"); + setting += std::to_string(i); + WCHAR value[MAX_PATH]; + DWORD length = ::GetPrivateProfileStringW( + L"General", setting.toStdWString().c_str(), L"", value, MAX_PATH, + customIni.toStdWString().c_str()); + if (length && wcscmp(value, L"") != 0) { + QString plugin = QString::fromWCharArray(value, length); + plugins.append(plugin); + } + } + } + } + return plugins; } @@ -261,7 +280,7 @@ QStringList GameStarfield::CCPlugins() const IPluginGame::LoadOrderMechanism GameStarfield::loadOrderMechanism() const { - return IPluginGame::LoadOrderMechanism::PluginsTxt; + return IPluginGame::LoadOrderMechanism::None; } int GameStarfield::nexusModOrganizerID() const From 794656dd7b4afbab1a230157bf2a49636f144362 Mon Sep 17 00:00:00 2001 From: Jeremy Rimpo Date: Tue, 12 Sep 2023 14:54:17 -0500 Subject: [PATCH 1325/1544] [game_starfield] Fix archive parsing and BSA invalidation --- src/games/starfield/src/game_starfield_en.ts | 4 ++-- src/games/starfield/src/gamestarfield.cpp | 5 +++-- src/games/starfield/src/starfieldbsainvalidation.cpp | 2 +- src/games/starfield/src/starfielddataarchives.cpp | 10 ++++------ src/games/starfield/src/starfielddataarchives.h | 5 ++++- src/games/starfield/src/starfieldmoddatachecker.h | 2 +- 6 files changed, 15 insertions(+), 13 deletions(-) diff --git a/src/games/starfield/src/game_starfield_en.ts b/src/games/starfield/src/game_starfield_en.ts index df8298c6..cfcb6dd2 100644 --- a/src/games/starfield/src/game_starfield_en.ts +++ b/src/games/starfield/src/game_starfield_en.ts @@ -4,12 +4,12 @@ GameStarfield - + Starfield Support Plugin - + Adds support for the game Starfield. diff --git a/src/games/starfield/src/gamestarfield.cpp b/src/games/starfield/src/gamestarfield.cpp index c4af9430..1e4aeed1 100644 --- a/src/games/starfield/src/gamestarfield.cpp +++ b/src/games/starfield/src/gamestarfield.cpp @@ -39,7 +39,8 @@ bool GameStarfield::init(IOrganizer* moInfo) } registerFeature(new StarfieldScriptExtender(this)); - registerFeature(new StarfieldDataArchives(myGamesPath())); + registerFeature( + new StarfieldDataArchives(myGamesPath(), gameDirectory())); registerFeature( new GamebryoLocalSavegames(myGamesPath(), "StarfieldCustom.ini")); registerFeature(new StarfieldModDataChecker(this)); @@ -163,7 +164,7 @@ void GameStarfield::initializeProfile(const QDir& path, ProfileSettings settings if (settings.testFlag(IPluginGame::CONFIGURATION)) { if (settings.testFlag(IPluginGame::PREFER_DEFAULTS) || !QFileInfo(myGamesPath() + "/Starfield.ini").exists()) { - copyToProfile(gameDirectory().absolutePath(), path, "StarfieldDefault.ini", + copyToProfile(gameDirectory().absolutePath(), path, "Starfield.ini", "Starfield.ini"); } else { copyToProfile(myGamesPath(), path, "Starfield.ini"); diff --git a/src/games/starfield/src/starfieldbsainvalidation.cpp b/src/games/starfield/src/starfieldbsainvalidation.cpp index a0c2d105..b511e9c4 100644 --- a/src/games/starfield/src/starfieldbsainvalidation.cpp +++ b/src/games/starfield/src/starfieldbsainvalidation.cpp @@ -17,7 +17,7 @@ StarfieldBSAInvalidation::StarfieldBSAInvalidation(DataArchives* dataArchives, bool StarfieldBSAInvalidation::isInvalidationBSA(const QString& bsaName) { - return true; + return false; } QString StarfieldBSAInvalidation::invalidationBSAName() const diff --git a/src/games/starfield/src/starfielddataarchives.cpp b/src/games/starfield/src/starfielddataarchives.cpp index 713ede18..ffbbc7cb 100644 --- a/src/games/starfield/src/starfielddataarchives.cpp +++ b/src/games/starfield/src/starfielddataarchives.cpp @@ -3,8 +3,9 @@ #include "iprofile.h" #include -StarfieldDataArchives::StarfieldDataArchives(const QDir& myGamesDir) - : GamebryoDataArchives(myGamesDir) +StarfieldDataArchives::StarfieldDataArchives(const QDir& myGamesDir, + const QDir& gamePath) + : GamebryoDataArchives(myGamesDir), m_GamePath(gamePath.absolutePath()) {} QStringList StarfieldDataArchives::vanillaArchives() const @@ -70,10 +71,7 @@ QStringList StarfieldDataArchives::archives(const MOBase::IProfile* profile) con { QStringList result; - QString iniFile = - profile->localSettingsEnabled() - ? QDir(profile->absolutePath()).absoluteFilePath("Starfield.ini") - : m_LocalGameDir.absoluteFilePath("Starfield.ini"); + QString iniFile = m_GamePath.absoluteFilePath("Starfield.ini"); result.append(getArchivesFromKey(iniFile, "SResourceArchiveList")); result.append(getArchivesFromKey(iniFile, "sResourceIndexFileList")); result.append(getArchivesFromKey(iniFile, "SResourceArchiveMemoryCacheList")); diff --git a/src/games/starfield/src/starfielddataarchives.h b/src/games/starfield/src/starfielddataarchives.h index 613127f3..9da5c81c 100644 --- a/src/games/starfield/src/starfielddataarchives.h +++ b/src/games/starfield/src/starfielddataarchives.h @@ -15,12 +15,15 @@ class StarfieldDataArchives : public GamebryoDataArchives { public: - StarfieldDataArchives(const QDir& myGamesDir); + StarfieldDataArchives(const QDir& myGamesDir, const QDir& gamePath); public: virtual QStringList vanillaArchives() const override; virtual QStringList archives(const MOBase::IProfile* profile) const override; +protected: + const QDir m_GamePath; + private: virtual void writeArchiveList(MOBase::IProfile* profile, const QStringList& before) override; diff --git a/src/games/starfield/src/starfieldmoddatachecker.h b/src/games/starfield/src/starfieldmoddatachecker.h index 1fa1c5e3..90c3eee9 100644 --- a/src/games/starfield/src/starfieldmoddatachecker.h +++ b/src/games/starfield/src/starfieldmoddatachecker.h @@ -15,7 +15,7 @@ protected: "interface", "meshes", "music", "scripts", "sound", "strings", "textures", "trees", "video", "materials", "sfse", "distantlod", "asi", "Tools", "MCM", "distantland", "mits", "dllplugins", - "CalienteTools", "shadersfx", "aaf"}; + "CalienteTools", "shadersfx", "aaf", "root"}; return result; } virtual const FileNameSet& possibleFileExtensions() const override From d4e9ac60e0399ceb43547d065b2819732d4f19e8 Mon Sep 17 00:00:00 2001 From: Jeremy Rimpo Date: Thu, 14 Sep 2023 03:08:17 -0500 Subject: [PATCH 1326/1544] [game_starfield] Remove Starfield.ini from managed INI files --- src/games/starfield/src/gamestarfield.cpp | 13 +------------ 1 file changed, 1 insertion(+), 12 deletions(-) diff --git a/src/games/starfield/src/gamestarfield.cpp b/src/games/starfield/src/gamestarfield.cpp index 1e4aeed1..ded525a2 100644 --- a/src/games/starfield/src/gamestarfield.cpp +++ b/src/games/starfield/src/gamestarfield.cpp @@ -159,17 +159,6 @@ void GameStarfield::initializeProfile(const QDir& path, ProfileSettings settings { if (settings.testFlag(IPluginGame::MODS)) { copyToProfile(localAppFolder() + "/Starfield", path, "plugins.txt"); - } - - if (settings.testFlag(IPluginGame::CONFIGURATION)) { - if (settings.testFlag(IPluginGame::PREFER_DEFAULTS) || - !QFileInfo(myGamesPath() + "/Starfield.ini").exists()) { - copyToProfile(gameDirectory().absolutePath(), path, "Starfield.ini", - "Starfield.ini"); - } else { - copyToProfile(myGamesPath(), path, "Starfield.ini"); - } - copyToProfile(myGamesPath(), path, "StarfieldPrefs.ini"); copyToProfile(myGamesPath(), path, "StarfieldCustom.ini"); } @@ -242,7 +231,7 @@ QString GameStarfield::gameNexusName() const QStringList GameStarfield::iniFiles() const { - return {"Starfield.ini", "StarfieldPrefs.ini", "StarfieldCustom.ini"}; + return {"StarfieldPrefs.ini", "StarfieldCustom.ini"}; } QStringList GameStarfield::DLCPlugins() const From ccaebc01cf0b4a6a7b389fd96cfbb845e761c3ab Mon Sep 17 00:00:00 2001 From: Jeremy Rimpo Date: Thu, 14 Sep 2023 03:18:35 -0500 Subject: [PATCH 1327/1544] [game_starfield] No need to modify Starfield.ini We may be able to move this change to the Creation game plugin library, I don't know that this edit is necessary on newer games --- src/games/starfield/src/gamestarfield.cpp | 5 +++++ src/games/starfield/src/gamestarfield.h | 1 + 2 files changed, 6 insertions(+) diff --git a/src/games/starfield/src/gamestarfield.cpp b/src/games/starfield/src/gamestarfield.cpp index ded525a2..00a0a140 100644 --- a/src/games/starfield/src/gamestarfield.cpp +++ b/src/games/starfield/src/gamestarfield.cpp @@ -234,6 +234,11 @@ QStringList GameStarfield::iniFiles() const return {"StarfieldPrefs.ini", "StarfieldCustom.ini"}; } +bool GameStarfield::prepareIni(const QString& exec) +{ + return true; // no need to write to Starfield.ini +} + QStringList GameStarfield::DLCPlugins() const { return {}; diff --git a/src/games/starfield/src/gamestarfield.h b/src/games/starfield/src/gamestarfield.h index 4b04d7f8..f08155b2 100644 --- a/src/games/starfield/src/gamestarfield.h +++ b/src/games/starfield/src/gamestarfield.h @@ -33,6 +33,7 @@ public: // IPluginGame interface virtual QString gameShortName() const override; virtual QString gameNexusName() const override; virtual QStringList iniFiles() const override; + virtual bool prepareIni(const QString& exec) override; virtual QStringList DLCPlugins() const override; virtual QStringList CCPlugins() const override; virtual LoadOrderMechanism loadOrderMechanism() const override; From eb57068652a36e994e7660f468100bc5f4f01985 Mon Sep 17 00:00:00 2001 From: Mikael CAPELLE Date: Mon, 18 Sep 2023 10:25:47 +0200 Subject: [PATCH 1328/1544] [game_starfield] Add github action workflows. --- .../starfield/.github/workflows/build.yml | 16 ++++++++ .../starfield/.github/workflows/linting.yml | 17 ++++++++ src/games/starfield/appveyor.yml | 40 ------------------- 3 files changed, 33 insertions(+), 40 deletions(-) create mode 100644 src/games/starfield/.github/workflows/build.yml create mode 100644 src/games/starfield/.github/workflows/linting.yml delete mode 100644 src/games/starfield/appveyor.yml diff --git a/src/games/starfield/.github/workflows/build.yml b/src/games/starfield/.github/workflows/build.yml new file mode 100644 index 00000000..25c90eac --- /dev/null +++ b/src/games/starfield/.github/workflows/build.yml @@ -0,0 +1,16 @@ +name: Build Starfield Plugin + +on: + push: + branches: master + pull_request: + types: [opened, synchronize, reopened] + +jobs: + build: + runs-on: windows-2022 + steps: + - name: Build Starfield Plugin + uses: ModOrganizer2/build-with-mob-action@master + with: + mo2-dependencies: cmake_common uibase game_gamebryo diff --git a/src/games/starfield/.github/workflows/linting.yml b/src/games/starfield/.github/workflows/linting.yml new file mode 100644 index 00000000..620b27f7 --- /dev/null +++ b/src/games/starfield/.github/workflows/linting.yml @@ -0,0 +1,17 @@ +name: Lint Starfield Plugin + +on: + push: + pull_request: + types: [opened, synchronize, reopened] + +jobs: + lint: + runs-on: ubuntu-latest + steps: + - uses: actions/checkout@v3 + - name: Run clang-format + uses: jidicula/clang-format-action@v4.11.0 + with: + clang-format-version: "15" + check-path: "." diff --git a/src/games/starfield/appveyor.yml b/src/games/starfield/appveyor.yml deleted file mode 100644 index 1e625dd0..00000000 --- a/src/games/starfield/appveyor.yml +++ /dev/null @@ -1,40 +0,0 @@ -version: 1.0.{build} -skip_branch_with_pr: true -image: Visual Studio 2019 -environment: - WEBHOOK_URL: - secure: gOKbXaZM9ImtMD5XrYITvdyZUW/az082G9OIN1EC1Vbg57wBaeLhi49uGjxPw5GVujHku6kxN6ab89zhbS5GVeluR76GM83IbKV4Sh7udXzoYZZdg6YudtYHzdhCgUeiedpswbuczTq9ceIkkfSEWZuh/lMAAVVwvcGsJAnoPFw= -build_script: -- pwsh: >- - $ErrorActionPreference = 'Stop' - - git clone --depth=1 --no-single-branch https://github.com/ModOrganizer2/modorganizer-umbrella.git c:\projects\modorganizer-umbrella - - New-Item -ItemType Directory -Path c:\projects\modorganizer-build - - cd c:\projects\modorganizer-umbrella - - ($env:APPVEYOR_PULL_REQUEST_HEAD_REPO_BRANCH -eq $null) ? ($branch = $env:APPVEYOR_REPO_BRANCH) : ($branch = $env:APPVEYOR_PULL_REQUEST_HEAD_REPO_BRANCH) - - git checkout $(git show-ref --verify --quiet refs/remotes/origin/${branch} || echo '-b') ${branch} - - C:\Python37-x64\python.exe unimake.py -d c:\projects\modorganizer-build -s Appveyor_Build=True ${env:APPVEYOR_PROJECT_NAME} - - if($LastExitCode -ne 0) { $host.SetShouldExit($LastExitCode ) } -artifacts: -- path: vsbuild\src\RelWithDebInfo\game_fallout4.dll - name: game_fallout4_dll -- path: vsbuild\src\RelWithDebInfo\game_fallout4.pdb - name: game_fallout4_pdb -- path: vsbuild\src\RelWithDebInfo\game_fallout4.lib - name: game_fallout4_lib -on_success: - - ps: Set-Location -Path $env:APPVEYOR_BUILD_FOLDER - - ps: Invoke-RestMethod https://raw.githubusercontent.com/DiscordHooks/appveyor-discord-webhook/master/send.ps1 -o send.ps1 - - ps: ./send.ps1 success $env:WEBHOOK_URL -on_failure: - - ps: Set-Location -Path $env:APPVEYOR_BUILD_FOLDER - - ps: Push-AppveyorArtifact ${env:APPVEYOR_BUILD_FOLDER}\stdout.log - - ps: Push-AppveyorArtifact ${env:APPVEYOR_BUILD_FOLDER}\stderr.log - - ps: Invoke-RestMethod https://raw.githubusercontent.com/DiscordHooks/appveyor-discord-webhook/master/send.ps1 -o send.ps1 - - ps: ./send.ps1 failure $env:WEBHOOK_URL \ No newline at end of file From 63536ef3ec1e308cb63bf9e65cf48b8722916224 Mon Sep 17 00:00:00 2001 From: Mikael CAPELLE Date: Mon, 18 Sep 2023 11:13:27 +0200 Subject: [PATCH 1329/1544] [game_starfield] Apply clang-format and eol fix. --- src/games/starfield/.gitattributes | 7 +++++++ src/games/starfield/src/starfieldbsainvalidation.cpp | 2 +- src/games/starfield/src/starfieldgameplugins.cpp | 2 +- src/games/starfield/src/starfieldgameplugins.h | 2 +- src/games/starfield/src/starfieldmoddatacontent.h | 2 +- src/games/starfield/src/vdf_parser.h | 2 +- 6 files changed, 12 insertions(+), 5 deletions(-) create mode 100644 src/games/starfield/.gitattributes diff --git a/src/games/starfield/.gitattributes b/src/games/starfield/.gitattributes new file mode 100644 index 00000000..f8697127 --- /dev/null +++ b/src/games/starfield/.gitattributes @@ -0,0 +1,7 @@ +# Set the default behavior, in case people don't have core.autocrlf set. +* text=auto + +# Explicitly declare text files you want to always be normalized and converted +# to native line endings on checkout. +*.cpp text eol=crlf +*.h text eol=crlf diff --git a/src/games/starfield/src/starfieldbsainvalidation.cpp b/src/games/starfield/src/starfieldbsainvalidation.cpp index b511e9c4..f86f7c55 100644 --- a/src/games/starfield/src/starfieldbsainvalidation.cpp +++ b/src/games/starfield/src/starfieldbsainvalidation.cpp @@ -65,4 +65,4 @@ bool StarfieldBSAInvalidation::prepareProfile(MOBase::IProfile* profile) } return dirty; -} \ No newline at end of file +} diff --git a/src/games/starfield/src/starfieldgameplugins.cpp b/src/games/starfield/src/starfieldgameplugins.cpp index b346e872..d946ed43 100644 --- a/src/games/starfield/src/starfieldgameplugins.cpp +++ b/src/games/starfield/src/starfieldgameplugins.cpp @@ -9,4 +9,4 @@ StarfieldGamePlugins::StarfieldGamePlugins(MOBase::IOrganizer* organizer) bool StarfieldGamePlugins::overridePluginsAreSupported() { return true; -} \ No newline at end of file +} diff --git a/src/games/starfield/src/starfieldgameplugins.h b/src/games/starfield/src/starfieldgameplugins.h index 1f21bd55..693edb70 100644 --- a/src/games/starfield/src/starfieldgameplugins.h +++ b/src/games/starfield/src/starfieldgameplugins.h @@ -16,4 +16,4 @@ protected: virtual bool overridePluginsAreSupported() override; }; -#endif // _STARFIELDGAMEPLUGINS_H \ No newline at end of file +#endif // _STARFIELDGAMEPLUGINS_H diff --git a/src/games/starfield/src/starfieldmoddatacontent.h b/src/games/starfield/src/starfieldmoddatacontent.h index 325c64f3..da33044c 100644 --- a/src/games/starfield/src/starfieldmoddatacontent.h +++ b/src/games/starfield/src/starfieldmoddatacontent.h @@ -41,4 +41,4 @@ public: } }; -#endif // STARFIELD_MODDATACONTENT_H \ No newline at end of file +#endif // STARFIELD_MODDATACONTENT_H diff --git a/src/games/starfield/src/vdf_parser.h b/src/games/starfield/src/vdf_parser.h index 771ba828..32d4d27d 100644 --- a/src/games/starfield/src/vdf_parser.h +++ b/src/games/starfield/src/vdf_parser.h @@ -736,4 +736,4 @@ namespace vdf #undef TYTI_UNDEF_NOTHROW #endif -#endif //__TYTI_STEAM_VDF_PARSER_H__ \ No newline at end of file +#endif //__TYTI_STEAM_VDF_PARSER_H__ From 95bc8aaaead172a3ec849cce4beba767ffc25df3 Mon Sep 17 00:00:00 2001 From: Mikael CAPELLE Date: Mon, 18 Sep 2023 11:14:56 +0200 Subject: [PATCH 1330/1544] [game_starfield] Add .git-blame-ignore-revs. --- src/games/starfield/.git-blame-ignore-revs | 1 + 1 file changed, 1 insertion(+) create mode 100644 src/games/starfield/.git-blame-ignore-revs diff --git a/src/games/starfield/.git-blame-ignore-revs b/src/games/starfield/.git-blame-ignore-revs new file mode 100644 index 00000000..2d5b70e4 --- /dev/null +++ b/src/games/starfield/.git-blame-ignore-revs @@ -0,0 +1 @@ +782e8588c56ab8fea7cfb9bd72e7b7a9e7fcb7f2 From f3747fd60fd0c6d8136a4b744ab232ec543ff1f0 Mon Sep 17 00:00:00 2001 From: Mikael CAPELLE Date: Mon, 18 Sep 2023 15:16:23 +0200 Subject: [PATCH 1331/1544] Add missing zlib in github actions. --- .github/workflows/build.yml | 2 +- appveyor.yml | 38 ------------------------------------- 2 files changed, 1 insertion(+), 39 deletions(-) delete mode 100644 appveyor.yml diff --git a/.github/workflows/build.yml b/.github/workflows/build.yml index 8bb44a2d..7efc43ff 100644 --- a/.github/workflows/build.yml +++ b/.github/workflows/build.yml @@ -13,5 +13,5 @@ jobs: - name: Build GameBryo Library uses: ModOrganizer2/build-with-mob-action@master with: - mo2-third-parties: fmt gtest spdlog boost lz4 + mo2-third-parties: lz4 zlib mo2-dependencies: cmake_common uibase diff --git a/appveyor.yml b/appveyor.yml deleted file mode 100644 index fbc95807..00000000 --- a/appveyor.yml +++ /dev/null @@ -1,38 +0,0 @@ -version: 1.0.{build} -skip_branch_with_pr: true -image: Visual Studio 2019 -environment: - WEBHOOK_URL: - secure: gOKbXaZM9ImtMD5XrYITvdyZUW/az082G9OIN1EC1Vbg57wBaeLhi49uGjxPw5GVujHku6kxN6ab89zhbS5GVeluR76GM83IbKV4Sh7udXzoYZZdg6YudtYHzdhCgUeiedpswbuczTq9ceIkkfSEWZuh/lMAAVVwvcGsJAnoPFw= -build_script: -- pwsh: >- - $ErrorActionPreference = 'Stop' - - git clone --depth=1 --no-single-branch https://github.com/ModOrganizer2/modorganizer-umbrella.git c:\projects\modorganizer-umbrella - - New-Item -ItemType Directory -Path c:\projects\modorganizer-build - - cd c:\projects\modorganizer-umbrella - - ($env:APPVEYOR_PULL_REQUEST_HEAD_REPO_BRANCH -eq $null) ? ($branch = $env:APPVEYOR_REPO_BRANCH) : ($branch = $env:APPVEYOR_PULL_REQUEST_HEAD_REPO_BRANCH) - - git checkout $(git show-ref --verify --quiet refs/remotes/origin/${branch} || echo '-b') ${branch} - - C:\Python37-x64\python.exe unimake.py -d c:\projects\modorganizer-build -s Appveyor_Build=True ${env:APPVEYOR_PROJECT_NAME} - - if($LastExitCode -ne 0) { $host.SetShouldExit($LastExitCode ) } -artifacts: -- path: vsbuild\src\RelWithDebInfo\gamebryo\game_gamebryo.lib - name: game_gamebryo_lib -- path: vsbuild\src\RelWithDebInfo\creation\game_creation.lib - name: game_creation_lib -on_success: - - ps: Set-Location -Path $env:APPVEYOR_BUILD_FOLDER - - ps: Invoke-RestMethod https://raw.githubusercontent.com/DiscordHooks/appveyor-discord-webhook/master/send.ps1 -o send.ps1 - - ps: ./send.ps1 success $env:WEBHOOK_URL -on_failure: - - ps: Set-Location -Path $env:APPVEYOR_BUILD_FOLDER - - ps: Push-AppveyorArtifact ${env:APPVEYOR_BUILD_FOLDER}\stdout.log - - ps: Push-AppveyorArtifact ${env:APPVEYOR_BUILD_FOLDER}\stderr.log - - ps: Invoke-RestMethod https://raw.githubusercontent.com/DiscordHooks/appveyor-discord-webhook/master/send.ps1 -o send.ps1 - - ps: ./send.ps1 failure $env:WEBHOOK_URL \ No newline at end of file From ccc15bf9cd5cd94ac1b33584e2577dbc84c60b79 Mon Sep 17 00:00:00 2001 From: Jeremy Rimpo Date: Mon, 18 Sep 2023 15:09:33 -0500 Subject: [PATCH 1332/1544] [game_enderalse] Tentative GOG variant (and LOOT) support --- src/games/enderalse/src/game_enderalse_en.ts | 160 +---------- src/games/enderalse/src/gameenderalse.cpp | 274 +++++++++++-------- src/games/enderalse/src/gameenderalse.h | 86 +++--- 3 files changed, 217 insertions(+), 303 deletions(-) diff --git a/src/games/enderalse/src/game_enderalse_en.ts b/src/games/enderalse/src/game_enderalse_en.ts index db0ba6ef..37750ea8 100644 --- a/src/games/enderalse/src/game_enderalse_en.ts +++ b/src/games/enderalse/src/game_enderalse_en.ts @@ -4,176 +4,22 @@ GameEnderalSE - + Enderal Special Edition Support Plugin - + Adds support for the game Enderal Special Edition. - - GamebryoModDataContent - - - Plugins (ESP/ESM/ESL) - - - - - Optional Plugins - - - - - Interface - - - - - Meshes - - - - - Bethesda Archive - - - - - Scripts (Papyrus) - - - - - Script Extender Plugin - - - - - Script Extender Files - - - - - SkyProc Patcher - - - - - Sound or Music - - - - - Textures - - - - - MCM Configuration - - - - - INI Files - - - - - FaceGen Data - - - - - ModGroup Files - - - - - GamebryoSaveGameInfoWidget - - - Save # - - - - - Character - - - - - Level - - - - - Location - - - - - Date - - - - - Has Script Extender Data - - - - - Missing ESPs - - - - - - None - - - - - Missing ESLs - - - QObject - - - + Some of your plugins have invalid names! These plugins can not be loaded by the game. Please see mo_interface.log for a list of affected plugins and rename them. - - - %1, #%2, Level %3, %4 - - - - - failed to open %1 - - - - - wrong file format - expected %1 got %2 - - - - - failed to query registry path (preflight): %1 - - - - - failed to query registry path (read): %1 - - diff --git a/src/games/enderalse/src/gameenderalse.cpp b/src/games/enderalse/src/gameenderalse.cpp index b13bef8c..833769e9 100644 --- a/src/games/enderalse/src/gameenderalse.cpp +++ b/src/games/enderalse/src/gameenderalse.cpp @@ -30,254 +30,312 @@ using namespace MOBase; -GameEnderalSE::GameEnderalSE() +GameEnderalSE::GameEnderalSE() {} + +void GameEnderalSE::setVariant(QString variant) { + m_GameVariant = variant; +} + +void GameEnderalSE::checkVariants() +{ + QFileInfo gog_dll(m_GamePath + "\\Galaxy64.dll"); + if (gog_dll.exists()) + setVariant("GOG"); + else + setVariant("Steam"); +} + +QDir GameEnderalSE::documentsDirectory() const +{ + return m_MyGamesPath; +} + +void GameEnderalSE::detectGame() +{ + m_GamePath = identifyGamePath(); + checkVariants(); + m_MyGamesPath = determineMyGamesPath(gameDirectoryName()); } QString GameEnderalSE::identifyGamePath() const { - QString path = "Software\\SureAI\\EnderalSE"; - QString result; - try { - result = findInRegistry(HKEY_CURRENT_USER, path.toStdWString().c_str(), L"Install_Path"); - } - catch (MOBase::MyException) { - result = MOBase::findSteamGame("Enderal Special Edition", "Data\\Enderal - Forgotten Stories.esm"); - } - return result; + QMap paths = { + {"Software\\Bethesda Softworks\\" + gameName(), "Installed Path"}, + {"Software\\GOG.com\\Games\\1708684988", "path"}, + }; + QString result; + try { + for (auto& path : paths.toStdMap()) { + result = findInRegistry(HKEY_LOCAL_MACHINE, path.first.toStdWString().c_str(), + path.second.toStdWString().c_str()); + if (!result.isEmpty()) + break; + } + } + catch (MOBase::MyException) { + result = MOBase::findSteamGame("Enderal Special Edition", "Data\\Enderal - Forgotten Stories.esm"); + } + return result; } -bool GameEnderalSE::init(IOrganizer *moInfo) +void GameEnderalSE::setGamePath(const QString& path) { - if (!GameGamebryo::init(moInfo)) { - return false; - } + m_GamePath = path; + checkVariants(); + m_MyGamesPath = determineMyGamesPath(gameDirectoryName()); + registerFeature(new EnderalSEDataArchives(myGamesPath())); + registerFeature(new EnderalSELocalSavegames(myGamesPath(), "Enderal.ini")); +} - registerFeature(new EnderalSEScriptExtender(this)); - registerFeature(new EnderalSEDataArchives(myGamesPath())); - registerFeature(new EnderalSELocalSavegames(myGamesPath(), "Enderal.ini")); - registerFeature(new EnderalSEModDataChecker(this)); - registerFeature(new EnderalSEModDataContent(this)); - registerFeature(new GamebryoSaveGameInfo(this)); - registerFeature(new EnderalSEGamePlugins(moInfo)); - registerFeature(new EnderalSEUnmangedMods(this)); +QDir GameEnderalSE::savesDirectory() const +{ + return QDir(m_MyGamesPath + "/Saves"); +} - return true; +QString GameEnderalSE::myGamesPath() const +{ + return m_MyGamesPath; +} + +bool GameEnderalSE::isInstalled() const +{ + return !m_GamePath.isEmpty(); +} + +bool GameEnderalSE::init(IOrganizer* moInfo) +{ + if (!GameGamebryo::init(moInfo)) { + return false; + } + + registerFeature(new EnderalSEScriptExtender(this)); + registerFeature(new EnderalSEDataArchives(myGamesPath())); + registerFeature(new EnderalSELocalSavegames(myGamesPath(), "Enderal.ini")); + registerFeature(new EnderalSEModDataChecker(this)); + registerFeature(new EnderalSEModDataContent(this)); + registerFeature(new GamebryoSaveGameInfo(this)); + registerFeature(new EnderalSEGamePlugins(moInfo)); + registerFeature(new EnderalSEUnmangedMods(this)); + + return true; } QString GameEnderalSE::gameName() const { - return "Enderal Special Edition"; + return "Enderal Special Edition"; +} + +QString GameEnderalSE::gameDirectoryName() const +{ + if (selectedVariant() == "GOG") + return "Enderal Special Edition GOG"; + else + return "Enderal Special Edition"; } QIcon GameEnderalSE::gameIcon() const { - return MOBase::iconForExecutable(gameDirectory().absoluteFilePath(getLauncherName())); + return MOBase::iconForExecutable(gameDirectory().absoluteFilePath(getLauncherName())); } QList GameEnderalSE::executables() const { - return { - ExecutableInfo("Enderal Special Edition (SKSE)", findInGameFolder(feature()->loaderName())), - ExecutableInfo("Enderal Special Edition Launcher", findInGameFolder(getLauncherName())), - // ExecutableInfo("LOOT", QFileInfo(getLootPath())).withArgument("--game=\"Skyrim Special Edition\""), - ExecutableInfo("Creation Kit", findInGameFolder("CreationKit.exe")) - }; + return QList() + << ExecutableInfo("Enderal Special Edition (SKSE)", findInGameFolder(feature()->loaderName())) + << ExecutableInfo("Enderal Special Edition Launcher", findInGameFolder(getLauncherName())) + << ExecutableInfo("Creation Kit", findInGameFolder("CreationKit.exe")).withSteamAppId("1946180") + << ExecutableInfo("LOOT", QFileInfo(getLootPath())).withArgument("--game=\"Enderal Special Edition\""); } QList GameEnderalSE::executableForcedLoads() const { - return QList(); + return QList(); } QString GameEnderalSE::binaryName() const { - return "skse64_loader.exe"; + return "skse64_loader.exe"; } QString GameEnderalSE::getLauncherName() const { - return "Enderal Launcher.exe"; + return "Enderal Launcher.exe"; } bool GameEnderalSE::looksValid(const QDir& folder) const { - // we need to check both launcher and binary because the binary also exists for - // Skyrim SE and the launcher for Enderal LE - return folder.exists(getLauncherName()) && folder.exists(binaryName()); + // we need to check both launcher and binary because the binary also exists for + // Skyrim SE and the launcher for Enderal LE + return folder.exists(getLauncherName()) && folder.exists(binaryName()); } -QFileInfo GameEnderalSE::findInGameFolder(const QString &relativePath) const +QFileInfo GameEnderalSE::findInGameFolder(const QString& relativePath) const { - return QFileInfo(m_GamePath + "/" + relativePath); + return QFileInfo(m_GamePath + "/" + relativePath); } QString GameEnderalSE::name() const { - return "Enderal Special Edition Support Plugin"; + return "Enderal Special Edition Support Plugin"; } QString GameEnderalSE::localizedName() const { - return tr("Enderal Special Edition Support Plugin"); + return tr("Enderal Special Edition Support Plugin"); } QString GameEnderalSE::author() const { - return "Holt59, Archost & ZachHaber"; + return "Holt59, Archost & ZachHaber"; } QString GameEnderalSE::description() const { - return tr("Adds support for the game Enderal Special Edition."); + return tr("Adds support for the game Enderal Special Edition."); } MOBase::VersionInfo GameEnderalSE::version() const { - return VersionInfo(1, 1, 0, VersionInfo::RELEASE_FINAL); + return VersionInfo(1, 1, 0, VersionInfo::RELEASE_FINAL); } QList GameEnderalSE::settings() const { - return QList(); + return QList(); } -void GameEnderalSE::initializeProfile(const QDir &path, ProfileSettings settings) const +void GameEnderalSE::initializeProfile(const QDir& path, ProfileSettings settings) const { - if (settings.testFlag(IPluginGame::MODS)) { - copyToProfile(localAppFolder() + "/Enderal Special Edition", path, "plugins.txt"); - } + if (settings.testFlag(IPluginGame::MODS)) { + copyToProfile(localAppFolder() + "/Enderal Special Edition", path, "plugins.txt"); + } - if (settings.testFlag(IPluginGame::CONFIGURATION)) { - if (settings.testFlag(IPluginGame::PREFER_DEFAULTS) - || !QFileInfo(myGamesPath() + "/Enderal.ini").exists()) { + if (settings.testFlag(IPluginGame::CONFIGURATION)) { + if (settings.testFlag(IPluginGame::PREFER_DEFAULTS) + || !QFileInfo(myGamesPath() + "/Enderal.ini").exists()) { - //there is no default ini, actually they are going to put them in for us! - copyToProfile(gameDirectory().absolutePath(), path, "enderal_default.ini", "Enderal.ini"); - copyToProfile(gameDirectory().absolutePath(), path, "enderalprefs_default.ini", "EnderalPrefs.ini"); - } - else { - copyToProfile(myGamesPath(), path, "Enderal.ini"); - copyToProfile(myGamesPath(), path, "EnderalPrefs.ini"); - } - } + //there is no default ini, actually they are going to put them in for us! + copyToProfile(gameDirectory().absolutePath(), path, "enderal_default.ini", "Enderal.ini"); + copyToProfile(gameDirectory().absolutePath(), path, "enderalprefs_default.ini", "EnderalPrefs.ini"); + } + else { + copyToProfile(myGamesPath(), path, "Enderal.ini"); + copyToProfile(myGamesPath(), path, "EnderalPrefs.ini"); + } + } } QString GameEnderalSE::savegameExtension() const { - return "ess"; + return "ess"; } QString GameEnderalSE::savegameSEExtension() const { - return "skse"; + return "skse"; } std::shared_ptr GameEnderalSE::makeSaveGame(QString filePath) const { - return std::make_shared(filePath, this); + return std::make_shared(filePath, this); } QString GameEnderalSE::steamAPPId() const { - return "976620"; + if (selectedVariant() == "Steam") + return "976620"; + return ""; } QStringList GameEnderalSE::primaryPlugins() const { - return { - "skyrim.esm", - "update.esm", - "dawnguard.esm", - "hearthfires.esm", - "dragonborn.esm", + return { + "skyrim.esm", + "update.esm", + "dawnguard.esm", + "hearthfires.esm", + "dragonborn.esm", - // these two plugins are considered "primary" for users but are not - // automatically loaded by the game so we need to force-write them - // to the plugin list - "enderal - forgotten stories.esm", - "skyui_se.esp" - }; + // these two plugins are considered "primary" for users but are not + // automatically loaded by the game so we need to force-write them + // to the plugin list + "enderal - forgotten stories.esm", + "skyui_se.esp" + }; } QStringList GameEnderalSE::DLCPlugins() const { - return { }; + return { }; } QStringList GameEnderalSE::gameVariants() const { - return{ "Regular" }; + return{ "Steam", "GOG" }; } QString GameEnderalSE::gameShortName() const { - return "EnderalSE"; + return "EnderalSE"; } QStringList GameEnderalSE::validShortNames() const { - return { "Skyrim", "SkyrimSE", "Enderal" }; + return { "Skyrim", "SkyrimSE", "Enderal" }; } QString GameEnderalSE::gameNexusName() const { - return "enderalspecialedition"; + return "enderalspecialedition"; } QStringList GameEnderalSE::iniFiles() const { - return { "Enderal.ini", "EnderalPrefs.ini" }; + return { "Enderal.ini", "EnderalPrefs.ini" }; } + QStringList GameEnderalSE::CCPlugins() const { - QStringList plugins; - std::set pluginsLookup; - - const QString path = gameDirectory().filePath("Skyrim.ccc"); - - MOBase::forEachLineInFile(path, [&](QString s) { - const auto lc = s.toLower(); - if (!pluginsLookup.contains(lc)) { - pluginsLookup.insert(lc); - plugins.append(std::move(s)); - } - }); - - return plugins; + return { }; } MOBase::IPluginGame::SortMechanism GameEnderalSE::sortMechanism() const { - return SortMechanism::NONE; + return SortMechanism::LOOT; } IPluginGame::LoadOrderMechanism GameEnderalSE::loadOrderMechanism() const { - return IPluginGame::LoadOrderMechanism::PluginsTxt; + return IPluginGame::LoadOrderMechanism::PluginsTxt; } int GameEnderalSE::nexusModOrganizerID() const { - return 0; + return 0; } int GameEnderalSE::nexusGameID() const { - return 3685; + return 3685; +} + +QDir GameEnderalSE::gameDirectory() const +{ + return QDir(m_GamePath); } // Not to delete all the spaces... MappingType GameEnderalSE::mappings() const { - MappingType result; + MappingType result; - for (const QString &profileFile : { "plugins.txt", "loadorder.txt" }) { - result.push_back({ m_Organizer->profilePath() + "/" + profileFile, - localAppFolder() + "/Enderal Special Edition/" + profileFile, - false }); - } + for (const QString& profileFile : { "plugins.txt", "loadorder.txt" }) { + result.push_back({ m_Organizer->profilePath() + "/" + profileFile, + localAppFolder() + "/Enderal Special Edition/" + profileFile, + false }); + } - return result; + return result; } diff --git a/src/games/enderalse/src/gameenderalse.h b/src/games/enderalse/src/gameenderalse.h index 99b3578d..f84d1672 100644 --- a/src/games/enderalse/src/gameenderalse.h +++ b/src/games/enderalse/src/gameenderalse.h @@ -8,60 +8,70 @@ class GameEnderalSE : public GameGamebryo { - Q_OBJECT + Q_OBJECT - Q_PLUGIN_METADATA(IID "com.soundcontactstudio.GameEnderalSE" FILE "gameenderalse.json") + Q_PLUGIN_METADATA(IID "com.soundcontactstudio.GameEnderalSE" FILE "gameenderalse.json") public: - GameEnderalSE(); + GameEnderalSE(); - virtual bool init(MOBase::IOrganizer *moInfo) override; + virtual bool init(MOBase::IOrganizer* moInfo) override; public: // IPluginGame interface + virtual void detectGame() override; + virtual QString gameName() const override; + virtual QIcon gameIcon() const override; + virtual QList executables() const override; + virtual QList 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 getLauncherName() const override; + virtual bool looksValid(const QDir& folder) const override; + virtual QString gameShortName() const override; + virtual QString gameNexusName() const override; + virtual QStringList validShortNames() const override; + virtual QStringList iniFiles() const override; + virtual QStringList DLCPlugins() const override; + virtual QStringList CCPlugins() const override; + SortMechanism sortMechanism() const override; + virtual LoadOrderMechanism loadOrderMechanism() const override; + virtual int nexusModOrganizerID() const override; + virtual int nexusGameID() const override; - virtual QString gameName() const override; - virtual QIcon gameIcon() const override; - virtual QList executables() const override; - virtual QList 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 getLauncherName() const override; - virtual bool looksValid(const QDir& folder) const override; - virtual QString gameShortName() const override; - virtual QString gameNexusName() const override; - virtual QStringList validShortNames() const override; - virtual QStringList iniFiles() const override; - virtual QStringList DLCPlugins() const override; - virtual QStringList CCPlugins() const override; - SortMechanism sortMechanism() const override; - virtual LoadOrderMechanism loadOrderMechanism() const override; - virtual int nexusModOrganizerID() const override; - virtual int nexusGameID() 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 settings() const override; - virtual MappingType mappings() const override; + 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 settings() const override; + virtual MappingType mappings() const override; protected: - std::shared_ptr makeSaveGame(QString filePath) const override; - QString savegameExtension() const override; - QString savegameSEExtension() const override; + std::shared_ptr makeSaveGame(QString filePath) const override; + QString savegameExtension() const override; + QString savegameSEExtension() const override; - QFileInfo findInGameFolder(const QString &relativePath) const; + QString gameDirectoryName() const; + QDir documentsDirectory() const; + QDir savesDirectory() const; + QFileInfo findInGameFolder(const QString& relativePath) const; + QString myGamesPath() const; - virtual QString identifyGamePath() const override; + void checkVariants(); + void setVariant(QString variant); + + virtual QString identifyGamePath() const override; }; From 1a53411c6266d628be984a7f329ef07727d2c3dc Mon Sep 17 00:00:00 2001 From: Jeremy Rimpo Date: Mon, 18 Sep 2023 15:19:12 -0500 Subject: [PATCH 1333/1544] [game_enderalse] Prep project --- src/games/enderalse/.clang-format | 41 +++++++++++++++++++ src/games/enderalse/.gitattributes | 7 ++++ .../enderalse/.github/workflows/build.yml | 17 ++++++++ .../enderalse/.github/workflows/linting.yml | 15 +++++++ src/games/enderalse/appveyor.yml | 40 ------------------ 5 files changed, 80 insertions(+), 40 deletions(-) create mode 100644 src/games/enderalse/.clang-format create mode 100644 src/games/enderalse/.gitattributes create mode 100644 src/games/enderalse/.github/workflows/build.yml create mode 100644 src/games/enderalse/.github/workflows/linting.yml delete mode 100644 src/games/enderalse/appveyor.yml diff --git a/src/games/enderalse/.clang-format b/src/games/enderalse/.clang-format new file mode 100644 index 00000000..6098e1f5 --- /dev/null +++ b/src/games/enderalse/.clang-format @@ -0,0 +1,41 @@ +--- +# We'll use defaults from the LLVM style, but with 4 columns indentation. +BasedOnStyle: LLVM +IndentWidth: 2 +--- +Language: Cpp +DeriveLineEnding: false +UseCRLF: true +DerivePointerAlignment: false +PointerAlignment: Left +AlignConsecutiveAssignments: true +AllowShortFunctionsOnASingleLine: Inline +AllowShortIfStatementsOnASingleLine: Never +AllowShortLambdasOnASingleLine: Empty +AlwaysBreakTemplateDeclarations: Yes +AccessModifierOffset: -2 +AlignTrailingComments: true +SpacesBeforeTrailingComments: 2 +NamespaceIndentation: Inner +MaxEmptyLinesToKeep: 1 +BreakBeforeBraces: Custom +BraceWrapping: + AfterCaseLabel: false + AfterClass: true + AfterControlStatement: false + AfterEnum: true + AfterFunction: true + AfterNamespace: true + AfterStruct: true + AfterUnion: true + AfterExternBlock: true + BeforeCatch: false + BeforeElse: false + BeforeLambdaBody: false + BeforeWhile: false + IndentBraces: false + SplitEmptyFunction: false + SplitEmptyRecord: false + SplitEmptyNamespace: true +ColumnLimit: 88 +ForEachMacros: ['Q_FOREACH', 'foreach'] diff --git a/src/games/enderalse/.gitattributes b/src/games/enderalse/.gitattributes new file mode 100644 index 00000000..f8697127 --- /dev/null +++ b/src/games/enderalse/.gitattributes @@ -0,0 +1,7 @@ +# Set the default behavior, in case people don't have core.autocrlf set. +* text=auto + +# Explicitly declare text files you want to always be normalized and converted +# to native line endings on checkout. +*.cpp text eol=crlf +*.h text eol=crlf diff --git a/src/games/enderalse/.github/workflows/build.yml b/src/games/enderalse/.github/workflows/build.yml new file mode 100644 index 00000000..5d309623 --- /dev/null +++ b/src/games/enderalse/.github/workflows/build.yml @@ -0,0 +1,17 @@ +name: Build Enderal SE Plugin + +on: + push: + branches: master + pull_request: + types: [opened, synchronize, reopened] + +jobs: + build: + runs-on: windows-2022 + steps: + - name: Build Enderal SE Plugin + uses: ModOrganizer2/build-with-mob-action@master + with: + mo2-third-parties: fmt gtest spdlog boost lz4 + mo2-dependencies: cmake_common uibase game_gamebryo diff --git a/src/games/enderalse/.github/workflows/linting.yml b/src/games/enderalse/.github/workflows/linting.yml new file mode 100644 index 00000000..b457e70e --- /dev/null +++ b/src/games/enderalse/.github/workflows/linting.yml @@ -0,0 +1,15 @@ +name: Lint LootCLI +on: + push: + pull_request: + types: [opened, synchronize, reopened] +jobs: + lint: + runs-on: ubuntu-latest + steps: + - uses: actions/checkout@v3 + - name: Run clang-format + uses: jidicula/clang-format-action@v4.11.0 + with: + clang-format-version: "15" + check-path: "." diff --git a/src/games/enderalse/appveyor.yml b/src/games/enderalse/appveyor.yml deleted file mode 100644 index 2faa4a11..00000000 --- a/src/games/enderalse/appveyor.yml +++ /dev/null @@ -1,40 +0,0 @@ -version: 1.0.{build} -skip_branch_with_pr: true -image: Visual Studio 2019 -environment: - WEBHOOK_URL: - secure: gOKbXaZM9ImtMD5XrYITvdyZUW/az082G9OIN1EC1Vbg57wBaeLhi49uGjxPw5GVujHku6kxN6ab89zhbS5GVeluR76GM83IbKV4Sh7udXzoYZZdg6YudtYHzdhCgUeiedpswbuczTq9ceIkkfSEWZuh/lMAAVVwvcGsJAnoPFw= -build_script: -- pwsh: >- - $ErrorActionPreference = 'Stop' - - git clone --depth=1 --no-single-branch https://github.com/ModOrganizer2/modorganizer-umbrella.git c:\projects\modorganizer-umbrella - - New-Item -ItemType Directory -Path c:\projects\modorganizer-build - - cd c:\projects\modorganizer-umbrella - - ($env:APPVEYOR_PULL_REQUEST_HEAD_REPO_BRANCH -eq $null) ? ($branch = $env:APPVEYOR_REPO_BRANCH) : ($branch = $env:APPVEYOR_PULL_REQUEST_HEAD_REPO_BRANCH) - - git checkout $(git show-ref --verify --quiet refs/remotes/origin/${branch} || echo '-b') ${branch} - - C:\Python37-x64\python.exe unimake.py -d c:\projects\modorganizer-build -s Appveyor_Build=True ${env:APPVEYOR_PROJECT_NAME} - - if($LastExitCode -ne 0) { $host.SetShouldExit($LastExitCode ) } -artifacts: -- path: vsbuild\src\RelWithDebInfo\game_skyrimse.dll - name: game_skyrimse_dll -- path: vsbuild\src\RelWithDebInfo\game_skyrimse.pdb - name: game_skyrimse_pdb -- path: vsbuild\src\RelWithDebInfo\game_skyrimse.lib - name: game_skyrimse_lib -on_success: - - ps: Set-Location -Path $env:APPVEYOR_BUILD_FOLDER - - ps: Invoke-RestMethod https://raw.githubusercontent.com/DiscordHooks/appveyor-discord-webhook/master/send.ps1 -o send.ps1 - - ps: ./send.ps1 success $env:WEBHOOK_URL -on_failure: - - ps: Set-Location -Path $env:APPVEYOR_BUILD_FOLDER - - ps: Push-AppveyorArtifact ${env:APPVEYOR_BUILD_FOLDER}\stdout.log - - ps: Push-AppveyorArtifact ${env:APPVEYOR_BUILD_FOLDER}\stderr.log - - ps: Invoke-RestMethod https://raw.githubusercontent.com/DiscordHooks/appveyor-discord-webhook/master/send.ps1 -o send.ps1 - - ps: ./send.ps1 failure $env:WEBHOOK_URL \ No newline at end of file From c8b66669a88cda3adf86a9dcdad510a4bf291b3e Mon Sep 17 00:00:00 2001 From: Jeremy Rimpo Date: Mon, 18 Sep 2023 15:20:54 -0500 Subject: [PATCH 1334/1544] [game_enderalse] Format files --- .../enderalse/src/enderalsedataarchives.cpp | 72 ++--- .../enderalse/src/enderalsedataarchives.h | 21 +- .../enderalse/src/enderalsegameplugins.cpp | 44 ++- .../enderalse/src/enderalsegameplugins.h | 8 +- .../enderalse/src/enderalselocalsavegames.cpp | 84 +++--- .../enderalse/src/enderalselocalsavegames.h | 6 +- .../enderalse/src/enderalsemoddatachecker.h | 25 +- .../enderalse/src/enderalsemoddatacontent.h | 11 +- src/games/enderalse/src/enderalsesavegame.cpp | 55 ++-- src/games/enderalse/src/enderalsesavegame.h | 22 +- .../enderalse/src/enderalsescriptextender.cpp | 7 +- .../enderalse/src/enderalsescriptextender.h | 5 +- .../enderalse/src/enderalseunmanagedmods.cpp | 17 +- .../enderalse/src/enderalseunmanagedmods.h | 11 +- src/games/enderalse/src/gameenderalse.cpp | 261 +++++++++--------- src/games/enderalse/src/gameenderalse.h | 107 ++++--- 16 files changed, 370 insertions(+), 386 deletions(-) diff --git a/src/games/enderalse/src/enderalsedataarchives.cpp b/src/games/enderalse/src/enderalsedataarchives.cpp index 6d50a216..4082d4f2 100644 --- a/src/games/enderalse/src/enderalsedataarchives.cpp +++ b/src/games/enderalse/src/enderalsedataarchives.cpp @@ -3,59 +3,61 @@ #include "iprofile.h" #include -EnderalSEDataArchives::EnderalSEDataArchives(const QDir &myGamesDir) : - GamebryoDataArchives(myGamesDir) +EnderalSEDataArchives::EnderalSEDataArchives(const QDir& myGamesDir) + : GamebryoDataArchives(myGamesDir) {} QStringList EnderalSEDataArchives::vanillaArchives() const { - return { - "Skyrim - Textures0.bsa", - "Skyrim - Textures1.bsa", - "Skyrim - Textures2.bsa", - "Skyrim - Textures3.bsa", - "Skyrim - Textures4.bsa", - "Skyrim - Textures5.bsa", - "Skyrim - Textures6.bsa", - "Skyrim - Textures7.bsa", - "Skyrim - Textures8.bsa", - "Skyrim - Meshes0.bsa", - "Skyrim - Meshes1.bsa", - "Skyrim - Voices_en0.bsa", - "Skyrim - Sounds.bsa", - "Skyrim - Interface.bsa", - "Skyrim - Animations.bsa", - "Skyrim - Shaders.bsa", - "Skyrim - Misc.bsa", - "E - Meshes.bsa", - "E - SE.bsa", - "E - Scripts.bsa", - "E - Sounds.bsa", - "E - Textures1.bsa", - "E - Textures2.bsa", - "E - Textures3.bsa", - "L - Textures.bsa", - "L - Voices.bsa" - }; + return {"Skyrim - Textures0.bsa", + "Skyrim - Textures1.bsa", + "Skyrim - Textures2.bsa", + "Skyrim - Textures3.bsa", + "Skyrim - Textures4.bsa", + "Skyrim - Textures5.bsa", + "Skyrim - Textures6.bsa", + "Skyrim - Textures7.bsa", + "Skyrim - Textures8.bsa", + "Skyrim - Meshes0.bsa", + "Skyrim - Meshes1.bsa", + "Skyrim - Voices_en0.bsa", + "Skyrim - Sounds.bsa", + "Skyrim - Interface.bsa", + "Skyrim - Animations.bsa", + "Skyrim - Shaders.bsa", + "Skyrim - Misc.bsa", + "E - Meshes.bsa", + "E - SE.bsa", + "E - Scripts.bsa", + "E - Sounds.bsa", + "E - Textures1.bsa", + "E - Textures2.bsa", + "E - Textures3.bsa", + "L - Textures.bsa", + "L - Voices.bsa"}; } - -QStringList EnderalSEDataArchives::archives(const MOBase::IProfile *profile) const +QStringList EnderalSEDataArchives::archives(const MOBase::IProfile* profile) const { QStringList result; - QString iniFile = profile->localSettingsEnabled() ? QDir(profile->absolutePath()).absoluteFilePath("enderal.ini") : m_LocalGameDir.absoluteFilePath("enderal.ini"); + QString iniFile = profile->localSettingsEnabled() + ? QDir(profile->absolutePath()).absoluteFilePath("enderal.ini") + : m_LocalGameDir.absoluteFilePath("enderal.ini"); result.append(getArchivesFromKey(iniFile, "SResourceArchiveList", 512)); result.append(getArchivesFromKey(iniFile, "SResourceArchiveList2", 512)); return result; } -void EnderalSEDataArchives::writeArchiveList(MOBase::IProfile *profile, const QStringList &before) +void EnderalSEDataArchives::writeArchiveList(MOBase::IProfile* profile, + const QStringList& before) { QString list = before.join(","); - QString iniFile = profile->localSettingsEnabled() ? QDir(profile->absolutePath()).absoluteFilePath("enderal.ini") : m_LocalGameDir.absoluteFilePath("enderal.ini"); + QString iniFile = profile->localSettingsEnabled() + ? QDir(profile->absolutePath()).absoluteFilePath("enderal.ini") + : m_LocalGameDir.absoluteFilePath("enderal.ini"); if (list.length() > 511) { int splitIdx = list.lastIndexOf(",", 512); setArchivesToKey(iniFile, "SResourceArchiveList", list.mid(0, splitIdx)); diff --git a/src/games/enderalse/src/enderalsedataarchives.h b/src/games/enderalse/src/enderalsedataarchives.h index b6954db0..4048444d 100644 --- a/src/games/enderalse/src/enderalsedataarchives.h +++ b/src/games/enderalse/src/enderalsedataarchives.h @@ -2,28 +2,27 @@ #define ENDERALSEDATAARCHIVES_H #include "gamebryodataarchives.h" -#include #include +#include -namespace MOBase { class IProfile; } - +namespace MOBase +{ +class IProfile; +} class EnderalSEDataArchives : public GamebryoDataArchives { public: - - EnderalSEDataArchives(const QDir &myGamesDir); + EnderalSEDataArchives(const QDir& myGamesDir); public: - virtual QStringList vanillaArchives() const override; - virtual QStringList archives(const MOBase::IProfile *profile) const override; + virtual QStringList archives(const MOBase::IProfile* profile) const override; private: - - virtual void writeArchiveList(MOBase::IProfile *profile, const QStringList &before) override; - + virtual void writeArchiveList(MOBase::IProfile* profile, + const QStringList& before) override; }; -#endif // _SKYRIMSEDATAARCHIVES_H +#endif // _SKYRIMSEDATAARCHIVES_H diff --git a/src/games/enderalse/src/enderalsegameplugins.cpp b/src/games/enderalse/src/enderalsegameplugins.cpp index 55682b90..653ba100 100644 --- a/src/games/enderalse/src/enderalsegameplugins.cpp +++ b/src/games/enderalse/src/enderalsegameplugins.cpp @@ -1,15 +1,16 @@ #include "enderalsegameplugins.h" #include -#include #include +#include #include #include using namespace MOBase; -void EnderalSEGamePlugins::writePluginList(const MOBase::IPluginList* pluginList, const QString& filePath) +void EnderalSEGamePlugins::writePluginList(const MOBase::IPluginList* pluginList, + const QString& filePath) { SafeWriteFile file(filePath); @@ -17,21 +18,22 @@ void EnderalSEGamePlugins::writePluginList(const MOBase::IPluginList* pluginList file->resize(0); - file->write(encoder.encode( - "# This file was automatically generated by Mod Organizer.\r\n")); + file->write( + encoder.encode("# This file was automatically generated by Mod Organizer.\r\n")); bool invalidFileNames = false; - int writtenCount = 0; + int writtenCount = 0; QStringList plugins = pluginList->pluginNames(); std::sort(plugins.begin(), plugins.end(), - [pluginList](const QString& lhs, const QString& rhs) { - return pluginList->priority(lhs) < pluginList->priority(rhs); - }); + [pluginList](const QString& lhs, const QString& rhs) { + return pluginList->priority(lhs) < pluginList->priority(rhs); + }); QStringList PrimaryPlugins = organizer()->managedGame()->primaryPlugins(); - QStringList DLCPlugins = organizer()->managedGame()->DLCPlugins(); - QSet ManagedMods = QSet(PrimaryPlugins.begin(), PrimaryPlugins.end()); + QStringList DLCPlugins = organizer()->managedGame()->DLCPlugins(); + QSet ManagedMods = + QSet(PrimaryPlugins.begin(), PrimaryPlugins.end()); QSet DLCSet = QSet(DLCPlugins.begin(), DLCPlugins.end()); ManagedMods.subtract(DLCSet); PrimaryPlugins.append(QList(ManagedMods.begin(), ManagedMods.end())); @@ -41,7 +43,7 @@ void EnderalSEGamePlugins::writePluginList(const MOBase::IPluginList* pluginList file->write("*Enderal - Forgotten Stories.esm\r\n"); file->write("*SkyUI_SE.esp\r\n"); - //TODO: do not write plugins in OFFICIAL_FILES container + // TODO: do not write plugins in OFFICIAL_FILES container for (const QString& pluginName : plugins) { if (!PrimaryPlugins.contains(pluginName, Qt::CaseInsensitive)) { if (pluginList->state(pluginName) == IPluginList::STATE_ACTIVE) { @@ -49,25 +51,18 @@ void EnderalSEGamePlugins::writePluginList(const MOBase::IPluginList* pluginList if (encoder.hasError()) { invalidFileNames = true; qCritical("invalid plugin name %s", qUtf8Printable(pluginName)); - } - else - { + } else { file->write("*"); file->write(result); - } file->write("\r\n"); ++writtenCount; - } - else - { + } else { auto result = encoder.encode(pluginName); if (encoder.hasError()) { invalidFileNames = true; qCritical("invalid plugin name %s", qUtf8Printable(pluginName)); - } - else - { + } else { file->write(result); } file->write("\r\n"); @@ -78,11 +73,10 @@ void EnderalSEGamePlugins::writePluginList(const MOBase::IPluginList* pluginList if (invalidFileNames) { reportError(QObject::tr("Some of your plugins have invalid names! These " - "plugins can not be loaded by the game. Please see " - "mo_interface.log for a list of affected plugins " - "and rename them.")); + "plugins can not be loaded by the game. Please see " + "mo_interface.log for a list of affected plugins " + "and rename them.")); } file.commitIfDifferent(m_LastSaveHash[filePath]); } - diff --git a/src/games/enderalse/src/enderalsegameplugins.h b/src/games/enderalse/src/enderalsegameplugins.h index 560dc090..16077f90 100644 --- a/src/games/enderalse/src/enderalsegameplugins.h +++ b/src/games/enderalse/src/enderalsegameplugins.h @@ -2,8 +2,8 @@ #define ENDERALSEGAMEPLUGINS_H #include -#include #include +#include #include class EnderalSEGamePlugins : public CreationGamePlugins @@ -12,11 +12,11 @@ public: using CreationGamePlugins::CreationGamePlugins; protected: - void writePluginList(const MOBase::IPluginList* pluginList, const QString& filePath) override; + void writePluginList(const MOBase::IPluginList* pluginList, + const QString& filePath) override; private: std::map m_LastSaveHash; - }; -#endif // ENDERALSEGAMEPLUGINS_H \ No newline at end of file +#endif // ENDERALSEGAMEPLUGINS_H \ No newline at end of file diff --git a/src/games/enderalse/src/enderalselocalsavegames.cpp b/src/games/enderalse/src/enderalselocalsavegames.cpp index 839542b3..b3aa2546 100644 --- a/src/games/enderalse/src/enderalselocalsavegames.cpp +++ b/src/games/enderalse/src/enderalselocalsavegames.cpp @@ -16,57 +16,48 @@ License along with this library; if not, write to the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA */ - #include "enderalselocalsavegames.h" #include "registry.h" -#include #include -#include +#include #include #include - +#include static const QString LocalSavesDummy = "..\\Enderal Special Edition\\__MO_Saves\\"; - EnderalSELocalSavegames::EnderalSELocalSavegames(const QDir& myGamesDir, - const QString& iniFileName) - : m_LocalSavesDir(myGamesDir.absoluteFilePath(LocalSavesDummy)) - , m_LocalGameDir(myGamesDir.absolutePath()) - , m_IniFileName(iniFileName) + const QString& iniFileName) + : m_LocalSavesDir(myGamesDir.absoluteFilePath(LocalSavesDummy)), + m_LocalGameDir(myGamesDir.absolutePath()), m_IniFileName(iniFileName) {} - MappingType EnderalSELocalSavegames::mappings(const QDir& profileSaveDir) const { - return { { - profileSaveDir.absolutePath(), - m_LocalSavesDir.absolutePath(), - true, - true - } }; + return {{profileSaveDir.absolutePath(), m_LocalSavesDir.absolutePath(), true, true}}; } - bool EnderalSELocalSavegames::prepareProfile(MOBase::IProfile* profile) { bool enable = profile->localSavesEnabled(); - QString basePath - = profile->localSettingsEnabled() - ? profile->absolutePath() - : m_LocalGameDir.absolutePath(); + QString basePath = profile->localSettingsEnabled() ? profile->absolutePath() + : m_LocalGameDir.absolutePath(); QString iniFilePath = basePath + "/" + m_IniFileName; - QString saveIni = profile->absolutePath() + "/" + "savepath.ini"; + QString saveIni = profile->absolutePath() + "/" + "savepath.ini"; // Get the current sLocalSavePath WCHAR currentPath[MAX_PATH]; - GetPrivateProfileStringW(L"General", L"sLocalSavePath", L"SKIP_ME", currentPath, MAX_PATH, iniFilePath.toStdWString().c_str()); - bool alreadyEnabled = wcscmp(currentPath, LocalSavesDummy.toStdWString().c_str()) == 0; + GetPrivateProfileStringW(L"General", L"sLocalSavePath", L"SKIP_ME", currentPath, + MAX_PATH, iniFilePath.toStdWString().c_str()); + bool alreadyEnabled = + wcscmp(currentPath, LocalSavesDummy.toStdWString().c_str()) == 0; // Get the current bUseMyGamesDirectory WCHAR currentMyGames[MAX_PATH]; - GetPrivateProfileStringW(L"General", L"bUseMyGamesDirectory", L"SKIP_ME", currentMyGames, MAX_PATH, iniFilePath.toStdWString().c_str()); + GetPrivateProfileStringW(L"General", L"bUseMyGamesDirectory", L"SKIP_ME", + currentMyGames, MAX_PATH, + iniFilePath.toStdWString().c_str()); // Create the __MO_Saves directory if local saves are enabled and it doesn't exist if (enable) { @@ -80,13 +71,18 @@ bool EnderalSELocalSavegames::prepareProfile(MOBase::IProfile* profile) if (enable && !alreadyEnabled) { // If the path is not blank, save it to savepath.ini if (wcscmp(currentPath, L"SKIP_ME") != 0) { - MOBase::WriteRegistryValue(L"General", L"sLocalSavePath", currentPath, saveIni.toStdWString().c_str()); + MOBase::WriteRegistryValue(L"General", L"sLocalSavePath", currentPath, + saveIni.toStdWString().c_str()); } if (wcscmp(currentMyGames, L"SKIP_ME") != 0) { - MOBase::WriteRegistryValue(L"General", L"bUseMyGamesDirectory", currentMyGames, saveIni.toStdWString().c_str()); + MOBase::WriteRegistryValue(L"General", L"bUseMyGamesDirectory", currentMyGames, + saveIni.toStdWString().c_str()); } - MOBase::WriteRegistryValue(L"General", L"sLocalSavePath", LocalSavesDummy.toStdWString().c_str(), iniFilePath.toStdWString().c_str()); - MOBase::WriteRegistryValue(L"General", L"bUseMyGamesDirectory", L"1", iniFilePath.toStdWString().c_str()); + MOBase::WriteRegistryValue(L"General", L"sLocalSavePath", + LocalSavesDummy.toStdWString().c_str(), + iniFilePath.toStdWString().c_str()); + MOBase::WriteRegistryValue(L"General", L"bUseMyGamesDirectory", L"1", + iniFilePath.toStdWString().c_str()); } // Get rid of the local saves setting if it's still there @@ -95,26 +91,32 @@ bool EnderalSELocalSavegames::prepareProfile(MOBase::IProfile* profile) if (QFile::exists(saveIni)) { WCHAR savedPath[MAX_PATH]; WCHAR savedMyGames[MAX_PATH]; - GetPrivateProfileStringW(L"General", L"sLocalSavePath", L"DELETE_ME", savedPath, MAX_PATH, saveIni.toStdWString().c_str()); - GetPrivateProfileStringW(L"General", L"bUseMyGamesDirectory", L"DELETE_ME", savedMyGames, MAX_PATH, saveIni.toStdWString().c_str()); + GetPrivateProfileStringW(L"General", L"sLocalSavePath", L"DELETE_ME", savedPath, + MAX_PATH, saveIni.toStdWString().c_str()); + GetPrivateProfileStringW(L"General", L"bUseMyGamesDirectory", L"DELETE_ME", + savedMyGames, MAX_PATH, saveIni.toStdWString().c_str()); if (wcscmp(savedPath, L"DELETE_ME") != 0) { - MOBase::WriteRegistryValue(L"General", L"sLocalSavePath", savedPath, iniFilePath.toStdWString().c_str()); - } - else { - MOBase::WriteRegistryValue(L"General", L"sLocalSavePath", NULL, iniFilePath.toStdWString().c_str()); + MOBase::WriteRegistryValue(L"General", L"sLocalSavePath", savedPath, + iniFilePath.toStdWString().c_str()); + } else { + MOBase::WriteRegistryValue(L"General", L"sLocalSavePath", NULL, + iniFilePath.toStdWString().c_str()); } if (wcscmp(savedMyGames, L"DELETE_ME") != 0) { - MOBase::WriteRegistryValue(L"General", L"bUseMyGamesDirectory", savedMyGames, iniFilePath.toStdWString().c_str()); - } - else { - MOBase::WriteRegistryValue(L"General", L"bUseMyGamesDirectory", NULL, iniFilePath.toStdWString().c_str()); + MOBase::WriteRegistryValue(L"General", L"bUseMyGamesDirectory", savedMyGames, + iniFilePath.toStdWString().c_str()); + } else { + MOBase::WriteRegistryValue(L"General", L"bUseMyGamesDirectory", NULL, + iniFilePath.toStdWString().c_str()); } QFile::remove(saveIni); } // Otherwise just delete the setting else { - MOBase::WriteRegistryValue(L"General", L"sLocalSavePath", NULL, iniFilePath.toStdWString().c_str()); - MOBase::WriteRegistryValue(L"General", L"bUseMyGamesDirectory", NULL, iniFilePath.toStdWString().c_str()); + MOBase::WriteRegistryValue(L"General", L"sLocalSavePath", NULL, + iniFilePath.toStdWString().c_str()); + MOBase::WriteRegistryValue(L"General", L"bUseMyGamesDirectory", NULL, + iniFilePath.toStdWString().c_str()); } } diff --git a/src/games/enderalse/src/enderalselocalsavegames.h b/src/games/enderalse/src/enderalselocalsavegames.h index b24cfe59..3fd2d3fc 100644 --- a/src/games/enderalse/src/enderalselocalsavegames.h +++ b/src/games/enderalse/src/enderalselocalsavegames.h @@ -1,7 +1,6 @@ #ifndef ENDERALSELOCALSAVEGAMES_H #define ENDERALSELOCALSAVEGAMES_H - #include #include @@ -17,12 +16,9 @@ public: virtual bool prepareProfile(MOBase::IProfile* profile) override; private: - QDir m_LocalSavesDir; QDir m_LocalGameDir; QString m_IniFileName; - }; - -#endif // ENDERALSELOCALSAVEGAMES_H +#endif // ENDERALSELOCALSAVEGAMES_H diff --git a/src/games/enderalse/src/enderalsemoddatachecker.h b/src/games/enderalse/src/enderalsemoddatachecker.h index c2b48b69..23368197 100644 --- a/src/games/enderalse/src/enderalsemoddatachecker.h +++ b/src/games/enderalse/src/enderalsemoddatachecker.h @@ -9,22 +9,23 @@ public: using GamebryoModDataChecker::GamebryoModDataChecker; protected: - virtual const FileNameSet& possibleFolderNames() const override { + virtual const FileNameSet& possibleFolderNames() const override + { static FileNameSet result{ - "fonts", "interface", "menus", "meshes", "music", "scripts", "shaders", - "sound", "strings", "textures", "trees", "video", "facegen", "materials", - "skse", "distantlod", "asi", "Tools", "MCM", "distantland", "mits", - "dllplugins", "CalienteTools", "NetScriptFramework", "shadersfx", - "Nemesis_Engine" - }; + "fonts", "interface", "menus", "meshes", + "music", "scripts", "shaders", "sound", + "strings", "textures", "trees", "video", + "facegen", "materials", "skse", "distantlod", + "asi", "Tools", "MCM", "distantland", + "mits", "dllplugins", "CalienteTools", "NetScriptFramework", + "shadersfx", "Nemesis_Engine"}; return result; } - virtual const FileNameSet& possibleFileExtensions() const override { - static FileNameSet result{ - "esp", "esm", "esl", "bsa", "modgroups", "ini" - }; + virtual const FileNameSet& possibleFileExtensions() const override + { + static FileNameSet result{"esp", "esm", "esl", "bsa", "modgroups", "ini"}; return result; } }; -#endif // SKYRIMSE_MODATACHECKER_H +#endif // SKYRIMSE_MODATACHECKER_H diff --git a/src/games/enderalse/src/enderalsemoddatacontent.h b/src/games/enderalse/src/enderalsemoddatacontent.h index d1582917..b72b59dd 100644 --- a/src/games/enderalse/src/enderalsemoddatacontent.h +++ b/src/games/enderalse/src/enderalsemoddatacontent.h @@ -4,17 +4,18 @@ #include #include -class EnderalSEModDataContent : public GamebryoModDataContent { +class EnderalSEModDataContent : public GamebryoModDataContent +{ public: - /** * */ - EnderalSEModDataContent(GameGamebryo const* gamePlugin) : GamebryoModDataContent(gamePlugin) { + EnderalSEModDataContent(GameGamebryo const* gamePlugin) + : GamebryoModDataContent(gamePlugin) + { // Just need to disable some contents: m_Enabled[CONTENT_SKYPROC] = false; } - }; -#endif // SKYRIMSE_MODDATACONTENT_H +#endif // SKYRIMSE_MODDATACONTENT_H diff --git a/src/games/enderalse/src/enderalsesavegame.cpp b/src/games/enderalse/src/enderalsesavegame.cpp index 955c84a7..c5bf68af 100644 --- a/src/games/enderalse/src/enderalsesavegame.cpp +++ b/src/games/enderalse/src/enderalsesavegame.cpp @@ -2,27 +2,28 @@ #include -EnderalSESaveGame::EnderalSESaveGame(QString const &fileName, GameEnderalSE const *game) : - GamebryoSaveGame(fileName, game, true) +EnderalSESaveGame::EnderalSESaveGame(QString const& fileName, GameEnderalSE const* game) + : GamebryoSaveGame(fileName, game, true) { - FileWrapper file(fileName, "TESV_SAVEGAME"); //10bytes + FileWrapper file(fileName, "TESV_SAVEGAME"); // 10bytes unsigned long version; FILETIME ftime; - fetchInformationFields(file, version, m_PCName, m_PCLevel, m_PCLocation, m_SaveNumber, ftime); + fetchInformationFields(file, version, m_PCName, m_PCLevel, m_PCLocation, m_SaveNumber, + ftime); - //A file time is a 64-bit value that represents the number of 100-nanosecond - //intervals that have elapsed since 12:00 A.M. January 1, 1601 Coordinated Universal Time (UTC). - //So we need to convert that to something useful + // A file time is a 64-bit value that represents the number of 100-nanosecond + // intervals that have elapsed since 12:00 A.M. January 1, 1601 Coordinated Universal + // Time (UTC). So we need to convert that to something useful - //For some reason, the file time is off by about 6 hours. - //So we need to subtract those 6 hours from the filetime. + // For some reason, the file time is off by about 6 hours. + // So we need to subtract those 6 hours from the filetime. _ULARGE_INTEGER time; - time.LowPart = ftime.dwLowDateTime; + time.LowPart = ftime.dwLowDateTime; time.HighPart = ftime.dwHighDateTime; time.QuadPart -= 2.16e11; ftime.dwHighDateTime = time.HighPart; - ftime.dwLowDateTime = time.LowPart; + ftime.dwLowDateTime = time.LowPart; SYSTEMTIME ctime; ::FileTimeToSystemTime(&ftime, &ctime); @@ -31,16 +32,12 @@ EnderalSESaveGame::EnderalSESaveGame(QString const &fileName, GameEnderalSE cons } void EnderalSESaveGame::fetchInformationFields( - FileWrapper& file, - unsigned long& version, - QString& playerName, - unsigned short& playerLevel, - QString& playerLocation, - unsigned long& saveNumber, - FILETIME& creationTime) const + FileWrapper& file, unsigned long& version, QString& playerName, + unsigned short& playerLevel, QString& playerLocation, unsigned long& saveNumber, + FILETIME& creationTime) const { unsigned long headerSize; - file.read(headerSize); // header size "TESV_SAVEGAME" + file.read(headerSize); // header size "TESV_SAVEGAME" file.read(version); file.read(saveNumber); file.read(playerName); @@ -54,17 +51,17 @@ void EnderalSESaveGame::fetchInformationFields( file.read(timeOfDay); QString race; - file.read(race); // race name (i.e. BretonRace) + file.read(race); // race name (i.e. BretonRace) - file.skip(); // Player gender (0 = male) - file.skip(2); // experience gathered, experience required + file.skip(); // Player gender (0 = male) + file.skip(2); // experience gathered, experience required - file.read(creationTime); //filetime + file.read(creationTime); // filetime } std::unique_ptr EnderalSESaveGame::fetchDataFields() const { - FileWrapper file(getFilepath(), "TESV_SAVEGAME"); //10bytes + FileWrapper file(getFilepath(), "TESV_SAVEGAME"); // 10bytes unsigned long version = 0; { @@ -73,8 +70,8 @@ std::unique_ptr EnderalSESaveGame::fetchDataFields unsigned long dummySaveNumber; FILETIME dummyTime; - fetchInformationFields(file, version, dummyName, dummyLevel, - dummyLocation, dummySaveNumber, dummyTime); + fetchInformationFields(file, version, dummyName, dummyLevel, dummyLocation, + dummySaveNumber, dummyTime); } std::unique_ptr fields = std::make_unique(); @@ -101,10 +98,10 @@ std::unique_ptr EnderalSESaveGame::fetchDataFields file.openCompressedData(); uint8_t saveGameVersion = file.readChar(); - uint8_t pluginInfoSize = file.readChar(); - uint16_t other = file.readShort(); //Unknown + uint8_t pluginInfoSize = file.readChar(); + uint16_t other = file.readShort(); // Unknown - fields->Plugins = file.readPlugins(1); // Just empty data + fields->Plugins = file.readPlugins(1); // Just empty data if (saveGameVersion >= 78) { fields->LightPlugins = file.readLightPlugins(); diff --git a/src/games/enderalse/src/enderalsesavegame.h b/src/games/enderalse/src/enderalsesavegame.h index f92a12d5..addd11fe 100644 --- a/src/games/enderalse/src/enderalsesavegame.h +++ b/src/games/enderalse/src/enderalsesavegame.h @@ -4,26 +4,24 @@ #include "gamebryosavegame.h" #include "gameenderalse.h" -namespace MOBase { class IPluginGame; } +namespace MOBase +{ +class IPluginGame; +} class EnderalSESaveGame : public GamebryoSaveGame { public: - EnderalSESaveGame(QString const &fileName, GameEnderalSE const *game); + EnderalSESaveGame(QString const& fileName, GameEnderalSE const* game); protected: - // Fetch easy-to-access information. - void fetchInformationFields(FileWrapper& wrapper, - unsigned long& version, - QString& playerName, - unsigned short& playerLevel, - QString& playerLocation, - unsigned long& saveNumber, - FILETIME& creationTime) const; + void fetchInformationFields(FileWrapper& wrapper, unsigned long& version, + QString& playerName, unsigned short& playerLevel, + QString& playerLocation, unsigned long& saveNumber, + FILETIME& creationTime) const; std::unique_ptr fetchDataFields() const override; - }; -#endif // _SKYRIMSESAVEGAME_H +#endif // _SKYRIMSESAVEGAME_H diff --git a/src/games/enderalse/src/enderalsescriptextender.cpp b/src/games/enderalse/src/enderalsescriptextender.cpp index 6c073f34..f7a31136 100644 --- a/src/games/enderalse/src/enderalsescriptextender.cpp +++ b/src/games/enderalse/src/enderalsescriptextender.cpp @@ -3,10 +3,9 @@ #include #include -EnderalSEScriptExtender::EnderalSEScriptExtender(GameGamebryo const *game) : - GamebryoScriptExtender(game) -{ -} +EnderalSEScriptExtender::EnderalSEScriptExtender(GameGamebryo const* game) + : GamebryoScriptExtender(game) +{} QString EnderalSEScriptExtender::BinaryName() const { diff --git a/src/games/enderalse/src/enderalsescriptextender.h b/src/games/enderalse/src/enderalsescriptextender.h index a410e5d1..79edaf2f 100644 --- a/src/games/enderalse/src/enderalsescriptextender.h +++ b/src/games/enderalse/src/enderalsescriptextender.h @@ -8,11 +8,10 @@ class GameGamebryo; class EnderalSEScriptExtender : public GamebryoScriptExtender { public: - EnderalSEScriptExtender(GameGamebryo const *game); + EnderalSEScriptExtender(GameGamebryo const* game); virtual QString BinaryName() const override; virtual QString PluginPath() const override; - }; -#endif // _SKYRIMSESCRIPTEXTENDER_H +#endif // _SKYRIMSESCRIPTEXTENDER_H diff --git a/src/games/enderalse/src/enderalseunmanagedmods.cpp b/src/games/enderalse/src/enderalseunmanagedmods.cpp index 7bf0c5d2..9f11b442 100644 --- a/src/games/enderalse/src/enderalseunmanagedmods.cpp +++ b/src/games/enderalse/src/enderalseunmanagedmods.cpp @@ -1,27 +1,26 @@ #include "enderalseunmanagedmods.h" - -EnderalSEUnmangedMods::EnderalSEUnmangedMods(const GameGamebryo *game) - : GamebryoUnmangedMods(game) +EnderalSEUnmangedMods::EnderalSEUnmangedMods(const GameGamebryo* game) + : GamebryoUnmangedMods(game) {} -EnderalSEUnmangedMods::~EnderalSEUnmangedMods() -{} +EnderalSEUnmangedMods::~EnderalSEUnmangedMods() {} -QStringList EnderalSEUnmangedMods::mods(bool onlyOfficial) const { +QStringList EnderalSEUnmangedMods::mods(bool onlyOfficial) const +{ QStringList result; - QStringList pluginList = game()->primaryPlugins(); + QStringList pluginList = game()->primaryPlugins(); QStringList otherPlugins = game()->DLCPlugins(); otherPlugins.append(game()->CCPlugins()); for (QString plugin : otherPlugins) { pluginList.removeAll(plugin); } QDir dataDir(game()->dataDirectory()); - for (const QString &fileName : dataDir.entryList({ "*.esp", "*.esl", "*.esm" })) { + for (const QString& fileName : dataDir.entryList({"*.esp", "*.esl", "*.esm"})) { if (!pluginList.contains(fileName, Qt::CaseInsensitive)) { if (!onlyOfficial || pluginList.contains(fileName, Qt::CaseInsensitive)) { - result.append(fileName.chopped(4)); // trims the extension off + result.append(fileName.chopped(4)); // trims the extension off } } } diff --git a/src/games/enderalse/src/enderalseunmanagedmods.h b/src/games/enderalse/src/enderalseunmanagedmods.h index f8102d5d..6eda5028 100644 --- a/src/games/enderalse/src/enderalseunmanagedmods.h +++ b/src/games/enderalse/src/enderalseunmanagedmods.h @@ -1,19 +1,16 @@ #ifndef ENDERALSEUNMANAGEDMODS_H #define ENDERALSEUNMANAGEDMODS_H - #include "gamebryounmanagedmods.h" #include - -class EnderalSEUnmangedMods : public GamebryoUnmangedMods { +class EnderalSEUnmangedMods : public GamebryoUnmangedMods +{ public: - EnderalSEUnmangedMods(const GameGamebryo *game); + EnderalSEUnmangedMods(const GameGamebryo* game); ~EnderalSEUnmangedMods(); virtual QStringList mods(bool onlyOfficial) const override; }; - - -#endif // _SKYRIMSEUNMANAGEDMODS_H +#endif // _SKYRIMSEUNMANAGEDMODS_H diff --git a/src/games/enderalse/src/gameenderalse.cpp b/src/games/enderalse/src/gameenderalse.cpp index 833769e9..514c9137 100644 --- a/src/games/enderalse/src/gameenderalse.cpp +++ b/src/games/enderalse/src/gameenderalse.cpp @@ -1,20 +1,20 @@ #include "gameenderalse.h" #include "enderalsedataarchives.h" -#include "enderalsescriptextender.h" -#include "enderalseunmanagedmods.h" #include "enderalsegameplugins.h" #include "enderalselocalsavegames.h" #include "enderalsemoddatachecker.h" #include "enderalsemoddatacontent.h" #include "enderalsesavegame.h" +#include "enderalsescriptextender.h" +#include "enderalseunmanagedmods.h" #include "steamutility.h" -#include +#include "versioninfo.h" #include #include -#include "versioninfo.h" #include +#include #include #include @@ -25,8 +25,8 @@ #include #include -#include #include "scopeguard.h" +#include using namespace MOBase; @@ -34,308 +34,309 @@ GameEnderalSE::GameEnderalSE() {} void GameEnderalSE::setVariant(QString variant) { - m_GameVariant = variant; + m_GameVariant = variant; } void GameEnderalSE::checkVariants() { - QFileInfo gog_dll(m_GamePath + "\\Galaxy64.dll"); - if (gog_dll.exists()) - setVariant("GOG"); - else - setVariant("Steam"); + QFileInfo gog_dll(m_GamePath + "\\Galaxy64.dll"); + if (gog_dll.exists()) + setVariant("GOG"); + else + setVariant("Steam"); } QDir GameEnderalSE::documentsDirectory() const { - return m_MyGamesPath; + return m_MyGamesPath; } void GameEnderalSE::detectGame() { - m_GamePath = identifyGamePath(); - checkVariants(); - m_MyGamesPath = determineMyGamesPath(gameDirectoryName()); + m_GamePath = identifyGamePath(); + checkVariants(); + m_MyGamesPath = determineMyGamesPath(gameDirectoryName()); } QString GameEnderalSE::identifyGamePath() const { - QMap paths = { - {"Software\\Bethesda Softworks\\" + gameName(), "Installed Path"}, - {"Software\\GOG.com\\Games\\1708684988", "path"}, - }; - QString result; - try { - for (auto& path : paths.toStdMap()) { - result = findInRegistry(HKEY_LOCAL_MACHINE, path.first.toStdWString().c_str(), - path.second.toStdWString().c_str()); - if (!result.isEmpty()) - break; - } - } - catch (MOBase::MyException) { - result = MOBase::findSteamGame("Enderal Special Edition", "Data\\Enderal - Forgotten Stories.esm"); - } - return result; + QMap paths = { + {"Software\\Bethesda Softworks\\" + gameName(), "Installed Path"}, + {"Software\\GOG.com\\Games\\1708684988", "path"}, + }; + QString result; + try { + for (auto& path : paths.toStdMap()) { + result = findInRegistry(HKEY_LOCAL_MACHINE, path.first.toStdWString().c_str(), + path.second.toStdWString().c_str()); + if (!result.isEmpty()) + break; + } + } catch (MOBase::MyException) { + result = MOBase::findSteamGame("Enderal Special Edition", + "Data\\Enderal - Forgotten Stories.esm"); + } + return result; } void GameEnderalSE::setGamePath(const QString& path) { - m_GamePath = path; - checkVariants(); - m_MyGamesPath = determineMyGamesPath(gameDirectoryName()); - registerFeature(new EnderalSEDataArchives(myGamesPath())); - registerFeature(new EnderalSELocalSavegames(myGamesPath(), "Enderal.ini")); + m_GamePath = path; + checkVariants(); + m_MyGamesPath = determineMyGamesPath(gameDirectoryName()); + registerFeature(new EnderalSEDataArchives(myGamesPath())); + registerFeature( + new EnderalSELocalSavegames(myGamesPath(), "Enderal.ini")); } QDir GameEnderalSE::savesDirectory() const { - return QDir(m_MyGamesPath + "/Saves"); + return QDir(m_MyGamesPath + "/Saves"); } QString GameEnderalSE::myGamesPath() const { - return m_MyGamesPath; + return m_MyGamesPath; } bool GameEnderalSE::isInstalled() const { - return !m_GamePath.isEmpty(); + return !m_GamePath.isEmpty(); } bool GameEnderalSE::init(IOrganizer* moInfo) { - if (!GameGamebryo::init(moInfo)) { - return false; - } + if (!GameGamebryo::init(moInfo)) { + return false; + } - registerFeature(new EnderalSEScriptExtender(this)); - registerFeature(new EnderalSEDataArchives(myGamesPath())); - registerFeature(new EnderalSELocalSavegames(myGamesPath(), "Enderal.ini")); - registerFeature(new EnderalSEModDataChecker(this)); - registerFeature(new EnderalSEModDataContent(this)); - registerFeature(new GamebryoSaveGameInfo(this)); - registerFeature(new EnderalSEGamePlugins(moInfo)); - registerFeature(new EnderalSEUnmangedMods(this)); + registerFeature(new EnderalSEScriptExtender(this)); + registerFeature(new EnderalSEDataArchives(myGamesPath())); + registerFeature( + new EnderalSELocalSavegames(myGamesPath(), "Enderal.ini")); + registerFeature(new EnderalSEModDataChecker(this)); + registerFeature(new EnderalSEModDataContent(this)); + registerFeature(new GamebryoSaveGameInfo(this)); + registerFeature(new EnderalSEGamePlugins(moInfo)); + registerFeature(new EnderalSEUnmangedMods(this)); - return true; + return true; } QString GameEnderalSE::gameName() const { - return "Enderal Special Edition"; + return "Enderal Special Edition"; } QString GameEnderalSE::gameDirectoryName() const { - if (selectedVariant() == "GOG") - return "Enderal Special Edition GOG"; - else - return "Enderal Special Edition"; + if (selectedVariant() == "GOG") + return "Enderal Special Edition GOG"; + else + return "Enderal Special Edition"; } QIcon GameEnderalSE::gameIcon() const { - return MOBase::iconForExecutable(gameDirectory().absoluteFilePath(getLauncherName())); + return MOBase::iconForExecutable(gameDirectory().absoluteFilePath(getLauncherName())); } QList GameEnderalSE::executables() const { - return QList() - << ExecutableInfo("Enderal Special Edition (SKSE)", findInGameFolder(feature()->loaderName())) - << ExecutableInfo("Enderal Special Edition Launcher", findInGameFolder(getLauncherName())) - << ExecutableInfo("Creation Kit", findInGameFolder("CreationKit.exe")).withSteamAppId("1946180") - << ExecutableInfo("LOOT", QFileInfo(getLootPath())).withArgument("--game=\"Enderal Special Edition\""); + return QList() + << ExecutableInfo("Enderal Special Edition (SKSE)", + findInGameFolder(feature()->loaderName())) + << ExecutableInfo("Enderal Special Edition Launcher", + findInGameFolder(getLauncherName())) + << ExecutableInfo("Creation Kit", findInGameFolder("CreationKit.exe")) + .withSteamAppId("1946180") + << ExecutableInfo("LOOT", QFileInfo(getLootPath())) + .withArgument("--game=\"Enderal Special Edition\""); } QList GameEnderalSE::executableForcedLoads() const { - return QList(); + return QList(); } QString GameEnderalSE::binaryName() const { - return "skse64_loader.exe"; + return "skse64_loader.exe"; } QString GameEnderalSE::getLauncherName() const { - return "Enderal Launcher.exe"; + return "Enderal Launcher.exe"; } bool GameEnderalSE::looksValid(const QDir& folder) const { - // we need to check both launcher and binary because the binary also exists for - // Skyrim SE and the launcher for Enderal LE - return folder.exists(getLauncherName()) && folder.exists(binaryName()); + // we need to check both launcher and binary because the binary also exists for + // Skyrim SE and the launcher for Enderal LE + return folder.exists(getLauncherName()) && folder.exists(binaryName()); } QFileInfo GameEnderalSE::findInGameFolder(const QString& relativePath) const { - return QFileInfo(m_GamePath + "/" + relativePath); + return QFileInfo(m_GamePath + "/" + relativePath); } QString GameEnderalSE::name() const { - return "Enderal Special Edition Support Plugin"; + return "Enderal Special Edition Support Plugin"; } QString GameEnderalSE::localizedName() const { - return tr("Enderal Special Edition Support Plugin"); + return tr("Enderal Special Edition Support Plugin"); } QString GameEnderalSE::author() const { - return "Holt59, Archost & ZachHaber"; + return "Holt59, Archost & ZachHaber"; } QString GameEnderalSE::description() const { - return tr("Adds support for the game Enderal Special Edition."); + return tr("Adds support for the game Enderal Special Edition."); } MOBase::VersionInfo GameEnderalSE::version() const { - return VersionInfo(1, 1, 0, VersionInfo::RELEASE_FINAL); + return VersionInfo(1, 1, 0, VersionInfo::RELEASE_FINAL); } QList GameEnderalSE::settings() const { - return QList(); + return QList(); } void GameEnderalSE::initializeProfile(const QDir& path, ProfileSettings settings) const { - if (settings.testFlag(IPluginGame::MODS)) { - copyToProfile(localAppFolder() + "/Enderal Special Edition", path, "plugins.txt"); - } + if (settings.testFlag(IPluginGame::MODS)) { + copyToProfile(localAppFolder() + "/Enderal Special Edition", path, "plugins.txt"); + } - if (settings.testFlag(IPluginGame::CONFIGURATION)) { - if (settings.testFlag(IPluginGame::PREFER_DEFAULTS) - || !QFileInfo(myGamesPath() + "/Enderal.ini").exists()) { + if (settings.testFlag(IPluginGame::CONFIGURATION)) { + if (settings.testFlag(IPluginGame::PREFER_DEFAULTS) || + !QFileInfo(myGamesPath() + "/Enderal.ini").exists()) { - //there is no default ini, actually they are going to put them in for us! - copyToProfile(gameDirectory().absolutePath(), path, "enderal_default.ini", "Enderal.ini"); - copyToProfile(gameDirectory().absolutePath(), path, "enderalprefs_default.ini", "EnderalPrefs.ini"); - } - else { - copyToProfile(myGamesPath(), path, "Enderal.ini"); - copyToProfile(myGamesPath(), path, "EnderalPrefs.ini"); - } - } + // there is no default ini, actually they are going to put them in for us! + copyToProfile(gameDirectory().absolutePath(), path, "enderal_default.ini", + "Enderal.ini"); + copyToProfile(gameDirectory().absolutePath(), path, "enderalprefs_default.ini", + "EnderalPrefs.ini"); + } else { + copyToProfile(myGamesPath(), path, "Enderal.ini"); + copyToProfile(myGamesPath(), path, "EnderalPrefs.ini"); + } + } } QString GameEnderalSE::savegameExtension() const { - return "ess"; + return "ess"; } QString GameEnderalSE::savegameSEExtension() const { - return "skse"; + return "skse"; } -std::shared_ptr GameEnderalSE::makeSaveGame(QString filePath) const +std::shared_ptr +GameEnderalSE::makeSaveGame(QString filePath) const { - return std::make_shared(filePath, this); + return std::make_shared(filePath, this); } QString GameEnderalSE::steamAPPId() const { - if (selectedVariant() == "Steam") - return "976620"; - return ""; + if (selectedVariant() == "Steam") + return "976620"; + return ""; } QStringList GameEnderalSE::primaryPlugins() const { - return { - "skyrim.esm", - "update.esm", - "dawnguard.esm", - "hearthfires.esm", - "dragonborn.esm", + return {"skyrim.esm", "update.esm", "dawnguard.esm", "hearthfires.esm", + "dragonborn.esm", - // these two plugins are considered "primary" for users but are not - // automatically loaded by the game so we need to force-write them - // to the plugin list - "enderal - forgotten stories.esm", - "skyui_se.esp" - }; + // these two plugins are considered "primary" for users but are not + // automatically loaded by the game so we need to force-write them + // to the plugin list + "enderal - forgotten stories.esm", "skyui_se.esp"}; } QStringList GameEnderalSE::DLCPlugins() const { - return { }; + return {}; } - QStringList GameEnderalSE::gameVariants() const { - return{ "Steam", "GOG" }; + return {"Steam", "GOG"}; } QString GameEnderalSE::gameShortName() const { - return "EnderalSE"; + return "EnderalSE"; } QStringList GameEnderalSE::validShortNames() const { - return { "Skyrim", "SkyrimSE", "Enderal" }; + return {"Skyrim", "SkyrimSE", "Enderal"}; } QString GameEnderalSE::gameNexusName() const { - return "enderalspecialedition"; + return "enderalspecialedition"; } QStringList GameEnderalSE::iniFiles() const { - return { "Enderal.ini", "EnderalPrefs.ini" }; + return {"Enderal.ini", "EnderalPrefs.ini"}; } QStringList GameEnderalSE::CCPlugins() const { - return { }; + return {}; } MOBase::IPluginGame::SortMechanism GameEnderalSE::sortMechanism() const { - return SortMechanism::LOOT; + return SortMechanism::LOOT; } IPluginGame::LoadOrderMechanism GameEnderalSE::loadOrderMechanism() const { - return IPluginGame::LoadOrderMechanism::PluginsTxt; + return IPluginGame::LoadOrderMechanism::PluginsTxt; } int GameEnderalSE::nexusModOrganizerID() const { - return 0; + return 0; } int GameEnderalSE::nexusGameID() const { - return 3685; + return 3685; } QDir GameEnderalSE::gameDirectory() const { - return QDir(m_GamePath); + return QDir(m_GamePath); } // Not to delete all the spaces... MappingType GameEnderalSE::mappings() const { - MappingType result; + MappingType result; - for (const QString& profileFile : { "plugins.txt", "loadorder.txt" }) { - result.push_back({ m_Organizer->profilePath() + "/" + profileFile, - localAppFolder() + "/Enderal Special Edition/" + profileFile, - false }); - } + for (const QString& profileFile : {"plugins.txt", "loadorder.txt"}) { + result.push_back({m_Organizer->profilePath() + "/" + profileFile, + localAppFolder() + "/Enderal Special Edition/" + profileFile, + false}); + } - return result; + return result; } diff --git a/src/games/enderalse/src/gameenderalse.h b/src/games/enderalse/src/gameenderalse.h index f84d1672..11f00575 100644 --- a/src/games/enderalse/src/gameenderalse.h +++ b/src/games/enderalse/src/gameenderalse.h @@ -8,71 +8,70 @@ class GameEnderalSE : public GameGamebryo { - Q_OBJECT + Q_OBJECT - Q_PLUGIN_METADATA(IID "com.soundcontactstudio.GameEnderalSE" FILE "gameenderalse.json") + Q_PLUGIN_METADATA(IID "com.soundcontactstudio.GameEnderalSE" FILE + "gameenderalse.json") public: + GameEnderalSE(); - GameEnderalSE(); + virtual bool init(MOBase::IOrganizer* moInfo) override; - virtual bool init(MOBase::IOrganizer* moInfo) override; +public: // IPluginGame interface + virtual void detectGame() override; + virtual QString gameName() const override; + virtual QIcon gameIcon() const override; + virtual QList executables() const override; + virtual QList + 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 getLauncherName() const override; + virtual bool looksValid(const QDir& folder) const override; + virtual QString gameShortName() const override; + virtual QString gameNexusName() const override; + virtual QStringList validShortNames() const override; + virtual QStringList iniFiles() const override; + virtual QStringList DLCPlugins() const override; + virtual QStringList CCPlugins() const override; + SortMechanism sortMechanism() const override; + virtual LoadOrderMechanism loadOrderMechanism() const override; + virtual int nexusModOrganizerID() const override; + virtual int nexusGameID() const override; -public: // IPluginGame interface - virtual void detectGame() override; - virtual QString gameName() const override; - virtual QIcon gameIcon() const override; - virtual QList executables() const override; - virtual QList 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 getLauncherName() const override; - virtual bool looksValid(const QDir& folder) const override; - virtual QString gameShortName() const override; - virtual QString gameNexusName() const override; - virtual QStringList validShortNames() const override; - virtual QStringList iniFiles() const override; - virtual QStringList DLCPlugins() const override; - virtual QStringList CCPlugins() const override; - SortMechanism sortMechanism() const override; - virtual LoadOrderMechanism loadOrderMechanism() const override; - virtual int nexusModOrganizerID() const override; - virtual int nexusGameID() 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 settings() const override; - virtual MappingType mappings() 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 settings() const override; + virtual MappingType mappings() const override; protected: + std::shared_ptr makeSaveGame(QString filePath) const override; + QString savegameExtension() const override; + QString savegameSEExtension() const override; - std::shared_ptr makeSaveGame(QString filePath) const override; - QString savegameExtension() const override; - QString savegameSEExtension() const override; + QString gameDirectoryName() const; + QDir documentsDirectory() const; + QDir savesDirectory() const; + QFileInfo findInGameFolder(const QString& relativePath) const; + QString myGamesPath() const; - QString gameDirectoryName() const; - QDir documentsDirectory() const; - QDir savesDirectory() const; - QFileInfo findInGameFolder(const QString& relativePath) const; - QString myGamesPath() const; - - void checkVariants(); - void setVariant(QString variant); - - virtual QString identifyGamePath() const override; + void checkVariants(); + void setVariant(QString variant); + virtual QString identifyGamePath() const override; }; -#endif // _GAMESKYRIMSE_H +#endif // _GAMESKYRIMSE_H From 7333a9fa9b0236cdb147602db851266ddfef1123 Mon Sep 17 00:00:00 2001 From: Jeremy Rimpo Date: Mon, 18 Sep 2023 15:22:07 -0500 Subject: [PATCH 1335/1544] [game_enderalse] Ignore revs --- src/games/enderalse/src/game_enderalse_en.ts | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/src/games/enderalse/src/game_enderalse_en.ts b/src/games/enderalse/src/game_enderalse_en.ts index 37750ea8..875af5a4 100644 --- a/src/games/enderalse/src/game_enderalse_en.ts +++ b/src/games/enderalse/src/game_enderalse_en.ts @@ -4,12 +4,12 @@ GameEnderalSE - + Enderal Special Edition Support Plugin - + Adds support for the game Enderal Special Edition. @@ -17,7 +17,7 @@ QObject - + Some of your plugins have invalid names! These plugins can not be loaded by the game. Please see mo_interface.log for a list of affected plugins and rename them. From 162e2058d7c57f1057b11dea1c0df2c6f73c876b Mon Sep 17 00:00:00 2001 From: Jeremy Rimpo Date: Mon, 18 Sep 2023 21:26:42 -0500 Subject: [PATCH 1336/1544] [game_enderalse] Fix directory paths --- src/games/enderalse/src/gameenderalse.cpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/games/enderalse/src/gameenderalse.cpp b/src/games/enderalse/src/gameenderalse.cpp index 514c9137..7151e29e 100644 --- a/src/games/enderalse/src/gameenderalse.cpp +++ b/src/games/enderalse/src/gameenderalse.cpp @@ -214,7 +214,7 @@ QList GameEnderalSE::settings() const void GameEnderalSE::initializeProfile(const QDir& path, ProfileSettings settings) const { if (settings.testFlag(IPluginGame::MODS)) { - copyToProfile(localAppFolder() + "/Enderal Special Edition", path, "plugins.txt"); + copyToProfile(localAppFolder() + gameDirectoryName(), path, "plugins.txt"); } if (settings.testFlag(IPluginGame::CONFIGURATION)) { @@ -334,7 +334,7 @@ MappingType GameEnderalSE::mappings() const for (const QString& profileFile : {"plugins.txt", "loadorder.txt"}) { result.push_back({m_Organizer->profilePath() + "/" + profileFile, - localAppFolder() + "/Enderal Special Edition/" + profileFile, + localAppFolder() + "/" + gameDirectoryName() + "/" + profileFile, false}); } From 44d26382a671e1fe55b4f84b117b57233520f6fb Mon Sep 17 00:00:00 2001 From: Jeremy Rimpo Date: Mon, 18 Sep 2023 21:28:15 -0500 Subject: [PATCH 1337/1544] [game_enderalse] Ignore revs --- src/games/enderalse/.git-blame-ignore-revs | 2 ++ 1 file changed, 2 insertions(+) create mode 100644 src/games/enderalse/.git-blame-ignore-revs diff --git a/src/games/enderalse/.git-blame-ignore-revs b/src/games/enderalse/.git-blame-ignore-revs new file mode 100644 index 00000000..e8f4aa81 --- /dev/null +++ b/src/games/enderalse/.git-blame-ignore-revs @@ -0,0 +1,2 @@ +a5c06c204687d6bd51ef26721c548dd8695e9140 +c8fcf8490b2e4db5a1c7b9171adc68a014604d8e \ No newline at end of file From a1085e1abe278744ce2ed3f6e8e53240ec77bbde Mon Sep 17 00:00:00 2001 From: Jeremy Rimpo Date: Wed, 20 Sep 2023 20:50:38 -0500 Subject: [PATCH 1338/1544] [game_starfield] Update sorting methods --- src/games/starfield/src/gamestarfield.cpp | 5 +++++ src/games/starfield/src/gamestarfield.h | 1 + 2 files changed, 6 insertions(+) diff --git a/src/games/starfield/src/gamestarfield.cpp b/src/games/starfield/src/gamestarfield.cpp index 00a0a140..9592fef4 100644 --- a/src/games/starfield/src/gamestarfield.cpp +++ b/src/games/starfield/src/gamestarfield.cpp @@ -273,6 +273,11 @@ QStringList GameStarfield::CCPlugins() const return plugins; } +IPluginGame::SortMechanism GameStarfield::sortMechanism() const +{ + return IPluginGame::SortMechanism::NONE; +} + IPluginGame::LoadOrderMechanism GameStarfield::loadOrderMechanism() const { return IPluginGame::LoadOrderMechanism::None; diff --git a/src/games/starfield/src/gamestarfield.h b/src/games/starfield/src/gamestarfield.h index f08155b2..8b37a153 100644 --- a/src/games/starfield/src/gamestarfield.h +++ b/src/games/starfield/src/gamestarfield.h @@ -36,6 +36,7 @@ public: // IPluginGame interface virtual bool prepareIni(const QString& exec) override; virtual QStringList DLCPlugins() const override; virtual QStringList CCPlugins() const override; + virtual SortMechanism sortMechanism() const override; virtual LoadOrderMechanism loadOrderMechanism() const override; virtual int nexusModOrganizerID() const override; virtual int nexusGameID() const override; From 14ccd8cbddc2126437632b18a04c13c9a9df3661 Mon Sep 17 00:00:00 2001 From: Jeremy Rimpo Date: Wed, 20 Sep 2023 20:50:38 -0500 Subject: [PATCH 1339/1544] [game_enderalse] Update sorting methods --- src/games/enderalse/src/gameenderalse.cpp | 5 ----- src/games/enderalse/src/gameenderalse.h | 1 - 2 files changed, 6 deletions(-) diff --git a/src/games/enderalse/src/gameenderalse.cpp b/src/games/enderalse/src/gameenderalse.cpp index 7151e29e..851b5a25 100644 --- a/src/games/enderalse/src/gameenderalse.cpp +++ b/src/games/enderalse/src/gameenderalse.cpp @@ -302,11 +302,6 @@ QStringList GameEnderalSE::CCPlugins() const return {}; } -MOBase::IPluginGame::SortMechanism GameEnderalSE::sortMechanism() const -{ - return SortMechanism::LOOT; -} - IPluginGame::LoadOrderMechanism GameEnderalSE::loadOrderMechanism() const { return IPluginGame::LoadOrderMechanism::PluginsTxt; diff --git a/src/games/enderalse/src/gameenderalse.h b/src/games/enderalse/src/gameenderalse.h index 11f00575..51d77646 100644 --- a/src/games/enderalse/src/gameenderalse.h +++ b/src/games/enderalse/src/gameenderalse.h @@ -39,7 +39,6 @@ public: // IPluginGame interface virtual QStringList iniFiles() const override; virtual QStringList DLCPlugins() const override; virtual QStringList CCPlugins() const override; - SortMechanism sortMechanism() const override; virtual LoadOrderMechanism loadOrderMechanism() const override; virtual int nexusModOrganizerID() const override; virtual int nexusGameID() const override; From d0f9d3986083970b3021da0baa4752182a10ddb1 Mon Sep 17 00:00:00 2001 From: Jeremy Rimpo Date: Wed, 20 Sep 2023 20:50:39 -0500 Subject: [PATCH 1340/1544] [game_nehrim] Update sorting methods --- src/games/nehrim/src/gamenehrim.cpp | 127 ++++++++++++++-------------- 1 file changed, 64 insertions(+), 63 deletions(-) diff --git a/src/games/nehrim/src/gamenehrim.cpp b/src/games/nehrim/src/gamenehrim.cpp index b7e9e845..35548381 100644 --- a/src/games/nehrim/src/gamenehrim.cpp +++ b/src/games/nehrim/src/gamenehrim.cpp @@ -26,169 +26,170 @@ GameNehrim::GameNehrim() { } -bool GameNehrim::init(IOrganizer *moInfo) +bool GameNehrim::init(IOrganizer* moInfo) { - if (!GameGamebryo::init(moInfo)) { - return false; - } - registerFeature(new NehrimScriptExtender(this)); - registerFeature(new NehrimDataArchives(myGamesPath())); - registerFeature(new NehrimBSAInvalidation(feature(), this)); - registerFeature(new GamebryoSaveGameInfo(this)); - registerFeature(new GamebryoLocalSavegames(myGamesPath(), "oblivion.ini")); - registerFeature(new NehrimModDataChecker(this)); - registerFeature(new NehrimModDataContent(this)); - registerFeature(new GamebryoGamePlugins(moInfo)); - registerFeature(new GamebryoUnmangedMods(this)); - return true; + if (!GameGamebryo::init(moInfo)) { + return false; + } + registerFeature(new NehrimScriptExtender(this)); + registerFeature(new NehrimDataArchives(myGamesPath())); + registerFeature(new NehrimBSAInvalidation(feature(), this)); + registerFeature(new GamebryoSaveGameInfo(this)); + registerFeature(new GamebryoLocalSavegames(myGamesPath(), "oblivion.ini")); + registerFeature(new NehrimModDataChecker(this)); + registerFeature(new NehrimModDataContent(this)); + registerFeature(new GamebryoGamePlugins(moInfo)); + registerFeature(new GamebryoUnmangedMods(this)); + return true; } QString GameNehrim::gameName() const { - return "Nehrim"; + return "Nehrim"; } QList GameNehrim::executables() const { - return QList() - << ExecutableInfo("Nehrim", findInGameFolder("Oblivion.exe")) - << ExecutableInfo("Nehrim Launcher", findInGameFolder("NehrimLauncher.exe")) - << ExecutableInfo("Oblivion Mod Manager", findInGameFolder("OblivionModManager.exe")) - << ExecutableInfo("BOSS", findInGameFolder("BOSS/BOSS.exe")) - << ExecutableInfo("LOOT", QFileInfo(getLootPath())).withArgument("--game=\"Oblivion\"") - << ExecutableInfo("Construction Set", findInGameFolder("TESConstructionSet.exe")) - ; + return QList() + << ExecutableInfo("Nehrim", findInGameFolder("Oblivion.exe")) + << ExecutableInfo("Nehrim Launcher", findInGameFolder("NehrimLauncher.exe")) + << ExecutableInfo("Oblivion Mod Manager", findInGameFolder("OblivionModManager.exe")) + << ExecutableInfo("BOSS", findInGameFolder("BOSS/BOSS.exe")) + << ExecutableInfo("LOOT", QFileInfo(getLootPath())).withArgument("--game=\"Nehrim\"") + << ExecutableInfo("Construction Set", findInGameFolder("TESConstructionSet.exe")) + ; } QList GameNehrim::executableForcedLoads() const { - //TODO Search game directory for OBSE DLLs - return QList() - << ExecutableForcedLoadSetting("Oblvion.exe", "obse_1_2_416.dll").withForced().withEnabled() - << ExecutableForcedLoadSetting("TESConstructionSet.exe", "obse_editor_1_2.dll").withForced().withEnabled() - ; + //TODO Search game directory for OBSE DLLs + return QList() + << ExecutableForcedLoadSetting("Oblvion.exe", "obse_1_2_416.dll").withForced().withEnabled() + << ExecutableForcedLoadSetting("TESConstructionSet.exe", "obse_editor_1_2.dll").withForced().withEnabled() + ; } QString GameNehrim::name() const { - return "Nehrim Support Plugin"; + return "Nehrim Support Plugin"; } QString GameNehrim::localizedName() const { - return tr("Nehrim Support Plugin"); + return tr("Nehrim Support Plugin"); } QString GameNehrim::author() const { - return "Tannin"; + return "Tannin"; } QString GameNehrim::description() const { - return tr("Adds support for the game Nehrim"); + return tr("Adds support for the game Nehrim"); } MOBase::VersionInfo GameNehrim::version() const { - return VersionInfo(1, 1, 0, VersionInfo::RELEASE_FINAL); + return VersionInfo(1, 1, 0, VersionInfo::RELEASE_FINAL); } QList GameNehrim::settings() const { - return QList(); + return QList(); } -void GameNehrim::initializeProfile(const QDir &path, ProfileSettings settings) const +void GameNehrim::initializeProfile(const QDir& path, ProfileSettings settings) const { - if (settings.testFlag(IPluginGame::MODS)) { - copyToProfile(localAppFolder() + "/Oblvion", path, "plugins.txt"); - } + if (settings.testFlag(IPluginGame::MODS)) { + copyToProfile(localAppFolder() + "/Oblvion", path, "plugins.txt"); + } - if (settings.testFlag(IPluginGame::CONFIGURATION)) { - if (settings.testFlag(IPluginGame::PREFER_DEFAULTS) - || !QFileInfo(myGamesPath() + "/oblivion.ini").exists()) { - copyToProfile(gameDirectory().absolutePath(), path, "oblivion_default.ini", "oblivion.ini"); - } else { - copyToProfile(myGamesPath(), path, "oblivion.ini"); - } + if (settings.testFlag(IPluginGame::CONFIGURATION)) { + if (settings.testFlag(IPluginGame::PREFER_DEFAULTS) + || !QFileInfo(myGamesPath() + "/oblivion.ini").exists()) { + copyToProfile(gameDirectory().absolutePath(), path, "oblivion_default.ini", "oblivion.ini"); + } + else { + copyToProfile(myGamesPath(), path, "oblivion.ini"); + } - copyToProfile(myGamesPath(), path, "oblivionprefs.ini"); - } + copyToProfile(myGamesPath(), path, "oblivionprefs.ini"); + } } QString GameNehrim::savegameExtension() const { - return "ess"; + return "ess"; } QString GameNehrim::savegameSEExtension() const { - return "obse"; + return "obse"; } std::shared_ptr GameNehrim::makeSaveGame(QString filePath) const { - return std::make_shared(filePath, this); + return std::make_shared(filePath, this); } QString GameNehrim::steamAPPId() const { - return "22330"; + return "22330"; } QStringList GameNehrim::primaryPlugins() const { - return { "Nehrim.esm", "Translation.esp" }; + return { "Nehrim.esm", "Translation.esp" }; } QString GameNehrim::gameShortName() const { - return "Nehrim"; + return "Nehrim"; } QString GameNehrim::gameNexusName() const { - return "Nehrim"; + return "Nehrim"; } QStringList GameNehrim::iniFiles() const { - return { "oblivion.ini", "oblivionprefs.ini" }; + return { "oblivion.ini", "oblivionprefs.ini" }; } QStringList GameNehrim::DLCPlugins() const { - return {}; + return {}; } int GameNehrim::nexusModOrganizerID() const { - return -1; + return -1; } int GameNehrim::nexusGameID() const { - return 3312; + return 3312; } QStringList GameNehrim::primarySources() const { - return {"Oblivion"}; + return { "Oblivion" }; } QStringList GameNehrim::validShortNames() const { - return {"Oblivion"}; + return { "Oblivion" }; } QString GameNehrim::identifyGamePath() const { - QString path = "Software\\Bethesda Softworks\\Oblivion"; - return findInRegistry(HKEY_LOCAL_MACHINE, path.toStdWString().c_str(), L"Installed Path"); + QString path = "Software\\Bethesda Softworks\\Oblivion"; + return findInRegistry(HKEY_LOCAL_MACHINE, path.toStdWString().c_str(), L"Installed Path"); } QString GameNehrim::binaryName() const { - return "NehrimLauncher.exe"; + return "NehrimLauncher.exe"; } From 9cccf0214a85682b9394ffcb568e33d3d7d55646 Mon Sep 17 00:00:00 2001 From: Jeremy Rimpo Date: Wed, 20 Sep 2023 21:03:28 -0500 Subject: [PATCH 1341/1544] [game_nehrim] Add formatting and CI --- src/games/nehrim/.clang-format | 41 +++++ src/games/nehrim/.gitattributes | 7 + src/games/nehrim/.github/workflows/build.yml | 17 +++ .../nehrim/.github/workflows/linting.yml | 17 +++ src/games/nehrim/src/gamenehrim.cpp | 144 +++++++++--------- src/games/nehrim/src/gamenehrim.h | 21 ++- .../nehrim/src/nehrimbsainvalidation.cpp | 9 +- src/games/nehrim/src/nehrimbsainvalidation.h | 8 +- src/games/nehrim/src/nehrimdataarchives.cpp | 30 ++-- src/games/nehrim/src/nehrimdataarchives.h | 19 +-- src/games/nehrim/src/nehrimmoddatachecker.cpp | 6 +- src/games/nehrim/src/nehrimmoddatachecker.h | 31 ++-- src/games/nehrim/src/nehrimmoddatacontent.h | 13 +- src/games/nehrim/src/nehrimsavegame.cpp | 47 +++--- src/games/nehrim/src/nehrimsavegame.h | 14 +- src/games/nehrim/src/nehrimscriptextender.cpp | 11 +- src/games/nehrim/src/nehrimscriptextender.h | 5 +- 17 files changed, 256 insertions(+), 184 deletions(-) create mode 100644 src/games/nehrim/.clang-format create mode 100644 src/games/nehrim/.gitattributes create mode 100644 src/games/nehrim/.github/workflows/build.yml create mode 100644 src/games/nehrim/.github/workflows/linting.yml diff --git a/src/games/nehrim/.clang-format b/src/games/nehrim/.clang-format new file mode 100644 index 00000000..6098e1f5 --- /dev/null +++ b/src/games/nehrim/.clang-format @@ -0,0 +1,41 @@ +--- +# We'll use defaults from the LLVM style, but with 4 columns indentation. +BasedOnStyle: LLVM +IndentWidth: 2 +--- +Language: Cpp +DeriveLineEnding: false +UseCRLF: true +DerivePointerAlignment: false +PointerAlignment: Left +AlignConsecutiveAssignments: true +AllowShortFunctionsOnASingleLine: Inline +AllowShortIfStatementsOnASingleLine: Never +AllowShortLambdasOnASingleLine: Empty +AlwaysBreakTemplateDeclarations: Yes +AccessModifierOffset: -2 +AlignTrailingComments: true +SpacesBeforeTrailingComments: 2 +NamespaceIndentation: Inner +MaxEmptyLinesToKeep: 1 +BreakBeforeBraces: Custom +BraceWrapping: + AfterCaseLabel: false + AfterClass: true + AfterControlStatement: false + AfterEnum: true + AfterFunction: true + AfterNamespace: true + AfterStruct: true + AfterUnion: true + AfterExternBlock: true + BeforeCatch: false + BeforeElse: false + BeforeLambdaBody: false + BeforeWhile: false + IndentBraces: false + SplitEmptyFunction: false + SplitEmptyRecord: false + SplitEmptyNamespace: true +ColumnLimit: 88 +ForEachMacros: ['Q_FOREACH', 'foreach'] diff --git a/src/games/nehrim/.gitattributes b/src/games/nehrim/.gitattributes new file mode 100644 index 00000000..f8697127 --- /dev/null +++ b/src/games/nehrim/.gitattributes @@ -0,0 +1,7 @@ +# Set the default behavior, in case people don't have core.autocrlf set. +* text=auto + +# Explicitly declare text files you want to always be normalized and converted +# to native line endings on checkout. +*.cpp text eol=crlf +*.h text eol=crlf diff --git a/src/games/nehrim/.github/workflows/build.yml b/src/games/nehrim/.github/workflows/build.yml new file mode 100644 index 00000000..54468d57 --- /dev/null +++ b/src/games/nehrim/.github/workflows/build.yml @@ -0,0 +1,17 @@ +name: Build Nehrim Plugin + +on: + push: + branches: master + pull_request: + types: [opened, synchronize, reopened] + +jobs: + build: + runs-on: windows-2022 + steps: + - name: Build Nehrim Plugin + uses: ModOrganizer2/build-with-mob-action@master + with: + mo2-third-parties: fmt gtest spdlog boost lz4 + mo2-dependencies: cmake_common uibase game_gamebryo diff --git a/src/games/nehrim/.github/workflows/linting.yml b/src/games/nehrim/.github/workflows/linting.yml new file mode 100644 index 00000000..006464fa --- /dev/null +++ b/src/games/nehrim/.github/workflows/linting.yml @@ -0,0 +1,17 @@ +name: Lint Nehrim Plugin + +on: + push: + pull_request: + types: [opened, synchronize, reopened] + +jobs: + lint: + runs-on: ubuntu-latest + steps: + - uses: actions/checkout@v3 + - name: Run clang-format + uses: jidicula/clang-format-action@v4.11.0 + with: + clang-format-version: "15" + check-path: "." diff --git a/src/games/nehrim/src/gamenehrim.cpp b/src/games/nehrim/src/gamenehrim.cpp index 35548381..084efe9f 100644 --- a/src/games/nehrim/src/gamenehrim.cpp +++ b/src/games/nehrim/src/gamenehrim.cpp @@ -2,17 +2,17 @@ #include "nehrimbsainvalidation.h" #include "nehrimdataarchives.h" -#include "nehrimscriptextender.h" #include "nehrimmoddatachecker.h" #include "nehrimmoddatacontent.h" #include "nehrimsavegame.h" +#include "nehrimscriptextender.h" -#include "pluginsetting.h" #include "executableinfo.h" -#include +#include "pluginsetting.h" #include -#include +#include #include +#include #include #include @@ -22,174 +22,180 @@ using namespace MOBase; -GameNehrim::GameNehrim() -{ -} +GameNehrim::GameNehrim() {} bool GameNehrim::init(IOrganizer* moInfo) { - if (!GameGamebryo::init(moInfo)) { - return false; - } - registerFeature(new NehrimScriptExtender(this)); - registerFeature(new NehrimDataArchives(myGamesPath())); - registerFeature(new NehrimBSAInvalidation(feature(), this)); - registerFeature(new GamebryoSaveGameInfo(this)); - registerFeature(new GamebryoLocalSavegames(myGamesPath(), "oblivion.ini")); - registerFeature(new NehrimModDataChecker(this)); - registerFeature(new NehrimModDataContent(this)); - registerFeature(new GamebryoGamePlugins(moInfo)); - registerFeature(new GamebryoUnmangedMods(this)); - return true; + if (!GameGamebryo::init(moInfo)) { + return false; + } + registerFeature(new NehrimScriptExtender(this)); + registerFeature(new NehrimDataArchives(myGamesPath())); + registerFeature( + new NehrimBSAInvalidation(feature(), this)); + registerFeature(new GamebryoSaveGameInfo(this)); + registerFeature( + new GamebryoLocalSavegames(myGamesPath(), "oblivion.ini")); + registerFeature(new NehrimModDataChecker(this)); + registerFeature(new NehrimModDataContent(this)); + registerFeature(new GamebryoGamePlugins(moInfo)); + registerFeature(new GamebryoUnmangedMods(this)); + return true; } QString GameNehrim::gameName() const { - return "Nehrim"; + return "Nehrim"; } QList GameNehrim::executables() const { - return QList() - << ExecutableInfo("Nehrim", findInGameFolder("Oblivion.exe")) - << ExecutableInfo("Nehrim Launcher", findInGameFolder("NehrimLauncher.exe")) - << ExecutableInfo("Oblivion Mod Manager", findInGameFolder("OblivionModManager.exe")) - << ExecutableInfo("BOSS", findInGameFolder("BOSS/BOSS.exe")) - << ExecutableInfo("LOOT", QFileInfo(getLootPath())).withArgument("--game=\"Nehrim\"") - << ExecutableInfo("Construction Set", findInGameFolder("TESConstructionSet.exe")) - ; + return QList() + << ExecutableInfo("Nehrim", findInGameFolder("Oblivion.exe")) + << ExecutableInfo("Nehrim Launcher", findInGameFolder("NehrimLauncher.exe")) + << ExecutableInfo("Oblivion Mod Manager", + findInGameFolder("OblivionModManager.exe")) + << ExecutableInfo("BOSS", findInGameFolder("BOSS/BOSS.exe")) + << ExecutableInfo("LOOT", QFileInfo(getLootPath())) + .withArgument("--game=\"Nehrim\"") + << ExecutableInfo("Construction Set", + findInGameFolder("TESConstructionSet.exe")); } QList GameNehrim::executableForcedLoads() const { - //TODO Search game directory for OBSE DLLs - return QList() - << ExecutableForcedLoadSetting("Oblvion.exe", "obse_1_2_416.dll").withForced().withEnabled() - << ExecutableForcedLoadSetting("TESConstructionSet.exe", "obse_editor_1_2.dll").withForced().withEnabled() - ; + // TODO Search game directory for OBSE DLLs + return QList() + << ExecutableForcedLoadSetting("Oblvion.exe", "obse_1_2_416.dll") + .withForced() + .withEnabled() + << ExecutableForcedLoadSetting("TESConstructionSet.exe", "obse_editor_1_2.dll") + .withForced() + .withEnabled(); } QString GameNehrim::name() const { - return "Nehrim Support Plugin"; + return "Nehrim Support Plugin"; } QString GameNehrim::localizedName() const { - return tr("Nehrim Support Plugin"); + return tr("Nehrim Support Plugin"); } QString GameNehrim::author() const { - return "Tannin"; + return "Tannin"; } QString GameNehrim::description() const { - return tr("Adds support for the game Nehrim"); + return tr("Adds support for the game Nehrim"); } MOBase::VersionInfo GameNehrim::version() const { - return VersionInfo(1, 1, 0, VersionInfo::RELEASE_FINAL); + return VersionInfo(1, 1, 0, VersionInfo::RELEASE_FINAL); } QList GameNehrim::settings() const { - return QList(); + return QList(); } void GameNehrim::initializeProfile(const QDir& path, ProfileSettings settings) const { - if (settings.testFlag(IPluginGame::MODS)) { - copyToProfile(localAppFolder() + "/Oblvion", path, "plugins.txt"); - } + if (settings.testFlag(IPluginGame::MODS)) { + copyToProfile(localAppFolder() + "/Oblvion", path, "plugins.txt"); + } - if (settings.testFlag(IPluginGame::CONFIGURATION)) { - if (settings.testFlag(IPluginGame::PREFER_DEFAULTS) - || !QFileInfo(myGamesPath() + "/oblivion.ini").exists()) { - copyToProfile(gameDirectory().absolutePath(), path, "oblivion_default.ini", "oblivion.ini"); - } - else { - copyToProfile(myGamesPath(), path, "oblivion.ini"); - } + if (settings.testFlag(IPluginGame::CONFIGURATION)) { + if (settings.testFlag(IPluginGame::PREFER_DEFAULTS) || + !QFileInfo(myGamesPath() + "/oblivion.ini").exists()) { + copyToProfile(gameDirectory().absolutePath(), path, "oblivion_default.ini", + "oblivion.ini"); + } else { + copyToProfile(myGamesPath(), path, "oblivion.ini"); + } - copyToProfile(myGamesPath(), path, "oblivionprefs.ini"); - } + copyToProfile(myGamesPath(), path, "oblivionprefs.ini"); + } } QString GameNehrim::savegameExtension() const { - return "ess"; + return "ess"; } QString GameNehrim::savegameSEExtension() const { - return "obse"; + return "obse"; } std::shared_ptr GameNehrim::makeSaveGame(QString filePath) const { - return std::make_shared(filePath, this); + return std::make_shared(filePath, this); } QString GameNehrim::steamAPPId() const { - return "22330"; + return "22330"; } QStringList GameNehrim::primaryPlugins() const { - return { "Nehrim.esm", "Translation.esp" }; + return {"Nehrim.esm", "Translation.esp"}; } QString GameNehrim::gameShortName() const { - return "Nehrim"; + return "Nehrim"; } QString GameNehrim::gameNexusName() const { - return "Nehrim"; + return "Nehrim"; } QStringList GameNehrim::iniFiles() const { - return { "oblivion.ini", "oblivionprefs.ini" }; + return {"oblivion.ini", "oblivionprefs.ini"}; } QStringList GameNehrim::DLCPlugins() const { - return {}; + return {}; } int GameNehrim::nexusModOrganizerID() const { - return -1; + return -1; } int GameNehrim::nexusGameID() const { - return 3312; + return 3312; } QStringList GameNehrim::primarySources() const { - return { "Oblivion" }; + return {"Oblivion"}; } QStringList GameNehrim::validShortNames() const { - return { "Oblivion" }; + return {"Oblivion"}; } QString GameNehrim::identifyGamePath() const { - QString path = "Software\\Bethesda Softworks\\Oblivion"; - return findInRegistry(HKEY_LOCAL_MACHINE, path.toStdWString().c_str(), L"Installed Path"); + QString path = "Software\\Bethesda Softworks\\Oblivion"; + return findInRegistry(HKEY_LOCAL_MACHINE, path.toStdWString().c_str(), + L"Installed Path"); } QString GameNehrim::binaryName() const { - return "NehrimLauncher.exe"; + return "NehrimLauncher.exe"; } diff --git a/src/games/nehrim/src/gamenehrim.h b/src/games/nehrim/src/gamenehrim.h index f08447bc..a8af24c4 100644 --- a/src/games/nehrim/src/gamenehrim.h +++ b/src/games/nehrim/src/gamenehrim.h @@ -12,17 +12,17 @@ class GameNehrim : public GameGamebryo Q_PLUGIN_METADATA(IID "org.tannin.GameNehrim" FILE "gamenehrim.json") public: - GameNehrim(); - virtual bool init(MOBase::IOrganizer *moInfo) override; - -public: // IPluginGame interface + virtual bool init(MOBase::IOrganizer* moInfo) override; +public: // IPluginGame interface virtual QString gameName() const override; virtual QList executables() const override; - virtual QList executableForcedLoads() const override; - virtual void initializeProfile(const QDir &path, ProfileSettings settings) const override; + virtual QList + executableForcedLoads() const override; + virtual void initializeProfile(const QDir& path, + ProfileSettings settings) const override; virtual QString steamAPPId() const override; virtual QStringList primaryPlugins() const override; virtual QString gameShortName() const override; @@ -34,13 +34,12 @@ public: // IPluginGame interface virtual QStringList primarySources() const override; virtual QStringList validShortNames() const override; - // Weird stuff happens in these functions due to Nehrim + // Weird stuff happens in these functions due to Nehrim // technically being in the Oblivion folder virtual QString identifyGamePath() const override; virtual QString binaryName() const override; -public: // IPlugin interface - +public: // IPlugin interface virtual QString name() const override; virtual QString localizedName() const override; virtual QString author() const override; @@ -49,11 +48,9 @@ public: // IPlugin interface virtual QList settings() const override; protected: - std::shared_ptr makeSaveGame(QString filePath) const override; QString savegameExtension() const override; QString savegameSEExtension() const override; - }; -#endif // GAMENEHRIM_H +#endif // GAMENEHRIM_H diff --git a/src/games/nehrim/src/nehrimbsainvalidation.cpp b/src/games/nehrim/src/nehrimbsainvalidation.cpp index 0af89fc1..7830da09 100644 --- a/src/games/nehrim/src/nehrimbsainvalidation.cpp +++ b/src/games/nehrim/src/nehrimbsainvalidation.cpp @@ -1,10 +1,9 @@ #include "nehrimbsainvalidation.h" - -NehrimBSAInvalidation::NehrimBSAInvalidation(DataArchives *dataArchives, MOBase::IPluginGame const *game) - : GamebryoBSAInvalidation(dataArchives, "oblivion.ini", game) -{ -} +NehrimBSAInvalidation::NehrimBSAInvalidation(DataArchives* dataArchives, + MOBase::IPluginGame const* game) + : GamebryoBSAInvalidation(dataArchives, "oblivion.ini", game) +{} QString NehrimBSAInvalidation::invalidationBSAName() const { diff --git a/src/games/nehrim/src/nehrimbsainvalidation.h b/src/games/nehrim/src/nehrimbsainvalidation.h index 59f471d6..51fcd9ae 100644 --- a/src/games/nehrim/src/nehrimbsainvalidation.h +++ b/src/games/nehrim/src/nehrimbsainvalidation.h @@ -1,7 +1,6 @@ #ifndef NEHRIMBSAINVALIDATION_H #define NEHRIMBSAINVALIDATION_H - #include "gamebryobsainvalidation.h" #include "nehrimdataarchives.h" @@ -10,14 +9,11 @@ class NehrimBSAInvalidation : public GamebryoBSAInvalidation { public: - - NehrimBSAInvalidation(DataArchives *dataArchives, MOBase::IPluginGame const *game); + NehrimBSAInvalidation(DataArchives* dataArchives, MOBase::IPluginGame const* game); private: - virtual QString invalidationBSAName() const override; virtual unsigned long bsaVersion() const override; - }; -#endif // NEHRIMBSAINVALIDATION_H +#endif // NEHRIMBSAINVALIDATION_H diff --git a/src/games/nehrim/src/nehrimdataarchives.cpp b/src/games/nehrim/src/nehrimdataarchives.cpp index 28e09f03..8673bb86 100644 --- a/src/games/nehrim/src/nehrimdataarchives.cpp +++ b/src/games/nehrim/src/nehrimdataarchives.cpp @@ -1,37 +1,35 @@ #include "nehrimdataarchives.h" #include -NehrimDataArchives::NehrimDataArchives(const QDir &myGamesDir) : - GamebryoDataArchives(myGamesDir) -{ -} +NehrimDataArchives::NehrimDataArchives(const QDir& myGamesDir) + : GamebryoDataArchives(myGamesDir) +{} QStringList NehrimDataArchives::vanillaArchives() const { - return { "N - Meshes.bsa" - , "N - Textures1.bsa" - , "N - Textures2.bsa" - , "N - Misc.bsa" - , "N - Sounds.bsa" - , "L - Voices.bsa" - , "L - Misc.bsa" - }; + return {"N - Meshes.bsa", "N - Textures1.bsa", "N - Textures2.bsa", "N - Misc.bsa", + "N - Sounds.bsa", "L - Voices.bsa", "L - Misc.bsa"}; } -QStringList NehrimDataArchives::archives(const MOBase::IProfile *profile) const +QStringList NehrimDataArchives::archives(const MOBase::IProfile* profile) const { QStringList result; - QString iniFile = profile->localSettingsEnabled() ? QDir(profile->absolutePath()).absoluteFilePath("oblivion.ini") : m_LocalGameDir.absoluteFilePath("oblivion.ini"); + QString iniFile = profile->localSettingsEnabled() + ? QDir(profile->absolutePath()).absoluteFilePath("oblivion.ini") + : m_LocalGameDir.absoluteFilePath("oblivion.ini"); result.append(getArchivesFromKey(iniFile, "SArchiveList")); return result; } -void NehrimDataArchives::writeArchiveList(MOBase::IProfile *profile, const QStringList &before) +void NehrimDataArchives::writeArchiveList(MOBase::IProfile* profile, + const QStringList& before) { QString list = before.join(", "); - QString iniFile = profile->localSettingsEnabled() ? QDir(profile->absolutePath()).absoluteFilePath("oblivion.ini") : m_LocalGameDir.absoluteFilePath("oblivion.ini"); + QString iniFile = profile->localSettingsEnabled() + ? QDir(profile->absolutePath()).absoluteFilePath("oblivion.ini") + : m_LocalGameDir.absoluteFilePath("oblivion.ini"); setArchivesToKey(iniFile, "SArchiveList", list); } diff --git a/src/games/nehrim/src/nehrimdataarchives.h b/src/games/nehrim/src/nehrimdataarchives.h index beed56e2..9bfd5908 100644 --- a/src/games/nehrim/src/nehrimdataarchives.h +++ b/src/games/nehrim/src/nehrimdataarchives.h @@ -1,28 +1,25 @@ #ifndef NEHRIMDATAARCHIVES_H #define NEHRIMDATAARCHIVES_H - -#include -#include +#include #include #include -#include +#include +#include class NehrimDataArchives : public GamebryoDataArchives { public: - NehrimDataArchives(const QDir &myGamesDir); + NehrimDataArchives(const QDir& myGamesDir); public: - virtual QStringList vanillaArchives() const override; - virtual QStringList archives(const MOBase::IProfile *profile) const override; + virtual QStringList archives(const MOBase::IProfile* profile) const override; private: - - virtual void writeArchiveList(MOBase::IProfile *profile, const QStringList &before) override; - + virtual void writeArchiveList(MOBase::IProfile* profile, + const QStringList& before) override; }; -#endif // NEHRIMDATAARCHIVES_H +#endif // NEHRIMDATAARCHIVES_H diff --git a/src/games/nehrim/src/nehrimmoddatachecker.cpp b/src/games/nehrim/src/nehrimmoddatachecker.cpp index 45077822..6ca61214 100644 --- a/src/games/nehrim/src/nehrimmoddatachecker.cpp +++ b/src/games/nehrim/src/nehrimmoddatachecker.cpp @@ -1,7 +1,7 @@ #include "nehrimmoddatachecker.h" ModDataChecker::CheckReturn NehrimModDataChecker::dataLooksValid( - std::shared_ptr fileTree) const + std::shared_ptr fileTree) const { // Check with Gamebryo stuff: auto check = GamebryoModDataChecker::dataLooksValid(fileTree); @@ -19,8 +19,8 @@ ModDataChecker::CheckReturn NehrimModDataChecker::dataLooksValid( return CheckReturn::FIXABLE; } -std::shared_ptr NehrimModDataChecker::fix( - std::shared_ptr fileTree) const +std::shared_ptr +NehrimModDataChecker::fix(std::shared_ptr fileTree) const { // If we arrive here, it means all files starts with OBSE. auto data = fileTree->createOrphanTree(); diff --git a/src/games/nehrim/src/nehrimmoddatachecker.h b/src/games/nehrim/src/nehrimmoddatachecker.h index ddf6a550..c8717dd9 100644 --- a/src/games/nehrim/src/nehrimmoddatachecker.h +++ b/src/games/nehrim/src/nehrimmoddatachecker.h @@ -8,25 +8,28 @@ class NehrimModDataChecker : public GamebryoModDataChecker public: using GamebryoModDataChecker::GamebryoModDataChecker; - CheckReturn dataLooksValid(std::shared_ptr fileTree) const override; - std::shared_ptr fix(std::shared_ptr fileTree) const override; + CheckReturn + dataLooksValid(std::shared_ptr fileTree) const override; + std::shared_ptr + fix(std::shared_ptr fileTree) const override; protected: - virtual const FileNameSet& possibleFolderNames() const override { - static FileNameSet result{ - "fonts", "interface", "menus", "meshes", "music", "scripts", "shaders", - "sound", "strings", "textures", "trees", "video", "facegen", - "obse", "distantlod", "asi", "distantland", "mits", "dllplugins", "CalienteTools", - "NetScriptFramework" - }; + virtual const FileNameSet& possibleFolderNames() const override + { + static FileNameSet result{"fonts", "interface", "menus", + "meshes", "music", "scripts", + "shaders", "sound", "strings", + "textures", "trees", "video", + "facegen", "obse", "distantlod", + "asi", "distantland", "mits", + "dllplugins", "CalienteTools", "NetScriptFramework"}; return result; } - virtual const FileNameSet& possibleFileExtensions() const override { - static FileNameSet result{ - "esp", "esm", "bsa", "modgroups", "ini" - }; + virtual const FileNameSet& possibleFileExtensions() const override + { + static FileNameSet result{"esp", "esm", "bsa", "modgroups", "ini"}; return result; } }; -#endif // NEHRIM_MODATACHECKER_H +#endif // NEHRIM_MODATACHECKER_H diff --git a/src/games/nehrim/src/nehrimmoddatacontent.h b/src/games/nehrim/src/nehrimmoddatacontent.h index b6768d1a..02391dfe 100644 --- a/src/games/nehrim/src/nehrimmoddatacontent.h +++ b/src/games/nehrim/src/nehrimmoddatacontent.h @@ -4,18 +4,19 @@ #include #include -class NehrimModDataContent : public GamebryoModDataContent { +class NehrimModDataContent : public GamebryoModDataContent +{ public: - /** * */ - NehrimModDataContent(GameGamebryo const* gamePlugin) : GamebryoModDataContent(gamePlugin) { + NehrimModDataContent(GameGamebryo const* gamePlugin) + : GamebryoModDataContent(gamePlugin) + { // Just need to disable some contents: - m_Enabled[CONTENT_MCM] = false; + m_Enabled[CONTENT_MCM] = false; m_Enabled[CONTENT_SKYPROC] = false; } - }; -#endif // NEHRIM_MODDATACONTENT_H +#endif // NEHRIM_MODDATACONTENT_H diff --git a/src/games/nehrim/src/nehrimsavegame.cpp b/src/games/nehrim/src/nehrimsavegame.cpp index 1cb574da..88356326 100644 --- a/src/games/nehrim/src/nehrimsavegame.cpp +++ b/src/games/nehrim/src/nehrimsavegame.cpp @@ -2,31 +2,32 @@ #include -NehrimSaveGame::NehrimSaveGame(QString const &fileName, GameNehrim const *game) : - GamebryoSaveGame(fileName, game) +NehrimSaveGame::NehrimSaveGame(QString const& fileName, GameNehrim const* game) + : GamebryoSaveGame(fileName, game) { FileWrapper file(getFilepath(), "TES4SAVEGAME"); file.setPluginString(GamebryoSaveGame::StringType::TYPE_BSTRING); SYSTEMTIME creationTime; - fetchInformationFields(file, m_SaveNumber, m_PCName, m_PCLevel, m_PCLocation, creationTime); + fetchInformationFields(file, m_SaveNumber, m_PCName, m_PCLevel, m_PCLocation, + creationTime); setCreationTime(creationTime); } void NehrimSaveGame::fetchInformationFields(FileWrapper& file, - unsigned long& saveNumber, - QString& playerName, - unsigned short& playerLevel, - QString& playerLocation, - SYSTEMTIME& creationTime) const + unsigned long& saveNumber, + QString& playerName, + unsigned short& playerLevel, + QString& playerLocation, + SYSTEMTIME& creationTime) const { - file.skip(); //Major version - file.skip(); //Minor version + file.skip(); // Major version + file.skip(); // Minor version file.skip(); // exe last modified (!) - file.skip(); //Header version - file.skip(); //Header size + file.skip(); // Header version + file.skip(); // Header size file.read(saveNumber); @@ -34,13 +35,13 @@ void NehrimSaveGame::fetchInformationFields(FileWrapper& file, file.read(playerLevel); file.read(playerLocation); - file.skip(); //game days - file.skip(); //game ticks + file.skip(); // game days + file.skip(); // game ticks - //there is a save time stored here. So use it rather than the file time, which - //could have been copied. - //Note: This says it uses getlocaltime api to obtain it which is u/s - if so - //we should ignore this. + // there is a save time stored here. So use it rather than the file time, which + // could have been copied. + // Note: This says it uses getlocaltime api to obtain it which is u/s - if so + // we should ignore this. file.read(creationTime); } @@ -57,13 +58,13 @@ std::unique_ptr NehrimSaveGame::fetchDataFields() unsigned long dummySaveNumber; SYSTEMTIME dummyTime; - fetchInformationFields(file, dummySaveNumber, dummyName, dummyLevel, - dummyLocation, dummyTime); + fetchInformationFields(file, dummySaveNumber, dummyName, dummyLevel, dummyLocation, + dummyTime); } - //Note that screenshot size, width, height and data are apparently the same - //structure - file.skip(); //Screenshot size. + // Note that screenshot size, width, height and data are apparently the same + // structure + file.skip(); // Screenshot size. fields->Screenshot = file.readImage(); diff --git a/src/games/nehrim/src/nehrimsavegame.h b/src/games/nehrim/src/nehrimsavegame.h index ef8c1afd..be3d2a95 100644 --- a/src/games/nehrim/src/nehrimsavegame.h +++ b/src/games/nehrim/src/nehrimsavegame.h @@ -7,19 +7,15 @@ class NehrimSaveGame : public GamebryoSaveGame { public: - NehrimSaveGame(QString const &fileName, GameNehrim const *game); + NehrimSaveGame(QString const& fileName, GameNehrim const* game); protected: - // Fetch easy-to-access information. - void fetchInformationFields(FileWrapper& wrapper, - unsigned long& saveNumber, - QString& playerName, - unsigned short& playerLevel, - QString& playerLocation, - SYSTEMTIME& creationTime) const; + void fetchInformationFields(FileWrapper& wrapper, unsigned long& saveNumber, + QString& playerName, unsigned short& playerLevel, + QString& playerLocation, SYSTEMTIME& creationTime) const; std::unique_ptr fetchDataFields() const override; }; -#endif // NEHRIMSAVEGAME_H +#endif // NEHRIMSAVEGAME_H diff --git a/src/games/nehrim/src/nehrimscriptextender.cpp b/src/games/nehrim/src/nehrimscriptextender.cpp index e1b7e7d0..c50c59ef 100644 --- a/src/games/nehrim/src/nehrimscriptextender.cpp +++ b/src/games/nehrim/src/nehrimscriptextender.cpp @@ -3,14 +3,11 @@ #include #include -NehrimScriptExtender::NehrimScriptExtender(GameGamebryo const *game) : - GamebryoScriptExtender(game) -{ -} +NehrimScriptExtender::NehrimScriptExtender(GameGamebryo const* game) + : GamebryoScriptExtender(game) +{} -NehrimScriptExtender::~NehrimScriptExtender() -{ -} +NehrimScriptExtender::~NehrimScriptExtender() {} QString NehrimScriptExtender::BinaryName() const { diff --git a/src/games/nehrim/src/nehrimscriptextender.h b/src/games/nehrim/src/nehrimscriptextender.h index 95977ee4..3bdac2a4 100644 --- a/src/games/nehrim/src/nehrimscriptextender.h +++ b/src/games/nehrim/src/nehrimscriptextender.h @@ -8,12 +8,11 @@ class GameGamebryo; class NehrimScriptExtender : public GamebryoScriptExtender { public: - NehrimScriptExtender(const GameGamebryo *game); + NehrimScriptExtender(const GameGamebryo* game); ~NehrimScriptExtender(); virtual QString BinaryName() const override; virtual QString PluginPath() const override; - }; -#endif // NEHRIMSCRIPTEXTENDER_H +#endif // NEHRIMSCRIPTEXTENDER_H From 93e843092ec6afb5368a30b5bb2d117c626b874e Mon Sep 17 00:00:00 2001 From: Jeremy Rimpo Date: Wed, 20 Sep 2023 21:04:11 -0500 Subject: [PATCH 1342/1544] [game_nehrim] Ignore revs --- src/games/nehrim/.git-blame-ignore-revs | 1 + 1 file changed, 1 insertion(+) create mode 100644 src/games/nehrim/.git-blame-ignore-revs diff --git a/src/games/nehrim/.git-blame-ignore-revs b/src/games/nehrim/.git-blame-ignore-revs new file mode 100644 index 00000000..6a4df124 --- /dev/null +++ b/src/games/nehrim/.git-blame-ignore-revs @@ -0,0 +1 @@ +7023386ee0712cf45aec2253735737b4bca7f8a4 \ No newline at end of file From 6f96a6cd165352addb96a4c8f4ffb2efcacbea34 Mon Sep 17 00:00:00 2001 From: Jeremy Rimpo Date: Wed, 20 Sep 2023 21:05:53 -0500 Subject: [PATCH 1343/1544] [game_nehrim] Remove outdated files --- src/games/nehrim/appveyor.yml | 40 ----------------------- src/games/nehrim/src/SConscript | 13 -------- src/games/nehrim/src/gameNehrim.pro | 49 ----------------------------- 3 files changed, 102 deletions(-) delete mode 100644 src/games/nehrim/appveyor.yml delete mode 100644 src/games/nehrim/src/SConscript delete mode 100644 src/games/nehrim/src/gameNehrim.pro diff --git a/src/games/nehrim/appveyor.yml b/src/games/nehrim/appveyor.yml deleted file mode 100644 index f9e8186a..00000000 --- a/src/games/nehrim/appveyor.yml +++ /dev/null @@ -1,40 +0,0 @@ -version: 1.0.{build} -skip_branch_with_pr: true -image: Visual Studio 2019 -environment: - WEBHOOK_URL: - secure: gOKbXaZM9ImtMD5XrYITvdyZUW/az082G9OIN1EC1Vbg57wBaeLhi49uGjxPw5GVujHku6kxN6ab89zhbS5GVeluR76GM83IbKV4Sh7udXzoYZZdg6YudtYHzdhCgUeiedpswbuczTq9ceIkkfSEWZuh/lMAAVVwvcGsJAnoPFw= -build_script: -- pwsh: >- - $ErrorActionPreference = 'Stop' - - git clone --depth=1 --no-single-branch https://github.com/ModOrganizer2/modorganizer-umbrella.git c:\projects\modorganizer-umbrella - - New-Item -ItemType Directory -Path c:\projects\modorganizer-build - - cd c:\projects\modorganizer-umbrella - - ($env:APPVEYOR_PULL_REQUEST_HEAD_REPO_BRANCH -eq $null) ? ($branch = $env:APPVEYOR_REPO_BRANCH) : ($branch = $env:APPVEYOR_PULL_REQUEST_HEAD_REPO_BRANCH) - - git checkout $(git show-ref --verify --quiet refs/remotes/origin/${branch} || echo '-b') ${branch} - - C:\Python37-x64\python.exe unimake.py -d c:\projects\modorganizer-build -s Appveyor_Build=True ${env:APPVEYOR_PROJECT_NAME} - - if($LastExitCode -ne 0) { $host.SetShouldExit($LastExitCode ) } -artifacts: -- path: vsbuild\src\RelWithDebInfo\game_nehrim.dll - name: game_nehrim_dll -- path: vsbuild\src\RelWithDebInfo\game_nehrim.pdb - name: game_nehrim_pdb -- path: vsbuild\src\RelWithDebInfo\game_nehrim.lib - name: game_nehrim_lib -on_success: - - ps: Set-Location -Path $env:APPVEYOR_BUILD_FOLDER - - ps: Invoke-RestMethod https://raw.githubusercontent.com/DiscordHooks/appveyor-discord-webhook/master/send.ps1 -o send.ps1 - - ps: ./send.ps1 success $env:WEBHOOK_URL -on_failure: - - ps: Set-Location -Path $env:APPVEYOR_BUILD_FOLDER - - ps: Push-AppveyorArtifact ${env:APPVEYOR_BUILD_FOLDER}\stdout.log - - ps: Push-AppveyorArtifact ${env:APPVEYOR_BUILD_FOLDER}\stderr.log - - ps: Invoke-RestMethod https://raw.githubusercontent.com/DiscordHooks/appveyor-discord-webhook/master/send.ps1 -o send.ps1 - - ps: ./send.ps1 failure $env:WEBHOOK_URL diff --git a/src/games/nehrim/src/SConscript b/src/games/nehrim/src/SConscript deleted file mode 100644 index 7abd3a4f..00000000 --- a/src/games/nehrim/src/SConscript +++ /dev/null @@ -1,13 +0,0 @@ -Import('qt_env') - -env = qt_env.Clone() - -env.AppendUnique(CPPDEFINES = [ 'GAMENEHRIM_LIBRARY' ]) - -env.RequiresGamebryo() - -lib = env.SharedLibrary('gameNehrim', env.Glob('*.cpp')) -env.InstallModule(lib) - -res = env['QT_USED_MODULES'] -Return('res') diff --git a/src/games/nehrim/src/gameNehrim.pro b/src/games/nehrim/src/gameNehrim.pro deleted file mode 100644 index e3fa2468..00000000 --- a/src/games/nehrim/src/gameNehrim.pro +++ /dev/null @@ -1,49 +0,0 @@ -#------------------------------------------------- -# -# Project created by QtCreator 2014-11-15T15:36:33 -# -#------------------------------------------------- - - -TARGET = gameNehrim -TEMPLATE = lib - -CONFIG += plugins -CONFIG += dll - -DEFINES += GAMENEHRIM_LIBRARY - -SOURCES += gamenehrim.cpp \ - nehrimbsainvalidation.cpp \ - nehrimscriptextender.cpp \ - nehrimdataarchives.cpp \ - nehrimsavegame.cpp \ - nehrimsavegameinfo.cpp - -HEADERS += gamenehrim.h \ - nehrimbsainvalidation.h \ - nehrimscriptextender.h \ - nehrimdataarchives.h \ - nehrimsavegame.h \ - nehrimsavegameinfo.h - -CONFIG(debug, debug|release) { - LIBS += -L"$${OUT_PWD}/../gameGamebryo/debug" - PRE_TARGETDEPS += \ - $$OUT_PWD/../gameGamebryo/debug/gameGamebryo.lib -} else { - LIBS += -L"$${OUT_PWD}/../gameGamebryo/release" - PRE_TARGETDEPS += \ - $$OUT_PWD/../gameGamebryo/release/gameGamebryo.lib -} - -include(../plugin_template.pri) - -INCLUDEPATH += "$${BOOSTPATH}" "$${PWD}/../gamefeatures" "$${PWD}/../gamegamebryo" - -LIBS += -ladvapi32 -lole32 -lgameGamebryo - -OTHER_FILES += \ - gamenehrim.json\ - SConscript \ - CMakeLists.txt From fb53b3fb604f0d2b3ab0b85f0e8f783fab512779 Mon Sep 17 00:00:00 2001 From: Jeremy Rimpo Date: Wed, 20 Sep 2023 22:20:05 -0500 Subject: [PATCH 1344/1544] Check both 32- and 64-bit registry keys --- src/gamebryo/gamegamebryo.cpp | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/src/gamebryo/gamegamebryo.cpp b/src/gamebryo/gamegamebryo.cpp index af77e942..7467fbd4 100644 --- a/src/gamebryo/gamegamebryo.cpp +++ b/src/gamebryo/gamegamebryo.cpp @@ -328,7 +328,9 @@ std::unique_ptr GameGamebryo::getRegValue(HKEY key, LPCWSTR path, LPCWST HKEY subKey; LONG res = ::RegOpenKeyExW(key, path, 0, KEY_QUERY_VALUE | KEY_WOW64_32KEY, &subKey); if (res != ERROR_SUCCESS) { - return std::unique_ptr(); + res = ::RegOpenKeyExW(key, path, 0, KEY_QUERY_VALUE | KEY_WOW64_64KEY, &subKey); + if (res != ERROR_SUCCESS) + return std::unique_ptr(); } res = ::RegGetValueW(subKey, L"", value, flags, type, nullptr, &size); if (res == ERROR_FILE_NOT_FOUND || res == ERROR_UNSUPPORTED_TYPE) { From 9f9db4b7d22f271530fe845d995b81118ff5f707 Mon Sep 17 00:00:00 2001 From: Jeremy Rimpo Date: Fri, 22 Sep 2023 21:22:58 -0500 Subject: [PATCH 1345/1544] [game_enderalse] Remove third party deps --- src/games/enderalse/.github/workflows/build.yml | 1 - 1 file changed, 1 deletion(-) diff --git a/src/games/enderalse/.github/workflows/build.yml b/src/games/enderalse/.github/workflows/build.yml index 5d309623..d31a4458 100644 --- a/src/games/enderalse/.github/workflows/build.yml +++ b/src/games/enderalse/.github/workflows/build.yml @@ -13,5 +13,4 @@ jobs: - name: Build Enderal SE Plugin uses: ModOrganizer2/build-with-mob-action@master with: - mo2-third-parties: fmt gtest spdlog boost lz4 mo2-dependencies: cmake_common uibase game_gamebryo From b1c2b36cc857163269d95662b14106125fb46e81 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Mika=C3=ABl=20Capelle?= Date: Sat, 23 Sep 2023 11:43:49 +0200 Subject: [PATCH 1346/1544] [game_nehrim] Remove 3rd party dependencies from CI. --- src/games/nehrim/.github/workflows/build.yml | 1 - 1 file changed, 1 deletion(-) diff --git a/src/games/nehrim/.github/workflows/build.yml b/src/games/nehrim/.github/workflows/build.yml index 54468d57..36fc8933 100644 --- a/src/games/nehrim/.github/workflows/build.yml +++ b/src/games/nehrim/.github/workflows/build.yml @@ -13,5 +13,4 @@ jobs: - name: Build Nehrim Plugin uses: ModOrganizer2/build-with-mob-action@master with: - mo2-third-parties: fmt gtest spdlog boost lz4 mo2-dependencies: cmake_common uibase game_gamebryo From 04fb36292a4cee0369193971f3c895fe33bebbc4 Mon Sep 17 00:00:00 2001 From: Jeremy Rimpo Date: Sun, 24 Sep 2023 21:21:21 -0500 Subject: [PATCH 1347/1544] Improve Starfield save performance - Decompress data one chunk at a time - Track next chunk location and total size - If end of stream reached during read, attempt to decompress another chunk and append missing bytes --- src/gamebryo/gamebryosavegame.cpp | 154 +++++++++++++++++------------- src/gamebryo/gamebryosavegame.h | 9 ++ 2 files changed, 95 insertions(+), 68 deletions(-) diff --git a/src/gamebryo/gamebryosavegame.cpp b/src/gamebryo/gamebryosavegame.cpp index 66029b6f..dc599cf6 100644 --- a/src/gamebryo/gamebryosavegame.cpp +++ b/src/gamebryo/gamebryosavegame.cpp @@ -92,7 +92,7 @@ void GamebryoSaveGame::setCreationTime(_SYSTEMTIME const& ctime) GamebryoSaveGame::FileWrapper::FileWrapper(QString const& filepath, QString const& expected) : m_File(filepath), m_HasFieldMarkers(false), - m_PluginString(StringType::TYPE_WSTRING) + m_PluginString(StringType::TYPE_WSTRING), m_NextChunk(0) { if (!m_File.open(QIODevice::ReadOnly)) { throw std::runtime_error( @@ -123,20 +123,32 @@ void GamebryoSaveGame::FileWrapper::setPluginString(StringType type) m_PluginString = type; } -void readQDataStream(QDataStream& data, void* buff, std::size_t length) +void GamebryoSaveGame::FileWrapper::readQDataStream(QDataStream& data, void* buff, + std::size_t length) { int read = data.readRawData(static_cast(buff), static_cast(length)); if (read != length) { - throw std::runtime_error("unexpected end of file"); + bool result = readNextChunk(); + if (result) { + read = data.readRawData(static_cast(buff) + read, + static_cast(length - read)); + } else { + throw std::runtime_error("unexpected end of file"); + } } } template -void readQDataStream(QDataStream& data, T& value) +void GamebryoSaveGame::FileWrapper::readQDataStream(QDataStream& data, T& value) { int read = data.readRawData(reinterpret_cast(&value), sizeof(T)); if (read != sizeof(T)) { - throw std::runtime_error("unexpected end of file"); + bool result = readNextChunk(); + if (result) { + read = data.readRawData(reinterpret_cast(&value) + read, sizeof(T) - read); + } else { + throw std::runtime_error("unexpected end of file"); + } } } @@ -252,6 +264,8 @@ void GamebryoSaveGame::FileWrapper::closeCompressedData() { if (m_CompressionType == 0) { } else if (m_CompressionType == 1 || m_CompressionType == 2) { + m_NextChunk = 0; + m_UncompressedSize = 0; m_Data->device()->close(); delete m_Data; } else @@ -266,69 +280,14 @@ bool GamebryoSaveGame::FileWrapper::openCompressedData(int bytesToIgnore) skip(bytesToIgnore); return false; } else if (m_CompressionType == 1) { - uint64_t location; - read(location); - uint64_t totalSize; - read(totalSize); - uint32_t have; - uint64_t read = 0; - std::unique_ptr inBuffer(new unsigned char[CHUNK]); - std::unique_ptr outBuffer(new unsigned char[CHUNK]); - QByteArray finalData; - z_stream stream; - try { - stream.zalloc = Z_NULL; - stream.zfree = Z_NULL; - stream.opaque = Z_NULL; - stream.avail_in = 0; - stream.next_in = Z_NULL; - do { - uint64_t remainder = (location + read) % 16; - uint64_t next = location + read + 16 - (remainder == 0 ? 16 : remainder); - location = next; - read = 0; - if (next >= m_File.size()) - break; - m_File.seek(next); - int zlibRet = inflateInit2(&stream, 15 + 32); - if (zlibRet != Z_OK) { - return false; - } - do { - stream.avail_in = m_File.read(reinterpret_cast(inBuffer.get()), CHUNK); - read += stream.avail_in; - if (!m_File.isReadable()) { - (void)inflateEnd(&stream); - return false; - } - if (stream.avail_in == 0) - break; - stream.next_in = static_cast(inBuffer.get()); - do { - stream.avail_out = CHUNK; - stream.next_out = reinterpret_cast(outBuffer.get()); - zlibRet = inflate(&stream, Z_NO_FLUSH); - if ((zlibRet != Z_OK) && (zlibRet != Z_STREAM_END) && - (zlibRet != Z_BUF_ERROR)) { - return false; - } - have = CHUNK - stream.avail_out; - finalData += QByteArray::fromRawData( - reinterpret_cast(outBuffer.get()), have); - } while (stream.avail_out == 0); - read -= stream.avail_in; - } while (zlibRet != Z_STREAM_END); - inflateEnd(&stream); - if (finalData.size() == totalSize) - break; - } while (m_File.size() > location + read); - } catch (const std::exception&) { - inflateEnd(&stream); - return false; - } - m_Data = new QDataStream(finalData); - m_Data->skipRawData(bytesToIgnore); - return true; + read(m_NextChunk); + read(m_UncompressedSize); + QByteArray placeholder; + m_Data = new QDataStream(placeholder); + bool result = readNextChunk(); + if (result) + m_Data->skipRawData(bytesToIgnore); + return result; } else if (m_CompressionType == 2) { uint32_t uncompressedSize; read(uncompressedSize); @@ -354,6 +313,65 @@ bool GamebryoSaveGame::FileWrapper::openCompressedData(int bytesToIgnore) } } +bool GamebryoSaveGame::FileWrapper::readNextChunk() +{ + uint32_t have; + uint64_t read = 0; + std::unique_ptr inBuffer(new unsigned char[CHUNK]); + std::unique_ptr outBuffer(new unsigned char[CHUNK]); + QByteArray finalData; + m_Data->device()->close(); + delete m_Data; + z_stream stream{}; + try { + stream.zalloc = Z_NULL; + stream.zfree = Z_NULL; + stream.opaque = Z_NULL; + stream.avail_in = 0; + stream.next_in = Z_NULL; + if (m_NextChunk >= m_File.size() || finalData.size() == m_UncompressedSize) + return false; + m_File.seek(m_NextChunk); + int zlibRet = inflateInit2(&stream, 15 + 32); + if (zlibRet != Z_OK) { + return false; + } + do { + stream.avail_in = m_File.read(reinterpret_cast(inBuffer.get()), CHUNK); + read += stream.avail_in; + if (!m_File.isReadable()) { + (void)inflateEnd(&stream); + return false; + } + if (stream.avail_in == 0) + break; + stream.next_in = static_cast(inBuffer.get()); + do { + stream.avail_out = CHUNK; + stream.next_out = reinterpret_cast(outBuffer.get()); + zlibRet = inflate(&stream, Z_NO_FLUSH); + if ((zlibRet != Z_OK) && (zlibRet != Z_STREAM_END) && + (zlibRet != Z_BUF_ERROR)) { + return false; + } + have = CHUNK - stream.avail_out; + finalData += QByteArray::fromRawData( + reinterpret_cast(outBuffer.get()), have); + } while (stream.avail_out == 0); + read -= stream.avail_in; + } while (zlibRet != Z_STREAM_END); + inflateEnd(&stream); + uint64_t remainder = (m_NextChunk + read) % 16; + uint64_t next = m_NextChunk + read + 16 - (remainder == 0 ? 16 : remainder); + m_NextChunk = next; + } catch (const std::exception&) { + inflateEnd(&stream); + return false; + } + m_Data = new QDataStream(finalData); + return true; +} + uint8_t GamebryoSaveGame::FileWrapper::readChar(int bytesToIgnore) { if (m_CompressionType == 0) { diff --git a/src/gamebryo/gamebryosavegame.h b/src/gamebryo/gamebryosavegame.h index b719ec73..7ab95150 100644 --- a/src/gamebryo/gamebryosavegame.h +++ b/src/gamebryo/gamebryosavegame.h @@ -115,6 +115,10 @@ protected: void read(void* buff, std::size_t length); + template + void readQDataStream(QDataStream& data, T& value); + void readQDataStream(QDataStream& data, void* buff, std::size_t length); + /* Reads RGB image from save * Assumes picture dimentions come immediately before the save */ @@ -130,6 +134,9 @@ protected: /* uncompress the begining of the compressed block */ bool openCompressedData(int bytesToIgnore = 0); + /* read the next compressed block */ + bool readNextChunk(); + /* frees the uncompressed block */ void closeCompressedData(); @@ -154,6 +161,8 @@ protected: private: QFile m_File; + uint64_t m_NextChunk; + uint64_t m_UncompressedSize; bool m_HasFieldMarkers; StringType m_PluginString; QDataStream* m_Data; From 4b208407c2f8504e5d9c97b1dc9add616deaceec Mon Sep 17 00:00:00 2001 From: Jeremy Rimpo Date: Sun, 24 Sep 2023 23:14:38 -0500 Subject: [PATCH 1348/1544] Make the code a little more robust - Apply readNextChunk to skips as well - Better checking for compression type --- src/gamebryo/gamebryosavegame.cpp | 63 ++++++++++++++++++++----------- src/gamebryo/gamebryosavegame.h | 1 + 2 files changed, 43 insertions(+), 21 deletions(-) diff --git a/src/gamebryo/gamebryosavegame.cpp b/src/gamebryo/gamebryosavegame.cpp index dc599cf6..186c64c7 100644 --- a/src/gamebryo/gamebryosavegame.cpp +++ b/src/gamebryo/gamebryosavegame.cpp @@ -126,30 +126,51 @@ void GamebryoSaveGame::FileWrapper::setPluginString(StringType type) void GamebryoSaveGame::FileWrapper::readQDataStream(QDataStream& data, void* buff, std::size_t length) { - int read = data.readRawData(static_cast(buff), static_cast(length)); - if (read != length) { + int read = data.readRawData(static_cast(buff), static_cast(length)); + bool result = true; + if (read != length && m_CompressionType == 1) { bool result = readNextChunk(); if (result) { - read = data.readRawData(static_cast(buff) + read, - static_cast(length - read)); - } else { - throw std::runtime_error("unexpected end of file"); + read += data.readRawData(static_cast(buff) + read, + static_cast(length - read)); } } + if (read != length || !result) { + throw std::runtime_error("unexpected end of file"); + } } template void GamebryoSaveGame::FileWrapper::readQDataStream(QDataStream& data, T& value) { - int read = data.readRawData(reinterpret_cast(&value), sizeof(T)); - if (read != sizeof(T)) { - bool result = readNextChunk(); + int read = data.readRawData(reinterpret_cast(&value), sizeof(T)); + bool result = true; + if (read != sizeof(T) && m_CompressionType == 1) { + result = readNextChunk(); if (result) { - read = data.readRawData(reinterpret_cast(&value) + read, sizeof(T) - read); - } else { - throw std::runtime_error("unexpected end of file"); + read += + data.readRawData(reinterpret_cast(&value) + read, sizeof(T) - read); } } + if (read != sizeof(T) || !result) { + throw std::runtime_error("unexpected end of file"); + } +} + +void GamebryoSaveGame::FileWrapper::qDataStreamSkip(QDataStream& data, + std::size_t length) +{ + int skip = data.skipRawData(static_cast(length)); + bool result = true; + if (skip != length && m_CompressionType == 1) { + result = readNextChunk(); + if (result) { + skip += data.skipRawData(static_cast(length - skip)); + } + } + if (skip != length || !result) { + throw std::runtime_error("unexpected end of file"); + } } template <> @@ -286,7 +307,7 @@ bool GamebryoSaveGame::FileWrapper::openCompressedData(int bytesToIgnore) m_Data = new QDataStream(placeholder); bool result = readNextChunk(); if (result) - m_Data->skipRawData(bytesToIgnore); + qDataStreamSkip(*m_Data, bytesToIgnore); return result; } else if (m_CompressionType == 2) { uint32_t uncompressedSize; @@ -303,7 +324,7 @@ bool GamebryoSaveGame::FileWrapper::openCompressedData(int bytesToIgnore) compressed.clear(); m_Data = new QDataStream(decompressed); - m_Data->skipRawData(bytesToIgnore); + qDataStreamSkip(*m_Data, bytesToIgnore); return true; } else { @@ -382,7 +403,7 @@ uint8_t GamebryoSaveGame::FileWrapper::readChar(int bytesToIgnore) return version; } else if (m_CompressionType == 1 || m_CompressionType == 2) { // decompression already done by readSaveGameVersion - m_Data->skipRawData(bytesToIgnore); + qDataStreamSkip(*m_Data, bytesToIgnore); uint8_t version; readQDataStream(*m_Data, version); @@ -405,7 +426,7 @@ uint16_t GamebryoSaveGame::FileWrapper::readShort(int bytesToIgnore) return size; } else if (m_CompressionType == 1 || m_CompressionType == 2) { // decompression already done by readSaveGameVersion - m_Data->skipRawData(bytesToIgnore); + qDataStreamSkip(*m_Data, bytesToIgnore); uint16_t size; readQDataStream(*m_Data, size); @@ -427,7 +448,7 @@ uint32_t GamebryoSaveGame::FileWrapper::readInt(int bytesToIgnore) return size; } else if (m_CompressionType == 1 || m_CompressionType == 2) { // decompression already done by readSaveGameVersion - m_Data->skipRawData(bytesToIgnore); + qDataStreamSkip(*m_Data, bytesToIgnore); uint32_t size; readQDataStream(*m_Data, size); @@ -449,7 +470,7 @@ uint64_t GamebryoSaveGame::FileWrapper::readLong(int bytesToIgnore) return size; } else if (m_CompressionType == 1 || m_CompressionType == 2) { // decompression already done by readSaveGameVersion - m_Data->skipRawData(bytesToIgnore); + qDataStreamSkip(*m_Data, bytesToIgnore); uint64_t size; readQDataStream(*m_Data, size); @@ -471,7 +492,7 @@ float_t GamebryoSaveGame::FileWrapper::readFloat(int bytesToIgnore) return value; } else if (m_CompressionType == 1 || m_CompressionType == 2) { // decompression already done by readSaveGameVersion - m_Data->skipRawData(bytesToIgnore); + qDataStreamSkip(*m_Data, bytesToIgnore); float_t value; readQDataStream(*m_Data, value); @@ -499,7 +520,7 @@ QStringList GamebryoSaveGame::FileWrapper::readPlugins(int bytesToIgnore) plugins.push_back(name); } } else if (m_CompressionType == 1 || m_CompressionType == 2) { - m_Data->skipRawData(bytesToIgnore); + qDataStreamSkip(*m_Data, bytesToIgnore); uint8_t count; readQDataStream(*m_Data, count); uint16_t finalCount = count; @@ -528,7 +549,7 @@ QStringList GamebryoSaveGame::FileWrapper::readLightPlugins(int bytesToIgnore) plugins.push_back(name); } } else if (m_CompressionType == 1 || m_CompressionType == 2) { - m_Data->skipRawData(bytesToIgnore); + qDataStreamSkip(*m_Data, bytesToIgnore); uint16_t count; readQDataStream(*m_Data, count); diff --git a/src/gamebryo/gamebryosavegame.h b/src/gamebryo/gamebryosavegame.h index 7ab95150..dff06a7a 100644 --- a/src/gamebryo/gamebryosavegame.h +++ b/src/gamebryo/gamebryosavegame.h @@ -118,6 +118,7 @@ protected: template void readQDataStream(QDataStream& data, T& value); void readQDataStream(QDataStream& data, void* buff, std::size_t length); + void qDataStreamSkip(QDataStream& data, std::size_t length); /* Reads RGB image from save * Assumes picture dimentions come immediately before the save From f31a33b24e5eeee4a708bde68459d99fe38badde Mon Sep 17 00:00:00 2001 From: Jeremy Rimpo Date: Sun, 24 Sep 2023 23:22:09 -0500 Subject: [PATCH 1349/1544] Make QDataStream functions private --- src/gamebryo/gamebryosavegame.h | 13 ++++++++----- 1 file changed, 8 insertions(+), 5 deletions(-) diff --git a/src/gamebryo/gamebryosavegame.h b/src/gamebryo/gamebryosavegame.h index dff06a7a..e906f29b 100644 --- a/src/gamebryo/gamebryosavegame.h +++ b/src/gamebryo/gamebryosavegame.h @@ -115,11 +115,6 @@ protected: void read(void* buff, std::size_t length); - template - void readQDataStream(QDataStream& data, T& value); - void readQDataStream(QDataStream& data, void* buff, std::size_t length); - void qDataStreamSkip(QDataStream& data, std::size_t length); - /* Reads RGB image from save * Assumes picture dimentions come immediately before the save */ @@ -168,6 +163,14 @@ protected: StringType m_PluginString; QDataStream* m_Data; uint16_t m_CompressionType = 0; + + private: + template + void readQDataStream(QDataStream& data, T& value); + + void readQDataStream(QDataStream& data, void* buff, std::size_t length); + + void qDataStreamSkip(QDataStream& data, std::size_t length); }; void setCreationTime(_SYSTEMTIME const& time); From 74af0fb8f0efb7e5d96821480ad82a132c273dbf Mon Sep 17 00:00:00 2001 From: Jeremy Rimpo Date: Tue, 26 Sep 2023 19:32:04 -0500 Subject: [PATCH 1350/1544] Streamline code from review --- src/gamebryo/gamebryosavegame.cpp | 47 ++++++++++++------------------- src/gamebryo/gamebryosavegame.h | 2 +- 2 files changed, 19 insertions(+), 30 deletions(-) diff --git a/src/gamebryo/gamebryosavegame.cpp b/src/gamebryo/gamebryosavegame.cpp index 186c64c7..978414c5 100644 --- a/src/gamebryo/gamebryosavegame.cpp +++ b/src/gamebryo/gamebryosavegame.cpp @@ -143,21 +143,11 @@ void GamebryoSaveGame::FileWrapper::readQDataStream(QDataStream& data, void* buf template void GamebryoSaveGame::FileWrapper::readQDataStream(QDataStream& data, T& value) { - int read = data.readRawData(reinterpret_cast(&value), sizeof(T)); - bool result = true; - if (read != sizeof(T) && m_CompressionType == 1) { - result = readNextChunk(); - if (result) { - read += - data.readRawData(reinterpret_cast(&value) + read, sizeof(T) - read); - } - } - if (read != sizeof(T) || !result) { - throw std::runtime_error("unexpected end of file"); - } + static_assert(std::is_trivial_v && std::is_standard_layout_v); + readQDataStream(data, &value, sizeof(T)); } -void GamebryoSaveGame::FileWrapper::qDataStreamSkip(QDataStream& data, +void GamebryoSaveGame::FileWrapper::skipQDataStream(QDataStream& data, std::size_t length) { int skip = data.skipRawData(static_cast(length)); @@ -307,7 +297,7 @@ bool GamebryoSaveGame::FileWrapper::openCompressedData(int bytesToIgnore) m_Data = new QDataStream(placeholder); bool result = readNextChunk(); if (result) - qDataStreamSkip(*m_Data, bytesToIgnore); + skipQDataStream(*m_Data, bytesToIgnore); return result; } else if (m_CompressionType == 2) { uint32_t uncompressedSize; @@ -324,7 +314,7 @@ bool GamebryoSaveGame::FileWrapper::openCompressedData(int bytesToIgnore) compressed.clear(); m_Data = new QDataStream(decompressed); - qDataStreamSkip(*m_Data, bytesToIgnore); + skipQDataStream(*m_Data, bytesToIgnore); return true; } else { @@ -337,9 +327,9 @@ bool GamebryoSaveGame::FileWrapper::openCompressedData(int bytesToIgnore) bool GamebryoSaveGame::FileWrapper::readNextChunk() { uint32_t have; - uint64_t read = 0; - std::unique_ptr inBuffer(new unsigned char[CHUNK]); - std::unique_ptr outBuffer(new unsigned char[CHUNK]); + uint64_t read = 0; + std::unique_ptr inBuffer = std::make_unique(CHUNK); + std::unique_ptr outBuffer = std::make_unique(CHUNK); QByteArray finalData; m_Data->device()->close(); delete m_Data; @@ -358,7 +348,7 @@ bool GamebryoSaveGame::FileWrapper::readNextChunk() return false; } do { - stream.avail_in = m_File.read(reinterpret_cast(inBuffer.get()), CHUNK); + stream.avail_in = m_File.read(inBuffer.get(), CHUNK); read += stream.avail_in; if (!m_File.isReadable()) { (void)inflateEnd(&stream); @@ -366,7 +356,7 @@ bool GamebryoSaveGame::FileWrapper::readNextChunk() } if (stream.avail_in == 0) break; - stream.next_in = static_cast(inBuffer.get()); + stream.next_in = reinterpret_cast(inBuffer.get()); do { stream.avail_out = CHUNK; stream.next_out = reinterpret_cast(outBuffer.get()); @@ -376,8 +366,7 @@ bool GamebryoSaveGame::FileWrapper::readNextChunk() return false; } have = CHUNK - stream.avail_out; - finalData += QByteArray::fromRawData( - reinterpret_cast(outBuffer.get()), have); + finalData += QByteArray::fromRawData(outBuffer.get(), have); } while (stream.avail_out == 0); read -= stream.avail_in; } while (zlibRet != Z_STREAM_END); @@ -403,7 +392,7 @@ uint8_t GamebryoSaveGame::FileWrapper::readChar(int bytesToIgnore) return version; } else if (m_CompressionType == 1 || m_CompressionType == 2) { // decompression already done by readSaveGameVersion - qDataStreamSkip(*m_Data, bytesToIgnore); + skipQDataStream(*m_Data, bytesToIgnore); uint8_t version; readQDataStream(*m_Data, version); @@ -426,7 +415,7 @@ uint16_t GamebryoSaveGame::FileWrapper::readShort(int bytesToIgnore) return size; } else if (m_CompressionType == 1 || m_CompressionType == 2) { // decompression already done by readSaveGameVersion - qDataStreamSkip(*m_Data, bytesToIgnore); + skipQDataStream(*m_Data, bytesToIgnore); uint16_t size; readQDataStream(*m_Data, size); @@ -448,7 +437,7 @@ uint32_t GamebryoSaveGame::FileWrapper::readInt(int bytesToIgnore) return size; } else if (m_CompressionType == 1 || m_CompressionType == 2) { // decompression already done by readSaveGameVersion - qDataStreamSkip(*m_Data, bytesToIgnore); + skipQDataStream(*m_Data, bytesToIgnore); uint32_t size; readQDataStream(*m_Data, size); @@ -470,7 +459,7 @@ uint64_t GamebryoSaveGame::FileWrapper::readLong(int bytesToIgnore) return size; } else if (m_CompressionType == 1 || m_CompressionType == 2) { // decompression already done by readSaveGameVersion - qDataStreamSkip(*m_Data, bytesToIgnore); + skipQDataStream(*m_Data, bytesToIgnore); uint64_t size; readQDataStream(*m_Data, size); @@ -492,7 +481,7 @@ float_t GamebryoSaveGame::FileWrapper::readFloat(int bytesToIgnore) return value; } else if (m_CompressionType == 1 || m_CompressionType == 2) { // decompression already done by readSaveGameVersion - qDataStreamSkip(*m_Data, bytesToIgnore); + skipQDataStream(*m_Data, bytesToIgnore); float_t value; readQDataStream(*m_Data, value); @@ -520,7 +509,7 @@ QStringList GamebryoSaveGame::FileWrapper::readPlugins(int bytesToIgnore) plugins.push_back(name); } } else if (m_CompressionType == 1 || m_CompressionType == 2) { - qDataStreamSkip(*m_Data, bytesToIgnore); + skipQDataStream(*m_Data, bytesToIgnore); uint8_t count; readQDataStream(*m_Data, count); uint16_t finalCount = count; @@ -549,7 +538,7 @@ QStringList GamebryoSaveGame::FileWrapper::readLightPlugins(int bytesToIgnore) plugins.push_back(name); } } else if (m_CompressionType == 1 || m_CompressionType == 2) { - qDataStreamSkip(*m_Data, bytesToIgnore); + skipQDataStream(*m_Data, bytesToIgnore); uint16_t count; readQDataStream(*m_Data, count); diff --git a/src/gamebryo/gamebryosavegame.h b/src/gamebryo/gamebryosavegame.h index e906f29b..da241e8a 100644 --- a/src/gamebryo/gamebryosavegame.h +++ b/src/gamebryo/gamebryosavegame.h @@ -170,7 +170,7 @@ protected: void readQDataStream(QDataStream& data, void* buff, std::size_t length); - void qDataStreamSkip(QDataStream& data, std::size_t length); + void skipQDataStream(QDataStream& data, std::size_t length); }; void setCreationTime(_SYSTEMTIME const& time); From de00e418235b9cfad0cb4f64756dba6439fb2d6a Mon Sep 17 00:00:00 2001 From: Mikael CAPELLE Date: Wed, 27 Sep 2023 08:29:35 +0200 Subject: [PATCH 1351/1544] Fix onAboutToRun ambiguous call. --- src/gamebryo/gamegamebryo.cpp | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/src/gamebryo/gamegamebryo.cpp b/src/gamebryo/gamegamebryo.cpp index 7467fbd4..cf916ee2 100644 --- a/src/gamebryo/gamegamebryo.cpp +++ b/src/gamebryo/gamegamebryo.cpp @@ -43,9 +43,10 @@ void GameGamebryo::detectGame() bool GameGamebryo::init(MOBase::IOrganizer* moInfo) { - using namespace std::placeholders; m_Organizer = moInfo; - m_Organizer->onAboutToRun(std::bind(&GameGamebryo::prepareIni, this, _1)); + m_Organizer->onAboutToRun([this](const auto& binary) { + return prepareIni(binary); + }); return true; } From 94d84a8702506ccc713b54a3442634dd68038cce Mon Sep 17 00:00:00 2001 From: Jeremy Rimpo Date: Thu, 28 Sep 2023 03:35:02 -0500 Subject: [PATCH 1352/1544] [game_starfield] Support plugins.txt by setting - SFSE plugin adds plugins.txt support - Allow advanced users to enable this in the plugin settings - Fully disable writing to the plugins.txt file if disabled - Fully disable mapping the plugins.txt if disabled --- src/games/starfield/src/gamestarfield.cpp | 22 ++++++++++++++++++- src/games/starfield/src/gamestarfield.h | 1 + .../starfield/src/starfieldgameplugins.cpp | 11 ++++++++++ .../starfield/src/starfieldgameplugins.h | 2 ++ 4 files changed, 35 insertions(+), 1 deletion(-) diff --git a/src/games/starfield/src/gamestarfield.cpp b/src/games/starfield/src/gamestarfield.cpp index 9592fef4..039a1e8f 100644 --- a/src/games/starfield/src/gamestarfield.cpp +++ b/src/games/starfield/src/gamestarfield.cpp @@ -152,7 +152,24 @@ MOBase::VersionInfo GameStarfield::version() const QList GameStarfield::settings() const { - return QList(); + return QList() + << PluginSetting("enable_plugin_management", + tr("Turn on plugin management. As of Starfield 1.7.33 this " + "REQUIRES SPECIAL WORKAROUNDS."), + false); +} + +MappingType GameStarfield::mappings() const +{ + MappingType result; + if (m_Organizer->pluginSetting(name(), "enable_plugin_management").toBool()) { + for (const QString& profileFile : {"plugins.txt", "loadorder.txt"}) { + result.push_back({m_Organizer->profilePath() + "/" + profileFile, + localAppFolder() + "/" + gameShortName() + "/" + profileFile, + false}); + } + } + return result; } void GameStarfield::initializeProfile(const QDir& path, ProfileSettings settings) const @@ -280,6 +297,9 @@ IPluginGame::SortMechanism GameStarfield::sortMechanism() const IPluginGame::LoadOrderMechanism GameStarfield::loadOrderMechanism() const { + if (m_Organizer->pluginSetting(name(), "enable_plugin_management").toBool()) { + return IPluginGame::LoadOrderMechanism::PluginsTxt; + } return IPluginGame::LoadOrderMechanism::None; } diff --git a/src/games/starfield/src/gamestarfield.h b/src/games/starfield/src/gamestarfield.h index 8b37a153..a29b2eb3 100644 --- a/src/games/starfield/src/gamestarfield.h +++ b/src/games/starfield/src/gamestarfield.h @@ -48,6 +48,7 @@ public: // IPlugin interface virtual QString description() const override; virtual MOBase::VersionInfo version() const override; virtual QList settings() const override; + virtual MappingType mappings() const override; protected: virtual QString identifyGamePath() const override; diff --git a/src/games/starfield/src/starfieldgameplugins.cpp b/src/games/starfield/src/starfieldgameplugins.cpp index d946ed43..3d02b9b7 100644 --- a/src/games/starfield/src/starfieldgameplugins.cpp +++ b/src/games/starfield/src/starfieldgameplugins.cpp @@ -10,3 +10,14 @@ bool StarfieldGamePlugins::overridePluginsAreSupported() { return true; } + +void StarfieldGamePlugins::writePluginList(const IPluginList* pluginList, + const QString& filePath) +{ + if (m_Organizer + ->pluginSetting(m_Organizer->managedGame()->name(), + "enable_plugin_management") + .toBool()) { + CreationGamePlugins::writePluginList(pluginList, filePath); + } +} \ No newline at end of file diff --git a/src/games/starfield/src/starfieldgameplugins.h b/src/games/starfield/src/starfieldgameplugins.h index 693edb70..49c46a7c 100644 --- a/src/games/starfield/src/starfieldgameplugins.h +++ b/src/games/starfield/src/starfieldgameplugins.h @@ -14,6 +14,8 @@ public: protected: virtual bool overridePluginsAreSupported() override; + virtual void writePluginList(const MOBase::IPluginList* pluginList, + const QString& filePath) override; }; #endif // _STARFIELDGAMEPLUGINS_H From 43e340bf23ef429d917ab52387f92c574654948b Mon Sep 17 00:00:00 2001 From: Jeremy Rimpo Date: Thu, 28 Sep 2023 09:47:16 -0500 Subject: [PATCH 1353/1544] [game_starfield] Update wording for setting - Bump version to .5b --- src/games/starfield/src/gamestarfield.cpp | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/src/games/starfield/src/gamestarfield.cpp b/src/games/starfield/src/gamestarfield.cpp index 039a1e8f..f124b5f0 100644 --- a/src/games/starfield/src/gamestarfield.cpp +++ b/src/games/starfield/src/gamestarfield.cpp @@ -147,7 +147,7 @@ QString GameStarfield::description() const MOBase::VersionInfo GameStarfield::version() const { - return VersionInfo(0, 0, 1, VersionInfo::RELEASE_PREALPHA); + return VersionInfo(0, 5, 0, VersionInfo::RELEASE_BETA); } QList GameStarfield::settings() const @@ -155,7 +155,8 @@ QList GameStarfield::settings() const return QList() << PluginSetting("enable_plugin_management", tr("Turn on plugin management. As of Starfield 1.7.33 this " - "REQUIRES SPECIAL WORKAROUNDS."), + "REQUIRES fixing 'plugins.txt' with a SFSE plugin. This " + "will do nothing otherwise."), false); } From 1ece9081db3364c7ddf885b0c54f0787f4bddffc Mon Sep 17 00:00:00 2001 From: Jeremy Rimpo Date: Thu, 28 Sep 2023 11:24:34 -0500 Subject: [PATCH 1354/1544] [game_starfield] Consolidate game search code in Gamebryo --- src/games/starfield/src/gamestarfield.cpp | 30 +- src/games/starfield/src/vdf_parser.h | 739 ---------------------- 2 files changed, 1 insertion(+), 768 deletions(-) delete mode 100644 src/games/starfield/src/vdf_parser.h diff --git a/src/games/starfield/src/gamestarfield.cpp b/src/games/starfield/src/gamestarfield.cpp index f124b5f0..8b723312 100644 --- a/src/games/starfield/src/gamestarfield.cpp +++ b/src/games/starfield/src/gamestarfield.cpp @@ -26,7 +26,6 @@ #include #include "scopeguard.h" -#include "vdf_parser.h" using namespace MOBase; @@ -67,34 +66,7 @@ void GameStarfield::detectGame() QString GameStarfield::identifyGamePath() const { - QString path = "Software\\Valve\\Steam"; - QString steamLocation = - findInRegistry(HKEY_CURRENT_USER, path.toStdWString().c_str(), L"SteamPath"); - if (!steamLocation.isEmpty()) { - QString steamLibraryLocation; - QString steamLibraries(steamLocation + "\\" + "config" + "\\" + - "libraryfolders.vdf"); - if (QFile(steamLibraries).exists()) { - std::ifstream file(steamLibraries.toStdString()); - auto root = tyti::vdf::read(file); - for (auto child : root.childs) { - tyti::vdf::object* library = child.second.get(); - auto apps = library->childs["apps"]; - if (apps->attribs.contains(steamAPPId().toStdString())) { - steamLibraryLocation = QString::fromStdString(library->attribs["path"]); - break; - } - } - } - if (!steamLibraryLocation.isEmpty()) { - QString gameLocation = steamLibraryLocation + "\\" + "steamapps" + "\\" + - "common" + "\\" + "Starfield"; - if (QDir(gameLocation).exists() && - QFile(gameLocation + "\\" + "Starfield.exe").exists()) - return gameLocation; - } - } - return ""; + return parseSteamLocation(steamAPPId()); } QDir GameStarfield::dataDirectory() const diff --git a/src/games/starfield/src/vdf_parser.h b/src/games/starfield/src/vdf_parser.h deleted file mode 100644 index 32d4d27d..00000000 --- a/src/games/starfield/src/vdf_parser.h +++ /dev/null @@ -1,739 +0,0 @@ -// MIT License -// -// Copyright(c) 2016 Matthias Moeller -// -// Permission is hereby granted, free of charge, to any person obtaining a copy -// of this software and associated documentation files(the "Software"), to deal -// in the Software without restriction, including without limitation the rights -// to use, copy, modify, merge, publish, distribute, sublicense, and / or sell -// copies of the Software, and to permit persons to whom the Software is -// furnished to do so, subject to the following conditions : -// -// The above copyright notice and this permission notice shall be included in all -// copies or substantial portions of the Software. -// -// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.IN NO EVENT SHALL THE -// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER -// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, -// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE -// SOFTWARE. - -#ifndef __TYTI_STEAM_VDF_PARSER_H__ -#define __TYTI_STEAM_VDF_PARSER_H__ - -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - -#include -#include - -// for wstring support -#include -#include - -// internal -#include - -// VS < 2015 has only partial C++11 support -#if defined(_MSC_VER) && _MSC_VER < 1900 -#ifndef CONSTEXPR -#define CONSTEXPR -#endif - -#ifndef NOEXCEPT -#define NOEXCEPT -#endif -#else -#ifndef CONSTEXPR -#define CONSTEXPR constexpr -#define TYTI_UNDEF_CONSTEXPR -#endif - -#ifndef NOEXCEPT -#define NOEXCEPT noexcept -#define TYTI_UNDEF_NOEXCEPT -#endif - -#endif - -namespace tyti -{ -namespace vdf -{ - namespace detail - { - /////////////////////////////////////////////////////////////////////////// - // Helper functions selecting the right encoding (char/wchar_T) - /////////////////////////////////////////////////////////////////////////// - - template - struct literal_macro_help - { - static CONSTEXPR const char* result(const char* c, const wchar_t*) NOEXCEPT - { - return c; - } - static CONSTEXPR const char result(const char c, const wchar_t) NOEXCEPT - { - return c; - } - }; - - template <> - struct literal_macro_help - { - static CONSTEXPR const wchar_t* result(const char*, const wchar_t* wc) NOEXCEPT - { - return wc; - } - static CONSTEXPR const wchar_t result(const char, const wchar_t wc) NOEXCEPT - { - return wc; - } - }; -#define TYTI_L(type, text) vdf::detail::literal_macro_help::result(text, L##text) - - inline std::string string_converter(const std::string& w) NOEXCEPT - { - return w; - } - - // utility wrapper to adapt locale-bound facets for wstring/wbuffer convert - // from cppreference - template - struct deletable_facet : Facet - { - template - deletable_facet(Args&&... args) : Facet(std::forward(args)...) - {} - ~deletable_facet() {} - }; - - inline std::string string_converter(const std::wstring& w) // todo: use us-locale - { - std::wstring_convert>> - conv1; - return conv1.to_bytes(w); - } - - /////////////////////////////////////////////////////////////////////////// - // Writer helper functions - /////////////////////////////////////////////////////////////////////////// - - template - class tabs - { - const size_t t; - - public: - explicit CONSTEXPR tabs(size_t i) NOEXCEPT : t(i) {} - std::basic_string print() const - { - return std::basic_string(t, TYTI_L(charT, '\t')); - } - inline CONSTEXPR tabs operator+(size_t i) const NOEXCEPT { return tabs(t + i); } - }; - - template - oStreamT& operator<<(oStreamT& s, const tabs t) - { - s << t.print(); - return s; - } - } // end namespace detail - - /////////////////////////////////////////////////////////////////////////// - // Interface - /////////////////////////////////////////////////////////////////////////// - - /// custom objects and their corresponding write functions - - /// basic object node. Every object has a name and can contains attributes saved as - /// key_value pairs or childrens - template - struct basic_object - { - typedef CharT char_type; - std::basic_string name; - std::unordered_map, std::basic_string> - attribs; - std::unordered_map, - std::shared_ptr>> - childs; - - void add_attribute(std::basic_string key, - std::basic_string value) - { - attribs.emplace(std::move(key), std::move(value)); - } - void add_child(std::unique_ptr> child) - { - std::shared_ptr> obj{child.release()}; - childs.emplace(obj->name, obj); - } - void set_name(std::basic_string n) { name = std::move(n); } - }; - - template - struct basic_multikey_object - { - typedef CharT char_type; - std::basic_string name; - std::unordered_multimap, std::basic_string> - attribs; - std::unordered_multimap, - std::shared_ptr>> - childs; - - void add_attribute(std::basic_string key, - std::basic_string value) - { - attribs.emplace(std::move(key), std::move(value)); - } - void add_child(std::unique_ptr> child) - { - std::shared_ptr> obj{child.release()}; - childs.emplace(obj->name, obj); - } - void set_name(std::basic_string n) { name = std::move(n); } - }; - - typedef basic_object object; - typedef basic_object wobject; - typedef basic_multikey_object multikey_object; - typedef basic_multikey_object wmultikey_object; - - struct Options - { - bool strip_escape_symbols; - bool ignore_all_platform_conditionals; - bool ignore_includes; - - Options() - : strip_escape_symbols(true), ignore_all_platform_conditionals(false), - ignore_includes(false) - {} - }; - - // forward decls - // forward decl - template - OutputT read(iStreamT& inStream, const Options& opt = Options{}); - - /** \brief writes given object tree in vdf format to given stream. - Output is prettyfied, using tabs - */ - template - void write(oStreamT& s, const T& r, - const detail::tabs tab = - detail::tabs(0)) - { - typedef typename oStreamT::char_type charT; - using namespace detail; - s << tab << TYTI_L(charT, '"') << r.name << TYTI_L(charT, "\"\n") << tab - << TYTI_L(charT, "{\n"); - for (const auto& i : r.attribs) - s << tab + 1 << TYTI_L(charT, '"') << i.first << TYTI_L(charT, "\"\t\t\"") - << i.second << TYTI_L(charT, "\"\n"); - for (const auto& i : r.childs) - if (i.second) - write(s, *i.second, tab + 1); - s << tab << TYTI_L(charT, "}\n"); - } - - namespace detail - { - template - std::basic_string read_file(iStreamT& inStream) - { - // cache the file - typedef typename iStreamT::char_type charT; - std::basic_string str; - inStream.seekg(0, std::ios::end); - str.resize(static_cast(inStream.tellg())); - if (str.empty()) - return str; - - inStream.seekg(0, std::ios::beg); - inStream.read(&str[0], str.size()); - return str; - } - - /** \brief Read VDF formatted sequences defined by the range [first, last). - If the file is mailformatted, parser will try to read it until it can. - @param first begin iterator - @param end end iterator - @param exclude_files list of files which cant be included anymore. - prevents circular includes - - can thow: - - "std::runtime_error" if a parsing error occured - - "std::bad_alloc" if not enough memory coup be allocated - */ - template - std::vector> - read_internal(IterT first, const IterT last, - std::unordered_set::value_type>>& exclude_files, - const Options& opt) - { - static_assert(std::is_default_constructible::value, - "Output Type must be default constructible (provide constructor " - "without arguments)"); - static_assert(std::is_move_constructible::value, - "Output Type must be move constructible"); - - typedef typename std::iterator_traits::value_type charT; - - const std::basic_string comment_end_str = TYTI_L(charT, "*/"); - const std::basic_string whitespaces = TYTI_L(charT, " \n\v\f\r\t"); - -#ifdef WIN32 - std::function&)> is_platform_str = - [](const std::basic_string& in) { - return in == TYTI_L(charT, "$WIN32") || in == TYTI_L(charT, "$WINDOWS"); - }; -#elif __APPLE__ - // WIN32 stands for pc in general - std::function&)> is_platform_str = - [](const std::basic_string& in) { - return in == TYTI_L(charT, "$WIN32") || in == TYTI_L(charT, "$POSIX") || - in == TYTI_L(charT, "$OSX"); - }; - -#elif __linux__ - // WIN32 stands for pc in general - std::function&)> is_platform_str = - [](const std::basic_string& in) { - return in == TYTI_L(charT, "$WIN32") || in == TYTI_L(charT, "$POSIX") || - in == TYTI_L(charT, "$LINUX"); - }; -#else - std::function&)> is_platform_str = - [](const std::basic_string& in) { - return false; - }; -#endif - - if (opt.ignore_all_platform_conditionals) - is_platform_str = [](const std::basic_string&) { - return false; - }; - - // function for skipping a comment block - // iter: iterator poition to the position after a '/' - auto skip_comments = [&comment_end_str](IterT iter, const IterT& last) -> IterT { - ++iter; - if (iter != last) { - if (*iter == TYTI_L(charT, '/')) { - // line comment, skip whole line - iter = std::find(iter + 1, last, TYTI_L(charT, '\n')); - } - - if (*iter == '*') { - // block comment, skip until next occurance of "*\" - iter = std::search(iter + 1, last, std::begin(comment_end_str), - std::end(comment_end_str)); - iter += 2; - } - } - return iter; - }; - - auto end_quote = [](IterT iter, const IterT& last) -> IterT { - const auto begin = iter; - auto last_esc = iter; - do { - ++iter; - iter = std::find(iter, last, TYTI_L(charT, '\"')); - if (iter == last) - break; - - last_esc = std::prev(iter); - while (last_esc != begin && *last_esc == '\\') - --last_esc; - } while (!(std::distance(last_esc, iter) % 2)); - if (iter == last) - throw std::runtime_error{"quote was opened but not closed."}; - return iter; - }; - - auto end_word = [&whitespaces](IterT iter, const IterT& last) -> IterT { - const auto begin = iter; - auto last_esc = iter; - do { - ++iter; - iter = std::find_first_of(iter, last, std::begin(whitespaces), - std::end(whitespaces)); - if (iter == last) - break; - - last_esc = std::prev(iter); - while (last_esc != begin && *last_esc == '\\') - --last_esc; - } while (!(std::distance(last_esc, iter) % 2)); - // if (iter == last) - // throw std::runtime_error{ "word wasnt properly ended" }; - return iter; - }; - - auto skip_whitespaces = [&whitespaces](IterT iter, const IterT& last) -> IterT { - iter = std::find_if_not(iter, last, [&whitespaces](charT c) { - // return true if whitespace - return std::any_of(std::begin(whitespaces), std::end(whitespaces), - [c](charT pc) { - return pc == c; - }); - }); - return iter; - }; - - std::function&)> strip_escape_symbols = - [](std::basic_string& s) { - auto quote_searcher = [&s](size_t pos) { - return s.find(TYTI_L(charT, "\\\""), pos); - }; - auto p = quote_searcher(0); - while (p != s.npos) { - s.replace(p, 2, TYTI_L(charT, "\"")); - p = quote_searcher(p); - } - auto searcher = [&s](size_t pos) { - return s.find(TYTI_L(charT, "\\\\"), pos); - }; - p = searcher(0); - while (p != s.npos) { - s.replace(p, 2, TYTI_L(charT, "\\")); - p = searcher(p); - } - }; - - if (!opt.strip_escape_symbols) - strip_escape_symbols = [](std::basic_string&) {}; - - auto conditional_fullfilled = [&skip_whitespaces, - &is_platform_str](IterT& iter, const IterT& last) { - iter = skip_whitespaces(iter, last); - if (*iter == '[') { - ++iter; - const auto end = std::find(iter, last, ']'); - const bool negate = *iter == '!'; - if (negate) - ++iter; - auto conditional = std::basic_string(iter, end); - - const bool is_platform = is_platform_str(conditional); - iter = end + 1; - - return static_cast(is_platform ^ negate); - } - return true; - }; - - // read header - // first, quoted name - std::unique_ptr curObj = nullptr; - std::vector> roots; - std::stack> lvls; - auto curIter = first; - - while (curIter != last && *curIter != '\0') { - // find first starting attrib/child, or ending - curIter = skip_whitespaces(curIter, last); - if (curIter == last || *curIter == '\0') - break; - if (*curIter == TYTI_L(charT, '/')) { - curIter = skip_comments(curIter, last); - } else if (*curIter != TYTI_L(charT, '}')) { - - // get key - const auto keyEnd = (*curIter == TYTI_L(charT, '\"')) - ? end_quote(curIter, last) - : end_word(curIter, last); - if (*curIter == TYTI_L(charT, '\"')) - ++curIter; - std::basic_string key(curIter, keyEnd); - strip_escape_symbols(key); - curIter = keyEnd + ((*keyEnd == TYTI_L(charT, '\"')) ? 1 : 0); - - curIter = skip_whitespaces(curIter, last); - - auto conditional = conditional_fullfilled(curIter, last); - if (!conditional) - continue; - - while (*curIter == TYTI_L(charT, '/')) { - - curIter = skip_comments(curIter, last); - if (curIter == last || *curIter == '}') - throw std::runtime_error{"key declared, but no value"}; - curIter = skip_whitespaces(curIter, last); - if (curIter == last || *curIter == '}') - throw std::runtime_error{"key declared, but no value"}; - } - // get value - if (*curIter != '{') { - const auto valueEnd = (*curIter == TYTI_L(charT, '\"')) - ? end_quote(curIter, last) - : end_word(curIter, last); - if (*curIter == TYTI_L(charT, '\"')) - ++curIter; - - auto value = std::basic_string(curIter, valueEnd); - strip_escape_symbols(value); - curIter = valueEnd + ((*valueEnd == TYTI_L(charT, '\"')) ? 1 : 0); - - auto conditional = conditional_fullfilled(curIter, last); - if (!conditional) - continue; - - // process value - if (key != TYTI_L(charT, "#include") && key != TYTI_L(charT, "#base")) { - if (curObj) { - curObj->add_attribute(std::move(key), std::move(value)); - } else { - throw std::runtime_error{"unexpected key without object"}; - } - } else { - if (!opt.ignore_includes && - exclude_files.find(value) == exclude_files.end()) { - exclude_files.insert(value); - std::basic_ifstream i(detail::string_converter(value)); - auto str = read_file(i); - auto file_objs = - read_internal(str.begin(), str.end(), exclude_files, opt); - for (auto& n : file_objs) { - if (curObj) - curObj->add_child(std::move(n)); - else - roots.push_back(std::move(n)); - } - exclude_files.erase(value); - } - } - } else if (*curIter == '{') { - if (curObj) - lvls.push(std::move(curObj)); - curObj = std::make_unique(); - curObj->set_name(std::move(key)); - ++curIter; - } - } - // end of new object - else if (curObj && *curIter == TYTI_L(charT, '}')) { - if (!lvls.empty()) { - // get object before - std::unique_ptr prev{std::move(lvls.top())}; - lvls.pop(); - - // add finished obj to obj before and release it from processing - prev->add_child(std::move(curObj)); - curObj = std::move(prev); - } else { - roots.push_back(std::move(curObj)); - curObj.reset(); - } - ++curIter; - } else { - throw std::runtime_error{"unexpected '}'"}; - } - } - if (curObj != nullptr || !lvls.empty()) { - throw std::runtime_error{"object is not closed with '}'"}; - } - - return roots; - } - - } // namespace detail - - /** \brief Read VDF formatted sequences defined by the range [first, last). - If the file is mailformatted, parser will try to read it until it can. - @param first begin iterator - @param end end iterator - - can thow: - - "std::runtime_error" if a parsing error occured - - "std::bad_alloc" if not enough memory coup be allocated - */ - template - OutputT read(IterT first, const IterT last, const Options& opt = Options{}) - { - auto exclude_files = std::unordered_set< - std::basic_string::value_type>>{}; - auto roots = detail::read_internal(first, last, exclude_files, opt); - - OutputT result; - if (roots.size() > 1) { - for (auto& i : roots) - result.add_child(std::move(i)); - } else if (roots.size() == 1) - result = std::move(*roots[0]); - - return result; - } - - /** \brief Read VDF formatted sequences defined by the range [first, last). - If the file is mailformatted, parser will try to read it until it can. - @param first begin iterator - @param end end iterator - @param ec output bool. 0 if ok, otherwise, holds an system error code - - Possible error codes: - std::errc::protocol_error: file is mailformatted - std::errc::not_enough_memory: not enough space - std::errc::invalid_argument: iterators throws e.g. out of range - */ - template - OutputT read(IterT first, IterT last, std::error_code& ec, - const Options& opt = Options{}) NOEXCEPT - - { - ec.clear(); - OutputT r{}; - try { - r = read(first, last, opt); - } catch (std::runtime_error&) { - ec = std::make_error_code(std::errc::protocol_error); - } catch (std::bad_alloc&) { - ec = std::make_error_code(std::errc::not_enough_memory); - } catch (...) { - ec = std::make_error_code(std::errc::invalid_argument); - } - return r; - } - - /** \brief Read VDF formatted sequences defined by the range [first, last). - If the file is mailformatted, parser will try to read it until it can. - @param first begin iterator - @param end end iterator - @param ok output bool. true, if parser successed, false, if parser failed - */ - template - OutputT read(IterT first, const IterT last, bool* ok, - const Options& opt = Options{}) NOEXCEPT - { - std::error_code ec; - auto r = read(first, last, ec, opt); - if (ok) - *ok = !ec; - return r; - } - - template - inline auto read(IterT first, const IterT last, bool* ok, - const Options& opt = Options{}) NOEXCEPT - ->basic_object::value_type> - { - return read::value_type>>( - first, last, ok, opt); - } - - template - inline auto read(IterT first, IterT last, std::error_code& ec, - const Options& opt = Options{}) NOEXCEPT - ->basic_object::value_type> - { - return read::value_type>>( - first, last, ec, opt); - } - - template - inline auto read(IterT first, const IterT last, const Options& opt = Options{}) - -> basic_object::value_type> - { - return read::value_type>>( - first, last, opt); - } - - /** \brief Loads a stream (e.g. filestream) into the memory and parses the vdf - formatted data. throws "std::bad_alloc" if file buffer could not be allocated - */ - template - OutputT read(iStreamT& inStream, std::error_code& ec, const Options& opt = Options{}) - { - // cache the file - typedef typename iStreamT::char_type charT; - std::basic_string str = detail::read_file(inStream); - - // parse it - return read(str.begin(), str.end(), ec, opt); - } - - template - inline basic_object - read(iStreamT& inStream, std::error_code& ec, const Options& opt = Options{}) - { - return read>(inStream, ec, opt); - } - - /** \brief Loads a stream (e.g. filestream) into the memory and parses the vdf - formatted data. throws "std::bad_alloc" if file buffer could not be allocated ok == - false, if a parsing error occured - */ - template - OutputT read(iStreamT& inStream, bool* ok, const Options& opt = Options{}) - { - std::error_code ec; - const auto r = read(inStream, ec, opt); - if (ok) - *ok = !ec; - return r; - } - - template - inline basic_object read(iStreamT& inStream, bool* ok, - const Options& opt = Options{}) - { - return read>(inStream, ok, opt); - } - - /** \brief Loads a stream (e.g. filestream) into the memory and parses the vdf - formatted data. throws "std::bad_alloc" if file buffer could not be allocated - throws "std::runtime_error" if a parsing error occured - */ - template - OutputT read(iStreamT& inStream, const Options& opt) - { - - // cache the file - typedef typename iStreamT::char_type charT; - std::basic_string str = detail::read_file(inStream); - // parse it - return read(str.begin(), str.end(), opt); - } - - template - inline basic_object read(iStreamT& inStream, - const Options& opt = Options{}) - { - return read>(inStream, opt); - } - -} // namespace vdf -} // namespace tyti -#ifndef TYTI_NO_L_UNDEF -#undef TYTI_L -#endif - -#ifdef TYTI_UNDEF_CONSTEXPR -#undef CONSTEXPR -#undef TYTI_NO_L_UNDEF -#endif - -#ifdef TYTI_UNDEF_NOTHROW -#undef NOTHROW -#undef TYTI_UNDEF_NOTHROW -#endif - -#endif //__TYTI_STEAM_VDF_PARSER_H__ From 2300ce09ae05399d57631de88dcaa820d82a6dcf Mon Sep 17 00:00:00 2001 From: Jeremy Rimpo Date: Thu, 28 Sep 2023 11:24:42 -0500 Subject: [PATCH 1355/1544] [game_skyrimse] Consolidate game search code in Gamebryo --- src/games/skyrimse/src/gameskyrimse.cpp | 35 ++----------------------- 1 file changed, 2 insertions(+), 33 deletions(-) diff --git a/src/games/skyrimse/src/gameskyrimse.cpp b/src/games/skyrimse/src/gameskyrimse.cpp index 194c7446..ad612659 100644 --- a/src/games/skyrimse/src/gameskyrimse.cpp +++ b/src/games/skyrimse/src/gameskyrimse.cpp @@ -81,39 +81,8 @@ QString GameSkyrimSE::identifyGamePath() const // AppName: ac82db5035584c7f8a2c548d98c86b2c // AE Update: 5d600e4f59974aeba0259c7734134e27 if (result.isEmpty()) { - // Use the registry entry to find the EGL Data dir first, just in case something - // changes - QString manifestDir = findInRegistry( - HKEY_LOCAL_MACHINE, L"SOFTWARE\\WOW6432Node\\Epic Games\\EpicGamesLauncher", - L"AppDataPath"); - if (manifestDir.isEmpty()) - manifestDir = getKnownFolderPath(FOLDERID_ProgramData, false) + - "\\Epic\\EpicGamesLauncher\\Data\\"; - manifestDir += "Manifests"; - QDir epicManifests(manifestDir, "*.item", - QDir::SortFlags(QDir::Name | QDir::IgnoreCase), QDir::Files); - if (epicManifests.exists()) { - QDirIterator it(epicManifests); - while (it.hasNext()) { - QString manifestFile = it.next(); - QFile manifest(manifestFile); - - if (!manifest.open(QIODevice::ReadOnly)) { - qWarning("Couldn't open Epic Games manifest file."); - continue; - } - - QByteArray manifestData = manifest.readAll(); - - QJsonDocument manifestJson(QJsonDocument::fromJson(manifestData)); - - if (manifestJson["AppName"] == "ac82db5035584c7f8a2c548d98c86b2c" || - manifestJson["AppName"] == "5d600e4f59974aeba0259c7734134e27") { - result = manifestJson["InstallLocation"].toString(); - break; - } - } - } + result = parseEpicGamesLocation( + {"ac82db5035584c7f8a2c548d98c86b2c", "5d600e4f59974aeba0259c7734134e27"}); } return result; From 26c585837f73af0a9f9552c3756f950a4db78797 Mon Sep 17 00:00:00 2001 From: Jeremy Rimpo Date: Thu, 28 Sep 2023 11:24:43 -0500 Subject: [PATCH 1356/1544] Consolidate game search code in Gamebryo --- src/gamebryo/gamegamebryo.cpp | 70 ++++ src/gamebryo/gamegamebryo.h | 4 + src/gamebryo/vdf_parser.h | 739 ++++++++++++++++++++++++++++++++++ 3 files changed, 813 insertions(+) create mode 100644 src/gamebryo/vdf_parser.h diff --git a/src/gamebryo/gamegamebryo.cpp b/src/gamebryo/gamegamebryo.cpp index 7467fbd4..71c1e4d4 100644 --- a/src/gamebryo/gamegamebryo.cpp +++ b/src/gamebryo/gamegamebryo.cpp @@ -11,12 +11,14 @@ #include "scopeguard.h" #include "scriptextender.h" #include "utility.h" +#include "vdf_parser.h" #include #include #include #include #include +#include #include #include @@ -425,3 +427,71 @@ QString GameGamebryo::determineMyGamesPath(const QString& gameName) return {}; } + +QString GameGamebryo::parseEpicGamesLocation(const QStringList& manifests) +{ + // Use the registry entry to find the EGL Data dir first, just in case something + // changes + QString manifestDir = findInRegistry( + HKEY_LOCAL_MACHINE, L"SOFTWARE\\WOW6432Node\\Epic Games\\EpicGamesLauncher", + L"AppDataPath"); + if (manifestDir.isEmpty()) + manifestDir = getKnownFolderPath(FOLDERID_ProgramData, false) + + "\\Epic\\EpicGamesLauncher\\Data\\"; + manifestDir += "Manifests"; + QDir epicManifests(manifestDir, "*.item", + QDir::SortFlags(QDir::Name | QDir::IgnoreCase), QDir::Files); + if (epicManifests.exists()) { + QDirIterator it(epicManifests); + while (it.hasNext()) { + QString manifestFile = it.next(); + QFile manifest(manifestFile); + + if (!manifest.open(QIODevice::ReadOnly)) { + qWarning("Couldn't open Epic Games manifest file."); + continue; + } + + QByteArray manifestData = manifest.readAll(); + + QJsonDocument manifestJson(QJsonDocument::fromJson(manifestData)); + + if (manifests.contains(manifestJson["AppName"].toString())) { + return manifestJson["InstallLocation"].toString(); + } + } + } + return ""; +} + +QString GameGamebryo::parseSteamLocation(const QString& appid) +{ + QString path = "Software\\Valve\\Steam"; + QString steamLocation = + findInRegistry(HKEY_CURRENT_USER, path.toStdWString().c_str(), L"SteamPath"); + if (!steamLocation.isEmpty()) { + QString steamLibraryLocation; + QString steamLibraries(steamLocation + "\\" + "config" + "\\" + + "libraryfolders.vdf"); + if (QFile(steamLibraries).exists()) { + std::ifstream file(steamLibraries.toStdString()); + auto root = tyti::vdf::read(file); + for (auto child : root.childs) { + tyti::vdf::object* library = child.second.get(); + auto apps = library->childs["apps"]; + if (apps->attribs.contains(appid.toStdString())) { + steamLibraryLocation = QString::fromStdString(library->attribs["path"]); + break; + } + } + } + if (!steamLibraryLocation.isEmpty()) { + QString gameLocation = steamLibraryLocation + "\\" + "steamapps" + "\\" + + "common" + "\\" + "Starfield"; + if (QDir(gameLocation).exists() && + QFile(gameLocation + "\\" + "Starfield.exe").exists()) + return gameLocation; + } + } + return ""; +} diff --git a/src/gamebryo/gamegamebryo.h b/src/gamebryo/gamegamebryo.h index f19f7501..b1aca9a9 100644 --- a/src/gamebryo/gamegamebryo.h +++ b/src/gamebryo/gamegamebryo.h @@ -126,6 +126,10 @@ protected: static QString determineMyGamesPath(const QString& gameName); + static QString parseEpicGamesLocation(const QStringList& manifests); + + static QString parseSteamLocation(const QString& appid); + protected: std::map featureList() const override; diff --git a/src/gamebryo/vdf_parser.h b/src/gamebryo/vdf_parser.h new file mode 100644 index 00000000..32d4d27d --- /dev/null +++ b/src/gamebryo/vdf_parser.h @@ -0,0 +1,739 @@ +// MIT License +// +// Copyright(c) 2016 Matthias Moeller +// +// Permission is hereby granted, free of charge, to any person obtaining a copy +// of this software and associated documentation files(the "Software"), to deal +// in the Software without restriction, including without limitation the rights +// to use, copy, modify, merge, publish, distribute, sublicense, and / or sell +// copies of the Software, and to permit persons to whom the Software is +// furnished to do so, subject to the following conditions : +// +// The above copyright notice and this permission notice shall be included in all +// copies or substantial portions of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.IN NO EVENT SHALL THE +// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +// SOFTWARE. + +#ifndef __TYTI_STEAM_VDF_PARSER_H__ +#define __TYTI_STEAM_VDF_PARSER_H__ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include + +// for wstring support +#include +#include + +// internal +#include + +// VS < 2015 has only partial C++11 support +#if defined(_MSC_VER) && _MSC_VER < 1900 +#ifndef CONSTEXPR +#define CONSTEXPR +#endif + +#ifndef NOEXCEPT +#define NOEXCEPT +#endif +#else +#ifndef CONSTEXPR +#define CONSTEXPR constexpr +#define TYTI_UNDEF_CONSTEXPR +#endif + +#ifndef NOEXCEPT +#define NOEXCEPT noexcept +#define TYTI_UNDEF_NOEXCEPT +#endif + +#endif + +namespace tyti +{ +namespace vdf +{ + namespace detail + { + /////////////////////////////////////////////////////////////////////////// + // Helper functions selecting the right encoding (char/wchar_T) + /////////////////////////////////////////////////////////////////////////// + + template + struct literal_macro_help + { + static CONSTEXPR const char* result(const char* c, const wchar_t*) NOEXCEPT + { + return c; + } + static CONSTEXPR const char result(const char c, const wchar_t) NOEXCEPT + { + return c; + } + }; + + template <> + struct literal_macro_help + { + static CONSTEXPR const wchar_t* result(const char*, const wchar_t* wc) NOEXCEPT + { + return wc; + } + static CONSTEXPR const wchar_t result(const char, const wchar_t wc) NOEXCEPT + { + return wc; + } + }; +#define TYTI_L(type, text) vdf::detail::literal_macro_help::result(text, L##text) + + inline std::string string_converter(const std::string& w) NOEXCEPT + { + return w; + } + + // utility wrapper to adapt locale-bound facets for wstring/wbuffer convert + // from cppreference + template + struct deletable_facet : Facet + { + template + deletable_facet(Args&&... args) : Facet(std::forward(args)...) + {} + ~deletable_facet() {} + }; + + inline std::string string_converter(const std::wstring& w) // todo: use us-locale + { + std::wstring_convert>> + conv1; + return conv1.to_bytes(w); + } + + /////////////////////////////////////////////////////////////////////////// + // Writer helper functions + /////////////////////////////////////////////////////////////////////////// + + template + class tabs + { + const size_t t; + + public: + explicit CONSTEXPR tabs(size_t i) NOEXCEPT : t(i) {} + std::basic_string print() const + { + return std::basic_string(t, TYTI_L(charT, '\t')); + } + inline CONSTEXPR tabs operator+(size_t i) const NOEXCEPT { return tabs(t + i); } + }; + + template + oStreamT& operator<<(oStreamT& s, const tabs t) + { + s << t.print(); + return s; + } + } // end namespace detail + + /////////////////////////////////////////////////////////////////////////// + // Interface + /////////////////////////////////////////////////////////////////////////// + + /// custom objects and their corresponding write functions + + /// basic object node. Every object has a name and can contains attributes saved as + /// key_value pairs or childrens + template + struct basic_object + { + typedef CharT char_type; + std::basic_string name; + std::unordered_map, std::basic_string> + attribs; + std::unordered_map, + std::shared_ptr>> + childs; + + void add_attribute(std::basic_string key, + std::basic_string value) + { + attribs.emplace(std::move(key), std::move(value)); + } + void add_child(std::unique_ptr> child) + { + std::shared_ptr> obj{child.release()}; + childs.emplace(obj->name, obj); + } + void set_name(std::basic_string n) { name = std::move(n); } + }; + + template + struct basic_multikey_object + { + typedef CharT char_type; + std::basic_string name; + std::unordered_multimap, std::basic_string> + attribs; + std::unordered_multimap, + std::shared_ptr>> + childs; + + void add_attribute(std::basic_string key, + std::basic_string value) + { + attribs.emplace(std::move(key), std::move(value)); + } + void add_child(std::unique_ptr> child) + { + std::shared_ptr> obj{child.release()}; + childs.emplace(obj->name, obj); + } + void set_name(std::basic_string n) { name = std::move(n); } + }; + + typedef basic_object object; + typedef basic_object wobject; + typedef basic_multikey_object multikey_object; + typedef basic_multikey_object wmultikey_object; + + struct Options + { + bool strip_escape_symbols; + bool ignore_all_platform_conditionals; + bool ignore_includes; + + Options() + : strip_escape_symbols(true), ignore_all_platform_conditionals(false), + ignore_includes(false) + {} + }; + + // forward decls + // forward decl + template + OutputT read(iStreamT& inStream, const Options& opt = Options{}); + + /** \brief writes given object tree in vdf format to given stream. + Output is prettyfied, using tabs + */ + template + void write(oStreamT& s, const T& r, + const detail::tabs tab = + detail::tabs(0)) + { + typedef typename oStreamT::char_type charT; + using namespace detail; + s << tab << TYTI_L(charT, '"') << r.name << TYTI_L(charT, "\"\n") << tab + << TYTI_L(charT, "{\n"); + for (const auto& i : r.attribs) + s << tab + 1 << TYTI_L(charT, '"') << i.first << TYTI_L(charT, "\"\t\t\"") + << i.second << TYTI_L(charT, "\"\n"); + for (const auto& i : r.childs) + if (i.second) + write(s, *i.second, tab + 1); + s << tab << TYTI_L(charT, "}\n"); + } + + namespace detail + { + template + std::basic_string read_file(iStreamT& inStream) + { + // cache the file + typedef typename iStreamT::char_type charT; + std::basic_string str; + inStream.seekg(0, std::ios::end); + str.resize(static_cast(inStream.tellg())); + if (str.empty()) + return str; + + inStream.seekg(0, std::ios::beg); + inStream.read(&str[0], str.size()); + return str; + } + + /** \brief Read VDF formatted sequences defined by the range [first, last). + If the file is mailformatted, parser will try to read it until it can. + @param first begin iterator + @param end end iterator + @param exclude_files list of files which cant be included anymore. + prevents circular includes + + can thow: + - "std::runtime_error" if a parsing error occured + - "std::bad_alloc" if not enough memory coup be allocated + */ + template + std::vector> + read_internal(IterT first, const IterT last, + std::unordered_set::value_type>>& exclude_files, + const Options& opt) + { + static_assert(std::is_default_constructible::value, + "Output Type must be default constructible (provide constructor " + "without arguments)"); + static_assert(std::is_move_constructible::value, + "Output Type must be move constructible"); + + typedef typename std::iterator_traits::value_type charT; + + const std::basic_string comment_end_str = TYTI_L(charT, "*/"); + const std::basic_string whitespaces = TYTI_L(charT, " \n\v\f\r\t"); + +#ifdef WIN32 + std::function&)> is_platform_str = + [](const std::basic_string& in) { + return in == TYTI_L(charT, "$WIN32") || in == TYTI_L(charT, "$WINDOWS"); + }; +#elif __APPLE__ + // WIN32 stands for pc in general + std::function&)> is_platform_str = + [](const std::basic_string& in) { + return in == TYTI_L(charT, "$WIN32") || in == TYTI_L(charT, "$POSIX") || + in == TYTI_L(charT, "$OSX"); + }; + +#elif __linux__ + // WIN32 stands for pc in general + std::function&)> is_platform_str = + [](const std::basic_string& in) { + return in == TYTI_L(charT, "$WIN32") || in == TYTI_L(charT, "$POSIX") || + in == TYTI_L(charT, "$LINUX"); + }; +#else + std::function&)> is_platform_str = + [](const std::basic_string& in) { + return false; + }; +#endif + + if (opt.ignore_all_platform_conditionals) + is_platform_str = [](const std::basic_string&) { + return false; + }; + + // function for skipping a comment block + // iter: iterator poition to the position after a '/' + auto skip_comments = [&comment_end_str](IterT iter, const IterT& last) -> IterT { + ++iter; + if (iter != last) { + if (*iter == TYTI_L(charT, '/')) { + // line comment, skip whole line + iter = std::find(iter + 1, last, TYTI_L(charT, '\n')); + } + + if (*iter == '*') { + // block comment, skip until next occurance of "*\" + iter = std::search(iter + 1, last, std::begin(comment_end_str), + std::end(comment_end_str)); + iter += 2; + } + } + return iter; + }; + + auto end_quote = [](IterT iter, const IterT& last) -> IterT { + const auto begin = iter; + auto last_esc = iter; + do { + ++iter; + iter = std::find(iter, last, TYTI_L(charT, '\"')); + if (iter == last) + break; + + last_esc = std::prev(iter); + while (last_esc != begin && *last_esc == '\\') + --last_esc; + } while (!(std::distance(last_esc, iter) % 2)); + if (iter == last) + throw std::runtime_error{"quote was opened but not closed."}; + return iter; + }; + + auto end_word = [&whitespaces](IterT iter, const IterT& last) -> IterT { + const auto begin = iter; + auto last_esc = iter; + do { + ++iter; + iter = std::find_first_of(iter, last, std::begin(whitespaces), + std::end(whitespaces)); + if (iter == last) + break; + + last_esc = std::prev(iter); + while (last_esc != begin && *last_esc == '\\') + --last_esc; + } while (!(std::distance(last_esc, iter) % 2)); + // if (iter == last) + // throw std::runtime_error{ "word wasnt properly ended" }; + return iter; + }; + + auto skip_whitespaces = [&whitespaces](IterT iter, const IterT& last) -> IterT { + iter = std::find_if_not(iter, last, [&whitespaces](charT c) { + // return true if whitespace + return std::any_of(std::begin(whitespaces), std::end(whitespaces), + [c](charT pc) { + return pc == c; + }); + }); + return iter; + }; + + std::function&)> strip_escape_symbols = + [](std::basic_string& s) { + auto quote_searcher = [&s](size_t pos) { + return s.find(TYTI_L(charT, "\\\""), pos); + }; + auto p = quote_searcher(0); + while (p != s.npos) { + s.replace(p, 2, TYTI_L(charT, "\"")); + p = quote_searcher(p); + } + auto searcher = [&s](size_t pos) { + return s.find(TYTI_L(charT, "\\\\"), pos); + }; + p = searcher(0); + while (p != s.npos) { + s.replace(p, 2, TYTI_L(charT, "\\")); + p = searcher(p); + } + }; + + if (!opt.strip_escape_symbols) + strip_escape_symbols = [](std::basic_string&) {}; + + auto conditional_fullfilled = [&skip_whitespaces, + &is_platform_str](IterT& iter, const IterT& last) { + iter = skip_whitespaces(iter, last); + if (*iter == '[') { + ++iter; + const auto end = std::find(iter, last, ']'); + const bool negate = *iter == '!'; + if (negate) + ++iter; + auto conditional = std::basic_string(iter, end); + + const bool is_platform = is_platform_str(conditional); + iter = end + 1; + + return static_cast(is_platform ^ negate); + } + return true; + }; + + // read header + // first, quoted name + std::unique_ptr curObj = nullptr; + std::vector> roots; + std::stack> lvls; + auto curIter = first; + + while (curIter != last && *curIter != '\0') { + // find first starting attrib/child, or ending + curIter = skip_whitespaces(curIter, last); + if (curIter == last || *curIter == '\0') + break; + if (*curIter == TYTI_L(charT, '/')) { + curIter = skip_comments(curIter, last); + } else if (*curIter != TYTI_L(charT, '}')) { + + // get key + const auto keyEnd = (*curIter == TYTI_L(charT, '\"')) + ? end_quote(curIter, last) + : end_word(curIter, last); + if (*curIter == TYTI_L(charT, '\"')) + ++curIter; + std::basic_string key(curIter, keyEnd); + strip_escape_symbols(key); + curIter = keyEnd + ((*keyEnd == TYTI_L(charT, '\"')) ? 1 : 0); + + curIter = skip_whitespaces(curIter, last); + + auto conditional = conditional_fullfilled(curIter, last); + if (!conditional) + continue; + + while (*curIter == TYTI_L(charT, '/')) { + + curIter = skip_comments(curIter, last); + if (curIter == last || *curIter == '}') + throw std::runtime_error{"key declared, but no value"}; + curIter = skip_whitespaces(curIter, last); + if (curIter == last || *curIter == '}') + throw std::runtime_error{"key declared, but no value"}; + } + // get value + if (*curIter != '{') { + const auto valueEnd = (*curIter == TYTI_L(charT, '\"')) + ? end_quote(curIter, last) + : end_word(curIter, last); + if (*curIter == TYTI_L(charT, '\"')) + ++curIter; + + auto value = std::basic_string(curIter, valueEnd); + strip_escape_symbols(value); + curIter = valueEnd + ((*valueEnd == TYTI_L(charT, '\"')) ? 1 : 0); + + auto conditional = conditional_fullfilled(curIter, last); + if (!conditional) + continue; + + // process value + if (key != TYTI_L(charT, "#include") && key != TYTI_L(charT, "#base")) { + if (curObj) { + curObj->add_attribute(std::move(key), std::move(value)); + } else { + throw std::runtime_error{"unexpected key without object"}; + } + } else { + if (!opt.ignore_includes && + exclude_files.find(value) == exclude_files.end()) { + exclude_files.insert(value); + std::basic_ifstream i(detail::string_converter(value)); + auto str = read_file(i); + auto file_objs = + read_internal(str.begin(), str.end(), exclude_files, opt); + for (auto& n : file_objs) { + if (curObj) + curObj->add_child(std::move(n)); + else + roots.push_back(std::move(n)); + } + exclude_files.erase(value); + } + } + } else if (*curIter == '{') { + if (curObj) + lvls.push(std::move(curObj)); + curObj = std::make_unique(); + curObj->set_name(std::move(key)); + ++curIter; + } + } + // end of new object + else if (curObj && *curIter == TYTI_L(charT, '}')) { + if (!lvls.empty()) { + // get object before + std::unique_ptr prev{std::move(lvls.top())}; + lvls.pop(); + + // add finished obj to obj before and release it from processing + prev->add_child(std::move(curObj)); + curObj = std::move(prev); + } else { + roots.push_back(std::move(curObj)); + curObj.reset(); + } + ++curIter; + } else { + throw std::runtime_error{"unexpected '}'"}; + } + } + if (curObj != nullptr || !lvls.empty()) { + throw std::runtime_error{"object is not closed with '}'"}; + } + + return roots; + } + + } // namespace detail + + /** \brief Read VDF formatted sequences defined by the range [first, last). + If the file is mailformatted, parser will try to read it until it can. + @param first begin iterator + @param end end iterator + + can thow: + - "std::runtime_error" if a parsing error occured + - "std::bad_alloc" if not enough memory coup be allocated + */ + template + OutputT read(IterT first, const IterT last, const Options& opt = Options{}) + { + auto exclude_files = std::unordered_set< + std::basic_string::value_type>>{}; + auto roots = detail::read_internal(first, last, exclude_files, opt); + + OutputT result; + if (roots.size() > 1) { + for (auto& i : roots) + result.add_child(std::move(i)); + } else if (roots.size() == 1) + result = std::move(*roots[0]); + + return result; + } + + /** \brief Read VDF formatted sequences defined by the range [first, last). + If the file is mailformatted, parser will try to read it until it can. + @param first begin iterator + @param end end iterator + @param ec output bool. 0 if ok, otherwise, holds an system error code + + Possible error codes: + std::errc::protocol_error: file is mailformatted + std::errc::not_enough_memory: not enough space + std::errc::invalid_argument: iterators throws e.g. out of range + */ + template + OutputT read(IterT first, IterT last, std::error_code& ec, + const Options& opt = Options{}) NOEXCEPT + + { + ec.clear(); + OutputT r{}; + try { + r = read(first, last, opt); + } catch (std::runtime_error&) { + ec = std::make_error_code(std::errc::protocol_error); + } catch (std::bad_alloc&) { + ec = std::make_error_code(std::errc::not_enough_memory); + } catch (...) { + ec = std::make_error_code(std::errc::invalid_argument); + } + return r; + } + + /** \brief Read VDF formatted sequences defined by the range [first, last). + If the file is mailformatted, parser will try to read it until it can. + @param first begin iterator + @param end end iterator + @param ok output bool. true, if parser successed, false, if parser failed + */ + template + OutputT read(IterT first, const IterT last, bool* ok, + const Options& opt = Options{}) NOEXCEPT + { + std::error_code ec; + auto r = read(first, last, ec, opt); + if (ok) + *ok = !ec; + return r; + } + + template + inline auto read(IterT first, const IterT last, bool* ok, + const Options& opt = Options{}) NOEXCEPT + ->basic_object::value_type> + { + return read::value_type>>( + first, last, ok, opt); + } + + template + inline auto read(IterT first, IterT last, std::error_code& ec, + const Options& opt = Options{}) NOEXCEPT + ->basic_object::value_type> + { + return read::value_type>>( + first, last, ec, opt); + } + + template + inline auto read(IterT first, const IterT last, const Options& opt = Options{}) + -> basic_object::value_type> + { + return read::value_type>>( + first, last, opt); + } + + /** \brief Loads a stream (e.g. filestream) into the memory and parses the vdf + formatted data. throws "std::bad_alloc" if file buffer could not be allocated + */ + template + OutputT read(iStreamT& inStream, std::error_code& ec, const Options& opt = Options{}) + { + // cache the file + typedef typename iStreamT::char_type charT; + std::basic_string str = detail::read_file(inStream); + + // parse it + return read(str.begin(), str.end(), ec, opt); + } + + template + inline basic_object + read(iStreamT& inStream, std::error_code& ec, const Options& opt = Options{}) + { + return read>(inStream, ec, opt); + } + + /** \brief Loads a stream (e.g. filestream) into the memory and parses the vdf + formatted data. throws "std::bad_alloc" if file buffer could not be allocated ok == + false, if a parsing error occured + */ + template + OutputT read(iStreamT& inStream, bool* ok, const Options& opt = Options{}) + { + std::error_code ec; + const auto r = read(inStream, ec, opt); + if (ok) + *ok = !ec; + return r; + } + + template + inline basic_object read(iStreamT& inStream, bool* ok, + const Options& opt = Options{}) + { + return read>(inStream, ok, opt); + } + + /** \brief Loads a stream (e.g. filestream) into the memory and parses the vdf + formatted data. throws "std::bad_alloc" if file buffer could not be allocated + throws "std::runtime_error" if a parsing error occured + */ + template + OutputT read(iStreamT& inStream, const Options& opt) + { + + // cache the file + typedef typename iStreamT::char_type charT; + std::basic_string str = detail::read_file(inStream); + // parse it + return read(str.begin(), str.end(), opt); + } + + template + inline basic_object read(iStreamT& inStream, + const Options& opt = Options{}) + { + return read>(inStream, opt); + } + +} // namespace vdf +} // namespace tyti +#ifndef TYTI_NO_L_UNDEF +#undef TYTI_L +#endif + +#ifdef TYTI_UNDEF_CONSTEXPR +#undef CONSTEXPR +#undef TYTI_NO_L_UNDEF +#endif + +#ifdef TYTI_UNDEF_NOTHROW +#undef NOTHROW +#undef TYTI_UNDEF_NOTHROW +#endif + +#endif //__TYTI_STEAM_VDF_PARSER_H__ From 4514b1048bf02da990ccb8eaacf52e9f8fd4f9ed Mon Sep 17 00:00:00 2001 From: Jeremy Rimpo Date: Thu, 28 Sep 2023 11:25:05 -0500 Subject: [PATCH 1357/1544] [game_falloutnv] Preliminary EPIC Games support - Requires gamebryo game detection pull request --- src/games/falloutnv/src/gamefalloutnv.cpp | 226 ++++++++++++++++------ src/games/falloutnv/src/gamefalloutnv.h | 70 ++++--- 2 files changed, 203 insertions(+), 93 deletions(-) diff --git a/src/games/falloutnv/src/gamefalloutnv.cpp b/src/games/falloutnv/src/gamefalloutnv.cpp index b4e637eb..d92c891f 100644 --- a/src/games/falloutnv/src/gamefalloutnv.cpp +++ b/src/games/falloutnv/src/gamefalloutnv.cpp @@ -31,164 +31,262 @@ GameFalloutNV::GameFalloutNV() { } -bool GameFalloutNV::init(IOrganizer *moInfo) +bool GameFalloutNV::init(IOrganizer* moInfo) { - if (!GameGamebryo::init(moInfo)) { - return false; - } - registerFeature(new FalloutNVScriptExtender(this)); - registerFeature(new FalloutNVDataArchives(myGamesPath())); - registerFeature(new FalloutNVBSAInvalidation(feature(), this)); - registerFeature(new GamebryoSaveGameInfo(this)); - registerFeature(new GamebryoLocalSavegames(myGamesPath(), "fallout.ini")); - registerFeature(new FalloutNVModDataChecker(this)); - registerFeature(new FalloutNVModDataContent(this)); - registerFeature(new GamebryoGamePlugins(moInfo)); - registerFeature(new GamebryoUnmangedMods(this)); - return true; + if (!GameGamebryo::init(moInfo)) { + return false; + } + registerFeature(new FalloutNVScriptExtender(this)); + registerFeature(new FalloutNVDataArchives(myGamesPath())); + registerFeature(new FalloutNVBSAInvalidation(feature(), this)); + registerFeature(new GamebryoSaveGameInfo(this)); + registerFeature(new GamebryoLocalSavegames(myGamesPath(), "fallout.ini")); + registerFeature(new FalloutNVModDataChecker(this)); + registerFeature(new FalloutNVModDataContent(this)); + registerFeature(new GamebryoGamePlugins(moInfo)); + registerFeature(new GamebryoUnmangedMods(this)); + return true; +} + +void GameFalloutNV::setVariant(QString variant) +{ + m_GameVariant = variant; +} + +void GameFalloutNV::checkVariants() +{ + QFileInfo gog_dll(m_GamePath + "\\Galaxy64.dll"); + QFileInfo epic_dll(m_GamePath + "\\EOSSDK-Win32-Shipping.dll"); + if (epic_dll.exists()) + setVariant("Epic Games"); + else + setVariant("Steam"); +} + +QDir GameFalloutNV::documentsDirectory() const +{ + return m_MyGamesPath; +} + +QString GameFalloutNV::identifyGamePath() const +{ + auto result = GameGamebryo::identifyGamePath(); // Default registry path + // 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" }); + } + return result; +} + +void GameFalloutNV::setGamePath(const QString& path) +{ + m_GamePath = path; + checkVariants(); + m_MyGamesPath = determineMyGamesPath(gameDirectoryName()); + registerFeature(new FalloutNVDataArchives(myGamesPath())); + registerFeature(new GamebryoLocalSavegames(myGamesPath(), "fallout.ini")); +} + +QDir GameFalloutNV::savesDirectory() const +{ + return QDir(m_MyGamesPath + "/Saves"); +} + +QString GameFalloutNV::myGamesPath() const +{ + return m_MyGamesPath; +} + +bool GameFalloutNV::isInstalled() const +{ + return !m_GamePath.isEmpty(); } QString GameFalloutNV::gameName() const { - return "New Vegas"; + return "New Vegas"; +} + +QString GameFalloutNV::gameDirectoryName() const +{ + if (selectedVariant() == "GOG") + return "Skyrim Special Edition GOG"; + else if (selectedVariant() == "Epic Games") + return "Skyrim Special Edition EPIC"; + else + return "Skyrim Special Edition"; } void GameFalloutNV::detectGame() { - m_GamePath = identifyGamePath(); - m_MyGamesPath = determineMyGamesPath("FalloutNV"); + m_GamePath = identifyGamePath(); + m_MyGamesPath = determineMyGamesPath("FalloutNV"); } QList GameFalloutNV::executables() const { - return QList() - << ExecutableInfo("NVSE", findInGameFolder(feature()->loaderName())) - << ExecutableInfo("New Vegas", findInGameFolder(binaryName())) - << ExecutableInfo("Fallout Mod Manager", findInGameFolder("fomm/fomm.exe")) - << ExecutableInfo("Construction Kit", findInGameFolder("geck.exe")) - << ExecutableInfo("Fallout Launcher", findInGameFolder(getLauncherName())) - << ExecutableInfo("BOSS", findInGameFolder("BOSS/BOSS.exe")) - << ExecutableInfo("LOOT", QFileInfo(getLootPath())).withArgument("--game=\"FalloutNV\"") - ; + return QList() + << ExecutableInfo("NVSE", findInGameFolder(feature()->loaderName())) + << ExecutableInfo("New Vegas", findInGameFolder(binaryName())) + << ExecutableInfo("Fallout Mod Manager", findInGameFolder("fomm/fomm.exe")) + << ExecutableInfo("Construction Kit", findInGameFolder("geck.exe")) + << ExecutableInfo("Fallout Launcher", findInGameFolder(getLauncherName())) + << ExecutableInfo("BOSS", findInGameFolder("BOSS/BOSS.exe")) + << ExecutableInfo("LOOT", QFileInfo(getLootPath())).withArgument("--game=\"FalloutNV\"") + ; } QList GameFalloutNV::executableForcedLoads() const { - return QList(); + return QList(); } QString GameFalloutNV::name() const { - return "Fallout NV Support Plugin"; + return "Fallout NV Support Plugin"; } QString GameFalloutNV::localizedName() const { - return tr("Fallout NV Support Plugin"); + return tr("Fallout NV Support Plugin"); } QString GameFalloutNV::author() const { - return "Tannin"; + return "Tannin"; } QString GameFalloutNV::description() const { - return tr("Adds support for the game Fallout New Vegas"); + return tr("Adds support for the game Fallout New Vegas"); } MOBase::VersionInfo GameFalloutNV::version() const { - return VersionInfo(1, 5, 1, VersionInfo::RELEASE_FINAL); + return VersionInfo(1, 5, 1, VersionInfo::RELEASE_FINAL); } QList GameFalloutNV::settings() const { - return QList(); + return QList(); } -void GameFalloutNV::initializeProfile(const QDir &path, ProfileSettings settings) const +void GameFalloutNV::initializeProfile(const QDir& path, ProfileSettings settings) const { - if (settings.testFlag(IPluginGame::MODS)) { - copyToProfile(localAppFolder() + "/FalloutNV", path, "plugins.txt"); - } + if (settings.testFlag(IPluginGame::MODS)) { + copyToProfile(localAppFolder() + "/FalloutNV", 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"); - } + 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, "custom.ini"); - copyToProfile(myGamesPath(), path, "GECKCustom.ini"); - copyToProfile(myGamesPath(), path, "GECKPrefs.ini"); + copyToProfile(myGamesPath(), path, "falloutprefs.ini"); + copyToProfile(myGamesPath(), path, "falloutcustom.ini"); + copyToProfile(myGamesPath(), path, "custom.ini"); + copyToProfile(myGamesPath(), path, "GECKCustom.ini"); + copyToProfile(myGamesPath(), path, "GECKPrefs.ini"); - } + } } QString GameFalloutNV::savegameExtension() const { - return "fos"; + return "fos"; } QString GameFalloutNV::savegameSEExtension() const { - return "nvse"; + return "nvse"; } std::shared_ptr GameFalloutNV::makeSaveGame(QString filePath) const { - return std::make_shared(filePath, this); + return std::make_shared(filePath, this); } QString GameFalloutNV::steamAPPId() const { - return "22380"; + return "22380"; } QStringList GameFalloutNV::primaryPlugins() const { - return { "falloutnv.esm" }; + return { "falloutnv.esm" }; +} + +QStringList GameFalloutNV::gameVariants() const +{ + return { "Steam", "Epic Games" }; } QString GameFalloutNV::gameShortName() const { - return "FalloutNV"; + return "FalloutNV"; } QStringList GameFalloutNV::validShortNames() const { - return { "Fallout3" }; + return { "Fallout3" }; } QString GameFalloutNV::gameNexusName() const { - return "newvegas"; + return "newvegas"; } QStringList GameFalloutNV::iniFiles() const { - return { "fallout.ini", "falloutprefs.ini", "falloutcustom.ini", "custom.ini", "GECKCustom.ini", "GECKPrefs.ini"}; + return { "fallout.ini", "falloutprefs.ini", "falloutcustom.ini", "custom.ini", "GECKCustom.ini", "GECKPrefs.ini" }; } QStringList GameFalloutNV::DLCPlugins() const { - return { "DeadMoney.esm", "HonestHearts.esm", "OldWorldBlues.esm", - "LonesomeRoad.esm", "GunRunnersArsenal.esm", "CaravanPack.esm", - "ClassicPack.esm", "MercenaryPack.esm", "TribalPack.esm" }; + return { "DeadMoney.esm", "HonestHearts.esm", "OldWorldBlues.esm", + "LonesomeRoad.esm", "GunRunnersArsenal.esm", "CaravanPack.esm", + "ClassicPack.esm", "MercenaryPack.esm", "TribalPack.esm" }; } int GameFalloutNV::nexusModOrganizerID() const { - return 42572; + return 42572; } int GameFalloutNV::nexusGameID() const { - return 130; + return 130; +} + +QDir GameFalloutNV::gameDirectory() const +{ + return QDir(m_GamePath); +} + +// Not to delete all the spaces... +MappingType GameFalloutNV::mappings() const +{ + MappingType result; + + for (const QString& profileFile : { "plugins.txt", "loadorder.txt" }) { + result.push_back({ m_Organizer->profilePath() + "/" + profileFile, + localAppFolder() + "/" + gameDirectoryName() + "/" + profileFile, + false }); + } + + return result; } diff --git a/src/games/falloutnv/src/gamefalloutnv.h b/src/games/falloutnv/src/gamefalloutnv.h index ee37ec2b..582bd3c7 100644 --- a/src/games/falloutnv/src/gamefalloutnv.h +++ b/src/games/falloutnv/src/gamefalloutnv.h @@ -8,48 +8,60 @@ class GameFalloutNV : public GameGamebryo { - Q_OBJECT + Q_OBJECT #if QT_VERSION >= QT_VERSION_CHECK(5,0,0) - Q_PLUGIN_METADATA(IID "org.tannin.GameFalloutNV" FILE "gamefalloutnv.json") + Q_PLUGIN_METADATA(IID "org.tannin.GameFalloutNV" FILE "gamefalloutnv.json") #endif public: + GameFalloutNV(); - GameFalloutNV(); - - virtual bool init(MOBase::IOrganizer *moInfo) override; + virtual bool init(MOBase::IOrganizer* moInfo) override; public: // IPluginGame interface + virtual QString gameName() const override; + virtual void detectGame() override; + virtual QList executables() const override; + virtual QList 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 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 QString gameName() const override; - virtual void detectGame() override; - virtual QList executables() const override; - virtual QList executableForcedLoads() const override; - virtual void initializeProfile(const QDir &path, ProfileSettings settings) const override; - virtual QString steamAPPId() const override; - virtual QStringList primaryPlugins() 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 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 settings() const override; + 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 settings() const override; + virtual MappingType mappings() const override; protected: + QString gameDirectoryName() const; + QDir documentsDirectory() const; + QDir savesDirectory() const; + QString myGamesPath() const; - virtual QString savegameExtension() const override; - virtual QString savegameSEExtension() const override; - std::shared_ptr makeSaveGame(QString filePath) const override; + 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 makeSaveGame(QString filePath) const override; }; From b2e29b6fc3a202ca36fe9f01fadd8a121b25373d Mon Sep 17 00:00:00 2001 From: Jeremy Rimpo Date: Thu, 28 Sep 2023 11:31:20 -0500 Subject: [PATCH 1358/1544] [game_skyrimse] Revert "Consolidate game search code in Gamebryo" This reverts commit 2300ce09ae05399d57631de88dcaa820d82a6dcf. --- src/games/skyrimse/src/gameskyrimse.cpp | 35 +++++++++++++++++++++++-- 1 file changed, 33 insertions(+), 2 deletions(-) diff --git a/src/games/skyrimse/src/gameskyrimse.cpp b/src/games/skyrimse/src/gameskyrimse.cpp index ad612659..194c7446 100644 --- a/src/games/skyrimse/src/gameskyrimse.cpp +++ b/src/games/skyrimse/src/gameskyrimse.cpp @@ -81,8 +81,39 @@ QString GameSkyrimSE::identifyGamePath() const // AppName: ac82db5035584c7f8a2c548d98c86b2c // AE Update: 5d600e4f59974aeba0259c7734134e27 if (result.isEmpty()) { - result = parseEpicGamesLocation( - {"ac82db5035584c7f8a2c548d98c86b2c", "5d600e4f59974aeba0259c7734134e27"}); + // Use the registry entry to find the EGL Data dir first, just in case something + // changes + QString manifestDir = findInRegistry( + HKEY_LOCAL_MACHINE, L"SOFTWARE\\WOW6432Node\\Epic Games\\EpicGamesLauncher", + L"AppDataPath"); + if (manifestDir.isEmpty()) + manifestDir = getKnownFolderPath(FOLDERID_ProgramData, false) + + "\\Epic\\EpicGamesLauncher\\Data\\"; + manifestDir += "Manifests"; + QDir epicManifests(manifestDir, "*.item", + QDir::SortFlags(QDir::Name | QDir::IgnoreCase), QDir::Files); + if (epicManifests.exists()) { + QDirIterator it(epicManifests); + while (it.hasNext()) { + QString manifestFile = it.next(); + QFile manifest(manifestFile); + + if (!manifest.open(QIODevice::ReadOnly)) { + qWarning("Couldn't open Epic Games manifest file."); + continue; + } + + QByteArray manifestData = manifest.readAll(); + + QJsonDocument manifestJson(QJsonDocument::fromJson(manifestData)); + + if (manifestJson["AppName"] == "ac82db5035584c7f8a2c548d98c86b2c" || + manifestJson["AppName"] == "5d600e4f59974aeba0259c7734134e27") { + result = manifestJson["InstallLocation"].toString(); + break; + } + } + } } return result; From b56dec76645186c8fe59a0609de699e9f58af748 Mon Sep 17 00:00:00 2001 From: Jeremy Rimpo Date: Thu, 28 Sep 2023 11:33:41 -0500 Subject: [PATCH 1359/1544] [game_skyrimse] Revert "Revert "Consolidate game search code in Gamebryo"" This reverts commit b2e29b6fc3a202ca36fe9f01fadd8a121b25373d. --- src/games/skyrimse/src/gameskyrimse.cpp | 35 ++----------------------- 1 file changed, 2 insertions(+), 33 deletions(-) diff --git a/src/games/skyrimse/src/gameskyrimse.cpp b/src/games/skyrimse/src/gameskyrimse.cpp index 194c7446..ad612659 100644 --- a/src/games/skyrimse/src/gameskyrimse.cpp +++ b/src/games/skyrimse/src/gameskyrimse.cpp @@ -81,39 +81,8 @@ QString GameSkyrimSE::identifyGamePath() const // AppName: ac82db5035584c7f8a2c548d98c86b2c // AE Update: 5d600e4f59974aeba0259c7734134e27 if (result.isEmpty()) { - // Use the registry entry to find the EGL Data dir first, just in case something - // changes - QString manifestDir = findInRegistry( - HKEY_LOCAL_MACHINE, L"SOFTWARE\\WOW6432Node\\Epic Games\\EpicGamesLauncher", - L"AppDataPath"); - if (manifestDir.isEmpty()) - manifestDir = getKnownFolderPath(FOLDERID_ProgramData, false) + - "\\Epic\\EpicGamesLauncher\\Data\\"; - manifestDir += "Manifests"; - QDir epicManifests(manifestDir, "*.item", - QDir::SortFlags(QDir::Name | QDir::IgnoreCase), QDir::Files); - if (epicManifests.exists()) { - QDirIterator it(epicManifests); - while (it.hasNext()) { - QString manifestFile = it.next(); - QFile manifest(manifestFile); - - if (!manifest.open(QIODevice::ReadOnly)) { - qWarning("Couldn't open Epic Games manifest file."); - continue; - } - - QByteArray manifestData = manifest.readAll(); - - QJsonDocument manifestJson(QJsonDocument::fromJson(manifestData)); - - if (manifestJson["AppName"] == "ac82db5035584c7f8a2c548d98c86b2c" || - manifestJson["AppName"] == "5d600e4f59974aeba0259c7734134e27") { - result = manifestJson["InstallLocation"].toString(); - break; - } - } - } + result = parseEpicGamesLocation( + {"ac82db5035584c7f8a2c548d98c86b2c", "5d600e4f59974aeba0259c7734134e27"}); } return result; From 9af2d2b4ab5b333fd2737be325f5d4007d40836e Mon Sep 17 00:00:00 2001 From: Jeremy Rimpo Date: Thu, 28 Sep 2023 11:53:25 -0500 Subject: [PATCH 1360/1544] [game_falloutnv] Additional fixes --- src/games/falloutnv/src/gamefalloutnv.cpp | 588 +++++++++++----------- 1 file changed, 296 insertions(+), 292 deletions(-) diff --git a/src/games/falloutnv/src/gamefalloutnv.cpp b/src/games/falloutnv/src/gamefalloutnv.cpp index d92c891f..1eea113a 100644 --- a/src/games/falloutnv/src/gamefalloutnv.cpp +++ b/src/games/falloutnv/src/gamefalloutnv.cpp @@ -1,292 +1,296 @@ -#include "gamefalloutnv.h" - -#include "falloutnvbsainvalidation.h" -#include "falloutnvdataarchives.h" -#include "falloutnvscriptextender.h" -#include "falloutnvmoddatachecker.h" -#include "falloutnvmoddatacontent.h" -#include "falloutnvsavegame.h" - -#include "executableinfo.h" -#include "pluginsetting.h" -#include "versioninfo.h" -#include -#include -#include -#include - -#include -#include -#include -#include -#include -#include -#include - -#include - -using namespace MOBase; - -GameFalloutNV::GameFalloutNV() -{ -} - -bool GameFalloutNV::init(IOrganizer* moInfo) -{ - if (!GameGamebryo::init(moInfo)) { - return false; - } - registerFeature(new FalloutNVScriptExtender(this)); - registerFeature(new FalloutNVDataArchives(myGamesPath())); - registerFeature(new FalloutNVBSAInvalidation(feature(), this)); - registerFeature(new GamebryoSaveGameInfo(this)); - registerFeature(new GamebryoLocalSavegames(myGamesPath(), "fallout.ini")); - registerFeature(new FalloutNVModDataChecker(this)); - registerFeature(new FalloutNVModDataContent(this)); - registerFeature(new GamebryoGamePlugins(moInfo)); - registerFeature(new GamebryoUnmangedMods(this)); - return true; -} - -void GameFalloutNV::setVariant(QString variant) -{ - m_GameVariant = variant; -} - -void GameFalloutNV::checkVariants() -{ - QFileInfo gog_dll(m_GamePath + "\\Galaxy64.dll"); - QFileInfo epic_dll(m_GamePath + "\\EOSSDK-Win32-Shipping.dll"); - if (epic_dll.exists()) - setVariant("Epic Games"); - else - setVariant("Steam"); -} - -QDir GameFalloutNV::documentsDirectory() const -{ - return m_MyGamesPath; -} - -QString GameFalloutNV::identifyGamePath() const -{ - auto result = GameGamebryo::identifyGamePath(); // Default registry path - // 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" }); - } - return result; -} - -void GameFalloutNV::setGamePath(const QString& path) -{ - m_GamePath = path; - checkVariants(); - m_MyGamesPath = determineMyGamesPath(gameDirectoryName()); - registerFeature(new FalloutNVDataArchives(myGamesPath())); - registerFeature(new GamebryoLocalSavegames(myGamesPath(), "fallout.ini")); -} - -QDir GameFalloutNV::savesDirectory() const -{ - return QDir(m_MyGamesPath + "/Saves"); -} - -QString GameFalloutNV::myGamesPath() const -{ - return m_MyGamesPath; -} - -bool GameFalloutNV::isInstalled() const -{ - return !m_GamePath.isEmpty(); -} - -QString GameFalloutNV::gameName() const -{ - return "New Vegas"; -} - -QString GameFalloutNV::gameDirectoryName() const -{ - if (selectedVariant() == "GOG") - return "Skyrim Special Edition GOG"; - else if (selectedVariant() == "Epic Games") - return "Skyrim Special Edition EPIC"; - else - return "Skyrim Special Edition"; -} - -void GameFalloutNV::detectGame() -{ - m_GamePath = identifyGamePath(); - m_MyGamesPath = determineMyGamesPath("FalloutNV"); -} - -QList GameFalloutNV::executables() const -{ - return QList() - << ExecutableInfo("NVSE", findInGameFolder(feature()->loaderName())) - << ExecutableInfo("New Vegas", findInGameFolder(binaryName())) - << ExecutableInfo("Fallout Mod Manager", findInGameFolder("fomm/fomm.exe")) - << ExecutableInfo("Construction Kit", findInGameFolder("geck.exe")) - << ExecutableInfo("Fallout Launcher", findInGameFolder(getLauncherName())) - << ExecutableInfo("BOSS", findInGameFolder("BOSS/BOSS.exe")) - << ExecutableInfo("LOOT", QFileInfo(getLootPath())).withArgument("--game=\"FalloutNV\"") - ; -} - -QList GameFalloutNV::executableForcedLoads() const -{ - return QList(); -} - -QString GameFalloutNV::name() const -{ - return "Fallout NV Support Plugin"; -} - -QString GameFalloutNV::localizedName() const -{ - return tr("Fallout NV Support Plugin"); -} - - -QString GameFalloutNV::author() const -{ - return "Tannin"; -} - -QString GameFalloutNV::description() const -{ - return tr("Adds support for the game Fallout New Vegas"); -} - -MOBase::VersionInfo GameFalloutNV::version() const -{ - return VersionInfo(1, 5, 1, VersionInfo::RELEASE_FINAL); -} - -QList GameFalloutNV::settings() const -{ - return QList(); -} - -void GameFalloutNV::initializeProfile(const QDir& path, ProfileSettings settings) const -{ - if (settings.testFlag(IPluginGame::MODS)) { - copyToProfile(localAppFolder() + "/FalloutNV", 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, "custom.ini"); - copyToProfile(myGamesPath(), path, "GECKCustom.ini"); - copyToProfile(myGamesPath(), path, "GECKPrefs.ini"); - - } -} - -QString GameFalloutNV::savegameExtension() const -{ - return "fos"; -} - -QString GameFalloutNV::savegameSEExtension() const -{ - return "nvse"; -} - -std::shared_ptr GameFalloutNV::makeSaveGame(QString filePath) const -{ - return std::make_shared(filePath, this); -} - -QString GameFalloutNV::steamAPPId() const -{ - return "22380"; -} - -QStringList GameFalloutNV::primaryPlugins() const -{ - return { "falloutnv.esm" }; -} - -QStringList GameFalloutNV::gameVariants() const -{ - return { "Steam", "Epic Games" }; -} - -QString GameFalloutNV::gameShortName() const -{ - return "FalloutNV"; -} - -QStringList GameFalloutNV::validShortNames() const -{ - return { "Fallout3" }; -} - -QString GameFalloutNV::gameNexusName() const -{ - return "newvegas"; -} - -QStringList GameFalloutNV::iniFiles() const -{ - return { "fallout.ini", "falloutprefs.ini", "falloutcustom.ini", "custom.ini", "GECKCustom.ini", "GECKPrefs.ini" }; -} - -QStringList GameFalloutNV::DLCPlugins() const -{ - return { "DeadMoney.esm", "HonestHearts.esm", "OldWorldBlues.esm", - "LonesomeRoad.esm", "GunRunnersArsenal.esm", "CaravanPack.esm", - "ClassicPack.esm", "MercenaryPack.esm", "TribalPack.esm" }; -} - -int GameFalloutNV::nexusModOrganizerID() const -{ - return 42572; -} - -int GameFalloutNV::nexusGameID() const -{ - return 130; -} - -QDir GameFalloutNV::gameDirectory() const -{ - return QDir(m_GamePath); -} - -// Not to delete all the spaces... -MappingType GameFalloutNV::mappings() const -{ - MappingType result; - - for (const QString& profileFile : { "plugins.txt", "loadorder.txt" }) { - result.push_back({ m_Organizer->profilePath() + "/" + profileFile, - localAppFolder() + "/" + gameDirectoryName() + "/" + profileFile, - false }); - } - - return result; -} +#include "gamefalloutnv.h" + +#include "falloutnvbsainvalidation.h" +#include "falloutnvdataarchives.h" +#include "falloutnvscriptextender.h" +#include "falloutnvmoddatachecker.h" +#include "falloutnvmoddatacontent.h" +#include "falloutnvsavegame.h" + +#include "executableinfo.h" +#include "pluginsetting.h" +#include "versioninfo.h" +#include +#include +#include +#include + +#include +#include +#include +#include +#include +#include +#include + +#include + +using namespace MOBase; + +GameFalloutNV::GameFalloutNV() +{ +} + +bool GameFalloutNV::init(IOrganizer* moInfo) +{ + if (!GameGamebryo::init(moInfo)) { + return false; + } + registerFeature(new FalloutNVScriptExtender(this)); + registerFeature(new FalloutNVDataArchives(myGamesPath())); + registerFeature(new FalloutNVBSAInvalidation(feature(), this)); + registerFeature(new GamebryoSaveGameInfo(this)); + registerFeature(new GamebryoLocalSavegames(myGamesPath(), "fallout.ini")); + registerFeature(new FalloutNVModDataChecker(this)); + registerFeature(new FalloutNVModDataContent(this)); + registerFeature(new GamebryoGamePlugins(moInfo)); + registerFeature(new GamebryoUnmangedMods(this)); + return true; +} + +void GameFalloutNV::setVariant(QString variant) +{ + m_GameVariant = variant; +} + +void GameFalloutNV::checkVariants() +{ + QFileInfo gog_dll(m_GamePath + "\\Galaxy64.dll"); + QFileInfo epic_dll(m_GamePath + "\\EOSSDK-Win32-Shipping.dll"); + if (epic_dll.exists()) + setVariant("Epic Games"); + else + setVariant("Steam"); +} + +QDir GameFalloutNV::documentsDirectory() const +{ + return m_MyGamesPath; +} + +QString GameFalloutNV::identifyGamePath() const +{ + auto result = GameGamebryo::identifyGamePath(); // Default registry path + // 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" }); + } + return result; +} + +void GameFalloutNV::setGamePath(const QString& path) +{ + m_GamePath = path; + checkVariants(); + m_MyGamesPath = determineMyGamesPath(gameDirectoryName()); + registerFeature(new FalloutNVDataArchives(myGamesPath())); + registerFeature(new GamebryoLocalSavegames(myGamesPath(), "fallout.ini")); +} + +QDir GameFalloutNV::savesDirectory() const +{ + return QDir(m_MyGamesPath + "/Saves"); +} + +QString GameFalloutNV::myGamesPath() const +{ + return m_MyGamesPath; +} + +bool GameFalloutNV::isInstalled() const +{ + return !m_GamePath.isEmpty(); +} + +QString GameFalloutNV::gameName() const +{ + return "New Vegas"; +} + +QString GameFalloutNV::gameDirectoryName() const +{ + if (selectedVariant() == "Epic Games") + return "FalloutNV_Epic"; + else + return "FalloutNV_Epic"; +} + +void GameFalloutNV::detectGame() +{ + m_GamePath = identifyGamePath(); + checkVariants(); + m_MyGamesPath = determineMyGamesPath(gameDirectoryName()); +} + +QList GameFalloutNV::executables() const +{ + QList executables = + QList() + << ExecutableInfo("New Vegas", findInGameFolder(binaryName())) + << ExecutableInfo("Fallout Mod Manager", findInGameFolder("fomm/fomm.exe")) + << ExecutableInfo("Construction Kit", findInGameFolder("geck.exe")) + << ExecutableInfo("Fallout Launcher", findInGameFolder(getLauncherName())) + << ExecutableInfo("BOSS", findInGameFolder("BOSS/BOSS.exe")) + << ExecutableInfo("LOOT", QFileInfo(getLootPath())) + .withArgument("--game=\"FalloutNV\""); + if (selectedVariant() == "Epic Games") { + executables.append(ExecutableInfo( + "NVSE", findInGameFolder(feature()->loaderName()))); + } + return executables; +} + +QList GameFalloutNV::executableForcedLoads() const +{ + return QList(); +} + +QString GameFalloutNV::name() const +{ + return "Fallout NV Support Plugin"; +} + +QString GameFalloutNV::localizedName() const +{ + return tr("Fallout NV Support Plugin"); +} + + +QString GameFalloutNV::author() const +{ + return "Tannin"; +} + +QString GameFalloutNV::description() const +{ + return tr("Adds support for the game Fallout New Vegas"); +} + +MOBase::VersionInfo GameFalloutNV::version() const +{ + return VersionInfo(1, 5, 2, VersionInfo::RELEASE_FINAL); +} + +QList GameFalloutNV::settings() const +{ + return QList(); +} + +void GameFalloutNV::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, "custom.ini"); + copyToProfile(myGamesPath(), path, "GECKCustom.ini"); + copyToProfile(myGamesPath(), path, "GECKPrefs.ini"); + + } +} + +QString GameFalloutNV::savegameExtension() const +{ + return "fos"; +} + +QString GameFalloutNV::savegameSEExtension() const +{ + return "nvse"; +} + +std::shared_ptr GameFalloutNV::makeSaveGame(QString filePath) const +{ + return std::make_shared(filePath, this); +} + +QString GameFalloutNV::steamAPPId() const +{ + return "22380"; +} + +QStringList GameFalloutNV::primaryPlugins() const +{ + return { "falloutnv.esm" }; +} + +QStringList GameFalloutNV::gameVariants() const +{ + return { "Steam", "Epic Games" }; +} + +QString GameFalloutNV::gameShortName() const +{ + return "FalloutNV"; +} + +QStringList GameFalloutNV::validShortNames() const +{ + return { "Fallout3" }; +} + +QString GameFalloutNV::gameNexusName() const +{ + return "newvegas"; +} + +QStringList GameFalloutNV::iniFiles() const +{ + return { "fallout.ini", "falloutprefs.ini", "falloutcustom.ini", "custom.ini", "GECKCustom.ini", "GECKPrefs.ini" }; +} + +QStringList GameFalloutNV::DLCPlugins() const +{ + return { "DeadMoney.esm", "HonestHearts.esm", "OldWorldBlues.esm", + "LonesomeRoad.esm", "GunRunnersArsenal.esm", "CaravanPack.esm", + "ClassicPack.esm", "MercenaryPack.esm", "TribalPack.esm" }; +} + +int GameFalloutNV::nexusModOrganizerID() const +{ + return 42572; +} + +int GameFalloutNV::nexusGameID() const +{ + return 130; +} + +QDir GameFalloutNV::gameDirectory() const +{ + return QDir(m_GamePath); +} + +// Not to delete all the spaces... +MappingType GameFalloutNV::mappings() const +{ + MappingType result; + + for (const QString& profileFile : { "plugins.txt", "loadorder.txt" }) { + result.push_back({ m_Organizer->profilePath() + "/" + profileFile, + localAppFolder() + "/" + gameDirectoryName() + "/" + profileFile, + false }); + } + + return result; +} From 0927d26723a215f258c9a04baac95f5d24e8c5c8 Mon Sep 17 00:00:00 2001 From: Jeremy Rimpo Date: Thu, 28 Sep 2023 11:54:50 -0500 Subject: [PATCH 1361/1544] [game_falloutnv] Cleanup code and add CI --- src/games/falloutnv/.clang-format | 41 ++++ src/games/falloutnv/.gitattributes | 7 + .../falloutnv/.github/workflows/build.yml | 16 ++ .../falloutnv/.github/workflows/linting.yml | 17 ++ src/games/falloutnv/appveyor.yml | 40 ---- src/games/falloutnv/src/SConscript | 13 -- .../src/falloutnvbsainvalidation.cpp | 32 +-- .../falloutnv/src/falloutnvbsainvalidation.h | 42 ++-- .../falloutnv/src/falloutnvdataarchives.cpp | 69 ++++--- .../falloutnv/src/falloutnvdataarchives.h | 49 +++-- .../falloutnv/src/falloutnvmoddatachecker.h | 22 +- .../falloutnv/src/falloutnvmoddatacontent.h | 13 +- src/games/falloutnv/src/falloutnvsavegame.cpp | 44 ++-- src/games/falloutnv/src/falloutnvsavegame.h | 17 +- .../falloutnv/src/falloutnvscriptextender.cpp | 37 ++-- .../falloutnv/src/falloutnvscriptextender.h | 35 ++-- src/games/falloutnv/src/gameFalloutNV.pro | 50 ----- src/games/falloutnv/src/game_falloutNV_en.ts | 165 +-------------- src/games/falloutnv/src/gamefalloutnv.cpp | 193 +++++++++--------- src/games/falloutnv/src/gamefalloutnv.h | 137 +++++++------ 20 files changed, 423 insertions(+), 616 deletions(-) create mode 100644 src/games/falloutnv/.clang-format create mode 100644 src/games/falloutnv/.gitattributes create mode 100644 src/games/falloutnv/.github/workflows/build.yml create mode 100644 src/games/falloutnv/.github/workflows/linting.yml delete mode 100644 src/games/falloutnv/appveyor.yml delete mode 100644 src/games/falloutnv/src/SConscript delete mode 100644 src/games/falloutnv/src/gameFalloutNV.pro diff --git a/src/games/falloutnv/.clang-format b/src/games/falloutnv/.clang-format new file mode 100644 index 00000000..6098e1f5 --- /dev/null +++ b/src/games/falloutnv/.clang-format @@ -0,0 +1,41 @@ +--- +# We'll use defaults from the LLVM style, but with 4 columns indentation. +BasedOnStyle: LLVM +IndentWidth: 2 +--- +Language: Cpp +DeriveLineEnding: false +UseCRLF: true +DerivePointerAlignment: false +PointerAlignment: Left +AlignConsecutiveAssignments: true +AllowShortFunctionsOnASingleLine: Inline +AllowShortIfStatementsOnASingleLine: Never +AllowShortLambdasOnASingleLine: Empty +AlwaysBreakTemplateDeclarations: Yes +AccessModifierOffset: -2 +AlignTrailingComments: true +SpacesBeforeTrailingComments: 2 +NamespaceIndentation: Inner +MaxEmptyLinesToKeep: 1 +BreakBeforeBraces: Custom +BraceWrapping: + AfterCaseLabel: false + AfterClass: true + AfterControlStatement: false + AfterEnum: true + AfterFunction: true + AfterNamespace: true + AfterStruct: true + AfterUnion: true + AfterExternBlock: true + BeforeCatch: false + BeforeElse: false + BeforeLambdaBody: false + BeforeWhile: false + IndentBraces: false + SplitEmptyFunction: false + SplitEmptyRecord: false + SplitEmptyNamespace: true +ColumnLimit: 88 +ForEachMacros: ['Q_FOREACH', 'foreach'] diff --git a/src/games/falloutnv/.gitattributes b/src/games/falloutnv/.gitattributes new file mode 100644 index 00000000..f8697127 --- /dev/null +++ b/src/games/falloutnv/.gitattributes @@ -0,0 +1,7 @@ +# Set the default behavior, in case people don't have core.autocrlf set. +* text=auto + +# Explicitly declare text files you want to always be normalized and converted +# to native line endings on checkout. +*.cpp text eol=crlf +*.h text eol=crlf diff --git a/src/games/falloutnv/.github/workflows/build.yml b/src/games/falloutnv/.github/workflows/build.yml new file mode 100644 index 00000000..7c3f446b --- /dev/null +++ b/src/games/falloutnv/.github/workflows/build.yml @@ -0,0 +1,16 @@ +name: Build Fallout NV Plugin + +on: + push: + branches: master + pull_request: + types: [opened, synchronize, reopened] + +jobs: + build: + runs-on: windows-2022 + steps: + - name: Build Fallout NV Plugin + uses: ModOrganizer2/build-with-mob-action@master + with: + mo2-dependencies: cmake_common uibase game_gamebryo diff --git a/src/games/falloutnv/.github/workflows/linting.yml b/src/games/falloutnv/.github/workflows/linting.yml new file mode 100644 index 00000000..5b9b6d71 --- /dev/null +++ b/src/games/falloutnv/.github/workflows/linting.yml @@ -0,0 +1,17 @@ +name: Lint Fallout NV Plugin + +on: + push: + pull_request: + types: [opened, synchronize, reopened] + +jobs: + lint: + runs-on: ubuntu-latest + steps: + - uses: actions/checkout@v3 + - name: Run clang-format + uses: jidicula/clang-format-action@v4.11.0 + with: + clang-format-version: "15" + check-path: "." diff --git a/src/games/falloutnv/appveyor.yml b/src/games/falloutnv/appveyor.yml deleted file mode 100644 index 78c3cb1b..00000000 --- a/src/games/falloutnv/appveyor.yml +++ /dev/null @@ -1,40 +0,0 @@ -version: 1.0.{build} -skip_branch_with_pr: true -image: Visual Studio 2019 -environment: - WEBHOOK_URL: - secure: gOKbXaZM9ImtMD5XrYITvdyZUW/az082G9OIN1EC1Vbg57wBaeLhi49uGjxPw5GVujHku6kxN6ab89zhbS5GVeluR76GM83IbKV4Sh7udXzoYZZdg6YudtYHzdhCgUeiedpswbuczTq9ceIkkfSEWZuh/lMAAVVwvcGsJAnoPFw= -build_script: -- pwsh: >- - $ErrorActionPreference = 'Stop' - - git clone --depth=1 --no-single-branch https://github.com/ModOrganizer2/modorganizer-umbrella.git c:\projects\modorganizer-umbrella - - New-Item -ItemType Directory -Path c:\projects\modorganizer-build - - cd c:\projects\modorganizer-umbrella - - ($env:APPVEYOR_PULL_REQUEST_HEAD_REPO_BRANCH -eq $null) ? ($branch = $env:APPVEYOR_REPO_BRANCH) : ($branch = $env:APPVEYOR_PULL_REQUEST_HEAD_REPO_BRANCH) - - git checkout $(git show-ref --verify --quiet refs/remotes/origin/${branch} || echo '-b') ${branch} - - C:\Python37-x64\python.exe unimake.py -d c:\projects\modorganizer-build -s Appveyor_Build=True ${env:APPVEYOR_PROJECT_NAME} - - if($LastExitCode -ne 0) { $host.SetShouldExit($LastExitCode ) } -artifacts: -- path: vsbuild\src\RelWithDebInfo\game_falloutNV.dll - name: game_falloutNV_dll -- path: vsbuild\src\RelWithDebInfo\game_falloutNV.pdb - name: game_falloutNV_pdb -- path: vsbuild\src\RelWithDebInfo\game_falloutNV.lib - name: game_falloutNVe_lib -on_success: - - ps: Set-Location -Path $env:APPVEYOR_BUILD_FOLDER - - ps: Invoke-RestMethod https://raw.githubusercontent.com/DiscordHooks/appveyor-discord-webhook/master/send.ps1 -o send.ps1 - - ps: ./send.ps1 success $env:WEBHOOK_URL -on_failure: - - ps: Set-Location -Path $env:APPVEYOR_BUILD_FOLDER - - ps: Push-AppveyorArtifact ${env:APPVEYOR_BUILD_FOLDER}\stdout.log - - ps: Push-AppveyorArtifact ${env:APPVEYOR_BUILD_FOLDER}\stderr.log - - ps: Invoke-RestMethod https://raw.githubusercontent.com/DiscordHooks/appveyor-discord-webhook/master/send.ps1 -o send.ps1 - - ps: ./send.ps1 failure $env:WEBHOOK_URL \ No newline at end of file diff --git a/src/games/falloutnv/src/SConscript b/src/games/falloutnv/src/SConscript deleted file mode 100644 index 998dca40..00000000 --- a/src/games/falloutnv/src/SConscript +++ /dev/null @@ -1,13 +0,0 @@ -Import('qt_env') - -env = qt_env.Clone() - -env.AppendUnique(CPPDEFINES = [ 'GAMEFALLOUTNV_LIBRARY' ]) - -env.RequiresGamebryo() - -lib = env.SharedLibrary('gameFalloutNV', env.Glob('*.cpp')) -env.InstallModule(lib) - -res = env['QT_USED_MODULES'] -Return('res') diff --git a/src/games/falloutnv/src/falloutnvbsainvalidation.cpp b/src/games/falloutnv/src/falloutnvbsainvalidation.cpp index 5066e61f..5436957c 100644 --- a/src/games/falloutnv/src/falloutnvbsainvalidation.cpp +++ b/src/games/falloutnv/src/falloutnvbsainvalidation.cpp @@ -1,16 +1,16 @@ -#include "falloutnvbsainvalidation.h" - -FalloutNVBSAInvalidation::FalloutNVBSAInvalidation(DataArchives *dataArchives, MOBase::IPluginGame const *game) - : GamebryoBSAInvalidation(dataArchives, "fallout.ini", game) -{ -} - -QString FalloutNVBSAInvalidation::invalidationBSAName() const -{ - return "Fallout - Invalidation.bsa"; -} - -unsigned long FalloutNVBSAInvalidation::bsaVersion() const -{ - return 0x68; -} +#include "falloutnvbsainvalidation.h" + +FalloutNVBSAInvalidation::FalloutNVBSAInvalidation(DataArchives* dataArchives, + MOBase::IPluginGame const* game) + : GamebryoBSAInvalidation(dataArchives, "fallout.ini", game) +{} + +QString FalloutNVBSAInvalidation::invalidationBSAName() const +{ + return "Fallout - Invalidation.bsa"; +} + +unsigned long FalloutNVBSAInvalidation::bsaVersion() const +{ + return 0x68; +} diff --git a/src/games/falloutnv/src/falloutnvbsainvalidation.h b/src/games/falloutnv/src/falloutnvbsainvalidation.h index 3f2dcd5f..e0ede071 100644 --- a/src/games/falloutnv/src/falloutnvbsainvalidation.h +++ b/src/games/falloutnv/src/falloutnvbsainvalidation.h @@ -1,23 +1,19 @@ -#ifndef FALLOUTNVBSAINVALIDATION_H -#define FALLOUTNVBSAINVALIDATION_H - - -#include "gamebryobsainvalidation.h" -#include "falloutnvdataarchives.h" - -#include - -class FalloutNVBSAInvalidation : public GamebryoBSAInvalidation -{ -public: - - FalloutNVBSAInvalidation(DataArchives *dataArchives, MOBase::IPluginGame const *game); - -private: - - virtual QString invalidationBSAName() const override; - virtual unsigned long bsaVersion() const override; - -}; - -#endif // FALLOUTNVBSAINVALIDATION_H +#ifndef FALLOUTNVBSAINVALIDATION_H +#define FALLOUTNVBSAINVALIDATION_H + +#include "falloutnvdataarchives.h" +#include "gamebryobsainvalidation.h" + +#include + +class FalloutNVBSAInvalidation : public GamebryoBSAInvalidation +{ +public: + FalloutNVBSAInvalidation(DataArchives* dataArchives, MOBase::IPluginGame const* game); + +private: + virtual QString invalidationBSAName() const override; + virtual unsigned long bsaVersion() const override; +}; + +#endif // FALLOUTNVBSAINVALIDATION_H diff --git a/src/games/falloutnv/src/falloutnvdataarchives.cpp b/src/games/falloutnv/src/falloutnvdataarchives.cpp index 7a2dbb64..d0cf873f 100644 --- a/src/games/falloutnv/src/falloutnvdataarchives.cpp +++ b/src/games/falloutnv/src/falloutnvdataarchives.cpp @@ -1,35 +1,36 @@ -#include "falloutnvdataarchives.h" -#include - -FalloutNVDataArchives::FalloutNVDataArchives(const QDir &myGamesDir) : - GamebryoDataArchives(myGamesDir) -{ -} - -QStringList FalloutNVDataArchives::vanillaArchives() const -{ - return { "Fallout - Textures.bsa" - , "Fallout - Textures2.bsa" - , "Fallout - Meshes.bsa" - , "Fallout - Voices1.bsa" - , "Fallout - Sound.bsa" - , "Fallout - Misc.bsa" }; -} - -QStringList FalloutNVDataArchives::archives(const MOBase::IProfile *profile) const -{ - QStringList result; - - QString iniFile = profile->localSettingsEnabled() ? QDir(profile->absolutePath()).absoluteFilePath("fallout.ini") : m_LocalGameDir.absoluteFilePath("fallout.ini"); - result.append(getArchivesFromKey(iniFile, "SArchiveList", 8192)); //NVAC expands the maximum string limit - - return result; -} - -void FalloutNVDataArchives::writeArchiveList(MOBase::IProfile *profile, const QStringList &before) -{ - QString list = before.join(", "); - - QString iniFile = profile->localSettingsEnabled() ? QDir(profile->absolutePath()).absoluteFilePath("fallout.ini") : m_LocalGameDir.absoluteFilePath("fallout.ini"); - setArchivesToKey(iniFile, "SArchiveList", list); +#include "falloutnvdataarchives.h" +#include + +FalloutNVDataArchives::FalloutNVDataArchives(const QDir& myGamesDir) + : GamebryoDataArchives(myGamesDir) +{} + +QStringList FalloutNVDataArchives::vanillaArchives() const +{ + return {"Fallout - Textures.bsa", "Fallout - Textures2.bsa", "Fallout - Meshes.bsa", + "Fallout - Voices1.bsa", "Fallout - Sound.bsa", "Fallout - Misc.bsa"}; +} + +QStringList FalloutNVDataArchives::archives(const MOBase::IProfile* profile) const +{ + QStringList result; + + QString iniFile = profile->localSettingsEnabled() + ? QDir(profile->absolutePath()).absoluteFilePath("fallout.ini") + : m_LocalGameDir.absoluteFilePath("fallout.ini"); + result.append(getArchivesFromKey(iniFile, "SArchiveList", + 8192)); // NVAC expands the maximum string limit + + return result; +} + +void FalloutNVDataArchives::writeArchiveList(MOBase::IProfile* profile, + const QStringList& before) +{ + QString list = before.join(", "); + + QString iniFile = profile->localSettingsEnabled() + ? QDir(profile->absolutePath()).absoluteFilePath("fallout.ini") + : m_LocalGameDir.absoluteFilePath("fallout.ini"); + setArchivesToKey(iniFile, "SArchiveList", list); } \ No newline at end of file diff --git a/src/games/falloutnv/src/falloutnvdataarchives.h b/src/games/falloutnv/src/falloutnvdataarchives.h index 995e7275..8b7ca21f 100644 --- a/src/games/falloutnv/src/falloutnvdataarchives.h +++ b/src/games/falloutnv/src/falloutnvdataarchives.h @@ -1,25 +1,24 @@ -#ifndef FALLOUTNVDATAARCHIVES_H -#define FALLOUTNVDATAARCHIVES_H - - -#include -#include -#include -#include -#include - -class FalloutNVDataArchives : public GamebryoDataArchives -{ -public: - FalloutNVDataArchives(const QDir &myGamesDir); - -public: - 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 // FALLOUTNVDATAARCHIVES_H +#ifndef FALLOUTNVDATAARCHIVES_H +#define FALLOUTNVDATAARCHIVES_H + +#include +#include +#include +#include +#include + +class FalloutNVDataArchives : public GamebryoDataArchives +{ +public: + FalloutNVDataArchives(const QDir& myGamesDir); + +public: + 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 // FALLOUTNVDATAARCHIVES_H diff --git a/src/games/falloutnv/src/falloutnvmoddatachecker.h b/src/games/falloutnv/src/falloutnvmoddatachecker.h index 35a6dbe8..2aeb1ab6 100644 --- a/src/games/falloutnv/src/falloutnvmoddatachecker.h +++ b/src/games/falloutnv/src/falloutnvmoddatachecker.h @@ -9,21 +9,21 @@ public: using GamebryoModDataChecker::GamebryoModDataChecker; protected: - virtual const FileNameSet& possibleFolderNames() const override { + 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" - }; + "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"}; return result; } - virtual const FileNameSet& possibleFileExtensions() const override { - static FileNameSet result{ - "esp", "esm", "bsa", "modgroups", "ini" - }; + virtual const FileNameSet& possibleFileExtensions() const override + { + static FileNameSet result{"esp", "esm", "bsa", "modgroups", "ini"}; return result; } }; -#endif // FALLOUTNV_MODATACHECKER_H +#endif // FALLOUTNV_MODATACHECKER_H diff --git a/src/games/falloutnv/src/falloutnvmoddatacontent.h b/src/games/falloutnv/src/falloutnvmoddatacontent.h index 6d66bf8e..44a2a258 100644 --- a/src/games/falloutnv/src/falloutnvmoddatacontent.h +++ b/src/games/falloutnv/src/falloutnvmoddatacontent.h @@ -4,18 +4,19 @@ #include #include -class FalloutNVModDataContent : public GamebryoModDataContent { +class FalloutNVModDataContent : public GamebryoModDataContent +{ public: - /** * */ - FalloutNVModDataContent(GameGamebryo const* gamePlugin) : GamebryoModDataContent(gamePlugin) { + FalloutNVModDataContent(GameGamebryo const* gamePlugin) + : GamebryoModDataContent(gamePlugin) + { // Just need to disable some contents: - m_Enabled[CONTENT_MCM] = false; + m_Enabled[CONTENT_MCM] = false; m_Enabled[CONTENT_SKYPROC] = false; } - }; -#endif // FALLOUTNV_MODDATACONTENT_H +#endif // FALLOUTNV_MODDATACONTENT_H diff --git a/src/games/falloutnv/src/falloutnvsavegame.cpp b/src/games/falloutnv/src/falloutnvsavegame.cpp index 21560de2..749053f3 100644 --- a/src/games/falloutnv/src/falloutnvsavegame.cpp +++ b/src/games/falloutnv/src/falloutnvsavegame.cpp @@ -2,34 +2,32 @@ #include "gamefalloutnv.h" -FalloutNVSaveGame::FalloutNVSaveGame(QString const &fileName, GameFalloutNV const *game) : - GamebryoSaveGame(fileName, game) +FalloutNVSaveGame::FalloutNVSaveGame(QString const& fileName, GameFalloutNV const* game) + : GamebryoSaveGame(fileName, game) { FileWrapper file(getFilepath(), "FO3SAVEGAME"); unsigned long width, height; - fetchInformationFields(file, width, height, m_SaveNumber, m_PCName, m_PCLevel, m_PCLocation); - + fetchInformationFields(file, width, height, m_SaveNumber, m_PCName, m_PCLevel, + m_PCLocation); } -void FalloutNVSaveGame::fetchInformationFields( - FileWrapper& file, - unsigned long& width, - unsigned long& height, - unsigned long& saveNumber, - QString& playerName, - unsigned short& playerLevel, - QString& playerLocation) const +void FalloutNVSaveGame::fetchInformationFields(FileWrapper& file, unsigned long& width, + unsigned long& height, + unsigned long& saveNumber, + QString& playerName, + unsigned short& playerLevel, + QString& playerLocation) const { - file.skip(); //Save header size + file.skip(); // Save header size - file.skip(); //File version? - file.skip(); //Delimiter + file.skip(); // File version? + file.skip(); // 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 + // 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); @@ -61,8 +59,8 @@ std::unique_ptr FalloutNVSaveGame::fetchDataFields unsigned short dummyLevel; unsigned long dummySaveNumber; - fetchInformationFields(file, width, height, - dummySaveNumber, dummyName, dummyLevel, dummyLocation); + fetchInformationFields(file, width, height, dummySaveNumber, dummyName, dummyLevel, + dummyLocation); } QString playtime; @@ -70,7 +68,7 @@ std::unique_ptr FalloutNVSaveGame::fetchDataFields fields->Screenshot = file.readImage(width, height, 256); - file.skip(5); // unknown (1 byte), plugin size (4 bytes) + file.skip(5); // unknown (1 byte), plugin size (4 bytes) file.setPluginString(GamebryoSaveGame::StringType::TYPE_BSTRING); fields->Plugins = file.readPlugins(); diff --git a/src/games/falloutnv/src/falloutnvsavegame.h b/src/games/falloutnv/src/falloutnvsavegame.h index b1772e3f..957c458d 100644 --- a/src/games/falloutnv/src/falloutnvsavegame.h +++ b/src/games/falloutnv/src/falloutnvsavegame.h @@ -8,21 +8,16 @@ class GameFalloutNV; class FalloutNVSaveGame : public GamebryoSaveGame { public: - FalloutNVSaveGame(QString const &fileName, GameFalloutNV const *game); + FalloutNVSaveGame(QString const& fileName, GameFalloutNV const* game); protected: - // Fetch easy-to-access information. - void fetchInformationFields( - FileWrapper& wrapper, - unsigned long& width, - unsigned long& height, - unsigned long& saveNumber, - QString& playerName, - unsigned short& playerLevel, - QString& playerLocation) const; + void fetchInformationFields(FileWrapper& wrapper, unsigned long& width, + unsigned long& height, unsigned long& saveNumber, + QString& playerName, unsigned short& playerLevel, + QString& playerLocation) const; std::unique_ptr fetchDataFields() const override; }; -#endif // FALLOUTNVSAVEGAME_H +#endif // FALLOUTNVSAVEGAME_H diff --git a/src/games/falloutnv/src/falloutnvscriptextender.cpp b/src/games/falloutnv/src/falloutnvscriptextender.cpp index 987b5012..fc00c318 100644 --- a/src/games/falloutnv/src/falloutnvscriptextender.cpp +++ b/src/games/falloutnv/src/falloutnvscriptextender.cpp @@ -1,19 +1,18 @@ -#include "falloutnvscriptextender.h" - -#include -#include - -FalloutNVScriptExtender::FalloutNVScriptExtender(GameGamebryo const *game) : - GamebryoScriptExtender(game) -{ -} - -QString FalloutNVScriptExtender::BinaryName() const -{ - return "nvse_loader.exe"; -} - -QString FalloutNVScriptExtender::PluginPath() const -{ - return "nvse/plugins"; -} +#include "falloutnvscriptextender.h" + +#include +#include + +FalloutNVScriptExtender::FalloutNVScriptExtender(GameGamebryo const* game) + : GamebryoScriptExtender(game) +{} + +QString FalloutNVScriptExtender::BinaryName() const +{ + return "nvse_loader.exe"; +} + +QString FalloutNVScriptExtender::PluginPath() const +{ + return "nvse/plugins"; +} diff --git a/src/games/falloutnv/src/falloutnvscriptextender.h b/src/games/falloutnv/src/falloutnvscriptextender.h index 66e4274e..9db160ff 100644 --- a/src/games/falloutnv/src/falloutnvscriptextender.h +++ b/src/games/falloutnv/src/falloutnvscriptextender.h @@ -1,18 +1,17 @@ -#ifndef FALLOUTNVSCRIPTEXTENDER_H -#define FALLOUTNVSCRIPTEXTENDER_H - -#include "gamebryoscriptextender.h" - -class GameGamebryo; - -class FalloutNVScriptExtender : public GamebryoScriptExtender -{ -public: - FalloutNVScriptExtender(const GameGamebryo *game); - - virtual QString BinaryName() const override; - virtual QString PluginPath() const override; - -}; - -#endif // FALLOUTNVSCRIPTEXTENDER_H +#ifndef FALLOUTNVSCRIPTEXTENDER_H +#define FALLOUTNVSCRIPTEXTENDER_H + +#include "gamebryoscriptextender.h" + +class GameGamebryo; + +class FalloutNVScriptExtender : public GamebryoScriptExtender +{ +public: + FalloutNVScriptExtender(const GameGamebryo* game); + + virtual QString BinaryName() const override; + virtual QString PluginPath() const override; +}; + +#endif // FALLOUTNVSCRIPTEXTENDER_H diff --git a/src/games/falloutnv/src/gameFalloutNV.pro b/src/games/falloutnv/src/gameFalloutNV.pro deleted file mode 100644 index d15f0b1a..00000000 --- a/src/games/falloutnv/src/gameFalloutNV.pro +++ /dev/null @@ -1,50 +0,0 @@ -#------------------------------------------------- -# -# Project created by QtCreator 2014-11-15T15:36:33 -# -#------------------------------------------------- - - -TARGET = gameFalloutNV -TEMPLATE = lib - -CONFIG += plugins -CONFIG += dll - -DEFINES += GAMEFALLOUTNV_LIBRARY - -SOURCES += gamefalloutnv.cpp \ - falloutnvbsainvalidation.cpp \ - falloutnvscriptextender.cpp \ - falloutnvdataarchives.cpp \ - falloutnvsavegame.cpp \ - falloutnvsavegameinfo.cpp - -HEADERS += gamefalloutnv.h \ - falloutnvbsainvalidation.h \ - falloutnvscriptextender.h \ - falloutnvdataarchives.h \ - falloutnvsavegame.h \ - falloutnvsavegameinfo.h - -CONFIG(debug, debug|release) { - LIBS += -L"$${OUT_PWD}/../gameGamebryo/debug" - PRE_TARGETDEPS += \ - $$OUT_PWD/../gameGamebryo/debug/gameGamebryo.lib -} else { - LIBS += -L"$${OUT_PWD}/../gameGamebryo/release" - PRE_TARGETDEPS += \ - $$OUT_PWD/../gameGamebryo/release/gameGamebryo.lib -} - -include(../plugin_template.pri) - -INCLUDEPATH += "$${BOOSTPATH}" "$${PWD}/../gamefeatures" "$${PWD}/../gamegamebryo" - -LIBS += -ladvapi32 -lole32 -lgameGamebryo - -OTHER_FILES += \ - gamefalloutnv.json\ - SConscript \ - CMakeLists.txt - diff --git a/src/games/falloutnv/src/game_falloutNV_en.ts b/src/games/falloutnv/src/game_falloutNV_en.ts index f517b2db..ceb068ad 100644 --- a/src/games/falloutnv/src/game_falloutNV_en.ts +++ b/src/games/falloutnv/src/game_falloutNV_en.ts @@ -4,175 +4,14 @@ GameFalloutNV - + Fallout NV Support Plugin - + Adds support for the game Fallout New Vegas - - GamebryoModDataContent - - - Plugins (ESP/ESM/ESL) - - - - - Optional Plugins - - - - - Interface - - - - - Meshes - - - - - Bethesda Archive - - - - - Scripts (Papyrus) - - - - - Script Extender Plugin - - - - - Script Extender Files - - - - - SkyProc Patcher - - - - - Sound or Music - - - - - Textures - - - - - MCM Configuration - - - - - INI Files - - - - - FaceGen Data - - - - - ModGroup Files - - - - - GamebryoSaveGameInfoWidget - - - Save # - - - - - Character - - - - - Level - - - - - Location - - - - - Date - - - - - Has Script Extender Data - - - - - Missing ESPs - - - - - - None - - - - - Missing ESLs - - - - - QObject - - - - Some of your plugins have invalid names! These plugins can not be loaded by the game. Please see mo_interface.log for a list of affected plugins and rename them. - - - - - %1, #%2, Level %3, %4 - - - - - failed to open %1 - - - - - wrong file format - expected %1 got %2 - - - - - failed to query registry path (preflight): %1 - - - - - failed to query registry path (read): %1 - - - diff --git a/src/games/falloutnv/src/gamefalloutnv.cpp b/src/games/falloutnv/src/gamefalloutnv.cpp index 1eea113a..e8f02868 100644 --- a/src/games/falloutnv/src/gamefalloutnv.cpp +++ b/src/games/falloutnv/src/gamefalloutnv.cpp @@ -2,16 +2,16 @@ #include "falloutnvbsainvalidation.h" #include "falloutnvdataarchives.h" -#include "falloutnvscriptextender.h" #include "falloutnvmoddatachecker.h" #include "falloutnvmoddatacontent.h" #include "falloutnvsavegame.h" +#include "falloutnvscriptextender.h" #include "executableinfo.h" #include "pluginsetting.h" #include "versioninfo.h" -#include #include +#include #include #include @@ -27,93 +27,94 @@ using namespace MOBase; -GameFalloutNV::GameFalloutNV() -{ -} +GameFalloutNV::GameFalloutNV() {} bool GameFalloutNV::init(IOrganizer* moInfo) { - if (!GameGamebryo::init(moInfo)) { - return false; - } - registerFeature(new FalloutNVScriptExtender(this)); - registerFeature(new FalloutNVDataArchives(myGamesPath())); - registerFeature(new FalloutNVBSAInvalidation(feature(), this)); - registerFeature(new GamebryoSaveGameInfo(this)); - registerFeature(new GamebryoLocalSavegames(myGamesPath(), "fallout.ini")); - registerFeature(new FalloutNVModDataChecker(this)); - registerFeature(new FalloutNVModDataContent(this)); - registerFeature(new GamebryoGamePlugins(moInfo)); - registerFeature(new GamebryoUnmangedMods(this)); - return true; + if (!GameGamebryo::init(moInfo)) { + return false; + } + registerFeature(new FalloutNVScriptExtender(this)); + registerFeature(new FalloutNVDataArchives(myGamesPath())); + registerFeature( + new FalloutNVBSAInvalidation(feature(), this)); + registerFeature(new GamebryoSaveGameInfo(this)); + registerFeature( + new GamebryoLocalSavegames(myGamesPath(), "fallout.ini")); + registerFeature(new FalloutNVModDataChecker(this)); + registerFeature(new FalloutNVModDataContent(this)); + registerFeature(new GamebryoGamePlugins(moInfo)); + registerFeature(new GamebryoUnmangedMods(this)); + return true; } void GameFalloutNV::setVariant(QString variant) { - m_GameVariant = variant; + m_GameVariant = variant; } void GameFalloutNV::checkVariants() { - QFileInfo gog_dll(m_GamePath + "\\Galaxy64.dll"); - QFileInfo epic_dll(m_GamePath + "\\EOSSDK-Win32-Shipping.dll"); - if (epic_dll.exists()) - setVariant("Epic Games"); - else - setVariant("Steam"); + QFileInfo gog_dll(m_GamePath + "\\Galaxy64.dll"); + QFileInfo epic_dll(m_GamePath + "\\EOSSDK-Win32-Shipping.dll"); + if (epic_dll.exists()) + setVariant("Epic Games"); + else + setVariant("Steam"); } QDir GameFalloutNV::documentsDirectory() const { - return m_MyGamesPath; + return m_MyGamesPath; } QString GameFalloutNV::identifyGamePath() const { - auto result = GameGamebryo::identifyGamePath(); // Default registry path - // 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" }); - } - return result; + auto result = GameGamebryo::identifyGamePath(); // Default registry path + // 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"}); + } + return result; } void GameFalloutNV::setGamePath(const QString& path) { - m_GamePath = path; - checkVariants(); - m_MyGamesPath = determineMyGamesPath(gameDirectoryName()); - registerFeature(new FalloutNVDataArchives(myGamesPath())); - registerFeature(new GamebryoLocalSavegames(myGamesPath(), "fallout.ini")); + m_GamePath = path; + checkVariants(); + m_MyGamesPath = determineMyGamesPath(gameDirectoryName()); + registerFeature(new FalloutNVDataArchives(myGamesPath())); + registerFeature( + new GamebryoLocalSavegames(myGamesPath(), "fallout.ini")); } QDir GameFalloutNV::savesDirectory() const { - return QDir(m_MyGamesPath + "/Saves"); + return QDir(m_MyGamesPath + "/Saves"); } QString GameFalloutNV::myGamesPath() const { - return m_MyGamesPath; + return m_MyGamesPath; } bool GameFalloutNV::isInstalled() const { - return !m_GamePath.isEmpty(); + return !m_GamePath.isEmpty(); } QString GameFalloutNV::gameName() const { - return "New Vegas"; + return "New Vegas"; } QString GameFalloutNV::gameDirectoryName() const @@ -151,28 +152,27 @@ QList GameFalloutNV::executables() const QList GameFalloutNV::executableForcedLoads() const { - return QList(); + return QList(); } QString GameFalloutNV::name() const { - return "Fallout NV Support Plugin"; + return "Fallout NV Support Plugin"; } QString GameFalloutNV::localizedName() const { - return tr("Fallout NV Support Plugin"); + return tr("Fallout NV Support Plugin"); } - QString GameFalloutNV::author() const { - return "Tannin"; + return "Tannin"; } QString GameFalloutNV::description() const { - return tr("Adds support for the game Fallout New Vegas"); + return tr("Adds support for the game Fallout New Vegas"); } MOBase::VersionInfo GameFalloutNV::version() const @@ -182,7 +182,7 @@ MOBase::VersionInfo GameFalloutNV::version() const QList GameFalloutNV::settings() const { - return QList(); + return QList(); } void GameFalloutNV::initializeProfile(const QDir& path, ProfileSettings settings) const @@ -191,106 +191,107 @@ void GameFalloutNV::initializeProfile(const QDir& path, ProfileSettings settings 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"); - } + 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, "custom.ini"); - copyToProfile(myGamesPath(), path, "GECKCustom.ini"); - copyToProfile(myGamesPath(), path, "GECKPrefs.ini"); - - } + copyToProfile(myGamesPath(), path, "falloutprefs.ini"); + copyToProfile(myGamesPath(), path, "falloutcustom.ini"); + copyToProfile(myGamesPath(), path, "custom.ini"); + copyToProfile(myGamesPath(), path, "GECKCustom.ini"); + copyToProfile(myGamesPath(), path, "GECKPrefs.ini"); + } } QString GameFalloutNV::savegameExtension() const { - return "fos"; + return "fos"; } QString GameFalloutNV::savegameSEExtension() const { - return "nvse"; + return "nvse"; } -std::shared_ptr GameFalloutNV::makeSaveGame(QString filePath) const +std::shared_ptr +GameFalloutNV::makeSaveGame(QString filePath) const { - return std::make_shared(filePath, this); + return std::make_shared(filePath, this); } QString GameFalloutNV::steamAPPId() const { - return "22380"; + return "22380"; } QStringList GameFalloutNV::primaryPlugins() const { - return { "falloutnv.esm" }; + return {"falloutnv.esm"}; } QStringList GameFalloutNV::gameVariants() const { - return { "Steam", "Epic Games" }; + return {"Steam", "Epic Games"}; } QString GameFalloutNV::gameShortName() const { - return "FalloutNV"; + return "FalloutNV"; } QStringList GameFalloutNV::validShortNames() const { - return { "Fallout3" }; + return {"Fallout3"}; } QString GameFalloutNV::gameNexusName() const { - return "newvegas"; + return "newvegas"; } QStringList GameFalloutNV::iniFiles() const { - return { "fallout.ini", "falloutprefs.ini", "falloutcustom.ini", "custom.ini", "GECKCustom.ini", "GECKPrefs.ini" }; + return {"fallout.ini", "falloutprefs.ini", "falloutcustom.ini", + "custom.ini", "GECKCustom.ini", "GECKPrefs.ini"}; } QStringList GameFalloutNV::DLCPlugins() const { - return { "DeadMoney.esm", "HonestHearts.esm", "OldWorldBlues.esm", - "LonesomeRoad.esm", "GunRunnersArsenal.esm", "CaravanPack.esm", - "ClassicPack.esm", "MercenaryPack.esm", "TribalPack.esm" }; + return {"DeadMoney.esm", "HonestHearts.esm", "OldWorldBlues.esm", + "LonesomeRoad.esm", "GunRunnersArsenal.esm", "CaravanPack.esm", + "ClassicPack.esm", "MercenaryPack.esm", "TribalPack.esm"}; } int GameFalloutNV::nexusModOrganizerID() const { - return 42572; + return 42572; } int GameFalloutNV::nexusGameID() const { - return 130; + return 130; } QDir GameFalloutNV::gameDirectory() const { - return QDir(m_GamePath); + return QDir(m_GamePath); } // Not to delete all the spaces... MappingType GameFalloutNV::mappings() const { - MappingType result; + MappingType result; - for (const QString& profileFile : { "plugins.txt", "loadorder.txt" }) { - result.push_back({ m_Organizer->profilePath() + "/" + profileFile, - localAppFolder() + "/" + gameDirectoryName() + "/" + profileFile, - false }); - } + for (const QString& profileFile : {"plugins.txt", "loadorder.txt"}) { + result.push_back({m_Organizer->profilePath() + "/" + profileFile, + localAppFolder() + "/" + gameDirectoryName() + "/" + profileFile, + false}); + } - return result; + return result; } diff --git a/src/games/falloutnv/src/gamefalloutnv.h b/src/games/falloutnv/src/gamefalloutnv.h index 582bd3c7..b3ab7057 100644 --- a/src/games/falloutnv/src/gamefalloutnv.h +++ b/src/games/falloutnv/src/gamefalloutnv.h @@ -1,68 +1,69 @@ -#ifndef GAMEFALLOUTNV_H -#define GAMEFALLOUTNV_H - -#include "gamegamebryo.h" - -#include -#include - -class GameFalloutNV : public GameGamebryo -{ - Q_OBJECT -#if QT_VERSION >= QT_VERSION_CHECK(5,0,0) - Q_PLUGIN_METADATA(IID "org.tannin.GameFalloutNV" FILE "gamefalloutnv.json") -#endif - -public: - GameFalloutNV(); - - virtual bool init(MOBase::IOrganizer* moInfo) override; - -public: // IPluginGame interface - virtual QString gameName() const override; - virtual void detectGame() override; - virtual QList executables() const override; - virtual QList 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 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 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 settings() const override; - 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 makeSaveGame(QString filePath) const override; - -}; - -#endif // GAMEFALLOUTNV_H +#ifndef GAMEFALLOUTNV_H +#define GAMEFALLOUTNV_H + +#include "gamegamebryo.h" + +#include +#include + +class GameFalloutNV : public GameGamebryo +{ + Q_OBJECT +#if QT_VERSION >= QT_VERSION_CHECK(5, 0, 0) + Q_PLUGIN_METADATA(IID "org.tannin.GameFalloutNV" FILE "gamefalloutnv.json") +#endif + +public: + GameFalloutNV(); + + virtual bool init(MOBase::IOrganizer* moInfo) override; + +public: // IPluginGame interface + virtual QString gameName() const override; + virtual void detectGame() override; + virtual QList executables() const override; + virtual QList + 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 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 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 settings() const override; + 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 makeSaveGame(QString filePath) const override; +}; + +#endif // GAMEFALLOUTNV_H From e4e91eb69233077c478e753e0e0f85cb58e199db Mon Sep 17 00:00:00 2001 From: Jeremy Rimpo Date: Thu, 28 Sep 2023 11:57:06 -0500 Subject: [PATCH 1362/1544] [game_falloutnv] Git blame ignore revs --- src/games/falloutnv/.git-blame-ignore-revs | 1 + 1 file changed, 1 insertion(+) create mode 100644 src/games/falloutnv/.git-blame-ignore-revs diff --git a/src/games/falloutnv/.git-blame-ignore-revs b/src/games/falloutnv/.git-blame-ignore-revs new file mode 100644 index 00000000..9e3d3dee --- /dev/null +++ b/src/games/falloutnv/.git-blame-ignore-revs @@ -0,0 +1 @@ +e2800fc889373e18126dd1150a99b37eb1c45443 From 043b6a40b1e6b6f033ce3fb5b73a423f093ed2c8 Mon Sep 17 00:00:00 2001 From: Jeremy Rimpo Date: Thu, 28 Sep 2023 12:11:12 -0500 Subject: [PATCH 1363/1544] [game_falloutnv] Attempt to get subdirectory of EGS install path --- src/games/falloutnv/src/gamefalloutnv.cpp | 9 ++++++++- 1 file changed, 8 insertions(+), 1 deletion(-) diff --git a/src/games/falloutnv/src/gamefalloutnv.cpp b/src/games/falloutnv/src/gamefalloutnv.cpp index e8f02868..d93b071e 100644 --- a/src/games/falloutnv/src/gamefalloutnv.cpp +++ b/src/games/falloutnv/src/gamefalloutnv.cpp @@ -55,7 +55,6 @@ void GameFalloutNV::setVariant(QString variant) void GameFalloutNV::checkVariants() { - QFileInfo gog_dll(m_GamePath + "\\Galaxy64.dll"); QFileInfo epic_dll(m_GamePath + "\\EOSSDK-Win32-Shipping.dll"); if (epic_dll.exists()) setVariant("Epic Games"); @@ -279,6 +278,14 @@ int GameFalloutNV::nexusGameID() const QDir GameFalloutNV::gameDirectory() const { + if (selectedVariant() == "Epic Games") { + if (QFileInfo(m_GamePath).isDir()) { + } + QDir startPath = QDir(m_GamePath); + auto subDirs = startPath.entryList(QDir::Dirs); + if (!subDirs.isEmpty()) + return subDirs.first(); + } return QDir(m_GamePath); } From bcba2dc18a48607be562e88738de8f383349b79d Mon Sep 17 00:00:00 2001 From: Jeremy Rimpo Date: Thu, 28 Sep 2023 12:20:19 -0500 Subject: [PATCH 1364/1544] [game_falloutnv] Move subdirectory game parsing to identifyGamePath - EGS apparently installs multiple copies based on language, just grab the first subdirectory for now --- src/games/falloutnv/src/gamefalloutnv.cpp | 14 ++++++-------- 1 file changed, 6 insertions(+), 8 deletions(-) diff --git a/src/games/falloutnv/src/gamefalloutnv.cpp b/src/games/falloutnv/src/gamefalloutnv.cpp index d93b071e..8e442a2d 100644 --- a/src/games/falloutnv/src/gamefalloutnv.cpp +++ b/src/games/falloutnv/src/gamefalloutnv.cpp @@ -82,6 +82,12 @@ QString GameFalloutNV::identifyGamePath() const * Courier's Stash: ee9a44b4530942499ef1c8c390731fce */ result = parseEpicGamesLocation({"5daeb974a22a435988892319b3a4f476"}); + if (QFileInfo(result).isDir()) { + QDir startPath = QDir(result); + auto subDirs = startPath.entryList(QDir::Dirs | QDir::NoDotAndDotDot); + if (!subDirs.isEmpty()) + result = subDirs.first(); + } } return result; } @@ -278,14 +284,6 @@ int GameFalloutNV::nexusGameID() const QDir GameFalloutNV::gameDirectory() const { - if (selectedVariant() == "Epic Games") { - if (QFileInfo(m_GamePath).isDir()) { - } - QDir startPath = QDir(m_GamePath); - auto subDirs = startPath.entryList(QDir::Dirs); - if (!subDirs.isEmpty()) - return subDirs.first(); - } return QDir(m_GamePath); } From a130944cecd62e9e4fb989a23e1528b958e9a528 Mon Sep 17 00:00:00 2001 From: Jeremy Rimpo Date: Thu, 28 Sep 2023 20:20:04 -0500 Subject: [PATCH 1365/1544] [game_falloutnv] Fixes --- src/games/falloutnv/src/gamefalloutnv.cpp | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/src/games/falloutnv/src/gamefalloutnv.cpp b/src/games/falloutnv/src/gamefalloutnv.cpp index 8e442a2d..d9bb80d0 100644 --- a/src/games/falloutnv/src/gamefalloutnv.cpp +++ b/src/games/falloutnv/src/gamefalloutnv.cpp @@ -98,6 +98,8 @@ void GameFalloutNV::setGamePath(const QString& path) checkVariants(); m_MyGamesPath = determineMyGamesPath(gameDirectoryName()); registerFeature(new FalloutNVDataArchives(myGamesPath())); + registerFeature( + new FalloutNVBSAInvalidation(feature(), this)); registerFeature( new GamebryoLocalSavegames(myGamesPath(), "fallout.ini")); } @@ -127,7 +129,7 @@ QString GameFalloutNV::gameDirectoryName() const if (selectedVariant() == "Epic Games") return "FalloutNV_Epic"; else - return "FalloutNV_Epic"; + return "FalloutNV"; } void GameFalloutNV::detectGame() From 8a481992f0f11d5937177355af8b32534bfe27b4 Mon Sep 17 00:00:00 2001 From: Jeremy Rimpo Date: Thu, 28 Sep 2023 20:26:11 -0500 Subject: [PATCH 1366/1544] Fix starfield-specific code --- src/gamebryo/gamegamebryo.cpp | 8 ++++---- src/gamebryo/gamegamebryo.h | 2 +- 2 files changed, 5 insertions(+), 5 deletions(-) diff --git a/src/gamebryo/gamegamebryo.cpp b/src/gamebryo/gamegamebryo.cpp index 71c1e4d4..89ec5237 100644 --- a/src/gamebryo/gamegamebryo.cpp +++ b/src/gamebryo/gamegamebryo.cpp @@ -464,7 +464,8 @@ QString GameGamebryo::parseEpicGamesLocation(const QStringList& manifests) return ""; } -QString GameGamebryo::parseSteamLocation(const QString& appid) +QString GameGamebryo::parseSteamLocation(const QString& appid, + const QString& directoryName) { QString path = "Software\\Valve\\Steam"; QString steamLocation = @@ -487,9 +488,8 @@ QString GameGamebryo::parseSteamLocation(const QString& appid) } if (!steamLibraryLocation.isEmpty()) { QString gameLocation = steamLibraryLocation + "\\" + "steamapps" + "\\" + - "common" + "\\" + "Starfield"; - if (QDir(gameLocation).exists() && - QFile(gameLocation + "\\" + "Starfield.exe").exists()) + "common" + "\\" + directoryName; + if (QDir(gameLocation).exists()) return gameLocation; } } diff --git a/src/gamebryo/gamegamebryo.h b/src/gamebryo/gamegamebryo.h index b1aca9a9..7f671e1b 100644 --- a/src/gamebryo/gamegamebryo.h +++ b/src/gamebryo/gamegamebryo.h @@ -128,7 +128,7 @@ protected: static QString parseEpicGamesLocation(const QStringList& manifests); - static QString parseSteamLocation(const QString& appid); + static QString parseSteamLocation(const QString& appid, const QString& directoryName); protected: std::map featureList() const override; From 859e133eccab8af6071ac3555b1e895e30c62ee9 Mon Sep 17 00:00:00 2001 From: Jeremy Rimpo Date: Thu, 28 Sep 2023 20:26:28 -0500 Subject: [PATCH 1367/1544] [game_starfield] Updated parseSteamLocation --- src/games/starfield/src/gamestarfield.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/games/starfield/src/gamestarfield.cpp b/src/games/starfield/src/gamestarfield.cpp index 8b723312..1f46df9d 100644 --- a/src/games/starfield/src/gamestarfield.cpp +++ b/src/games/starfield/src/gamestarfield.cpp @@ -66,7 +66,7 @@ void GameStarfield::detectGame() QString GameStarfield::identifyGamePath() const { - return parseSteamLocation(steamAPPId()); + return parseSteamLocation(steamAPPId(), gameName()); } QDir GameStarfield::dataDirectory() const From 867658f1710fc4db05fd7a968f73e572b6943af7 Mon Sep 17 00:00:00 2001 From: Jeremy Rimpo Date: Thu, 28 Sep 2023 21:03:50 -0500 Subject: [PATCH 1368/1544] Remove extraneous registry directory --- src/gamebryo/gamegamebryo.cpp | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/src/gamebryo/gamegamebryo.cpp b/src/gamebryo/gamegamebryo.cpp index 89ec5237..d38109ad 100644 --- a/src/gamebryo/gamegamebryo.cpp +++ b/src/gamebryo/gamegamebryo.cpp @@ -433,8 +433,7 @@ QString GameGamebryo::parseEpicGamesLocation(const QStringList& manifests) // Use the registry entry to find the EGL Data dir first, just in case something // changes QString manifestDir = findInRegistry( - HKEY_LOCAL_MACHINE, L"SOFTWARE\\WOW6432Node\\Epic Games\\EpicGamesLauncher", - L"AppDataPath"); + HKEY_LOCAL_MACHINE, L"Software\\Epic Games\\EpicGamesLauncher", L"AppDataPath"); if (manifestDir.isEmpty()) manifestDir = getKnownFolderPath(FOLDERID_ProgramData, false) + "\\Epic\\EpicGamesLauncher\\Data\\"; From 93253ac016c7c81cf4c9516090a46f72c8ffa898 Mon Sep 17 00:00:00 2001 From: Jeremy Rimpo Date: Thu, 28 Sep 2023 22:15:56 -0500 Subject: [PATCH 1369/1544] [game_starfield] Translation updates --- src/games/starfield/src/game_starfield_en.ts | 10 ++++++++-- 1 file changed, 8 insertions(+), 2 deletions(-) diff --git a/src/games/starfield/src/game_starfield_en.ts b/src/games/starfield/src/game_starfield_en.ts index cfcb6dd2..e0427b80 100644 --- a/src/games/starfield/src/game_starfield_en.ts +++ b/src/games/starfield/src/game_starfield_en.ts @@ -4,14 +4,20 @@ GameStarfield - + Starfield Support Plugin - + Adds support for the game Starfield. + + + Turn on plugin management. As of Starfield 1.7.33 this REQUIRES fixing 'plugins.txt' with a SFSE plugin. This will do nothing otherwise. + Turn on plugin management. As of Starfield 1.7.33 this REQUIRES SPECIAL WORKAROUNDS. + + From e81e8578047da2b56d9e7c68099d986913b3a9d8 Mon Sep 17 00:00:00 2001 From: Jeremy Rimpo Date: Sat, 30 Sep 2023 16:22:15 -0500 Subject: [PATCH 1370/1544] Add toggle for using fromLocal8Bit - Some games use windows encoding for locality - Allow toggling between loading utf-8 and local8bit, defaulting to utf-8 for backward compatibility --- src/gamebryo/gamebryosavegame.cpp | 14 +++++++++++--- src/gamebryo/gamebryosavegame.h | 8 +++++--- 2 files changed, 16 insertions(+), 6 deletions(-) diff --git a/src/gamebryo/gamebryosavegame.cpp b/src/gamebryo/gamebryosavegame.cpp index 978414c5..9b2011a9 100644 --- a/src/gamebryo/gamebryosavegame.cpp +++ b/src/gamebryo/gamebryosavegame.cpp @@ -163,8 +163,7 @@ void GamebryoSaveGame::FileWrapper::skipQDataStream(QDataStream& data, } } -template <> -void GamebryoSaveGame::FileWrapper::read(QString& value) +void GamebryoSaveGame::FileWrapper::read(QString& value, bool isUtf8) { if (m_CompressionType == 0) { unsigned short length; @@ -223,13 +222,22 @@ void GamebryoSaveGame::FileWrapper::read(QString& value) m_Data->skipRawData(1); } - value = QString::fromUtf8(buffer.constData()); + if (isUtf8) + value = QString::fromUtf8(buffer.constData()); + else + value = QString::fromLocal8Bit(buffer.constData()); } else { MOBase::log::warn("Please create an issue on the MO github labeled \"Found unknown " "Compressed\" with your savefile attached"); } } +template <> +void GamebryoSaveGame::FileWrapper::read(QString& value) +{ + read(value, true); +} + void GamebryoSaveGame::FileWrapper::read(void* buff, std::size_t length) { int read = m_File.read(static_cast(buff), length); diff --git a/src/gamebryo/gamebryosavegame.h b/src/gamebryo/gamebryosavegame.h index da241e8a..017c53b9 100644 --- a/src/gamebryo/gamebryosavegame.h +++ b/src/gamebryo/gamebryosavegame.h @@ -106,6 +106,11 @@ protected: } } + template <> + void read(QString& value); + + void read(QString& value, bool isUtf8); + void seek(unsigned long pos) { if (!m_File.seek(pos)) { @@ -206,7 +211,4 @@ protected: virtual std::unique_ptr fetchDataFields() const = 0; }; -template <> -void GamebryoSaveGame::FileWrapper::read(QString&); - #endif // GAMEBRYOSAVEGAME_H From 97a1635935f53c6824bf175d3167bcb6f0194653 Mon Sep 17 00:00:00 2001 From: Jeremy Rimpo Date: Sat, 30 Sep 2023 16:22:25 -0500 Subject: [PATCH 1371/1544] [game_skyrim] Add toggle for using fromLocal8Bit - Some games use windows encoding for locality - Allow toggling between loading utf-8 and local8bit, defaulting to utf-8 for backward compatibility --- src/games/skyrim/src/skyrimsavegame.cpp | 92 ++++++++++++------------- 1 file changed, 46 insertions(+), 46 deletions(-) diff --git a/src/games/skyrim/src/skyrimsavegame.cpp b/src/games/skyrim/src/skyrimsavegame.cpp index 0797b20e..35038fd9 100644 --- a/src/games/skyrim/src/skyrimsavegame.cpp +++ b/src/games/skyrim/src/skyrimsavegame.cpp @@ -4,75 +4,75 @@ #include "gameskyrim.h" -SkyrimSaveGame::SkyrimSaveGame(QString const &fileName, GameSkyrim const *game) : - GamebryoSaveGame(fileName, game) +SkyrimSaveGame::SkyrimSaveGame(QString const& fileName, GameSkyrim const* game) : + GamebryoSaveGame(fileName, game) { - FileWrapper file(getFilepath(), "TESV_SAVEGAME"); + FileWrapper file(getFilepath(), "TESV_SAVEGAME"); - FILETIME ftime; - fetchInformationFields(file, m_SaveNumber, m_PCName, m_PCLevel, m_PCLocation, ftime); + FILETIME ftime; + fetchInformationFields(file, m_SaveNumber, m_PCName, m_PCLevel, m_PCLocation, ftime); - //A file time is a 64-bit value that represents the number of 100-nanosecond - //intervals that have elapsed since 12:00 A.M. January 1, 1601 Coordinated Universal Time (UTC). - //So we need to convert that to something useful - SYSTEMTIME ctime; - ::FileTimeToSystemTime(&ftime, &ctime); - setCreationTime(ctime); + //A file time is a 64-bit value that represents the number of 100-nanosecond + //intervals that have elapsed since 12:00 A.M. January 1, 1601 Coordinated Universal Time (UTC). + //So we need to convert that to something useful + SYSTEMTIME ctime; + ::FileTimeToSystemTime(&ftime, &ctime); + setCreationTime(ctime); } void SkyrimSaveGame::fetchInformationFields(FileWrapper& file, - unsigned long& saveNumber, - QString& playerName, - unsigned short& playerLevel, - QString& playerLocation, - FILETIME& creationTime) const + unsigned long& saveNumber, + QString& playerName, + unsigned short& playerLevel, + QString& playerLocation, + FILETIME& creationTime) const { - file.skip(); // header size - file.skip(); // header version - file.read(saveNumber); + file.skip(); // header size + file.skip(); // header version + file.read(saveNumber); - file.read(playerName); + file.read(playerName, false); - unsigned long temp; - file.read(temp); - playerLevel = static_cast(temp); + unsigned long temp; + file.read(temp); + playerLevel = static_cast(temp); - file.read(playerLocation); + file.read(playerLocation, false); - QString timeOfDay; - file.read(timeOfDay); + QString timeOfDay; + file.read(timeOfDay, false); - QString race; - file.read(race); // race name (i.e. BretonRace) + QString race; + file.read(race, false); // race name (i.e. BretonRace) - file.skip(); // Player gender (0 = male) - file.skip(2); // experience gathered, experience required + file.skip(); // Player gender (0 = male) + file.skip(2); // experience gathered, experience required - file.read(creationTime); + file.read(creationTime); } std::unique_ptr SkyrimSaveGame::fetchDataFields() const { - FileWrapper file(getFilepath(), "TESV_SAVEGAME"); - std::unique_ptr fields = std::make_unique(); + FileWrapper file(getFilepath(), "TESV_SAVEGAME"); + std::unique_ptr fields = std::make_unique(); - { - QString dummyName, dummyLocation; - unsigned short dummyLevel; - unsigned long dummySaveNumber; - FILETIME dummyTime; + { + QString dummyName, dummyLocation; + unsigned short dummyLevel; + unsigned long dummySaveNumber; + FILETIME dummyTime; - fetchInformationFields(file, dummySaveNumber, dummyName, dummyLevel, - dummyLocation, dummyTime); - } + fetchInformationFields(file, dummySaveNumber, dummyName, dummyLevel, + dummyLocation, dummyTime); + } - fields->Screenshot = file.readImage(); + fields->Screenshot = file.readImage(); - file.skip(); // form version - file.skip(); // plugin info size + file.skip(); // form version + file.skip(); // plugin info size - fields->Plugins = file.readPlugins(); + fields->Plugins = file.readPlugins(); - return fields; + return fields; } From d3324aa55323bf43dd0bb423804a6299241d2241 Mon Sep 17 00:00:00 2001 From: Jeremy Rimpo Date: Sat, 30 Sep 2023 16:43:13 -0500 Subject: [PATCH 1372/1544] [game_skyrim] Migrate to new enum flags --- src/games/skyrim/src/skyrimsavegame.cpp | 10 ++++++---- 1 file changed, 6 insertions(+), 4 deletions(-) diff --git a/src/games/skyrim/src/skyrimsavegame.cpp b/src/games/skyrim/src/skyrimsavegame.cpp index 35038fd9..db4039cf 100644 --- a/src/games/skyrim/src/skyrimsavegame.cpp +++ b/src/games/skyrim/src/skyrimsavegame.cpp @@ -8,6 +8,7 @@ SkyrimSaveGame::SkyrimSaveGame(QString const& fileName, GameSkyrim const* game) GamebryoSaveGame(fileName, game) { FileWrapper file(getFilepath(), "TESV_SAVEGAME"); + file.setPluginStringFormat(GamebryoSaveGame::LOCAL8BIT); FILETIME ftime; fetchInformationFields(file, m_SaveNumber, m_PCName, m_PCLevel, m_PCLocation, ftime); @@ -32,19 +33,19 @@ void SkyrimSaveGame::fetchInformationFields(FileWrapper& file, file.skip(); // header version file.read(saveNumber); - file.read(playerName, false); + file.read(playerName); unsigned long temp; file.read(temp); playerLevel = static_cast(temp); - file.read(playerLocation, false); + file.read(playerLocation); QString timeOfDay; - file.read(timeOfDay, false); + file.read(timeOfDay); QString race; - file.read(race, false); // race name (i.e. BretonRace) + file.read(race); // race name (i.e. BretonRace) file.skip(); // Player gender (0 = male) file.skip(2); // experience gathered, experience required @@ -55,6 +56,7 @@ void SkyrimSaveGame::fetchInformationFields(FileWrapper& file, std::unique_ptr SkyrimSaveGame::fetchDataFields() const { FileWrapper file(getFilepath(), "TESV_SAVEGAME"); + file.setPluginStringFormat(GamebryoSaveGame::LOCAL8BIT); std::unique_ptr fields = std::make_unique(); { From 1f841484383285cf359bf8b12becbf9429a79fb9 Mon Sep 17 00:00:00 2001 From: Jeremy Rimpo Date: Sat, 30 Sep 2023 16:45:10 -0500 Subject: [PATCH 1373/1544] Use enum instead of new function - Simpler to set once after initializing the FileWrapper - Mirrors WSTRING / BSTRING / BZSTRING --- src/gamebryo/gamebryosavegame.cpp | 19 ++++++++++--------- src/gamebryo/gamebryosavegame.h | 13 +++++++++++-- 2 files changed, 21 insertions(+), 11 deletions(-) diff --git a/src/gamebryo/gamebryosavegame.cpp b/src/gamebryo/gamebryosavegame.cpp index 9b2011a9..ce9f460f 100644 --- a/src/gamebryo/gamebryosavegame.cpp +++ b/src/gamebryo/gamebryosavegame.cpp @@ -92,7 +92,8 @@ void GamebryoSaveGame::setCreationTime(_SYSTEMTIME const& ctime) GamebryoSaveGame::FileWrapper::FileWrapper(QString const& filepath, QString const& expected) : m_File(filepath), m_HasFieldMarkers(false), - m_PluginString(StringType::TYPE_WSTRING), m_NextChunk(0) + m_PluginString(StringType::TYPE_WSTRING), + m_PluginStringFormat(StringFormat::UTF8), m_NextChunk(0) { if (!m_File.open(QIODevice::ReadOnly)) { throw std::runtime_error( @@ -123,6 +124,11 @@ void GamebryoSaveGame::FileWrapper::setPluginString(StringType type) m_PluginString = type; } +void GamebryoSaveGame::FileWrapper::setPluginStringFormat(StringFormat type) +{ + m_PluginStringFormat = type; +} + void GamebryoSaveGame::FileWrapper::readQDataStream(QDataStream& data, void* buff, std::size_t length) { @@ -163,7 +169,8 @@ void GamebryoSaveGame::FileWrapper::skipQDataStream(QDataStream& data, } } -void GamebryoSaveGame::FileWrapper::read(QString& value, bool isUtf8) +template <> +void GamebryoSaveGame::FileWrapper::read(QString& value) { if (m_CompressionType == 0) { unsigned short length; @@ -222,7 +229,7 @@ void GamebryoSaveGame::FileWrapper::read(QString& value, bool isUtf8) m_Data->skipRawData(1); } - if (isUtf8) + if (m_PluginStringFormat == StringFormat::UTF8) value = QString::fromUtf8(buffer.constData()); else value = QString::fromLocal8Bit(buffer.constData()); @@ -232,12 +239,6 @@ void GamebryoSaveGame::FileWrapper::read(QString& value, bool isUtf8) } } -template <> -void GamebryoSaveGame::FileWrapper::read(QString& value) -{ - read(value, true); -} - void GamebryoSaveGame::FileWrapper::read(void* buff, std::size_t length) { int read = m_File.read(static_cast(buff), length); diff --git a/src/gamebryo/gamebryosavegame.h b/src/gamebryo/gamebryosavegame.h index 017c53b9..e7b43fbf 100644 --- a/src/gamebryo/gamebryosavegame.h +++ b/src/gamebryo/gamebryosavegame.h @@ -62,6 +62,12 @@ public: TYPE_WSTRING }; + enum StringFormat + { + UTF8, + LOCAL8BIT + }; + protected: friend class FileWrapper; @@ -86,6 +92,10 @@ protected: **/ void setPluginString(StringType); + /** Set string format (utf-8, windows local 8 bit strings) + **/ + void setPluginStringFormat(StringFormat); + template void skip(int count = 1) { @@ -109,8 +119,6 @@ protected: template <> void read(QString& value); - void read(QString& value, bool isUtf8); - void seek(unsigned long pos) { if (!m_File.seek(pos)) { @@ -166,6 +174,7 @@ protected: uint64_t m_UncompressedSize; bool m_HasFieldMarkers; StringType m_PluginString; + StringFormat m_PluginStringFormat; QDataStream* m_Data; uint16_t m_CompressionType = 0; From 41c43db0e3ec4016f1bdb0c7e6b75c808c9808eb Mon Sep 17 00:00:00 2001 From: Jeremy Rimpo Date: Sat, 30 Sep 2023 16:46:37 -0500 Subject: [PATCH 1374/1544] Fix for linting --- src/gamebryo/gamebryosavegame.h | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/src/gamebryo/gamebryosavegame.h b/src/gamebryo/gamebryosavegame.h index e7b43fbf..dfd5f8d1 100644 --- a/src/gamebryo/gamebryosavegame.h +++ b/src/gamebryo/gamebryosavegame.h @@ -64,8 +64,8 @@ public: enum StringFormat { - UTF8, - LOCAL8BIT + UTF8, + LOCAL8BIT }; protected: @@ -93,7 +93,7 @@ protected: void setPluginString(StringType); /** Set string format (utf-8, windows local 8 bit strings) - **/ + **/ void setPluginStringFormat(StringFormat); template From cc57181c98a5071d8f2c05d59cd85787ebc749e3 Mon Sep 17 00:00:00 2001 From: Jeremy Rimpo Date: Sat, 30 Sep 2023 17:15:36 -0500 Subject: [PATCH 1375/1544] Add to uncompressed string parser --- src/gamebryo/gamebryosavegame.cpp | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/src/gamebryo/gamebryosavegame.cpp b/src/gamebryo/gamebryosavegame.cpp index ce9f460f..7daf96f3 100644 --- a/src/gamebryo/gamebryosavegame.cpp +++ b/src/gamebryo/gamebryosavegame.cpp @@ -200,7 +200,10 @@ void GamebryoSaveGame::FileWrapper::read(QString& value) skip(); } - value = QString::fromUtf8(buffer.constData()); + if (m_PluginStringFormat == StringFormat::UTF8) + value = QString::fromUtf8(buffer.constData()); + else + value = QString::fromLocal8Bit(buffer.constData()); } else if (m_CompressionType == 1 || m_CompressionType == 2) { unsigned short length; if (m_PluginString == StringType::TYPE_BSTRING || From 5ce0d3e5a98862cd1b2e0f3ce44a15ebc42abbbc Mon Sep 17 00:00:00 2001 From: Jeremy Rimpo Date: Sat, 30 Sep 2023 17:16:06 -0500 Subject: [PATCH 1376/1544] [game_skyrim] Only use local8bit for location --- src/games/skyrim/src/skyrimsavegame.cpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/games/skyrim/src/skyrimsavegame.cpp b/src/games/skyrim/src/skyrimsavegame.cpp index db4039cf..a6ded123 100644 --- a/src/games/skyrim/src/skyrimsavegame.cpp +++ b/src/games/skyrim/src/skyrimsavegame.cpp @@ -8,7 +8,6 @@ SkyrimSaveGame::SkyrimSaveGame(QString const& fileName, GameSkyrim const* game) GamebryoSaveGame(fileName, game) { FileWrapper file(getFilepath(), "TESV_SAVEGAME"); - file.setPluginStringFormat(GamebryoSaveGame::LOCAL8BIT); FILETIME ftime; fetchInformationFields(file, m_SaveNumber, m_PCName, m_PCLevel, m_PCLocation, ftime); @@ -39,7 +38,9 @@ void SkyrimSaveGame::fetchInformationFields(FileWrapper& file, file.read(temp); playerLevel = static_cast(temp); + file.setPluginStringFormat(GamebryoSaveGame::LOCAL8BIT); file.read(playerLocation); + file.setPluginStringFormat(GamebryoSaveGame::UTF8); QString timeOfDay; file.read(timeOfDay); @@ -56,7 +57,6 @@ void SkyrimSaveGame::fetchInformationFields(FileWrapper& file, std::unique_ptr SkyrimSaveGame::fetchDataFields() const { FileWrapper file(getFilepath(), "TESV_SAVEGAME"); - file.setPluginStringFormat(GamebryoSaveGame::LOCAL8BIT); std::unique_ptr fields = std::make_unique(); { From 08dd6062da16317b4d252ec52d36f0f28211fbe4 Mon Sep 17 00:00:00 2001 From: Jeremy Rimpo Date: Mon, 2 Oct 2023 15:27:12 -0500 Subject: [PATCH 1377/1544] [game_starfield] Plugin sorting updates - Add enabledPlugins for core plugins which are enabled but NOT auto-loaded (may need to be written to plugins.txt or have an ambiguous load order position) - General Starfield updates - Add enabledPlugins for "BlueprintShips-Starfield.esm" - Disable plugin management if sTestFile is in use (also applies to FO4) - Write the enabledPlugins to plugins.txt to enforce base game load order - Allow for LOOT sorting (dynamic based on settings) - Incorporate enabledPlugins into force enabled plugins in plugin list - Update various interface layers TODO: Fix sort button to dynamically update if status changes TODO: Auto refresh lists if the INI Editor is closed --- src/games/starfield/src/gamestarfield.cpp | 41 ++++++++++++++----- src/games/starfield/src/gamestarfield.h | 4 ++ .../starfield/src/starfieldgameplugins.cpp | 6 +-- 3 files changed, 37 insertions(+), 14 deletions(-) diff --git a/src/games/starfield/src/gamestarfield.cpp b/src/games/starfield/src/gamestarfield.cpp index 1f46df9d..86f67d07 100644 --- a/src/games/starfield/src/gamestarfield.cpp +++ b/src/games/starfield/src/gamestarfield.cpp @@ -135,7 +135,8 @@ QList GameStarfield::settings() const MappingType GameStarfield::mappings() const { MappingType result; - if (m_Organizer->pluginSetting(name(), "enable_plugin_management").toBool()) { + if (m_Organizer->pluginSetting(name(), "enable_plugin_management").toBool() && + testFilePlugins().isEmpty()) { for (const QString& profileFile : {"plugins.txt", "loadorder.txt"}) { result.push_back({m_Organizer->profilePath() + "/" + profileFile, localAppFolder() + "/" + gameShortName() + "/" + profileFile, @@ -175,13 +176,9 @@ QString GameStarfield::steamAPPId() const return "1716740"; } -QStringList GameStarfield::primaryPlugins() const +QStringList GameStarfield::testFilePlugins() const { - QStringList plugins = {"Starfield.esm", "Constellation.esm", "OldMars.esm", - "BlueprintShips-Starfield.esm"}; - - plugins.append(CCPlugins()); - + QStringList plugins; if (m_Organizer != nullptr && m_Organizer->profile() != nullptr) { QString customIni( m_Organizer->profile()->absoluteIniFilePath("StarfieldCustom.ini")); @@ -195,15 +192,36 @@ QStringList GameStarfield::primaryPlugins() const customIni.toStdWString().c_str()); if (length && wcscmp(value, L"") != 0) { QString plugin = QString::fromWCharArray(value, length); - plugins.append(plugin); + if (!plugin.isEmpty() && !plugins.contains(plugin)) + plugins.append(plugin); } } } } + return plugins; +} + +QStringList GameStarfield::primaryPlugins() const +{ + QStringList plugins = {"Starfield.esm", "Constellation.esm", "OldMars.esm"}; + + auto testPlugins = testFilePlugins(); + + if (!testPlugins.isEmpty()) { + plugins += enabledPlugins(); + plugins += testPlugins; + } else { + plugins.append(CCPlugins()); + } return plugins; } +QStringList GameStarfield::enabledPlugins() const +{ + return {"BlueprintShips-Starfield.esm"}; +} + QStringList GameStarfield::gameVariants() const { return {"Regular"}; @@ -265,14 +283,17 @@ QStringList GameStarfield::CCPlugins() const IPluginGame::SortMechanism GameStarfield::sortMechanism() const { + if (m_Organizer->pluginSetting(name(), "enable_plugin_management").toBool() && + testFilePlugins().isEmpty()) + return IPluginGame::SortMechanism::LOOT; return IPluginGame::SortMechanism::NONE; } IPluginGame::LoadOrderMechanism GameStarfield::loadOrderMechanism() const { - if (m_Organizer->pluginSetting(name(), "enable_plugin_management").toBool()) { + if (m_Organizer->pluginSetting(name(), "enable_plugin_management").toBool() && + testFilePlugins().isEmpty()) return IPluginGame::LoadOrderMechanism::PluginsTxt; - } return IPluginGame::LoadOrderMechanism::None; } diff --git a/src/games/starfield/src/gamestarfield.h b/src/games/starfield/src/gamestarfield.h index a29b2eb3..d346c59a 100644 --- a/src/games/starfield/src/gamestarfield.h +++ b/src/games/starfield/src/gamestarfield.h @@ -17,6 +17,9 @@ public: virtual bool init(MOBase::IOrganizer* moInfo) override; +public: + QStringList testFilePlugins() const; + public: // IPluginGame interface virtual QString gameName() const override; virtual void detectGame() override; @@ -29,6 +32,7 @@ public: // IPluginGame interface ProfileSettings settings) const override; virtual QString steamAPPId() const override; virtual QStringList primaryPlugins() const override; + virtual QStringList enabledPlugins() const override; virtual QStringList gameVariants() const override; virtual QString gameShortName() const override; virtual QString gameNexusName() const override; diff --git a/src/games/starfield/src/starfieldgameplugins.cpp b/src/games/starfield/src/starfieldgameplugins.cpp index 3d02b9b7..5806b28c 100644 --- a/src/games/starfield/src/starfieldgameplugins.cpp +++ b/src/games/starfield/src/starfieldgameplugins.cpp @@ -14,10 +14,8 @@ bool StarfieldGamePlugins::overridePluginsAreSupported() void StarfieldGamePlugins::writePluginList(const IPluginList* pluginList, const QString& filePath) { - if (m_Organizer - ->pluginSetting(m_Organizer->managedGame()->name(), - "enable_plugin_management") - .toBool()) { + if (m_Organizer->managedGame()->sortMechanism() != + MOBase::IPluginGame::SortMechanism::NONE) { CreationGamePlugins::writePluginList(pluginList, filePath); } } \ No newline at end of file From 57531c7074a7a46edbb5569ce9a85caec6ba2d9c Mon Sep 17 00:00:00 2001 From: Jeremy Rimpo Date: Mon, 2 Oct 2023 15:27:13 -0500 Subject: [PATCH 1378/1544] Plugin sorting updates - Add enabledPlugins for core plugins which are enabled but NOT auto-loaded (may need to be written to plugins.txt or have an ambiguous load order position) - General Starfield updates - Add enabledPlugins for "BlueprintShips-Starfield.esm" - Disable plugin management if sTestFile is in use (also applies to FO4) - Write the enabledPlugins to plugins.txt to enforce base game load order - Allow for LOOT sorting (dynamic based on settings) - Incorporate enabledPlugins into force enabled plugins in plugin list - Update various interface layers TODO: Fix sort button to dynamically update if status changes TODO: Auto refresh lists if the INI Editor is closed --- src/gamebryo/gamegamebryo.h | 1 + 1 file changed, 1 insertion(+) diff --git a/src/gamebryo/gamegamebryo.h b/src/gamebryo/gamegamebryo.h index 7f671e1b..6e0cb4f4 100644 --- a/src/gamebryo/gamegamebryo.h +++ b/src/gamebryo/gamegamebryo.h @@ -63,6 +63,7 @@ public: // IPluginGame interface // executables // steamAPPId // primaryPlugins + virtual QStringList enabledPlugins() const override { return {}; } virtual QStringList gameVariants() const override; virtual void setGameVariant(const QString& variant) override; virtual QString binaryName() const override; From 87878dd6cbb49f56e34ccc6caa70f41ccdd268ff Mon Sep 17 00:00:00 2001 From: Jeremy Rimpo Date: Mon, 2 Oct 2023 16:04:13 -0500 Subject: [PATCH 1379/1544] Use enum class --- src/gamebryo/gamebryosavegame.h | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/gamebryo/gamebryosavegame.h b/src/gamebryo/gamebryosavegame.h index dfd5f8d1..eebdd8f1 100644 --- a/src/gamebryo/gamebryosavegame.h +++ b/src/gamebryo/gamebryosavegame.h @@ -55,14 +55,14 @@ public: bool isLightEnabled() const { return m_LightEnabled; } - enum StringType + enum class StringType { TYPE_BZSTRING, TYPE_BSTRING, TYPE_WSTRING }; - enum StringFormat + enum class StringFormat { UTF8, LOCAL8BIT From a76d6841ec5e7c2ed10a4f8f96e38b1c91626057 Mon Sep 17 00:00:00 2001 From: Jeremy Rimpo Date: Mon, 2 Oct 2023 19:20:41 -0500 Subject: [PATCH 1380/1544] [game_skyrim] Update enum reference --- src/games/skyrim/src/skyrimsavegame.cpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/games/skyrim/src/skyrimsavegame.cpp b/src/games/skyrim/src/skyrimsavegame.cpp index a6ded123..dd9ef1f4 100644 --- a/src/games/skyrim/src/skyrimsavegame.cpp +++ b/src/games/skyrim/src/skyrimsavegame.cpp @@ -38,9 +38,9 @@ void SkyrimSaveGame::fetchInformationFields(FileWrapper& file, file.read(temp); playerLevel = static_cast(temp); - file.setPluginStringFormat(GamebryoSaveGame::LOCAL8BIT); + file.setPluginStringFormat(GamebryoSaveGame::StringFormat::LOCAL8BIT); file.read(playerLocation); - file.setPluginStringFormat(GamebryoSaveGame::UTF8); + file.setPluginStringFormat(GamebryoSaveGame::StringFormat::UTF8); QString timeOfDay; file.read(timeOfDay); From 79451950736197c68eb834761698cd9f3db67ee8 Mon Sep 17 00:00:00 2001 From: Jeremy Rimpo Date: Tue, 3 Oct 2023 22:54:56 -0500 Subject: [PATCH 1381/1544] [game_falloutnv] Squashed commit of the following: commit d90aac56052bc99548d7e5038645bd7585a76858 Author: Jeremy Rimpo Date: Mon Oct 2 19:31:23 2023 -0500 Filter the install directories to avoid grabbing a hidden directory commit de602320fa8073a53502851efc2b6480f750e7d0 Merge: 72cfce0 fa4c9ba Author: Jeremy Rimpo Date: Sun Oct 1 17:18:37 2023 -0500 Merge branch 'master' of https://github.com/ModOrganizer2/modorganizer-game_falloutnv into epic_support commit 72cfce0910362937d9b9d2f25a2b9be4ed7fe1ac Author: Jeremy Rimpo Date: Sun Oct 1 17:14:51 2023 -0500 GOG 'support' commit 662b84ac39211f41e3cce832bf1db98b7ef5c612 Author: Jeremy Rimpo Date: Sat Sep 30 19:54:33 2023 -0500 Move NVSE to top of 'extra' executables commit 10079e95b8523ec06205fa99e3a4b8eddc13931b Author: Jeremy Rimpo Date: Sat Sep 30 19:46:05 2023 -0500 Update launch args to work properly with EGS commit c3a946ecdb3f11b8e1f8710a4a09fb19b79bc739 Author: Jeremy Rimpo Date: Sat Sep 30 18:51:57 2023 -0500 Virtualize both FalloutNV / _Epic for plugins.txt - Apparently BGS shipped with the launcher using one and the game using the other. (The game uses the original directory.) --- src/games/falloutnv/src/gamefalloutnv.cpp | 33 ++++++++++++++++------- 1 file changed, 23 insertions(+), 10 deletions(-) diff --git a/src/games/falloutnv/src/gamefalloutnv.cpp b/src/games/falloutnv/src/gamefalloutnv.cpp index d9bb80d0..247c0878 100644 --- a/src/games/falloutnv/src/gamefalloutnv.cpp +++ b/src/games/falloutnv/src/gamefalloutnv.cpp @@ -55,8 +55,11 @@ void GameFalloutNV::setVariant(QString variant) void GameFalloutNV::checkVariants() { + QFileInfo gog_dll(m_GamePath + "\\Galaxy.dll"); QFileInfo epic_dll(m_GamePath + "\\EOSSDK-Win32-Shipping.dll"); - if (epic_dll.exists()) + if (gog_dll.exists()) + setVariant("GOG"); + else if (epic_dll.exists()) setVariant("Epic Games"); else setVariant("Steam"); @@ -84,7 +87,8 @@ QString GameFalloutNV::identifyGamePath() const result = parseEpicGamesLocation({"5daeb974a22a435988892319b3a4f476"}); if (QFileInfo(result).isDir()) { QDir startPath = QDir(result); - auto subDirs = startPath.entryList(QDir::Dirs | QDir::NoDotAndDotDot); + auto subDirs = startPath.entryList({"Fallout New Vegas*"}, + QDir::Dirs | QDir::NoDotAndDotDot); if (!subDirs.isEmpty()) result = subDirs.first(); } @@ -141,19 +145,24 @@ void GameFalloutNV::detectGame() QList GameFalloutNV::executables() const { - QList executables = + ExecutableInfo game("New Vegas", findInGameFolder(binaryName())); + ExecutableInfo launcher("Fallout Launcher", findInGameFolder(getLauncherName())); + QList extraExecutables = QList() - << ExecutableInfo("New Vegas", findInGameFolder(binaryName())) << ExecutableInfo("Fallout Mod Manager", findInGameFolder("fomm/fomm.exe")) << ExecutableInfo("Construction Kit", findInGameFolder("geck.exe")) - << ExecutableInfo("Fallout Launcher", findInGameFolder(getLauncherName())) << ExecutableInfo("BOSS", findInGameFolder("BOSS/BOSS.exe")) << ExecutableInfo("LOOT", QFileInfo(getLootPath())) .withArgument("--game=\"FalloutNV\""); - if (selectedVariant() == "Epic Games") { - executables.append(ExecutableInfo( + if (selectedVariant() != "Epic Games") { + extraExecutables.prepend(ExecutableInfo( "NVSE", findInGameFolder(feature()->loaderName()))); + } else { + game.withArgument("-EpicPortal"); + launcher.withArgument("-EpicPortal"); } + QList executables = {game, launcher}; + executables += extraExecutables; return executables; } @@ -243,7 +252,7 @@ QStringList GameFalloutNV::primaryPlugins() const QStringList GameFalloutNV::gameVariants() const { - return {"Steam", "Epic Games"}; + return {"Steam", "GOG", "Epic Games"}; } QString GameFalloutNV::gameShortName() const @@ -289,15 +298,19 @@ QDir GameFalloutNV::gameDirectory() const return QDir(m_GamePath); } -// Not to delete all the spaces... MappingType GameFalloutNV::mappings() const { MappingType result; for (const QString& profileFile : {"plugins.txt", "loadorder.txt"}) { result.push_back({m_Organizer->profilePath() + "/" + profileFile, - localAppFolder() + "/" + gameDirectoryName() + "/" + profileFile, + localAppFolder() + "/" + gameShortName() + "/" + profileFile, false}); + if (selectedVariant() == "Epic Games") { + result.push_back( + {m_Organizer->profilePath() + "/" + profileFile, + localAppFolder() + "/" + gameDirectoryName() + "/" + profileFile, false}); + } } return result; From 3439dfbcc2e8a892e2211177facfdfd5695a525e Mon Sep 17 00:00:00 2001 From: Jeremy Rimpo Date: Tue, 3 Oct 2023 22:59:55 -0500 Subject: [PATCH 1382/1544] [game_starfield] Only read plugins.txt if enabled --- src/games/starfield/src/starfieldgameplugins.cpp | 9 +++++++++ src/games/starfield/src/starfieldgameplugins.h | 1 + 2 files changed, 10 insertions(+) diff --git a/src/games/starfield/src/starfieldgameplugins.cpp b/src/games/starfield/src/starfieldgameplugins.cpp index 5806b28c..93f2e477 100644 --- a/src/games/starfield/src/starfieldgameplugins.cpp +++ b/src/games/starfield/src/starfieldgameplugins.cpp @@ -18,4 +18,13 @@ void StarfieldGamePlugins::writePluginList(const IPluginList* pluginList, MOBase::IPluginGame::SortMechanism::NONE) { CreationGamePlugins::writePluginList(pluginList, filePath); } +} + +QStringList StarfieldGamePlugins::readPluginList(MOBase::IPluginList* pluginList) +{ + if (m_Organizer->managedGame()->sortMechanism() != + MOBase::IPluginGame::SortMechanism::NONE) { + return CreationGamePlugins::readPluginList(pluginList); + } + return {}; } \ No newline at end of file diff --git a/src/games/starfield/src/starfieldgameplugins.h b/src/games/starfield/src/starfieldgameplugins.h index 49c46a7c..652ef70e 100644 --- a/src/games/starfield/src/starfieldgameplugins.h +++ b/src/games/starfield/src/starfieldgameplugins.h @@ -16,6 +16,7 @@ protected: virtual bool overridePluginsAreSupported() override; virtual void writePluginList(const MOBase::IPluginList* pluginList, const QString& filePath) override; + virtual QStringList readPluginList(MOBase::IPluginList* pluginList) override; }; #endif // _STARFIELDGAMEPLUGINS_H From 9e26e71d984a268315d5dc76befede93373b27e8 Mon Sep 17 00:00:00 2001 From: Jeremy Rimpo Date: Tue, 3 Oct 2023 23:13:31 -0500 Subject: [PATCH 1383/1544] Move 'empty' defaults to uibase --- src/gamebryo/gamegamebryo.cpp | 25 ------------------------- src/gamebryo/gamegamebryo.h | 12 ++++++------ 2 files changed, 6 insertions(+), 31 deletions(-) diff --git a/src/gamebryo/gamegamebryo.cpp b/src/gamebryo/gamegamebryo.cpp index a60d7260..b01d1370 100644 --- a/src/gamebryo/gamegamebryo.cpp +++ b/src/gamebryo/gamegamebryo.cpp @@ -72,11 +72,6 @@ QDir GameGamebryo::dataDirectory() const return gameDirectory().absoluteFilePath("data"); } -QMap GameGamebryo::secondaryDataDirectories() const -{ - return QMap(); -} - void GameGamebryo::setGamePath(const QString& path) { m_GamePath = path; @@ -106,11 +101,6 @@ GameGamebryo::listSaves(QDir folder) const return saves; } -QStringList GameGamebryo::gameVariants() const -{ - return QStringList(); -} - void GameGamebryo::setGameVariant(const QString& variant) { m_GameVariant = variant; @@ -121,21 +111,6 @@ QString GameGamebryo::binaryName() const return gameShortName() + ".exe"; } -QStringList GameGamebryo::primarySources() const -{ - return {}; -} - -QStringList GameGamebryo::validShortNames() const -{ - return {}; -} - -QStringList GameGamebryo::CCPlugins() const -{ - return {}; -} - MOBase::IPluginGame::LoadOrderMechanism GameGamebryo::loadOrderMechanism() const { return LoadOrderMechanism::FileTime; diff --git a/src/gamebryo/gamegamebryo.h b/src/gamebryo/gamegamebryo.h index 6e0cb4f4..306df84e 100644 --- a/src/gamebryo/gamegamebryo.h +++ b/src/gamebryo/gamegamebryo.h @@ -56,23 +56,23 @@ public: // IPluginGame interface virtual QIcon gameIcon() const override; virtual QDir gameDirectory() const override; virtual QDir dataDirectory() const override; - virtual QMap secondaryDataDirectories() const override; + // secondaryDataDirectories virtual void setGamePath(const QString& path) override; virtual QDir documentsDirectory() const override; virtual QDir savesDirectory() const override; // executables // steamAPPId // primaryPlugins - virtual QStringList enabledPlugins() const override { return {}; } - virtual QStringList gameVariants() const override; + // enabledPlugins + // gameVariants virtual void setGameVariant(const QString& variant) override; virtual QString binaryName() const override; // gameShortName - virtual QStringList primarySources() const override; - virtual QStringList validShortNames() const override; + // primarySources + // validShortNames // iniFiles // DLCPlugins - virtual QStringList CCPlugins() const override; + // CCPlugins virtual LoadOrderMechanism loadOrderMechanism() const override; virtual SortMechanism sortMechanism() const override; // nexusModOrganizerID From 61d3030ab3ac15d4a00d294a1cbe29459c88f357 Mon Sep 17 00:00:00 2001 From: Jeremy Rimpo Date: Wed, 4 Oct 2023 16:50:16 -0500 Subject: [PATCH 1384/1544] [game_starfield] Don't include 'force-enabled' plugins --- src/games/starfield/src/starfieldunmanagedmods.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/games/starfield/src/starfieldunmanagedmods.cpp b/src/games/starfield/src/starfieldunmanagedmods.cpp index 6b42b226..037d57c3 100644 --- a/src/games/starfield/src/starfieldunmanagedmods.cpp +++ b/src/games/starfield/src/starfieldunmanagedmods.cpp @@ -10,7 +10,7 @@ QStringList StarfieldUnmangedMods::mods(bool onlyOfficial) const { QStringList result; - QStringList pluginList = game()->primaryPlugins(); + QStringList pluginList = game()->primaryPlugins() + game()->enabledPlugins(); QStringList otherPlugins = game()->DLCPlugins(); otherPlugins.append(game()->CCPlugins()); for (QString plugin : otherPlugins) { From 19a487509cc09ecf855d28bfe737c26405844166 Mon Sep 17 00:00:00 2001 From: Liderate Date: Thu, 5 Oct 2023 01:15:22 -0400 Subject: [PATCH 1385/1544] [game_ttw] Epic Games Support for TTW --- src/games/ttw/src/gamefalloutttw.cpp | 208 +++++++++++++++++++-------- src/games/ttw/src/gamefalloutttw.h | 43 +++--- 2 files changed, 176 insertions(+), 75 deletions(-) diff --git a/src/games/ttw/src/gamefalloutttw.cpp b/src/games/ttw/src/gamefalloutttw.cpp index f71d1660..7d3b640b 100644 --- a/src/games/ttw/src/gamefalloutttw.cpp +++ b/src/games/ttw/src/gamefalloutttw.cpp @@ -2,16 +2,16 @@ #include "falloutttwbsainvalidation.h" #include "falloutttwdataarchives.h" -#include "falloutttwscriptextender.h" #include "falloutttwmoddatachecker.h" #include "falloutttwmoddatacontent.h" #include "falloutttwsavegame.h" +#include "falloutttwscriptextender.h" #include "executableinfo.h" #include "pluginsetting.h" #include "versioninfo.h" -#include #include +#include #include #include @@ -27,17 +27,9 @@ using namespace MOBase; -GameFalloutTTW::GameFalloutTTW() -{ -} +GameFalloutTTW::GameFalloutTTW() {} -void GameFalloutTTW::detectGame() -{ - GameGamebryo::detectGame(); - m_MyGamesPath = determineMyGamesPath("FalloutNV"); -} - -bool GameFalloutTTW::init(IOrganizer *moInfo) +bool GameFalloutTTW::init(IOrganizer* moInfo) { if (!GameGamebryo::init(moInfo)) { return false; @@ -45,9 +37,11 @@ bool GameFalloutTTW::init(IOrganizer *moInfo) registerFeature(new FalloutTTWScriptExtender(this)); registerFeature(new FalloutTTWDataArchives(myGamesPath())); - registerFeature(new FalloutTTWBSAInvalidation(feature(), this)); + registerFeature( + new FalloutTTWBSAInvalidation(feature(), this)); registerFeature(new GamebryoSaveGameInfo(this)); - registerFeature(new GamebryoLocalSavegames(myGamesPath(), "fallout.ini")); + registerFeature( + new GamebryoLocalSavegames(myGamesPath(), "fallout.ini")); registerFeature(new FalloutTTWModDataChecker(this)); registerFeature(new FalloutTTWModDataContent(this)); registerFeature(new GamebryoGamePlugins(moInfo)); @@ -55,22 +49,122 @@ bool GameFalloutTTW::init(IOrganizer *moInfo) 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 +{ + auto result = GameGamebryo::identifyGamePath(); // Default registry path + // 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()); + registerFeature(new FalloutTTWDataArchives(myGamesPath())); + registerFeature( + new FalloutTTWBSAInvalidation(feature(), this)); + registerFeature( + new GamebryoLocalSavegames(myGamesPath(), "fallout.ini")); +} + +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::gameDirectoryName() const +{ + if (selectedVariant() == "Epic Games") + return "FalloutNV_Epic"; + else + return "FalloutNV"; +} + +void GameFalloutTTW::detectGame() +{ + m_GamePath = identifyGamePath(); + checkVariants(); + m_MyGamesPath = determineMyGamesPath(gameDirectoryName()); +} + QList GameFalloutTTW::executables() const { - return QList() - << ExecutableInfo("NVSE", findInGameFolder(feature()->loaderName())) - << ExecutableInfo("Tale of Two Wastelands", findInGameFolder(binaryName())) + ExecutableInfo game("Tale of Two Wastelands", findInGameFolder(binaryName())); + ExecutableInfo launcher("Fallout Launcher", findInGameFolder(getLauncherName())); + QList extraExecutables = + QList() << ExecutableInfo("Fallout Mod Manager", findInGameFolder("fomm/fomm.exe")) << ExecutableInfo("Construction Kit", findInGameFolder("geck.exe")) - << ExecutableInfo("Fallout Launcher", findInGameFolder(getLauncherName())) << ExecutableInfo("BOSS", findInGameFolder("BOSS/BOSS.exe")) - << ExecutableInfo("LOOT", QFileInfo(getLootPath())).withArgument("--game=\"FalloutNV\"") - ; + << ExecutableInfo("LOOT", QFileInfo(getLootPath())) + .withArgument("--game=\"FalloutNV\""); + if (selectedVariant() != "Epic Games") { + extraExecutables.prepend(ExecutableInfo( + "NVSE", findInGameFolder(feature()->loaderName()))); + } else { + game.withArgument("-EpicPortal"); + launcher.withArgument("-EpicPortal"); + } + QList executables = {game, launcher}; + executables += extraExecutables; + return executables; } QList GameFalloutTTW::executableForcedLoads() const @@ -108,16 +202,17 @@ QList GameFalloutTTW::settings() const return QList(); } -void GameFalloutTTW::initializeProfile(const QDir &path, ProfileSettings settings) const +void GameFalloutTTW::initializeProfile(const QDir& path, ProfileSettings settings) const { if (settings.testFlag(IPluginGame::MODS)) { - copyToProfile(localAppFolder() + "/FalloutNV", path, "plugins.txt"); + 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"); + 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"); } @@ -140,12 +235,12 @@ QString GameFalloutTTW::savegameSEExtension() const return "nvse"; } -std::shared_ptr GameFalloutTTW::makeSaveGame(QString filePath) const +std::shared_ptr +GameFalloutTTW::makeSaveGame(QString filePath) const { return std::make_shared(filePath, this); } - QString GameFalloutTTW::steamAPPId() const { return "22380"; @@ -153,23 +248,17 @@ QString GameFalloutTTW::steamAPPId() const 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" }; + 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"}; +} + +QStringList GameFalloutTTW::gameVariants() const +{ + return {"Steam", "GOG", "Epic Games"}; } QString GameFalloutTTW::binaryName() const @@ -184,12 +273,12 @@ QString GameFalloutTTW::gameShortName() const QStringList GameFalloutTTW::primarySources() const { - return { "FalloutNV" }; + return {"FalloutNV"}; } QStringList GameFalloutTTW::validShortNames() const { - return { "FalloutNV", "Fallout3" }; + return {"FalloutNV", "Fallout3"}; } QString GameFalloutTTW::gameNexusName() const @@ -199,7 +288,8 @@ QString GameFalloutTTW::gameNexusName() const QStringList GameFalloutTTW::iniFiles() const { - return { "fallout.ini", "falloutprefs.ini", "falloutcustom.ini", "custom.ini", "GECKCustom.ini", "GECKPrefs.ini" }; + return {"fallout.ini", "falloutprefs.ini", "falloutcustom.ini", + "custom.ini", "GECKCustom.ini", "GECKPrefs.ini"}; } QStringList GameFalloutTTW::DLCPlugins() const @@ -222,26 +312,28 @@ int GameFalloutTTW::nexusGameID() const return 0; } +QDir GameFalloutTTW::gameDirectory() const +{ + return QDir(m_GamePath); +} + QString GameFalloutTTW::getLauncherName() const { return "FalloutNVLauncher.exe"; } -QString GameFalloutTTW::identifyGamePath() const -{ - QString path = "Software\\Bethesda Softworks\\FalloutNV"; - return findInRegistry(HKEY_LOCAL_MACHINE, path.toStdWString().c_str(), L"Installed Path"); -} - 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 }); + 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/src/games/ttw/src/gamefalloutttw.h b/src/games/ttw/src/gamefalloutttw.h index 95d20424..8394c1a4 100644 --- a/src/games/ttw/src/gamefalloutttw.h +++ b/src/games/ttw/src/gamefalloutttw.h @@ -9,39 +9,43 @@ class GameFalloutTTW : public GameGamebryo { Q_OBJECT -#if QT_VERSION >= QT_VERSION_CHECK(5,0,0) +#if QT_VERSION >= QT_VERSION_CHECK(5, 0, 0) Q_PLUGIN_METADATA(IID "org.tannin.GameFalloutTTW" FILE "gamefalloutttw.json") #endif public: - GameFalloutTTW(); - void detectGame() override; - bool init(MOBase::IOrganizer *moInfo) override; - -public: // IPluginGame interface + bool init(MOBase::IOrganizer* moInfo) override; +public: // IPluginGame interface virtual QString gameName() const override; + virtual void detectGame() override; virtual QList executables() const override; - virtual QList executableForcedLoads() const override; - virtual void initializeProfile(const QDir &path, ProfileSettings settings) const override; + virtual QList + 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 primarySources() const override; virtual QStringList validShortNames() const override; virtual QString gameNexusName() const override; virtual QStringList iniFiles() const override; virtual QStringList DLCPlugins() const override; - virtual SortMechanism sortMechanism() const override; virtual int nexusModOrganizerID() const override; virtual int nexusGameID() const override; + virtual QStringList primarySources() const override; + virtual SortMechanism sortMechanism() const override; virtual QString getLauncherName() const override; -public: // IPlugin interface + 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; @@ -49,18 +53,23 @@ public: // IPlugin interface virtual MOBase::VersionInfo version() const override; virtual QList settings() const override; -public: // IPluginFileMapper interface - +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 makeSaveGame(QString filePath) const override; - - virtual QString identifyGamePath() const override; - }; -#endif // GAMEFALLOUTTTW_H +#endif // GAMEFALLOUTTTW_H From 41aa85cfa4fff6d1775f5b52312dbb48f18c8fdd Mon Sep 17 00:00:00 2001 From: Jeremy Rimpo Date: Fri, 6 Oct 2023 02:19:46 -0500 Subject: [PATCH 1386/1544] [game_starfield] Fix nexus game ID --- src/games/starfield/src/gamestarfield.cpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/games/starfield/src/gamestarfield.cpp b/src/games/starfield/src/gamestarfield.cpp index 86f67d07..a6c515f2 100644 --- a/src/games/starfield/src/gamestarfield.cpp +++ b/src/games/starfield/src/gamestarfield.cpp @@ -299,10 +299,10 @@ IPluginGame::LoadOrderMechanism GameStarfield::loadOrderMechanism() const int GameStarfield::nexusModOrganizerID() const { - return 28715; + return 0; } int GameStarfield::nexusGameID() const { - return 1151; + return 4187; } From 305bb18df83ee3095c292c46617e47de59e6bfdd Mon Sep 17 00:00:00 2001 From: Jeremy Rimpo Date: Thu, 5 Oct 2023 19:09:49 -0500 Subject: [PATCH 1387/1544] [game_falloutnv] Include directory path --- src/games/falloutnv/src/gamefalloutnv.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/games/falloutnv/src/gamefalloutnv.cpp b/src/games/falloutnv/src/gamefalloutnv.cpp index 247c0878..072cc8b0 100644 --- a/src/games/falloutnv/src/gamefalloutnv.cpp +++ b/src/games/falloutnv/src/gamefalloutnv.cpp @@ -90,7 +90,7 @@ QString GameFalloutNV::identifyGamePath() const auto subDirs = startPath.entryList({"Fallout New Vegas*"}, QDir::Dirs | QDir::NoDotAndDotDot); if (!subDirs.isEmpty()) - result = subDirs.first(); + result = startPath.absoluteFilePath(subDirs.first()); } } return result; From 2b848dff08cf81a386f3f2ec472546501c8c8d43 Mon Sep 17 00:00:00 2001 From: Jeremy Rimpo Date: Sun, 8 Oct 2023 03:21:38 -0500 Subject: [PATCH 1388/1544] [game_starfield] Fix enabled plugins when management disabled --- src/games/starfield/src/gamestarfield.cpp | 9 ++++----- 1 file changed, 4 insertions(+), 5 deletions(-) diff --git a/src/games/starfield/src/gamestarfield.cpp b/src/games/starfield/src/gamestarfield.cpp index a6c515f2..9a44e322 100644 --- a/src/games/starfield/src/gamestarfield.cpp +++ b/src/games/starfield/src/gamestarfield.cpp @@ -206,12 +206,11 @@ QStringList GameStarfield::primaryPlugins() const QStringList plugins = {"Starfield.esm", "Constellation.esm", "OldMars.esm"}; auto testPlugins = testFilePlugins(); - - if (!testPlugins.isEmpty()) { - plugins += enabledPlugins(); - plugins += testPlugins; + if (loadOrderMechanism() == LoadOrderMechanism::None) { + plugins << enabledPlugins(); + plugins << testPlugins; } else { - plugins.append(CCPlugins()); + plugins << CCPlugins(); } return plugins; From 2170e7ec04eca3e4c0fc15d74b0f3a6759066575 Mon Sep 17 00:00:00 2001 From: Jeremy Rimpo Date: Sun, 8 Oct 2023 04:34:55 -0500 Subject: [PATCH 1389/1544] [game_starfield] Add LOOT to executables --- src/games/starfield/src/gamestarfield.cpp | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/src/games/starfield/src/gamestarfield.cpp b/src/games/starfield/src/gamestarfield.cpp index 9a44e322..9db78ec7 100644 --- a/src/games/starfield/src/gamestarfield.cpp +++ b/src/games/starfield/src/gamestarfield.cpp @@ -89,7 +89,9 @@ QList GameStarfield::executables() const return QList() << ExecutableInfo("SFSE", findInGameFolder(feature()->loaderName())) - << ExecutableInfo("Starfield", findInGameFolder(binaryName())); + << ExecutableInfo("Starfield", findInGameFolder(binaryName())) + << ExecutableInfo("LOOT", QFileInfo(getLootPath())) + .withArgument("--game=\"Starfield\""); } QList GameStarfield::executableForcedLoads() const From 99d7805d7c6e006b54d5a19263cc7cf6bd26c547 Mon Sep 17 00:00:00 2001 From: Jeremy Rimpo Date: Sun, 8 Oct 2023 15:53:37 -0500 Subject: [PATCH 1390/1544] [game_starfield] Add geometries to valid data and content type --- .../starfield/src/starfieldmoddatachecker.h | 8 +++---- .../starfield/src/starfieldmoddatacontent.h | 23 +++++++++++++------ 2 files changed, 20 insertions(+), 11 deletions(-) diff --git a/src/games/starfield/src/starfieldmoddatachecker.h b/src/games/starfield/src/starfieldmoddatachecker.h index 90c3eee9..fa63e5a7 100644 --- a/src/games/starfield/src/starfieldmoddatachecker.h +++ b/src/games/starfield/src/starfieldmoddatachecker.h @@ -12,10 +12,10 @@ protected: virtual const FileNameSet& possibleFolderNames() const override { static FileNameSet result{ - "interface", "meshes", "music", "scripts", "sound", "strings", - "textures", "trees", "video", "materials", "sfse", "distantlod", - "asi", "Tools", "MCM", "distantland", "mits", "dllplugins", - "CalienteTools", "shadersfx", "aaf", "root"}; + "interface", "meshes", "geometries", "music", "scripts", "sound", + "strings", "textures", "trees", "video", "materials", "sfse", + "distantlod", "asi", "Tools", "MCM", "distantland", "mits", + "dllplugins", "CalienteTools", "shadersfx", "aaf", "root"}; return result; } virtual const FileNameSet& possibleFileExtensions() const override diff --git a/src/games/starfield/src/starfieldmoddatacontent.h b/src/games/starfield/src/starfieldmoddatacontent.h index da33044c..66cbf9ca 100644 --- a/src/games/starfield/src/starfieldmoddatacontent.h +++ b/src/games/starfield/src/starfieldmoddatacontent.h @@ -9,21 +9,27 @@ class StarfieldModDataContent : public GamebryoModDataContent protected: enum StarfieldContent { - CONTENT_MATERIAL = CONTENT_NEXT_VALUE + CONTENT_MATERIAL = CONTENT_NEXT_VALUE, + CONTENT_GEOMETRIES = CONTENT_NEXT_VALUE + 1 }; public: StarfieldModDataContent(GameGamebryo const* gamePlugin) : GamebryoModDataContent(gamePlugin) { - m_Enabled[CONTENT_SKYPROC] = false; + m_Enabled[CONTENT_SKYPROC] = false; + m_Enabled[CONTENT_MATERIAL] = true; + m_Enabled[CONTENT_GEOMETRIES] = true; } std::vector getAllContents() const override { + static std::vector STARFIELD_CONTENTS{ + {CONTENT_MATERIAL, QT_TR_NOOP("Materials"), ":/MO/gui/content/material"}, + {CONTENT_GEOMETRIES, QT_TR_NOOP("Geometries"), ":/MO/gui/content/mesh"}}; auto contents = GamebryoModDataContent::getAllContents(); - contents.push_back( - Content(CONTENT_MATERIAL, "Materials", ":/MO/gui/content/material")); + std::copy(std::begin(STARFIELD_CONTENTS), std::end(STARFIELD_CONTENTS), + std::back_inserter(contents)); return contents; } @@ -32,9 +38,12 @@ public: { auto contents = GamebryoModDataContent::getContentsFor(fileTree); for (auto e : *fileTree) { - if (e->compare("materials") == 0) { - contents.push_back(CONTENT_MATERIAL); - break; // Early break if you have nothing else to check. + if (e->isDir()) { + if (e->compare("materials") == 0) { + contents.push_back(CONTENT_MATERIAL); + } else if (e->compare("geometries") == 0) { + contents.push_back(CONTENT_GEOMETRIES); + } } } return contents; From ba4b50e5fedfd905a704138b24b04fc4ec3e9b2c Mon Sep 17 00:00:00 2001 From: Jeremy Rimpo Date: Tue, 17 Oct 2023 01:02:57 -0500 Subject: [PATCH 1391/1544] [game_starfield] Add new content images to resources --- src/games/starfield/src/starfieldmoddatacontent.h | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) diff --git a/src/games/starfield/src/starfieldmoddatacontent.h b/src/games/starfield/src/starfieldmoddatacontent.h index 66cbf9ca..574e7baf 100644 --- a/src/games/starfield/src/starfieldmoddatacontent.h +++ b/src/games/starfield/src/starfieldmoddatacontent.h @@ -10,7 +10,8 @@ protected: enum StarfieldContent { CONTENT_MATERIAL = CONTENT_NEXT_VALUE, - CONTENT_GEOMETRIES = CONTENT_NEXT_VALUE + 1 + CONTENT_GEOMETRIES = CONTENT_NEXT_VALUE + 1, + CONTENT_VIDEO = CONTENT_NEXT_VALUE + 2 }; public: @@ -26,7 +27,8 @@ public: { static std::vector STARFIELD_CONTENTS{ {CONTENT_MATERIAL, QT_TR_NOOP("Materials"), ":/MO/gui/content/material"}, - {CONTENT_GEOMETRIES, QT_TR_NOOP("Geometries"), ":/MO/gui/content/mesh"}}; + {CONTENT_GEOMETRIES, QT_TR_NOOP("Geometries"), ":/MO/gui/content/geometries"}, + {CONTENT_VIDEO, QT_TR_NOOP("Video"), ":/MO/gui/content/media"}}; auto contents = GamebryoModDataContent::getAllContents(); std::copy(std::begin(STARFIELD_CONTENTS), std::end(STARFIELD_CONTENTS), std::back_inserter(contents)); @@ -43,6 +45,8 @@ public: contents.push_back(CONTENT_MATERIAL); } else if (e->compare("geometries") == 0) { contents.push_back(CONTENT_GEOMETRIES); + } else if (e->compare("video") == 0) { + contents.push_back(CONTENT_VIDEO); } } } From b9393360768a623cf34b626cf807e106ef78f105 Mon Sep 17 00:00:00 2001 From: Jeremy Rimpo Date: Tue, 17 Oct 2023 00:47:53 -0500 Subject: [PATCH 1392/1544] [game_starfield] Add IPluginDiagnose interface * Check for ESP files * Check for non-dummy light files * Check for overlay files * Checks for plugin management compatibility --- src/games/starfield/src/gamestarfield.cpp | 202 ++++++++++++++++++++++ src/games/starfield/src/gamestarfield.h | 30 +++- 2 files changed, 230 insertions(+), 2 deletions(-) diff --git a/src/games/starfield/src/gamestarfield.cpp b/src/games/starfield/src/gamestarfield.cpp index 9db78ec7..3470f25f 100644 --- a/src/games/starfield/src/gamestarfield.cpp +++ b/src/games/starfield/src/gamestarfield.cpp @@ -1,5 +1,7 @@ #include "gamestarfield.h" +#include "ipluginlist.h" + #include "starfieldbsainvalidation.h" #include "starfielddataarchives.h" #include "starfieldgameplugins.h" @@ -16,6 +18,7 @@ #include #include +#include #include #include #include @@ -26,6 +29,7 @@ #include #include "scopeguard.h" +#include "utility.h" using namespace MOBase; @@ -307,3 +311,201 @@ int GameStarfield::nexusGameID() const { return 4187; } + +// Start Diagnose +std::vector GameStarfield::activeProblems() const +{ + std::vector result; + if (m_Organizer->managedGame() == this) { + if (activeESP()) + result.push_back(PROBLEM_ESP); + if (activeESL()) + result.push_back(PROBLEM_ESL); + if (activeOverlay()) + result.push_back(PROBLEM_OVERLAY); + if (testFilePresent()) + result.push_back(PROBLEM_TEST_FILE); + else if (pluginsTxtEnabler()) + result.push_back(PROBLEM_PLUGINS_TXT); + } + return result; +} + +bool GameStarfield::activeESP() const +{ + m_Active_ESPs.clear(); + std::set enabledPlugins; + + QStringList esps = m_Organizer->findFiles("", [](const QString& fileName) -> bool { + return fileName.endsWith(".esp", FileNameComparator::CaseSensitivity); + }); + + for (const QString& esp : esps) { + QString baseName = QFileInfo(esp).fileName(); + if (m_Organizer->pluginList()->state(baseName) == IPluginList::STATE_ACTIVE) { + m_Active_ESPs.insert(baseName); + } + } + + if (!m_Active_ESPs.empty()) + return true; + return false; +} + +bool GameStarfield::activeESL() const +{ + m_Active_ESLs.clear(); + std::set enabledPlugins; + + QStringList esps = m_Organizer->findFiles("", [](const QString& fileName) -> bool { + return fileName.endsWith(".esp", FileNameComparator::CaseSensitivity) || + fileName.endsWith(".esm", FileNameComparator::CaseSensitivity) || + fileName.endsWith(".esl", FileNameComparator::CaseSensitivity); + }); + + for (const QString& esp : esps) { + QString baseName = QFileInfo(esp).fileName(); + if (primaryPlugins().contains(baseName, Qt::CaseInsensitive)) + continue; + if (m_Organizer->pluginList()->state(baseName) == IPluginList::STATE_ACTIVE && + !m_Organizer->pluginList()->isDummy(baseName)) + if (m_Organizer->pluginList()->hasLightExtension(baseName) || + m_Organizer->pluginList()->isLightFlagged(baseName)) + m_Active_ESLs.insert(baseName); + } + + if (!m_Active_ESLs.empty()) + return true; + return false; +} + +bool GameStarfield::activeOverlay() const +{ + m_Active_Overlays.clear(); + std::set enabledPlugins; + + QStringList esps = m_Organizer->findFiles("", [](const QString& fileName) -> bool { + return fileName.endsWith(".esp", FileNameComparator::CaseSensitivity) || + fileName.endsWith(".esm", FileNameComparator::CaseSensitivity) || + fileName.endsWith(".esl", FileNameComparator::CaseSensitivity); + }); + + for (const QString& esp : esps) { + QString baseName = QFileInfo(esp).fileName(); + if (primaryPlugins().contains(baseName, Qt::CaseInsensitive)) + continue; + if (m_Organizer->pluginList()->state(baseName) == IPluginList::STATE_ACTIVE) { + if (m_Organizer->pluginList()->isOverlayFlagged(baseName)) + m_Active_Overlays.insert(baseName); + } + } + + if (!m_Active_Overlays.empty()) + return true; + return false; +} + +bool GameStarfield::testFilePresent() const +{ + if (m_Organizer->pluginSetting(name(), "enable_plugin_management").toBool() && + !testFilePlugins().isEmpty()) + return true; + return false; +} + +bool GameStarfield::pluginsTxtEnabler() const +{ + if (sortMechanism() != SortMechanism::NONE) { + auto files = m_Organizer->findFiles("sfse\\plugins", {"sfpluginstxtenabler.dll"}); + if (files.isEmpty()) + return true; + } + return false; +} + +QString GameStarfield::shortDescription(unsigned int key) const +{ + switch (key) { + case PROBLEM_ESP: + return tr("You have active ESP plugins in Starfield"); + case PROBLEM_ESL: + return tr("You have active ESL plugins in Starfield"); + case PROBLEM_OVERLAY: + return tr("You have active overlay plugins"); + case PROBLEM_TEST_FILE: + return tr("sTestFile entries are present"); + case PROBLEM_PLUGINS_TXT: + return tr("Plugins.txt Enabler missing"); + } +} + +QString GameStarfield::fullDescription(unsigned int key) const +{ + switch (key) { + case PROBLEM_ESP: { + QString espInfo = SetJoin(m_Active_ESPs, ", "); + return tr("

ESP plugins are not ideal for Starfield. They cannot be sorted " + "alongside ESM or master-flagged plugins and always have their records " + "loaded by the game, taking up unnecessary space in memory.

" + "

Ideally, plugins should be saved as ESM files upon release. It can " + "also " + "be released as an ESL plugin, however there are additional concerns " + "with the way light plugins are currently handled and should only be " + "used when absolutely certain about what you're doing.

" + "

Notably, xEdit does not currently support saving ESP files.

" + "

Current ESPs:

%1

") + .arg(espInfo); + } + case PROBLEM_ESL: { + QString eslInfo = SetJoin(m_Active_ESLs, ", "); + return tr("

Light plugins work differently in Starfield. They use a different " + "base " + "form ID compared with standard plugin files.

" + "

What this means is that you can't just change a standard plugin to a " + "light plugin at will, it can and will break any dependent plugin. If " + "you do so, be absolutely certain no other plugins use that plugin as a " + "master.

" + "

Notably, xEdit does not currently support saving ESL files.

" + "

Current ESLs:

%1

") + .arg(eslInfo); + } + case PROBLEM_OVERLAY: { + QString overlayInfo = SetJoin(m_Active_Overlays, ", "); + return tr("

Overlay-flagged plugins are not currently recommended. In theory, " + "they " + "should allow you to update existing records without utilizing " + "additional memory space. Unfortunately, it appears that the game still " + "allocates memory as if these were standard plugins. Therefore, at the " + "moment there is no real use for this plugin flag.

" + "

Notably, xEdit does not currently support saving overlay-flagged " + "files.

" + "

Current Overlays:

%1

") + .arg(overlayInfo); + } + case PROBLEM_TEST_FILE: { + return tr("

You have plugin managment enabled but you still have sTestFile " + "settings in your StarfieldCustom.ini. These must be removed or the game " + "will not read the plugins.txt file. Management is still disabled.

"); + } + case PROBLEM_PLUGINS_TXT: { + return tr("

You have plugin management turned on but do not have the Plugins.txt " + "Enabler SFSE plugin installed. Plugin file management for Starfield " + "will not work without this SFSE plugin.

"); + } + } +} + +bool GameStarfield::hasGuidedFix(unsigned int key) const +{ + if (key == PROBLEM_PLUGINS_TXT) + return true; + return false; +} + +void GameStarfield::startGuidedFix(unsigned int key) const +{ + if (key == PROBLEM_PLUGINS_TXT) { + QDesktopServices::openUrl( + QUrl("https://www.nexusmods.com/starfield/mods/4157?tab=files")); + } +} diff --git a/src/games/starfield/src/gamestarfield.h b/src/games/starfield/src/gamestarfield.h index d346c59a..ff8d7489 100644 --- a/src/games/starfield/src/gamestarfield.h +++ b/src/games/starfield/src/gamestarfield.h @@ -2,14 +2,15 @@ #define GAMESTARFIELD_H #include "gamegamebryo.h" +#include "iplugindiagnose.h" #include #include -class GameStarfield : public GameGamebryo +class GameStarfield : public GameGamebryo, public MOBase::IPluginDiagnose { Q_OBJECT - + Q_INTERFACES(MOBase::IPlugin MOBase::IPluginGame MOBase::IPluginDiagnose) Q_PLUGIN_METADATA(IID "org.modorganizer.GameStarfield" FILE "gamestarfield.json") public: @@ -45,6 +46,13 @@ public: // IPluginGame interface virtual int nexusModOrganizerID() const override; virtual int nexusGameID() const override; +public: // IPluginDiagnose interface + virtual std::vector activeProblems() const override; + virtual QString shortDescription(unsigned int key) const override; + virtual QString fullDescription(unsigned int key) const override; + virtual bool hasGuidedFix(unsigned int key) const override; + virtual void startGuidedFix(unsigned int key) const override; + public: // IPlugin interface virtual QString name() const override; virtual QString localizedName() const override; @@ -59,6 +67,24 @@ protected: std::shared_ptr makeSaveGame(QString filePath) const override; QString savegameExtension() const override; QString savegameSEExtension() const override; + +private: + bool activeESP() const; + bool activeESL() const; + bool activeOverlay() const; + bool testFilePresent() const; + bool pluginsTxtEnabler() const; + +private: + static const unsigned int PROBLEM_ESP = 1; + static const unsigned int PROBLEM_ESL = 2; + static const unsigned int PROBLEM_OVERLAY = 3; + static const unsigned int PROBLEM_TEST_FILE = 4; + static const unsigned int PROBLEM_PLUGINS_TXT = 5; + + mutable std::set m_Active_ESPs; + mutable std::set m_Active_ESLs; + mutable std::set m_Active_Overlays; }; #endif // GAMEStarfield_H From 395527e70a38e4b477b25c7b5edf838223473b24 Mon Sep 17 00:00:00 2001 From: Jeremy Rimpo Date: Tue, 17 Oct 2023 01:51:29 -0500 Subject: [PATCH 1393/1544] [game_starfield] Clarify and update warnings --- src/games/starfield/src/gamestarfield.cpp | 34 +++++++++++------------ 1 file changed, 17 insertions(+), 17 deletions(-) diff --git a/src/games/starfield/src/gamestarfield.cpp b/src/games/starfield/src/gamestarfield.cpp index 3470f25f..c0053da8 100644 --- a/src/games/starfield/src/gamestarfield.cpp +++ b/src/games/starfield/src/gamestarfield.cpp @@ -444,14 +444,15 @@ QString GameStarfield::fullDescription(unsigned int key) const switch (key) { case PROBLEM_ESP: { QString espInfo = SetJoin(m_Active_ESPs, ", "); - return tr("

ESP plugins are not ideal for Starfield. They cannot be sorted " - "alongside ESM or master-flagged plugins and always have their records " - "loaded by the game, taking up unnecessary space in memory.

" + return tr("

ESP plugins are not ideal for Starfield. In addition to being unable " + "to sort them alongside ESM or master-flagged plugins, certain record " + "references are always kept loaded by the game. This consumes " + "unnecessary resources and limits the game's ability to load what it " + "needs.

" "

Ideally, plugins should be saved as ESM files upon release. It can " - "also " - "be released as an ESL plugin, however there are additional concerns " - "with the way light plugins are currently handled and should only be " - "used when absolutely certain about what you're doing.

" + "also be released as an ESL plugin, however there are additional " + "concerns with the way light plugins are currently handled and should " + "only be used when absolutely certain about what you're doing.

" "

Notably, xEdit does not currently support saving ESP files.

" "

Current ESPs:

%1

") .arg(espInfo); @@ -459,26 +460,25 @@ QString GameStarfield::fullDescription(unsigned int key) const case PROBLEM_ESL: { QString eslInfo = SetJoin(m_Active_ESLs, ", "); return tr("

Light plugins work differently in Starfield. They use a different " - "base " - "form ID compared with standard plugin files.

" + "base form ID compared with standard plugin files.

" "

What this means is that you can't just change a standard plugin to a " "light plugin at will, it can and will break any dependent plugin. If " "you do so, be absolutely certain no other plugins use that plugin as a " "master.

" - "

Notably, xEdit does not currently support saving ESL files.

" + "

Notably, xEdit does not currently support saving or loading ESL " + "files under these conditions.

" "

Current ESLs:

%1

") .arg(eslInfo); } case PROBLEM_OVERLAY: { QString overlayInfo = SetJoin(m_Active_Overlays, ", "); return tr("

Overlay-flagged plugins are not currently recommended. In theory, " - "they " - "should allow you to update existing records without utilizing " - "additional memory space. Unfortunately, it appears that the game still " - "allocates memory as if these were standard plugins. Therefore, at the " - "moment there is no real use for this plugin flag.

" - "

Notably, xEdit does not currently support saving overlay-flagged " - "files.

" + "they should allow you to update existing records without utilizing " + "additional load order slots. Unfortunately, it appears that the game " + "still allocates the slots as if these were standard plugins. Therefore, " + "at the moment there is no real use for this plugin flag.

" + "

Notably, xEdit does not currently support saving or loading " + "overlay-flagged files under these conditions.

" "

Current Overlays:

%1

") .arg(overlayInfo); } From 6bade33e433671a90210a62dd9799b7193ee1537 Mon Sep 17 00:00:00 2001 From: Jeremy Rimpo Date: Tue, 17 Oct 2023 02:18:25 -0500 Subject: [PATCH 1394/1544] [game_starfield] Add plugin settings for warnings --- src/games/starfield/src/gamestarfield.cpp | 23 +++++++++++++++++++---- 1 file changed, 19 insertions(+), 4 deletions(-) diff --git a/src/games/starfield/src/gamestarfield.cpp b/src/games/starfield/src/gamestarfield.cpp index c0053da8..e1a66876 100644 --- a/src/games/starfield/src/gamestarfield.cpp +++ b/src/games/starfield/src/gamestarfield.cpp @@ -135,7 +135,19 @@ QList GameStarfield::settings() const tr("Turn on plugin management. As of Starfield 1.7.33 this " "REQUIRES fixing 'plugins.txt' with a SFSE plugin. This " "will do nothing otherwise."), - false); + false) + << PluginSetting( + "enable_esp_warning", + tr("Show a warning when ESP plugins are enabled in the load order."), + true) + << PluginSetting( + "enable_esl_warning", + tr("Show a warning when light plugins are enabled in the load order."), + true) + << PluginSetting("enable_overlay_warning", + tr("Show a warning when overlay-flagged plugins ar enabled " + "in the load order."), + true); } MappingType GameStarfield::mappings() const @@ -317,11 +329,14 @@ std::vector GameStarfield::activeProblems() const { std::vector result; if (m_Organizer->managedGame() == this) { - if (activeESP()) + if (m_Organizer->pluginSetting(name(), "enable_esp_warning").toBool() && + activeESP()) result.push_back(PROBLEM_ESP); - if (activeESL()) + if (m_Organizer->pluginSetting(name(), "enable_esl_warning").toBool() && + activeESL()) result.push_back(PROBLEM_ESL); - if (activeOverlay()) + if (m_Organizer->pluginSetting(name(), "enable_overlay_warning").toBool() && + activeOverlay()) result.push_back(PROBLEM_OVERLAY); if (testFilePresent()) result.push_back(PROBLEM_TEST_FILE); From c0818258484ec554295d97675c80caa18f09ba26 Mon Sep 17 00:00:00 2001 From: Jeremy Rimpo Date: Wed, 18 Oct 2023 22:56:21 -0500 Subject: [PATCH 1395/1544] [game_starfield] Use hasNoRecords --- src/games/starfield/src/gamestarfield.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/games/starfield/src/gamestarfield.cpp b/src/games/starfield/src/gamestarfield.cpp index e1a66876..8f39e83c 100644 --- a/src/games/starfield/src/gamestarfield.cpp +++ b/src/games/starfield/src/gamestarfield.cpp @@ -383,7 +383,7 @@ bool GameStarfield::activeESL() const if (primaryPlugins().contains(baseName, Qt::CaseInsensitive)) continue; if (m_Organizer->pluginList()->state(baseName) == IPluginList::STATE_ACTIVE && - !m_Organizer->pluginList()->isDummy(baseName)) + !m_Organizer->pluginList()->hasNoRecords(baseName)) if (m_Organizer->pluginList()->hasLightExtension(baseName) || m_Organizer->pluginList()->isLightFlagged(baseName)) m_Active_ESLs.insert(baseName); From a71cab28d5cea137f3acd9b6b37c23605dccabad Mon Sep 17 00:00:00 2001 From: Jeremy Rimpo Date: Tue, 31 Oct 2023 23:07:19 -0500 Subject: [PATCH 1396/1544] [game_starfield] Various updates - Allow plugin management automatically - Updates to reading archives from INIs - Remove version check for light plugin parser - Add some notes for save file headers --- src/games/starfield/src/gamestarfield.cpp | 19 +++----- .../starfield/src/starfielddataarchives.cpp | 43 ++++++++++--------- .../starfield/src/starfielddataarchives.h | 4 ++ src/games/starfield/src/starfieldsavegame.cpp | 34 +++++++++------ 4 files changed, 53 insertions(+), 47 deletions(-) diff --git a/src/games/starfield/src/gamestarfield.cpp b/src/games/starfield/src/gamestarfield.cpp index 8f39e83c..5307f2e9 100644 --- a/src/games/starfield/src/gamestarfield.cpp +++ b/src/games/starfield/src/gamestarfield.cpp @@ -125,17 +125,12 @@ QString GameStarfield::description() const MOBase::VersionInfo GameStarfield::version() const { - return VersionInfo(0, 5, 0, VersionInfo::RELEASE_BETA); + return VersionInfo(1, 0, 0, VersionInfo::RELEASE_CANDIDATE); } QList GameStarfield::settings() const { return QList() - << PluginSetting("enable_plugin_management", - tr("Turn on plugin management. As of Starfield 1.7.33 this " - "REQUIRES fixing 'plugins.txt' with a SFSE plugin. This " - "will do nothing otherwise."), - false) << PluginSetting( "enable_esp_warning", tr("Show a warning when ESP plugins are enabled in the load order."), @@ -153,8 +148,7 @@ QList GameStarfield::settings() const MappingType GameStarfield::mappings() const { MappingType result; - if (m_Organizer->pluginSetting(name(), "enable_plugin_management").toBool() && - testFilePlugins().isEmpty()) { + if (testFilePlugins().isEmpty()) { for (const QString& profileFile : {"plugins.txt", "loadorder.txt"}) { result.push_back({m_Organizer->profilePath() + "/" + profileFile, localAppFolder() + "/" + gameShortName() + "/" + profileFile, @@ -300,16 +294,14 @@ QStringList GameStarfield::CCPlugins() const IPluginGame::SortMechanism GameStarfield::sortMechanism() const { - if (m_Organizer->pluginSetting(name(), "enable_plugin_management").toBool() && - testFilePlugins().isEmpty()) + if (testFilePlugins().isEmpty()) return IPluginGame::SortMechanism::LOOT; return IPluginGame::SortMechanism::NONE; } IPluginGame::LoadOrderMechanism GameStarfield::loadOrderMechanism() const { - if (m_Organizer->pluginSetting(name(), "enable_plugin_management").toBool() && - testFilePlugins().isEmpty()) + if (testFilePlugins().isEmpty()) return IPluginGame::LoadOrderMechanism::PluginsTxt; return IPluginGame::LoadOrderMechanism::None; } @@ -422,8 +414,7 @@ bool GameStarfield::activeOverlay() const bool GameStarfield::testFilePresent() const { - if (m_Organizer->pluginSetting(name(), "enable_plugin_management").toBool() && - !testFilePlugins().isEmpty()) + if (!testFilePlugins().isEmpty()) return true; return false; } diff --git a/src/games/starfield/src/starfielddataarchives.cpp b/src/games/starfield/src/starfielddataarchives.cpp index ffbbc7cb..3604bed3 100644 --- a/src/games/starfield/src/starfielddataarchives.cpp +++ b/src/games/starfield/src/starfielddataarchives.cpp @@ -71,30 +71,33 @@ QStringList StarfieldDataArchives::archives(const MOBase::IProfile* profile) con { QStringList result; - QString iniFile = m_GamePath.absoluteFilePath("Starfield.ini"); - result.append(getArchivesFromKey(iniFile, "SResourceArchiveList")); - result.append(getArchivesFromKey(iniFile, "sResourceIndexFileList")); - result.append(getArchivesFromKey(iniFile, "SResourceArchiveMemoryCacheList")); - result.append(getArchivesFromKey(iniFile, "sResourceStartUpArchiveList")); - result.append(getArchivesFromKey(iniFile, "sResourceEnglishVoiceList")); + QString defaultIniFile = m_GamePath.absoluteFilePath("Starfield.ini"); + QString customIniFile = + profile->localSettingsEnabled() + ? QDir(profile->absolutePath()).absoluteFilePath("StarfieldCustom.ini") + : m_LocalGameDir.absoluteFilePath("StarfieldCustom.ini"); + QStringList archiveSettings = {"SResourceArchiveList", "sResourceIndexFileList", + "SResourceArchiveMemoryCacheList", + "sResourceStartUpArchiveList", + "sResourceEnglishVoiceList"}; + for (auto setting : archiveSettings) { + auto archives = getArchivesFromKey(customIniFile, setting, 1023); + if (archives.isEmpty()) + archives = getArchivesFromKey(defaultIniFile, setting, 1023); + result.append(archives); + } return result; } void StarfieldDataArchives::writeArchiveList(MOBase::IProfile* profile, const QStringList& before) -{ - QString list = before.join(", "); +{} - QString iniFile = - profile->localSettingsEnabled() - ? QDir(profile->absolutePath()).absoluteFilePath("Starfield.ini") - : m_LocalGameDir.absoluteFilePath("Starfield.ini"); - if (list.length() > 255) { - int splitIdx = list.lastIndexOf(",", 256); - setArchivesToKey(iniFile, "SResourceArchiveList", list.mid(0, splitIdx)); - setArchivesToKey(iniFile, "SResourceArchiveList2", list.mid(splitIdx + 2)); - } else { - setArchivesToKey(iniFile, "SResourceArchiveList", list); - } -} +void StarfieldDataArchives::addArchive(MOBase::IProfile* profile, int index, + const QString& archiveName) +{} + +void StarfieldDataArchives::removeArchive(MOBase::IProfile* profile, + const QString& archiveName) +{} \ No newline at end of file diff --git a/src/games/starfield/src/starfielddataarchives.h b/src/games/starfield/src/starfielddataarchives.h index 9da5c81c..f889c009 100644 --- a/src/games/starfield/src/starfielddataarchives.h +++ b/src/games/starfield/src/starfielddataarchives.h @@ -20,6 +20,10 @@ public: public: virtual QStringList vanillaArchives() const override; virtual QStringList archives(const MOBase::IProfile* profile) const override; + virtual void addArchive(MOBase::IProfile* profile, int index, + const QString& archiveName) override; + virtual void removeArchive(MOBase::IProfile* profile, + const QString& archiveName) override; protected: const QDir m_GamePath; diff --git a/src/games/starfield/src/starfieldsavegame.cpp b/src/games/starfield/src/starfieldsavegame.cpp index f5a27102..1b75c658 100644 --- a/src/games/starfield/src/starfieldsavegame.cpp +++ b/src/games/starfield/src/starfieldsavegame.cpp @@ -28,16 +28,26 @@ StarfieldSaveGame::StarfieldSaveGame(QString const& fileName, GameStarfield cons void StarfieldSaveGame::getData(FileWrapper& file) const { file.skip(); // header version - file.skip(); // zip start location - file.skip(); // unknown + file.skip(); // chunk compressed size array start location + file.skip(); // unknown (0?) file.setCompressionType(1); - file.openCompressedData(); // long = start, long = size - // double - // float - // long - // long - // short - return; + /* + * Parse following variables then begin decompressing data + * - 64-bit int = compressed data start location + * - 64-bit int = complete uncompressed data size + */ + file.openCompressedData(); + /* + * Remaining headers before start of compressed data: + * - 32-bit float (version? appears to be 2.0) + * - 64-bit int - size of uncompressed chunks (250 KiB) + * - 64-bit int - size of byte rows? (16 bytes) used to determine start of each + * compressed chunk + * - 32-bit int - number of chunks? + * - 'ZIP ' - denotes start of chunk compressed size array + * - compressed size array - array of 32-bit ints containing the compressed size of + * each compressed chunk (see number of chunks above) + */ } void StarfieldSaveGame::fetchInformationFields( @@ -102,10 +112,8 @@ std::unique_ptr StarfieldSaveGame::fetchDataFields file.read(ignore); // game version again? file.readInt(); // plugin info size - fields->Plugins = file.readPlugins(); - if (saveGameVersion >= 82) { - fields->LightPlugins = file.readLightPlugins(); - } + fields->Plugins = file.readPlugins(); + fields->LightPlugins = file.readLightPlugins(); file.closeCompressedData(); file.close(); From 730d26629876dc2ad5aac63d67a745b9bf763622 Mon Sep 17 00:00:00 2001 From: Jeremy Rimpo Date: Sun, 5 Nov 2023 21:17:54 -0600 Subject: [PATCH 1397/1544] [game_starfield] Various updates - Disable LOOT sorting by default with option to enable - Update length of INI strings for archive parsing - Fix issues with plugin list state based on various scenarios - Allow disabling plugin management checks for diagnoses - Use active plugin management method to determine when to read/write plugins.txt - Translation file --- src/games/starfield/src/game_starfield_en.ts | 97 ++++++++++++++++++- src/games/starfield/src/gamestarfield.cpp | 38 +++++--- src/games/starfield/src/gamestarfield.h | 2 +- .../starfield/src/starfielddataarchives.cpp | 4 +- .../starfield/src/starfieldgameplugins.cpp | 8 +- 5 files changed, 122 insertions(+), 27 deletions(-) diff --git a/src/games/starfield/src/game_starfield_en.ts b/src/games/starfield/src/game_starfield_en.ts index e0427b80..6f800511 100644 --- a/src/games/starfield/src/game_starfield_en.ts +++ b/src/games/starfield/src/game_starfield_en.ts @@ -4,19 +4,106 @@ GameStarfield - + Starfield Support Plugin - + Adds support for the game Starfield. - - Turn on plugin management. As of Starfield 1.7.33 this REQUIRES fixing 'plugins.txt' with a SFSE plugin. This will do nothing otherwise. - Turn on plugin management. As of Starfield 1.7.33 this REQUIRES SPECIAL WORKAROUNDS. + + Show a warning when ESP plugins are enabled in the load order. + + + + + Show a warning when light plugins are enabled in the load order. + + + + + Show a warning when overlay-flagged plugins ar enabled in the load order. + + + + + Show a warning when plugins.txt management is invalid. + + + + + As of this release LOOT Starfield support is minimal to nonexistant. Toggle this to enable it anyway. + + + + + You have active ESP plugins in Starfield + + + + + You have active ESL plugins in Starfield + + + + + You have active overlay plugins + + + + + sTestFile entries are present + + + + + Plugins.txt Enabler missing + + + + + <p>ESP plugins are not ideal for Starfield. In addition to being unable to sort them alongside ESM or master-flagged plugins, certain record references are always kept loaded by the game. This consumes unnecessary resources and limits the game's ability to load what it needs.</p><p>Ideally, plugins should be saved as ESM files upon release. It can also be released as an ESL plugin, however there are additional concerns with the way light plugins are currently handled and should only be used when absolutely certain about what you're doing.</p><p>Notably, xEdit does not currently support saving ESP files.</p><h4>Current ESPs:</h4><p>%1</p> + + + + + <p>Light plugins work differently in Starfield. They use a different base form ID compared with standard plugin files.</p><p>What this means is that you can't just change a standard plugin to a light plugin at will, it can and will break any dependent plugin. If you do so, be absolutely certain no other plugins use that plugin as a master.</p><p>Notably, xEdit does not currently support saving or loading ESL files under these conditions.<p><h4>Current ESLs:</h4><p>%1</p> + + + + + <p>Overlay-flagged plugins are not currently recommended. In theory, they should allow you to update existing records without utilizing additional load order slots. Unfortunately, it appears that the game still allocates the slots as if these were standard plugins. Therefore, at the moment there is no real use for this plugin flag.</p><p>Notably, xEdit does not currently support saving or loading overlay-flagged files under these conditions.</p><h4>Current Overlays:</h4><p>%1</p> + + + + + <p>You have plugin managment enabled but you still have sTestFile settings in your StarfieldCustom.ini. These must be removed or the game will not read the plugins.txt file. Management is still disabled.</p> + + + + + <p>You have plugin management turned on but do not have the Plugins.txt Enabler SFSE plugin installed. Plugin file management for Starfield will not work without this SFSE plugin.</p> + + + + + StarfieldModDataContent + + + Materials + + + + + Geometries + + + + + Video diff --git a/src/games/starfield/src/gamestarfield.cpp b/src/games/starfield/src/gamestarfield.cpp index 5307f2e9..025c988d 100644 --- a/src/games/starfield/src/gamestarfield.cpp +++ b/src/games/starfield/src/gamestarfield.cpp @@ -125,7 +125,7 @@ QString GameStarfield::description() const MOBase::VersionInfo GameStarfield::version() const { - return VersionInfo(1, 0, 0, VersionInfo::RELEASE_CANDIDATE); + return VersionInfo(1, 0, 0, VersionInfo::RELEASE_FINAL); } QList GameStarfield::settings() const @@ -142,7 +142,14 @@ QList GameStarfield::settings() const << PluginSetting("enable_overlay_warning", tr("Show a warning when overlay-flagged plugins ar enabled " "in the load order."), - true); + true) + << PluginSetting("enable_management_warnings", + tr("Show a warning when plugins.txt management is invalid."), + true) + << PluginSetting("enable_loot_sorting", + tr("As of this release LOOT Starfield support is minimal to " + "nonexistant. Toggle this to enable it anyway."), + false); } MappingType GameStarfield::mappings() const @@ -294,14 +301,15 @@ QStringList GameStarfield::CCPlugins() const IPluginGame::SortMechanism GameStarfield::sortMechanism() const { - if (testFilePlugins().isEmpty()) + if (!testFilePresent() && + m_Organizer->pluginSetting(name(), "enable_loot_sorting").toBool()) return IPluginGame::SortMechanism::LOOT; return IPluginGame::SortMechanism::NONE; } IPluginGame::LoadOrderMechanism GameStarfield::loadOrderMechanism() const { - if (testFilePlugins().isEmpty()) + if (!testFilePresent() && pluginsTxtEnablerPresent()) return IPluginGame::LoadOrderMechanism::PluginsTxt; return IPluginGame::LoadOrderMechanism::None; } @@ -330,10 +338,12 @@ std::vector GameStarfield::activeProblems() const if (m_Organizer->pluginSetting(name(), "enable_overlay_warning").toBool() && activeOverlay()) result.push_back(PROBLEM_OVERLAY); - if (testFilePresent()) - result.push_back(PROBLEM_TEST_FILE); - else if (pluginsTxtEnabler()) - result.push_back(PROBLEM_PLUGINS_TXT); + if (m_Organizer->pluginSetting(name(), "enable_management_warnings").toBool()) { + if (testFilePresent()) + result.push_back(PROBLEM_TEST_FILE); + else if (!pluginsTxtEnablerPresent()) + result.push_back(PROBLEM_PLUGINS_TXT); + } } return result; } @@ -419,14 +429,12 @@ bool GameStarfield::testFilePresent() const return false; } -bool GameStarfield::pluginsTxtEnabler() const +bool GameStarfield::pluginsTxtEnablerPresent() const { - if (sortMechanism() != SortMechanism::NONE) { - auto files = m_Organizer->findFiles("sfse\\plugins", {"sfpluginstxtenabler.dll"}); - if (files.isEmpty()) - return true; - } - return false; + auto files = m_Organizer->findFiles("sfse\\plugins", {"sfpluginstxtenabler.dll"}); + if (files.isEmpty()) + return false; + return true; } QString GameStarfield::shortDescription(unsigned int key) const diff --git a/src/games/starfield/src/gamestarfield.h b/src/games/starfield/src/gamestarfield.h index ff8d7489..7fde2e83 100644 --- a/src/games/starfield/src/gamestarfield.h +++ b/src/games/starfield/src/gamestarfield.h @@ -73,7 +73,7 @@ private: bool activeESL() const; bool activeOverlay() const; bool testFilePresent() const; - bool pluginsTxtEnabler() const; + bool pluginsTxtEnablerPresent() const; private: static const unsigned int PROBLEM_ESP = 1; diff --git a/src/games/starfield/src/starfielddataarchives.cpp b/src/games/starfield/src/starfielddataarchives.cpp index 3604bed3..fea785d8 100644 --- a/src/games/starfield/src/starfielddataarchives.cpp +++ b/src/games/starfield/src/starfielddataarchives.cpp @@ -81,9 +81,9 @@ QStringList StarfieldDataArchives::archives(const MOBase::IProfile* profile) con "sResourceStartUpArchiveList", "sResourceEnglishVoiceList"}; for (auto setting : archiveSettings) { - auto archives = getArchivesFromKey(customIniFile, setting, 1023); + auto archives = getArchivesFromKey(customIniFile, setting, 4096); if (archives.isEmpty()) - archives = getArchivesFromKey(defaultIniFile, setting, 1023); + archives = getArchivesFromKey(defaultIniFile, setting, 4096); result.append(archives); } diff --git a/src/games/starfield/src/starfieldgameplugins.cpp b/src/games/starfield/src/starfieldgameplugins.cpp index 93f2e477..b8907c79 100644 --- a/src/games/starfield/src/starfieldgameplugins.cpp +++ b/src/games/starfield/src/starfieldgameplugins.cpp @@ -14,16 +14,16 @@ bool StarfieldGamePlugins::overridePluginsAreSupported() void StarfieldGamePlugins::writePluginList(const IPluginList* pluginList, const QString& filePath) { - if (m_Organizer->managedGame()->sortMechanism() != - MOBase::IPluginGame::SortMechanism::NONE) { + if (m_Organizer->managedGame()->loadOrderMechanism() == + MOBase::IPluginGame::LoadOrderMechanism::PluginsTxt) { CreationGamePlugins::writePluginList(pluginList, filePath); } } QStringList StarfieldGamePlugins::readPluginList(MOBase::IPluginList* pluginList) { - if (m_Organizer->managedGame()->sortMechanism() != - MOBase::IPluginGame::SortMechanism::NONE) { + if (m_Organizer->managedGame()->loadOrderMechanism() == + MOBase::IPluginGame::LoadOrderMechanism::PluginsTxt) { return CreationGamePlugins::readPluginList(pluginList); } return {}; From ff33e904e5a0f3e16036aae4490d7db05f63d074 Mon Sep 17 00:00:00 2001 From: Jeremy Rimpo Date: Tue, 7 Nov 2023 03:55:22 -0500 Subject: [PATCH 1398/1544] [game_morrowind] Translation updates --- src/games/morrowind/src/game_morrowind_en.ts | 156 +------------------ 1 file changed, 1 insertion(+), 155 deletions(-) diff --git a/src/games/morrowind/src/game_morrowind_en.ts b/src/games/morrowind/src/game_morrowind_en.ts index 65f7a2eb..77dee4aa 100644 --- a/src/games/morrowind/src/game_morrowind_en.ts +++ b/src/games/morrowind/src/game_morrowind_en.ts @@ -15,133 +15,6 @@ Splash by %1 - - GamebryoModDataContent - - - Plugins (ESP/ESM/ESL) - - - - - Optional Plugins - - - - - Interface - - - - - Meshes - - - - - Bethesda Archive - - - - - Scripts (Papyrus) - - - - - Script Extender Plugin - - - - - Script Extender Files - - - - - SkyProc Patcher - - - - - Sound or Music - - - - - Textures - - - - - MCM Configuration - - - - - INI Files - - - - - FaceGen Data - - - - - ModGroup Files - - - - - GamebryoSaveGameInfoWidget - - - Save # - - - - - Character - - - - - Level - - - - - Location - - - - - Date - - - - - Has Script Extender Data - - - - - Missing ESPs - - - - - - None - - - - - Missing ESLs - - - MorrowindSaveGameInfoWidget @@ -188,36 +61,9 @@ Splash by %1 QObject - - - + Some of your plugins have invalid names! These plugins can not be loaded by the game. Please see mo_interface.log for a list of affected plugins and rename them. - - - %1, #%2, Level %3, %4 - - - - - failed to open %1 - - - - - wrong file format - expected %1 got %2 - - - - - failed to query registry path (preflight): %1 - - - - - failed to query registry path (read): %1 - - From 13bff68dc90964bffcfc8fdb0f6b6feaf9c9e250 Mon Sep 17 00:00:00 2001 From: Jeremy Rimpo Date: Tue, 7 Nov 2023 23:42:36 -0600 Subject: [PATCH 1399/1544] [game_starfield] Extend management checks * Look for ASI loader option * Add bypass setting --- src/games/starfield/src/game_starfield_en.ts | 25 ++++++++++++-------- src/games/starfield/src/gamestarfield.cpp | 9 ++++++- 2 files changed, 23 insertions(+), 11 deletions(-) diff --git a/src/games/starfield/src/game_starfield_en.ts b/src/games/starfield/src/game_starfield_en.ts index 6f800511..baa0b381 100644 --- a/src/games/starfield/src/game_starfield_en.ts +++ b/src/games/starfield/src/game_starfield_en.ts @@ -35,56 +35,61 @@ + Bypass check for Plugins.txt Enabler. This may be useful if you use the ASI loader. + + + + As of this release LOOT Starfield support is minimal to nonexistant. Toggle this to enable it anyway. - + You have active ESP plugins in Starfield - + You have active ESL plugins in Starfield - + You have active overlay plugins - + sTestFile entries are present - + Plugins.txt Enabler missing - + <p>ESP plugins are not ideal for Starfield. In addition to being unable to sort them alongside ESM or master-flagged plugins, certain record references are always kept loaded by the game. This consumes unnecessary resources and limits the game's ability to load what it needs.</p><p>Ideally, plugins should be saved as ESM files upon release. It can also be released as an ESL plugin, however there are additional concerns with the way light plugins are currently handled and should only be used when absolutely certain about what you're doing.</p><p>Notably, xEdit does not currently support saving ESP files.</p><h4>Current ESPs:</h4><p>%1</p> - + <p>Light plugins work differently in Starfield. They use a different base form ID compared with standard plugin files.</p><p>What this means is that you can't just change a standard plugin to a light plugin at will, it can and will break any dependent plugin. If you do so, be absolutely certain no other plugins use that plugin as a master.</p><p>Notably, xEdit does not currently support saving or loading ESL files under these conditions.<p><h4>Current ESLs:</h4><p>%1</p> - + <p>Overlay-flagged plugins are not currently recommended. In theory, they should allow you to update existing records without utilizing additional load order slots. Unfortunately, it appears that the game still allocates the slots as if these were standard plugins. Therefore, at the moment there is no real use for this plugin flag.</p><p>Notably, xEdit does not currently support saving or loading overlay-flagged files under these conditions.</p><h4>Current Overlays:</h4><p>%1</p> - + <p>You have plugin managment enabled but you still have sTestFile settings in your StarfieldCustom.ini. These must be removed or the game will not read the plugins.txt file. Management is still disabled.</p> - + <p>You have plugin management turned on but do not have the Plugins.txt Enabler SFSE plugin installed. Plugin file management for Starfield will not work without this SFSE plugin.</p> diff --git a/src/games/starfield/src/gamestarfield.cpp b/src/games/starfield/src/gamestarfield.cpp index 025c988d..480ee9c2 100644 --- a/src/games/starfield/src/gamestarfield.cpp +++ b/src/games/starfield/src/gamestarfield.cpp @@ -146,6 +146,10 @@ QList GameStarfield::settings() const << PluginSetting("enable_management_warnings", tr("Show a warning when plugins.txt management is invalid."), true) + << PluginSetting("bypass_plugins_enabler_check", + tr("Bypass check for Plugins.txt Enabler. This may be useful " + "if you use the ASI loader."), + false) << PluginSetting("enable_loot_sorting", tr("As of this release LOOT Starfield support is minimal to " "nonexistant. Toggle this to enable it anyway."), @@ -309,7 +313,9 @@ IPluginGame::SortMechanism GameStarfield::sortMechanism() const IPluginGame::LoadOrderMechanism GameStarfield::loadOrderMechanism() const { - if (!testFilePresent() && pluginsTxtEnablerPresent()) + if (!testFilePresent() && + (pluginsTxtEnablerPresent() || + m_Organizer->pluginSetting(name(), "bypass_plugins_enabler_check").toBool())) return IPluginGame::LoadOrderMechanism::PluginsTxt; return IPluginGame::LoadOrderMechanism::None; } @@ -432,6 +438,7 @@ bool GameStarfield::testFilePresent() const bool GameStarfield::pluginsTxtEnablerPresent() const { auto files = m_Organizer->findFiles("sfse\\plugins", {"sfpluginstxtenabler.dll"}); + files += m_Organizer->findFiles("", {"sfpluginstxtenabler.asi"}); if (files.isEmpty()) return false; return true; From 8832316424ccf71735ebefaa8a632fccf4cc5312 Mon Sep 17 00:00:00 2001 From: Jeremy Rimpo Date: Thu, 16 Nov 2023 23:04:52 -0600 Subject: [PATCH 1400/1544] [game_ttw] Fix steam game directory check --- src/games/ttw/src/gamefalloutttw.cpp | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/src/games/ttw/src/gamefalloutttw.cpp b/src/games/ttw/src/gamefalloutttw.cpp index 7d3b640b..f48fb4cb 100644 --- a/src/games/ttw/src/gamefalloutttw.cpp +++ b/src/games/ttw/src/gamefalloutttw.cpp @@ -73,7 +73,8 @@ QDir GameFalloutTTW::documentsDirectory() const QString GameFalloutTTW::identifyGamePath() const { - auto result = GameGamebryo::identifyGamePath(); // Default registry path + QString path = "Software\\Bethesda Softworks\\FalloutNV"; + auto result = findInRegistry(HKEY_LOCAL_MACHINE, path.toStdWString().c_str(), L"Installed Path"); // EPIC Game Store if (result.isEmpty()) { /** From dab102c95bfd1568791a343c93229f272e6950a0 Mon Sep 17 00:00:00 2001 From: Jeremy Rimpo Date: Fri, 24 Nov 2023 21:15:23 -0600 Subject: [PATCH 1401/1544] [game_fallout4vr] Bump version to reflect 2.5.0 release --- src/games/fallout4vr/src/gamefallout4vr.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/games/fallout4vr/src/gamefallout4vr.cpp b/src/games/fallout4vr/src/gamefallout4vr.cpp index f9c4ad8e..c835ba5f 100644 --- a/src/games/fallout4vr/src/gamefallout4vr.cpp +++ b/src/games/fallout4vr/src/gamefallout4vr.cpp @@ -97,7 +97,7 @@ QString GameFallout4VR::description() const MOBase::VersionInfo GameFallout4VR::version() const { - return VersionInfo(1, 6, 0, VersionInfo::RELEASE_FINAL); + return VersionInfo(1, 6, 1, VersionInfo::RELEASE_FINAL); } QList GameFallout4VR::settings() const From 9b24fd52dcb6025fd0276c4a3a38a58d3c16597f Mon Sep 17 00:00:00 2001 From: Jeremy Rimpo Date: Fri, 24 Nov 2023 21:15:30 -0600 Subject: [PATCH 1402/1544] [game_fallout76] Bump version to reflect 2.5.0 release --- src/games/fallout76/src/gamefallout76.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/games/fallout76/src/gamefallout76.cpp b/src/games/fallout76/src/gamefallout76.cpp index 3a8f9331..bfa428d8 100644 --- a/src/games/fallout76/src/gamefallout76.cpp +++ b/src/games/fallout76/src/gamefallout76.cpp @@ -85,7 +85,7 @@ QString GameFallout76::description() const MOBase::VersionInfo GameFallout76::version() const { - return VersionInfo(3, 0, 1, VersionInfo::RELEASE_ALPHA); + return VersionInfo(1, 0, 0, VersionInfo::RELEASE_FINAL); } QList GameFallout76::settings() const From e9e9c671b9ff4849da3d518277f6535bfcfefd48 Mon Sep 17 00:00:00 2001 From: Jeremy Rimpo Date: Fri, 24 Nov 2023 21:15:31 -0600 Subject: [PATCH 1403/1544] [game_falloutnv] Bump version to reflect 2.5.0 release --- src/games/falloutnv/src/gamefalloutnv.cpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/games/falloutnv/src/gamefalloutnv.cpp b/src/games/falloutnv/src/gamefalloutnv.cpp index 072cc8b0..5938e4dd 100644 --- a/src/games/falloutnv/src/gamefalloutnv.cpp +++ b/src/games/falloutnv/src/gamefalloutnv.cpp @@ -183,7 +183,7 @@ QString GameFalloutNV::localizedName() const QString GameFalloutNV::author() const { - return "Tannin"; + return "Tannin & MO2 Team"; } QString GameFalloutNV::description() const @@ -193,7 +193,7 @@ QString GameFalloutNV::description() const MOBase::VersionInfo GameFalloutNV::version() const { - return VersionInfo(1, 5, 2, VersionInfo::RELEASE_FINAL); + return VersionInfo(1, 6, 0, VersionInfo::RELEASE_FINAL); } QList GameFalloutNV::settings() const From 3854b36d4cc2b34d3b6b36b30f0694f78fdc75c5 Mon Sep 17 00:00:00 2001 From: Jeremy Rimpo Date: Fri, 24 Nov 2023 21:15:32 -0600 Subject: [PATCH 1404/1544] [game_enderalse] Bump version to reflect 2.5.0 release --- src/games/enderalse/src/gameenderalse.cpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/games/enderalse/src/gameenderalse.cpp b/src/games/enderalse/src/gameenderalse.cpp index 851b5a25..f30b1f89 100644 --- a/src/games/enderalse/src/gameenderalse.cpp +++ b/src/games/enderalse/src/gameenderalse.cpp @@ -193,7 +193,7 @@ QString GameEnderalSE::localizedName() const QString GameEnderalSE::author() const { - return "Holt59, Archost & ZachHaber"; + return "Archost, ZachHaber & MO2 Team"; } QString GameEnderalSE::description() const @@ -203,7 +203,7 @@ QString GameEnderalSE::description() const MOBase::VersionInfo GameEnderalSE::version() const { - return VersionInfo(1, 1, 0, VersionInfo::RELEASE_FINAL); + return VersionInfo(1, 2, 0, VersionInfo::RELEASE_FINAL); } QList GameEnderalSE::settings() const From 4c885c1a65d1a1194ee4afa2859bdf08d4a1d90f Mon Sep 17 00:00:00 2001 From: Jeremy Rimpo Date: Fri, 24 Nov 2023 21:15:33 -0600 Subject: [PATCH 1405/1544] [game_morrowind] Bump version to reflect 2.5.0 release --- src/games/morrowind/src/gamemorrowind.cpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/games/morrowind/src/gamemorrowind.cpp b/src/games/morrowind/src/gamemorrowind.cpp index b9cc13e1..87efab12 100644 --- a/src/games/morrowind/src/gamemorrowind.cpp +++ b/src/games/morrowind/src/gamemorrowind.cpp @@ -107,7 +107,7 @@ QString GameMorrowind::localizedName() const QString GameMorrowind::author() const { - return "Schilduin"; + return "Schilduin & MO2 Team"; } QString GameMorrowind::description() const @@ -118,7 +118,7 @@ QString GameMorrowind::description() const MOBase::VersionInfo GameMorrowind::version() const { - return VersionInfo(1, 5, 0, VersionInfo::RELEASE_FINAL); + return VersionInfo(1, 5, 1, VersionInfo::RELEASE_FINAL); } QList GameMorrowind::settings() const From 9025ff98dcd5811f0315b882a9dd5a3dd38ed093 Mon Sep 17 00:00:00 2001 From: Jeremy Rimpo Date: Fri, 24 Nov 2023 21:15:35 -0600 Subject: [PATCH 1406/1544] [game_skyrimse] Bump version to reflect 2.5.0 release --- src/games/skyrimse/src/gameskyrimse.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/games/skyrimse/src/gameskyrimse.cpp b/src/games/skyrimse/src/gameskyrimse.cpp index ad612659..0a802de9 100644 --- a/src/games/skyrimse/src/gameskyrimse.cpp +++ b/src/games/skyrimse/src/gameskyrimse.cpp @@ -193,7 +193,7 @@ QString GameSkyrimSE::description() const MOBase::VersionInfo GameSkyrimSE::version() const { - return VersionInfo(1, 7, 0, VersionInfo::RELEASE_FINAL); + return VersionInfo(1, 7, 1, VersionInfo::RELEASE_FINAL); } QList GameSkyrimSE::settings() const From 19f18f579a66b82ea9f2f073c268e8e11cf06904 Mon Sep 17 00:00:00 2001 From: Jeremy Rimpo Date: Fri, 24 Nov 2023 21:15:35 -0600 Subject: [PATCH 1407/1544] [game_oblivion] Bump version to reflect 2.5.0 release --- src/games/oblivion/src/gameoblivion.cpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/games/oblivion/src/gameoblivion.cpp b/src/games/oblivion/src/gameoblivion.cpp index 43a3bca8..2642e212 100644 --- a/src/games/oblivion/src/gameoblivion.cpp +++ b/src/games/oblivion/src/gameoblivion.cpp @@ -80,7 +80,7 @@ QString GameOblivion::localizedName() const QString GameOblivion::author() const { - return "Tannin"; + return "Tannin & MO2 Team"; } QString GameOblivion::description() const @@ -90,7 +90,7 @@ QString GameOblivion::description() const MOBase::VersionInfo GameOblivion::version() const { - return VersionInfo(1, 6, 0, VersionInfo::RELEASE_FINAL); + return VersionInfo(1, 6, 1, VersionInfo::RELEASE_FINAL); } QList GameOblivion::settings() const From 93eb1e100e2468c684b08c7cb12ff49d3d5a4763 Mon Sep 17 00:00:00 2001 From: Jeremy Rimpo Date: Fri, 24 Nov 2023 21:15:36 -0600 Subject: [PATCH 1408/1544] [game_skyrimvr] Bump version to reflect 2.5.0 release --- src/games/skyrimvr/src/gameskyrimvr.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/games/skyrimvr/src/gameskyrimvr.cpp b/src/games/skyrimvr/src/gameskyrimvr.cpp index 995d6604..a5a8cf3e 100644 --- a/src/games/skyrimvr/src/gameskyrimvr.cpp +++ b/src/games/skyrimvr/src/gameskyrimvr.cpp @@ -129,7 +129,7 @@ QString GameSkyrimVR::description() const MOBase::VersionInfo GameSkyrimVR::version() const { - return VersionInfo(1, 5, 0, VersionInfo::RELEASE_FINAL); + return VersionInfo(1, 5, 1, VersionInfo::RELEASE_FINAL); } QList GameSkyrimVR::settings() const From 6540db971fb0474315882e2161df6234dc164924 Mon Sep 17 00:00:00 2001 From: Jeremy Rimpo Date: Fri, 24 Nov 2023 21:15:37 -0600 Subject: [PATCH 1409/1544] [game_fallout4] Bump version to reflect 2.5.0 release --- src/games/fallout4/src/gamefallout4.cpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/games/fallout4/src/gamefallout4.cpp b/src/games/fallout4/src/gamefallout4.cpp index 8482c04e..c3c6f058 100644 --- a/src/games/fallout4/src/gamefallout4.cpp +++ b/src/games/fallout4/src/gamefallout4.cpp @@ -90,7 +90,7 @@ QString GameFallout4::localizedName() const QString GameFallout4::author() const { - return "Tannin"; + return "Tannin & MO2 Team"; } QString GameFallout4::description() const @@ -101,7 +101,7 @@ QString GameFallout4::description() const MOBase::VersionInfo GameFallout4::version() const { - return VersionInfo(1, 7, 0, VersionInfo::RELEASE_FINAL); + return VersionInfo(1, 8, 0, VersionInfo::RELEASE_FINAL); } QList GameFallout4::settings() const From 2d7930bd498f751aefe20ee389fb30124a4f103e Mon Sep 17 00:00:00 2001 From: Jeremy Rimpo Date: Fri, 24 Nov 2023 21:15:38 -0600 Subject: [PATCH 1410/1544] [game_skyrim] Bump version to reflect 2.5.0 release --- src/games/skyrim/src/gameskyrim.cpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/games/skyrim/src/gameskyrim.cpp b/src/games/skyrim/src/gameskyrim.cpp index db63fea7..68babc3b 100644 --- a/src/games/skyrim/src/gameskyrim.cpp +++ b/src/games/skyrim/src/gameskyrim.cpp @@ -89,7 +89,7 @@ QString GameSkyrim::localizedName() const QString GameSkyrim::author() const { - return "Tannin"; + return "Tannin & MO2 Team"; } QString GameSkyrim::description() const @@ -99,7 +99,7 @@ QString GameSkyrim::description() const MOBase::VersionInfo GameSkyrim::version() const { - return VersionInfo(1, 6, 0, VersionInfo::RELEASE_FINAL); + return VersionInfo(1, 6, 1, VersionInfo::RELEASE_FINAL); } QList GameSkyrim::settings() const From 5fb4266a22158718ad1641398217446c54f115b0 Mon Sep 17 00:00:00 2001 From: Jeremy Rimpo Date: Fri, 24 Nov 2023 21:15:40 -0600 Subject: [PATCH 1411/1544] [game_nehrim] Bump version to reflect 2.5.0 release --- src/games/nehrim/src/gamenehrim.cpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/games/nehrim/src/gamenehrim.cpp b/src/games/nehrim/src/gamenehrim.cpp index 084efe9f..44d650fe 100644 --- a/src/games/nehrim/src/gamenehrim.cpp +++ b/src/games/nehrim/src/gamenehrim.cpp @@ -86,7 +86,7 @@ QString GameNehrim::localizedName() const QString GameNehrim::author() const { - return "Tannin"; + return "Tannin & MO2 Team"; } QString GameNehrim::description() const @@ -96,7 +96,7 @@ QString GameNehrim::description() const MOBase::VersionInfo GameNehrim::version() const { - return VersionInfo(1, 1, 0, VersionInfo::RELEASE_FINAL); + return VersionInfo(1, 1, 1, VersionInfo::RELEASE_FINAL); } QList GameNehrim::settings() const From 4b0c30fd7630ea3d87481b731a0d9f7bdf1b0e0c Mon Sep 17 00:00:00 2001 From: Jeremy Rimpo Date: Fri, 24 Nov 2023 21:15:42 -0600 Subject: [PATCH 1412/1544] [game_ttw] Bump version to reflect 2.5.0 release --- src/games/ttw/src/gamefalloutttw.cpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/games/ttw/src/gamefalloutttw.cpp b/src/games/ttw/src/gamefalloutttw.cpp index f48fb4cb..783edfbd 100644 --- a/src/games/ttw/src/gamefalloutttw.cpp +++ b/src/games/ttw/src/gamefalloutttw.cpp @@ -185,7 +185,7 @@ QString GameFalloutTTW::localizedName() const QString GameFalloutTTW::author() const { - return "SuperSandro2000"; + return "SuperSandro2000 & MO2 Team"; } QString GameFalloutTTW::description() const @@ -195,7 +195,7 @@ QString GameFalloutTTW::description() const MOBase::VersionInfo GameFalloutTTW::version() const { - return VersionInfo(1, 5, 0, VersionInfo::RELEASE_FINAL); + return VersionInfo(1, 6, 0, VersionInfo::RELEASE_FINAL); } QList GameFalloutTTW::settings() const From 243a784dfd2f877cd66b702fce4e6d2a3f6adca3 Mon Sep 17 00:00:00 2001 From: Liderate Date: Fri, 1 Dec 2023 13:45:13 -0500 Subject: [PATCH 1413/1544] [game_fallout4] Add Automatic Archive Invalidation --- .../fallout4/src/fallout4bsainvalidation.cpp | 68 +++++++++++++++++++ .../fallout4/src/fallout4bsainvalidation.h | 32 +++++++++ src/games/fallout4/src/gamefallout4.cpp | 3 + 3 files changed, 103 insertions(+) create mode 100644 src/games/fallout4/src/fallout4bsainvalidation.cpp create mode 100644 src/games/fallout4/src/fallout4bsainvalidation.h diff --git a/src/games/fallout4/src/fallout4bsainvalidation.cpp b/src/games/fallout4/src/fallout4bsainvalidation.cpp new file mode 100644 index 00000000..3e676f64 --- /dev/null +++ b/src/games/fallout4/src/fallout4bsainvalidation.cpp @@ -0,0 +1,68 @@ +#include "fallout4bsainvalidation.h" + +#include "dummybsa.h" +#include "iplugingame.h" +#include "iprofile.h" +#include "registry.h" +#include +#include + +Fallout4BSAInvalidation::Fallout4BSAInvalidation(DataArchives* dataArchives, + MOBase::IPluginGame const* game) + : GamebryoBSAInvalidation(dataArchives, "Fallout4Custom.ini", game) +{ + m_IniFileName = "Fallout4Custom.ini"; + m_Game = game; +} + +bool Fallout4BSAInvalidation::isInvalidationBSA(const QString& bsaName) +{ + return false; +} + +QString Fallout4BSAInvalidation::invalidationBSAName() const +{ + return ""; +} + +unsigned long Fallout4BSAInvalidation::bsaVersion() const +{ + return 0x68; +} + +bool Fallout4BSAInvalidation::prepareProfile(MOBase::IProfile* profile) +{ + bool dirty = false; + QString basePath = profile->localSettingsEnabled() + ? profile->absolutePath() + : m_Game->documentsDirectory().absolutePath(); + QString iniFilePath = basePath + "/" + m_IniFileName; + WCHAR setting[MAX_PATH]; + + if (profile->invalidationActive(nullptr)) { + // write bInvalidateOlderFiles = 1, if needed + if (!::GetPrivateProfileStringW(L"Archive", L"bInvalidateOlderFiles", L"0", setting, + MAX_PATH, iniFilePath.toStdWString().c_str()) || + wcstol(setting, nullptr, 10) != 1) { + dirty = true; + if (!MOBase::WriteRegistryValue(L"Archive", L"bInvalidateOlderFiles", L"1", + iniFilePath.toStdWString().c_str())) { + qWarning("failed to override data directory in \"%s\"", + qUtf8Printable(m_IniFileName)); + } + } + if (!::GetPrivateProfileStringW(L"Archive", L"sResourceDataDirsFinal", L"STRINGS\\", + setting, MAX_PATH, + iniFilePath.toStdWString().c_str()) || + wcscmp(setting, L"") != 0) { + dirty = true; + if (!MOBase::WriteRegistryValue(L"Archive", L"sResourceDataDirsFinal", L"", + iniFilePath.toStdWString().c_str())) { + qWarning("failed to override data directory in \"%s\"", + qUtf8Printable(m_IniFileName)); + } + } + } + + return dirty; +} diff --git a/src/games/fallout4/src/fallout4bsainvalidation.h b/src/games/fallout4/src/fallout4bsainvalidation.h new file mode 100644 index 00000000..a7e35db9 --- /dev/null +++ b/src/games/fallout4/src/fallout4bsainvalidation.h @@ -0,0 +1,32 @@ +#ifndef FALLOUT4BSAINVALIDATION_H +#define FALLOUT4BSAINVALIDATION_H + +#include "fallout4dataarchives.h" +#include "gamebryobsainvalidation.h" +#include +#include + +#include + +namespace MOBase +{ +class IPluginGame; +} + +class Fallout4BSAInvalidation : public GamebryoBSAInvalidation +{ +public: + Fallout4BSAInvalidation(DataArchives* dataArchives, MOBase::IPluginGame const* game); + virtual bool isInvalidationBSA(const QString& bsaName) override; + virtual bool prepareProfile(MOBase::IProfile* profile) override; + +private: + virtual QString invalidationBSAName() const override; + virtual unsigned long bsaVersion() const override; + +private: + QString m_IniFileName; + MOBase::IPluginGame const* m_Game; +}; + +#endif // FALLOUT4BSAINVALIDATION_H \ No newline at end of file diff --git a/src/games/fallout4/src/gamefallout4.cpp b/src/games/fallout4/src/gamefallout4.cpp index 8482c04e..db0e89a6 100644 --- a/src/games/fallout4/src/gamefallout4.cpp +++ b/src/games/fallout4/src/gamefallout4.cpp @@ -1,5 +1,6 @@ #include "gameFallout4.h" +#include "fallout4bsainvalidation.h" #include "fallout4dataarchives.h" #include "fallout4scriptextender.h" #include "fallout4unmanagedmods.h" @@ -46,6 +47,8 @@ bool GameFallout4::init(IOrganizer *moInfo) registerFeature(new GamebryoSaveGameInfo(this)); registerFeature(new CreationGamePlugins(moInfo)); registerFeature(new Fallout4UnmangedMods(this)); + registerFeature( + new Fallout4BSAInvalidation(feature(), this)); return true; } From 14dc7d278d55da8e4f0024e2aa6b5fee933d623c Mon Sep 17 00:00:00 2001 From: Liderate Date: Fri, 1 Dec 2023 18:22:50 -0500 Subject: [PATCH 1414/1544] [game_fallout4] Check for sTestFile entries --- src/games/fallout4/src/gamefallout4.cpp | 102 ++++++++++++++++++++++-- src/games/fallout4/src/gamefallout4.h | 25 ++++-- 2 files changed, 116 insertions(+), 11 deletions(-) diff --git a/src/games/fallout4/src/gamefallout4.cpp b/src/games/fallout4/src/gamefallout4.cpp index db0e89a6..831979e2 100644 --- a/src/games/fallout4/src/gamefallout4.cpp +++ b/src/games/fallout4/src/gamefallout4.cpp @@ -112,6 +112,19 @@ QList GameFallout4::settings() const return QList(); } +MappingType GameFallout4::mappings() const +{ + MappingType result; + if (testFilePlugins().isEmpty()) { + for (const QString& profileFile : { "plugins.txt", "loadorder.txt" }) { + result.push_back({ m_Organizer->profilePath() + "/" + profileFile, + localAppFolder() + "/" + gameShortName() + "/" + profileFile, + false }); + } + } + return result; +} + void GameFallout4::initializeProfile(const QDir &path, ProfileSettings settings) const { if (settings.testFlag(IPluginGame::MODS)) { @@ -151,11 +164,44 @@ QString GameFallout4::steamAPPId() const return "377160"; } -QStringList GameFallout4::primaryPlugins() const { - QStringList plugins = {"fallout4.esm", "dlcrobot.esm", "dlcworkshop01.esm", "dlccoast.esm", "dlcworkshop02.esm", - "dlcworkshop03.esm", "dlcnukaworld.esm", "dlcultrahighresolution.esm"}; +QStringList GameFallout4::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); + WCHAR value[MAX_PATH]; + DWORD length = ::GetPrivateProfileStringW( + L"General", setting.toStdWString().c_str(), L"", value, MAX_PATH, + customIni.toStdWString().c_str()); + if (length && wcscmp(value, L"") != 0) { + QString plugin = QString::fromWCharArray(value, length); + if (!plugin.isEmpty() && !plugins.contains(plugin)) + plugins.append(plugin); + } + } + } + } + return plugins; +} - plugins.append(CCPlugins()); +QStringList GameFallout4::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; } @@ -213,9 +259,18 @@ QStringList GameFallout4::CCPlugins() const return plugins; } +IPluginGame::SortMechanism GameFallout4::sortMechanism() const +{ + if (!testFilePresent()) + return IPluginGame::SortMechanism::LOOT; + return IPluginGame::SortMechanism::NONE; +} + IPluginGame::LoadOrderMechanism GameFallout4::loadOrderMechanism() const { - return IPluginGame::LoadOrderMechanism::PluginsTxt; + if (!testFilePresent()) + return IPluginGame::LoadOrderMechanism::PluginsTxt; + return IPluginGame::LoadOrderMechanism::None; } int GameFallout4::nexusModOrganizerID() const @@ -227,3 +282,40 @@ int GameFallout4::nexusGameID() const { return 1151; } + +// Start Diagnose +std::vector GameFallout4::activeProblems() const +{ + std::vector result; + if (m_Organizer->managedGame() == this) { + if (testFilePresent()) + result.push_back(PROBLEM_TEST_FILE); + } + return result; +} + +bool GameFallout4::testFilePresent() const +{ + if (!testFilePlugins().isEmpty()) + return true; + return false; +} + +QString GameFallout4::shortDescription(unsigned int key) const +{ + switch (key) { + case PROBLEM_TEST_FILE: + return tr("sTestFile entries are present"); + } +} + +QString GameFallout4::fullDescription(unsigned int key) const { + switch (key) { + case PROBLEM_TEST_FILE: { + return tr("

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.

"); + } + } +} \ No newline at end of file diff --git a/src/games/fallout4/src/gamefallout4.h b/src/games/fallout4/src/gamefallout4.h index f80fc170..4d6be8c3 100644 --- a/src/games/fallout4/src/gamefallout4.h +++ b/src/games/fallout4/src/gamefallout4.h @@ -3,24 +3,26 @@ #include "gamegamebryo.h" +#include "iplugindiagnose.h" #include #include -class GameFallout4 : public GameGamebryo +class GameFallout4 : public GameGamebryo, public MOBase::IPluginDiagnose { Q_OBJECT - + Q_INTERFACES(MOBase::IPlugin MOBase::IPluginGame MOBase::IPluginDiagnose) Q_PLUGIN_METADATA(IID "org.tannin.GameFallout4" FILE "gamefallout4.json") public: - GameFallout4(); virtual bool init(MOBase::IOrganizer *moInfo) override; -public: // IPluginGame interface +public: + QStringList testFilePlugins() const; +public: // IPluginGame interface virtual QString gameName() const override; virtual void detectGame() override; virtual QList executables() const override; @@ -34,25 +36,36 @@ public: // IPluginGame interface virtual QStringList iniFiles() const override; virtual QStringList DLCPlugins() const override; virtual QStringList CCPlugins() const override; + virtual SortMechanism sortMechanism() const override; virtual LoadOrderMechanism loadOrderMechanism() const override; virtual int nexusModOrganizerID() const override; virtual int nexusGameID() const override; +public: // IPluginDiagnose interface + virtual std::vector activeProblems() const override; + virtual QString shortDescription(unsigned int key) const override; + virtual QString fullDescription(unsigned int key) const override; + virtual bool hasGuidedFix(unsigned int key) const override { return false; } + virtual void startGuidedFix(unsigned int key) 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 settings() const override; + virtual MappingType mappings() const override; protected: - std::shared_ptr makeSaveGame(QString filePath) const override; QString savegameExtension() const override; QString savegameSEExtension() const override; +private: + bool testFilePresent() const; + +private: + static const unsigned int PROBLEM_TEST_FILE = 1; }; #endif // GAMEFallout4_H From 5580bf4568ae48e9f668e1a1b9d5fcb3d1437fe3 Mon Sep 17 00:00:00 2001 From: Jeremy Rimpo Date: Sat, 16 Dec 2023 16:42:42 -0600 Subject: [PATCH 1415/1544] [game_ttw] Use newvegas as Nexus slug to allow pulling categories --- src/games/ttw/src/gamefalloutttw.cpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/games/ttw/src/gamefalloutttw.cpp b/src/games/ttw/src/gamefalloutttw.cpp index f48fb4cb..3fa8e85e 100644 --- a/src/games/ttw/src/gamefalloutttw.cpp +++ b/src/games/ttw/src/gamefalloutttw.cpp @@ -284,7 +284,7 @@ QStringList GameFalloutTTW::validShortNames() const QString GameFalloutTTW::gameNexusName() const { - return QString(); + return "newvegas"; } QStringList GameFalloutTTW::iniFiles() const @@ -310,7 +310,7 @@ int GameFalloutTTW::nexusModOrganizerID() const int GameFalloutTTW::nexusGameID() const { - return 0; + return 130; } QDir GameFalloutTTW::gameDirectory() const From fc41c894b45f1bc195df066ec622d1236c889d41 Mon Sep 17 00:00:00 2001 From: Jeremy Rimpo Date: Sat, 16 Dec 2023 16:54:43 -0600 Subject: [PATCH 1416/1544] [game_skyrimvr] Add conditional ESL support with xSE plugin --- src/games/skyrimvr/src/skyrimvrgameplugins.cpp | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/src/games/skyrimvr/src/skyrimvrgameplugins.cpp b/src/games/skyrimvr/src/skyrimvrgameplugins.cpp index f310f82e..7818666f 100644 --- a/src/games/skyrimvr/src/skyrimvrgameplugins.cpp +++ b/src/games/skyrimvr/src/skyrimvrgameplugins.cpp @@ -8,5 +8,8 @@ SkyrimVRGamePlugins::SkyrimVRGamePlugins(MOBase::IOrganizer* organizer) : Creati bool SkyrimVRGamePlugins::lightPluginsAreSupported() { - return false; + auto files = m_Organizer->findFiles("sfse\\plugins", { "skyrimvresl.dll" }); + if (files.isEmpty()) + return false; + return true; } \ No newline at end of file From b694d7e19978b61fde0f15d2b380cb459133f720 Mon Sep 17 00:00:00 2001 From: Jeremy Rimpo Date: Sat, 16 Dec 2023 16:55:57 -0600 Subject: [PATCH 1417/1544] [game_skyrimvr] Fix a typo --- src/games/skyrimvr/src/skyrimvrgameplugins.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/games/skyrimvr/src/skyrimvrgameplugins.cpp b/src/games/skyrimvr/src/skyrimvrgameplugins.cpp index 7818666f..c5f5b55b 100644 --- a/src/games/skyrimvr/src/skyrimvrgameplugins.cpp +++ b/src/games/skyrimvr/src/skyrimvrgameplugins.cpp @@ -8,7 +8,7 @@ SkyrimVRGamePlugins::SkyrimVRGamePlugins(MOBase::IOrganizer* organizer) : Creati bool SkyrimVRGamePlugins::lightPluginsAreSupported() { - auto files = m_Organizer->findFiles("sfse\\plugins", { "skyrimvresl.dll" }); + auto files = m_Organizer->findFiles("skse\\plugins", { "skyrimvresl.dll" }); if (files.isEmpty()) return false; return true; From cd38770894a865c2a3e45d9498bf9fa9708d5d45 Mon Sep 17 00:00:00 2001 From: Jeremy Rimpo Date: Thu, 28 Dec 2023 03:24:18 -0600 Subject: [PATCH 1418/1544] [game_ttw] Revert changes - Using an alternate method to determine category source --- src/games/ttw/src/gamefalloutttw.cpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/games/ttw/src/gamefalloutttw.cpp b/src/games/ttw/src/gamefalloutttw.cpp index 3fa8e85e..a9fe912d 100644 --- a/src/games/ttw/src/gamefalloutttw.cpp +++ b/src/games/ttw/src/gamefalloutttw.cpp @@ -284,7 +284,7 @@ QStringList GameFalloutTTW::validShortNames() const QString GameFalloutTTW::gameNexusName() const { - return "newvegas"; + return ""; } QStringList GameFalloutTTW::iniFiles() const @@ -310,7 +310,7 @@ int GameFalloutTTW::nexusModOrganizerID() const int GameFalloutTTW::nexusGameID() const { - return 130; + return 0; } QDir GameFalloutTTW::gameDirectory() const From e19009baa6249c74d73a178ba434c77187bbd297 Mon Sep 17 00:00:00 2001 From: Liderate <122295667+Liderate@users.noreply.github.com> Date: Mon, 8 Jan 2024 03:33:02 -0500 Subject: [PATCH 1419/1544] [game_ttw] KEYWORDS and BaseObjectSwapper valid folders. (#34) * KEYWORDS and BaseObjectSwapper valid folders. * Remove unused custom.ini --------- Co-authored-by: Liderate --- src/games/ttw/src/falloutttwmoddatachecker.h | 27 +++++++++++--------- src/games/ttw/src/gamefalloutttw.cpp | 5 ++-- 2 files changed, 17 insertions(+), 15 deletions(-) diff --git a/src/games/ttw/src/falloutttwmoddatachecker.h b/src/games/ttw/src/falloutttwmoddatachecker.h index 744153c8..89365f2f 100644 --- a/src/games/ttw/src/falloutttwmoddatachecker.h +++ b/src/games/ttw/src/falloutttwmoddatachecker.h @@ -9,21 +9,24 @@ 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" - }; + 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"}; return result; } - virtual const FileNameSet& possibleFileExtensions() const override { - static FileNameSet result{ - "esp", "esm", "bsa", "modgroups", "ini" - }; + virtual const FileNameSet& possibleFileExtensions() const override + { + static FileNameSet result{"esp", "esm", "bsa", "modgroups", "ini"}; return result; } }; -#endif // FALLOUTTTW_MODATACHECKER_H +#endif // FALLOUTTTW_MODATACHECKER_H diff --git a/src/games/ttw/src/gamefalloutttw.cpp b/src/games/ttw/src/gamefalloutttw.cpp index 1185379f..7dfd21af 100644 --- a/src/games/ttw/src/gamefalloutttw.cpp +++ b/src/games/ttw/src/gamefalloutttw.cpp @@ -220,7 +220,6 @@ void GameFalloutTTW::initializeProfile(const QDir& path, ProfileSettings setting copyToProfile(myGamesPath(), path, "falloutprefs.ini"); copyToProfile(myGamesPath(), path, "falloutcustom.ini"); - copyToProfile(myGamesPath(), path, "custom.ini"); copyToProfile(myGamesPath(), path, "GECKCustom.ini"); copyToProfile(myGamesPath(), path, "GECKPrefs.ini"); } @@ -289,8 +288,8 @@ QString GameFalloutTTW::gameNexusName() const QStringList GameFalloutTTW::iniFiles() const { - return {"fallout.ini", "falloutprefs.ini", "falloutcustom.ini", - "custom.ini", "GECKCustom.ini", "GECKPrefs.ini"}; + return {"fallout.ini", "falloutprefs.ini", "falloutcustom.ini", "GECKCustom.ini", + "GECKPrefs.ini"}; } QStringList GameFalloutTTW::DLCPlugins() const From 9fc0bde40c736d3e051877da1c200f36329f8153 Mon Sep 17 00:00:00 2001 From: Liderate <122295667+Liderate@users.noreply.github.com> Date: Mon, 8 Jan 2024 05:12:16 -0500 Subject: [PATCH 1420/1544] [game_falloutnv] KEYWORDS and BaseObjectSwapper valid folders. (#28) * KEYWORDS and BaseObjectSwapper valid folders. * Remove unused custom.ini --------- Co-authored-by: Liderate --- src/games/falloutnv/src/falloutnvmoddatachecker.h | 15 +++++++++------ src/games/falloutnv/src/gamefalloutnv.cpp | 5 ++--- 2 files changed, 11 insertions(+), 9 deletions(-) diff --git a/src/games/falloutnv/src/falloutnvmoddatachecker.h b/src/games/falloutnv/src/falloutnvmoddatachecker.h index 2aeb1ab6..fa81d74b 100644 --- a/src/games/falloutnv/src/falloutnvmoddatachecker.h +++ b/src/games/falloutnv/src/falloutnvmoddatachecker.h @@ -11,12 +11,15 @@ public: 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"}; + 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"}; return result; } virtual const FileNameSet& possibleFileExtensions() const override diff --git a/src/games/falloutnv/src/gamefalloutnv.cpp b/src/games/falloutnv/src/gamefalloutnv.cpp index 5938e4dd..ffdf0ee8 100644 --- a/src/games/falloutnv/src/gamefalloutnv.cpp +++ b/src/games/falloutnv/src/gamefalloutnv.cpp @@ -218,7 +218,6 @@ void GameFalloutNV::initializeProfile(const QDir& path, ProfileSettings settings copyToProfile(myGamesPath(), path, "falloutprefs.ini"); copyToProfile(myGamesPath(), path, "falloutcustom.ini"); - copyToProfile(myGamesPath(), path, "custom.ini"); copyToProfile(myGamesPath(), path, "GECKCustom.ini"); copyToProfile(myGamesPath(), path, "GECKPrefs.ini"); } @@ -272,8 +271,8 @@ QString GameFalloutNV::gameNexusName() const QStringList GameFalloutNV::iniFiles() const { - return {"fallout.ini", "falloutprefs.ini", "falloutcustom.ini", - "custom.ini", "GECKCustom.ini", "GECKPrefs.ini"}; + return {"fallout.ini", "falloutprefs.ini", "falloutcustom.ini", "GECKCustom.ini", + "GECKPrefs.ini"}; } QStringList GameFalloutNV::DLCPlugins() const From 4319df6eaa4335a86b9982c5c31ff9006516fb4b Mon Sep 17 00:00:00 2001 From: Liderate Date: Tue, 9 Jan 2024 00:40:26 -0500 Subject: [PATCH 1421/1544] [game_fallout3] EGS game path detection. --- src/games/fallout3/src/gamefallout3.cpp | 18 ++++++++++++++++++ src/games/fallout3/src/gamefallout3.h | 2 +- 2 files changed, 19 insertions(+), 1 deletion(-) diff --git a/src/games/fallout3/src/gamefallout3.cpp b/src/games/fallout3/src/gamefallout3.cpp index 00d566d5..87f3cad3 100644 --- a/src/games/fallout3/src/gamefallout3.cpp +++ b/src/games/fallout3/src/gamefallout3.cpp @@ -48,6 +48,24 @@ bool GameFallout3::init(IOrganizer *moInfo) return true; } +QString GameFallout3::identifyGamePath() const +{ + auto result = GameGamebryo::identifyGamePath(); // Default registry path + // EPIC Game Store + if (result.isEmpty()) { + // Fallout 3: Game of the Year Edition: adeae8bbfc94427db57c7dfecce3f1d4 + result = parseEpicGamesLocation({ "adeae8bbfc94427db57c7dfecce3f1d4" }); + if (QFileInfo(result).isDir()) { + QDir startPath = QDir(result); + auto subDirs = startPath.entryList({ "Fallout 3 GOTY*" }, + QDir::Dirs | QDir::NoDotAndDotDot); + if (!subDirs.isEmpty()) + result = startPath.absoluteFilePath(subDirs.first()); + } + } + return result; +} + QString GameFallout3::gameName() const { return "Fallout 3"; diff --git a/src/games/fallout3/src/gamefallout3.h b/src/games/fallout3/src/gamefallout3.h index 4712e035..c3c92e5f 100644 --- a/src/games/fallout3/src/gamefallout3.h +++ b/src/games/fallout3/src/gamefallout3.h @@ -46,7 +46,7 @@ public: // IPlugin interface virtual QList settings() const override; protected: - + virtual QString identifyGamePath() const override; virtual QString savegameExtension() const override; virtual QString savegameSEExtension() const override; std::shared_ptr makeSaveGame(QString filePath) const override; From 3b173b79e24e5a5238f1e30c3bd560f727f5247a Mon Sep 17 00:00:00 2001 From: Ungeziefi <163609976+Ungeziefi@users.noreply.github.com> Date: Sat, 11 May 2024 08:10:37 +0200 Subject: [PATCH 1422/1544] [game_ttw] Create README.md --- src/games/ttw/README.md | 11 +++++++++++ 1 file changed, 11 insertions(+) create mode 100644 src/games/ttw/README.md diff --git a/src/games/ttw/README.md b/src/games/ttw/README.md new file mode 100644 index 00000000..56708f20 --- /dev/null +++ b/src/games/ttw/README.md @@ -0,0 +1,11 @@ +https://github.com/ModOrganizer2/modorganizer + +https://github.com/Ungeziefi/ML-ModOrganizer2 + +https://github.com/Ungeziefi/ML-USVFS + +https://github.com/Ungeziefi/ML-NXMHandler + +https://github.com/Ungeziefi/ML-DiagnoseBasic + +https://github.com/Ungeziefi/ML-TTWPlugin From 28705904be8145e0869958761de8d8bdf800b7a2 Mon Sep 17 00:00:00 2001 From: Ungeziefi <163609976+Ungeziefi@users.noreply.github.com> Date: Sat, 11 May 2024 08:11:52 +0200 Subject: [PATCH 1423/1544] [game_ttw] YUPTTW.esm as base plugin --- src/games/ttw/src/gamefalloutttw.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/games/ttw/src/gamefalloutttw.cpp b/src/games/ttw/src/gamefalloutttw.cpp index 7dfd21af..683b2e25 100644 --- a/src/games/ttw/src/gamefalloutttw.cpp +++ b/src/games/ttw/src/gamefalloutttw.cpp @@ -253,7 +253,7 @@ QStringList GameFalloutTTW::primaryPlugins() const "fallout3.esm", "anchorage.esm", "thepitt.esm", "brokensteel.esm", "pointlookout.esm", "zeta.esm", "caravanpack.esm", "classicpack.esm", "mercenarypack.esm", - "tribalpack.esm", "taleoftwowastelands.esm"}; + "tribalpack.esm", "taleoftwowastelands.esm","YUPTTW.esm"}; } QStringList GameFalloutTTW::gameVariants() const From 85a5c2862282e3594dc8f954839435c5a07cf071 Mon Sep 17 00:00:00 2001 From: Ungeziefi Date: Sat, 11 May 2024 12:28:48 +0200 Subject: [PATCH 1424/1544] [game_falloutnv] Removed BOSS and FOMM --- src/games/falloutnv/src/gamefalloutnv.cpp | 2 -- 1 file changed, 2 deletions(-) diff --git a/src/games/falloutnv/src/gamefalloutnv.cpp b/src/games/falloutnv/src/gamefalloutnv.cpp index ffdf0ee8..47f09004 100644 --- a/src/games/falloutnv/src/gamefalloutnv.cpp +++ b/src/games/falloutnv/src/gamefalloutnv.cpp @@ -149,9 +149,7 @@ QList GameFalloutNV::executables() const ExecutableInfo launcher("Fallout Launcher", findInGameFolder(getLauncherName())); QList extraExecutables = QList() - << ExecutableInfo("Fallout Mod Manager", findInGameFolder("fomm/fomm.exe")) << ExecutableInfo("Construction Kit", findInGameFolder("geck.exe")) - << ExecutableInfo("BOSS", findInGameFolder("BOSS/BOSS.exe")) << ExecutableInfo("LOOT", QFileInfo(getLootPath())) .withArgument("--game=\"FalloutNV\""); if (selectedVariant() != "Epic Games") { From 1ecb4dd7465fb0a4ba409b15c725eb29d7a2f541 Mon Sep 17 00:00:00 2001 From: Ungeziefi Date: Sat, 11 May 2024 12:30:04 +0200 Subject: [PATCH 1425/1544] [game_ttw] Removed BOSS and FOMM --- src/games/ttw/src/gamefalloutttw.cpp | 2 -- 1 file changed, 2 deletions(-) diff --git a/src/games/ttw/src/gamefalloutttw.cpp b/src/games/ttw/src/gamefalloutttw.cpp index 683b2e25..a80628a3 100644 --- a/src/games/ttw/src/gamefalloutttw.cpp +++ b/src/games/ttw/src/gamefalloutttw.cpp @@ -151,9 +151,7 @@ QList GameFalloutTTW::executables() const ExecutableInfo launcher("Fallout Launcher", findInGameFolder(getLauncherName())); QList extraExecutables = QList() - << ExecutableInfo("Fallout Mod Manager", findInGameFolder("fomm/fomm.exe")) << ExecutableInfo("Construction Kit", findInGameFolder("geck.exe")) - << ExecutableInfo("BOSS", findInGameFolder("BOSS/BOSS.exe")) << ExecutableInfo("LOOT", QFileInfo(getLootPath())) .withArgument("--game=\"FalloutNV\""); if (selectedVariant() != "Epic Games") { From 4fad0a2d6ca715163cbff8fab29d56c38e3ce8b8 Mon Sep 17 00:00:00 2001 From: Senjay-id <110238760+Senjay-id@users.noreply.github.com> Date: Sun, 12 May 2024 14:05:11 +0700 Subject: [PATCH 1426/1544] [game_ttw] change construction kit into geck --- src/games/ttw/src/gamefalloutttw.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/games/ttw/src/gamefalloutttw.cpp b/src/games/ttw/src/gamefalloutttw.cpp index a80628a3..901bd0bd 100644 --- a/src/games/ttw/src/gamefalloutttw.cpp +++ b/src/games/ttw/src/gamefalloutttw.cpp @@ -151,7 +151,7 @@ QList GameFalloutTTW::executables() const ExecutableInfo launcher("Fallout Launcher", findInGameFolder(getLauncherName())); QList extraExecutables = QList() - << ExecutableInfo("Construction Kit", findInGameFolder("geck.exe")) + << ExecutableInfo("GECK", findInGameFolder("geck.exe")) << ExecutableInfo("LOOT", QFileInfo(getLootPath())) .withArgument("--game=\"FalloutNV\""); if (selectedVariant() != "Epic Games") { From 401b03b4d226b1ebd85de16fcf4dddf56eae5edd Mon Sep 17 00:00:00 2001 From: Senjay-id <110238760+Senjay-id@users.noreply.github.com> Date: Mon, 13 May 2024 07:22:37 +0700 Subject: [PATCH 1427/1544] [game_falloutnv] change construction kit to geck --- src/games/falloutnv/src/gamefalloutnv.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/games/falloutnv/src/gamefalloutnv.cpp b/src/games/falloutnv/src/gamefalloutnv.cpp index 47f09004..1c47d23c 100644 --- a/src/games/falloutnv/src/gamefalloutnv.cpp +++ b/src/games/falloutnv/src/gamefalloutnv.cpp @@ -149,7 +149,7 @@ QList GameFalloutNV::executables() const ExecutableInfo launcher("Fallout Launcher", findInGameFolder(getLauncherName())); QList extraExecutables = QList() - << ExecutableInfo("Construction Kit", findInGameFolder("geck.exe")) + << ExecutableInfo("GECK", findInGameFolder("geck.exe")) << ExecutableInfo("LOOT", QFileInfo(getLootPath())) .withArgument("--game=\"FalloutNV\""); if (selectedVariant() != "Epic Games") { From 7903fb9d312c05ada2040288d4ccb015d3f20320 Mon Sep 17 00:00:00 2001 From: Ungeziefi Date: Tue, 14 May 2024 19:38:51 +0200 Subject: [PATCH 1428/1544] [game_ttw] Update README.md --- src/games/ttw/README.md | 12 +----------- 1 file changed, 1 insertion(+), 11 deletions(-) diff --git a/src/games/ttw/README.md b/src/games/ttw/README.md index 56708f20..f360c06e 100644 --- a/src/games/ttw/README.md +++ b/src/games/ttw/README.md @@ -1,11 +1 @@ -https://github.com/ModOrganizer2/modorganizer - -https://github.com/Ungeziefi/ML-ModOrganizer2 - -https://github.com/Ungeziefi/ML-USVFS - -https://github.com/Ungeziefi/ML-NXMHandler - -https://github.com/Ungeziefi/ML-DiagnoseBasic - -https://github.com/Ungeziefi/ML-TTWPlugin +https://www.nexusmods.com/site/mods/874 \ No newline at end of file From e47654ce58058447fedb39717bfcc76f8ac30806 Mon Sep 17 00:00:00 2001 From: Ungeziefi Date: Tue, 14 May 2024 20:47:00 +0200 Subject: [PATCH 1429/1544] [game_falloutnv] Forced the correct DLC positions --- src/games/falloutnv/src/game_falloutNV_en.ts | 4 ++-- src/games/falloutnv/src/gamefalloutnv.cpp | 6 +++++- 2 files changed, 7 insertions(+), 3 deletions(-) diff --git a/src/games/falloutnv/src/game_falloutNV_en.ts b/src/games/falloutnv/src/game_falloutNV_en.ts index ceb068ad..cf6b182c 100644 --- a/src/games/falloutnv/src/game_falloutNV_en.ts +++ b/src/games/falloutnv/src/game_falloutNV_en.ts @@ -4,12 +4,12 @@ GameFalloutNV - + Fallout NV Support Plugin - + Adds support for the game Fallout New Vegas diff --git a/src/games/falloutnv/src/gamefalloutnv.cpp b/src/games/falloutnv/src/gamefalloutnv.cpp index 1c47d23c..1b609fab 100644 --- a/src/games/falloutnv/src/gamefalloutnv.cpp +++ b/src/games/falloutnv/src/gamefalloutnv.cpp @@ -244,7 +244,11 @@ QString GameFalloutNV::steamAPPId() const QStringList GameFalloutNV::primaryPlugins() const { - return {"falloutnv.esm"}; + return { + "falloutnv.esm", "DeadMoney.esm", "HonestHearts.esm", "OldWorldBlues.esm", + "LonesomeRoad.esm", "GunRunnersArsenal.esm", "ClassicPack.esm", + "MercenaryPack.esm", "TribalPack.esm", "CaravanPack.esm" + }; } QStringList GameFalloutNV::gameVariants() const From f44e1eccd652da6ee720fff61a3f178674837bca Mon Sep 17 00:00:00 2001 From: Twinki Date: Tue, 14 May 2024 18:12:20 -0400 Subject: [PATCH 1430/1544] [game_ttw] remove readme --- src/games/ttw/README.md | 1 - 1 file changed, 1 deletion(-) delete mode 100644 src/games/ttw/README.md diff --git a/src/games/ttw/README.md b/src/games/ttw/README.md deleted file mode 100644 index f360c06e..00000000 --- a/src/games/ttw/README.md +++ /dev/null @@ -1 +0,0 @@ -https://www.nexusmods.com/site/mods/874 \ No newline at end of file From 9285b99bc965d159c107e691eedca9c5d1527962 Mon Sep 17 00:00:00 2001 From: Twinki Date: Wed, 15 May 2024 11:58:41 -0400 Subject: [PATCH 1431/1544] [game_falloutnv] revert primary plugins --- src/games/falloutnv/src/gamefalloutnv.cpp | 6 +----- 1 file changed, 1 insertion(+), 5 deletions(-) diff --git a/src/games/falloutnv/src/gamefalloutnv.cpp b/src/games/falloutnv/src/gamefalloutnv.cpp index 1b609fab..4cfe036a 100644 --- a/src/games/falloutnv/src/gamefalloutnv.cpp +++ b/src/games/falloutnv/src/gamefalloutnv.cpp @@ -244,11 +244,7 @@ QString GameFalloutNV::steamAPPId() const QStringList GameFalloutNV::primaryPlugins() const { - return { - "falloutnv.esm", "DeadMoney.esm", "HonestHearts.esm", "OldWorldBlues.esm", - "LonesomeRoad.esm", "GunRunnersArsenal.esm", "ClassicPack.esm", - "MercenaryPack.esm", "TribalPack.esm", "CaravanPack.esm" - }; + return { "falloutnv.esm" }; } QStringList GameFalloutNV::gameVariants() const From 93e487aa2b8b4983011e6fa3641407f54995f768 Mon Sep 17 00:00:00 2001 From: Twinki Date: Wed, 15 May 2024 11:59:16 -0400 Subject: [PATCH 1432/1544] [game_falloutnv] formatting --- src/games/falloutnv/src/gamefalloutnv.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/games/falloutnv/src/gamefalloutnv.cpp b/src/games/falloutnv/src/gamefalloutnv.cpp index 4cfe036a..1c47d23c 100644 --- a/src/games/falloutnv/src/gamefalloutnv.cpp +++ b/src/games/falloutnv/src/gamefalloutnv.cpp @@ -244,7 +244,7 @@ QString GameFalloutNV::steamAPPId() const QStringList GameFalloutNV::primaryPlugins() const { - return { "falloutnv.esm" }; + return {"falloutnv.esm"}; } QStringList GameFalloutNV::gameVariants() const From ecc37f5f97b45e210153ec081ca942ea07cd83df Mon Sep 17 00:00:00 2001 From: Twinki Date: Wed, 15 May 2024 12:00:05 -0400 Subject: [PATCH 1433/1544] [game_falloutnv] add old execs --- src/games/falloutnv/src/gamefalloutnv.cpp | 2 ++ 1 file changed, 2 insertions(+) diff --git a/src/games/falloutnv/src/gamefalloutnv.cpp b/src/games/falloutnv/src/gamefalloutnv.cpp index 1c47d23c..2230b13d 100644 --- a/src/games/falloutnv/src/gamefalloutnv.cpp +++ b/src/games/falloutnv/src/gamefalloutnv.cpp @@ -149,6 +149,8 @@ QList GameFalloutNV::executables() const ExecutableInfo launcher("Fallout Launcher", findInGameFolder(getLauncherName())); QList extraExecutables = QList() + << ExecutableInfo("Fallout Mod Manager", findInGameFolder("fomm/fomm.exe")) + << ExecutableInfo("BOSS", findInGameFolder("BOSS/BOSS.exe")) << ExecutableInfo("GECK", findInGameFolder("geck.exe")) << ExecutableInfo("LOOT", QFileInfo(getLootPath())) .withArgument("--game=\"FalloutNV\""); From 5885edec195d8e40bbebd1a89064275082ecbde4 Mon Sep 17 00:00:00 2001 From: Twinki Date: Wed, 15 May 2024 12:00:41 -0400 Subject: [PATCH 1434/1544] [game_falloutnv] revert ts --- src/games/falloutnv/src/game_falloutNV_en.ts | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/games/falloutnv/src/game_falloutNV_en.ts b/src/games/falloutnv/src/game_falloutNV_en.ts index cf6b182c..ceb068ad 100644 --- a/src/games/falloutnv/src/game_falloutNV_en.ts +++ b/src/games/falloutnv/src/game_falloutNV_en.ts @@ -4,12 +4,12 @@ GameFalloutNV - + Fallout NV Support Plugin - + Adds support for the game Fallout New Vegas From 674962018a3c1a382191f50a57c567da25ca8ad5 Mon Sep 17 00:00:00 2001 From: Twinki Date: Wed, 15 May 2024 13:14:11 -0400 Subject: [PATCH 1435/1544] [game_falloutnv] run clang-format --- src/games/falloutnv/src/gamefalloutnv.cpp | 13 +++++++------ 1 file changed, 7 insertions(+), 6 deletions(-) diff --git a/src/games/falloutnv/src/gamefalloutnv.cpp b/src/games/falloutnv/src/gamefalloutnv.cpp index 2230b13d..b256efd3 100644 --- a/src/games/falloutnv/src/gamefalloutnv.cpp +++ b/src/games/falloutnv/src/gamefalloutnv.cpp @@ -148,12 +148,13 @@ QList GameFalloutNV::executables() const ExecutableInfo game("New Vegas", findInGameFolder(binaryName())); ExecutableInfo launcher("Fallout Launcher", findInGameFolder(getLauncherName())); QList extraExecutables = - QList() - << ExecutableInfo("Fallout Mod Manager", findInGameFolder("fomm/fomm.exe")) - << ExecutableInfo("BOSS", findInGameFolder("BOSS/BOSS.exe")) - << ExecutableInfo("GECK", findInGameFolder("geck.exe")) - << ExecutableInfo("LOOT", QFileInfo(getLootPath())) - .withArgument("--game=\"FalloutNV\""); + QList() << ExecutableInfo("Fallout Mod Manager", + findInGameFolder("fomm/fomm.exe")) + << ExecutableInfo("BOSS", + findInGameFolder("BOSS/BOSS.exe")) + << ExecutableInfo("GECK", findInGameFolder("geck.exe")) + << ExecutableInfo("LOOT", QFileInfo(getLootPath())) + .withArgument("--game=\"FalloutNV\""); if (selectedVariant() != "Epic Games") { extraExecutables.prepend(ExecutableInfo( "NVSE", findInGameFolder(feature()->loaderName()))); From 7713005a48ead7422a9d4f69e7e61c66c3400c14 Mon Sep 17 00:00:00 2001 From: Liderate Date: Wed, 15 May 2024 23:47:26 -0400 Subject: [PATCH 1436/1544] List valid saves if exception is raised for invalid save --- src/gamebryo/gamebryosavegame.cpp | 12 +++++++----- src/gamebryo/gamegamebryo.cpp | 8 +++++++- 2 files changed, 14 insertions(+), 6 deletions(-) diff --git a/src/gamebryo/gamebryosavegame.cpp b/src/gamebryo/gamebryosavegame.cpp index 7daf96f3..e6fe6be6 100644 --- a/src/gamebryo/gamebryosavegame.cpp +++ b/src/gamebryo/gamebryosavegame.cpp @@ -106,11 +106,13 @@ GamebryoSaveGame::FileWrapper::FileWrapper(QString const& filepath, QString id(fileID.data()); if (expected != id) { - throw std::runtime_error(QObject::tr("wrong file format - expected %1 got %2") - .arg(expected) - .arg(id) - .toUtf8() - .constData()); + throw std::runtime_error( + QObject::tr("wrong file format - expected %1 got \'%2\' for %3") + .arg(expected) + .arg(id) + .arg(filepath) + .toUtf8() + .constData()); } } diff --git a/src/gamebryo/gamegamebryo.cpp b/src/gamebryo/gamegamebryo.cpp index b01d1370..1aeebdfb 100644 --- a/src/gamebryo/gamegamebryo.cpp +++ b/src/gamebryo/gamegamebryo.cpp @@ -6,6 +6,7 @@ #include "gamebryosavegame.h" #include "gameplugins.h" #include "iprofile.h" +#include "log.h" #include "registry.h" #include "savegameinfo.h" #include "scopeguard.h" @@ -95,7 +96,12 @@ GameGamebryo::listSaves(QDir folder) const std::vector> saves; for (auto info : folder.entryInfoList(filters, QDir::Files)) { - saves.push_back(makeSaveGame(info.filePath())); + try { + saves.push_back(makeSaveGame(info.filePath())); + } catch (std::exception& e) { + MOBase::log::error("{}", e.what()); + continue; + } } return saves; From 1d67f536fdcd7515f01ff421e651fc1b0f61446c Mon Sep 17 00:00:00 2001 From: Jeremy Rimpo Date: Thu, 16 May 2024 23:44:43 -0500 Subject: [PATCH 1437/1544] [game_starfield] Add main plugins introduced with new update --- src/games/starfield/src/gamestarfield.cpp | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/src/games/starfield/src/gamestarfield.cpp b/src/games/starfield/src/gamestarfield.cpp index 480ee9c2..218aa19e 100644 --- a/src/games/starfield/src/gamestarfield.cpp +++ b/src/games/starfield/src/gamestarfield.cpp @@ -226,7 +226,8 @@ QStringList GameStarfield::testFilePlugins() const QStringList GameStarfield::primaryPlugins() const { - QStringList plugins = {"Starfield.esm", "Constellation.esm", "OldMars.esm"}; + QStringList plugins = {"Starfield.esm", "Constellation.esm", "OldMars.esm", + "SFBGS006.esm", "SFBGS007.esm", "SFBGS008.esm"}; auto testPlugins = testFilePlugins(); if (loadOrderMechanism() == LoadOrderMechanism::None) { From a707d7e793fbf4c38f31d80dca140a5ab952b88c Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Mika=C3=ABl=20Capelle?= Date: Tue, 21 May 2024 21:24:55 +0200 Subject: [PATCH 1438/1544] Remove unused fmt header. (#53) --- src/gamebryo/game_gamebryo_en.ts | 10 +++++----- src/gamebryo/gamegamebryo.cpp | 2 -- 2 files changed, 5 insertions(+), 7 deletions(-) diff --git a/src/gamebryo/game_gamebryo_en.ts b/src/gamebryo/game_gamebryo_en.ts index d875a0fc..2dcc143b 100644 --- a/src/gamebryo/game_gamebryo_en.ts +++ b/src/gamebryo/game_gamebryo_en.ts @@ -136,7 +136,7 @@ - + %1, #%2, Level %3, %4 @@ -146,17 +146,17 @@ - - wrong file format - expected %1 got %2 + + wrong file format - expected %1 got '%2' for %3 - + failed to query registry path (preflight): %1 - + failed to query registry path (read): %1 diff --git a/src/gamebryo/gamegamebryo.cpp b/src/gamebryo/gamegamebryo.cpp index 1aeebdfb..0ad60004 100644 --- a/src/gamebryo/gamegamebryo.cpp +++ b/src/gamebryo/gamegamebryo.cpp @@ -34,8 +34,6 @@ #include #include -#include - GameGamebryo::GameGamebryo() {} void GameGamebryo::detectGame() From 894ad476b7d3159643e807d42ffeb0b1dd1b18f9 Mon Sep 17 00:00:00 2001 From: Twinki Date: Thu, 23 May 2024 03:57:45 -0400 Subject: [PATCH 1439/1544] [game_falloutnv] Add setting to disable/enable LOOT (#30) * Add setting to disable/enable LOOT # Motivations This plugin has been missing a sortMechanism definition for awhile, and generally it's recommended in the FNV modding community not to use LOOT # Modifications - Add a plugin setting to enable/disable the LOOT sort button, default it to false - Update the `gameName()` to follow the other Fallout game plugins * revert gameName --- src/games/falloutnv/src/game_falloutNV_en.ts | 9 +++++++-- src/games/falloutnv/src/gamefalloutnv.cpp | 13 ++++++++++++- src/games/falloutnv/src/gamefalloutnv.h | 1 + 3 files changed, 20 insertions(+), 3 deletions(-) diff --git a/src/games/falloutnv/src/game_falloutNV_en.ts b/src/games/falloutnv/src/game_falloutNV_en.ts index ceb068ad..589af613 100644 --- a/src/games/falloutnv/src/game_falloutNV_en.ts +++ b/src/games/falloutnv/src/game_falloutNV_en.ts @@ -4,14 +4,19 @@ GameFalloutNV - + Fallout NV Support Plugin - + Adds support for the game Fallout New Vegas + + + While not recommended by the FNV modding community, enables LOOT sorting + + diff --git a/src/games/falloutnv/src/gamefalloutnv.cpp b/src/games/falloutnv/src/gamefalloutnv.cpp index b256efd3..e5b64b82 100644 --- a/src/games/falloutnv/src/gamefalloutnv.cpp +++ b/src/games/falloutnv/src/gamefalloutnv.cpp @@ -199,7 +199,11 @@ MOBase::VersionInfo GameFalloutNV::version() const QList GameFalloutNV::settings() const { - return QList(); + return QList() + << PluginSetting("enable_loot_sorting", + tr("While not recommended by the FNV modding community, " + "enables LOOT sorting"), + false); } void GameFalloutNV::initializeProfile(const QDir& path, ProfileSettings settings) const @@ -283,6 +287,13 @@ QStringList GameFalloutNV::DLCPlugins() const "ClassicPack.esm", "MercenaryPack.esm", "TribalPack.esm"}; } +MOBase::IPluginGame::SortMechanism GameFalloutNV::sortMechanism() const +{ + if (m_Organizer->pluginSetting(name(), "enable_loot_sorting").toBool()) + return IPluginGame::SortMechanism::LOOT; + return IPluginGame::SortMechanism::NONE; +} + int GameFalloutNV::nexusModOrganizerID() const { return 42572; diff --git a/src/games/falloutnv/src/gamefalloutnv.h b/src/games/falloutnv/src/gamefalloutnv.h index b3ab7057..74f98b2f 100644 --- a/src/games/falloutnv/src/gamefalloutnv.h +++ b/src/games/falloutnv/src/gamefalloutnv.h @@ -34,6 +34,7 @@ public: // IPluginGame interface virtual QString gameNexusName() const override; virtual QStringList iniFiles() const override; virtual QStringList DLCPlugins() const override; + virtual SortMechanism sortMechanism() const override; virtual int nexusModOrganizerID() const override; virtual int nexusGameID() const override; From 996f65813471149e381012f185fe9a36ca49069c Mon Sep 17 00:00:00 2001 From: Twinki Date: Sun, 26 May 2024 05:15:07 -0400 Subject: [PATCH 1440/1544] [game_ttw] Add plugin setting to enable/disable LOOT & add loot & display name (#36) * Add plugin setting to enable/disable LOOT, update names. --- src/games/ttw/.clang-format | 41 +++++++++++++++++++++++++++ src/games/ttw/src/game_ttw_en.ts | 6 ++-- src/games/ttw/src/gamefalloutttw.cpp | 42 +++++++++++++++++++--------- src/games/ttw/src/gamefalloutttw.h | 2 ++ 4 files changed, 76 insertions(+), 15 deletions(-) create mode 100644 src/games/ttw/.clang-format diff --git a/src/games/ttw/.clang-format b/src/games/ttw/.clang-format new file mode 100644 index 00000000..6098e1f5 --- /dev/null +++ b/src/games/ttw/.clang-format @@ -0,0 +1,41 @@ +--- +# We'll use defaults from the LLVM style, but with 4 columns indentation. +BasedOnStyle: LLVM +IndentWidth: 2 +--- +Language: Cpp +DeriveLineEnding: false +UseCRLF: true +DerivePointerAlignment: false +PointerAlignment: Left +AlignConsecutiveAssignments: true +AllowShortFunctionsOnASingleLine: Inline +AllowShortIfStatementsOnASingleLine: Never +AllowShortLambdasOnASingleLine: Empty +AlwaysBreakTemplateDeclarations: Yes +AccessModifierOffset: -2 +AlignTrailingComments: true +SpacesBeforeTrailingComments: 2 +NamespaceIndentation: Inner +MaxEmptyLinesToKeep: 1 +BreakBeforeBraces: Custom +BraceWrapping: + AfterCaseLabel: false + AfterClass: true + AfterControlStatement: false + AfterEnum: true + AfterFunction: true + AfterNamespace: true + AfterStruct: true + AfterUnion: true + AfterExternBlock: true + BeforeCatch: false + BeforeElse: false + BeforeLambdaBody: false + BeforeWhile: false + IndentBraces: false + SplitEmptyFunction: false + SplitEmptyRecord: false + SplitEmptyNamespace: true +ColumnLimit: 88 +ForEachMacros: ['Q_FOREACH', 'foreach'] diff --git a/src/games/ttw/src/game_ttw_en.ts b/src/games/ttw/src/game_ttw_en.ts index 477a00c3..5784cf81 100644 --- a/src/games/ttw/src/game_ttw_en.ts +++ b/src/games/ttw/src/game_ttw_en.ts @@ -4,12 +4,12 @@ GameFalloutTTW - + Fallout TTW Support Plugin - + Adds support for the game Fallout TTW @@ -172,6 +172,8 @@ failed to query registry path (read): %1 + + While not recommended by the TTW modding community, enables LOOT sorting diff --git a/src/games/ttw/src/gamefalloutttw.cpp b/src/games/ttw/src/gamefalloutttw.cpp index 901bd0bd..8f809ec6 100644 --- a/src/games/ttw/src/gamefalloutttw.cpp +++ b/src/games/ttw/src/gamefalloutttw.cpp @@ -74,7 +74,8 @@ QDir GameFalloutTTW::documentsDirectory() const QString GameFalloutTTW::identifyGamePath() const { QString path = "Software\\Bethesda Softworks\\FalloutNV"; - auto result = findInRegistry(HKEY_LOCAL_MACHINE, path.toStdWString().c_str(), L"Installed Path"); + auto result = findInRegistry(HKEY_LOCAL_MACHINE, path.toStdWString().c_str(), + L"Installed Path"); // EPIC Game Store if (result.isEmpty()) { /** @@ -130,6 +131,11 @@ QString GameFalloutTTW::gameName() const return "TTW"; } +QString GameFalloutTTW::displayGameName() const +{ + return "Tale of Two Wastelands"; +} + QString GameFalloutTTW::gameDirectoryName() const { if (selectedVariant() == "Epic Games") @@ -150,10 +156,9 @@ QList GameFalloutTTW::executables() const ExecutableInfo game("Tale of Two Wastelands", findInGameFolder(binaryName())); ExecutableInfo launcher("Fallout Launcher", findInGameFolder(getLauncherName())); QList extraExecutables = - QList() - << ExecutableInfo("GECK", findInGameFolder("geck.exe")) - << ExecutableInfo("LOOT", QFileInfo(getLootPath())) - .withArgument("--game=\"FalloutNV\""); + QList() << ExecutableInfo("GECK", findInGameFolder("geck.exe")) + << ExecutableInfo("LOOT", QFileInfo(getLootPath())) + .withArgument("--game=\"FalloutNV\""); if (selectedVariant() != "Epic Games") { extraExecutables.prepend(ExecutableInfo( "NVSE", findInGameFolder(feature()->loaderName()))); @@ -198,7 +203,11 @@ MOBase::VersionInfo GameFalloutTTW::version() const QList GameFalloutTTW::settings() const { - return QList(); + return QList() + << 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 @@ -246,12 +255,12 @@ QString GameFalloutTTW::steamAPPId() const 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"}; + 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 @@ -297,7 +306,14 @@ QStringList GameFalloutTTW::DLCPlugins() const MOBase::IPluginGame::SortMechanism GameFalloutTTW::sortMechanism() const { - return SortMechanism::NONE; + 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 diff --git a/src/games/ttw/src/gamefalloutttw.h b/src/games/ttw/src/gamefalloutttw.h index 8394c1a4..7f989b0a 100644 --- a/src/games/ttw/src/gamefalloutttw.h +++ b/src/games/ttw/src/gamefalloutttw.h @@ -20,6 +20,7 @@ public: public: // IPluginGame interface virtual QString gameName() const override; + virtual QString displayGameName() const override; virtual void detectGame() override; virtual QList executables() const override; virtual QList @@ -39,6 +40,7 @@ public: // IPluginGame interface 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; From 5e6faece79e7f55c4df03c176706868b36f20cb4 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Mika=C3=ABl=20Capelle?= Date: Sun, 26 May 2024 11:17:17 +0200 Subject: [PATCH 1441/1544] [game_ttw] Fix formatting. --- src/games/ttw/.gitattributes | 7 +++ .../ttw/src/falloutttwbsainvalidation.cpp | 8 ++-- src/games/ttw/src/falloutttwbsainvalidation.h | 11 ++--- src/games/ttw/src/falloutttwdataarchives.cpp | 28 +++++------ src/games/ttw/src/falloutttwdataarchives.h | 17 ++++--- src/games/ttw/src/falloutttwmoddatacontent.h | 13 ++--- src/games/ttw/src/falloutttwsavegame.cpp | 48 +++++++++---------- src/games/ttw/src/falloutttwsavegame.h | 17 +++---- .../ttw/src/falloutttwscriptextender.cpp | 7 ++- src/games/ttw/src/falloutttwscriptextender.h | 5 +- 10 files changed, 79 insertions(+), 82 deletions(-) create mode 100644 src/games/ttw/.gitattributes diff --git a/src/games/ttw/.gitattributes b/src/games/ttw/.gitattributes new file mode 100644 index 00000000..f8697127 --- /dev/null +++ b/src/games/ttw/.gitattributes @@ -0,0 +1,7 @@ +# Set the default behavior, in case people don't have core.autocrlf set. +* text=auto + +# Explicitly declare text files you want to always be normalized and converted +# to native line endings on checkout. +*.cpp text eol=crlf +*.h text eol=crlf diff --git a/src/games/ttw/src/falloutttwbsainvalidation.cpp b/src/games/ttw/src/falloutttwbsainvalidation.cpp index 1b2b0e60..a2303603 100644 --- a/src/games/ttw/src/falloutttwbsainvalidation.cpp +++ b/src/games/ttw/src/falloutttwbsainvalidation.cpp @@ -1,9 +1,9 @@ #include "falloutttwbsainvalidation.h" -FalloutTTWBSAInvalidation::FalloutTTWBSAInvalidation(DataArchives *dataArchives, MOBase::IPluginGame const *game) - : GamebryoBSAInvalidation(dataArchives, "fallout.ini", game) -{ -} +FalloutTTWBSAInvalidation::FalloutTTWBSAInvalidation(DataArchives* dataArchives, + MOBase::IPluginGame const* game) + : GamebryoBSAInvalidation(dataArchives, "fallout.ini", game) +{} QString FalloutTTWBSAInvalidation::invalidationBSAName() const { diff --git a/src/games/ttw/src/falloutttwbsainvalidation.h b/src/games/ttw/src/falloutttwbsainvalidation.h index 57b01506..6511c852 100644 --- a/src/games/ttw/src/falloutttwbsainvalidation.h +++ b/src/games/ttw/src/falloutttwbsainvalidation.h @@ -1,23 +1,20 @@ #ifndef FALLOUTTTWBSAINVALIDATION_H #define FALLOUTTTWBSAINVALIDATION_H - -#include "gamebryobsainvalidation.h" #include "falloutttwdataarchives.h" +#include "gamebryobsainvalidation.h" #include class FalloutTTWBSAInvalidation : public GamebryoBSAInvalidation { public: - - FalloutTTWBSAInvalidation(DataArchives *dataArchives, MOBase::IPluginGame const *game); + FalloutTTWBSAInvalidation(DataArchives* dataArchives, + MOBase::IPluginGame const* game); private: - virtual QString invalidationBSAName() const override; virtual unsigned long bsaVersion() const override; - }; -#endif // FALLOUTTTWBSAINVALIDATION_H +#endif // FALLOUTTTWBSAINVALIDATION_H diff --git a/src/games/ttw/src/falloutttwdataarchives.cpp b/src/games/ttw/src/falloutttwdataarchives.cpp index 15a8a5ae..1008630f 100644 --- a/src/games/ttw/src/falloutttwdataarchives.cpp +++ b/src/games/ttw/src/falloutttwdataarchives.cpp @@ -1,35 +1,35 @@ #include "falloutttwdataarchives.h" #include -FalloutTTWDataArchives::FalloutTTWDataArchives(const QDir &myGamesDir) : - GamebryoDataArchives(myGamesDir) -{ -} +FalloutTTWDataArchives::FalloutTTWDataArchives(const QDir& myGamesDir) + : GamebryoDataArchives(myGamesDir) +{} QStringList FalloutTTWDataArchives::vanillaArchives() const { - return { "Fallout - Textures.bsa" - , "Fallout - Textures2.bsa" - , "Fallout - Meshes.bsa" - , "Fallout - Voices1.bsa" - , "Fallout - Sound.bsa" - , "Fallout - Misc.bsa" }; + 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 FalloutTTWDataArchives::archives(const MOBase::IProfile* profile) const { QStringList result; - QString iniFile = profile->localSettingsEnabled() ? QDir(profile->absolutePath()).absoluteFilePath("fallout.ini") : m_LocalGameDir.absoluteFilePath("fallout.ini"); + QString iniFile = profile->localSettingsEnabled() + ? QDir(profile->absolutePath()).absoluteFilePath("fallout.ini") + : m_LocalGameDir.absoluteFilePath("fallout.ini"); result.append(getArchivesFromKey(iniFile, "SArchiveList")); return result; } -void FalloutTTWDataArchives::writeArchiveList(MOBase::IProfile *profile, const QStringList &before) +void FalloutTTWDataArchives::writeArchiveList(MOBase::IProfile* profile, + const QStringList& before) { QString list = before.join(", "); - QString iniFile = profile->localSettingsEnabled() ? QDir(profile->absolutePath()).absoluteFilePath("fallout.ini") : m_LocalGameDir.absoluteFilePath("fallout.ini"); + QString iniFile = profile->localSettingsEnabled() + ? QDir(profile->absolutePath()).absoluteFilePath("fallout.ini") + : m_LocalGameDir.absoluteFilePath("fallout.ini"); setArchivesToKey(iniFile, "SArchiveList", list); } diff --git a/src/games/ttw/src/falloutttwdataarchives.h b/src/games/ttw/src/falloutttwdataarchives.h index 83e011f9..8cb8233e 100644 --- a/src/games/ttw/src/falloutttwdataarchives.h +++ b/src/games/ttw/src/falloutttwdataarchives.h @@ -1,25 +1,24 @@ #ifndef FALLOUTTTWDATAARCHIVES_H #define FALLOUTTTWDATAARCHIVES_H - -#include -#include +#include #include #include -#include +#include +#include class FalloutTTWDataArchives : public GamebryoDataArchives { public: - FalloutTTWDataArchives(const QDir &myGamesDir); + FalloutTTWDataArchives(const QDir& myGamesDir); public: virtual QStringList vanillaArchives() const override; - virtual QStringList archives(const MOBase::IProfile *profile) const override; + virtual QStringList archives(const MOBase::IProfile* profile) const override; private: - virtual void writeArchiveList(MOBase::IProfile *profile, const QStringList &before) override; - + virtual void writeArchiveList(MOBase::IProfile* profile, + const QStringList& before) override; }; -#endif // FALLOUTTTWDATAARCHIVES_H +#endif // FALLOUTTTWDATAARCHIVES_H diff --git a/src/games/ttw/src/falloutttwmoddatacontent.h b/src/games/ttw/src/falloutttwmoddatacontent.h index 4c85d899..c9ef2fbb 100644 --- a/src/games/ttw/src/falloutttwmoddatacontent.h +++ b/src/games/ttw/src/falloutttwmoddatacontent.h @@ -4,18 +4,19 @@ #include #include -class FalloutTTWModDataContent : public GamebryoModDataContent { +class FalloutTTWModDataContent : public GamebryoModDataContent +{ public: - /** * */ - FalloutTTWModDataContent(GameGamebryo const* gamePlugin) : GamebryoModDataContent(gamePlugin) { + FalloutTTWModDataContent(GameGamebryo const* gamePlugin) + : GamebryoModDataContent(gamePlugin) + { // Just need to disable some contents: - m_Enabled[CONTENT_MCM] = false; + m_Enabled[CONTENT_MCM] = false; m_Enabled[CONTENT_SKYPROC] = false; } - }; -#endif // FALLOUTTTW_MODDATACONTENT_H +#endif // FALLOUTTTW_MODDATACONTENT_H diff --git a/src/games/ttw/src/falloutttwsavegame.cpp b/src/games/ttw/src/falloutttwsavegame.cpp index 910dcc81..b1cf212b 100644 --- a/src/games/ttw/src/falloutttwsavegame.cpp +++ b/src/games/ttw/src/falloutttwsavegame.cpp @@ -2,34 +2,33 @@ #include "gamefalloutttw.h" -FalloutTTWSaveGame::FalloutTTWSaveGame(QString const &fileName, GameFalloutTTW const *game) : - GamebryoSaveGame(fileName, game) +FalloutTTWSaveGame::FalloutTTWSaveGame(QString const& fileName, + GameFalloutTTW const* game) + : GamebryoSaveGame(fileName, game) { FileWrapper file(getFilepath(), "FO3SAVEGAME"); unsigned long width, height; - fetchInformationFields(file, width, height, m_SaveNumber, m_PCName, m_PCLevel, m_PCLocation); - + fetchInformationFields(file, width, height, m_SaveNumber, m_PCName, m_PCLevel, + m_PCLocation); } -void FalloutTTWSaveGame::fetchInformationFields( - FileWrapper& file, - unsigned long& width, - unsigned long& height, - unsigned long& saveNumber, - QString& playerName, - unsigned short& playerLevel, - QString& playerLocation) const +void FalloutTTWSaveGame::fetchInformationFields(FileWrapper& file, unsigned long& width, + unsigned long& height, + unsigned long& saveNumber, + QString& playerName, + unsigned short& playerLevel, + QString& playerLocation) const { - file.skip(); //Save header size + file.skip(); // Save header size - file.skip(); //File version? - file.skip(); //Delimiter + file.skip(); // File version? + file.skip(); // 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 + // 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); @@ -49,7 +48,8 @@ void FalloutTTWSaveGame::fetchInformationFields( file.read(playerLocation); } -std::unique_ptr FalloutTTWSaveGame::fetchDataFields() const +std::unique_ptr +FalloutTTWSaveGame::fetchDataFields() const { FileWrapper file(getFilepath(), "FO3SAVEGAME"); @@ -61,8 +61,8 @@ std::unique_ptr FalloutTTWSaveGame::fetchDataField unsigned short dummyLevel; unsigned long dummySaveNumber; - fetchInformationFields(file, width, height, - dummySaveNumber, dummyName, dummyLevel, dummyLocation); + fetchInformationFields(file, width, height, dummySaveNumber, dummyName, dummyLevel, + dummyLocation); } QString playtime; @@ -70,7 +70,7 @@ std::unique_ptr FalloutTTWSaveGame::fetchDataField fields->Screenshot = file.readImage(width, height, 256); - file.skip(5); // unknown (1 byte), plugin size (4 bytes) + file.skip(5); // unknown (1 byte), plugin size (4 bytes) file.setPluginString(GamebryoSaveGame::StringType::TYPE_BSTRING); fields->Plugins = file.readPlugins(); diff --git a/src/games/ttw/src/falloutttwsavegame.h b/src/games/ttw/src/falloutttwsavegame.h index 0344eb23..8fbd1809 100644 --- a/src/games/ttw/src/falloutttwsavegame.h +++ b/src/games/ttw/src/falloutttwsavegame.h @@ -8,21 +8,16 @@ class GameFalloutTTW; class FalloutTTWSaveGame : public GamebryoSaveGame { public: - FalloutTTWSaveGame(QString const &fileName, GameFalloutTTW const *game); + FalloutTTWSaveGame(QString const& fileName, GameFalloutTTW const* game); protected: - // Fetch easy-to-access information. - void fetchInformationFields( - FileWrapper& wrapper, - unsigned long& width, - unsigned long& height, - unsigned long& saveNumber, - QString& playerName, - unsigned short& playerLevel, - QString& playerLocation) const; + void fetchInformationFields(FileWrapper& wrapper, unsigned long& width, + unsigned long& height, unsigned long& saveNumber, + QString& playerName, unsigned short& playerLevel, + QString& playerLocation) const; std::unique_ptr fetchDataFields() const override; }; -#endif // FALLOUTTTWSAVEGAME_H +#endif // FALLOUTTTWSAVEGAME_H diff --git a/src/games/ttw/src/falloutttwscriptextender.cpp b/src/games/ttw/src/falloutttwscriptextender.cpp index cd542e6e..ab9474e5 100644 --- a/src/games/ttw/src/falloutttwscriptextender.cpp +++ b/src/games/ttw/src/falloutttwscriptextender.cpp @@ -3,10 +3,9 @@ #include #include -FalloutTTWScriptExtender::FalloutTTWScriptExtender(GameGamebryo const *game) : - GamebryoScriptExtender(game) -{ -} +FalloutTTWScriptExtender::FalloutTTWScriptExtender(GameGamebryo const* game) + : GamebryoScriptExtender(game) +{} QString FalloutTTWScriptExtender::BinaryName() const { diff --git a/src/games/ttw/src/falloutttwscriptextender.h b/src/games/ttw/src/falloutttwscriptextender.h index cd91f1d5..d1e4c9a4 100644 --- a/src/games/ttw/src/falloutttwscriptextender.h +++ b/src/games/ttw/src/falloutttwscriptextender.h @@ -8,11 +8,10 @@ class GameGamebryo; class FalloutTTWScriptExtender : public GamebryoScriptExtender { public: - FalloutTTWScriptExtender(const GameGamebryo *game); + FalloutTTWScriptExtender(const GameGamebryo* game); virtual QString BinaryName() const override; virtual QString PluginPath() const override; - }; -#endif // FALLOUTTTWSCRIPTEXTENDER_H +#endif // FALLOUTTTWSCRIPTEXTENDER_H From 1e8d0614c3d0af99f3f25d5cf5246f409aaf7b48 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Mika=C3=ABl=20Capelle?= Date: Sun, 26 May 2024 11:17:53 +0200 Subject: [PATCH 1442/1544] [game_ttw] Ignore formatting revision. --- src/games/ttw/.git-blame-ignore-revs | 1 + 1 file changed, 1 insertion(+) create mode 100644 src/games/ttw/.git-blame-ignore-revs diff --git a/src/games/ttw/.git-blame-ignore-revs b/src/games/ttw/.git-blame-ignore-revs new file mode 100644 index 00000000..ef64f05f --- /dev/null +++ b/src/games/ttw/.git-blame-ignore-revs @@ -0,0 +1 @@ +f40a37e2704e7b9ec0376ec0f04dd6eff7f3950b From 2b604d1bb7ef04ff69d54a498a1743b42399fc46 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Mika=C3=ABl=20Capelle?= Date: Sun, 26 May 2024 11:19:57 +0200 Subject: [PATCH 1443/1544] [game_ttw] Add github action for build and formatting. --- src/games/ttw/.github/workflows/build.yml | 16 ++++++++++++++++ src/games/ttw/.github/workflows/linting.yml | 17 +++++++++++++++++ 2 files changed, 33 insertions(+) create mode 100644 src/games/ttw/.github/workflows/build.yml create mode 100644 src/games/ttw/.github/workflows/linting.yml diff --git a/src/games/ttw/.github/workflows/build.yml b/src/games/ttw/.github/workflows/build.yml new file mode 100644 index 00000000..8b607a18 --- /dev/null +++ b/src/games/ttw/.github/workflows/build.yml @@ -0,0 +1,16 @@ +name: Build TTW Plugin + +on: + push: + branches: master + pull_request: + types: [opened, synchronize, reopened] + +jobs: + build: + runs-on: windows-2022 + steps: + - name: Build TTW Plugin + uses: ModOrganizer2/build-with-mob-action@master + with: + mo2-dependencies: cmake_common uibase game_gamebryo diff --git a/src/games/ttw/.github/workflows/linting.yml b/src/games/ttw/.github/workflows/linting.yml new file mode 100644 index 00000000..45de0445 --- /dev/null +++ b/src/games/ttw/.github/workflows/linting.yml @@ -0,0 +1,17 @@ +name: Lint TTW Plugin + +on: + push: + pull_request: + types: [opened, synchronize, reopened] + +jobs: + lint: + runs-on: ubuntu-latest + steps: + - uses: actions/checkout@v3 + - name: Check format + uses: ModOrganizer2/check-formatting-action@master + with: + check-path: "." + exclude-regex: "third-party" From 5d935b8ddde5ce654b225a8047ef9d167be047b6 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Mika=C3=ABl=20Capelle?= Date: Sun, 26 May 2024 11:20:28 +0200 Subject: [PATCH 1444/1544] [game_ttw] Remove old build files. --- src/games/ttw/appveyor.yml | 40 ------- src/games/ttw/src/SConscript | 13 --- src/games/ttw/src/gameFalloutTTW.pro | 50 --------- src/games/ttw/src/game_ttw_en.ts | 158 --------------------------- 4 files changed, 261 deletions(-) delete mode 100644 src/games/ttw/appveyor.yml delete mode 100644 src/games/ttw/src/SConscript delete mode 100644 src/games/ttw/src/gameFalloutTTW.pro diff --git a/src/games/ttw/appveyor.yml b/src/games/ttw/appveyor.yml deleted file mode 100644 index 5b490bd8..00000000 --- a/src/games/ttw/appveyor.yml +++ /dev/null @@ -1,40 +0,0 @@ -version: 1.0.{build} -skip_branch_with_pr: true -image: Visual Studio 2019 -environment: - WEBHOOK_URL: - secure: gOKbXaZM9ImtMD5XrYITvdyZUW/az082G9OIN1EC1Vbg57wBaeLhi49uGjxPw5GVujHku6kxN6ab89zhbS5GVeluR76GM83IbKV4Sh7udXzoYZZdg6YudtYHzdhCgUeiedpswbuczTq9ceIkkfSEWZuh/lMAAVVwvcGsJAnoPFw= -build_script: -- pwsh: >- - $ErrorActionPreference = 'Stop' - - git clone --depth=1 --no-single-branch https://github.com/ModOrganizer2/modorganizer-umbrella.git c:\projects\modorganizer-umbrella - - New-Item -ItemType Directory -Path c:\projects\modorganizer-build - - cd c:\projects\modorganizer-umbrella - - ($env:APPVEYOR_PULL_REQUEST_HEAD_REPO_BRANCH -eq $null) ? ($branch = $env:APPVEYOR_REPO_BRANCH) : ($branch = $env:APPVEYOR_PULL_REQUEST_HEAD_REPO_BRANCH) - - git checkout $(git show-ref --verify --quiet refs/remotes/origin/${branch} || echo '-b') ${branch} - - C:\Python37-x64\python.exe unimake.py -d c:\projects\modorganizer-build -s Appveyor_Build=True ${env:APPVEYOR_PROJECT_NAME} - - if($LastExitCode -ne 0) { $host.SetShouldExit($LastExitCode ) } -artifacts: -- path: vsbuild\src\RelWithDebInfo\game_ttw.dll - name: game_ttw_dll -- path: vsbuild\src\RelWithDebInfo\game_ttw.pdb - name: game_ttw_pdb -- path: vsbuild\src\RelWithDebInfo\game_ttw.lib - name: game_ttw_lib -on_success: - - ps: Set-Location -Path $env:APPVEYOR_BUILD_FOLDER - - ps: Invoke-RestMethod https://raw.githubusercontent.com/DiscordHooks/appveyor-discord-webhook/master/send.ps1 -o send.ps1 - - ps: ./send.ps1 success $env:WEBHOOK_URL -on_failure: - - ps: Set-Location -Path $env:APPVEYOR_BUILD_FOLDER - - ps: Push-AppveyorArtifact ${env:APPVEYOR_BUILD_FOLDER}\stdout.log - - ps: Push-AppveyorArtifact ${env:APPVEYOR_BUILD_FOLDER}\stderr.log - - ps: Invoke-RestMethod https://raw.githubusercontent.com/DiscordHooks/appveyor-discord-webhook/master/send.ps1 -o send.ps1 - - ps: ./send.ps1 failure $env:WEBHOOK_URL \ No newline at end of file diff --git a/src/games/ttw/src/SConscript b/src/games/ttw/src/SConscript deleted file mode 100644 index d6c52cc5..00000000 --- a/src/games/ttw/src/SConscript +++ /dev/null @@ -1,13 +0,0 @@ -Import('qt_env') - -env = qt_env.Clone() - -env.AppendUnique(CPPDEFINES = [ 'GAMEFALLOUTTTW_LIBRARY' ]) - -env.RequiresGamebryo() - -lib = env.SharedLibrary('gameFalloutTTW', env.Glob('*.cpp')) -env.InstallModule(lib) - -res = env['QT_USED_MODULES'] -Return('res') diff --git a/src/games/ttw/src/gameFalloutTTW.pro b/src/games/ttw/src/gameFalloutTTW.pro deleted file mode 100644 index b1349547..00000000 --- a/src/games/ttw/src/gameFalloutTTW.pro +++ /dev/null @@ -1,50 +0,0 @@ -#------------------------------------------------- -# -# Project created by QtCreator 2014-11-15T15:36:33 -# -#------------------------------------------------- - - -TARGET = gameFalloutTTW -TEMPLATE = lib - -CONFIG += plugins -CONFIG += dll - -DEFINES += GAMEFALLOUTTTW_LIBRARY - -SOURCES += gamefalloutTTW.cpp \ - falloutttwbsainvalidation.cpp \ - falloutttwscriptextender.cpp \ - falloutttwdataarchives.cpp \ - falloutttwsavegame.cpp \ - falloutttwsavegameinfo.cpp - -HEADERS += gamefalloutttw.h \ - falloutttwbsainvalidation.h \ - falloutttwscriptextender.h \ - falloutttwdataarchives.h \ - falloutttwsavegame.h \ - falloutttwsavegameinfo.h - -CONFIG(debug, debug|release) { - LIBS += -L"$${OUT_PWD}/../gameGamebryo/debug" - PRE_TARGETDEPS += \ - $$OUT_PWD/../gameGamebryo/debug/gameGamebryo.lib -} else { - LIBS += -L"$${OUT_PWD}/../gameGamebryo/release" - PRE_TARGETDEPS += \ - $$OUT_PWD/../gameGamebryo/release/gameGamebryo.lib -} - -include(../plugin_template.pri) - -INCLUDEPATH += "$${BOOSTPATH}" "$${PWD}/../gamefeatures" "$${PWD}/../gamegamebryo" - -LIBS += -ladvapi32 -lole32 -lgameGamebryo - -OTHER_FILES += \ - gamefalloutttw.json\ - SConscript \ - CMakeLists.txt - diff --git a/src/games/ttw/src/game_ttw_en.ts b/src/games/ttw/src/game_ttw_en.ts index 5784cf81..e06609b2 100644 --- a/src/games/ttw/src/game_ttw_en.ts +++ b/src/games/ttw/src/game_ttw_en.ts @@ -13,165 +13,7 @@ Adds support for the game Fallout TTW - - - GamebryoModDataContent - - Plugins (ESP/ESM/ESL) - - - - - Optional Plugins - - - - - Interface - - - - - Meshes - - - - - Bethesda Archive - - - - - Scripts (Papyrus) - - - - - Script Extender Plugin - - - - - Script Extender Files - - - - - SkyProc Patcher - - - - - Sound or Music - - - - - Textures - - - - - MCM Configuration - - - - - INI Files - - - - - FaceGen Data - - - - - ModGroup Files - - - - - GamebryoSaveGameInfoWidget - - - Save # - - - - - Character - - - - - Level - - - - - Location - - - - - Date - - - - - Has Script Extender Data - - - - - Missing ESPs - - - - - - None - - - - - Missing ESLs - - - - - QObject - - - - Some of your plugins have invalid names! These plugins can not be loaded by the game. Please see mo_interface.log for a list of affected plugins and rename them. - - - - - %1, #%2, Level %3, %4 - - - - - failed to open %1 - - - - - wrong file format - expected %1 got %2 - - - - - failed to query registry path (preflight): %1 - - - - - failed to query registry path (read): %1 While not recommended by the TTW modding community, enables LOOT sorting From 9e7dc0d60c43084deefae4823e37897e007b73c6 Mon Sep 17 00:00:00 2001 From: Twinki Date: Sun, 2 Jun 2024 03:06:00 -0400 Subject: [PATCH 1445/1544] [game_falloutnv] Add `RaceMenuPresets` to possible data folders (#31) --- .../falloutnv/src/falloutnvmoddatachecker.h | 37 ++++++++++++++----- 1 file changed, 28 insertions(+), 9 deletions(-) diff --git a/src/games/falloutnv/src/falloutnvmoddatachecker.h b/src/games/falloutnv/src/falloutnvmoddatachecker.h index fa81d74b..02c5c7f9 100644 --- a/src/games/falloutnv/src/falloutnvmoddatachecker.h +++ b/src/games/falloutnv/src/falloutnvmoddatachecker.h @@ -11,15 +11,34 @@ public: 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"}; + 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 From 0c23c8e3d890736d4633f02e4032f230c0e86ad6 Mon Sep 17 00:00:00 2001 From: Twinki Date: Sun, 2 Jun 2024 03:06:18 -0400 Subject: [PATCH 1446/1544] [game_ttw] Add `RaceMenuPresets` to possible data folders (#38) --- src/games/ttw/src/falloutttwmoddatachecker.h | 37 +++++++++++++++----- 1 file changed, 28 insertions(+), 9 deletions(-) diff --git a/src/games/ttw/src/falloutttwmoddatachecker.h b/src/games/ttw/src/falloutttwmoddatachecker.h index 89365f2f..12ed8819 100644 --- a/src/games/ttw/src/falloutttwmoddatachecker.h +++ b/src/games/ttw/src/falloutttwmoddatachecker.h @@ -11,15 +11,34 @@ public: 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"}; + 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 From 33a219d9f9abb0388899cbf37c479fa7b052f6ae Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Mika=C3=ABl=20Capelle?= Date: Sun, 9 Jun 2024 12:30:30 +0200 Subject: [PATCH 1447/1544] Refactoring of game features for better management. (#54) --- src/gamebryo/gamebryobsainvalidation.cpp | 2 +- src/gamebryo/gamebryobsainvalidation.h | 8 +++--- src/gamebryo/gamebryodataarchives.h | 2 +- src/gamebryo/gamebryogameplugins.h | 2 +- src/gamebryo/gamebryolocalsavegames.h | 2 +- src/gamebryo/gamebryomoddatachecker.h | 2 +- src/gamebryo/gamebryomoddatacontent.cpp | 10 ++++---- src/gamebryo/gamebryomoddatacontent.h | 11 ++++++--- src/gamebryo/gamebryosavegame.cpp | 5 ++-- src/gamebryo/gamebryosavegame.h | 2 +- src/gamebryo/gamebryosavegameinfo.h | 2 +- src/gamebryo/gamebryoscriptextender.h | 2 +- src/gamebryo/gamebryounmanagedmods.h | 2 +- src/gamebryo/gamegamebryo.cpp | 11 +++++---- src/gamebryo/gamegamebryo.h | 31 +++++------------------- 15 files changed, 40 insertions(+), 54 deletions(-) diff --git a/src/gamebryo/gamebryobsainvalidation.cpp b/src/gamebryo/gamebryobsainvalidation.cpp index c1ba7e64..1b7144bd 100644 --- a/src/gamebryo/gamebryobsainvalidation.cpp +++ b/src/gamebryo/gamebryobsainvalidation.cpp @@ -12,7 +12,7 @@ #include -GamebryoBSAInvalidation::GamebryoBSAInvalidation(DataArchives* dataArchives, +GamebryoBSAInvalidation::GamebryoBSAInvalidation(MOBase::DataArchives* dataArchives, const QString& iniFilename, MOBase::IPluginGame const* game) : m_DataArchives(dataArchives), m_IniFileName(iniFilename), m_Game(game) diff --git a/src/gamebryo/gamebryobsainvalidation.h b/src/gamebryo/gamebryobsainvalidation.h index 33d81f2c..efd3d7b2 100644 --- a/src/gamebryo/gamebryobsainvalidation.h +++ b/src/gamebryo/gamebryobsainvalidation.h @@ -11,11 +11,11 @@ namespace MOBase class IPluginGame; } -class GamebryoBSAInvalidation : public BSAInvalidation +class GamebryoBSAInvalidation : public MOBase::BSAInvalidation { public: - GamebryoBSAInvalidation(DataArchives* dataArchives, const QString& iniFilename, - MOBase::IPluginGame const* game); + GamebryoBSAInvalidation(MOBase::DataArchives* dataArchives, + const QString& iniFilename, MOBase::IPluginGame const* game); virtual bool isInvalidationBSA(const QString& bsaName) override; virtual void deactivate(MOBase::IProfile* profile) override; @@ -28,7 +28,7 @@ private: bsaVersion() const = 0; // 0x67 for oblivion, 0x68 for everything else private: - DataArchives* m_DataArchives; + MOBase::DataArchives* m_DataArchives; QString m_IniFileName; MOBase::IPluginGame const* m_Game; }; diff --git a/src/gamebryo/gamebryodataarchives.h b/src/gamebryo/gamebryodataarchives.h index 93383f64..e119bc4f 100644 --- a/src/gamebryo/gamebryodataarchives.h +++ b/src/gamebryo/gamebryodataarchives.h @@ -4,7 +4,7 @@ #include "dataarchives.h" #include -class GamebryoDataArchives : public DataArchives +class GamebryoDataArchives : public MOBase::DataArchives { public: diff --git a/src/gamebryo/gamebryogameplugins.h b/src/gamebryo/gamebryogameplugins.h index 80d09057..43f12a96 100644 --- a/src/gamebryo/gamebryogameplugins.h +++ b/src/gamebryo/gamebryogameplugins.h @@ -6,7 +6,7 @@ #include #include -class GamebryoGamePlugins : public GamePlugins +class GamebryoGamePlugins : public MOBase::GamePlugins { public: GamebryoGamePlugins(MOBase::IOrganizer* organizer); diff --git a/src/gamebryo/gamebryolocalsavegames.h b/src/gamebryo/gamebryolocalsavegames.h index 7b1dd738..675d52ce 100644 --- a/src/gamebryo/gamebryolocalsavegames.h +++ b/src/gamebryo/gamebryolocalsavegames.h @@ -24,7 +24,7 @@ Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA #include #include -class GamebryoLocalSavegames : public LocalSavegames +class GamebryoLocalSavegames : public MOBase::LocalSavegames { public: diff --git a/src/gamebryo/gamebryomoddatachecker.h b/src/gamebryo/gamebryomoddatachecker.h index 9a648bdd..e0b07335 100644 --- a/src/gamebryo/gamebryomoddatachecker.h +++ b/src/gamebryo/gamebryomoddatachecker.h @@ -14,7 +14,7 @@ class GameGamebryo; * extensions that were used before the ModDataChecker feature was added. It is possible * to inherit the class to provide custom list of folders or filenames. */ -class GamebryoModDataChecker : public ModDataChecker +class GamebryoModDataChecker : public MOBase::ModDataChecker { public: /** diff --git a/src/gamebryo/gamebryomoddatacontent.cpp b/src/gamebryo/gamebryomoddatacontent.cpp index 85ded01d..85b66b06 100644 --- a/src/gamebryo/gamebryomoddatacontent.cpp +++ b/src/gamebryo/gamebryomoddatacontent.cpp @@ -1,11 +1,11 @@ #include "gamebryomoddatacontent.h" +#include #include -#include "gamegamebryo.h" - -GamebryoModDataContent::GamebryoModDataContent(GameGamebryo const* gamePlugin) - : m_GamePlugin(gamePlugin), m_Enabled(CONTENT_MODGROUP + 1, true) +GamebryoModDataContent::GamebryoModDataContent( + MOBase::IGameFeatures const* gameFeatures) + : m_GameFeatures(gameFeatures), m_Enabled(CONTENT_MODGROUP + 1, true) {} std::vector @@ -94,7 +94,7 @@ std::vector GamebryoModDataContent::getContentsFor( } } - ScriptExtender* extender = m_GamePlugin->feature(); + auto extender = m_GameFeatures->gameFeature(); if (extender != nullptr) { auto e = fileTree->findDirectory(extender->PluginPath()); if (e) { diff --git a/src/gamebryo/gamebryomoddatacontent.h b/src/gamebryo/gamebryomoddatacontent.h index 526bcde5..be023318 100644 --- a/src/gamebryo/gamebryomoddatacontent.h +++ b/src/gamebryo/gamebryomoddatacontent.h @@ -4,13 +4,16 @@ #include #include -class GameGamebryo; +namespace MOBase +{ +class IGameFeatures; +} /** * @brief ModDataContent for GameBryo games. * */ -class GamebryoModDataContent : public ModDataContent +class GamebryoModDataContent : public MOBase::ModDataContent { protected: /** @@ -45,7 +48,7 @@ public: /** * */ - GamebryoModDataContent(GameGamebryo const* gamePlugin); + GamebryoModDataContent(const MOBase::IGameFeatures* gameFeatures); /** * @return the list of all possible contents for the corresponding game. @@ -63,7 +66,7 @@ public: getContentsFor(std::shared_ptr fileTree) const override; protected: - GameGamebryo const* const m_GamePlugin; + MOBase::IGameFeatures const* const m_GameFeatures; // List of enabled contents: std::vector m_Enabled; diff --git a/src/gamebryo/gamebryosavegame.cpp b/src/gamebryo/gamebryosavegame.cpp index e6fe6be6..61750f44 100644 --- a/src/gamebryo/gamebryosavegame.cpp +++ b/src/gamebryo/gamebryosavegame.cpp @@ -18,6 +18,7 @@ #include #include "gamegamebryo.h" +#include "imoinfo.h" #define CHUNK 16384 @@ -58,8 +59,8 @@ QString GamebryoSaveGame::getSaveGroupIdentifier() const QStringList GamebryoSaveGame::allFiles() const { // This returns all valid files associated with this game - QStringList res = {m_FileName}; - ScriptExtender const* e = m_Game->feature(); + QStringList res = {m_FileName}; + auto e = m_Game->m_Organizer->gameFeatures()->gameFeature(); if (e != nullptr) { QFileInfo file(m_FileName); QFileInfo SEfile(file.absolutePath() + "/" + file.completeBaseName() + "." + diff --git a/src/gamebryo/gamebryosavegame.h b/src/gamebryo/gamebryosavegame.h index eebdd8f1..07d34621 100644 --- a/src/gamebryo/gamebryosavegame.h +++ b/src/gamebryo/gamebryosavegame.h @@ -18,7 +18,7 @@ struct _SYSTEMTIME; namespace MOBase { class IPluginGame; -} +} // namespace MOBase class GameGamebryo; diff --git a/src/gamebryo/gamebryosavegameinfo.h b/src/gamebryo/gamebryosavegameinfo.h index 0521cc7a..e2142930 100644 --- a/src/gamebryo/gamebryosavegameinfo.h +++ b/src/gamebryo/gamebryosavegameinfo.h @@ -5,7 +5,7 @@ class GameGamebryo; -class GamebryoSaveGameInfo : public SaveGameInfo +class GamebryoSaveGameInfo : public MOBase::SaveGameInfo { public: GamebryoSaveGameInfo(GameGamebryo const* game); diff --git a/src/gamebryo/gamebryoscriptextender.h b/src/gamebryo/gamebryoscriptextender.h index 10bad1e6..7ab4f1d2 100644 --- a/src/gamebryo/gamebryoscriptextender.h +++ b/src/gamebryo/gamebryoscriptextender.h @@ -5,7 +5,7 @@ class GameGamebryo; -class GamebryoScriptExtender : public ScriptExtender +class GamebryoScriptExtender : public MOBase::ScriptExtender { public: GamebryoScriptExtender(GameGamebryo const* game); diff --git a/src/gamebryo/gamebryounmanagedmods.h b/src/gamebryo/gamebryounmanagedmods.h index a9585b0d..38e2ba50 100644 --- a/src/gamebryo/gamebryounmanagedmods.h +++ b/src/gamebryo/gamebryounmanagedmods.h @@ -5,7 +5,7 @@ class GameGamebryo; -class GamebryoUnmangedMods : public UnmanagedMods +class GamebryoUnmangedMods : public MOBase::UnmanagedMods { public: GamebryoUnmangedMods(const GameGamebryo* game); diff --git a/src/gamebryo/gamegamebryo.cpp b/src/gamebryo/gamegamebryo.cpp index 0ad60004..82a188cc 100644 --- a/src/gamebryo/gamegamebryo.cpp +++ b/src/gamebryo/gamegamebryo.cpp @@ -254,11 +254,6 @@ QString GameGamebryo::myGamesPath() const "/Loot.exe"; } -std::map GameGamebryo::featureList() const -{ - return m_FeatureList; -} - QString GameGamebryo::localAppFolder() { QString result = getKnownFolderPath(FOLDERID_LocalAppData, false); @@ -474,3 +469,9 @@ QString GameGamebryo::parseSteamLocation(const QString& appid, } return ""; } + +void GameGamebryo::registerFeature(std::shared_ptr feature) +{ + // priority does not matter, this is a game plugin so will get lowest priority in MO2 + m_Organizer->gameFeatures()->registerFeature(this, feature, 0, true); +} diff --git a/src/gamebryo/gamegamebryo.h b/src/gamebryo/gamegamebryo.h index 306df84e..38df69f7 100644 --- a/src/gamebryo/gamegamebryo.h +++ b/src/gamebryo/gamegamebryo.h @@ -22,6 +22,7 @@ class UnmanagedMods; #include #include "gamebryosavegame.h" +#include "igamefeatures.h" class GameGamebryo : public MOBase::IPluginGame, public MOBase::IPluginFileMapper { @@ -132,37 +133,17 @@ protected: static QString parseSteamLocation(const QString& appid, const QString& directoryName); protected: - std::map featureList() const override; - - // These should be implemented by anything that uses gamebryo (I think) - //(and if they don't, it'll be a null pointer and won't look implemented, - // so that's fine too). - /* - std::shared_ptr m_ScriptExtender { nullptr }; - std::shared_ptr m_DataArchives { nullptr }; - std::shared_ptr m_BSAInvalidation { nullptr }; - std::shared_ptr m_SaveGameInfo { nullptr }; - std::shared_ptr m_LocalSavegames { nullptr }; - std::shared_ptr m_GamePlugins { nullptr }; - std::shared_ptr m_UnmanagedMods { nullptr };*/ - - template - void registerFeature(T* type) - { - auto index = std::type_index(typeid(T)); - if (m_FeatureList.find(index) != m_FeatureList.end()) { - delete std::any_cast(m_FeatureList[index]); - } - m_FeatureList[index] = type; - } + void registerFeature(std::shared_ptr feature); protected: + // to access organizer for game features, avoid having to pass it to all saves since + // we already pass the game + friend class GamebryoSaveGame; + QString m_GamePath; QString m_MyGamesPath; QString m_GameVariant; MOBase::IOrganizer* m_Organizer; - - std::map m_FeatureList; }; #endif // GAMEGAMEBRYO_H From 7f936cf9b11c472c66220a89e5e522cb492cf7fd Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Mika=C3=ABl=20Capelle?= Date: Sun, 9 Jun 2024 12:31:05 +0200 Subject: [PATCH 1448/1544] [game_starfield] Refactoring following uibase change for game features. (#20) --- src/games/starfield/src/game_starfield_en.ts | 20 ++++++------ src/games/starfield/src/gamestarfield.cpp | 31 +++++++++++-------- .../src/starfieldbsainvalidation.cpp | 2 +- .../starfield/src/starfieldbsainvalidation.h | 3 +- .../starfield/src/starfielddataarchives.cpp | 2 +- .../starfield/src/starfieldgameplugins.cpp | 2 +- .../starfield/src/starfieldmoddatacontent.h | 4 +-- 7 files changed, 35 insertions(+), 29 deletions(-) diff --git a/src/games/starfield/src/game_starfield_en.ts b/src/games/starfield/src/game_starfield_en.ts index baa0b381..4326b8ed 100644 --- a/src/games/starfield/src/game_starfield_en.ts +++ b/src/games/starfield/src/game_starfield_en.ts @@ -44,52 +44,52 @@ - + You have active ESP plugins in Starfield - + You have active ESL plugins in Starfield - + You have active overlay plugins - + sTestFile entries are present - + Plugins.txt Enabler missing - + <p>ESP plugins are not ideal for Starfield. In addition to being unable to sort them alongside ESM or master-flagged plugins, certain record references are always kept loaded by the game. This consumes unnecessary resources and limits the game's ability to load what it needs.</p><p>Ideally, plugins should be saved as ESM files upon release. It can also be released as an ESL plugin, however there are additional concerns with the way light plugins are currently handled and should only be used when absolutely certain about what you're doing.</p><p>Notably, xEdit does not currently support saving ESP files.</p><h4>Current ESPs:</h4><p>%1</p> - + <p>Light plugins work differently in Starfield. They use a different base form ID compared with standard plugin files.</p><p>What this means is that you can't just change a standard plugin to a light plugin at will, it can and will break any dependent plugin. If you do so, be absolutely certain no other plugins use that plugin as a master.</p><p>Notably, xEdit does not currently support saving or loading ESL files under these conditions.<p><h4>Current ESLs:</h4><p>%1</p> - + <p>Overlay-flagged plugins are not currently recommended. In theory, they should allow you to update existing records without utilizing additional load order slots. Unfortunately, it appears that the game still allocates the slots as if these were standard plugins. Therefore, at the moment there is no real use for this plugin flag.</p><p>Notably, xEdit does not currently support saving or loading overlay-flagged files under these conditions.</p><h4>Current Overlays:</h4><p>%1</p> - + <p>You have plugin managment enabled but you still have sTestFile settings in your StarfieldCustom.ini. These must be removed or the game will not read the plugins.txt file. Management is still disabled.</p> - + <p>You have plugin management turned on but do not have the Plugins.txt Enabler SFSE plugin installed. Plugin file management for Starfield will not work without this SFSE plugin.</p> diff --git a/src/games/starfield/src/gamestarfield.cpp b/src/games/starfield/src/gamestarfield.cpp index 218aa19e..b521587d 100644 --- a/src/games/starfield/src/gamestarfield.cpp +++ b/src/games/starfield/src/gamestarfield.cpp @@ -41,18 +41,19 @@ bool GameStarfield::init(IOrganizer* moInfo) return false; } - registerFeature(new StarfieldScriptExtender(this)); - registerFeature( - new StarfieldDataArchives(myGamesPath(), gameDirectory())); - registerFeature( - new GamebryoLocalSavegames(myGamesPath(), "StarfieldCustom.ini")); - registerFeature(new StarfieldModDataChecker(this)); - registerFeature(new StarfieldModDataContent(this)); - registerFeature(new GamebryoSaveGameInfo(this)); - registerFeature(new StarfieldGamePlugins(moInfo)); - registerFeature(new StarfieldUnmangedMods(this)); - registerFeature( - new StarfieldBSAInvalidation(feature(), this)); + auto dataArchives = + std::make_shared(myGamesPath(), gameDirectory()); + registerFeature(std::make_shared(this)); + registerFeature(dataArchives); + registerFeature( + std::make_shared(myGamesPath(), "StarfieldCustom.ini")); + registerFeature(std::make_shared(this)); + registerFeature( + std::make_shared(m_Organizer->gameFeatures())); + registerFeature(std::make_shared(this)); + registerFeature(std::make_shared(moInfo)); + registerFeature(std::make_shared(this)); + registerFeature(std::make_shared(dataArchives.get(), this)); return true; } @@ -92,7 +93,9 @@ QList GameStarfield::executables() const { return QList() << ExecutableInfo("SFSE", - findInGameFolder(feature()->loaderName())) + findInGameFolder(m_Organizer->gameFeatures() + ->gameFeature() + ->loaderName())) << ExecutableInfo("Starfield", findInGameFolder(binaryName())) << ExecutableInfo("LOOT", QFileInfo(getLootPath())) .withArgument("--game=\"Starfield\""); @@ -459,6 +462,7 @@ QString GameStarfield::shortDescription(unsigned int key) const case PROBLEM_PLUGINS_TXT: return tr("Plugins.txt Enabler missing"); } + return ""; } QString GameStarfield::fullDescription(unsigned int key) const @@ -515,6 +519,7 @@ QString GameStarfield::fullDescription(unsigned int key) const "will not work without this SFSE plugin.

"); } } + return ""; } bool GameStarfield::hasGuidedFix(unsigned int key) const diff --git a/src/games/starfield/src/starfieldbsainvalidation.cpp b/src/games/starfield/src/starfieldbsainvalidation.cpp index f86f7c55..f03c1a86 100644 --- a/src/games/starfield/src/starfieldbsainvalidation.cpp +++ b/src/games/starfield/src/starfieldbsainvalidation.cpp @@ -7,7 +7,7 @@ #include #include -StarfieldBSAInvalidation::StarfieldBSAInvalidation(DataArchives* dataArchives, +StarfieldBSAInvalidation::StarfieldBSAInvalidation(MOBase::DataArchives* dataArchives, MOBase::IPluginGame const* game) : GamebryoBSAInvalidation(dataArchives, "StarfieldCustom.ini", game) { diff --git a/src/games/starfield/src/starfieldbsainvalidation.h b/src/games/starfield/src/starfieldbsainvalidation.h index 36d3637a..40ec3558 100644 --- a/src/games/starfield/src/starfieldbsainvalidation.h +++ b/src/games/starfield/src/starfieldbsainvalidation.h @@ -16,7 +16,8 @@ class IPluginGame; class StarfieldBSAInvalidation : public GamebryoBSAInvalidation { public: - StarfieldBSAInvalidation(DataArchives* dataArchives, MOBase::IPluginGame const* game); + StarfieldBSAInvalidation(MOBase::DataArchives* dataArchives, + MOBase::IPluginGame const* game); virtual bool isInvalidationBSA(const QString& bsaName) override; virtual bool prepareProfile(MOBase::IProfile* profile) override; diff --git a/src/games/starfield/src/starfielddataarchives.cpp b/src/games/starfield/src/starfielddataarchives.cpp index fea785d8..175550a7 100644 --- a/src/games/starfield/src/starfielddataarchives.cpp +++ b/src/games/starfield/src/starfielddataarchives.cpp @@ -100,4 +100,4 @@ void StarfieldDataArchives::addArchive(MOBase::IProfile* profile, int index, void StarfieldDataArchives::removeArchive(MOBase::IProfile* profile, const QString& archiveName) -{} \ No newline at end of file +{} diff --git a/src/games/starfield/src/starfieldgameplugins.cpp b/src/games/starfield/src/starfieldgameplugins.cpp index b8907c79..995aa58f 100644 --- a/src/games/starfield/src/starfieldgameplugins.cpp +++ b/src/games/starfield/src/starfieldgameplugins.cpp @@ -27,4 +27,4 @@ QStringList StarfieldGamePlugins::readPluginList(MOBase::IPluginList* pluginList return CreationGamePlugins::readPluginList(pluginList); } return {}; -} \ No newline at end of file +} diff --git a/src/games/starfield/src/starfieldmoddatacontent.h b/src/games/starfield/src/starfieldmoddatacontent.h index 574e7baf..5d134569 100644 --- a/src/games/starfield/src/starfieldmoddatacontent.h +++ b/src/games/starfield/src/starfieldmoddatacontent.h @@ -15,8 +15,8 @@ protected: }; public: - StarfieldModDataContent(GameGamebryo const* gamePlugin) - : GamebryoModDataContent(gamePlugin) + StarfieldModDataContent(MOBase::IGameFeatures const* gameFeatures) + : GamebryoModDataContent(gameFeatures) { m_Enabled[CONTENT_SKYPROC] = false; m_Enabled[CONTENT_MATERIAL] = true; From d958a4cd67657cc557f3ff7ebe7256abf4b2a954 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Mika=C3=ABl=20Capelle?= Date: Sun, 9 Jun 2024 12:31:09 +0200 Subject: [PATCH 1449/1544] [game_skyrimvr] Refactoring following uibase change for game features. (#31) --- src/games/skyrimvr/src/gameskyrimvr.cpp | 18 +++++++++--------- .../skyrimvr/src/skyrimvrmoddatacontent.h | 2 +- 2 files changed, 10 insertions(+), 10 deletions(-) diff --git a/src/games/skyrimvr/src/gameskyrimvr.cpp b/src/games/skyrimvr/src/gameskyrimvr.cpp index a5a8cf3e..61f8a755 100644 --- a/src/games/skyrimvr/src/gameskyrimvr.cpp +++ b/src/games/skyrimvr/src/gameskyrimvr.cpp @@ -68,14 +68,14 @@ bool GameSkyrimVR::init(IOrganizer *moInfo) return false; } - registerFeature(new SkyrimVRScriptExtender(this)); - registerFeature(new SkyrimVRDataArchives(myGamesPath())); - registerFeature(new GamebryoLocalSavegames(myGamesPath(), "SkyrimVR.ini")); - registerFeature(new SkyrimVRModDataChecker(this)); - registerFeature(new GamebryoSaveGameInfo(this)); - registerFeature(new SkyrimVRModDataContent(this)); - registerFeature(new SkyrimVRGamePlugins(moInfo)); - registerFeature(new SkyrimVRUnmangedMods(this)); + registerFeature(std::make_shared(this)); + registerFeature(std::make_shared(myGamesPath())); + registerFeature(std::make_shared(myGamesPath(), "SkyrimVR.ini")); + 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; } @@ -90,7 +90,7 @@ QString GameSkyrimVR::gameName() const QList GameSkyrimVR::executables() const { return QList() - << ExecutableInfo("SKSE", findInGameFolder(feature()->loaderName())) + << ExecutableInfo("SKSE", findInGameFolder(m_Organizer->gameFeatures()->gameFeature()->loaderName())) << ExecutableInfo("Skyrim VR", findInGameFolder(binaryName())) << ExecutableInfo("Creation Kit", findInGameFolder("CreationKit.exe")) << ExecutableInfo("LOOT", QFileInfo(getLootPath())).withArgument("--game=\"Skyrim VR\"") diff --git a/src/games/skyrimvr/src/skyrimvrmoddatacontent.h b/src/games/skyrimvr/src/skyrimvrmoddatacontent.h index 940cdda9..3a5dc9f6 100644 --- a/src/games/skyrimvr/src/skyrimvrmoddatacontent.h +++ b/src/games/skyrimvr/src/skyrimvrmoddatacontent.h @@ -10,7 +10,7 @@ public: /** * */ - SkyrimVRModDataContent(GameGamebryo const* gamePlugin) : GamebryoModDataContent(gamePlugin) { + SkyrimVRModDataContent(MOBase::IGameFeatures const* gameFeatures) : GamebryoModDataContent(gameFeatures) { // Just need to disable some contents: m_Enabled[CONTENT_SKYPROC] = false; } From 6700f21c1471611deaea480c36543f9b3ea07262 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Mika=C3=ABl=20Capelle?= Date: Sun, 9 Jun 2024 12:31:18 +0200 Subject: [PATCH 1450/1544] [game_skyrimse] Refactoring of game features for better management. (#36) --- .../skyrimse/.github/workflows/build.yml | 2 +- .../skyrimse/.github/workflows/linting.yml | 6 ++-- src/games/skyrimse/src/game_skyrimse_en.ts | 4 +-- src/games/skyrimse/src/gameskyrimse.cpp | 31 +++++++++++-------- .../skyrimse/src/skyrimsemoddatacontent.h | 4 +-- 5 files changed, 26 insertions(+), 21 deletions(-) diff --git a/src/games/skyrimse/.github/workflows/build.yml b/src/games/skyrimse/.github/workflows/build.yml index 0e51ab70..9dd68e54 100644 --- a/src/games/skyrimse/.github/workflows/build.yml +++ b/src/games/skyrimse/.github/workflows/build.yml @@ -13,5 +13,5 @@ jobs: - name: Build Skyrim SE Plugin uses: ModOrganizer2/build-with-mob-action@master with: - mo2-third-parties: fmt gtest spdlog boost lz4 + mo2-third-parties: gtest spdlog boost lz4 mo2-dependencies: cmake_common uibase game_gamebryo diff --git a/src/games/skyrimse/.github/workflows/linting.yml b/src/games/skyrimse/.github/workflows/linting.yml index d1c601ca..ef918638 100644 --- a/src/games/skyrimse/.github/workflows/linting.yml +++ b/src/games/skyrimse/.github/workflows/linting.yml @@ -10,8 +10,8 @@ jobs: runs-on: ubuntu-latest steps: - uses: actions/checkout@v3 - - name: Run clang-format - uses: jidicula/clang-format-action@v4.11.0 + - name: Check format + uses: ModOrganizer2/check-formatting-action@master with: - clang-format-version: "15" check-path: "." + exclude-regex: "third-party" diff --git a/src/games/skyrimse/src/game_skyrimse_en.ts b/src/games/skyrimse/src/game_skyrimse_en.ts index 9a725db7..903011a3 100644 --- a/src/games/skyrimse/src/game_skyrimse_en.ts +++ b/src/games/skyrimse/src/game_skyrimse_en.ts @@ -4,12 +4,12 @@ GameSkyrimSE - + Skyrim Special Edition Support Plugin - + Adds support for the game Skyrim Special Edition. diff --git a/src/games/skyrimse/src/gameskyrimse.cpp b/src/games/skyrimse/src/gameskyrimse.cpp index 0a802de9..f911b94c 100644 --- a/src/games/skyrimse/src/gameskyrimse.cpp +++ b/src/games/skyrimse/src/gameskyrimse.cpp @@ -93,9 +93,10 @@ void GameSkyrimSE::setGamePath(const QString& path) m_GamePath = path; checkVariants(); m_MyGamesPath = determineMyGamesPath(gameDirectoryName()); - registerFeature(new SkyrimSEDataArchives(myGamesPath())); - registerFeature( - new GamebryoLocalSavegames(myGamesPath(), "Skyrimcustom.ini")); + + registerFeature(std::make_shared(myGamesPath())); + registerFeature( + std::make_shared(myGamesPath(), "Skyrimcustom.ini")); } QDir GameSkyrimSE::savesDirectory() const @@ -119,15 +120,17 @@ bool GameSkyrimSE::init(IOrganizer* moInfo) return false; } - registerFeature(new SkyrimSEScriptExtender(this)); - registerFeature(new SkyrimSEDataArchives(myGamesPath())); - registerFeature( - new GamebryoLocalSavegames(myGamesPath(), "Skyrimcustom.ini")); - registerFeature(new SkyrimSEModDataChecker(this)); - registerFeature(new SkyrimSEModDataContent(this)); - registerFeature(new GamebryoSaveGameInfo(this)); - registerFeature(new CreationGamePlugins(moInfo)); - registerFeature(new SkyrimSEUnmangedMods(this)); + registerFeature(std::make_shared(myGamesPath())); + registerFeature(std::make_shared(this)); + registerFeature(std::make_shared(myGamesPath())); + registerFeature( + std::make_shared(myGamesPath(), "Skyrimcustom.ini")); + registerFeature(std::make_shared(this)); + registerFeature( + std::make_shared(m_Organizer->gameFeatures())); + registerFeature(std::make_shared(this)); + registerFeature(std::make_shared(moInfo)); + registerFeature(std::make_shared(this)); return true; } @@ -151,7 +154,9 @@ QList GameSkyrimSE::executables() const { return QList() << ExecutableInfo("SKSE", - findInGameFolder(feature()->loaderName())) + findInGameFolder(m_Organizer->gameFeatures() + ->gameFeature() + ->loaderName())) << ExecutableInfo("Skyrim Special Edition", findInGameFolder(binaryName())) << ExecutableInfo("Skyrim Special Edition Launcher", findInGameFolder(getLauncherName())) diff --git a/src/games/skyrimse/src/skyrimsemoddatacontent.h b/src/games/skyrimse/src/skyrimsemoddatacontent.h index b7571720..b252e94a 100644 --- a/src/games/skyrimse/src/skyrimsemoddatacontent.h +++ b/src/games/skyrimse/src/skyrimsemoddatacontent.h @@ -10,8 +10,8 @@ public: /** * */ - SkyrimSEModDataContent(GameGamebryo const* gamePlugin) - : GamebryoModDataContent(gamePlugin) + SkyrimSEModDataContent(MOBase::IGameFeatures const* gameFeatures) + : GamebryoModDataContent(gameFeatures) { // Just need to disable some contents: m_Enabled[CONTENT_SKYPROC] = false; From 7e6cc4442408b4bff0eb724f45c8af5c8da259a2 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Mika=C3=ABl=20Capelle?= Date: Sun, 9 Jun 2024 12:31:22 +0200 Subject: [PATCH 1451/1544] [game_skyrim] Refactoring following uibase change for game features. (#28) --- src/games/skyrim/src/game_skyrim_en.ts | 165 +----------------- src/games/skyrim/src/gameskyrim.cpp | 23 +-- .../skyrim/src/skyrimbsainvalidation.cpp | 2 +- src/games/skyrim/src/skyrimbsainvalidation.h | 2 +- 4 files changed, 17 insertions(+), 175 deletions(-) diff --git a/src/games/skyrim/src/game_skyrim_en.ts b/src/games/skyrim/src/game_skyrim_en.ts index 315e0547..df224736 100644 --- a/src/games/skyrim/src/game_skyrim_en.ts +++ b/src/games/skyrim/src/game_skyrim_en.ts @@ -4,175 +4,14 @@ GameSkyrim - + Skyrim Support Plugin - + Adds support for the game Skyrim - - GamebryoModDataContent - - - Plugins (ESP/ESM/ESL) - - - - - Optional Plugins - - - - - Interface - - - - - Meshes - - - - - Bethesda Archive - - - - - Scripts (Papyrus) - - - - - Script Extender Plugin - - - - - Script Extender Files - - - - - SkyProc Patcher - - - - - Sound or Music - - - - - Textures - - - - - MCM Configuration - - - - - INI Files - - - - - FaceGen Data - - - - - ModGroup Files - - - - - GamebryoSaveGameInfoWidget - - - Save # - - - - - Character - - - - - Level - - - - - Location - - - - - Date - - - - - Has Script Extender Data - - - - - Missing ESPs - - - - - - None - - - - - Missing ESLs - - - - - QObject - - - - Some of your plugins have invalid names! These plugins can not be loaded by the game. Please see mo_interface.log for a list of affected plugins and rename them. - - - - - %1, #%2, Level %3, %4 - - - - - failed to open %1 - - - - - wrong file format - expected %1 got %2 - - - - - failed to query registry path (preflight): %1 - - - - - failed to query registry path (read): %1 - - - diff --git a/src/games/skyrim/src/gameskyrim.cpp b/src/games/skyrim/src/gameskyrim.cpp index 68babc3b..a2edc928 100644 --- a/src/games/skyrim/src/gameskyrim.cpp +++ b/src/games/skyrim/src/gameskyrim.cpp @@ -42,15 +42,18 @@ bool GameSkyrim::init(IOrganizer *moInfo) if (!GameGamebryo::init(moInfo)) { return false; } - registerFeature(new SkyrimScriptExtender(this)); - registerFeature(new SkyrimDataArchives(myGamesPath())); - registerFeature(new SkyrimBSAInvalidation(feature(), this)); - registerFeature(new GamebryoSaveGameInfo(this)); - registerFeature(new GamebryoLocalSavegames(myGamesPath(), "skyrim.ini")); - registerFeature(new SkyrimModDataChecker(this)); - registerFeature(new SkyrimModDataContent(this)); - registerFeature(new SkyrimGamePlugins(moInfo)); - registerFeature(new GamebryoUnmangedMods(this)); + + auto dataArchives = std::make_shared(myGamesPath()); + registerFeature(std::make_shared(this)); + registerFeature(dataArchives); + registerFeature(std::make_shared(dataArchives.get(), this)); + registerFeature(std::make_shared(this)); + registerFeature(std::make_shared(myGamesPath(), "skyrim.ini")); + registerFeature(std::make_shared(this)); + registerFeature(std::make_shared(m_Organizer->gameFeatures())); + registerFeature(std::make_shared(moInfo)); + registerFeature(std::make_shared(this)); + return true; } @@ -62,7 +65,7 @@ QString GameSkyrim::gameName() const QList GameSkyrim::executables() const { return QList() - << ExecutableInfo("SKSE", findInGameFolder(feature()->loaderName())) + << ExecutableInfo("SKSE", findInGameFolder(m_Organizer->gameFeatures()->gameFeature()->loaderName())) << ExecutableInfo("SBW", findInGameFolder("SBW.exe")) << ExecutableInfo("Skyrim", findInGameFolder(binaryName())) << ExecutableInfo("Skyrim Launcher", findInGameFolder(getLauncherName())) diff --git a/src/games/skyrim/src/skyrimbsainvalidation.cpp b/src/games/skyrim/src/skyrimbsainvalidation.cpp index adab711b..6f6a814c 100644 --- a/src/games/skyrim/src/skyrimbsainvalidation.cpp +++ b/src/games/skyrim/src/skyrimbsainvalidation.cpp @@ -1,6 +1,6 @@ #include "skyrimbsainvalidation.h" -SkyrimBSAInvalidation::SkyrimBSAInvalidation(DataArchives *dataArchives, MOBase::IPluginGame const *game) +SkyrimBSAInvalidation::SkyrimBSAInvalidation(MOBase::DataArchives *dataArchives, MOBase::IPluginGame const *game) : GamebryoBSAInvalidation(dataArchives, "skyrim.ini", game) { } diff --git a/src/games/skyrim/src/skyrimbsainvalidation.h b/src/games/skyrim/src/skyrimbsainvalidation.h index 0dbb5ff5..cf32964d 100644 --- a/src/games/skyrim/src/skyrimbsainvalidation.h +++ b/src/games/skyrim/src/skyrimbsainvalidation.h @@ -11,7 +11,7 @@ class SkyrimBSAInvalidation : public GamebryoBSAInvalidation { public: - SkyrimBSAInvalidation(DataArchives *dataArchives, MOBase::IPluginGame const *game); + SkyrimBSAInvalidation(MOBase::DataArchives *dataArchives, MOBase::IPluginGame const *game); private: From 7f8ea3f4252ce96ac430c682b89ea256b11ad842 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Mika=C3=ABl=20Capelle?= Date: Sun, 9 Jun 2024 12:31:26 +0200 Subject: [PATCH 1452/1544] [game_oblivion] Refactoring following uibase change for game features. (#23) --- src/games/oblivion/src/game_oblivion_en.ts | 165 +----------------- src/games/oblivion/src/gameoblivion.cpp | 20 ++- .../oblivion/src/oblivionbsainvalidation.cpp | 2 +- .../oblivion/src/oblivionbsainvalidation.h | 2 +- .../oblivion/src/oblivionmoddatachecker.cpp | 2 +- .../oblivion/src/oblivionmoddatacontent.h | 2 +- 6 files changed, 17 insertions(+), 176 deletions(-) diff --git a/src/games/oblivion/src/game_oblivion_en.ts b/src/games/oblivion/src/game_oblivion_en.ts index 1146a0bb..ad614a85 100644 --- a/src/games/oblivion/src/game_oblivion_en.ts +++ b/src/games/oblivion/src/game_oblivion_en.ts @@ -4,175 +4,14 @@ GameOblivion - + Oblivion Support Plugin - + Adds support for the game Oblivion - - GamebryoModDataContent - - - Plugins (ESP/ESM/ESL) - - - - - Optional Plugins - - - - - Interface - - - - - Meshes - - - - - Bethesda Archive - - - - - Scripts (Papyrus) - - - - - Script Extender Plugin - - - - - Script Extender Files - - - - - SkyProc Patcher - - - - - Sound or Music - - - - - Textures - - - - - MCM Configuration - - - - - INI Files - - - - - FaceGen Data - - - - - ModGroup Files - - - - - GamebryoSaveGameInfoWidget - - - Save # - - - - - Character - - - - - Level - - - - - Location - - - - - Date - - - - - Has Script Extender Data - - - - - Missing ESPs - - - - - - None - - - - - Missing ESLs - - - - - QObject - - - - Some of your plugins have invalid names! These plugins can not be loaded by the game. Please see mo_interface.log for a list of affected plugins and rename them. - - - - - %1, #%2, Level %3, %4 - - - - - failed to open %1 - - - - - wrong file format - expected %1 got %2 - - - - - failed to query registry path (preflight): %1 - - - - - failed to query registry path (read): %1 - - - diff --git a/src/games/oblivion/src/gameoblivion.cpp b/src/games/oblivion/src/gameoblivion.cpp index 2642e212..6d8a1e9f 100644 --- a/src/games/oblivion/src/gameoblivion.cpp +++ b/src/games/oblivion/src/gameoblivion.cpp @@ -31,15 +31,17 @@ bool GameOblivion::init(IOrganizer *moInfo) if (!GameGamebryo::init(moInfo)) { return false; } - registerFeature(new OblivionScriptExtender(this)); - registerFeature(new OblivionDataArchives(myGamesPath())); - registerFeature(new OblivionBSAInvalidation(feature(), this)); - registerFeature(new GamebryoSaveGameInfo(this)); - registerFeature(new GamebryoLocalSavegames(myGamesPath(), "oblivion.ini")); - registerFeature(new OblivionModDataChecker(this)); - registerFeature(new OblivionModDataContent(this)); - registerFeature(new GamebryoGamePlugins(moInfo)); - registerFeature(new GamebryoUnmangedMods(this)); + + auto dataArchives = std::make_shared(myGamesPath()); + registerFeature(std::make_shared(this)); + registerFeature(dataArchives); + registerFeature(std::make_shared(dataArchives.get(), this)); + registerFeature(std::make_shared(this)); + registerFeature(std::make_shared(myGamesPath(), "oblivion.ini")); + registerFeature(std::make_shared(this)); + registerFeature(std::make_shared(m_Organizer->gameFeatures())); + registerFeature(std::make_shared(moInfo)); + registerFeature(std::make_shared(this)); return true; } diff --git a/src/games/oblivion/src/oblivionbsainvalidation.cpp b/src/games/oblivion/src/oblivionbsainvalidation.cpp index fb275a2d..8000d08b 100644 --- a/src/games/oblivion/src/oblivionbsainvalidation.cpp +++ b/src/games/oblivion/src/oblivionbsainvalidation.cpp @@ -1,7 +1,7 @@ #include "oblivionbsainvalidation.h" -OblivionBSAInvalidation::OblivionBSAInvalidation(DataArchives *dataArchives, MOBase::IPluginGame const *game) +OblivionBSAInvalidation::OblivionBSAInvalidation(MOBase::DataArchives *dataArchives, MOBase::IPluginGame const *game) : GamebryoBSAInvalidation(dataArchives, "oblivion.ini", game) { } diff --git a/src/games/oblivion/src/oblivionbsainvalidation.h b/src/games/oblivion/src/oblivionbsainvalidation.h index 96a6fa8e..91bd4d10 100644 --- a/src/games/oblivion/src/oblivionbsainvalidation.h +++ b/src/games/oblivion/src/oblivionbsainvalidation.h @@ -11,7 +11,7 @@ class OblivionBSAInvalidation : public GamebryoBSAInvalidation { public: - OblivionBSAInvalidation(DataArchives *dataArchives, MOBase::IPluginGame const *game); + OblivionBSAInvalidation(MOBase::DataArchives *dataArchives, MOBase::IPluginGame const *game); private: diff --git a/src/games/oblivion/src/oblivionmoddatachecker.cpp b/src/games/oblivion/src/oblivionmoddatachecker.cpp index 0cc3546c..58c4870f 100644 --- a/src/games/oblivion/src/oblivionmoddatachecker.cpp +++ b/src/games/oblivion/src/oblivionmoddatachecker.cpp @@ -1,6 +1,6 @@ #include "oblivionmoddatachecker.h" -ModDataChecker::CheckReturn OblivionModDataChecker::dataLooksValid( +MOBase::ModDataChecker::CheckReturn OblivionModDataChecker::dataLooksValid( std::shared_ptr fileTree) const { // Check with Gamebryo stuff: diff --git a/src/games/oblivion/src/oblivionmoddatacontent.h b/src/games/oblivion/src/oblivionmoddatacontent.h index 2e79a87f..75f22bf0 100644 --- a/src/games/oblivion/src/oblivionmoddatacontent.h +++ b/src/games/oblivion/src/oblivionmoddatacontent.h @@ -10,7 +10,7 @@ public: /** * */ - OblivionModDataContent(GameGamebryo const* gamePlugin) : GamebryoModDataContent(gamePlugin) { + OblivionModDataContent(const MOBase::IGameFeatures* gameFeatures) : GamebryoModDataContent(gameFeatures) { // Just need to disable some contents: m_Enabled[CONTENT_MCM] = false; m_Enabled[CONTENT_SKYPROC] = false; From e0ff093cee71fb69e4972a196c6e39f145ed4b7e Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Mika=C3=ABl=20Capelle?= Date: Sun, 9 Jun 2024 12:31:29 +0200 Subject: [PATCH 1453/1544] [game_nehrim] Refactoring following uibase change for game features. (#7) --- src/games/nehrim/src/game_nehrim_en.ts | 4 ++-- src/games/nehrim/src/gamenehrim.cpp | 23 ++++++++++--------- .../nehrim/src/nehrimbsainvalidation.cpp | 2 +- src/games/nehrim/src/nehrimbsainvalidation.h | 3 ++- src/games/nehrim/src/nehrimmoddatachecker.cpp | 2 +- src/games/nehrim/src/nehrimmoddatacontent.h | 4 ++-- 6 files changed, 20 insertions(+), 18 deletions(-) diff --git a/src/games/nehrim/src/game_nehrim_en.ts b/src/games/nehrim/src/game_nehrim_en.ts index 9b8f44c7..54b8d5a5 100644 --- a/src/games/nehrim/src/game_nehrim_en.ts +++ b/src/games/nehrim/src/game_nehrim_en.ts @@ -4,12 +4,12 @@ GameNehrim - + Nehrim Support Plugin - + Adds support for the game Nehrim diff --git a/src/games/nehrim/src/gamenehrim.cpp b/src/games/nehrim/src/gamenehrim.cpp index 44d650fe..595670fb 100644 --- a/src/games/nehrim/src/gamenehrim.cpp +++ b/src/games/nehrim/src/gamenehrim.cpp @@ -29,17 +29,18 @@ bool GameNehrim::init(IOrganizer* moInfo) if (!GameGamebryo::init(moInfo)) { return false; } - registerFeature(new NehrimScriptExtender(this)); - registerFeature(new NehrimDataArchives(myGamesPath())); - registerFeature( - new NehrimBSAInvalidation(feature(), this)); - registerFeature(new GamebryoSaveGameInfo(this)); - registerFeature( - new GamebryoLocalSavegames(myGamesPath(), "oblivion.ini")); - registerFeature(new NehrimModDataChecker(this)); - registerFeature(new NehrimModDataContent(this)); - registerFeature(new GamebryoGamePlugins(moInfo)); - registerFeature(new GamebryoUnmangedMods(this)); + + auto dataArchives = std::make_shared(myGamesPath()); + registerFeature(std::make_shared(this)); + registerFeature(dataArchives); + registerFeature(std::make_shared(dataArchives.get(), this)); + registerFeature(std::make_shared(this)); + registerFeature( + std::make_shared(myGamesPath(), "oblivion.ini")); + registerFeature(std::make_shared(this)); + registerFeature(std::make_shared(m_Organizer->gameFeatures())); + registerFeature(std::make_shared(moInfo)); + registerFeature(std::make_shared(this)); return true; } diff --git a/src/games/nehrim/src/nehrimbsainvalidation.cpp b/src/games/nehrim/src/nehrimbsainvalidation.cpp index 7830da09..ac89d546 100644 --- a/src/games/nehrim/src/nehrimbsainvalidation.cpp +++ b/src/games/nehrim/src/nehrimbsainvalidation.cpp @@ -1,6 +1,6 @@ #include "nehrimbsainvalidation.h" -NehrimBSAInvalidation::NehrimBSAInvalidation(DataArchives* dataArchives, +NehrimBSAInvalidation::NehrimBSAInvalidation(MOBase::DataArchives* dataArchives, MOBase::IPluginGame const* game) : GamebryoBSAInvalidation(dataArchives, "oblivion.ini", game) {} diff --git a/src/games/nehrim/src/nehrimbsainvalidation.h b/src/games/nehrim/src/nehrimbsainvalidation.h index 51fcd9ae..3a2e2b3b 100644 --- a/src/games/nehrim/src/nehrimbsainvalidation.h +++ b/src/games/nehrim/src/nehrimbsainvalidation.h @@ -9,7 +9,8 @@ class NehrimBSAInvalidation : public GamebryoBSAInvalidation { public: - NehrimBSAInvalidation(DataArchives* dataArchives, MOBase::IPluginGame const* game); + NehrimBSAInvalidation(MOBase::DataArchives* dataArchives, + MOBase::IPluginGame const* game); private: virtual QString invalidationBSAName() const override; diff --git a/src/games/nehrim/src/nehrimmoddatachecker.cpp b/src/games/nehrim/src/nehrimmoddatachecker.cpp index 6ca61214..3ec4eb09 100644 --- a/src/games/nehrim/src/nehrimmoddatachecker.cpp +++ b/src/games/nehrim/src/nehrimmoddatachecker.cpp @@ -1,6 +1,6 @@ #include "nehrimmoddatachecker.h" -ModDataChecker::CheckReturn NehrimModDataChecker::dataLooksValid( +MOBase::ModDataChecker::CheckReturn NehrimModDataChecker::dataLooksValid( std::shared_ptr fileTree) const { // Check with Gamebryo stuff: diff --git a/src/games/nehrim/src/nehrimmoddatacontent.h b/src/games/nehrim/src/nehrimmoddatacontent.h index 02391dfe..c640377c 100644 --- a/src/games/nehrim/src/nehrimmoddatacontent.h +++ b/src/games/nehrim/src/nehrimmoddatacontent.h @@ -10,8 +10,8 @@ public: /** * */ - NehrimModDataContent(GameGamebryo const* gamePlugin) - : GamebryoModDataContent(gamePlugin) + NehrimModDataContent(const MOBase::IGameFeatures* gameFeatures) + : GamebryoModDataContent(gameFeatures) { // Just need to disable some contents: m_Enabled[CONTENT_MCM] = false; From c4f9135347a72287db8164a577ca60493b6572ae Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Mika=C3=ABl=20Capelle?= Date: Sun, 9 Jun 2024 12:31:37 +0200 Subject: [PATCH 1454/1544] [game_morrowind] Refactoring of game features for better management. (#30) * Refactoring following uibase change for game features. * Do not redefine m_Organizer in GameMorrowind. --- src/games/morrowind/src/game_morrowind_en.ts | 4 ++-- src/games/morrowind/src/gamemorrowind.cpp | 20 ++++++++++--------- src/games/morrowind/src/gamemorrowind.h | 4 ---- .../src/morrowindbsainvalidation.cpp | 2 +- .../morrowind/src/morrowindbsainvalidation.h | 2 +- .../morrowind/src/morrowindlocalsavegames.h | 2 +- .../morrowind/src/morrowindmoddatacontent.h | 2 +- 7 files changed, 17 insertions(+), 19 deletions(-) diff --git a/src/games/morrowind/src/game_morrowind_en.ts b/src/games/morrowind/src/game_morrowind_en.ts index 77dee4aa..65bb4f28 100644 --- a/src/games/morrowind/src/game_morrowind_en.ts +++ b/src/games/morrowind/src/game_morrowind_en.ts @@ -4,12 +4,12 @@ GameMorrowind - + Morrowind Support Plugin - + Adds support for the game Morrowind. Splash by %1 diff --git a/src/games/morrowind/src/gamemorrowind.cpp b/src/games/morrowind/src/gamemorrowind.cpp index 87efab12..51f0eaa8 100644 --- a/src/games/morrowind/src/gamemorrowind.cpp +++ b/src/games/morrowind/src/gamemorrowind.cpp @@ -41,15 +41,17 @@ bool GameMorrowind::init(IOrganizer *moInfo) if (!GameGamebryo::init(moInfo)) { return false; } - registerFeature(new MorrowindDataArchives(this)); - registerFeature(new MorrowindBSAInvalidation(feature(), this)); - registerFeature(new MorrowindSaveGameInfo(this)); - registerFeature(new MorrowindLocalSavegames(this)); - registerFeature(new MorrowindModDataChecker(this)); - registerFeature(new MorrowindModDataContent(this)); - registerFeature(new MorrowindGamePlugins(moInfo)); - registerFeature(new GamebryoUnmangedMods(this)); - m_Organizer = moInfo; + + auto dataArchives = std::make_shared(this); + registerFeature(dataArchives); + registerFeature(std::make_shared(dataArchives.get(), this)); + registerFeature(std::make_shared(this)); + 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; } diff --git a/src/games/morrowind/src/gamemorrowind.h b/src/games/morrowind/src/gamemorrowind.h index b98d73b8..ece03a59 100644 --- a/src/games/morrowind/src/gamemorrowind.h +++ b/src/games/morrowind/src/gamemorrowind.h @@ -58,10 +58,6 @@ protected: virtual QString savegameExtension() const override; virtual QString savegameSEExtension() const override; virtual std::shared_ptr makeSaveGame(QString filepath) const override; - -private: - - MOBase::IOrganizer *m_Organizer; }; diff --git a/src/games/morrowind/src/morrowindbsainvalidation.cpp b/src/games/morrowind/src/morrowindbsainvalidation.cpp index bf4c3542..21590dbc 100644 --- a/src/games/morrowind/src/morrowindbsainvalidation.cpp +++ b/src/games/morrowind/src/morrowindbsainvalidation.cpp @@ -1,6 +1,6 @@ #include "morrowindbsainvalidation.h" -MorrowindBSAInvalidation::MorrowindBSAInvalidation(DataArchives *dataArchives, MOBase::IPluginGame const *game) +MorrowindBSAInvalidation::MorrowindBSAInvalidation(MOBase::DataArchives *dataArchives, MOBase::IPluginGame const *game) : GamebryoBSAInvalidation(dataArchives, "morrowind.ini", game) { } diff --git a/src/games/morrowind/src/morrowindbsainvalidation.h b/src/games/morrowind/src/morrowindbsainvalidation.h index d551c1d5..020d4ef0 100644 --- a/src/games/morrowind/src/morrowindbsainvalidation.h +++ b/src/games/morrowind/src/morrowindbsainvalidation.h @@ -11,7 +11,7 @@ class MorrowindBSAInvalidation : public GamebryoBSAInvalidation { public: - MorrowindBSAInvalidation(DataArchives *dataArchives, MOBase::IPluginGame const *game); + MorrowindBSAInvalidation(MOBase::DataArchives *dataArchives, MOBase::IPluginGame const *game); private: diff --git a/src/games/morrowind/src/morrowindlocalsavegames.h b/src/games/morrowind/src/morrowindlocalsavegames.h index b70f212c..a91114e7 100644 --- a/src/games/morrowind/src/morrowindlocalsavegames.h +++ b/src/games/morrowind/src/morrowindlocalsavegames.h @@ -27,7 +27,7 @@ Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA #include #include "iplugingame.h" -class MorrowindLocalSavegames : public LocalSavegames +class MorrowindLocalSavegames : public MOBase::LocalSavegames { public: diff --git a/src/games/morrowind/src/morrowindmoddatacontent.h b/src/games/morrowind/src/morrowindmoddatacontent.h index f52ce0a1..42c81b4c 100644 --- a/src/games/morrowind/src/morrowindmoddatacontent.h +++ b/src/games/morrowind/src/morrowindmoddatacontent.h @@ -10,7 +10,7 @@ public: /** * */ - MorrowindModDataContent(GameGamebryo const* gamePlugin) : GamebryoModDataContent(gamePlugin) { + MorrowindModDataContent(MOBase::IGameFeatures const* gameFeatures) : GamebryoModDataContent(gameFeatures) { // Just need to disable some contents: m_Enabled[CONTENT_MCM] = false; m_Enabled[CONTENT_SKYPROC] = false; From e7e473de6d97eecfab7d2534ecbda6f6f9d2aa4e Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Mika=C3=ABl=20Capelle?= Date: Sun, 9 Jun 2024 12:31:42 +0200 Subject: [PATCH 1455/1544] [game_falloutnv] Refactoring following uibase change for game features. (#32) --- .../src/falloutnvbsainvalidation.cpp | 2 +- .../falloutnv/src/falloutnvbsainvalidation.h | 3 +- .../falloutnv/src/falloutnvdataarchives.cpp | 2 +- .../falloutnv/src/falloutnvmoddatacontent.h | 4 +- src/games/falloutnv/src/game_falloutNV_en.ts | 6 +-- src/games/falloutnv/src/gamefalloutnv.cpp | 40 +++++++++++-------- 6 files changed, 32 insertions(+), 25 deletions(-) diff --git a/src/games/falloutnv/src/falloutnvbsainvalidation.cpp b/src/games/falloutnv/src/falloutnvbsainvalidation.cpp index 5436957c..d66591f3 100644 --- a/src/games/falloutnv/src/falloutnvbsainvalidation.cpp +++ b/src/games/falloutnv/src/falloutnvbsainvalidation.cpp @@ -1,6 +1,6 @@ #include "falloutnvbsainvalidation.h" -FalloutNVBSAInvalidation::FalloutNVBSAInvalidation(DataArchives* dataArchives, +FalloutNVBSAInvalidation::FalloutNVBSAInvalidation(MOBase::DataArchives* dataArchives, MOBase::IPluginGame const* game) : GamebryoBSAInvalidation(dataArchives, "fallout.ini", game) {} diff --git a/src/games/falloutnv/src/falloutnvbsainvalidation.h b/src/games/falloutnv/src/falloutnvbsainvalidation.h index e0ede071..2301acfe 100644 --- a/src/games/falloutnv/src/falloutnvbsainvalidation.h +++ b/src/games/falloutnv/src/falloutnvbsainvalidation.h @@ -9,7 +9,8 @@ class FalloutNVBSAInvalidation : public GamebryoBSAInvalidation { public: - FalloutNVBSAInvalidation(DataArchives* dataArchives, MOBase::IPluginGame const* game); + FalloutNVBSAInvalidation(MOBase::DataArchives* dataArchives, + MOBase::IPluginGame const* game); private: virtual QString invalidationBSAName() const override; diff --git a/src/games/falloutnv/src/falloutnvdataarchives.cpp b/src/games/falloutnv/src/falloutnvdataarchives.cpp index d0cf873f..b9f83596 100644 --- a/src/games/falloutnv/src/falloutnvdataarchives.cpp +++ b/src/games/falloutnv/src/falloutnvdataarchives.cpp @@ -33,4 +33,4 @@ void FalloutNVDataArchives::writeArchiveList(MOBase::IProfile* profile, ? QDir(profile->absolutePath()).absoluteFilePath("fallout.ini") : m_LocalGameDir.absoluteFilePath("fallout.ini"); setArchivesToKey(iniFile, "SArchiveList", list); -} \ No newline at end of file +} diff --git a/src/games/falloutnv/src/falloutnvmoddatacontent.h b/src/games/falloutnv/src/falloutnvmoddatacontent.h index 44a2a258..4effd97d 100644 --- a/src/games/falloutnv/src/falloutnvmoddatacontent.h +++ b/src/games/falloutnv/src/falloutnvmoddatacontent.h @@ -10,8 +10,8 @@ public: /** * */ - FalloutNVModDataContent(GameGamebryo const* gamePlugin) - : GamebryoModDataContent(gamePlugin) + FalloutNVModDataContent(MOBase::IGameFeatures const* gameFeatures) + : GamebryoModDataContent(gameFeatures) { // Just need to disable some contents: m_Enabled[CONTENT_MCM] = false; diff --git a/src/games/falloutnv/src/game_falloutNV_en.ts b/src/games/falloutnv/src/game_falloutNV_en.ts index 589af613..00dc6987 100644 --- a/src/games/falloutnv/src/game_falloutNV_en.ts +++ b/src/games/falloutnv/src/game_falloutNV_en.ts @@ -4,17 +4,17 @@ GameFalloutNV - + Fallout NV Support Plugin - + Adds support for the game Fallout New Vegas - + While not recommended by the FNV modding community, enables LOOT sorting diff --git a/src/games/falloutnv/src/gamefalloutnv.cpp b/src/games/falloutnv/src/gamefalloutnv.cpp index e5b64b82..9abba544 100644 --- a/src/games/falloutnv/src/gamefalloutnv.cpp +++ b/src/games/falloutnv/src/gamefalloutnv.cpp @@ -34,17 +34,20 @@ bool GameFalloutNV::init(IOrganizer* moInfo) if (!GameGamebryo::init(moInfo)) { return false; } - registerFeature(new FalloutNVScriptExtender(this)); - registerFeature(new FalloutNVDataArchives(myGamesPath())); - registerFeature( - new FalloutNVBSAInvalidation(feature(), this)); - registerFeature(new GamebryoSaveGameInfo(this)); - registerFeature( - new GamebryoLocalSavegames(myGamesPath(), "fallout.ini")); - registerFeature(new FalloutNVModDataChecker(this)); - registerFeature(new FalloutNVModDataContent(this)); - registerFeature(new GamebryoGamePlugins(moInfo)); - registerFeature(new GamebryoUnmangedMods(this)); + + auto dataArchives = std::make_shared(myGamesPath()); + registerFeature(std::make_shared(this)); + registerFeature(dataArchives); + registerFeature(std::make_shared(dataArchives.get(), this)); + registerFeature(std::make_shared(this)); + registerFeature( + std::make_shared(myGamesPath(), "fallout.ini")); + registerFeature(std::make_shared(this)); + registerFeature( + std::make_shared(m_Organizer->gameFeatures())); + registerFeature(std::make_shared(moInfo)); + registerFeature(std::make_shared(this)); + return true; } @@ -101,11 +104,12 @@ void GameFalloutNV::setGamePath(const QString& path) m_GamePath = path; checkVariants(); m_MyGamesPath = determineMyGamesPath(gameDirectoryName()); - registerFeature(new FalloutNVDataArchives(myGamesPath())); - registerFeature( - new FalloutNVBSAInvalidation(feature(), this)); - registerFeature( - new GamebryoLocalSavegames(myGamesPath(), "fallout.ini")); + + auto dataArchives = std::make_shared(myGamesPath()); + registerFeature(dataArchives); + registerFeature(std::make_shared(dataArchives.get(), this)); + registerFeature( + std::make_shared(myGamesPath(), "fallout.ini")); } QDir GameFalloutNV::savesDirectory() const @@ -157,7 +161,9 @@ QList GameFalloutNV::executables() const .withArgument("--game=\"FalloutNV\""); if (selectedVariant() != "Epic Games") { extraExecutables.prepend(ExecutableInfo( - "NVSE", findInGameFolder(feature()->loaderName()))); + "NVSE", findInGameFolder(m_Organizer->gameFeatures() + ->gameFeature() + ->loaderName()))); } else { game.withArgument("-EpicPortal"); launcher.withArgument("-EpicPortal"); From e7edb367a2ead14cb3ccac63a1f3297541812310 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Mika=C3=ABl=20Capelle?= Date: Sun, 9 Jun 2024 12:31:46 +0200 Subject: [PATCH 1456/1544] [game_fallout76] Refactoring following uibase change for game features. (#3) --- src/games/fallout76/src/fallout76moddatacontent.h | 4 ++-- src/games/fallout76/src/gamefallout76.cpp | 14 +++++++------- 2 files changed, 9 insertions(+), 9 deletions(-) diff --git a/src/games/fallout76/src/fallout76moddatacontent.h b/src/games/fallout76/src/fallout76moddatacontent.h index a38420f6..39129274 100644 --- a/src/games/fallout76/src/fallout76moddatacontent.h +++ b/src/games/fallout76/src/fallout76moddatacontent.h @@ -11,8 +11,8 @@ protected: }; public: - Fallout76ModDataContent(GameGamebryo const* gamePlugin) : - GamebryoModDataContent(gamePlugin) + Fallout76ModDataContent(MOBase::IGameFeatures const* gameFeatures) : + GamebryoModDataContent(gameFeatures) { m_Enabled[CONTENT_SKYPROC] = false; } diff --git a/src/games/fallout76/src/gamefallout76.cpp b/src/games/fallout76/src/gamefallout76.cpp index bfa428d8..559f4660 100644 --- a/src/games/fallout76/src/gamefallout76.cpp +++ b/src/games/fallout76/src/gamefallout76.cpp @@ -37,12 +37,12 @@ bool GameFallout76::init(IOrganizer *moInfo) return false; } - registerFeature(new Fallout76ScriptExtender(this)); - registerFeature(new Fallout76DataArchives(myGamesPath())); - registerFeature(new Fallout76ModDataChecker(this)); - registerFeature(new Fallout76ModDataContent(this)); - registerFeature(new CreationGamePlugins(moInfo)); - registerFeature(new Fallout76UnmangedMods(this)); + registerFeature(std::make_shared(this)); + registerFeature(std::make_shared(myGamesPath())); + registerFeature(std::make_shared(this)); + registerFeature(std::make_shared(m_Organizer->gameFeatures())); + registerFeature(std::make_shared(moInfo)); + registerFeature(std::make_shared(this)); return true; } @@ -55,7 +55,7 @@ QString GameFallout76::gameName() const QList GameFallout76::executables() const { return QList() - << ExecutableInfo("F76SE", findInGameFolder(feature()->loaderName())) + << ExecutableInfo("F76SE", findInGameFolder(m_Organizer->gameFeatures()->gameFeature()->loaderName())) << ExecutableInfo("Fallout 76", findInGameFolder(binaryName())) << ExecutableInfo("Fallout Launcher", findInGameFolder(getLauncherName())) << ExecutableInfo("Creation Kit", findInGameFolder("CreationKit.exe")) From d1b73d6d4168c77ace71d9af81dc0d42043aa902 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Mika=C3=ABl=20Capelle?= Date: Sun, 9 Jun 2024 12:31:50 +0200 Subject: [PATCH 1457/1544] [game_fallout4vr] Refactoring following uibase change for game features. (#25) --- .../fallout4vr/src/fallout4vrmoddatacontent.h | 4 +- .../fallout4vr/src/game_fallout4vr_en.ts | 161 ------------------ src/games/fallout4vr/src/gamefallout4vr.cpp | 14 +- 3 files changed, 9 insertions(+), 170 deletions(-) diff --git a/src/games/fallout4vr/src/fallout4vrmoddatacontent.h b/src/games/fallout4vr/src/fallout4vrmoddatacontent.h index 5ce3c2dd..693d1644 100644 --- a/src/games/fallout4vr/src/fallout4vrmoddatacontent.h +++ b/src/games/fallout4vr/src/fallout4vrmoddatacontent.h @@ -11,8 +11,8 @@ protected: }; public: - Fallout4VRModDataContent(GameGamebryo const* gamePlugin) : - GamebryoModDataContent(gamePlugin) + Fallout4VRModDataContent(MOBase::IGameFeatures const* gameFeatures) : + GamebryoModDataContent(gameFeatures) { m_Enabled[CONTENT_SKYPROC] = false; } diff --git a/src/games/fallout4vr/src/game_fallout4vr_en.ts b/src/games/fallout4vr/src/game_fallout4vr_en.ts index 066ae77f..6823bb92 100644 --- a/src/games/fallout4vr/src/game_fallout4vr_en.ts +++ b/src/games/fallout4vr/src/game_fallout4vr_en.ts @@ -15,165 +15,4 @@ Splash by %1 - - GamebryoModDataContent - - - Plugins (ESP/ESM/ESL) - - - - - Optional Plugins - - - - - Interface - - - - - Meshes - - - - - Bethesda Archive - - - - - Scripts (Papyrus) - - - - - Script Extender Plugin - - - - - Script Extender Files - - - - - SkyProc Patcher - - - - - Sound or Music - - - - - Textures - - - - - MCM Configuration - - - - - INI Files - - - - - FaceGen Data - - - - - ModGroup Files - - - - - GamebryoSaveGameInfoWidget - - - Save # - - - - - Character - - - - - Level - - - - - Location - - - - - Date - - - - - Has Script Extender Data - - - - - Missing ESPs - - - - - - None - - - - - Missing ESLs - - - - - QObject - - - - Some of your plugins have invalid names! These plugins can not be loaded by the game. Please see mo_interface.log for a list of affected plugins and rename them. - - - - - %1, #%2, Level %3, %4 - - - - - failed to open %1 - - - - - wrong file format - expected %1 got %2 - - - - - failed to query registry path (preflight): %1 - - - - - failed to query registry path (read): %1 - - - diff --git a/src/games/fallout4vr/src/gamefallout4vr.cpp b/src/games/fallout4vr/src/gamefallout4vr.cpp index c835ba5f..b4217686 100644 --- a/src/games/fallout4vr/src/gamefallout4vr.cpp +++ b/src/games/fallout4vr/src/gamefallout4vr.cpp @@ -37,13 +37,13 @@ bool GameFallout4VR::init(IOrganizer *moInfo) return false; } - registerFeature(new Fallout4VRDataArchives(myGamesPath())); - registerFeature(new GamebryoLocalSavegames(myGamesPath(), "fallout4custom.ini")); - registerFeature(new Fallout4VRModDataChecker(this)); - registerFeature(new Fallout4VRModDataContent(this)); - registerFeature(new GamebryoSaveGameInfo(this)); - registerFeature(new Fallout4VRGamePlugins(moInfo)); - registerFeature(new Fallout4VRUnmangedMods(this)); + registerFeature(std::make_shared(myGamesPath())); + registerFeature(std::make_shared(myGamesPath(), "fallout4custom.ini")); + registerFeature(std::make_shared(this)); + registerFeature(std::make_shared(m_Organizer->gameFeatures())); + registerFeature(std::make_shared(this)); + registerFeature(std::make_shared(moInfo)); + registerFeature(std::make_shared(this)); return true; } From 4500a855b7aff819f3c017d3052c25599fd5997a Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Mika=C3=ABl=20Capelle?= Date: Sun, 9 Jun 2024 12:31:55 +0200 Subject: [PATCH 1458/1544] [game_fallout4] Refactoring following uibase change for game features. (#26) --- .../fallout4/src/fallout4bsainvalidation.cpp | 2 +- .../fallout4/src/fallout4bsainvalidation.h | 2 +- .../fallout4/src/fallout4moddatacontent.h | 4 +- src/games/fallout4/src/game_fallout4_en.ts | 163 +----------------- src/games/fallout4/src/gamefallout4.cpp | 23 +-- 5 files changed, 22 insertions(+), 172 deletions(-) diff --git a/src/games/fallout4/src/fallout4bsainvalidation.cpp b/src/games/fallout4/src/fallout4bsainvalidation.cpp index 3e676f64..7dee7c01 100644 --- a/src/games/fallout4/src/fallout4bsainvalidation.cpp +++ b/src/games/fallout4/src/fallout4bsainvalidation.cpp @@ -7,7 +7,7 @@ #include #include -Fallout4BSAInvalidation::Fallout4BSAInvalidation(DataArchives* dataArchives, +Fallout4BSAInvalidation::Fallout4BSAInvalidation(MOBase::DataArchives* dataArchives, MOBase::IPluginGame const* game) : GamebryoBSAInvalidation(dataArchives, "Fallout4Custom.ini", game) { diff --git a/src/games/fallout4/src/fallout4bsainvalidation.h b/src/games/fallout4/src/fallout4bsainvalidation.h index a7e35db9..ae368bf0 100644 --- a/src/games/fallout4/src/fallout4bsainvalidation.h +++ b/src/games/fallout4/src/fallout4bsainvalidation.h @@ -16,7 +16,7 @@ class IPluginGame; class Fallout4BSAInvalidation : public GamebryoBSAInvalidation { public: - Fallout4BSAInvalidation(DataArchives* dataArchives, MOBase::IPluginGame const* game); + Fallout4BSAInvalidation(MOBase::DataArchives* dataArchives, MOBase::IPluginGame const* game); virtual bool isInvalidationBSA(const QString& bsaName) override; virtual bool prepareProfile(MOBase::IProfile* profile) override; diff --git a/src/games/fallout4/src/fallout4moddatacontent.h b/src/games/fallout4/src/fallout4moddatacontent.h index cc65ebe0..b358f809 100644 --- a/src/games/fallout4/src/fallout4moddatacontent.h +++ b/src/games/fallout4/src/fallout4moddatacontent.h @@ -11,8 +11,8 @@ protected: }; public: - Fallout4ModDataContent(GameGamebryo const* gamePlugin) : - GamebryoModDataContent(gamePlugin) + Fallout4ModDataContent(const MOBase::IGameFeatures* gameFeatures) : + GamebryoModDataContent(gameFeatures) { m_Enabled[CONTENT_SKYPROC] = false; } diff --git a/src/games/fallout4/src/game_fallout4_en.ts b/src/games/fallout4/src/game_fallout4_en.ts index 382f10fb..f01109fb 100644 --- a/src/games/fallout4/src/game_fallout4_en.ts +++ b/src/games/fallout4/src/game_fallout4_en.ts @@ -4,175 +4,24 @@ GameFallout4 - + Fallout 4 Support Plugin - + Adds support for the game Fallout 4. Splash by %1 - - - GamebryoModDataContent - - Plugins (ESP/ESM/ESL) + + sTestFile entries are present - - Optional Plugins - - - - - Interface - - - - - Meshes - - - - - Bethesda Archive - - - - - Scripts (Papyrus) - - - - - Script Extender Plugin - - - - - Script Extender Files - - - - - SkyProc Patcher - - - - - Sound or Music - - - - - Textures - - - - - MCM Configuration - - - - - INI Files - - - - - FaceGen Data - - - - - ModGroup Files - - - - - GamebryoSaveGameInfoWidget - - - Save # - - - - - Character - - - - - Level - - - - - Location - - - - - Date - - - - - Has Script Extender Data - - - - - Missing ESPs - - - - - - None - - - - - Missing ESLs - - - - - QObject - - - - Some of your plugins have invalid names! These plugins can not be loaded by the game. Please see mo_interface.log for a list of affected plugins and rename them. - - - - - %1, #%2, Level %3, %4 - - - - - failed to open %1 - - - - - wrong file format - expected %1 got %2 - - - - - failed to query registry path (preflight): %1 - - - - - failed to query registry path (read): %1 + + <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> diff --git a/src/games/fallout4/src/gamefallout4.cpp b/src/games/fallout4/src/gamefallout4.cpp index b7c57375..cab9b6a6 100644 --- a/src/games/fallout4/src/gamefallout4.cpp +++ b/src/games/fallout4/src/gamefallout4.cpp @@ -39,16 +39,17 @@ bool GameFallout4::init(IOrganizer *moInfo) return false; } - registerFeature(new Fallout4ScriptExtender(this)); - registerFeature(new Fallout4DataArchives(myGamesPath())); - registerFeature(new GamebryoLocalSavegames(myGamesPath(), "fallout4custom.ini")); - registerFeature(new Fallout4ModDataChecker(this)); - registerFeature(new Fallout4ModDataContent(this)); - registerFeature(new GamebryoSaveGameInfo(this)); - registerFeature(new CreationGamePlugins(moInfo)); - registerFeature(new Fallout4UnmangedMods(this)); - registerFeature( - new Fallout4BSAInvalidation(feature(), this)); + auto dataArchives = std::make_shared(myGamesPath()); + + registerFeature(std::make_shared(this)); + registerFeature(dataArchives); + registerFeature(std::make_shared(myGamesPath(), "fallout4custom.ini")); + registerFeature(std::make_shared(this)); + registerFeature(std::make_shared(m_Organizer->gameFeatures())); + registerFeature(std::make_shared(this)); + registerFeature(std::make_shared(moInfo)); + registerFeature(std::make_shared(this)); + registerFeature(std::make_shared(dataArchives.get(), this)); return true; } @@ -67,7 +68,7 @@ void GameFallout4::detectGame() QList GameFallout4::executables() const { return QList() - << ExecutableInfo("F4SE", findInGameFolder(feature()->loaderName())) + << ExecutableInfo("F4SE", findInGameFolder(m_Organizer->gameFeatures()->gameFeature()->loaderName())) << ExecutableInfo("Fallout 4", findInGameFolder(binaryName())) << ExecutableInfo("Fallout Launcher", findInGameFolder(getLauncherName())) << ExecutableInfo("Creation Kit", findInGameFolder("CreationKit.exe")).withSteamAppId("1946160") From 2fd428462c691707d4b9a64f6df0e2d1f8b5eb0a Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Mika=C3=ABl=20Capelle?= Date: Sun, 9 Jun 2024 12:31:59 +0200 Subject: [PATCH 1459/1544] [game_fallout3] Refactoring of game features for better management. (#22) --- .../fallout3/src/fallout3bsainvalidation.cpp | 2 +- .../fallout3/src/fallout3bsainvalidation.h | 2 +- .../fallout3/src/fallout3moddatacontent.h | 2 +- src/games/fallout3/src/game_fallout3_en.ts | 165 +----------------- src/games/fallout3/src/gamefallout3.cpp | 38 ++-- 5 files changed, 25 insertions(+), 184 deletions(-) diff --git a/src/games/fallout3/src/fallout3bsainvalidation.cpp b/src/games/fallout3/src/fallout3bsainvalidation.cpp index a55dec33..039ecf74 100644 --- a/src/games/fallout3/src/fallout3bsainvalidation.cpp +++ b/src/games/fallout3/src/fallout3bsainvalidation.cpp @@ -1,6 +1,6 @@ #include "fallout3bsainvalidation.h" -Fallout3BSAInvalidation::Fallout3BSAInvalidation(DataArchives *dataArchives, MOBase::IPluginGame const *game) +Fallout3BSAInvalidation::Fallout3BSAInvalidation(MOBase::DataArchives* dataArchives, MOBase::IPluginGame const* game) : GamebryoBSAInvalidation(dataArchives, "fallout.ini", game) { } diff --git a/src/games/fallout3/src/fallout3bsainvalidation.h b/src/games/fallout3/src/fallout3bsainvalidation.h index 16f0c656..1f3b9883 100644 --- a/src/games/fallout3/src/fallout3bsainvalidation.h +++ b/src/games/fallout3/src/fallout3bsainvalidation.h @@ -11,7 +11,7 @@ class Fallout3BSAInvalidation : public GamebryoBSAInvalidation { public: - Fallout3BSAInvalidation(DataArchives *dataArchives, MOBase::IPluginGame const *game); + Fallout3BSAInvalidation(MOBase::DataArchives* dataArchives, MOBase::IPluginGame const* game); private: diff --git a/src/games/fallout3/src/fallout3moddatacontent.h b/src/games/fallout3/src/fallout3moddatacontent.h index 5b99dd05..2a805845 100644 --- a/src/games/fallout3/src/fallout3moddatacontent.h +++ b/src/games/fallout3/src/fallout3moddatacontent.h @@ -10,7 +10,7 @@ public: /** * */ - Fallout3ModDataContent(GameGamebryo const* gamePlugin) : GamebryoModDataContent(gamePlugin) { + Fallout3ModDataContent(MOBase::IGameFeatures const* gameFeatures) : GamebryoModDataContent(gameFeatures) { // Just need to disable some contents: m_Enabled[CONTENT_MCM] = false; m_Enabled[CONTENT_SKYPROC] = false; diff --git a/src/games/fallout3/src/game_fallout3_en.ts b/src/games/fallout3/src/game_fallout3_en.ts index 3b92898f..c404839d 100644 --- a/src/games/fallout3/src/game_fallout3_en.ts +++ b/src/games/fallout3/src/game_fallout3_en.ts @@ -4,175 +4,14 @@ GameFallout3 - + Fallout 3 Support Plugin - + Adds support for the game Fallout 3. - - GamebryoModDataContent - - - Plugins (ESP/ESM/ESL) - - - - - Optional Plugins - - - - - Interface - - - - - Meshes - - - - - Bethesda Archive - - - - - Scripts (Papyrus) - - - - - Script Extender Plugin - - - - - Script Extender Files - - - - - SkyProc Patcher - - - - - Sound or Music - - - - - Textures - - - - - MCM Configuration - - - - - INI Files - - - - - FaceGen Data - - - - - ModGroup Files - - - - - GamebryoSaveGameInfoWidget - - - Save # - - - - - Character - - - - - Level - - - - - Location - - - - - Date - - - - - Has Script Extender Data - - - - - Missing ESPs - - - - - - None - - - - - Missing ESLs - - - - - QObject - - - - Some of your plugins have invalid names! These plugins can not be loaded by the game. Please see mo_interface.log for a list of affected plugins and rename them. - - - - - %1, #%2, Level %3, %4 - - - - - failed to open %1 - - - - - wrong file format - expected %1 got %2 - - - - - failed to query registry path (preflight): %1 - - - - - failed to query registry path (read): %1 - - - diff --git a/src/games/fallout3/src/gamefallout3.cpp b/src/games/fallout3/src/gamefallout3.cpp index 87f3cad3..7d7bdcfe 100644 --- a/src/games/fallout3/src/gamefallout3.cpp +++ b/src/games/fallout3/src/gamefallout3.cpp @@ -31,20 +31,22 @@ GameFallout3::GameFallout3() { } -bool GameFallout3::init(IOrganizer *moInfo) +bool GameFallout3::init(IOrganizer* moInfo) { if (!GameGamebryo::init(moInfo)) { return false; } - registerFeature(new Fallout3ScriptExtender(this)); - registerFeature(new Fallout3DataArchives(myGamesPath())); - registerFeature(new Fallout3BSAInvalidation(feature(), this)); - registerFeature(new GamebryoSaveGameInfo(this)); - registerFeature(new GamebryoLocalSavegames(myGamesPath(), "fallout.ini")); - registerFeature(new Fallout3ModDataChecker(this)); - registerFeature(new Fallout3ModDataContent(this)); - registerFeature(new GamebryoGamePlugins(moInfo)); - registerFeature(new GamebryoUnmangedMods(this)); + + auto dataArchives = std::make_shared(myGamesPath()); + registerFeature(std::make_shared(this)); + registerFeature(dataArchives); + registerFeature(std::make_shared(dataArchives.get(), this)); + registerFeature(std::make_shared(this)); + registerFeature(std::make_shared(myGamesPath(), "fallout.ini")); + registerFeature(std::make_shared(this)); + registerFeature(std::make_shared(m_Organizer->gameFeatures())); + registerFeature(std::make_shared(moInfo)); + registerFeature(std::make_shared(this)); return true; } @@ -80,14 +82,14 @@ void GameFallout3::detectGame() QList GameFallout3::executables() const { return QList() - << ExecutableInfo("FOSE", findInGameFolder(feature()->loaderName())) - << ExecutableInfo("Fallout 3", findInGameFolder(binaryName())) - << ExecutableInfo("Fallout Mod Manager", findInGameFolder("fomm/fomm.exe")) - << ExecutableInfo("Construction Kit", findInGameFolder("geck.exe")) - << ExecutableInfo("Fallout Launcher", findInGameFolder(getLauncherName())) - << ExecutableInfo("BOSS", findInGameFolder("BOSS/BOSS.exe")) - << ExecutableInfo("LOOT", QFileInfo(getLootPath())).withArgument("--game=\"Fallout3\"") - ; + << ExecutableInfo("FOSE", findInGameFolder(m_Organizer->gameFeatures()->gameFeature()->loaderName())) + << ExecutableInfo("Fallout 3", findInGameFolder(binaryName())) + << ExecutableInfo("Fallout Mod Manager", findInGameFolder("fomm/fomm.exe")) + << ExecutableInfo("Construction Kit", findInGameFolder("geck.exe")) + << ExecutableInfo("Fallout Launcher", findInGameFolder(getLauncherName())) + << ExecutableInfo("BOSS", findInGameFolder("BOSS/BOSS.exe")) + << ExecutableInfo("LOOT", QFileInfo(getLootPath())).withArgument("--game=\"Fallout3\"") + ; } QList GameFallout3::executableForcedLoads() const From 99d2d68f2197aa63f1e61e2e6889722af937ca6f Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Mika=C3=ABl=20Capelle?= Date: Sun, 9 Jun 2024 12:33:41 +0200 Subject: [PATCH 1460/1544] [game_enderalse] Refactoring of game features for better management. (#9) --- .../enderalse/src/enderalsegameplugins.h | 2 +- .../enderalse/src/enderalselocalsavegames.h | 2 +- .../enderalse/src/enderalsemoddatacontent.h | 4 +-- src/games/enderalse/src/enderalsesavegame.cpp | 2 +- src/games/enderalse/src/game_enderalse_en.ts | 4 +-- src/games/enderalse/src/gameenderalse.cpp | 29 ++++++++++--------- 6 files changed, 23 insertions(+), 20 deletions(-) diff --git a/src/games/enderalse/src/enderalsegameplugins.h b/src/games/enderalse/src/enderalsegameplugins.h index 16077f90..275733c1 100644 --- a/src/games/enderalse/src/enderalsegameplugins.h +++ b/src/games/enderalse/src/enderalsegameplugins.h @@ -19,4 +19,4 @@ private: std::map m_LastSaveHash; }; -#endif // ENDERALSEGAMEPLUGINS_H \ No newline at end of file +#endif // ENDERALSEGAMEPLUGINS_H diff --git a/src/games/enderalse/src/enderalselocalsavegames.h b/src/games/enderalse/src/enderalselocalsavegames.h index 3fd2d3fc..78b4d04d 100644 --- a/src/games/enderalse/src/enderalselocalsavegames.h +++ b/src/games/enderalse/src/enderalselocalsavegames.h @@ -6,7 +6,7 @@ #include #include -class EnderalSELocalSavegames : public LocalSavegames +class EnderalSELocalSavegames : public MOBase::LocalSavegames { public: diff --git a/src/games/enderalse/src/enderalsemoddatacontent.h b/src/games/enderalse/src/enderalsemoddatacontent.h index b72b59dd..a9cce03c 100644 --- a/src/games/enderalse/src/enderalsemoddatacontent.h +++ b/src/games/enderalse/src/enderalsemoddatacontent.h @@ -10,8 +10,8 @@ public: /** * */ - EnderalSEModDataContent(GameGamebryo const* gamePlugin) - : GamebryoModDataContent(gamePlugin) + EnderalSEModDataContent(MOBase::IGameFeatures* gameFeatures) + : GamebryoModDataContent(gameFeatures) { // Just need to disable some contents: m_Enabled[CONTENT_SKYPROC] = false; diff --git a/src/games/enderalse/src/enderalsesavegame.cpp b/src/games/enderalse/src/enderalsesavegame.cpp index c5bf68af..13a37eca 100644 --- a/src/games/enderalse/src/enderalsesavegame.cpp +++ b/src/games/enderalse/src/enderalsesavegame.cpp @@ -110,4 +110,4 @@ std::unique_ptr EnderalSESaveGame::fetchDataFields file.closeCompressedData(); return fields; -} \ No newline at end of file +} diff --git a/src/games/enderalse/src/game_enderalse_en.ts b/src/games/enderalse/src/game_enderalse_en.ts index 875af5a4..540fe0eb 100644 --- a/src/games/enderalse/src/game_enderalse_en.ts +++ b/src/games/enderalse/src/game_enderalse_en.ts @@ -4,12 +4,12 @@ GameEnderalSE - + Enderal Special Edition Support Plugin - + Adds support for the game Enderal Special Edition. diff --git a/src/games/enderalse/src/gameenderalse.cpp b/src/games/enderalse/src/gameenderalse.cpp index f30b1f89..8feed75e 100644 --- a/src/games/enderalse/src/gameenderalse.cpp +++ b/src/games/enderalse/src/gameenderalse.cpp @@ -84,9 +84,9 @@ void GameEnderalSE::setGamePath(const QString& path) m_GamePath = path; checkVariants(); m_MyGamesPath = determineMyGamesPath(gameDirectoryName()); - registerFeature(new EnderalSEDataArchives(myGamesPath())); - registerFeature( - new EnderalSELocalSavegames(myGamesPath(), "Enderal.ini")); + registerFeature(std::make_shared(myGamesPath())); + registerFeature( + std::make_shared(myGamesPath(), "Enderal.ini")); } QDir GameEnderalSE::savesDirectory() const @@ -110,15 +110,16 @@ bool GameEnderalSE::init(IOrganizer* moInfo) return false; } - registerFeature(new EnderalSEScriptExtender(this)); - registerFeature(new EnderalSEDataArchives(myGamesPath())); - registerFeature( - new EnderalSELocalSavegames(myGamesPath(), "Enderal.ini")); - registerFeature(new EnderalSEModDataChecker(this)); - registerFeature(new EnderalSEModDataContent(this)); - registerFeature(new GamebryoSaveGameInfo(this)); - registerFeature(new EnderalSEGamePlugins(moInfo)); - registerFeature(new EnderalSEUnmangedMods(this)); + auto dataArchives = std::make_shared(myGamesPath()); + registerFeature(std::make_shared(this)); + registerFeature(dataArchives); + registerFeature( + std::make_shared(myGamesPath(), "enderal.ini")); + registerFeature(std::make_shared(this)); + registerFeature(std::make_shared(moInfo->gameFeatures())); + registerFeature(std::make_shared(this)); + registerFeature(std::make_shared(moInfo)); + registerFeature(std::make_shared(this)); return true; } @@ -145,7 +146,9 @@ QList GameEnderalSE::executables() const { return QList() << ExecutableInfo("Enderal Special Edition (SKSE)", - findInGameFolder(feature()->loaderName())) + findInGameFolder(m_Organizer->gameFeatures() + ->gameFeature() + ->loaderName())) << ExecutableInfo("Enderal Special Edition Launcher", findInGameFolder(getLauncherName())) << ExecutableInfo("Creation Kit", findInGameFolder("CreationKit.exe")) From 212d41147ab4bec42e3a6f9cf7d4908632fb1010 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Mika=C3=ABl=20Capelle?= Date: Sun, 9 Jun 2024 12:33:55 +0200 Subject: [PATCH 1461/1544] [game_ttw] Refactoring of game features for better management. (#39) --- .../ttw/src/falloutttwbsainvalidation.cpp | 2 +- src/games/ttw/src/falloutttwbsainvalidation.h | 2 +- src/games/ttw/src/falloutttwmoddatacontent.h | 4 +- src/games/ttw/src/game_ttw_en.ts | 6 +-- src/games/ttw/src/gamefalloutttw.cpp | 41 +++++++++++-------- 5 files changed, 31 insertions(+), 24 deletions(-) diff --git a/src/games/ttw/src/falloutttwbsainvalidation.cpp b/src/games/ttw/src/falloutttwbsainvalidation.cpp index a2303603..67a7817e 100644 --- a/src/games/ttw/src/falloutttwbsainvalidation.cpp +++ b/src/games/ttw/src/falloutttwbsainvalidation.cpp @@ -1,6 +1,6 @@ #include "falloutttwbsainvalidation.h" -FalloutTTWBSAInvalidation::FalloutTTWBSAInvalidation(DataArchives* dataArchives, +FalloutTTWBSAInvalidation::FalloutTTWBSAInvalidation(MOBase::DataArchives* dataArchives, MOBase::IPluginGame const* game) : GamebryoBSAInvalidation(dataArchives, "fallout.ini", game) {} diff --git a/src/games/ttw/src/falloutttwbsainvalidation.h b/src/games/ttw/src/falloutttwbsainvalidation.h index 6511c852..96062d35 100644 --- a/src/games/ttw/src/falloutttwbsainvalidation.h +++ b/src/games/ttw/src/falloutttwbsainvalidation.h @@ -9,7 +9,7 @@ class FalloutTTWBSAInvalidation : public GamebryoBSAInvalidation { public: - FalloutTTWBSAInvalidation(DataArchives* dataArchives, + FalloutTTWBSAInvalidation(MOBase::DataArchives* dataArchives, MOBase::IPluginGame const* game); private: diff --git a/src/games/ttw/src/falloutttwmoddatacontent.h b/src/games/ttw/src/falloutttwmoddatacontent.h index c9ef2fbb..37f9d203 100644 --- a/src/games/ttw/src/falloutttwmoddatacontent.h +++ b/src/games/ttw/src/falloutttwmoddatacontent.h @@ -10,8 +10,8 @@ public: /** * */ - FalloutTTWModDataContent(GameGamebryo const* gamePlugin) - : GamebryoModDataContent(gamePlugin) + FalloutTTWModDataContent(MOBase::IGameFeatures const* gameFeatures) + : GamebryoModDataContent(gameFeatures) { // Just need to disable some contents: m_Enabled[CONTENT_MCM] = false; diff --git a/src/games/ttw/src/game_ttw_en.ts b/src/games/ttw/src/game_ttw_en.ts index e06609b2..53e2efb2 100644 --- a/src/games/ttw/src/game_ttw_en.ts +++ b/src/games/ttw/src/game_ttw_en.ts @@ -4,17 +4,17 @@ GameFalloutTTW - + Fallout TTW Support Plugin - + Adds support for the game Fallout TTW - + While not recommended by the TTW modding community, enables LOOT sorting diff --git a/src/games/ttw/src/gamefalloutttw.cpp b/src/games/ttw/src/gamefalloutttw.cpp index 8f809ec6..c2ca3ba1 100644 --- a/src/games/ttw/src/gamefalloutttw.cpp +++ b/src/games/ttw/src/gamefalloutttw.cpp @@ -35,17 +35,20 @@ bool GameFalloutTTW::init(IOrganizer* moInfo) return false; } - registerFeature(new FalloutTTWScriptExtender(this)); - registerFeature(new FalloutTTWDataArchives(myGamesPath())); - registerFeature( - new FalloutTTWBSAInvalidation(feature(), this)); - registerFeature(new GamebryoSaveGameInfo(this)); - registerFeature( - new GamebryoLocalSavegames(myGamesPath(), "fallout.ini")); - registerFeature(new FalloutTTWModDataChecker(this)); - registerFeature(new FalloutTTWModDataContent(this)); - registerFeature(new GamebryoGamePlugins(moInfo)); - registerFeature(new GamebryoUnmangedMods(this)); + auto dataArchives = std::make_shared(myGamesPath()); + registerFeature(std::make_shared(this)); + registerFeature(dataArchives); + registerFeature( + std::make_shared(dataArchives.get(), this)); + registerFeature(std::make_shared(this)); + registerFeature( + std::make_shared(myGamesPath(), "fallout.ini")); + registerFeature(std::make_shared(this)); + registerFeature( + std::make_shared(m_Organizer->gameFeatures())); + registerFeature(std::make_shared(moInfo)); + registerFeature(std::make_shared(this)); + return true; } @@ -104,11 +107,13 @@ void GameFalloutTTW::setGamePath(const QString& path) m_GamePath = path; checkVariants(); m_MyGamesPath = determineMyGamesPath(gameDirectoryName()); - registerFeature(new FalloutTTWDataArchives(myGamesPath())); - registerFeature( - new FalloutTTWBSAInvalidation(feature(), this)); - registerFeature( - new GamebryoLocalSavegames(myGamesPath(), "fallout.ini")); + + auto dataArchives = std::make_shared(myGamesPath()); + registerFeature(dataArchives); + registerFeature( + std::make_shared(dataArchives.get(), this)); + registerFeature( + std::make_shared(myGamesPath(), "fallout.ini")); } QDir GameFalloutTTW::savesDirectory() const @@ -161,7 +166,9 @@ QList GameFalloutTTW::executables() const .withArgument("--game=\"FalloutNV\""); if (selectedVariant() != "Epic Games") { extraExecutables.prepend(ExecutableInfo( - "NVSE", findInGameFolder(feature()->loaderName()))); + "NVSE", findInGameFolder(m_Organizer->gameFeatures() + ->gameFeature() + ->loaderName()))); } else { game.withArgument("-EpicPortal"); launcher.withArgument("-EpicPortal"); From 653dfa0876eba4e26780d112d4eb46ee06cc95ea Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Mika=C3=ABl=20Capelle?= Date: Sun, 9 Jun 2024 13:03:32 +0200 Subject: [PATCH 1462/1544] [game_fallout3] Remove appveyor.yml. --- src/games/fallout3/appveyor.yml | 40 --------------------------------- 1 file changed, 40 deletions(-) delete mode 100644 src/games/fallout3/appveyor.yml diff --git a/src/games/fallout3/appveyor.yml b/src/games/fallout3/appveyor.yml deleted file mode 100644 index b5abb0e1..00000000 --- a/src/games/fallout3/appveyor.yml +++ /dev/null @@ -1,40 +0,0 @@ -version: 1.0.{build} -skip_branch_with_pr: true -image: Visual Studio 2019 -environment: - WEBHOOK_URL: - secure: gOKbXaZM9ImtMD5XrYITvdyZUW/az082G9OIN1EC1Vbg57wBaeLhi49uGjxPw5GVujHku6kxN6ab89zhbS5GVeluR76GM83IbKV4Sh7udXzoYZZdg6YudtYHzdhCgUeiedpswbuczTq9ceIkkfSEWZuh/lMAAVVwvcGsJAnoPFw= -build_script: -- pwsh: >- - $ErrorActionPreference = 'Stop' - - git clone --depth=1 --no-single-branch https://github.com/ModOrganizer2/modorganizer-umbrella.git c:\projects\modorganizer-umbrella - - New-Item -ItemType Directory -Path c:\projects\modorganizer-build - - cd c:\projects\modorganizer-umbrella - - ($env:APPVEYOR_PULL_REQUEST_HEAD_REPO_BRANCH -eq $null) ? ($branch = $env:APPVEYOR_REPO_BRANCH) : ($branch = $env:APPVEYOR_PULL_REQUEST_HEAD_REPO_BRANCH) - - git checkout $(git show-ref --verify --quiet refs/remotes/origin/${branch} || echo '-b') ${branch} - - C:\Python37-x64\python.exe unimake.py -d c:\projects\modorganizer-build -s Appveyor_Build=True ${env:APPVEYOR_PROJECT_NAME} - - if($LastExitCode -ne 0) { $host.SetShouldExit($LastExitCode ) } -artifacts: -- path: vsbuild\src\RelWithDebInfo\game_fallout3.dll - name: game_fallout3_dll -- path: vsbuild\src\RelWithDebInfo\game_fallout3.pdb - name: game_fallout3_pdb -- path: vsbuild\src\RelWithDebInfo\game_fallout3.lib - name: game_fallout3_lib -on_success: - - ps: Set-Location -Path $env:APPVEYOR_BUILD_FOLDER - - ps: Invoke-RestMethod https://raw.githubusercontent.com/DiscordHooks/appveyor-discord-webhook/master/send.ps1 -o send.ps1 - - ps: ./send.ps1 success $env:WEBHOOK_URL -on_failure: - - ps: Set-Location -Path $env:APPVEYOR_BUILD_FOLDER - - ps: Push-AppveyorArtifact ${env:APPVEYOR_BUILD_FOLDER}\stdout.log - - ps: Push-AppveyorArtifact ${env:APPVEYOR_BUILD_FOLDER}\stderr.log - - ps: Invoke-RestMethod https://raw.githubusercontent.com/DiscordHooks/appveyor-discord-webhook/master/send.ps1 -o send.ps1 - - ps: ./send.ps1 failure $env:WEBHOOK_URL \ No newline at end of file From 739ef58d92661075647cf1ef142301451a252b06 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Mika=C3=ABl=20Capelle?= Date: Sun, 9 Jun 2024 13:05:40 +0200 Subject: [PATCH 1463/1544] [game_fallout3] Format files and add .gitattributes and .clang-format. --- src/games/fallout3/.clang-format | 41 +++++++ src/games/fallout3/.gitattributes | 7 ++ .../fallout3/src/fallout3bsainvalidation.cpp | 32 ++--- .../fallout3/src/fallout3bsainvalidation.h | 43 ++++--- .../fallout3/src/fallout3dataarchives.cpp | 75 ++++++------ src/games/fallout3/src/fallout3dataarchives.h | 47 ++++---- .../fallout3/src/fallout3moddatachecker.h | 24 ++-- .../fallout3/src/fallout3moddatacontent.h | 13 ++- src/games/fallout3/src/fallout3savegame.cpp | 33 +++--- src/games/fallout3/src/fallout3savegame.h | 17 +-- .../fallout3/src/fallout3scriptextender.cpp | 37 +++--- .../fallout3/src/fallout3scriptextender.h | 36 +++--- src/games/fallout3/src/gamefallout3.cpp | 72 ++++++------ src/games/fallout3/src/gamefallout3.h | 110 +++++++++--------- 14 files changed, 313 insertions(+), 274 deletions(-) create mode 100644 src/games/fallout3/.clang-format create mode 100644 src/games/fallout3/.gitattributes diff --git a/src/games/fallout3/.clang-format b/src/games/fallout3/.clang-format new file mode 100644 index 00000000..6098e1f5 --- /dev/null +++ b/src/games/fallout3/.clang-format @@ -0,0 +1,41 @@ +--- +# We'll use defaults from the LLVM style, but with 4 columns indentation. +BasedOnStyle: LLVM +IndentWidth: 2 +--- +Language: Cpp +DeriveLineEnding: false +UseCRLF: true +DerivePointerAlignment: false +PointerAlignment: Left +AlignConsecutiveAssignments: true +AllowShortFunctionsOnASingleLine: Inline +AllowShortIfStatementsOnASingleLine: Never +AllowShortLambdasOnASingleLine: Empty +AlwaysBreakTemplateDeclarations: Yes +AccessModifierOffset: -2 +AlignTrailingComments: true +SpacesBeforeTrailingComments: 2 +NamespaceIndentation: Inner +MaxEmptyLinesToKeep: 1 +BreakBeforeBraces: Custom +BraceWrapping: + AfterCaseLabel: false + AfterClass: true + AfterControlStatement: false + AfterEnum: true + AfterFunction: true + AfterNamespace: true + AfterStruct: true + AfterUnion: true + AfterExternBlock: true + BeforeCatch: false + BeforeElse: false + BeforeLambdaBody: false + BeforeWhile: false + IndentBraces: false + SplitEmptyFunction: false + SplitEmptyRecord: false + SplitEmptyNamespace: true +ColumnLimit: 88 +ForEachMacros: ['Q_FOREACH', 'foreach'] diff --git a/src/games/fallout3/.gitattributes b/src/games/fallout3/.gitattributes new file mode 100644 index 00000000..f8697127 --- /dev/null +++ b/src/games/fallout3/.gitattributes @@ -0,0 +1,7 @@ +# Set the default behavior, in case people don't have core.autocrlf set. +* text=auto + +# Explicitly declare text files you want to always be normalized and converted +# to native line endings on checkout. +*.cpp text eol=crlf +*.h text eol=crlf diff --git a/src/games/fallout3/src/fallout3bsainvalidation.cpp b/src/games/fallout3/src/fallout3bsainvalidation.cpp index 039ecf74..ce981fb6 100644 --- a/src/games/fallout3/src/fallout3bsainvalidation.cpp +++ b/src/games/fallout3/src/fallout3bsainvalidation.cpp @@ -1,16 +1,16 @@ -#include "fallout3bsainvalidation.h" - -Fallout3BSAInvalidation::Fallout3BSAInvalidation(MOBase::DataArchives* dataArchives, MOBase::IPluginGame const* game) - : GamebryoBSAInvalidation(dataArchives, "fallout.ini", game) -{ -} - -QString Fallout3BSAInvalidation::invalidationBSAName() const -{ - return "Fallout - Invalidation.bsa"; -} - -unsigned long Fallout3BSAInvalidation::bsaVersion() const -{ - return 0x68; -} +#include "fallout3bsainvalidation.h" + +Fallout3BSAInvalidation::Fallout3BSAInvalidation(MOBase::DataArchives* dataArchives, + MOBase::IPluginGame const* game) + : GamebryoBSAInvalidation(dataArchives, "fallout.ini", game) +{} + +QString Fallout3BSAInvalidation::invalidationBSAName() const +{ + return "Fallout - Invalidation.bsa"; +} + +unsigned long Fallout3BSAInvalidation::bsaVersion() const +{ + return 0x68; +} diff --git a/src/games/fallout3/src/fallout3bsainvalidation.h b/src/games/fallout3/src/fallout3bsainvalidation.h index 1f3b9883..f836073b 100644 --- a/src/games/fallout3/src/fallout3bsainvalidation.h +++ b/src/games/fallout3/src/fallout3bsainvalidation.h @@ -1,23 +1,20 @@ -#ifndef FALLOUT3BSAINVALIDATION_H -#define FALLOUT3BSAINVALIDATION_H - - -#include "gamebryobsainvalidation.h" -#include "fallout3dataarchives.h" - -#include - -class Fallout3BSAInvalidation : public GamebryoBSAInvalidation -{ -public: - - Fallout3BSAInvalidation(MOBase::DataArchives* dataArchives, MOBase::IPluginGame const* game); - -private: - - virtual QString invalidationBSAName() const override; - virtual unsigned long bsaVersion() const override; - -}; - -#endif // FALLOUT3BSAINVALIDATION_H +#ifndef FALLOUT3BSAINVALIDATION_H +#define FALLOUT3BSAINVALIDATION_H + +#include "fallout3dataarchives.h" +#include "gamebryobsainvalidation.h" + +#include + +class Fallout3BSAInvalidation : public GamebryoBSAInvalidation +{ +public: + Fallout3BSAInvalidation(MOBase::DataArchives* dataArchives, + MOBase::IPluginGame const* game); + +private: + virtual QString invalidationBSAName() const override; + virtual unsigned long bsaVersion() const override; +}; + +#endif // FALLOUT3BSAINVALIDATION_H diff --git a/src/games/fallout3/src/fallout3dataarchives.cpp b/src/games/fallout3/src/fallout3dataarchives.cpp index c308dda7..623b566a 100644 --- a/src/games/fallout3/src/fallout3dataarchives.cpp +++ b/src/games/fallout3/src/fallout3dataarchives.cpp @@ -1,38 +1,37 @@ -#include "fallout3dataarchives.h" - -#include "iprofile.h" -#include - -Fallout3DataArchives::Fallout3DataArchives(const QDir &myGamesDir) : - GamebryoDataArchives(myGamesDir) -{ -} - -QStringList Fallout3DataArchives::vanillaArchives() const -{ - return { "Fallout - Textures.bsa" - , "Fallout - Meshes.bsa" - , "Fallout - Voices.bsa" - , "Fallout - Sound.bsa" - , "Fallout - MenuVoices.bsa" - , "Fallout - Misc.bsa" }; -} - - -QStringList Fallout3DataArchives::archives(const MOBase::IProfile *profile) const -{ - QStringList result; - - QString iniFile = profile->localSettingsEnabled() ? QDir(profile->absolutePath()).absoluteFilePath("fallout.ini") : m_LocalGameDir.absoluteFilePath("fallout.ini"); - result.append(getArchivesFromKey(iniFile, "SArchiveList")); - - return result; -} - -void Fallout3DataArchives::writeArchiveList(MOBase::IProfile *profile, const QStringList &before) -{ - QString list = before.join(", "); - - QString iniFile = profile->localSettingsEnabled() ? QDir(profile->absolutePath()).absoluteFilePath("fallout.ini") : m_LocalGameDir.absoluteFilePath("fallout.ini"); - setArchivesToKey(iniFile, "SArchiveList", list); -} +#include "fallout3dataarchives.h" + +#include "iprofile.h" +#include + +Fallout3DataArchives::Fallout3DataArchives(const QDir& myGamesDir) + : GamebryoDataArchives(myGamesDir) +{} + +QStringList Fallout3DataArchives::vanillaArchives() const +{ + return {"Fallout - Textures.bsa", "Fallout - Meshes.bsa", "Fallout - Voices.bsa", + "Fallout - Sound.bsa", "Fallout - MenuVoices.bsa", "Fallout - Misc.bsa"}; +} + +QStringList Fallout3DataArchives::archives(const MOBase::IProfile* profile) const +{ + QStringList result; + + QString iniFile = profile->localSettingsEnabled() + ? QDir(profile->absolutePath()).absoluteFilePath("fallout.ini") + : m_LocalGameDir.absoluteFilePath("fallout.ini"); + result.append(getArchivesFromKey(iniFile, "SArchiveList")); + + return result; +} + +void Fallout3DataArchives::writeArchiveList(MOBase::IProfile* profile, + const QStringList& before) +{ + QString list = before.join(", "); + + QString iniFile = profile->localSettingsEnabled() + ? QDir(profile->absolutePath()).absoluteFilePath("fallout.ini") + : m_LocalGameDir.absoluteFilePath("fallout.ini"); + setArchivesToKey(iniFile, "SArchiveList", list); +} diff --git a/src/games/fallout3/src/fallout3dataarchives.h b/src/games/fallout3/src/fallout3dataarchives.h index 7caf47f7..5522e08f 100644 --- a/src/games/fallout3/src/fallout3dataarchives.h +++ b/src/games/fallout3/src/fallout3dataarchives.h @@ -1,25 +1,22 @@ -#ifndef FALLOUT3DATAARCHIVES_H -#define FALLOUT3DATAARCHIVES_H - - -#include "gamebryodataarchives.h" -#include - -class Fallout3DataArchives : public GamebryoDataArchives -{ - -public: - Fallout3DataArchives(const QDir &myGamesDir); - -public: - - 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 // FALLOUT3DATAARCHIVES_H +#ifndef FALLOUT3DATAARCHIVES_H +#define FALLOUT3DATAARCHIVES_H + +#include "gamebryodataarchives.h" +#include + +class Fallout3DataArchives : public GamebryoDataArchives +{ + +public: + Fallout3DataArchives(const QDir& myGamesDir); + +public: + 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 // FALLOUT3DATAARCHIVES_H diff --git a/src/games/fallout3/src/fallout3moddatachecker.h b/src/games/fallout3/src/fallout3moddatachecker.h index a91fdc60..00511379 100644 --- a/src/games/fallout3/src/fallout3moddatachecker.h +++ b/src/games/fallout3/src/fallout3moddatachecker.h @@ -9,21 +9,23 @@ public: using GamebryoModDataChecker::GamebryoModDataChecker; protected: - virtual const FileNameSet& possibleFolderNames() const override { + virtual const FileNameSet& possibleFolderNames() const override + { static FileNameSet result{ - "fonts", "interface", "menus", "meshes", "music", "scripts", "shaders", - "sound", "strings", "textures", "trees", "video", "facegen", "materials", - "fose", "distantlod", "asi", "Tools", "MCM", "distantland", "mits", - "dllplugins", "CalienteTools", "NetScriptFramework", "shadersfx" - }; + "fonts", "interface", "menus", "meshes", + "music", "scripts", "shaders", "sound", + "strings", "textures", "trees", "video", + "facegen", "materials", "fose", "distantlod", + "asi", "Tools", "MCM", "distantland", + "mits", "dllplugins", "CalienteTools", "NetScriptFramework", + "shadersfx"}; return result; } - virtual const FileNameSet& possibleFileExtensions() const override { - static FileNameSet result{ - "esp", "esm", "bsa", "modgroups", "ini" - }; + virtual const FileNameSet& possibleFileExtensions() const override + { + static FileNameSet result{"esp", "esm", "bsa", "modgroups", "ini"}; return result; } }; -#endif // FALLOUT3_MODATACHECKER_H +#endif // FALLOUT3_MODATACHECKER_H diff --git a/src/games/fallout3/src/fallout3moddatacontent.h b/src/games/fallout3/src/fallout3moddatacontent.h index 2a805845..bc314a9b 100644 --- a/src/games/fallout3/src/fallout3moddatacontent.h +++ b/src/games/fallout3/src/fallout3moddatacontent.h @@ -4,18 +4,19 @@ #include #include -class Fallout3ModDataContent : public GamebryoModDataContent { +class Fallout3ModDataContent : public GamebryoModDataContent +{ public: - /** * */ - Fallout3ModDataContent(MOBase::IGameFeatures const* gameFeatures) : GamebryoModDataContent(gameFeatures) { + Fallout3ModDataContent(MOBase::IGameFeatures const* gameFeatures) + : GamebryoModDataContent(gameFeatures) + { // Just need to disable some contents: - m_Enabled[CONTENT_MCM] = false; + m_Enabled[CONTENT_MCM] = false; m_Enabled[CONTENT_SKYPROC] = false; } - }; -#endif // FALLOUT3_MODDATACONTENT_H +#endif // FALLOUT3_MODDATACONTENT_H diff --git a/src/games/fallout3/src/fallout3savegame.cpp b/src/games/fallout3/src/fallout3savegame.cpp index 765be18f..60bba507 100644 --- a/src/games/fallout3/src/fallout3savegame.cpp +++ b/src/games/fallout3/src/fallout3savegame.cpp @@ -2,31 +2,30 @@ #include "gamefallout3.h" -Fallout3SaveGame::Fallout3SaveGame(QString const &fileName, GameFallout3 const *game) : - GamebryoSaveGame(fileName, game) +Fallout3SaveGame::Fallout3SaveGame(QString const& fileName, GameFallout3 const* game) + : GamebryoSaveGame(fileName, game) { FileWrapper file(getFilepath(), "FO3SAVEGAME"); unsigned long width, height; - fetchInformationFields(file, width, height, m_SaveNumber, m_PCName, m_PCLevel, m_PCLocation); + fetchInformationFields(file, width, height, m_SaveNumber, m_PCName, m_PCLevel, + m_PCLocation); } -void Fallout3SaveGame::fetchInformationFields( - FileWrapper& file, - unsigned long& width, - unsigned long& height, - unsigned long& saveNumber, - QString& playerName, - unsigned short& playerLevel, - QString& playerLocation) const +void Fallout3SaveGame::fetchInformationFields(FileWrapper& file, unsigned long& width, + unsigned long& height, + unsigned long& saveNumber, + QString& playerName, + unsigned short& playerLevel, + QString& playerLocation) const { - file.skip(); //Save header size + file.skip(); // Save header size file.setHasFieldMarkers(true); file.setPluginString(GamebryoSaveGame::StringType::TYPE_BZSTRING); - file.skip(); //File version ? - file.skip(); //delimiter + file.skip(); // File version ? + file.skip(); // delimiter file.read(width); file.read(height); @@ -55,8 +54,8 @@ std::unique_ptr Fallout3SaveGame::fetchDataFields( unsigned short dummyLevel; unsigned long dummySaveNumber; - fetchInformationFields(file, width, height, - dummySaveNumber, dummyName, dummyLevel, dummyLocation); + fetchInformationFields(file, width, height, dummySaveNumber, dummyName, dummyLevel, + dummyLocation); } QString playtime; @@ -64,7 +63,7 @@ std::unique_ptr Fallout3SaveGame::fetchDataFields( fields->Screenshot = file.readImage(width, height, 256); - file.skip(5); // unknown (1 byte), plugin size (4 bytes) + file.skip(5); // unknown (1 byte), plugin size (4 bytes) file.setPluginString(GamebryoSaveGame::StringType::TYPE_BSTRING); fields->Plugins = file.readPlugins(); diff --git a/src/games/fallout3/src/fallout3savegame.h b/src/games/fallout3/src/fallout3savegame.h index d325bb90..9ab57342 100644 --- a/src/games/fallout3/src/fallout3savegame.h +++ b/src/games/fallout3/src/fallout3savegame.h @@ -8,21 +8,16 @@ class GameFallout3; class Fallout3SaveGame : public GamebryoSaveGame { public: - Fallout3SaveGame(QString const &fileName, GameFallout3 const *game); + Fallout3SaveGame(QString const& fileName, GameFallout3 const* game); protected: - // Fetch easy-to-access information. - void fetchInformationFields( - FileWrapper& wrapper, - unsigned long& width, - unsigned long& height, - unsigned long& saveNumber, - QString& playerName, - unsigned short& playerLevel, - QString& playerLocation) const; + void fetchInformationFields(FileWrapper& wrapper, unsigned long& width, + unsigned long& height, unsigned long& saveNumber, + QString& playerName, unsigned short& playerLevel, + QString& playerLocation) const; std::unique_ptr fetchDataFields() const override; }; -#endif // FALLOUT3SAVEGAME_H +#endif // FALLOUT3SAVEGAME_H diff --git a/src/games/fallout3/src/fallout3scriptextender.cpp b/src/games/fallout3/src/fallout3scriptextender.cpp index b39e8953..608a3050 100644 --- a/src/games/fallout3/src/fallout3scriptextender.cpp +++ b/src/games/fallout3/src/fallout3scriptextender.cpp @@ -1,19 +1,18 @@ -#include "fallout3scriptextender.h" - -#include -#include - -Fallout3ScriptExtender::Fallout3ScriptExtender(GameGamebryo const *game) : - GamebryoScriptExtender(game) -{ -} - -QString Fallout3ScriptExtender::BinaryName() const -{ - return "fose_loader.exe"; -} - -QString Fallout3ScriptExtender::PluginPath() const -{ - return "fose/plugins"; -} +#include "fallout3scriptextender.h" + +#include +#include + +Fallout3ScriptExtender::Fallout3ScriptExtender(GameGamebryo const* game) + : GamebryoScriptExtender(game) +{} + +QString Fallout3ScriptExtender::BinaryName() const +{ + return "fose_loader.exe"; +} + +QString Fallout3ScriptExtender::PluginPath() const +{ + return "fose/plugins"; +} diff --git a/src/games/fallout3/src/fallout3scriptextender.h b/src/games/fallout3/src/fallout3scriptextender.h index 108196bf..1769d6bc 100644 --- a/src/games/fallout3/src/fallout3scriptextender.h +++ b/src/games/fallout3/src/fallout3scriptextender.h @@ -1,19 +1,17 @@ -#ifndef FALLOUT3SCRIPTEXTENDER_H -#define FALLOUT3SCRIPTEXTENDER_H - - -#include "gamebryoscriptextender.h" - -class GameGamebryo; - -class Fallout3ScriptExtender : public GamebryoScriptExtender -{ -public: - Fallout3ScriptExtender(GameGamebryo const *game); - - virtual QString BinaryName() const override; - virtual QString PluginPath() const override; - -}; - -#endif // FALLOUT3SCRIPTEXTENDER_H +#ifndef FALLOUT3SCRIPTEXTENDER_H +#define FALLOUT3SCRIPTEXTENDER_H + +#include "gamebryoscriptextender.h" + +class GameGamebryo; + +class Fallout3ScriptExtender : public GamebryoScriptExtender +{ +public: + Fallout3ScriptExtender(GameGamebryo const* game); + + virtual QString BinaryName() const override; + virtual QString PluginPath() const override; +}; + +#endif // FALLOUT3SCRIPTEXTENDER_H diff --git a/src/games/fallout3/src/gamefallout3.cpp b/src/games/fallout3/src/gamefallout3.cpp index 7d7bdcfe..6de76cd9 100644 --- a/src/games/fallout3/src/gamefallout3.cpp +++ b/src/games/fallout3/src/gamefallout3.cpp @@ -1,19 +1,19 @@ #include "gamefallout3.h" #include "fallout3bsainvalidation.h" -#include "fallout3scriptextender.h" #include "fallout3dataarchives.h" #include "fallout3moddatachecker.h" #include "fallout3moddatacontent.h" #include "fallout3savegame.h" +#include "fallout3scriptextender.h" #include "executableinfo.h" #include "pluginsetting.h" #include "versioninfo.h" -#include #include -#include +#include #include +#include #include #include @@ -27,9 +27,7 @@ using namespace MOBase; -GameFallout3::GameFallout3() -{ -} +GameFallout3::GameFallout3() {} bool GameFallout3::init(IOrganizer* moInfo) { @@ -42,9 +40,11 @@ bool GameFallout3::init(IOrganizer* moInfo) registerFeature(dataArchives); registerFeature(std::make_shared(dataArchives.get(), this)); registerFeature(std::make_shared(this)); - registerFeature(std::make_shared(myGamesPath(), "fallout.ini")); + registerFeature( + std::make_shared(myGamesPath(), "fallout.ini")); registerFeature(std::make_shared(this)); - registerFeature(std::make_shared(m_Organizer->gameFeatures())); + registerFeature( + std::make_shared(m_Organizer->gameFeatures())); registerFeature(std::make_shared(moInfo)); registerFeature(std::make_shared(this)); return true; @@ -56,11 +56,11 @@ QString GameFallout3::identifyGamePath() const // EPIC Game Store if (result.isEmpty()) { // Fallout 3: Game of the Year Edition: adeae8bbfc94427db57c7dfecce3f1d4 - result = parseEpicGamesLocation({ "adeae8bbfc94427db57c7dfecce3f1d4" }); + result = parseEpicGamesLocation({"adeae8bbfc94427db57c7dfecce3f1d4"}); if (QFileInfo(result).isDir()) { QDir startPath = QDir(result); - auto subDirs = startPath.entryList({ "Fallout 3 GOTY*" }, - QDir::Dirs | QDir::NoDotAndDotDot); + auto subDirs = + startPath.entryList({"Fallout 3 GOTY*"}, QDir::Dirs | QDir::NoDotAndDotDot); if (!subDirs.isEmpty()) result = startPath.absoluteFilePath(subDirs.first()); } @@ -75,21 +75,24 @@ QString GameFallout3::gameName() const void GameFallout3::detectGame() { - m_GamePath = identifyGamePath(); + m_GamePath = identifyGamePath(); m_MyGamesPath = determineMyGamesPath("Fallout3"); } QList GameFallout3::executables() const { return QList() - << ExecutableInfo("FOSE", findInGameFolder(m_Organizer->gameFeatures()->gameFeature()->loaderName())) - << ExecutableInfo("Fallout 3", findInGameFolder(binaryName())) - << ExecutableInfo("Fallout Mod Manager", findInGameFolder("fomm/fomm.exe")) - << ExecutableInfo("Construction Kit", findInGameFolder("geck.exe")) - << ExecutableInfo("Fallout Launcher", findInGameFolder(getLauncherName())) - << ExecutableInfo("BOSS", findInGameFolder("BOSS/BOSS.exe")) - << ExecutableInfo("LOOT", QFileInfo(getLootPath())).withArgument("--game=\"Fallout3\"") - ; + << ExecutableInfo("FOSE", + findInGameFolder(m_Organizer->gameFeatures() + ->gameFeature() + ->loaderName())) + << ExecutableInfo("Fallout 3", findInGameFolder(binaryName())) + << ExecutableInfo("Fallout Mod Manager", findInGameFolder("fomm/fomm.exe")) + << ExecutableInfo("Construction Kit", findInGameFolder("geck.exe")) + << ExecutableInfo("Fallout Launcher", findInGameFolder(getLauncherName())) + << ExecutableInfo("BOSS", findInGameFolder("BOSS/BOSS.exe")) + << ExecutableInfo("LOOT", QFileInfo(getLootPath())) + .withArgument("--game=\"Fallout3\""); } QList GameFallout3::executableForcedLoads() const @@ -122,13 +125,12 @@ MOBase::VersionInfo GameFallout3::version() const return VersionInfo(1, 4, 1, VersionInfo::RELEASE_FINAL); } - QList GameFallout3::settings() const { return QList(); } -void GameFallout3::initializeProfile(const QDir &path, ProfileSettings settings) const +void GameFallout3::initializeProfile(const QDir& path, ProfileSettings settings) const { if (settings.testFlag(IPluginGame::MODS)) { copyToProfile(localAppFolder() + "/Fallout3", path, "plugins.txt"); @@ -136,16 +138,17 @@ void GameFallout3::initializeProfile(const QDir &path, ProfileSettings settings) } 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"); + 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, "custom.ini"); + copyToProfile(myGamesPath(), path, "FalloutCustom.ini"); + copyToProfile(myGamesPath(), path, "custom.ini"); copyToProfile(myGamesPath(), path, "GECKCustom.ini"); copyToProfile(myGamesPath(), path, "GECKPrefs.ini"); } @@ -161,7 +164,8 @@ QString GameFallout3::savegameSEExtension() const return ""; } -std::shared_ptr GameFallout3::makeSaveGame(QString filePath) const +std::shared_ptr +GameFallout3::makeSaveGame(QString filePath) const { return std::make_shared(filePath, this); } @@ -177,12 +181,12 @@ QString GameFallout3::steamAPPId() const QStringList GameFallout3::primaryPlugins() const { - return { "fallout3.esm" }; + return {"fallout3.esm"}; } QStringList GameFallout3::gameVariants() const { - return { "Regular", "Game Of The Year" }; + return {"Regular", "Game Of The Year"}; } QString GameFallout3::gameShortName() const @@ -192,7 +196,7 @@ QString GameFallout3::gameShortName() const QStringList GameFallout3::validShortNames() const { - return { "FalloutNV" }; + return {"FalloutNV"}; } QString GameFallout3::gameNexusName() const @@ -202,12 +206,14 @@ QString GameFallout3::gameNexusName() const QStringList GameFallout3::iniFiles() const { - return { "fallout.ini", "falloutprefs.ini", "custom.ini", "FalloutCustom.ini", "GECKCustom.ini", "GECKPrefs.ini" }; + return {"fallout.ini", "falloutprefs.ini", "custom.ini", + "FalloutCustom.ini", "GECKCustom.ini", "GECKPrefs.ini"}; } QStringList GameFallout3::DLCPlugins() const { - return { "ThePitt.esm", "Anchorage.esm", "BrokenSteel.esm", "PointLookout.esm", "Zeta.esm" }; + return {"ThePitt.esm", "Anchorage.esm", "BrokenSteel.esm", "PointLookout.esm", + "Zeta.esm"}; } int GameFallout3::nexusModOrganizerID() const diff --git a/src/games/fallout3/src/gamefallout3.h b/src/games/fallout3/src/gamefallout3.h index c3c92e5f..8533f579 100644 --- a/src/games/fallout3/src/gamefallout3.h +++ b/src/games/fallout3/src/gamefallout3.h @@ -1,56 +1,54 @@ -#ifndef GAMEFALLOUT3_H -#define GAMEFALLOUT3_H - -#include "gamegamebryo.h" - -#include -#include - -class GameFallout3 : public GameGamebryo -{ - Q_OBJECT - Q_PLUGIN_METADATA(IID "org.tannin.GameFallout3" FILE "gamefallout3.json") - -public: - - GameFallout3(); - - virtual bool init(MOBase::IOrganizer *moInfo) override; - -public: // IPluginGame interface - - virtual QString gameName() const override; - virtual void detectGame() override; - virtual QList executables() const override; - virtual QList 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; - virtual QString gameShortName() const override; - virtual QStringList validShortNames() const override; - virtual QString gameNexusName() const override; - virtual QString getLauncherName() const override; - virtual QStringList iniFiles() const override; - virtual QStringList DLCPlugins() const override; - virtual int nexusModOrganizerID() const override; - virtual int nexusGameID() 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 settings() const override; - -protected: - virtual QString identifyGamePath() const override; - virtual QString savegameExtension() const override; - virtual QString savegameSEExtension() const override; - std::shared_ptr makeSaveGame(QString filePath) const override; - -}; - -#endif // GAMEFALLOUT3_H +#ifndef GAMEFALLOUT3_H +#define GAMEFALLOUT3_H + +#include "gamegamebryo.h" + +#include +#include + +class GameFallout3 : public GameGamebryo +{ + Q_OBJECT + Q_PLUGIN_METADATA(IID "org.tannin.GameFallout3" FILE "gamefallout3.json") + +public: + GameFallout3(); + + virtual bool init(MOBase::IOrganizer* moInfo) override; + +public: // IPluginGame interface + virtual QString gameName() const override; + virtual void detectGame() override; + virtual QList executables() const override; + virtual QList + 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; + virtual QString gameShortName() const override; + virtual QStringList validShortNames() const override; + virtual QString gameNexusName() const override; + virtual QString getLauncherName() const override; + virtual QStringList iniFiles() const override; + virtual QStringList DLCPlugins() const override; + virtual int nexusModOrganizerID() const override; + virtual int nexusGameID() 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 settings() const override; + +protected: + virtual QString identifyGamePath() const override; + virtual QString savegameExtension() const override; + virtual QString savegameSEExtension() const override; + std::shared_ptr makeSaveGame(QString filePath) const override; +}; + +#endif // GAMEFALLOUT3_H From 2cb7c7c01781619d201dd6a94672c50c9a141bb1 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Mika=C3=ABl=20Capelle?= Date: Sun, 9 Jun 2024 13:06:17 +0200 Subject: [PATCH 1464/1544] [game_fallout3] Add .git-blame-ignore-revs. --- src/games/fallout3/.git-blame-ignore-revs | 1 + 1 file changed, 1 insertion(+) create mode 100644 src/games/fallout3/.git-blame-ignore-revs diff --git a/src/games/fallout3/.git-blame-ignore-revs b/src/games/fallout3/.git-blame-ignore-revs new file mode 100644 index 00000000..ebacef70 --- /dev/null +++ b/src/games/fallout3/.git-blame-ignore-revs @@ -0,0 +1 @@ +4f0d232b8fbedb307f486880d079eab5c014923e From 70b1b07c82b99a981f294b45967259fdde8ae7fb Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Mika=C3=ABl=20Capelle?= Date: Sun, 9 Jun 2024 13:06:22 +0200 Subject: [PATCH 1465/1544] [game_fallout3] Add github actions. --- src/games/fallout3/.github/workflows/build.yml | 16 ++++++++++++++++ src/games/fallout3/.github/workflows/linting.yml | 16 ++++++++++++++++ 2 files changed, 32 insertions(+) create mode 100644 src/games/fallout3/.github/workflows/build.yml create mode 100644 src/games/fallout3/.github/workflows/linting.yml diff --git a/src/games/fallout3/.github/workflows/build.yml b/src/games/fallout3/.github/workflows/build.yml new file mode 100644 index 00000000..22349a44 --- /dev/null +++ b/src/games/fallout3/.github/workflows/build.yml @@ -0,0 +1,16 @@ +name: Build Fallout 3 Plugin + +on: + push: + branches: master + pull_request: + types: [opened, synchronize, reopened] + +jobs: + build: + runs-on: windows-2022 + steps: + - name: Build Fallout 3 Plugin + uses: ModOrganizer2/build-with-mob-action@master + with: + mo2-dependencies: cmake_common uibase game_gamebryo diff --git a/src/games/fallout3/.github/workflows/linting.yml b/src/games/fallout3/.github/workflows/linting.yml new file mode 100644 index 00000000..e2caad98 --- /dev/null +++ b/src/games/fallout3/.github/workflows/linting.yml @@ -0,0 +1,16 @@ +name: Lint Fallout 3 Plugin + +on: + push: + pull_request: + types: [opened, synchronize, reopened] + +jobs: + lint: + runs-on: ubuntu-latest + steps: + - uses: actions/checkout@v3 + - name: Check format + uses: ModOrganizer2/check-formatting-action@master + with: + check-path: "." From 767338dfd31fe4bef20c9658e87b3b34e8deca01 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Mika=C3=ABl=20Capelle?= Date: Sun, 9 Jun 2024 13:08:22 +0200 Subject: [PATCH 1466/1544] [game_fallout4] Remove appveyor.yml. --- src/games/fallout4/appveyor.yml | 40 --------------------------------- 1 file changed, 40 deletions(-) delete mode 100644 src/games/fallout4/appveyor.yml diff --git a/src/games/fallout4/appveyor.yml b/src/games/fallout4/appveyor.yml deleted file mode 100644 index 1e625dd0..00000000 --- a/src/games/fallout4/appveyor.yml +++ /dev/null @@ -1,40 +0,0 @@ -version: 1.0.{build} -skip_branch_with_pr: true -image: Visual Studio 2019 -environment: - WEBHOOK_URL: - secure: gOKbXaZM9ImtMD5XrYITvdyZUW/az082G9OIN1EC1Vbg57wBaeLhi49uGjxPw5GVujHku6kxN6ab89zhbS5GVeluR76GM83IbKV4Sh7udXzoYZZdg6YudtYHzdhCgUeiedpswbuczTq9ceIkkfSEWZuh/lMAAVVwvcGsJAnoPFw= -build_script: -- pwsh: >- - $ErrorActionPreference = 'Stop' - - git clone --depth=1 --no-single-branch https://github.com/ModOrganizer2/modorganizer-umbrella.git c:\projects\modorganizer-umbrella - - New-Item -ItemType Directory -Path c:\projects\modorganizer-build - - cd c:\projects\modorganizer-umbrella - - ($env:APPVEYOR_PULL_REQUEST_HEAD_REPO_BRANCH -eq $null) ? ($branch = $env:APPVEYOR_REPO_BRANCH) : ($branch = $env:APPVEYOR_PULL_REQUEST_HEAD_REPO_BRANCH) - - git checkout $(git show-ref --verify --quiet refs/remotes/origin/${branch} || echo '-b') ${branch} - - C:\Python37-x64\python.exe unimake.py -d c:\projects\modorganizer-build -s Appveyor_Build=True ${env:APPVEYOR_PROJECT_NAME} - - if($LastExitCode -ne 0) { $host.SetShouldExit($LastExitCode ) } -artifacts: -- path: vsbuild\src\RelWithDebInfo\game_fallout4.dll - name: game_fallout4_dll -- path: vsbuild\src\RelWithDebInfo\game_fallout4.pdb - name: game_fallout4_pdb -- path: vsbuild\src\RelWithDebInfo\game_fallout4.lib - name: game_fallout4_lib -on_success: - - ps: Set-Location -Path $env:APPVEYOR_BUILD_FOLDER - - ps: Invoke-RestMethod https://raw.githubusercontent.com/DiscordHooks/appveyor-discord-webhook/master/send.ps1 -o send.ps1 - - ps: ./send.ps1 success $env:WEBHOOK_URL -on_failure: - - ps: Set-Location -Path $env:APPVEYOR_BUILD_FOLDER - - ps: Push-AppveyorArtifact ${env:APPVEYOR_BUILD_FOLDER}\stdout.log - - ps: Push-AppveyorArtifact ${env:APPVEYOR_BUILD_FOLDER}\stderr.log - - ps: Invoke-RestMethod https://raw.githubusercontent.com/DiscordHooks/appveyor-discord-webhook/master/send.ps1 -o send.ps1 - - ps: ./send.ps1 failure $env:WEBHOOK_URL \ No newline at end of file From c89fe9b184b1f704767b4dfcae0f331767ef4318 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Mika=C3=ABl=20Capelle?= Date: Sun, 9 Jun 2024 13:10:27 +0200 Subject: [PATCH 1467/1544] [game_fallout4] Format files and add .gitattributes and .clang-format. --- src/games/fallout4/.clang-format | 41 +++++++++ src/games/fallout4/.gitattributes | 7 ++ .../fallout4/src/fallout4bsainvalidation.h | 5 +- .../fallout4/src/fallout4dataarchives.cpp | 47 +++++----- src/games/fallout4/src/fallout4dataarchives.h | 20 ++-- .../fallout4/src/fallout4moddatachecker.h | 21 +++-- .../fallout4/src/fallout4moddatacontent.h | 21 +++-- src/games/fallout4/src/fallout4savegame.cpp | 45 +++++---- src/games/fallout4/src/fallout4savegame.h | 15 +-- .../fallout4/src/fallout4scriptextender.cpp | 7 +- .../fallout4/src/fallout4scriptextender.h | 5 +- .../fallout4/src/fallout4unmanagedmods.cpp | 24 ++--- .../fallout4/src/fallout4unmanagedmods.h | 15 ++- src/games/fallout4/src/gamefallout4.cpp | 92 +++++++++++-------- src/games/fallout4/src/gamefallout4.h | 16 ++-- 15 files changed, 216 insertions(+), 165 deletions(-) create mode 100644 src/games/fallout4/.clang-format create mode 100644 src/games/fallout4/.gitattributes diff --git a/src/games/fallout4/.clang-format b/src/games/fallout4/.clang-format new file mode 100644 index 00000000..6098e1f5 --- /dev/null +++ b/src/games/fallout4/.clang-format @@ -0,0 +1,41 @@ +--- +# We'll use defaults from the LLVM style, but with 4 columns indentation. +BasedOnStyle: LLVM +IndentWidth: 2 +--- +Language: Cpp +DeriveLineEnding: false +UseCRLF: true +DerivePointerAlignment: false +PointerAlignment: Left +AlignConsecutiveAssignments: true +AllowShortFunctionsOnASingleLine: Inline +AllowShortIfStatementsOnASingleLine: Never +AllowShortLambdasOnASingleLine: Empty +AlwaysBreakTemplateDeclarations: Yes +AccessModifierOffset: -2 +AlignTrailingComments: true +SpacesBeforeTrailingComments: 2 +NamespaceIndentation: Inner +MaxEmptyLinesToKeep: 1 +BreakBeforeBraces: Custom +BraceWrapping: + AfterCaseLabel: false + AfterClass: true + AfterControlStatement: false + AfterEnum: true + AfterFunction: true + AfterNamespace: true + AfterStruct: true + AfterUnion: true + AfterExternBlock: true + BeforeCatch: false + BeforeElse: false + BeforeLambdaBody: false + BeforeWhile: false + IndentBraces: false + SplitEmptyFunction: false + SplitEmptyRecord: false + SplitEmptyNamespace: true +ColumnLimit: 88 +ForEachMacros: ['Q_FOREACH', 'foreach'] diff --git a/src/games/fallout4/.gitattributes b/src/games/fallout4/.gitattributes new file mode 100644 index 00000000..f8697127 --- /dev/null +++ b/src/games/fallout4/.gitattributes @@ -0,0 +1,7 @@ +# Set the default behavior, in case people don't have core.autocrlf set. +* text=auto + +# Explicitly declare text files you want to always be normalized and converted +# to native line endings on checkout. +*.cpp text eol=crlf +*.h text eol=crlf diff --git a/src/games/fallout4/src/fallout4bsainvalidation.h b/src/games/fallout4/src/fallout4bsainvalidation.h index ae368bf0..fe525057 100644 --- a/src/games/fallout4/src/fallout4bsainvalidation.h +++ b/src/games/fallout4/src/fallout4bsainvalidation.h @@ -16,7 +16,8 @@ class IPluginGame; class Fallout4BSAInvalidation : public GamebryoBSAInvalidation { public: - Fallout4BSAInvalidation(MOBase::DataArchives* dataArchives, MOBase::IPluginGame const* game); + Fallout4BSAInvalidation(MOBase::DataArchives* dataArchives, + MOBase::IPluginGame const* game); virtual bool isInvalidationBSA(const QString& bsaName) override; virtual bool prepareProfile(MOBase::IProfile* profile) override; @@ -29,4 +30,4 @@ private: MOBase::IPluginGame const* m_Game; }; -#endif // FALLOUT4BSAINVALIDATION_H \ No newline at end of file +#endif // FALLOUT4BSAINVALIDATION_H diff --git a/src/games/fallout4/src/fallout4dataarchives.cpp b/src/games/fallout4/src/fallout4dataarchives.cpp index 3cad8c96..5dccd793 100644 --- a/src/games/fallout4/src/fallout4dataarchives.cpp +++ b/src/games/fallout4/src/fallout4dataarchives.cpp @@ -3,50 +3,45 @@ #include "iprofile.h" #include -Fallout4DataArchives::Fallout4DataArchives(const QDir &myGamesDir) : - GamebryoDataArchives(myGamesDir) +Fallout4DataArchives::Fallout4DataArchives(const QDir& myGamesDir) + : GamebryoDataArchives(myGamesDir) {} QStringList Fallout4DataArchives::vanillaArchives() const { - return { "Fallout4 - Textures1.ba2" - , "Fallout4 - Textures2.ba2" - , "Fallout4 - Textures3.ba2" - , "Fallout4 - Textures4.ba2" - , "Fallout4 - Textures5.ba2" - , "Fallout4 - Textures6.ba2" - , "Fallout4 - Textures7.ba2" - , "Fallout4 - Textures8.ba2" - , "Fallout4 - Textures9.ba2" - , "Fallout4 - Meshes.ba2" - , "Fallout4 - MeshesExtra.ba2" - , "Fallout4 - Voices.ba2" - , "Fallout4 - Sounds.ba2" - , "Fallout4 - Interface.ba2" - , "Fallout4 - Animations.ba2" - , "Fallout4 - Materials.ba2" - , "Fallout4 - Shaders.ba2" - , "Fallout4 - Startup.ba2" - , "Fallout4 - Misc.ba2" }; + return {"Fallout4 - Textures1.ba2", "Fallout4 - Textures2.ba2", + "Fallout4 - Textures3.ba2", "Fallout4 - Textures4.ba2", + "Fallout4 - Textures5.ba2", "Fallout4 - Textures6.ba2", + "Fallout4 - Textures7.ba2", "Fallout4 - Textures8.ba2", + "Fallout4 - Textures9.ba2", "Fallout4 - Meshes.ba2", + "Fallout4 - MeshesExtra.ba2", "Fallout4 - Voices.ba2", + "Fallout4 - Sounds.ba2", "Fallout4 - Interface.ba2", + "Fallout4 - Animations.ba2", "Fallout4 - Materials.ba2", + "Fallout4 - Shaders.ba2", "Fallout4 - Startup.ba2", + "Fallout4 - Misc.ba2"}; } - -QStringList Fallout4DataArchives::archives(const MOBase::IProfile *profile) const +QStringList Fallout4DataArchives::archives(const MOBase::IProfile* profile) const { QStringList result; - QString iniFile = profile->localSettingsEnabled() ? QDir(profile->absolutePath()).absoluteFilePath("fallout4.ini") : m_LocalGameDir.absoluteFilePath("fallout4.ini"); + QString iniFile = profile->localSettingsEnabled() + ? QDir(profile->absolutePath()).absoluteFilePath("fallout4.ini") + : m_LocalGameDir.absoluteFilePath("fallout4.ini"); result.append(getArchivesFromKey(iniFile, "SResourceArchiveList")); result.append(getArchivesFromKey(iniFile, "SResourceArchiveList2")); return result; } -void Fallout4DataArchives::writeArchiveList(MOBase::IProfile *profile, const QStringList &before) +void Fallout4DataArchives::writeArchiveList(MOBase::IProfile* profile, + const QStringList& before) { QString list = before.join(", "); - QString iniFile = profile->localSettingsEnabled() ? QDir(profile->absolutePath()).absoluteFilePath("fallout4.ini") : m_LocalGameDir.absoluteFilePath("fallout4.ini"); + QString iniFile = profile->localSettingsEnabled() + ? QDir(profile->absolutePath()).absoluteFilePath("fallout4.ini") + : m_LocalGameDir.absoluteFilePath("fallout4.ini"); if (list.length() > 255) { int splitIdx = list.lastIndexOf(",", 256); setArchivesToKey(iniFile, "SResourceArchiveList", list.mid(0, splitIdx)); diff --git a/src/games/fallout4/src/fallout4dataarchives.h b/src/games/fallout4/src/fallout4dataarchives.h index b6abd173..42695f65 100644 --- a/src/games/fallout4/src/fallout4dataarchives.h +++ b/src/games/fallout4/src/fallout4dataarchives.h @@ -3,27 +3,27 @@ #include "gamebryodataarchives.h" -namespace MOBase { class IProfile; } +namespace MOBase +{ +class IProfile; +} -#include #include +#include class Fallout4DataArchives : public GamebryoDataArchives { public: - - Fallout4DataArchives(const QDir &myGamesDir); + Fallout4DataArchives(const QDir& myGamesDir); public: - virtual QStringList vanillaArchives() const override; - virtual QStringList archives(const MOBase::IProfile *profile) const override; + virtual QStringList archives(const MOBase::IProfile* profile) const override; private: - - virtual void writeArchiveList(MOBase::IProfile *profile, const QStringList &before) override; - + virtual void writeArchiveList(MOBase::IProfile* profile, + const QStringList& before) override; }; -#endif // FALLOUT4DATAARCHIVES_H +#endif // FALLOUT4DATAARCHIVES_H diff --git a/src/games/fallout4/src/fallout4moddatachecker.h b/src/games/fallout4/src/fallout4moddatachecker.h index 4dd2a2c5..08b04976 100644 --- a/src/games/fallout4/src/fallout4moddatachecker.h +++ b/src/games/fallout4/src/fallout4moddatachecker.h @@ -9,20 +9,21 @@ public: using GamebryoModDataChecker::GamebryoModDataChecker; protected: - virtual const FileNameSet& possibleFolderNames() const override { + virtual const FileNameSet& possibleFolderNames() const override + { static FileNameSet result{ - "interface", "meshes", "music", "scripts", "sound", "strings", "textures", - "trees", "video", "materials", "f4se", "distantlod", "asi", "Tools", "MCM", - "distantland", "mits", "dllplugins", "CalienteTools", "shadersfx", "aaf" - }; + "interface", "meshes", "music", "scripts", "sound", "strings", + "textures", "trees", "video", "materials", "f4se", "distantlod", + "asi", "Tools", "MCM", "distantland", "mits", "dllplugins", + "CalienteTools", "shadersfx", "aaf"}; return result; } - virtual const FileNameSet& possibleFileExtensions() const override { - static FileNameSet result{ - "esp", "esm", "esl", "ba2", "modgroups", "ini", "csg", "cdx" - }; + virtual const FileNameSet& possibleFileExtensions() const override + { + static FileNameSet result{"esp", "esm", "esl", "ba2", + "modgroups", "ini", "csg", "cdx"}; return result; } }; -#endif // FALLOUT4_MODATACHECKER_H +#endif // FALLOUT4_MODATACHECKER_H diff --git a/src/games/fallout4/src/fallout4moddatacontent.h b/src/games/fallout4/src/fallout4moddatacontent.h index b358f809..172e94f7 100644 --- a/src/games/fallout4/src/fallout4moddatacontent.h +++ b/src/games/fallout4/src/fallout4moddatacontent.h @@ -4,15 +4,17 @@ #include #include -class Fallout4ModDataContent : public GamebryoModDataContent { +class Fallout4ModDataContent : public GamebryoModDataContent +{ protected: - enum Fallout4Content { + enum Fallout4Content + { CONTENT_MATERIAL = CONTENT_NEXT_VALUE }; public: - Fallout4ModDataContent(const MOBase::IGameFeatures* gameFeatures) : - GamebryoModDataContent(gameFeatures) + Fallout4ModDataContent(const MOBase::IGameFeatures* gameFeatures) + : GamebryoModDataContent(gameFeatures) { m_Enabled[CONTENT_SKYPROC] = false; } @@ -20,22 +22,23 @@ public: std::vector getAllContents() const override { auto contents = GamebryoModDataContent::getAllContents(); - contents.push_back(Content(CONTENT_MATERIAL, "Materials", ":/MO/gui/content/material")); + contents.push_back( + Content(CONTENT_MATERIAL, "Materials", ":/MO/gui/content/material")); return contents; } - std::vector getContentsFor( - std::shared_ptr fileTree) const override + std::vector + getContentsFor(std::shared_ptr fileTree) const override { auto contents = GamebryoModDataContent::getContentsFor(fileTree); for (auto e : *fileTree) { if (e->compare("materials") == 0) { contents.push_back(CONTENT_MATERIAL); - break; // Early break if you have nothing else to check. + break; // Early break if you have nothing else to check. } } return contents; } }; -#endif // FALLOUT4_MODDATACONTENT_H \ No newline at end of file +#endif // FALLOUT4_MODDATACONTENT_H diff --git a/src/games/fallout4/src/fallout4savegame.cpp b/src/games/fallout4/src/fallout4savegame.cpp index 53bb5dcc..dcb3d855 100644 --- a/src/games/fallout4/src/fallout4savegame.cpp +++ b/src/games/fallout4/src/fallout4savegame.cpp @@ -4,17 +4,18 @@ #include "gamefallout4.h" -Fallout4SaveGame::Fallout4SaveGame(QString const &fileName, GameFallout4 const* game) : - GamebryoSaveGame(fileName, game, true) +Fallout4SaveGame::Fallout4SaveGame(QString const& fileName, GameFallout4 const* game) + : GamebryoSaveGame(fileName, game, true) { FileWrapper file(getFilepath(), "FO4_SAVEGAME"); FILETIME creationTime; - fetchInformationFields(file, m_SaveNumber, m_PCName, m_PCLevel, m_PCLocation, creationTime); + fetchInformationFields(file, m_SaveNumber, m_PCName, m_PCLevel, m_PCLocation, + creationTime); - //A file time is a 64-bit value that represents the number of 100-nanosecond - //intervals that have elapsed since 12:00 A.M. January 1, 1601 Coordinated Universal Time (UTC). - //So we need to convert that to something useful + // A file time is a 64-bit value that represents the number of 100-nanosecond + // intervals that have elapsed since 12:00 A.M. January 1, 1601 Coordinated Universal + // Time (UTC). So we need to convert that to something useful SYSTEMTIME ctime; ::FileTimeToSystemTime(&creationTime, &ctime); @@ -22,15 +23,11 @@ Fallout4SaveGame::Fallout4SaveGame(QString const &fileName, GameFallout4 const* } void Fallout4SaveGame::fetchInformationFields( - FileWrapper& file, - unsigned long& saveNumber, - QString& playerName, - unsigned short& playerLevel, - QString& playerLocation, - FILETIME& creationTime) const + FileWrapper& file, unsigned long& saveNumber, QString& playerName, + unsigned short& playerLevel, QString& playerLocation, FILETIME& creationTime) const { - file.skip(); // header size - file.skip(); // header version + file.skip(); // header size + file.skip(); // header version file.read(saveNumber); file.read(playerName); @@ -41,18 +38,18 @@ void Fallout4SaveGame::fetchInformationFields( file.read(playerLocation); QString ignore; - file.read(ignore); // playtime as ascii hh.mm.ss - file.read(ignore); // race name (i.e. BretonRace) + file.read(ignore); // playtime as ascii hh.mm.ss + file.read(ignore); // race name (i.e. BretonRace) - file.skip(); // Player gender (0 = male) - file.skip(2); // experience gathered, experience required + file.skip(); // Player gender (0 = male) + file.skip(2); // experience gathered, experience required file.read(creationTime); } std::unique_ptr Fallout4SaveGame::fetchDataFields() const { - FileWrapper file(getFilepath(), "FO4_SAVEGAME"); //10bytes + FileWrapper file(getFilepath(), "FO4_SAVEGAME"); // 10bytes { QString dummyName, dummyLocation; @@ -60,8 +57,8 @@ std::unique_ptr Fallout4SaveGame::fetchDataFields( unsigned long dummySaveNumber; FILETIME dummyTime; - fetchInformationFields(file, dummySaveNumber, dummyName, dummyLevel, - dummyLocation, dummyTime); + fetchInformationFields(file, dummySaveNumber, dummyName, dummyLevel, dummyLocation, + dummyTime); } QString ignore; @@ -70,8 +67,8 @@ std::unique_ptr Fallout4SaveGame::fetchDataFields( fields->Screenshot = file.readImage(384, true); uint8_t saveGameVersion = file.readChar(); - file.read(ignore); // game version - file.skip(); // plugin info size + file.read(ignore); // game version + file.skip(); // plugin info size fields->Plugins = file.readPlugins(); if (saveGameVersion >= 68) { @@ -79,4 +76,4 @@ std::unique_ptr Fallout4SaveGame::fetchDataFields( } return fields; -} \ No newline at end of file +} diff --git a/src/games/fallout4/src/fallout4savegame.h b/src/games/fallout4/src/fallout4savegame.h index 3c302e5a..c26e0eb8 100644 --- a/src/games/fallout4/src/fallout4savegame.h +++ b/src/games/fallout4/src/fallout4savegame.h @@ -10,20 +10,15 @@ class GameFallout4; class Fallout4SaveGame : public GamebryoSaveGame { public: - Fallout4SaveGame(QString const &fileName, GameFallout4 const* game); + Fallout4SaveGame(QString const& fileName, GameFallout4 const* game); protected: - // Fetch easy-to-access information. - void fetchInformationFields( - FileWrapper& file, - unsigned long& saveNumber, - QString& playerName, - unsigned short& playerLevel, - QString& playerLocation, - FILETIME& creationTime) const; + void fetchInformationFields(FileWrapper& file, unsigned long& saveNumber, + QString& playerName, unsigned short& playerLevel, + QString& playerLocation, FILETIME& creationTime) const; std::unique_ptr fetchDataFields() const override; }; -#endif // FALLOUT4SAVEGAME_H +#endif // FALLOUT4SAVEGAME_H diff --git a/src/games/fallout4/src/fallout4scriptextender.cpp b/src/games/fallout4/src/fallout4scriptextender.cpp index d40a09ad..1207d5e7 100644 --- a/src/games/fallout4/src/fallout4scriptextender.cpp +++ b/src/games/fallout4/src/fallout4scriptextender.cpp @@ -3,10 +3,9 @@ #include #include -Fallout4ScriptExtender::Fallout4ScriptExtender(GameGamebryo const *game) : - GamebryoScriptExtender(game) -{ -} +Fallout4ScriptExtender::Fallout4ScriptExtender(GameGamebryo const* game) + : GamebryoScriptExtender(game) +{} QString Fallout4ScriptExtender::BinaryName() const { diff --git a/src/games/fallout4/src/fallout4scriptextender.h b/src/games/fallout4/src/fallout4scriptextender.h index 319beb6c..b29df057 100644 --- a/src/games/fallout4/src/fallout4scriptextender.h +++ b/src/games/fallout4/src/fallout4scriptextender.h @@ -8,11 +8,10 @@ class GameGamebryo; class Fallout4ScriptExtender : public GamebryoScriptExtender { public: - Fallout4ScriptExtender(GameGamebryo const *game); + Fallout4ScriptExtender(GameGamebryo const* game); virtual QString BinaryName() const override; virtual QString PluginPath() const override; - }; -#endif // FALLOUT4SCRIPTEXTENDER_H +#endif // FALLOUT4SCRIPTEXTENDER_H diff --git a/src/games/fallout4/src/fallout4unmanagedmods.cpp b/src/games/fallout4/src/fallout4unmanagedmods.cpp index 1d0d314a..61b7b2a8 100644 --- a/src/games/fallout4/src/fallout4unmanagedmods.cpp +++ b/src/games/fallout4/src/fallout4unmanagedmods.cpp @@ -1,27 +1,26 @@ #include "fallout4unmanagedmods.h" - -Fallout4UnmangedMods::Fallout4UnmangedMods(const GameGamebryo *game) - : GamebryoUnmangedMods(game) +Fallout4UnmangedMods::Fallout4UnmangedMods(const GameGamebryo* game) + : GamebryoUnmangedMods(game) {} -Fallout4UnmangedMods::~Fallout4UnmangedMods() -{} +Fallout4UnmangedMods::~Fallout4UnmangedMods() {} -QStringList Fallout4UnmangedMods::mods(bool onlyOfficial) const { +QStringList Fallout4UnmangedMods::mods(bool onlyOfficial) const +{ QStringList result; - QStringList pluginList = game()->primaryPlugins(); + QStringList pluginList = game()->primaryPlugins(); QStringList otherPlugins = game()->DLCPlugins(); otherPlugins.append(game()->CCPlugins()); for (QString plugin : otherPlugins) { pluginList.removeAll(plugin); } QDir dataDir(game()->dataDirectory()); - for (const QString &fileName : dataDir.entryList({ "*.esp", "*.esl", "*.esm" })) { + for (const QString& fileName : dataDir.entryList({"*.esp", "*.esl", "*.esm"})) { if (!pluginList.contains(fileName, Qt::CaseInsensitive)) { if (!onlyOfficial || pluginList.contains(fileName, Qt::CaseInsensitive)) { - result.append(fileName.chopped(4)); // trims the extension off + result.append(fileName.chopped(4)); // trims the extension off } } } @@ -29,17 +28,18 @@ QStringList Fallout4UnmangedMods::mods(bool onlyOfficial) const { return result; } -QStringList Fallout4UnmangedMods::secondaryFiles(const QString &modName) const { +QStringList Fallout4UnmangedMods::secondaryFiles(const QString& modName) const +{ // file extension in FO4 is .ba2 instead of bsa QStringList archives; QDir dataDir = game()->dataDirectory(); - for (const QString &archiveName : dataDir.entryList({modName + "*.ba2"})) { + for (const QString& archiveName : dataDir.entryList({modName + "*.ba2"})) { archives.append(dataDir.absoluteFilePath(archiveName)); } return archives; } -QString Fallout4UnmangedMods::displayName(const QString &modName) const +QString Fallout4UnmangedMods::displayName(const QString& modName) const { // unlike in earlier games, in fallout 4 the file name doesn't correspond to // the public name diff --git a/src/games/fallout4/src/fallout4unmanagedmods.h b/src/games/fallout4/src/fallout4unmanagedmods.h index aaa97e56..6078b73b 100644 --- a/src/games/fallout4/src/fallout4unmanagedmods.h +++ b/src/games/fallout4/src/fallout4unmanagedmods.h @@ -1,21 +1,18 @@ #ifndef FALLOUT4UNMANAGEDMODS_H #define FALLOUT4UNMANAGEDMODS_H - #include "gamebryounmanagedmods.h" #include - -class Fallout4UnmangedMods : public GamebryoUnmangedMods { +class Fallout4UnmangedMods : public GamebryoUnmangedMods +{ public: - Fallout4UnmangedMods(const GameGamebryo *game); + Fallout4UnmangedMods(const GameGamebryo* game); ~Fallout4UnmangedMods(); virtual QStringList mods(bool onlyOfficial) const override; - virtual QStringList secondaryFiles(const QString &modName) const override; - virtual QString displayName(const QString &modName) const override; + virtual QStringList secondaryFiles(const QString& modName) const override; + virtual QString displayName(const QString& modName) const override; }; - - -#endif // FALLOUT4UNMANAGEDMODS_H +#endif // FALLOUT4UNMANAGEDMODS_H diff --git a/src/games/fallout4/src/gamefallout4.cpp b/src/games/fallout4/src/gamefallout4.cpp index cab9b6a6..cf7170ba 100644 --- a/src/games/fallout4/src/gamefallout4.cpp +++ b/src/games/fallout4/src/gamefallout4.cpp @@ -2,18 +2,18 @@ #include "fallout4bsainvalidation.h" #include "fallout4dataarchives.h" -#include "fallout4scriptextender.h" -#include "fallout4unmanagedmods.h" #include "fallout4moddatachecker.h" #include "fallout4moddatacontent.h" #include "fallout4savegame.h" +#include "fallout4scriptextender.h" +#include "fallout4unmanagedmods.h" -#include +#include "versioninfo.h" +#include #include #include #include -#include -#include "versioninfo.h" +#include #include #include @@ -29,11 +29,9 @@ using namespace MOBase; -GameFallout4::GameFallout4() -{ -} +GameFallout4::GameFallout4() {} -bool GameFallout4::init(IOrganizer *moInfo) +bool GameFallout4::init(IOrganizer* moInfo) { if (!GameGamebryo::init(moInfo)) { return false; @@ -43,9 +41,11 @@ bool GameFallout4::init(IOrganizer *moInfo) registerFeature(std::make_shared(this)); registerFeature(dataArchives); - registerFeature(std::make_shared(myGamesPath(), "fallout4custom.ini")); + registerFeature( + std::make_shared(myGamesPath(), "fallout4custom.ini")); registerFeature(std::make_shared(this)); - registerFeature(std::make_shared(m_Organizer->gameFeatures())); + registerFeature( + std::make_shared(m_Organizer->gameFeatures())); registerFeature(std::make_shared(this)); registerFeature(std::make_shared(moInfo)); registerFeature(std::make_shared(this)); @@ -61,19 +61,23 @@ QString GameFallout4::gameName() const void GameFallout4::detectGame() { - m_GamePath = identifyGamePath(); + m_GamePath = identifyGamePath(); m_MyGamesPath = determineMyGamesPath("Fallout4"); } QList GameFallout4::executables() const { return QList() - << ExecutableInfo("F4SE", findInGameFolder(m_Organizer->gameFeatures()->gameFeature()->loaderName())) - << ExecutableInfo("Fallout 4", findInGameFolder(binaryName())) - << ExecutableInfo("Fallout Launcher", findInGameFolder(getLauncherName())) - << ExecutableInfo("Creation Kit", findInGameFolder("CreationKit.exe")).withSteamAppId("1946160") - << ExecutableInfo("LOOT", QFileInfo(getLootPath())).withArgument("--game=\"Fallout4\"") - ; + << ExecutableInfo("F4SE", + findInGameFolder(m_Organizer->gameFeatures() + ->gameFeature() + ->loaderName())) + << ExecutableInfo("Fallout 4", findInGameFolder(binaryName())) + << ExecutableInfo("Fallout Launcher", findInGameFolder(getLauncherName())) + << ExecutableInfo("Creation Kit", findInGameFolder("CreationKit.exe")) + .withSteamAppId("1946160") + << ExecutableInfo("LOOT", QFileInfo(getLootPath())) + .withArgument("--game=\"Fallout4\""); } QList GameFallout4::executableForcedLoads() const @@ -91,7 +95,6 @@ QString GameFallout4::localizedName() const return tr("Fallout 4 Support Plugin"); } - QString GameFallout4::author() const { return "Tannin & MO2 Team"; @@ -100,7 +103,8 @@ QString GameFallout4::author() const QString GameFallout4::description() const { return tr("Adds support for the game Fallout 4.\n" - "Splash by %1").arg("nekoyoubi"); + "Splash by %1") + .arg("nekoyoubi"); } MOBase::VersionInfo GameFallout4::version() const @@ -117,31 +121,32 @@ MappingType GameFallout4::mappings() const { MappingType result; if (testFilePlugins().isEmpty()) { - for (const QString& profileFile : { "plugins.txt", "loadorder.txt" }) { - result.push_back({ m_Organizer->profilePath() + "/" + profileFile, + for (const QString& profileFile : {"plugins.txt", "loadorder.txt"}) { + result.push_back({m_Organizer->profilePath() + "/" + profileFile, localAppFolder() + "/" + gameShortName() + "/" + profileFile, - false }); + false}); } } return result; } -void GameFallout4::initializeProfile(const QDir &path, ProfileSettings settings) const +void GameFallout4::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"); + 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"); + copyToProfile(myGamesPath(), path, "fallout4custom.ini"); } } @@ -155,7 +160,8 @@ QString GameFallout4::savegameSEExtension() const return "f4se"; } -std::shared_ptr GameFallout4::makeSaveGame(QString filePath) const +std::shared_ptr +GameFallout4::makeSaveGame(QString filePath) const { return std::make_shared(filePath, this); } @@ -170,15 +176,15 @@ QStringList GameFallout4::testFilePlugins() const QStringList plugins; if (m_Organizer != nullptr && m_Organizer->profile() != nullptr) { QString customIni( - m_Organizer->profile()->absoluteIniFilePath("Fallout4Custom.ini")); + 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); WCHAR value[MAX_PATH]; DWORD length = ::GetPrivateProfileStringW( - L"General", setting.toStdWString().c_str(), L"", value, MAX_PATH, - customIni.toStdWString().c_str()); + L"General", setting.toStdWString().c_str(), L"", value, MAX_PATH, + customIni.toStdWString().c_str()); if (length && wcscmp(value, L"") != 0) { QString plugin = QString::fromWCharArray(value, length); if (!plugin.isEmpty() && !plugins.contains(plugin)) @@ -209,7 +215,7 @@ QStringList GameFallout4::primaryPlugins() const QStringList GameFallout4::gameVariants() const { - return { "Regular" }; + return {"Regular"}; } QString GameFallout4::gameShortName() const @@ -224,13 +230,18 @@ QString GameFallout4::gameNexusName() const QStringList GameFallout4::iniFiles() const { - return { "fallout4.ini", "fallout4prefs.ini", "fallout4custom.ini" }; + return {"fallout4.ini", "fallout4prefs.ini", "fallout4custom.ini"}; } QStringList GameFallout4::DLCPlugins() const { - return {"dlcrobot.esm", "dlcworkshop01.esm", "dlccoast.esm", "dlcworkshop02.esm", "dlcworkshop03.esm", - "dlcnukaworld.esm", "dlcultrahighresolution.esm"}; + return {"dlcrobot.esm", + "dlcworkshop01.esm", + "dlccoast.esm", + "dlcworkshop02.esm", + "dlcworkshop03.esm", + "dlcnukaworld.esm", + "dlcultrahighresolution.esm"}; } QStringList GameFallout4::CCPlugins() const @@ -238,7 +249,9 @@ QStringList GameFallout4::CCPlugins() const QStringList plugins = {}; QFile file(gameDirectory().absoluteFilePath("Fallout4.ccc")); if (file.open(QIODevice::ReadOnly)) { - ON_BLOCK_EXIT([&file]() { file.close(); }); + ON_BLOCK_EXIT([&file]() { + file.close(); + }); if (file.size() == 0) { return plugins; @@ -310,7 +323,8 @@ QString GameFallout4::shortDescription(unsigned int key) const } } -QString GameFallout4::fullDescription(unsigned int key) const { +QString GameFallout4::fullDescription(unsigned int key) const +{ switch (key) { case PROBLEM_TEST_FILE: { return tr("

You have sTestFile settings in your " @@ -319,4 +333,4 @@ QString GameFallout4::fullDescription(unsigned int key) const { "Management is disabled.

"); } } -} \ No newline at end of file +} diff --git a/src/games/fallout4/src/gamefallout4.h b/src/games/fallout4/src/gamefallout4.h index 4d6be8c3..7fc6271b 100644 --- a/src/games/fallout4/src/gamefallout4.h +++ b/src/games/fallout4/src/gamefallout4.h @@ -1,7 +1,6 @@ #ifndef GAMEFALLOUT4_H #define GAMEFALLOUT4_H - #include "gamegamebryo.h" #include "iplugindiagnose.h" @@ -17,17 +16,19 @@ class GameFallout4 : public GameGamebryo, public MOBase::IPluginDiagnose public: GameFallout4(); - virtual bool init(MOBase::IOrganizer *moInfo) override; + virtual bool init(MOBase::IOrganizer* moInfo) override; public: QStringList testFilePlugins() const; -public: // IPluginGame interface +public: // IPluginGame interface virtual QString gameName() const override; virtual void detectGame() override; virtual QList executables() const override; - virtual QList executableForcedLoads() const override; - virtual void initializeProfile(const QDir &path, ProfileSettings settings) const override; + virtual QList + 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; @@ -40,6 +41,7 @@ public: // IPluginGame interface virtual LoadOrderMechanism loadOrderMechanism() const override; virtual int nexusModOrganizerID() const override; virtual int nexusGameID() const override; + public: // IPluginDiagnose interface virtual std::vector activeProblems() const override; virtual QString shortDescription(unsigned int key) const override; @@ -47,7 +49,7 @@ public: // IPluginDiagnose interface virtual bool hasGuidedFix(unsigned int key) const override { return false; } virtual void startGuidedFix(unsigned int key) const override {} -public: // IPlugin interface +public: // IPlugin interface virtual QString name() const override; virtual QString localizedName() const override; virtual QString author() const override; @@ -68,4 +70,4 @@ private: static const unsigned int PROBLEM_TEST_FILE = 1; }; -#endif // GAMEFallout4_H +#endif // GAMEFallout4_H From a360374f02ad0a26de40fb5d61ad31af10904506 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Mika=C3=ABl=20Capelle?= Date: Sun, 9 Jun 2024 13:12:15 +0200 Subject: [PATCH 1468/1544] [game_fallout4] Add .git-blame-ignore-revs. --- src/games/fallout4/.git-blame-ignore-revs | 1 + 1 file changed, 1 insertion(+) create mode 100644 src/games/fallout4/.git-blame-ignore-revs diff --git a/src/games/fallout4/.git-blame-ignore-revs b/src/games/fallout4/.git-blame-ignore-revs new file mode 100644 index 00000000..f55deb1f --- /dev/null +++ b/src/games/fallout4/.git-blame-ignore-revs @@ -0,0 +1 @@ +ca290eff60953a6c4a395522694b83a92a6052ea From 7b63dfafbbfdfa4801c8a0d97d0eabd6d7b01d16 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Mika=C3=ABl=20Capelle?= Date: Sun, 9 Jun 2024 13:12:30 +0200 Subject: [PATCH 1469/1544] [game_enderalse] Switch to MO2 check-format action. (#10) --- src/games/enderalse/.github/workflows/linting.yml | 9 +++++---- 1 file changed, 5 insertions(+), 4 deletions(-) diff --git a/src/games/enderalse/.github/workflows/linting.yml b/src/games/enderalse/.github/workflows/linting.yml index b457e70e..5bf6a547 100644 --- a/src/games/enderalse/.github/workflows/linting.yml +++ b/src/games/enderalse/.github/workflows/linting.yml @@ -1,15 +1,16 @@ -name: Lint LootCLI +name: Lint Enderal SE Plugin + on: push: pull_request: types: [opened, synchronize, reopened] + jobs: lint: runs-on: ubuntu-latest steps: - uses: actions/checkout@v3 - - name: Run clang-format - uses: jidicula/clang-format-action@v4.11.0 + - name: Check format + uses: ModOrganizer2/check-formatting-action@master with: - clang-format-version: "15" check-path: "." From 67c6311bb9b039ba1074284ddf5d100b1bef28d8 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Mika=C3=ABl=20Capelle?= Date: Sun, 9 Jun 2024 13:18:03 +0200 Subject: [PATCH 1470/1544] [game_fallout4] Add github actions. --- src/games/fallout4/.github/workflows/build.yml | 16 ++++++++++++++++ src/games/fallout4/.github/workflows/linting.yml | 16 ++++++++++++++++ 2 files changed, 32 insertions(+) create mode 100644 src/games/fallout4/.github/workflows/build.yml create mode 100644 src/games/fallout4/.github/workflows/linting.yml diff --git a/src/games/fallout4/.github/workflows/build.yml b/src/games/fallout4/.github/workflows/build.yml new file mode 100644 index 00000000..5581fd57 --- /dev/null +++ b/src/games/fallout4/.github/workflows/build.yml @@ -0,0 +1,16 @@ +name: Build Fallout 4 Plugin + +on: + push: + branches: master + pull_request: + types: [opened, synchronize, reopened] + +jobs: + build: + runs-on: windows-2022 + steps: + - name: Build Fallout 4 Plugin + uses: ModOrganizer2/build-with-mob-action@master + with: + mo2-dependencies: cmake_common uibase game_gamebryo diff --git a/src/games/fallout4/.github/workflows/linting.yml b/src/games/fallout4/.github/workflows/linting.yml new file mode 100644 index 00000000..4ce7ef7b --- /dev/null +++ b/src/games/fallout4/.github/workflows/linting.yml @@ -0,0 +1,16 @@ +name: Lint Fallout 4 Plugin + +on: + push: + pull_request: + types: [opened, synchronize, reopened] + +jobs: + lint: + runs-on: ubuntu-latest + steps: + - uses: actions/checkout@v3 + - name: Check format + uses: ModOrganizer2/check-formatting-action@master + with: + check-path: "." From ea7f533a14ce116b7c2f9d311ade198b92b5ecef Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Mika=C3=ABl=20Capelle?= Date: Sun, 9 Jun 2024 13:26:28 +0200 Subject: [PATCH 1471/1544] [game_fallout4vr] Remove appveyor.yml. --- src/games/fallout4vr/appveyor.yml | 40 ------------------------------- 1 file changed, 40 deletions(-) delete mode 100644 src/games/fallout4vr/appveyor.yml diff --git a/src/games/fallout4vr/appveyor.yml b/src/games/fallout4vr/appveyor.yml deleted file mode 100644 index 2a42ba2a..00000000 --- a/src/games/fallout4vr/appveyor.yml +++ /dev/null @@ -1,40 +0,0 @@ -version: 1.0.{build} -skip_branch_with_pr: true -image: Visual Studio 2019 -environment: - WEBHOOK_URL: - secure: gOKbXaZM9ImtMD5XrYITvdyZUW/az082G9OIN1EC1Vbg57wBaeLhi49uGjxPw5GVujHku6kxN6ab89zhbS5GVeluR76GM83IbKV4Sh7udXzoYZZdg6YudtYHzdhCgUeiedpswbuczTq9ceIkkfSEWZuh/lMAAVVwvcGsJAnoPFw= -build_script: -- pwsh: >- - $ErrorActionPreference = 'Stop' - - git clone --depth=1 --no-single-branch https://github.com/ModOrganizer2/modorganizer-umbrella.git c:\projects\modorganizer-umbrella - - New-Item -ItemType Directory -Path c:\projects\modorganizer-build - - cd c:\projects\modorganizer-umbrella - - ($env:APPVEYOR_PULL_REQUEST_HEAD_REPO_BRANCH -eq $null) ? ($branch = $env:APPVEYOR_REPO_BRANCH) : ($branch = $env:APPVEYOR_PULL_REQUEST_HEAD_REPO_BRANCH) - - git checkout $(git show-ref --verify --quiet refs/remotes/origin/${branch} || echo '-b') ${branch} - - C:\Python37-x64\python.exe unimake.py -d c:\projects\modorganizer-build -s Appveyor_Build=True ${env:APPVEYOR_PROJECT_NAME} - - if($LastExitCode -ne 0) { $host.SetShouldExit($LastExitCode ) } -artifacts: -- path: vsbuild\src\RelWithDebInfo\game_fallout4vr.dll - name: game_fallout4vr_dll -- path: vsbuild\src\RelWithDebInfo\game_fallout4vr.pdb - name: game_fallout4vr_pdb -- path: vsbuild\src\RelWithDebInfo\game_fallout4vr.lib - name: game_fallout4vr_lib -on_success: - - ps: Set-Location -Path $env:APPVEYOR_BUILD_FOLDER - - ps: Invoke-RestMethod https://raw.githubusercontent.com/DiscordHooks/appveyor-discord-webhook/master/send.ps1 -o send.ps1 - - ps: ./send.ps1 success $env:WEBHOOK_URL -on_failure: - - ps: Set-Location -Path $env:APPVEYOR_BUILD_FOLDER - - ps: Push-AppveyorArtifact ${env:APPVEYOR_BUILD_FOLDER}\stdout.log - - ps: Push-AppveyorArtifact ${env:APPVEYOR_BUILD_FOLDER}\stderr.log - - ps: Invoke-RestMethod https://raw.githubusercontent.com/DiscordHooks/appveyor-discord-webhook/master/send.ps1 -o send.ps1 - - ps: ./send.ps1 failure $env:WEBHOOK_URL \ No newline at end of file From 1378da4c3b65349ec53871ee80fd2e55d02d0b8b Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Mika=C3=ABl=20Capelle?= Date: Sun, 9 Jun 2024 13:26:28 +0200 Subject: [PATCH 1472/1544] [game_fallout4vr] Format files and add .gitattributes and .clang-format. --- src/games/fallout4vr/.clang-format | 41 +++++++++++ src/games/fallout4vr/.gitattributes | 7 ++ .../fallout4vr/src/fallout4vrdataarchives.cpp | 51 ++++++------- .../fallout4vr/src/fallout4vrdataarchives.h | 20 ++--- .../fallout4vr/src/fallout4vrgameplugins.cpp | 10 +-- .../fallout4vr/src/fallout4vrgameplugins.h | 9 +-- .../fallout4vr/src/fallout4vrmoddatachecker.h | 23 +++--- .../fallout4vr/src/fallout4vrmoddatacontent.h | 21 +++--- .../fallout4vr/src/fallout4vrsavegame.cpp | 49 ++++++------- src/games/fallout4vr/src/fallout4vrsavegame.h | 15 ++-- .../src/fallout4vrscriptextender.cpp | 7 +- .../fallout4vr/src/fallout4vrscriptextender.h | 5 +- .../src/fallout4vrunmanagedmods.cpp | 24 +++--- .../fallout4vr/src/fallout4vrunmanagedmods.h | 15 ++-- src/games/fallout4vr/src/gamefallout4vr.cpp | 73 +++++++++++-------- src/games/fallout4vr/src/gamefallout4vr.h | 20 ++--- 16 files changed, 214 insertions(+), 176 deletions(-) create mode 100644 src/games/fallout4vr/.clang-format create mode 100644 src/games/fallout4vr/.gitattributes diff --git a/src/games/fallout4vr/.clang-format b/src/games/fallout4vr/.clang-format new file mode 100644 index 00000000..6098e1f5 --- /dev/null +++ b/src/games/fallout4vr/.clang-format @@ -0,0 +1,41 @@ +--- +# We'll use defaults from the LLVM style, but with 4 columns indentation. +BasedOnStyle: LLVM +IndentWidth: 2 +--- +Language: Cpp +DeriveLineEnding: false +UseCRLF: true +DerivePointerAlignment: false +PointerAlignment: Left +AlignConsecutiveAssignments: true +AllowShortFunctionsOnASingleLine: Inline +AllowShortIfStatementsOnASingleLine: Never +AllowShortLambdasOnASingleLine: Empty +AlwaysBreakTemplateDeclarations: Yes +AccessModifierOffset: -2 +AlignTrailingComments: true +SpacesBeforeTrailingComments: 2 +NamespaceIndentation: Inner +MaxEmptyLinesToKeep: 1 +BreakBeforeBraces: Custom +BraceWrapping: + AfterCaseLabel: false + AfterClass: true + AfterControlStatement: false + AfterEnum: true + AfterFunction: true + AfterNamespace: true + AfterStruct: true + AfterUnion: true + AfterExternBlock: true + BeforeCatch: false + BeforeElse: false + BeforeLambdaBody: false + BeforeWhile: false + IndentBraces: false + SplitEmptyFunction: false + SplitEmptyRecord: false + SplitEmptyNamespace: true +ColumnLimit: 88 +ForEachMacros: ['Q_FOREACH', 'foreach'] diff --git a/src/games/fallout4vr/.gitattributes b/src/games/fallout4vr/.gitattributes new file mode 100644 index 00000000..f8697127 --- /dev/null +++ b/src/games/fallout4vr/.gitattributes @@ -0,0 +1,7 @@ +# Set the default behavior, in case people don't have core.autocrlf set. +* text=auto + +# Explicitly declare text files you want to always be normalized and converted +# to native line endings on checkout. +*.cpp text eol=crlf +*.h text eol=crlf diff --git a/src/games/fallout4vr/src/fallout4vrdataarchives.cpp b/src/games/fallout4vr/src/fallout4vrdataarchives.cpp index c43d86b8..b28d8783 100644 --- a/src/games/fallout4vr/src/fallout4vrdataarchives.cpp +++ b/src/games/fallout4vr/src/fallout4vrdataarchives.cpp @@ -3,53 +3,46 @@ #include "iprofile.h" #include -Fallout4VRDataArchives::Fallout4VRDataArchives(const QDir &myGamesDir) : - GamebryoDataArchives(myGamesDir) +Fallout4VRDataArchives::Fallout4VRDataArchives(const QDir& myGamesDir) + : GamebryoDataArchives(myGamesDir) {} QStringList Fallout4VRDataArchives::vanillaArchives() const { - return { "Fallout4 - Textures1.ba2" - , "Fallout4 - Textures2.ba2" - , "Fallout4 - Textures3.ba2" - , "Fallout4 - Textures4.ba2" - , "Fallout4 - Textures5.ba2" - , "Fallout4 - Textures6.ba2" - , "Fallout4 - Textures7.ba2" - , "Fallout4 - Textures8.ba2" - , "Fallout4 - Textures9.ba2" - , "Fallout4 - Meshes.ba2" - , "Fallout4 - MeshesExtra.ba2" - , "Fallout4 - Voices.ba2" - , "Fallout4 - Sounds.ba2" - , "Fallout4 - Interface.ba2" - , "Fallout4 - Animations.ba2" - , "Fallout4 - Materials.ba2" - , "Fallout4 - Shaders.ba2" - , "Fallout4 - Startup.ba2" - , "Fallout4 - Misc.ba2" - , "Fallout4_VR - Main.ba2" - , "Fallout4_VR - Shaders.ba2" - , "Fallout4_VR - Textures.ba2" }; + return {"Fallout4 - Textures1.ba2", "Fallout4 - Textures2.ba2", + "Fallout4 - Textures3.ba2", "Fallout4 - Textures4.ba2", + "Fallout4 - Textures5.ba2", "Fallout4 - Textures6.ba2", + "Fallout4 - Textures7.ba2", "Fallout4 - Textures8.ba2", + "Fallout4 - Textures9.ba2", "Fallout4 - Meshes.ba2", + "Fallout4 - MeshesExtra.ba2", "Fallout4 - Voices.ba2", + "Fallout4 - Sounds.ba2", "Fallout4 - Interface.ba2", + "Fallout4 - Animations.ba2", "Fallout4 - Materials.ba2", + "Fallout4 - Shaders.ba2", "Fallout4 - Startup.ba2", + "Fallout4 - Misc.ba2", "Fallout4_VR - Main.ba2", + "Fallout4_VR - Shaders.ba2", "Fallout4_VR - Textures.ba2"}; } - -QStringList Fallout4VRDataArchives::archives(const MOBase::IProfile *profile) const +QStringList Fallout4VRDataArchives::archives(const MOBase::IProfile* profile) const { QStringList result; - QString iniFile = profile->localSettingsEnabled() ? QDir(profile->absolutePath()).absoluteFilePath("fallout4.ini") : m_LocalGameDir.absoluteFilePath("fallout4.ini"); + QString iniFile = profile->localSettingsEnabled() + ? QDir(profile->absolutePath()).absoluteFilePath("fallout4.ini") + : m_LocalGameDir.absoluteFilePath("fallout4.ini"); result.append(getArchivesFromKey(iniFile, "SResourceArchiveList")); result.append(getArchivesFromKey(iniFile, "SResourceArchiveList2")); return result; } -void Fallout4VRDataArchives::writeArchiveList(MOBase::IProfile *profile, const QStringList &before) +void Fallout4VRDataArchives::writeArchiveList(MOBase::IProfile* profile, + const QStringList& before) { QString list = before.join(", "); - QString iniFile = profile->localSettingsEnabled() ? QDir(profile->absolutePath()).absoluteFilePath("fallout4.ini") : m_LocalGameDir.absoluteFilePath("fallout4.ini"); + QString iniFile = profile->localSettingsEnabled() + ? QDir(profile->absolutePath()).absoluteFilePath("fallout4.ini") + : m_LocalGameDir.absoluteFilePath("fallout4.ini"); if (list.length() > 255) { int splitIdx = list.lastIndexOf(",", 256); setArchivesToKey(iniFile, "SResourceArchiveList", list.mid(0, splitIdx)); diff --git a/src/games/fallout4vr/src/fallout4vrdataarchives.h b/src/games/fallout4vr/src/fallout4vrdataarchives.h index 4f76a003..c7a6b796 100644 --- a/src/games/fallout4vr/src/fallout4vrdataarchives.h +++ b/src/games/fallout4vr/src/fallout4vrdataarchives.h @@ -3,27 +3,27 @@ #include "gamebryodataarchives.h" -namespace MOBase { class IProfile; } +namespace MOBase +{ +class IProfile; +} -#include #include +#include class Fallout4VRDataArchives : public GamebryoDataArchives { public: - - Fallout4VRDataArchives(const QDir &myGamesDir); + Fallout4VRDataArchives(const QDir& myGamesDir); public: - virtual QStringList vanillaArchives() const override; - virtual QStringList archives(const MOBase::IProfile *profile) const override; + virtual QStringList archives(const MOBase::IProfile* profile) const override; private: - - virtual void writeArchiveList(MOBase::IProfile *profile, const QStringList &before) override; - + virtual void writeArchiveList(MOBase::IProfile* profile, + const QStringList& before) override; }; -#endif // Fallout4VRDataArchives_H +#endif // Fallout4VRDataArchives_H diff --git a/src/games/fallout4vr/src/fallout4vrgameplugins.cpp b/src/games/fallout4vr/src/fallout4vrgameplugins.cpp index 8db9e372..187a4410 100644 --- a/src/games/fallout4vr/src/fallout4vrgameplugins.cpp +++ b/src/games/fallout4vr/src/fallout4vrgameplugins.cpp @@ -2,11 +2,11 @@ using namespace MOBase; -Fallout4VRGamePlugins::Fallout4VRGamePlugins(MOBase::IOrganizer* organizer) : CreationGamePlugins(organizer) -{ -} +Fallout4VRGamePlugins::Fallout4VRGamePlugins(MOBase::IOrganizer* organizer) + : CreationGamePlugins(organizer) +{} bool Fallout4VRGamePlugins::lightPluginsAreSupported() { - return false; -} \ No newline at end of file + return false; +} diff --git a/src/games/fallout4vr/src/fallout4vrgameplugins.h b/src/games/fallout4vr/src/fallout4vrgameplugins.h index 1909a844..741378fd 100644 --- a/src/games/fallout4vr/src/fallout4vrgameplugins.h +++ b/src/games/fallout4vr/src/fallout4vrgameplugins.h @@ -10,13 +10,10 @@ class Fallout4VRGamePlugins : public CreationGamePlugins { public: - - Fallout4VRGamePlugins(MOBase::IOrganizer* organizer); + Fallout4VRGamePlugins(MOBase::IOrganizer* organizer); protected: - - virtual bool lightPluginsAreSupported() override; - + virtual bool lightPluginsAreSupported() override; }; -#endif // _FALLOUT4VRGAMEPLUGINS_H \ No newline at end of file +#endif // _FALLOUT4VRGAMEPLUGINS_H diff --git a/src/games/fallout4vr/src/fallout4vrmoddatachecker.h b/src/games/fallout4vr/src/fallout4vrmoddatachecker.h index 8a4b4d8f..4517910d 100644 --- a/src/games/fallout4vr/src/fallout4vrmoddatachecker.h +++ b/src/games/fallout4vr/src/fallout4vrmoddatachecker.h @@ -9,21 +9,22 @@ public: using GamebryoModDataChecker::GamebryoModDataChecker; protected: - virtual const FileNameSet& possibleFolderNames() const override { + virtual const FileNameSet& possibleFolderNames() const override + { static FileNameSet result{ - "interface", "meshes", "music", "scripts", "sound", "strings", "textures", - "trees", "video", "materials", "f4se", "distantlod", "asi", "Tools", "MCM", - "distantland", "mits", "dllplugins", "CalienteTools", "NetScriptFramework", - "shadersfx", "aaf" - }; + "interface", "meshes", "music", "scripts", + "sound", "strings", "textures", "trees", + "video", "materials", "f4se", "distantlod", + "asi", "Tools", "MCM", "distantland", + "mits", "dllplugins", "CalienteTools", "NetScriptFramework", + "shadersfx", "aaf"}; return result; } - virtual const FileNameSet& possibleFileExtensions() const override { - static FileNameSet result{ - "esp", "esm", "ba2", "modgroups", "ini" - }; + virtual const FileNameSet& possibleFileExtensions() const override + { + static FileNameSet result{"esp", "esm", "ba2", "modgroups", "ini"}; return result; } }; -#endif // FALLOUT4VR_MODATACHECKER_H +#endif // FALLOUT4VR_MODATACHECKER_H diff --git a/src/games/fallout4vr/src/fallout4vrmoddatacontent.h b/src/games/fallout4vr/src/fallout4vrmoddatacontent.h index 693d1644..4244a957 100644 --- a/src/games/fallout4vr/src/fallout4vrmoddatacontent.h +++ b/src/games/fallout4vr/src/fallout4vrmoddatacontent.h @@ -4,15 +4,17 @@ #include #include -class Fallout4VRModDataContent : public GamebryoModDataContent { +class Fallout4VRModDataContent : public GamebryoModDataContent +{ protected: - enum Fallout4Content { + enum Fallout4Content + { CONTENT_MATERIAL = CONTENT_NEXT_VALUE }; public: - Fallout4VRModDataContent(MOBase::IGameFeatures const* gameFeatures) : - GamebryoModDataContent(gameFeatures) + Fallout4VRModDataContent(MOBase::IGameFeatures const* gameFeatures) + : GamebryoModDataContent(gameFeatures) { m_Enabled[CONTENT_SKYPROC] = false; } @@ -20,22 +22,23 @@ public: std::vector getAllContents() const override { auto contents = GamebryoModDataContent::getAllContents(); - contents.push_back(Content(CONTENT_MATERIAL, "Materials", ":/MO/gui/content/material")); + contents.push_back( + Content(CONTENT_MATERIAL, "Materials", ":/MO/gui/content/material")); return contents; } - std::vector getContentsFor( - std::shared_ptr fileTree) const override + std::vector + getContentsFor(std::shared_ptr fileTree) const override { auto contents = GamebryoModDataContent::getContentsFor(fileTree); for (auto e : *fileTree) { if (e->compare("materials") == 0) { contents.push_back(CONTENT_MATERIAL); - break; // Early break if you have nothing else to check. + break; // Early break if you have nothing else to check. } } return contents; } }; -#endif // FALLOUT4VR_MODDATACONTENT_H \ No newline at end of file +#endif // FALLOUT4VR_MODDATACONTENT_H diff --git a/src/games/fallout4vr/src/fallout4vrsavegame.cpp b/src/games/fallout4vr/src/fallout4vrsavegame.cpp index 7d6e47f3..ecbf4eb2 100644 --- a/src/games/fallout4vr/src/fallout4vrsavegame.cpp +++ b/src/games/fallout4vr/src/fallout4vrsavegame.cpp @@ -4,17 +4,19 @@ #include "gamefallout4vr.h" -Fallout4VRSaveGame::Fallout4VRSaveGame(QString const &fileName, GameFallout4VR const *game) : - GamebryoSaveGame(fileName, game, true) +Fallout4VRSaveGame::Fallout4VRSaveGame(QString const& fileName, + GameFallout4VR const* game) + : GamebryoSaveGame(fileName, game, true) { FileWrapper file(getFilepath(), "FO4_SAVEGAME"); FILETIME creationTime; - fetchInformationFields(file, m_SaveNumber, m_PCName, m_PCLevel, m_PCLocation, creationTime); + fetchInformationFields(file, m_SaveNumber, m_PCName, m_PCLevel, m_PCLocation, + creationTime); - //A file time is a 64-bit value that represents the number of 100-nanosecond - //intervals that have elapsed since 12:00 A.M. January 1, 1601 Coordinated Universal Time (UTC). - //So we need to convert that to something useful + // A file time is a 64-bit value that represents the number of 100-nanosecond + // intervals that have elapsed since 12:00 A.M. January 1, 1601 Coordinated Universal + // Time (UTC). So we need to convert that to something useful SYSTEMTIME ctime; ::FileTimeToSystemTime(&creationTime, &ctime); @@ -22,15 +24,11 @@ Fallout4VRSaveGame::Fallout4VRSaveGame(QString const &fileName, GameFallout4VR c } void Fallout4VRSaveGame::fetchInformationFields( - FileWrapper& file, - unsigned long& saveNumber, - QString& playerName, - unsigned short& playerLevel, - QString& playerLocation, - FILETIME& creationTime) const + FileWrapper& file, unsigned long& saveNumber, QString& playerName, + unsigned short& playerLevel, QString& playerLocation, FILETIME& creationTime) const { - file.skip(); // header size - file.skip(); // header version + file.skip(); // header size + file.skip(); // header version file.read(saveNumber); file.read(playerName); @@ -41,18 +39,19 @@ void Fallout4VRSaveGame::fetchInformationFields( file.read(playerLocation); QString ignore; - file.read(ignore); // playtime as ascii hh.mm.ss - file.read(ignore); // race name (i.e. BretonRace) + file.read(ignore); // playtime as ascii hh.mm.ss + file.read(ignore); // race name (i.e. BretonRace) - file.skip(); // Player gender (0 = male) - file.skip(2); // experience gathered, experience required + file.skip(); // Player gender (0 = male) + file.skip(2); // experience gathered, experience required file.read(creationTime); } -std::unique_ptr Fallout4VRSaveGame::fetchDataFields() const +std::unique_ptr +Fallout4VRSaveGame::fetchDataFields() const { - FileWrapper file(getFilepath(), "FO4_SAVEGAME"); //10bytes + FileWrapper file(getFilepath(), "FO4_SAVEGAME"); // 10bytes { QString dummyName, dummyLocation; @@ -60,8 +59,8 @@ std::unique_ptr Fallout4VRSaveGame::fetchDataField unsigned long dummySaveNumber; FILETIME dummyTime; - fetchInformationFields(file, dummySaveNumber, dummyName, dummyLevel, - dummyLocation, dummyTime); + fetchInformationFields(file, dummySaveNumber, dummyName, dummyLevel, dummyLocation, + dummyTime); } QString ignore; @@ -70,8 +69,8 @@ std::unique_ptr Fallout4VRSaveGame::fetchDataField fields->Screenshot = file.readImage(384, true); uint8_t saveGameVersion = file.readChar(); - file.read(ignore); // game version - file.skip(); // plugin info size + file.read(ignore); // game version + file.skip(); // plugin info size fields->Plugins = file.readPlugins(); if (saveGameVersion >= 68) { @@ -79,4 +78,4 @@ std::unique_ptr Fallout4VRSaveGame::fetchDataField } return fields; -} \ No newline at end of file +} diff --git a/src/games/fallout4vr/src/fallout4vrsavegame.h b/src/games/fallout4vr/src/fallout4vrsavegame.h index aaa7230d..34de34f3 100644 --- a/src/games/fallout4vr/src/fallout4vrsavegame.h +++ b/src/games/fallout4vr/src/fallout4vrsavegame.h @@ -10,20 +10,15 @@ class GameFallout4VR; class Fallout4VRSaveGame : public GamebryoSaveGame { public: - Fallout4VRSaveGame(QString const &fileName, GameFallout4VR const *game); + Fallout4VRSaveGame(QString const& fileName, GameFallout4VR const* game); protected: - // Fetch easy-to-access information. - void fetchInformationFields( - FileWrapper& file, - unsigned long& saveNumber, - QString& playerName, - unsigned short& playerLevel, - QString& playerLocation, - FILETIME& creationTime) const; + void fetchInformationFields(FileWrapper& file, unsigned long& saveNumber, + QString& playerName, unsigned short& playerLevel, + QString& playerLocation, FILETIME& creationTime) const; std::unique_ptr fetchDataFields() const override; }; -#endif // FALLOUT4VRSAVEGAME_H +#endif // FALLOUT4VRSAVEGAME_H diff --git a/src/games/fallout4vr/src/fallout4vrscriptextender.cpp b/src/games/fallout4vr/src/fallout4vrscriptextender.cpp index 8ae0e1b2..6508c6a8 100644 --- a/src/games/fallout4vr/src/fallout4vrscriptextender.cpp +++ b/src/games/fallout4vr/src/fallout4vrscriptextender.cpp @@ -3,10 +3,9 @@ #include #include -Fallout4VRScriptExtender::Fallout4VRScriptExtender(GameGamebryo const *game) : - GamebryoScriptExtender(game) -{ -} +Fallout4VRScriptExtender::Fallout4VRScriptExtender(GameGamebryo const* game) + : GamebryoScriptExtender(game) +{} QString Fallout4VRScriptExtender::BinaryName() const { diff --git a/src/games/fallout4vr/src/fallout4vrscriptextender.h b/src/games/fallout4vr/src/fallout4vrscriptextender.h index 4d738fce..f7f85879 100644 --- a/src/games/fallout4vr/src/fallout4vrscriptextender.h +++ b/src/games/fallout4vr/src/fallout4vrscriptextender.h @@ -8,11 +8,10 @@ class GameGamebryo; class Fallout4VRScriptExtender : public GamebryoScriptExtender { public: - Fallout4VRScriptExtender(GameGamebryo const *game); + Fallout4VRScriptExtender(GameGamebryo const* game); virtual QString BinaryName() const override; virtual QString PluginPath() const override; - }; -#endif // FALLOUT4SCRIPTEXTENDER_H +#endif // FALLOUT4SCRIPTEXTENDER_H diff --git a/src/games/fallout4vr/src/fallout4vrunmanagedmods.cpp b/src/games/fallout4vr/src/fallout4vrunmanagedmods.cpp index ef9c0e50..a217ef06 100644 --- a/src/games/fallout4vr/src/fallout4vrunmanagedmods.cpp +++ b/src/games/fallout4vr/src/fallout4vrunmanagedmods.cpp @@ -1,27 +1,26 @@ #include "fallout4vrunmanagedmods.h" - -Fallout4VRUnmangedMods::Fallout4VRUnmangedMods(const GameGamebryo *game) - : GamebryoUnmangedMods(game) +Fallout4VRUnmangedMods::Fallout4VRUnmangedMods(const GameGamebryo* game) + : GamebryoUnmangedMods(game) {} -Fallout4VRUnmangedMods::~Fallout4VRUnmangedMods() -{} +Fallout4VRUnmangedMods::~Fallout4VRUnmangedMods() {} -QStringList Fallout4VRUnmangedMods::mods(bool onlyOfficial) const { +QStringList Fallout4VRUnmangedMods::mods(bool onlyOfficial) const +{ QStringList result; - QStringList pluginList = game()->primaryPlugins(); + QStringList pluginList = game()->primaryPlugins(); QStringList otherPlugins = game()->DLCPlugins(); otherPlugins.append(game()->CCPlugins()); for (QString plugin : otherPlugins) { pluginList.removeAll(plugin); } QDir dataDir(game()->dataDirectory()); - for (const QString &fileName : dataDir.entryList({ "*.esp", "*.esl", "*.esm" })) { + for (const QString& fileName : dataDir.entryList({"*.esp", "*.esl", "*.esm"})) { if (!pluginList.contains(fileName, Qt::CaseInsensitive)) { if (!onlyOfficial || pluginList.contains(fileName, Qt::CaseInsensitive)) { - result.append(fileName.chopped(4)); // trims the extension off + result.append(fileName.chopped(4)); // trims the extension off } } } @@ -29,17 +28,18 @@ QStringList Fallout4VRUnmangedMods::mods(bool onlyOfficial) const { return result; } -QStringList Fallout4VRUnmangedMods::secondaryFiles(const QString &modName) const { +QStringList Fallout4VRUnmangedMods::secondaryFiles(const QString& modName) const +{ // file extension in FO4 is .ba2 instead of bsa QStringList archives; QDir dataDir = game()->dataDirectory(); - for (const QString &archiveName : dataDir.entryList({modName + "*.ba2"})) { + for (const QString& archiveName : dataDir.entryList({modName + "*.ba2"})) { archives.append(dataDir.absoluteFilePath(archiveName)); } return archives; } -QString Fallout4VRUnmangedMods::displayName(const QString &modName) const +QString Fallout4VRUnmangedMods::displayName(const QString& modName) const { // unlike in earlier games, in fallout 4 the file name doesn't correspond to // the public name diff --git a/src/games/fallout4vr/src/fallout4vrunmanagedmods.h b/src/games/fallout4vr/src/fallout4vrunmanagedmods.h index 65719490..f0f15fd8 100644 --- a/src/games/fallout4vr/src/fallout4vrunmanagedmods.h +++ b/src/games/fallout4vr/src/fallout4vrunmanagedmods.h @@ -1,21 +1,18 @@ #ifndef FALLOUT4VRUNMANAGEDMODS_H #define FALLOUT4VRUNMANAGEDMODS_H - #include "gamebryounmanagedmods.h" #include - -class Fallout4VRUnmangedMods : public GamebryoUnmangedMods { +class Fallout4VRUnmangedMods : public GamebryoUnmangedMods +{ public: - Fallout4VRUnmangedMods(const GameGamebryo *game); + Fallout4VRUnmangedMods(const GameGamebryo* game); ~Fallout4VRUnmangedMods(); virtual QStringList mods(bool onlyOfficial) const override; - virtual QStringList secondaryFiles(const QString &modName) const override; - virtual QString displayName(const QString &modName) const override; + virtual QStringList secondaryFiles(const QString& modName) const override; + virtual QString displayName(const QString& modName) const override; }; - - -#endif // FALLOUT4UNMANAGEDMODS_H +#endif // FALLOUT4UNMANAGEDMODS_H diff --git a/src/games/fallout4vr/src/gamefallout4vr.cpp b/src/games/fallout4vr/src/gamefallout4vr.cpp index b4217686..7374582a 100644 --- a/src/games/fallout4vr/src/gamefallout4vr.cpp +++ b/src/games/fallout4vr/src/gamefallout4vr.cpp @@ -1,17 +1,17 @@ #include "gameFallout4vr.h" #include "fallout4vrdataarchives.h" -#include "fallout4vrunmanagedmods.h" +#include "fallout4vrgameplugins.h" #include "fallout4vrmoddatachecker.h" #include "fallout4vrmoddatacontent.h" #include "fallout4vrsavegame.h" -#include "fallout4vrgameplugins.h" +#include "fallout4vrunmanagedmods.h" -#include +#include "versioninfo.h" #include #include #include -#include "versioninfo.h" +#include #include #include @@ -27,20 +27,20 @@ using namespace MOBase; -GameFallout4VR::GameFallout4VR() -{ -} +GameFallout4VR::GameFallout4VR() {} -bool GameFallout4VR::init(IOrganizer *moInfo) +bool GameFallout4VR::init(IOrganizer* moInfo) { if (!GameGamebryo::init(moInfo)) { return false; } registerFeature(std::make_shared(myGamesPath())); - registerFeature(std::make_shared(myGamesPath(), "fallout4custom.ini")); + registerFeature( + std::make_shared(myGamesPath(), "fallout4custom.ini")); registerFeature(std::make_shared(this)); - registerFeature(std::make_shared(m_Organizer->gameFeatures())); + registerFeature( + std::make_shared(m_Organizer->gameFeatures())); registerFeature(std::make_shared(this)); registerFeature(std::make_shared(moInfo)); registerFeature(std::make_shared(this)); @@ -55,17 +55,17 @@ QString GameFallout4VR::gameName() const void GameFallout4VR::detectGame() { - m_GamePath = identifyGamePath(); + m_GamePath = identifyGamePath(); m_MyGamesPath = determineMyGamesPath("Fallout4VR"); } QList GameFallout4VR::executables() const { return QList() - << ExecutableInfo("Fallout 4 VR", findInGameFolder(binaryName())) - << ExecutableInfo("Creation Kit", findInGameFolder("CreationKit.exe")) - << ExecutableInfo("LOOT", QFileInfo(getLootPath())).withArgument("--game=\"Fallout4VR\"") - ; + << ExecutableInfo("Fallout 4 VR", findInGameFolder(binaryName())) + << ExecutableInfo("Creation Kit", findInGameFolder("CreationKit.exe")) + << ExecutableInfo("LOOT", QFileInfo(getLootPath())) + .withArgument("--game=\"Fallout4VR\""); } QList GameFallout4VR::executableForcedLoads() const @@ -83,7 +83,6 @@ QString GameFallout4VR::localizedName() const return tr("Fallout 4 VR Support Plugin"); } - QString GameFallout4VR::author() const { return "MO2 Contibutors"; @@ -92,7 +91,8 @@ QString GameFallout4VR::author() const QString GameFallout4VR::description() const { return tr("Adds support for the game Fallout 4 VR.\n" - "Splash by %1").arg("nekoyoubi"); + "Splash by %1") + .arg("nekoyoubi"); } MOBase::VersionInfo GameFallout4VR::version() const @@ -105,15 +105,15 @@ QList GameFallout4VR::settings() const return QList(); } -void GameFallout4VR::initializeProfile(const QDir &path, ProfileSettings settings) const +void GameFallout4VR::initializeProfile(const QDir& path, ProfileSettings settings) const { if (settings.testFlag(IPluginGame::MODS)) { copyToProfile(localAppFolder() + "/Fallout4VR", path, "plugins.txt"); } if (settings.testFlag(IPluginGame::CONFIGURATION)) { - if (settings.testFlag(IPluginGame::PREFER_DEFAULTS) - || !QFileInfo(myGamesPath() + "/fallout4.ini").exists()) { + if (settings.testFlag(IPluginGame::PREFER_DEFAULTS) || + !QFileInfo(myGamesPath() + "/fallout4.ini").exists()) { copyToProfile(gameDirectory().absolutePath(), path, "fallout4.ini"); } else { copyToProfile(myGamesPath(), path, "fallout4.ini"); @@ -134,7 +134,8 @@ QString GameFallout4VR::savegameSEExtension() const return "f4se"; } -std::shared_ptr GameFallout4VR::makeSaveGame(QString filePath) const +std::shared_ptr +GameFallout4VR::makeSaveGame(QString filePath) const { return std::make_shared(filePath, this); } @@ -144,7 +145,8 @@ QString GameFallout4VR::steamAPPId() const return "611660"; } -QStringList GameFallout4VR::primaryPlugins() const { +QStringList GameFallout4VR::primaryPlugins() const +{ QStringList plugins = {"fallout4.esm", "fallout4_vr.esm"}; plugins.append(CCPlugins()); @@ -154,7 +156,7 @@ QStringList GameFallout4VR::primaryPlugins() const { QStringList GameFallout4VR::gameVariants() const { - return { "Regular" }; + return {"Regular"}; } QString GameFallout4VR::gameShortName() const @@ -164,7 +166,7 @@ QString GameFallout4VR::gameShortName() const QStringList GameFallout4VR::validShortNames() const { - return { "Fallout4" }; + return {"Fallout4"}; } QString GameFallout4VR::gameNexusName() const @@ -174,13 +176,18 @@ QString GameFallout4VR::gameNexusName() const QStringList GameFallout4VR::iniFiles() const { - return { "fallout4.ini", "fallout4custom.ini", "fallout4prefs.ini" }; + return {"fallout4.ini", "fallout4custom.ini", "fallout4prefs.ini"}; } QStringList GameFallout4VR::DLCPlugins() const { - return {"dlcrobot.esm", "dlcworkshop01.esm", "dlccoast.esm", "dlcworkshop02.esm", "dlcworkshop03.esm", - "dlcnukaworld.esm", "dlcultrahighresolution.esm"}; + return {"dlcrobot.esm", + "dlcworkshop01.esm", + "dlccoast.esm", + "dlcworkshop02.esm", + "dlcworkshop03.esm", + "dlcnukaworld.esm", + "dlcultrahighresolution.esm"}; } QStringList GameFallout4VR::CCPlugins() const @@ -188,7 +195,9 @@ QStringList GameFallout4VR::CCPlugins() const QStringList plugins = {}; QFile file(gameDirectory().absoluteFilePath("Fallout4.ccc")); if (file.open(QIODevice::ReadOnly)) { - ON_BLOCK_EXIT([&file]() { file.close(); }); + ON_BLOCK_EXIT([&file]() { + file.close(); + }); if (file.size() == 0) { return plugins; @@ -217,7 +226,7 @@ IPluginGame::LoadOrderMechanism GameFallout4VR::loadOrderMechanism() const int GameFallout4VR::nexusModOrganizerID() const { - return 0; //... + return 0; //... } int GameFallout4VR::nexusGameID() const @@ -227,11 +236,13 @@ int GameFallout4VR::nexusGameID() const QString GameFallout4VR::getLauncherName() const { - return binaryName(); // Fallout 4 VR has no Launcher, so we just return the name of the game binary + return binaryName(); // Fallout 4 VR has no Launcher, so we just return the name of + // the game binary } QString GameFallout4VR::identifyGamePath() const { QString path = "Software\\Bethesda Softworks\\" + gameName(); - return findInRegistry(HKEY_LOCAL_MACHINE, path.toStdWString().c_str(), L"Installed Path"); + return findInRegistry(HKEY_LOCAL_MACHINE, path.toStdWString().c_str(), + L"Installed Path"); } diff --git a/src/games/fallout4vr/src/gamefallout4vr.h b/src/games/fallout4vr/src/gamefallout4vr.h index 6904cff7..acd90d16 100644 --- a/src/games/fallout4vr/src/gamefallout4vr.h +++ b/src/games/fallout4vr/src/gamefallout4vr.h @@ -1,7 +1,6 @@ #ifndef GAMEFALLOUT4VR_H #define GAMEFALLOUT4VR_H - #include "gamegamebryo.h" #include @@ -14,18 +13,18 @@ class GameFallout4VR : public GameGamebryo Q_PLUGIN_METADATA(IID "org.tannin.GameFallout4VR" FILE "gamefallout4vr.json") public: - GameFallout4VR(); - virtual bool init(MOBase::IOrganizer *moInfo) override; - -public: // IPluginGame interface + virtual bool init(MOBase::IOrganizer* moInfo) override; +public: // IPluginGame interface virtual QString gameName() const override; virtual void detectGame() override; virtual QList executables() const override; - virtual QList executableForcedLoads() const override; - virtual void initializeProfile(const QDir &path, ProfileSettings settings) const override; + virtual QList + 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; @@ -41,8 +40,7 @@ public: // IPluginGame interface virtual int nexusGameID() const override; virtual QString getLauncherName() const override; -public: // IPlugin interface - +public: // IPlugin interface virtual QString name() const override; virtual QString localizedName() const override; virtual QString author() const override; @@ -51,13 +49,11 @@ public: // IPlugin interface virtual QList settings() const override; protected: - std::shared_ptr makeSaveGame(QString filePath) const override; QString savegameExtension() const override; QString savegameSEExtension() const override; virtual QString identifyGamePath() const override; - }; -#endif // GAMEFallout4VR_H +#endif // GAMEFallout4VR_H From e5cc7025a500bf8333c14ab4f8449e95f7a19e73 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Mika=C3=ABl=20Capelle?= Date: Sun, 9 Jun 2024 13:26:29 +0200 Subject: [PATCH 1473/1544] [game_fallout4vr] Add .git-blame-ignore-revs. --- src/games/fallout4vr/.git-blame-ignore-revs | 1 + 1 file changed, 1 insertion(+) create mode 100644 src/games/fallout4vr/.git-blame-ignore-revs diff --git a/src/games/fallout4vr/.git-blame-ignore-revs b/src/games/fallout4vr/.git-blame-ignore-revs new file mode 100644 index 00000000..262e4444 --- /dev/null +++ b/src/games/fallout4vr/.git-blame-ignore-revs @@ -0,0 +1 @@ +a5e8ea30c8c922a80c169231489ce6fd29e0dce0 From 576f61dcf56fd0827c2fb0fba1d5137099a145ee Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Mika=C3=ABl=20Capelle?= Date: Sun, 9 Jun 2024 13:26:29 +0200 Subject: [PATCH 1474/1544] [game_fallout4vr] Add github actions. --- src/games/fallout4vr/.github/workflows/build.yml | 16 ++++++++++++++++ .../fallout4vr/.github/workflows/linting.yml | 16 ++++++++++++++++ 2 files changed, 32 insertions(+) create mode 100644 src/games/fallout4vr/.github/workflows/build.yml create mode 100644 src/games/fallout4vr/.github/workflows/linting.yml diff --git a/src/games/fallout4vr/.github/workflows/build.yml b/src/games/fallout4vr/.github/workflows/build.yml new file mode 100644 index 00000000..0a68c9fa --- /dev/null +++ b/src/games/fallout4vr/.github/workflows/build.yml @@ -0,0 +1,16 @@ +name: Build Fallout 4 VR Plugin + +on: + push: + branches: master + pull_request: + types: [opened, synchronize, reopened] + +jobs: + build: + runs-on: windows-2022 + steps: + - name: Build Fallout 4 VR Plugin + uses: ModOrganizer2/build-with-mob-action@master + with: + mo2-dependencies: cmake_common uibase game_gamebryo diff --git a/src/games/fallout4vr/.github/workflows/linting.yml b/src/games/fallout4vr/.github/workflows/linting.yml new file mode 100644 index 00000000..9fb6ebef --- /dev/null +++ b/src/games/fallout4vr/.github/workflows/linting.yml @@ -0,0 +1,16 @@ +name: Lint Fallout 4 VR Plugin + +on: + push: + pull_request: + types: [opened, synchronize, reopened] + +jobs: + lint: + runs-on: ubuntu-latest + steps: + - uses: actions/checkout@v3 + - name: Check format + uses: ModOrganizer2/check-formatting-action@master + with: + check-path: "." From 55599116eb395584cbd9c3218fcabd6a6f03fae6 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Mika=C3=ABl=20Capelle?= Date: Sun, 9 Jun 2024 13:27:34 +0200 Subject: [PATCH 1475/1544] [game_fallout76] Format files and add .gitattributes and .clang-format. --- src/games/fallout76/.clang-format | 41 +++++ src/games/fallout76/.gitattributes | 7 + .../fallout76/src/fallout76dataarchives.cpp | 165 +++++++++--------- .../fallout76/src/fallout76dataarchives.h | 20 +-- .../fallout76/src/fallout76moddatachecker.h | 23 +-- .../fallout76/src/fallout76moddatacontent.h | 21 ++- src/games/fallout76/src/fallout76savegame.cpp | 48 ++--- src/games/fallout76/src/fallout76savegame.h | 14 +- .../fallout76/src/fallout76savegameinfo.cpp | 11 +- .../fallout76/src/fallout76savegameinfo.h | 4 +- .../fallout76/src/fallout76scriptextender.cpp | 7 +- .../fallout76/src/fallout76scriptextender.h | 4 +- .../fallout76/src/fallout76unmanagedmods.cpp | 22 +-- .../fallout76/src/fallout76unmanagedmods.h | 15 +- src/games/fallout76/src/gamefallout76.cpp | 63 ++++--- src/games/fallout76/src/gamefallout76.h | 17 +- 16 files changed, 268 insertions(+), 214 deletions(-) create mode 100644 src/games/fallout76/.clang-format create mode 100644 src/games/fallout76/.gitattributes diff --git a/src/games/fallout76/.clang-format b/src/games/fallout76/.clang-format new file mode 100644 index 00000000..6098e1f5 --- /dev/null +++ b/src/games/fallout76/.clang-format @@ -0,0 +1,41 @@ +--- +# We'll use defaults from the LLVM style, but with 4 columns indentation. +BasedOnStyle: LLVM +IndentWidth: 2 +--- +Language: Cpp +DeriveLineEnding: false +UseCRLF: true +DerivePointerAlignment: false +PointerAlignment: Left +AlignConsecutiveAssignments: true +AllowShortFunctionsOnASingleLine: Inline +AllowShortIfStatementsOnASingleLine: Never +AllowShortLambdasOnASingleLine: Empty +AlwaysBreakTemplateDeclarations: Yes +AccessModifierOffset: -2 +AlignTrailingComments: true +SpacesBeforeTrailingComments: 2 +NamespaceIndentation: Inner +MaxEmptyLinesToKeep: 1 +BreakBeforeBraces: Custom +BraceWrapping: + AfterCaseLabel: false + AfterClass: true + AfterControlStatement: false + AfterEnum: true + AfterFunction: true + AfterNamespace: true + AfterStruct: true + AfterUnion: true + AfterExternBlock: true + BeforeCatch: false + BeforeElse: false + BeforeLambdaBody: false + BeforeWhile: false + IndentBraces: false + SplitEmptyFunction: false + SplitEmptyRecord: false + SplitEmptyNamespace: true +ColumnLimit: 88 +ForEachMacros: ['Q_FOREACH', 'foreach'] diff --git a/src/games/fallout76/.gitattributes b/src/games/fallout76/.gitattributes new file mode 100644 index 00000000..f8697127 --- /dev/null +++ b/src/games/fallout76/.gitattributes @@ -0,0 +1,7 @@ +# Set the default behavior, in case people don't have core.autocrlf set. +* text=auto + +# Explicitly declare text files you want to always be normalized and converted +# to native line endings on checkout. +*.cpp text eol=crlf +*.h text eol=crlf diff --git a/src/games/fallout76/src/fallout76dataarchives.cpp b/src/games/fallout76/src/fallout76dataarchives.cpp index 3148f034..d9bff8dc 100644 --- a/src/games/fallout76/src/fallout76dataarchives.cpp +++ b/src/games/fallout76/src/fallout76dataarchives.cpp @@ -5,96 +5,88 @@ #include -Fallout76DataArchives::Fallout76DataArchives(const QDir &myGamesDir) : - GamebryoDataArchives(myGamesDir) +Fallout76DataArchives::Fallout76DataArchives(const QDir& myGamesDir) + : GamebryoDataArchives(myGamesDir) {} QStringList Fallout76DataArchives::vanillaArchives() const { - return { "SeventySix - Animations.ba2" - , "SeventySix - ATX_Main.ba2" - , "SeventySix - ATX_Textures.ba2" - , "SeventySix - EnlightenExteriors01.ba2" - , "SeventySix - EnlightenExteriors02.ba2" - , "SeventySix - EnlightenInteriors.ba2" - , "SeventySix - GeneratedMeshes.ba2" - , "SeventySix - GeneratedTextures.ba2" - , "SeventySix - Interface.ba2" - , "SeventySix - Localization.ba2" - , "SeventySix - Materials.ba2" - , "SeventySix - Meshes01.ba2" - , "SeventySix - Meshes02.ba2" - , "SeventySix - MeshesExtra.ba2" - , "SeventySix - MiscClient.ba2" - , "SeventySix - Shaders.ba2" - , "SeventySix - Sounds01.ba2" - , "SeventySix - Sounds02.ba2" - , "SeventySix - Startup.ba2" - , "SeventySix - Textures01.ba2" - , "SeventySix - Textures02.ba2" - , "SeventySix - Textures03.ba2" - , "SeventySix - Textures04.ba2" - , "SeventySix - Textures05.ba2" - , "SeventySix - Textures06.ba2" - , "SeventySix - Voices.ba2" }; + return {"SeventySix - Animations.ba2", + "SeventySix - ATX_Main.ba2", + "SeventySix - ATX_Textures.ba2", + "SeventySix - EnlightenExteriors01.ba2", + "SeventySix - EnlightenExteriors02.ba2", + "SeventySix - EnlightenInteriors.ba2", + "SeventySix - GeneratedMeshes.ba2", + "SeventySix - GeneratedTextures.ba2", + "SeventySix - Interface.ba2", + "SeventySix - Localization.ba2", + "SeventySix - Materials.ba2", + "SeventySix - Meshes01.ba2", + "SeventySix - Meshes02.ba2", + "SeventySix - MeshesExtra.ba2", + "SeventySix - MiscClient.ba2", + "SeventySix - Shaders.ba2", + "SeventySix - Sounds01.ba2", + "SeventySix - Sounds02.ba2", + "SeventySix - Startup.ba2", + "SeventySix - Textures01.ba2", + "SeventySix - Textures02.ba2", + "SeventySix - Textures03.ba2", + "SeventySix - Textures04.ba2", + "SeventySix - Textures05.ba2", + "SeventySix - Textures06.ba2", + "SeventySix - Voices.ba2"}; } QStringList Fallout76DataArchives::sResourceIndexFileList() const { - return { "SeventySix - Textures01.ba2" - , "SeventySix - Textures02.ba2" - , "SeventySix - Textures03.ba2" - , "SeventySix - Textures04.ba2" - , "SeventySix - Textures05.ba2" - , "SeventySix - Textures06.ba2" }; + return {"SeventySix - Textures01.ba2", "SeventySix - Textures02.ba2", + "SeventySix - Textures03.ba2", "SeventySix - Textures04.ba2", + "SeventySix - Textures05.ba2", "SeventySix - Textures06.ba2"}; } QStringList Fallout76DataArchives::sResourceStartUpArchiveList() const { - return { "SeventySix - Interface.ba2" - , "SeventySix - Localization.ba2" - , "SeventySix - Shaders.ba2" - , "SeventySix - Startup.ba2" }; + return {"SeventySix - Interface.ba2", "SeventySix - Localization.ba2", + "SeventySix - Shaders.ba2", "SeventySix - Startup.ba2"}; } -QStringList Fallout76DataArchives::SResourceArchiveMemoryCacheList() const { - return { "SeventySix - Interface.ba2" - , "SeventySix - Materials.ba2" - , "SeventySix - MiscClient.ba2" - , "SeventySix - Shaders.ba2" }; +QStringList Fallout76DataArchives::SResourceArchiveMemoryCacheList() const +{ + return {"SeventySix - Interface.ba2", "SeventySix - Materials.ba2", + "SeventySix - MiscClient.ba2", "SeventySix - Shaders.ba2"}; } -QStringList Fallout76DataArchives::SResourceArchiveList() const { - return { "SeventySix - GeneratedMeshes.ba2" - , "SeventySix - Materials.ba2" - , "SeventySix - Meshes01.ba2" - , "SeventySix - Meshes02.ba2" - , "SeventySix - MeshesExtra.ba2" - , "SeventySix - MiscClient.ba2" - , "SeventySix - Sounds01.ba2" - , "SeventySix - Sounds02.ba2" - , "SeventySix - Startup.ba2" - , "SeventySix - Voices.ba2" }; +QStringList Fallout76DataArchives::SResourceArchiveList() const +{ + return {"SeventySix - GeneratedMeshes.ba2", "SeventySix - Materials.ba2", + "SeventySix - Meshes01.ba2", "SeventySix - Meshes02.ba2", + "SeventySix - MeshesExtra.ba2", "SeventySix - MiscClient.ba2", + "SeventySix - Sounds01.ba2", "SeventySix - Sounds02.ba2", + "SeventySix - Startup.ba2", "SeventySix - Voices.ba2"}; } -QStringList Fallout76DataArchives::SResourceArchiveList2() const { - return { "SeventySix - Animations.ba2" - , "SeventySix - EnlightenInteriors.ba2" - , "SeventySix - GeneratedTextures.ba2" - , "SeventySix - EnlightenExteriors01.ba2" - , "SeventySix - EnlightenExteriors02.ba2" }; +QStringList Fallout76DataArchives::SResourceArchiveList2() const +{ + return {"SeventySix - Animations.ba2", "SeventySix - EnlightenInteriors.ba2", + "SeventySix - GeneratedTextures.ba2", "SeventySix - EnlightenExteriors01.ba2", + "SeventySix - EnlightenExteriors02.ba2"}; } -QStringList Fallout76DataArchives::sResourceArchive2List() const { - return { "SeventySix - ATX_Main.ba2" - , "SeventySix - ATX_Textures.ba2" }; +QStringList Fallout76DataArchives::sResourceArchive2List() const +{ + return {"SeventySix - ATX_Main.ba2", "SeventySix - ATX_Textures.ba2"}; } -QStringList Fallout76DataArchives::archives(const MOBase::IProfile *profile) const +QStringList Fallout76DataArchives::archives(const MOBase::IProfile* profile) const { QStringList result; - QString iniFile = profile->localSettingsEnabled() ? QDir(profile->absolutePath()).absoluteFilePath("Fallout76.ini") : m_LocalGameDir.absoluteFilePath("Fallout76.ini"); + QString iniFile = + profile->localSettingsEnabled() + ? QDir(profile->absolutePath()).absoluteFilePath("Fallout76.ini") + : m_LocalGameDir.absoluteFilePath("Fallout76.ini"); result.append(getArchivesFromKey(iniFile, "sResourceIndexFileList")); result.append(getArchivesFromKey(iniFile, "sResourceStartUpArchiveList")); @@ -106,28 +98,40 @@ QStringList Fallout76DataArchives::archives(const MOBase::IProfile *profile) con return result; } -void Fallout76DataArchives::writeArchiveList(MOBase::IProfile *profile, const QStringList &before) +void Fallout76DataArchives::writeArchiveList(MOBase::IProfile* profile, + const QStringList& before) { - QString iniFile = profile->localSettingsEnabled() ? QDir(profile->absolutePath()).absoluteFilePath("Fallout76.ini") : m_LocalGameDir.absoluteFilePath("Fallout76.ini"); + QString iniFile = + profile->localSettingsEnabled() + ? QDir(profile->absolutePath()).absoluteFilePath("Fallout76.ini") + : m_LocalGameDir.absoluteFilePath("Fallout76.ini"); - QStringList sResourceIndexFileList = {}; - QStringList sResourceStartUpArchiveList = {}; + QStringList sResourceIndexFileList = {}; + QStringList sResourceStartUpArchiveList = {}; QStringList SResourceArchiveMemoryCacheList = {}; - QStringList SResourceArchiveList = {}; - QStringList SResourceArchiveList2 = {}; - QStringList sResourceArchive2List = {}; + QStringList SResourceArchiveList = {}; + QStringList SResourceArchiveList2 = {}; + QStringList sResourceArchive2List = {}; for (int i = 0; i < before.size(); ++i) { QString archive = before[i]; if (archive.contains(QRegularExpression(" - Textures(\\d{2})\\.ba2$"))) { sResourceIndexFileList.append(archive); - } else if (archive.contains(QRegularExpression(" - (Interface|Localization|Shaders|Startup)\\.ba2$"))) { + } else if (archive.contains(QRegularExpression( + " - (Interface|Localization|Shaders|Startup)\\.ba2$"))) { sResourceStartUpArchiveList.append(archive); - } else if (archive.contains(QRegularExpression(" - (Interface|Materials|MiscClient|Shaders)\\.ba2$"))) { + } else if (archive.contains(QRegularExpression( + " - (Interface|Materials|MiscClient|Shaders)\\.ba2$"))) { SResourceArchiveMemoryCacheList.append(archive); - } else if (archive.contains(QRegularExpression(" - (GeneratedMeshes|Materials|Meshes(\\d{2}|\\w+)?|MiscClient|Sounds\\d{2}|Startup|Voices)\\.ba2$"))) { + } else if (archive.contains(QRegularExpression( + " - " + "(GeneratedMeshes|Materials|Meshes(\\d{2}|\\w+)?|MiscClient|" + "Sounds\\d{2}|Startup|Voices)\\.ba2$"))) { SResourceArchiveList.append(archive); - } else if (archive.contains(QRegularExpression(" - (Animations|Enlighten(Interiors|Exteriors\\d{2})|GeneratedTextures)\\.ba2$"))) { + } else if (archive.contains( + QRegularExpression(" - " + "(Animations|Enlighten(Interiors|Exteriors\\d{2})" + "|GeneratedTextures)\\.ba2$"))) { SResourceArchiveList2.append(archive); } else if (archive.contains(QRegularExpression(" - ATX_.*\\.ba2$"))) { // if it is named after DLC, it has to go here @@ -138,9 +142,12 @@ void Fallout76DataArchives::writeArchiveList(MOBase::IProfile *profile, const QS } } - setArchivesToKey(iniFile, "sResourceIndexFileList", sResourceIndexFileList.join(", ")); - setArchivesToKey(iniFile, "sResourceStartUpArchiveList", sResourceStartUpArchiveList.join(", ")); - setArchivesToKey(iniFile, "SResourceArchiveMemoryCacheList", SResourceArchiveMemoryCacheList.join(", ")); + setArchivesToKey(iniFile, "sResourceIndexFileList", + sResourceIndexFileList.join(", ")); + setArchivesToKey(iniFile, "sResourceStartUpArchiveList", + sResourceStartUpArchiveList.join(", ")); + setArchivesToKey(iniFile, "SResourceArchiveMemoryCacheList", + SResourceArchiveMemoryCacheList.join(", ")); setArchivesToKey(iniFile, "SResourceArchiveList", SResourceArchiveList.join(", ")); setArchivesToKey(iniFile, "SResourceArchiveList2", SResourceArchiveList2.join(", ")); setArchivesToKey(iniFile, "sResourceArchive2List", sResourceArchive2List.join(", ")); diff --git a/src/games/fallout76/src/fallout76dataarchives.h b/src/games/fallout76/src/fallout76dataarchives.h index 93fc5a3e..b507d281 100644 --- a/src/games/fallout76/src/fallout76dataarchives.h +++ b/src/games/fallout76/src/fallout76dataarchives.h @@ -3,20 +3,21 @@ #include "gamebryodataarchives.h" -namespace MOBase { class IProfile; } +namespace MOBase +{ +class IProfile; +} -#include #include +#include class Fallout76DataArchives : public GamebryoDataArchives { public: - - Fallout76DataArchives(const QDir &myGamesDir); + Fallout76DataArchives(const QDir& myGamesDir); public: - virtual QStringList vanillaArchives() const override; virtual QStringList sResourceIndexFileList() const; virtual QStringList sResourceStartUpArchiveList() const; @@ -24,12 +25,11 @@ public: virtual QStringList SResourceArchiveList() const; virtual QStringList SResourceArchiveList2() const; virtual QStringList sResourceArchive2List() const; - virtual QStringList archives(const MOBase::IProfile *profile) const override; + virtual QStringList archives(const MOBase::IProfile* profile) const override; private: - - virtual void writeArchiveList(MOBase::IProfile *profile, const QStringList &before) override; - + virtual void writeArchiveList(MOBase::IProfile* profile, + const QStringList& before) override; }; -#endif // FALLOUT76DATAARCHIVES_H +#endif // FALLOUT76DATAARCHIVES_H diff --git a/src/games/fallout76/src/fallout76moddatachecker.h b/src/games/fallout76/src/fallout76moddatachecker.h index 3fd1730b..4ccf6f31 100644 --- a/src/games/fallout76/src/fallout76moddatachecker.h +++ b/src/games/fallout76/src/fallout76moddatachecker.h @@ -9,21 +9,22 @@ public: using GamebryoModDataChecker::GamebryoModDataChecker; protected: - virtual const FileNameSet& possibleFolderNames() const override { + virtual const FileNameSet& possibleFolderNames() const override + { static FileNameSet result{ - "interface", "meshes", "music", "scripts", "sound", "strings", "textures", - "trees", "video", "materials", "f4se", "distantlod", "asi", "Tools", "MCM", - "distantland", "mits", "dllplugins", "CalienteTools", "NetScriptFramework", - "shadersfx", "aaf" - }; + "interface", "meshes", "music", "scripts", + "sound", "strings", "textures", "trees", + "video", "materials", "f4se", "distantlod", + "asi", "Tools", "MCM", "distantland", + "mits", "dllplugins", "CalienteTools", "NetScriptFramework", + "shadersfx", "aaf"}; return result; } - virtual const FileNameSet& possibleFileExtensions() const override { - static FileNameSet result{ - "esp", "esm", "esl", "ba2", "modgroups" - }; + virtual const FileNameSet& possibleFileExtensions() const override + { + static FileNameSet result{"esp", "esm", "esl", "ba2", "modgroups"}; return result; } }; -#endif // FALLOUT4_MODATACHECKER_H +#endif // FALLOUT4_MODATACHECKER_H diff --git a/src/games/fallout76/src/fallout76moddatacontent.h b/src/games/fallout76/src/fallout76moddatacontent.h index 39129274..54ba419f 100644 --- a/src/games/fallout76/src/fallout76moddatacontent.h +++ b/src/games/fallout76/src/fallout76moddatacontent.h @@ -4,15 +4,17 @@ #include #include -class Fallout76ModDataContent : public GamebryoModDataContent { +class Fallout76ModDataContent : public GamebryoModDataContent +{ protected: - enum Fallout4Content { + enum Fallout4Content + { CONTENT_MATERIAL = CONTENT_NEXT_VALUE }; public: - Fallout76ModDataContent(MOBase::IGameFeatures const* gameFeatures) : - GamebryoModDataContent(gameFeatures) + Fallout76ModDataContent(MOBase::IGameFeatures const* gameFeatures) + : GamebryoModDataContent(gameFeatures) { m_Enabled[CONTENT_SKYPROC] = false; } @@ -20,22 +22,23 @@ public: std::vector getAllContents() const override { auto contents = GamebryoModDataContent::getAllContents(); - contents.push_back(Content(CONTENT_MATERIAL, "Materials", ":/MO/gui/content/material")); + contents.push_back( + Content(CONTENT_MATERIAL, "Materials", ":/MO/gui/content/material")); return contents; } - std::vector getContentsFor( - std::shared_ptr fileTree) const override + std::vector + getContentsFor(std::shared_ptr fileTree) const override { auto contents = GamebryoModDataContent::getContentsFor(fileTree); for (auto e : *fileTree) { if (e->compare("materials") == 0) { contents.push_back(CONTENT_MATERIAL); - break; // Early break if you have nothing else to check. + break; // Early break if you have nothing else to check. } } return contents; } }; -#endif // FALLOUT4_MODDATACONTENT_H \ No newline at end of file +#endif // FALLOUT4_MODDATACONTENT_H diff --git a/src/games/fallout76/src/fallout76savegame.cpp b/src/games/fallout76/src/fallout76savegame.cpp index ee332747..bdda883c 100644 --- a/src/games/fallout76/src/fallout76savegame.cpp +++ b/src/games/fallout76/src/fallout76savegame.cpp @@ -2,32 +2,32 @@ #include "gamefallout76.h" -Fallout76SaveGame::Fallout76SaveGame(QString const& fileName, GameFallout76 const* game) : - GamebryoSaveGame(fileName, game, true) +Fallout76SaveGame::Fallout76SaveGame(QString const& fileName, GameFallout76 const* game) + : GamebryoSaveGame(fileName, game, true) { FileWrapper file(fileName, "FO76_SAVEGAME"); FILETIME ftime; fetchInformationFields(file, m_PCName, m_PCLevel, m_PCLocation, m_SaveNumber, ftime); - //A file time is a 64-bit value that represents the number of 100-nanosecond - //intervals that have elapsed since 12:00 A.M. January 1, 1601 Coordinated Universal Time (UTC). - //So we need to convert that to something useful + // A file time is a 64-bit value that represents the number of 100-nanosecond + // intervals that have elapsed since 12:00 A.M. January 1, 1601 Coordinated Universal + // Time (UTC). So we need to convert that to something useful SYSTEMTIME ctime; ::FileTimeToSystemTime(&ftime, &ctime); setCreationTime(ctime); } -void Fallout76SaveGame::fetchInformationFields(FileWrapper& file, - QString playerName, - unsigned short playerLevel, - QString playerLocation, - unsigned long saveNumber, - FILETIME& creationTime) const { +void Fallout76SaveGame::fetchInformationFields(FileWrapper& file, QString playerName, + unsigned short playerLevel, + QString playerLocation, + unsigned long saveNumber, + FILETIME& creationTime) const +{ - file.skip(); // header size - file.skip(); // header version + file.skip(); // header size + file.skip(); // header version file.read(saveNumber); file.read(playerName); @@ -38,25 +38,25 @@ void Fallout76SaveGame::fetchInformationFields(FileWrapper& file, file.read(playerLocation); QString ignore; - file.read(ignore); // playtime as ascii hh.mm.ss - file.read(ignore); // race name (i.e. BretonRace) + file.read(ignore); // playtime as ascii hh.mm.ss + file.read(ignore); // race name (i.e. BretonRace) - file.skip(); // Player gender (0 = male) - file.skip(2); // experience gathered, experience required + file.skip(); // Player gender (0 = male) + file.skip(2); // experience gathered, experience required FILETIME ftime; file.read(ftime); - } -std::unique_ptr Fallout76SaveGame::fetchDataFields() const { +std::unique_ptr Fallout76SaveGame::fetchDataFields() const +{ - FileWrapper file(getFilepath(), "TESV_SAVEGAME"); //10bytes + FileWrapper file(getFilepath(), "TESV_SAVEGAME"); // 10bytes { FILETIME ftime; - fetchInformationFields(file, m_PCName, m_PCLevel, m_PCLocation, m_SaveNumber, ftime); - + fetchInformationFields(file, m_PCName, m_PCLevel, m_PCLocation, m_SaveNumber, + ftime); } std::unique_ptr fields = std::make_unique(); @@ -65,8 +65,8 @@ std::unique_ptr Fallout76SaveGame::fetchDataFields uint8_t saveGameVersion = file.readChar(); QString ignore; - file.read(ignore); // game version - file.skip(); // plugin info size + file.read(ignore); // game version + file.skip(); // plugin info size file.readPlugins(); if (saveGameVersion >= 68) { diff --git a/src/games/fallout76/src/fallout76savegame.h b/src/games/fallout76/src/fallout76savegame.h index 7358c3f5..232e7582 100644 --- a/src/games/fallout76/src/fallout76savegame.h +++ b/src/games/fallout76/src/fallout76savegame.h @@ -10,19 +10,15 @@ class GameFallout76; class Fallout76SaveGame : public GamebryoSaveGame { public: - Fallout76SaveGame(QString const &fileName, GameFallout76 const *game); + Fallout76SaveGame(QString const& fileName, GameFallout76 const* game); protected: - // Fetch easy-to-access information. - void fetchInformationFields(FileWrapper& wrapper, - QString playerName, - unsigned short playerLevel, - QString playerLocation, - unsigned long saveNumber, - FILETIME& creationTime) const; + void fetchInformationFields(FileWrapper& wrapper, QString playerName, + unsigned short playerLevel, QString playerLocation, + unsigned long saveNumber, FILETIME& creationTime) const; std::unique_ptr fetchDataFields() const override; }; -#endif // FALLOUT76SAVEGAME_H +#endif // FALLOUT76SAVEGAME_H diff --git a/src/games/fallout76/src/fallout76savegameinfo.cpp b/src/games/fallout76/src/fallout76savegameinfo.cpp index 9ba77dd8..c6cb6213 100644 --- a/src/games/fallout76/src/fallout76savegameinfo.cpp +++ b/src/games/fallout76/src/fallout76savegameinfo.cpp @@ -3,11 +3,8 @@ #include "fallout76savegame.h" #include "gamegamebryo.h" -Fallout76SaveGameInfo::Fallout76SaveGameInfo(GameGamebryo const *game) : - GamebryoSaveGameInfo(game) -{ -} +Fallout76SaveGameInfo::Fallout76SaveGameInfo(GameGamebryo const* game) + : GamebryoSaveGameInfo(game) +{} -Fallout76SaveGameInfo::~Fallout76SaveGameInfo() -{ -} +Fallout76SaveGameInfo::~Fallout76SaveGameInfo() {} diff --git a/src/games/fallout76/src/fallout76savegameinfo.h b/src/games/fallout76/src/fallout76savegameinfo.h index 3aa57e5b..457777c1 100644 --- a/src/games/fallout76/src/fallout76savegameinfo.h +++ b/src/games/fallout76/src/fallout76savegameinfo.h @@ -8,8 +8,8 @@ class GameGamebryo; class Fallout76SaveGameInfo : public GamebryoSaveGameInfo { public: - Fallout76SaveGameInfo(GameGamebryo const *game); + Fallout76SaveGameInfo(GameGamebryo const* game); ~Fallout76SaveGameInfo(); }; -#endif // FALLOUT76SAVEGAMEINFO_H +#endif // FALLOUT76SAVEGAMEINFO_H diff --git a/src/games/fallout76/src/fallout76scriptextender.cpp b/src/games/fallout76/src/fallout76scriptextender.cpp index 11b0e0c5..8a46c5ef 100644 --- a/src/games/fallout76/src/fallout76scriptextender.cpp +++ b/src/games/fallout76/src/fallout76scriptextender.cpp @@ -3,10 +3,9 @@ #include #include -Fallout76ScriptExtender::Fallout76ScriptExtender(GameGamebryo const *game) : - GamebryoScriptExtender(game) -{ -} +Fallout76ScriptExtender::Fallout76ScriptExtender(GameGamebryo const* game) + : GamebryoScriptExtender(game) +{} QString Fallout76ScriptExtender::BinaryName() const { diff --git a/src/games/fallout76/src/fallout76scriptextender.h b/src/games/fallout76/src/fallout76scriptextender.h index b8c13799..206d5978 100644 --- a/src/games/fallout76/src/fallout76scriptextender.h +++ b/src/games/fallout76/src/fallout76scriptextender.h @@ -8,10 +8,10 @@ class GameGamebryo; class Fallout76ScriptExtender : public GamebryoScriptExtender { public: - Fallout76ScriptExtender(GameGamebryo const *game); + Fallout76ScriptExtender(GameGamebryo const* game); virtual QString BinaryName() const override; virtual QString PluginPath() const override; }; -#endif // FALLOUT76SCRIPTEXTENDER_H +#endif // FALLOUT76SCRIPTEXTENDER_H diff --git a/src/games/fallout76/src/fallout76unmanagedmods.cpp b/src/games/fallout76/src/fallout76unmanagedmods.cpp index 3eb4f450..1ddc21c8 100644 --- a/src/games/fallout76/src/fallout76unmanagedmods.cpp +++ b/src/games/fallout76/src/fallout76unmanagedmods.cpp @@ -1,24 +1,23 @@ #include "fallout76unmanagedmods.h" - -Fallout76UnmangedMods::Fallout76UnmangedMods(const GameGamebryo *game) - : GamebryoUnmangedMods(game) +Fallout76UnmangedMods::Fallout76UnmangedMods(const GameGamebryo* game) + : GamebryoUnmangedMods(game) {} -Fallout76UnmangedMods::~Fallout76UnmangedMods() -{} +Fallout76UnmangedMods::~Fallout76UnmangedMods() {} -QStringList Fallout76UnmangedMods::mods(bool onlyOfficial) const { +QStringList Fallout76UnmangedMods::mods(bool onlyOfficial) const +{ QStringList result; - QStringList pluginList = game()->primaryPlugins(); + QStringList pluginList = game()->primaryPlugins(); QStringList otherPlugins = game()->DLCPlugins(); otherPlugins.append(game()->CCPlugins()); for (QString plugin : otherPlugins) { pluginList.removeAll(plugin); } QDir dataDir(game()->dataDirectory()); - for (const QString &fileName : dataDir.entryList({ "*.esp", "*.esl", "*.esm" })) { + for (const QString& fileName : dataDir.entryList({"*.esp", "*.esl", "*.esm"})) { if (!pluginList.contains(fileName, Qt::CaseInsensitive)) { if (!onlyOfficial || pluginList.contains(fileName, Qt::CaseInsensitive)) { QFileInfo file(fileName); @@ -30,17 +29,18 @@ QStringList Fallout76UnmangedMods::mods(bool onlyOfficial) const { return result; } -QStringList Fallout76UnmangedMods::secondaryFiles(const QString &modName) const { +QStringList Fallout76UnmangedMods::secondaryFiles(const QString& modName) const +{ // file extension in FO76 is .ba2 instead of bsa QStringList archives; QDir dataDir = game()->dataDirectory(); - for (const QString &archiveName : dataDir.entryList({modName + "*.ba2"})) { + for (const QString& archiveName : dataDir.entryList({modName + "*.ba2"})) { archives.append(dataDir.absoluteFilePath(archiveName)); } return archives; } -QString Fallout76UnmangedMods::displayName(const QString &modName) const +QString Fallout76UnmangedMods::displayName(const QString& modName) const { return modName; } diff --git a/src/games/fallout76/src/fallout76unmanagedmods.h b/src/games/fallout76/src/fallout76unmanagedmods.h index f0d6f947..17d476d8 100644 --- a/src/games/fallout76/src/fallout76unmanagedmods.h +++ b/src/games/fallout76/src/fallout76unmanagedmods.h @@ -1,21 +1,18 @@ #ifndef FALLOUT76UNMANAGEDMODS_H #define FALLOUT76UNMANAGEDMODS_H - #include "gamebryounmanagedmods.h" #include - -class Fallout76UnmangedMods : public GamebryoUnmangedMods { +class Fallout76UnmangedMods : public GamebryoUnmangedMods +{ public: - Fallout76UnmangedMods(const GameGamebryo *game); + Fallout76UnmangedMods(const GameGamebryo* game); ~Fallout76UnmangedMods(); virtual QStringList mods(bool onlyOfficial) const override; - virtual QStringList secondaryFiles(const QString &modName) const override; - virtual QString displayName(const QString &modName) const override; + virtual QStringList secondaryFiles(const QString& modName) const override; + virtual QString displayName(const QString& modName) const override; }; - - -#endif // FALLOUT76UNMANAGEDMODS_H +#endif // FALLOUT76UNMANAGEDMODS_H diff --git a/src/games/fallout76/src/gamefallout76.cpp b/src/games/fallout76/src/gamefallout76.cpp index 559f4660..1d7fd711 100644 --- a/src/games/fallout76/src/gamefallout76.cpp +++ b/src/games/fallout76/src/gamefallout76.cpp @@ -3,15 +3,15 @@ #include "fallout76dataarchives.h" #include "fallout76moddatachecker.h" #include "fallout76moddatacontent.h" -#include "fallout76scriptextender.h" #include "fallout76savegameinfo.h" +#include "fallout76scriptextender.h" #include "fallout76unmanagedmods.h" -#include +#include "versioninfo.h" +#include #include #include -#include -#include "versioninfo.h" +#include #include #include @@ -27,11 +27,9 @@ using namespace MOBase; -GameFallout76::GameFallout76() -{ -} +GameFallout76::GameFallout76() {} -bool GameFallout76::init(IOrganizer *moInfo) +bool GameFallout76::init(IOrganizer* moInfo) { if (!GameGamebryo::init(moInfo)) { return false; @@ -40,7 +38,8 @@ bool GameFallout76::init(IOrganizer *moInfo) registerFeature(std::make_shared(this)); registerFeature(std::make_shared(myGamesPath())); registerFeature(std::make_shared(this)); - registerFeature(std::make_shared(m_Organizer->gameFeatures())); + registerFeature( + std::make_shared(m_Organizer->gameFeatures())); registerFeature(std::make_shared(moInfo)); registerFeature(std::make_shared(this)); @@ -55,15 +54,19 @@ QString GameFallout76::gameName() const QList GameFallout76::executables() const { return QList() - << ExecutableInfo("F76SE", findInGameFolder(m_Organizer->gameFeatures()->gameFeature()->loaderName())) - << ExecutableInfo("Fallout 76", findInGameFolder(binaryName())) - << ExecutableInfo("Fallout Launcher", findInGameFolder(getLauncherName())) - << ExecutableInfo("Creation Kit", findInGameFolder("CreationKit.exe")) - << ExecutableInfo("LOOT", QFileInfo(getLootPath())).withArgument("--game=\"Fallout76\"") - ; + << ExecutableInfo("F76SE", + findInGameFolder(m_Organizer->gameFeatures() + ->gameFeature() + ->loaderName())) + << ExecutableInfo("Fallout 76", findInGameFolder(binaryName())) + << ExecutableInfo("Fallout Launcher", findInGameFolder(getLauncherName())) + << ExecutableInfo("Creation Kit", findInGameFolder("CreationKit.exe")) + << ExecutableInfo("LOOT", QFileInfo(getLootPath())) + .withArgument("--game=\"Fallout76\""); } -QList GameFallout76::executableForcedLoads() const { +QList GameFallout76::executableForcedLoads() const +{ return {}; } @@ -80,7 +83,8 @@ QString GameFallout76::author() const QString GameFallout76::description() const { return tr("Adds support for the game Fallout 76.\n" - "Splash by %1").arg("nekoyoubi"); + "Splash by %1") + .arg("nekoyoubi"); } MOBase::VersionInfo GameFallout76::version() const @@ -93,7 +97,7 @@ QList GameFallout76::settings() const return QList(); } -void GameFallout76::initializeProfile(const QDir &path, ProfileSettings settings) const +void GameFallout76::initializeProfile(const QDir& path, ProfileSettings settings) const { if (settings.testFlag(IPluginGame::MODS)) { copyToProfile(localAppFolder() + "/Fallout76", path, "plugins.txt"); @@ -101,15 +105,16 @@ void GameFallout76::initializeProfile(const QDir &path, ProfileSettings settings } 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"); + 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"); + copyToProfile(myGamesPath(), path, "Fallout76Custom.ini"); } } @@ -123,7 +128,8 @@ QString GameFallout76::savegameSEExtension() const return "f76se"; } -std::vector> GameFallout76::listSaves(QDir folder) const +std::vector> +GameFallout76::listSaves(QDir folder) const { return {}; } @@ -138,7 +144,8 @@ QString GameFallout76::steamAPPId() const return "n/a"; } -QStringList GameFallout76::primaryPlugins() const { +QStringList GameFallout76::primaryPlugins() const +{ QStringList plugins = {"SeventySix.esm"}; plugins.append(CCPlugins()); @@ -148,7 +155,7 @@ QStringList GameFallout76::primaryPlugins() const { QStringList GameFallout76::gameVariants() const { - return { "Regular" }; + return {"Regular"}; } QString GameFallout76::gameShortName() const @@ -163,7 +170,7 @@ QString GameFallout76::gameNexusName() const QStringList GameFallout76::iniFiles() const { - return { "Fallout76.ini", "Fallout76Prefs.ini", "Fallout76Custom.ini" }; + return {"Fallout76.ini", "Fallout76Prefs.ini", "Fallout76Custom.ini"}; } QStringList GameFallout76::DLCPlugins() const @@ -176,7 +183,9 @@ QStringList GameFallout76::CCPlugins() const QStringList plugins = {}; QFile file(gameDirectory().absoluteFilePath("Fallout76.ccc")); if (file.open(QIODevice::ReadOnly)) { - ON_BLOCK_EXIT([&file]() { file.close(); }); + ON_BLOCK_EXIT([&file]() { + file.close(); + }); if (file.size() == 0) { return plugins; diff --git a/src/games/fallout76/src/gamefallout76.h b/src/games/fallout76/src/gamefallout76.h index c21e29e1..3386dc0c 100644 --- a/src/games/fallout76/src/gamefallout76.h +++ b/src/games/fallout76/src/gamefallout76.h @@ -1,7 +1,6 @@ #ifndef GAMEFALLOUT76_H #define GAMEFALLOUT76_H - #include "gamegamebryo.h" #include @@ -14,17 +13,15 @@ class GameFallout76 : public GameGamebryo Q_PLUGIN_METADATA(IID "in.ejew.GameFallout76" FILE "gamefallout76.json") public: - GameFallout76(); - virtual bool init(MOBase::IOrganizer *moInfo) override; - -public: // IPluginGame interface + virtual bool init(MOBase::IOrganizer* moInfo) override; +public: // IPluginGame interface QString gameName() const override; QList executables() const override; QList executableForcedLoads() const override; - void initializeProfile(const QDir &path, ProfileSettings settings) const override; + void initializeProfile(const QDir& path, ProfileSettings settings) const override; QString steamAPPId() const override; QStringList primaryPlugins() const override; QStringList gameVariants() const override; @@ -36,10 +33,10 @@ public: // IPluginGame interface LoadOrderMechanism loadOrderMechanism() const override; int nexusModOrganizerID() const override; int nexusGameID() const override; - std::vector> listSaves(QDir folder) const override; - -public: // IPlugin interface + std::vector> + listSaves(QDir folder) const override; +public: // IPlugin interface QString name() const override; QString author() const override; QString description() const override; @@ -52,4 +49,4 @@ protected: QString savegameSEExtension() const override; }; -#endif // GAMEFallout76_H +#endif // GAMEFallout76_H From 28ce51bec7097785175aaeba2153266229d23624 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Mika=C3=ABl=20Capelle?= Date: Sun, 9 Jun 2024 13:27:34 +0200 Subject: [PATCH 1476/1544] [game_fallout76] Add .git-blame-ignore-revs. --- src/games/fallout76/.git-blame-ignore-revs | 1 + 1 file changed, 1 insertion(+) create mode 100644 src/games/fallout76/.git-blame-ignore-revs diff --git a/src/games/fallout76/.git-blame-ignore-revs b/src/games/fallout76/.git-blame-ignore-revs new file mode 100644 index 00000000..946b4929 --- /dev/null +++ b/src/games/fallout76/.git-blame-ignore-revs @@ -0,0 +1 @@ +e3bfde72c076ac756d966ec87d848f628ba73088 From 4c32a6639441a5dad8b1d771470ea661d2c1fe90 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Mika=C3=ABl=20Capelle?= Date: Sun, 9 Jun 2024 13:27:34 +0200 Subject: [PATCH 1477/1544] [game_fallout76] Add github actions. --- src/games/fallout76/.github/workflows/build.yml | 16 ++++++++++++++++ .../fallout76/.github/workflows/linting.yml | 16 ++++++++++++++++ 2 files changed, 32 insertions(+) create mode 100644 src/games/fallout76/.github/workflows/build.yml create mode 100644 src/games/fallout76/.github/workflows/linting.yml diff --git a/src/games/fallout76/.github/workflows/build.yml b/src/games/fallout76/.github/workflows/build.yml new file mode 100644 index 00000000..7ba86be2 --- /dev/null +++ b/src/games/fallout76/.github/workflows/build.yml @@ -0,0 +1,16 @@ +name: Build Fallout 76 Plugin + +on: + push: + branches: master + pull_request: + types: [opened, synchronize, reopened] + +jobs: + build: + runs-on: windows-2022 + steps: + - name: Build Fallout 76 Plugin + uses: ModOrganizer2/build-with-mob-action@master + with: + mo2-dependencies: cmake_common uibase game_gamebryo diff --git a/src/games/fallout76/.github/workflows/linting.yml b/src/games/fallout76/.github/workflows/linting.yml new file mode 100644 index 00000000..d8353d71 --- /dev/null +++ b/src/games/fallout76/.github/workflows/linting.yml @@ -0,0 +1,16 @@ +name: Lint Fallout 76 Plugin + +on: + push: + pull_request: + types: [opened, synchronize, reopened] + +jobs: + lint: + runs-on: ubuntu-latest + steps: + - uses: actions/checkout@v3 + - name: Check format + uses: ModOrganizer2/check-formatting-action@master + with: + check-path: "." From 39ad440675fa84d7bf35c7b21966c8bb630c4326 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Mika=C3=ABl=20Capelle?= Date: Sun, 9 Jun 2024 13:29:33 +0200 Subject: [PATCH 1478/1544] [game_morrowind] Remove appveyor.yml. --- src/games/morrowind/appveyor.yml | 40 -------------------------------- 1 file changed, 40 deletions(-) delete mode 100644 src/games/morrowind/appveyor.yml diff --git a/src/games/morrowind/appveyor.yml b/src/games/morrowind/appveyor.yml deleted file mode 100644 index 97872c2b..00000000 --- a/src/games/morrowind/appveyor.yml +++ /dev/null @@ -1,40 +0,0 @@ -version: 1.0.{build} -skip_branch_with_pr: true -image: Visual Studio 2019 -environment: - WEBHOOK_URL: - secure: gOKbXaZM9ImtMD5XrYITvdyZUW/az082G9OIN1EC1Vbg57wBaeLhi49uGjxPw5GVujHku6kxN6ab89zhbS5GVeluR76GM83IbKV4Sh7udXzoYZZdg6YudtYHzdhCgUeiedpswbuczTq9ceIkkfSEWZuh/lMAAVVwvcGsJAnoPFw= -build_script: -- pwsh: >- - $ErrorActionPreference = 'Stop' - - git clone --depth=1 --no-single-branch https://github.com/ModOrganizer2/modorganizer-umbrella.git c:\projects\modorganizer-umbrella - - New-Item -ItemType Directory -Path c:\projects\modorganizer-build - - cd c:\projects\modorganizer-umbrella - - ($env:APPVEYOR_PULL_REQUEST_HEAD_REPO_BRANCH -eq $null) ? ($branch = $env:APPVEYOR_REPO_BRANCH) : ($branch = $env:APPVEYOR_PULL_REQUEST_HEAD_REPO_BRANCH) - - git checkout $(git show-ref --verify --quiet refs/remotes/origin/${branch} || echo '-b') ${branch} - - C:\Python37-x64\python.exe unimake.py -d c:\projects\modorganizer-build -s Appveyor_Build=True ${env:APPVEYOR_PROJECT_NAME} - - if($LastExitCode -ne 0) { $host.SetShouldExit($LastExitCode ) } -artifacts: -- path: vsbuild\src\RelWithDebInfo\game_morrowind.dll - name: game_morrowind_dll -- path: vsbuild\src\RelWithDebInfo\game_morrowind.pdb - name: game_morrowind_pdb -- path: vsbuild\src\RelWithDebInfo\game_morrowind.lib - name: game_morrowind_lib -on_success: - - ps: Set-Location -Path $env:APPVEYOR_BUILD_FOLDER - - ps: Invoke-RestMethod https://raw.githubusercontent.com/DiscordHooks/appveyor-discord-webhook/master/send.ps1 -o send.ps1 - - ps: ./send.ps1 success $env:WEBHOOK_URL -on_failure: - - ps: Set-Location -Path $env:APPVEYOR_BUILD_FOLDER - - ps: Push-AppveyorArtifact ${env:APPVEYOR_BUILD_FOLDER}\stdout.log - - ps: Push-AppveyorArtifact ${env:APPVEYOR_BUILD_FOLDER}\stderr.log - - ps: Invoke-RestMethod https://raw.githubusercontent.com/DiscordHooks/appveyor-discord-webhook/master/send.ps1 -o send.ps1 - - ps: ./send.ps1 failure $env:WEBHOOK_URL \ No newline at end of file From 127b1c53b990004673365aa0c65d209f4892d992 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Mika=C3=ABl=20Capelle?= Date: Sun, 9 Jun 2024 13:29:34 +0200 Subject: [PATCH 1479/1544] [game_morrowind] Format files and add .gitattributes and .clang-format. --- src/games/morrowind/.clang-format | 41 +++++ src/games/morrowind/.gitattributes | 7 + src/games/morrowind/src/gamemorrowind.cpp | 61 ++++---- src/games/morrowind/src/gamemorrowind.h | 27 ++-- .../src/morrowindbsainvalidation.cpp | 8 +- .../morrowind/src/morrowindbsainvalidation.h | 9 +- .../morrowind/src/morrowinddataarchives.cpp | 53 ++++--- .../morrowind/src/morrowinddataarchives.h | 28 ++-- .../morrowind/src/morrowindgameplugins.cpp | 142 ++++++++++-------- .../morrowind/src/morrowindgameplugins.h | 24 +-- .../morrowind/src/morrowindlocalsavegames.cpp | 25 ++- .../morrowind/src/morrowindlocalsavegames.h | 17 +-- .../morrowind/src/morrowindmoddatachecker.h | 19 ++- .../morrowind/src/morrowindmoddatacontent.h | 17 ++- src/games/morrowind/src/morrowindsavegame.cpp | 112 +++++++------- src/games/morrowind/src/morrowindsavegame.h | 36 ++--- .../morrowind/src/morrowindsavegameinfo.cpp | 17 +-- .../morrowind/src/morrowindsavegameinfo.h | 8 +- .../src/morrowindsavegameinfowidget.cpp | 60 +++++--- .../src/morrowindsavegameinfowidget.h | 13 +- 20 files changed, 388 insertions(+), 336 deletions(-) create mode 100644 src/games/morrowind/.clang-format create mode 100644 src/games/morrowind/.gitattributes diff --git a/src/games/morrowind/.clang-format b/src/games/morrowind/.clang-format new file mode 100644 index 00000000..6098e1f5 --- /dev/null +++ b/src/games/morrowind/.clang-format @@ -0,0 +1,41 @@ +--- +# We'll use defaults from the LLVM style, but with 4 columns indentation. +BasedOnStyle: LLVM +IndentWidth: 2 +--- +Language: Cpp +DeriveLineEnding: false +UseCRLF: true +DerivePointerAlignment: false +PointerAlignment: Left +AlignConsecutiveAssignments: true +AllowShortFunctionsOnASingleLine: Inline +AllowShortIfStatementsOnASingleLine: Never +AllowShortLambdasOnASingleLine: Empty +AlwaysBreakTemplateDeclarations: Yes +AccessModifierOffset: -2 +AlignTrailingComments: true +SpacesBeforeTrailingComments: 2 +NamespaceIndentation: Inner +MaxEmptyLinesToKeep: 1 +BreakBeforeBraces: Custom +BraceWrapping: + AfterCaseLabel: false + AfterClass: true + AfterControlStatement: false + AfterEnum: true + AfterFunction: true + AfterNamespace: true + AfterStruct: true + AfterUnion: true + AfterExternBlock: true + BeforeCatch: false + BeforeElse: false + BeforeLambdaBody: false + BeforeWhile: false + IndentBraces: false + SplitEmptyFunction: false + SplitEmptyRecord: false + SplitEmptyNamespace: true +ColumnLimit: 88 +ForEachMacros: ['Q_FOREACH', 'foreach'] diff --git a/src/games/morrowind/.gitattributes b/src/games/morrowind/.gitattributes new file mode 100644 index 00000000..f8697127 --- /dev/null +++ b/src/games/morrowind/.gitattributes @@ -0,0 +1,7 @@ +# Set the default behavior, in case people don't have core.autocrlf set. +* text=auto + +# Explicitly declare text files you want to always be normalized and converted +# to native line endings on checkout. +*.cpp text eol=crlf +*.h text eol=crlf diff --git a/src/games/morrowind/src/gamemorrowind.cpp b/src/games/morrowind/src/gamemorrowind.cpp index 51f0eaa8..c9e5b9d7 100644 --- a/src/games/morrowind/src/gamemorrowind.cpp +++ b/src/games/morrowind/src/gamemorrowind.cpp @@ -4,10 +4,10 @@ #include "morrowinddataarchives.h" #include "morrowindgameplugins.h" #include "morrowindlocalsavegames.h" -#include "morrowindsavegame.h" -#include "morrowindsavegameinfo.h" #include "morrowindmoddatachecker.h" #include "morrowindmoddatacontent.h" +#include "morrowindsavegame.h" +#include "morrowindsavegameinfo.h" #include "executableinfo.h" #include "pluginsetting.h" @@ -32,23 +32,22 @@ using namespace MOBase; -GameMorrowind::GameMorrowind() -{ -} +GameMorrowind::GameMorrowind() {} -bool GameMorrowind::init(IOrganizer *moInfo) +bool GameMorrowind::init(IOrganizer* moInfo) { if (!GameGamebryo::init(moInfo)) { return false; } - + auto dataArchives = std::make_shared(this); registerFeature(dataArchives); registerFeature(std::make_shared(dataArchives.get(), this)); registerFeature(std::make_shared(this)); registerFeature(std::make_shared(this)); registerFeature(std::make_shared(this)); - registerFeature(std::make_shared(m_Organizer->gameFeatures())); + registerFeature( + std::make_shared(m_Organizer->gameFeatures())); registerFeature(std::make_shared(moInfo)); registerFeature(std::make_shared(this)); @@ -83,12 +82,13 @@ QDir GameMorrowind::documentsDirectory() const QList GameMorrowind::executables() const { return QList() - << ExecutableInfo("MWSE (Launcher Method)", findInGameFolder("MWSE Launcher.exe")) - << ExecutableInfo("Morrowind", findInGameFolder(binaryName())) - << ExecutableInfo("Morrowind Launcher", findInGameFolder(getLauncherName())) - << ExecutableInfo("MGE XE", findInGameFolder("MGEXEgui.exe")) - << ExecutableInfo("LOOT", QFileInfo(getLootPath())).withArgument("--game=\"Morrowind\"") - ; + << ExecutableInfo("MWSE (Launcher Method)", + findInGameFolder("MWSE Launcher.exe")) + << ExecutableInfo("Morrowind", findInGameFolder(binaryName())) + << ExecutableInfo("Morrowind Launcher", findInGameFolder(getLauncherName())) + << ExecutableInfo("MGE XE", findInGameFolder("MGEXEgui.exe")) + << ExecutableInfo("LOOT", QFileInfo(getLootPath())) + .withArgument("--game=\"Morrowind\""); } QList GameMorrowind::executableForcedLoads() const @@ -106,7 +106,6 @@ QString GameMorrowind::localizedName() const return tr("Morrowind Support Plugin"); } - QString GameMorrowind::author() const { return "Schilduin & MO2 Team"; @@ -115,7 +114,8 @@ QString GameMorrowind::author() const QString GameMorrowind::description() const { return tr("Adds support for the game Morrowind.\n" - "Splash by %1").arg("AnyOldName3"); + "Splash by %1") + .arg("AnyOldName3"); } MOBase::VersionInfo GameMorrowind::version() const @@ -128,7 +128,7 @@ QList GameMorrowind::settings() const return QList(); } -void GameMorrowind::initializeProfile(const QDir &path, ProfileSettings settings) const +void GameMorrowind::initializeProfile(const QDir& path, ProfileSettings settings) const { if (settings.testFlag(IPluginGame::MODS)) { copyToProfile(localAppFolder() + "/Morrowind", path, "plugins.txt"); @@ -149,7 +149,8 @@ QString GameMorrowind::savegameSEExtension() const return "mwse"; } -std::shared_ptr GameMorrowind::makeSaveGame(QString filePath) const +std::shared_ptr +GameMorrowind::makeSaveGame(QString filePath) const { return std::make_shared(filePath, this); } @@ -161,7 +162,7 @@ QString GameMorrowind::steamAPPId() const QStringList GameMorrowind::primaryPlugins() const { - return { "morrowind.esm" }; + return {"morrowind.esm"}; } QString GameMorrowind::binaryName() const @@ -179,15 +180,14 @@ QString GameMorrowind::gameNexusName() const return "Morrowind"; } - QStringList GameMorrowind::iniFiles() const { - return { "morrowind.ini" }; + return {"morrowind.ini"}; } QStringList GameMorrowind::DLCPlugins() const { - return { "Tribunal.esm", "Bloodmoon.esm" }; + return {"Tribunal.esm", "Bloodmoon.esm"}; } MOBase::IPluginGame::SortMechanism GameMorrowind::sortMechanism() const @@ -195,15 +195,16 @@ MOBase::IPluginGame::SortMechanism GameMorrowind::sortMechanism() const return SortMechanism::LOOT; } -namespace { -//Note: This is ripped off from shared/util. And in an upcoming move, the fomod -//installer requires something similar. I suspect I should abstract this out -//into gamebryo (or lower level) +namespace +{ +// Note: This is ripped off from shared/util. And in an upcoming move, the fomod +// installer requires something similar. I suspect I should abstract this out +// into gamebryo (or lower level) -VS_FIXEDFILEINFO GetFileVersion(const std::wstring &fileName) +VS_FIXEDFILEINFO GetFileVersion(const std::wstring& fileName) { DWORD handle = 0UL; - DWORD size = ::GetFileVersionInfoSizeW(fileName.c_str(), &handle); + DWORD size = ::GetFileVersionInfoSizeW(fileName.c_str(), &handle); if (size == 0) { throw std::runtime_error("failed to determine file version info size"); } @@ -214,7 +215,7 @@ VS_FIXEDFILEINFO GetFileVersion(const std::wstring &fileName) throw std::runtime_error("failed to determine file version info"); } - void *versionInfoPtr = nullptr; + void* versionInfoPtr = nullptr; UINT versionInfoLength = 0; if (!::VerQueryValue(buffer.data(), L"\\", &versionInfoPtr, &versionInfoLength)) { throw std::runtime_error("failed to determine file version"); @@ -223,7 +224,7 @@ VS_FIXEDFILEINFO GetFileVersion(const std::wstring &fileName) return *static_cast(versionInfoPtr); } -} +} // namespace int GameMorrowind::nexusModOrganizerID() const { diff --git a/src/games/morrowind/src/gamemorrowind.h b/src/games/morrowind/src/gamemorrowind.h index ece03a59..a6f6862a 100644 --- a/src/games/morrowind/src/gamemorrowind.h +++ b/src/games/morrowind/src/gamemorrowind.h @@ -9,29 +9,29 @@ class GameMorrowind : public GameGamebryo { Q_OBJECT -#if QT_VERSION >= QT_VERSION_CHECK(5,0,0) - Q_PLUGIN_METADATA(IID "com.schilduin.GameMorrowind" FILE "gamemorrowind.json") +#if QT_VERSION >= QT_VERSION_CHECK(5, 0, 0) + Q_PLUGIN_METADATA(IID "com.schilduin.GameMorrowind" FILE "gamemorrowind.json") #endif friend class MorrowindSaveGameInfo; friend class MorrowindSaveGameInfoWidget; public: - GameMorrowind(); - virtual bool init(MOBase::IOrganizer *moInfo) override; - -public: // IPluginGame interface + virtual bool init(MOBase::IOrganizer* moInfo) override; +public: // IPluginGame interface virtual QString gameName() const override; virtual QString getLauncherName() const override; virtual QDir dataDirectory() const override; virtual QDir savesDirectory() const override; virtual QDir documentsDirectory() const override; virtual QList executables() const override; - virtual QList executableForcedLoads() const override; - virtual void initializeProfile(const QDir &path, ProfileSettings settings) const override; + virtual QList + executableForcedLoads() const override; + virtual void initializeProfile(const QDir& path, + ProfileSettings settings) const override; virtual QString steamAPPId() const override; virtual QStringList primaryPlugins() const override; virtual QString binaryName() const override; @@ -44,8 +44,7 @@ public: // IPluginGame interface virtual int nexusGameID() const override; virtual QString identifyGamePath() const; -public: // IPlugin interface - +public: // IPlugin interface virtual QString name() const override; virtual QString localizedName() const override; virtual QString author() const override; @@ -54,12 +53,10 @@ public: // IPlugin interface virtual QList settings() const override; protected: - virtual QString savegameExtension() const override; virtual QString savegameSEExtension() const override; - virtual std::shared_ptr makeSaveGame(QString filepath) const override; + virtual std::shared_ptr + makeSaveGame(QString filepath) const override; }; - - -#endif // GAMEMORROWIND_H +#endif // GAMEMORROWIND_H diff --git a/src/games/morrowind/src/morrowindbsainvalidation.cpp b/src/games/morrowind/src/morrowindbsainvalidation.cpp index 21590dbc..9b63d4c9 100644 --- a/src/games/morrowind/src/morrowindbsainvalidation.cpp +++ b/src/games/morrowind/src/morrowindbsainvalidation.cpp @@ -1,9 +1,9 @@ #include "morrowindbsainvalidation.h" -MorrowindBSAInvalidation::MorrowindBSAInvalidation(MOBase::DataArchives *dataArchives, MOBase::IPluginGame const *game) - : GamebryoBSAInvalidation(dataArchives, "morrowind.ini", game) -{ -} +MorrowindBSAInvalidation::MorrowindBSAInvalidation(MOBase::DataArchives* dataArchives, + MOBase::IPluginGame const* game) + : GamebryoBSAInvalidation(dataArchives, "morrowind.ini", game) +{} QString MorrowindBSAInvalidation::invalidationBSAName() const { diff --git a/src/games/morrowind/src/morrowindbsainvalidation.h b/src/games/morrowind/src/morrowindbsainvalidation.h index 020d4ef0..8395abe1 100644 --- a/src/games/morrowind/src/morrowindbsainvalidation.h +++ b/src/games/morrowind/src/morrowindbsainvalidation.h @@ -1,7 +1,6 @@ #ifndef MORROWINDBSAINVALIDATION_H #define MORROWINDBSAINVALIDATION_H - #include "gamebryobsainvalidation.h" #include "morrowinddataarchives.h" @@ -10,14 +9,12 @@ class MorrowindBSAInvalidation : public GamebryoBSAInvalidation { public: - - MorrowindBSAInvalidation(MOBase::DataArchives *dataArchives, MOBase::IPluginGame const *game); + MorrowindBSAInvalidation(MOBase::DataArchives* dataArchives, + MOBase::IPluginGame const* game); private: - virtual QString invalidationBSAName() const override; virtual unsigned long bsaVersion() const override; - }; -#endif // MORROWINDBSAINVALIDATION_H +#endif // MORROWINDBSAINVALIDATION_H diff --git a/src/games/morrowind/src/morrowinddataarchives.cpp b/src/games/morrowind/src/morrowinddataarchives.cpp index c35c8481..4a133a50 100644 --- a/src/games/morrowind/src/morrowinddataarchives.cpp +++ b/src/games/morrowind/src/morrowinddataarchives.cpp @@ -1,19 +1,20 @@ #include "morrowinddataarchives.h" -#include #include "registry.h" +#include -MorrowindDataArchives::MorrowindDataArchives(const MOBase::IPluginGame *game) - : GamebryoDataArchives(QDir()) // m_LocalGameDir is not used as it's determined too soon - , m_GamePlugin(game) -{ -} +MorrowindDataArchives::MorrowindDataArchives(const MOBase::IPluginGame* game) + : GamebryoDataArchives( + QDir()) // m_LocalGameDir is not used as it's determined too soon + , + m_GamePlugin(game) +{} QStringList MorrowindDataArchives::vanillaArchives() const { - return { "Morrowind.bsa" }; + return {"Morrowind.bsa"}; } -QStringList MorrowindDataArchives::getArchives(const QString &iniFile) const +QStringList MorrowindDataArchives::getArchives(const QString& iniFile) const { wchar_t buffer[256]; QStringList result; @@ -22,42 +23,52 @@ QStringList MorrowindDataArchives::getArchives(const QString &iniFile) const errno = 0; QString key = "Archive "; - int i=0; - while (::GetPrivateProfileStringW(L"Archives", (key+QString::number(i)).toStdWString().c_str(), - L"", buffer, 256, iniFileW.c_str()) != 0) { + int i = 0; + while (::GetPrivateProfileStringW(L"Archives", + (key + QString::number(i)).toStdWString().c_str(), + L"", buffer, 256, iniFileW.c_str()) != 0) { result.append(QString::fromStdWString(buffer).trimmed()); - i++; + i++; } return result; } -void MorrowindDataArchives::setArchives(const QString &iniFile, const QStringList &list) +void MorrowindDataArchives::setArchives(const QString& iniFile, const QStringList& list) { ::WritePrivateProfileSectionW(L"Archives", NULL, iniFile.toStdWString().c_str()); - QString key = "Archive "; + QString key = "Archive "; int writtenCount = 0; - foreach(const QString &value, list) { - if (!MOBase::WriteRegistryValue(L"Archives", (key+QString::number(writtenCount)).toStdWString().c_str(), value.toStdWString().c_str(), iniFile.toStdWString().c_str())) { + foreach (const QString& value, list) { + if (!MOBase::WriteRegistryValue( + L"Archives", (key + QString::number(writtenCount)).toStdWString().c_str(), + value.toStdWString().c_str(), iniFile.toStdWString().c_str())) { qWarning("failed to set archives in \"%s\"", qUtf8Printable(iniFile)); } - ++writtenCount; + ++writtenCount; } } -QStringList MorrowindDataArchives::archives(const MOBase::IProfile *profile) const +QStringList MorrowindDataArchives::archives(const MOBase::IProfile* profile) const { QStringList result; - QString iniFile = profile->localSettingsEnabled() ? QDir(profile->absolutePath()).absoluteFilePath("morrowind.ini") : m_GamePlugin->gameDirectory().absoluteFilePath("morrowind.ini"); + QString iniFile = + profile->localSettingsEnabled() + ? QDir(profile->absolutePath()).absoluteFilePath("morrowind.ini") + : m_GamePlugin->gameDirectory().absoluteFilePath("morrowind.ini"); result.append(getArchives(iniFile)); return result; } -void MorrowindDataArchives::writeArchiveList(MOBase::IProfile *profile, const QStringList &before) +void MorrowindDataArchives::writeArchiveList(MOBase::IProfile* profile, + const QStringList& before) { - QString iniFile = profile->localSettingsEnabled() ? QDir(profile->absolutePath()).absoluteFilePath("morrowind.ini") : m_GamePlugin->gameDirectory().absoluteFilePath("morrowind.ini"); + QString iniFile = + profile->localSettingsEnabled() + ? QDir(profile->absolutePath()).absoluteFilePath("morrowind.ini") + : m_GamePlugin->gameDirectory().absoluteFilePath("morrowind.ini"); setArchives(iniFile, before); } diff --git a/src/games/morrowind/src/morrowinddataarchives.h b/src/games/morrowind/src/morrowinddataarchives.h index d132ce17..e03500cf 100644 --- a/src/games/morrowind/src/morrowinddataarchives.h +++ b/src/games/morrowind/src/morrowinddataarchives.h @@ -1,36 +1,32 @@ #ifndef MORROWINDDATAARCHIVES_H #define MORROWINDDATAARCHIVES_H - -#include -#include -#include +#include #include #include -#include +#include +#include +#include class MorrowindDataArchives : public GamebryoDataArchives { public: - MorrowindDataArchives(const MOBase::IPluginGame *game); + MorrowindDataArchives(const MOBase::IPluginGame* game); public: - virtual QStringList vanillaArchives() const override; - virtual QStringList archives(const MOBase::IProfile *profile) const override; + virtual QStringList archives(const MOBase::IProfile* profile) const override; protected: + QStringList getArchives(const QString& iniFile) const; + void setArchives(const QString& iniFile, const QStringList& list); - QStringList getArchives(const QString &iniFile) const; - void setArchives(const QString &iniFile, const QStringList &list); - private: + virtual void writeArchiveList(MOBase::IProfile* profile, + const QStringList& before) override; - virtual void writeArchiveList(MOBase::IProfile *profile, const QStringList &before) override; - - const MOBase::IPluginGame *m_GamePlugin; - + const MOBase::IPluginGame* m_GamePlugin; }; -#endif // MORROWINDDATAARCHIVES_H +#endif // MORROWINDDATAARCHIVES_H diff --git a/src/games/morrowind/src/morrowindgameplugins.cpp b/src/games/morrowind/src/morrowindgameplugins.cpp index ddf64b29..8dd32def 100644 --- a/src/games/morrowind/src/morrowindgameplugins.cpp +++ b/src/games/morrowind/src/morrowindgameplugins.cpp @@ -1,44 +1,41 @@ #include "morrowindgameplugins.h" -#include -#include -#include -#include -#include -#include -#include #include "registry.h" +#include +#include +#include +#include +#include +#include +#include +#include #include -#include #include #include -#include +#include using MOBase::IOrganizer; using MOBase::IPluginList; using MOBase::reportError; -MorrowindGamePlugins::MorrowindGamePlugins(IOrganizer *organizer) : - GamebryoGamePlugins(organizer) -{ -} +MorrowindGamePlugins::MorrowindGamePlugins(IOrganizer* organizer) + : GamebryoGamePlugins(organizer) +{} -void MorrowindGamePlugins::writePluginLists(const IPluginList *pluginList) { +void MorrowindGamePlugins::writePluginLists(const IPluginList* pluginList) +{ if (!m_LastRead.isValid()) { // attempt to write uninitialized plugin lists return; } if (organizer()->profile()->localSettingsEnabled()) { - writePluginList( - pluginList, - organizer()->profile()->absolutePath() + "/Morrowind.ini" - ); + writePluginList(pluginList, + organizer()->profile()->absolutePath() + "/Morrowind.ini"); } else { - writePluginList( - pluginList, - organizer()->managedGame()->gameDirectory().absolutePath() + "/Morrowind.ini" - ); + writePluginList(pluginList, + organizer()->managedGame()->gameDirectory().absolutePath() + + "/Morrowind.ini"); } writeLoadOrderList(pluginList, @@ -47,20 +44,20 @@ void MorrowindGamePlugins::writePluginLists(const IPluginList *pluginList) { m_LastRead = QDateTime::currentDateTime(); } -void MorrowindGamePlugins::readPluginLists(MOBase::IPluginList *pluginList) { - QString loadOrderPath = - organizer()->profile()->absolutePath() + "/loadorder.txt"; +void MorrowindGamePlugins::readPluginLists(MOBase::IPluginList* pluginList) +{ + QString loadOrderPath = organizer()->profile()->absolutePath() + "/loadorder.txt"; QString pluginsPath = organizer()->profile()->absolutePath() + "/Morrowind.ini"; if (!organizer()->profile()->localSettingsEnabled()) { - pluginsPath = organizer()->managedGame()->gameDirectory().absolutePath() + "/Morrowind.ini"; + pluginsPath = + organizer()->managedGame()->gameDirectory().absolutePath() + "/Morrowind.ini"; } - bool loadOrderIsNew = !m_LastRead.isValid() || - !QFileInfo(loadOrderPath).exists() || - QFileInfo(loadOrderPath).lastModified() > m_LastRead; - bool pluginsIsNew = !m_LastRead.isValid() || - QFileInfo(pluginsPath).lastModified() > m_LastRead; + bool loadOrderIsNew = !m_LastRead.isValid() || !QFileInfo(loadOrderPath).exists() || + QFileInfo(loadOrderPath).lastModified() > m_LastRead; + bool pluginsIsNew = + !m_LastRead.isValid() || QFileInfo(pluginsPath).lastModified() > m_LastRead; if (loadOrderIsNew || !pluginsIsNew) { // read both files if they are both new or both older than the last read @@ -68,7 +65,8 @@ void MorrowindGamePlugins::readPluginLists(MOBase::IPluginList *pluginList) { pluginList->setLoadOrder(loadOrder); readPluginList(pluginList); } else { - // If the plugins is new but not loadorder, we must reparse the load order from the plugin files + // If the plugins is new but not loadorder, we must reparse the load order from the + // plugin files QStringList loadOrder = readPluginList(pluginList); pluginList->setLoadOrder(loadOrder); } @@ -76,35 +74,41 @@ void MorrowindGamePlugins::readPluginLists(MOBase::IPluginList *pluginList) { m_LastRead = QDateTime::currentDateTime(); } -void MorrowindGamePlugins::writePluginList(const MOBase::IPluginList *pluginList, - const QString &filePath) { +void MorrowindGamePlugins::writePluginList(const MOBase::IPluginList* pluginList, + const QString& filePath) +{ return writeList(pluginList, filePath, false); } -void MorrowindGamePlugins::writeList(const IPluginList *pluginList, - const QString &filePath, bool loadOrder) { - QStringEncoder encoder = loadOrder ? QStringEncoder(QStringConverter::Encoding::Utf8) : QStringEncoder(QStringConverter::Encoding::System); +void MorrowindGamePlugins::writeList(const IPluginList* pluginList, + const QString& filePath, bool loadOrder) +{ + QStringEncoder encoder = loadOrder + ? QStringEncoder(QStringConverter::Encoding::Utf8) + : QStringEncoder(QStringConverter::Encoding::System); ::WritePrivateProfileSectionW(L"Game Files", NULL, filePath.toStdWString().c_str()); bool invalidFileNames = false; - int writtenCount = 0; + int writtenCount = 0; QStringList plugins = pluginList->pluginNames(); std::sort(plugins.begin(), plugins.end(), - [pluginList](const QString &lhs, const QString &rhs) { + [pluginList](const QString& lhs, const QString& rhs) { return pluginList->priority(lhs) < pluginList->priority(rhs); }); QString key = "GameFile"; - for (const QString &pluginName : plugins) { - if (loadOrder || - (pluginList->state(pluginName) == IPluginList::STATE_ACTIVE)) { + for (const QString& pluginName : plugins) { + if (loadOrder || (pluginList->state(pluginName) == IPluginList::STATE_ACTIVE)) { auto result = encoder.encode(pluginName); if (encoder.hasError()) { invalidFileNames = true; qCritical("invalid plugin name %s", qUtf8Printable(pluginName)); } else { - if (!MOBase::WriteRegistryValue(L"Game Files", (key+QString::number(writtenCount)).toStdWString().c_str(), pluginName.toStdWString().c_str(), filePath.toStdWString().c_str())) { + if (!MOBase::WriteRegistryValue( + L"Game Files", + (key + QString::number(writtenCount)).toStdWString().c_str(), + pluginName.toStdWString().c_str(), filePath.toStdWString().c_str())) { qWarning("failed to set game files in \"%s\"", qUtf8Printable(filePath)); } } @@ -125,15 +129,17 @@ void MorrowindGamePlugins::writeList(const IPluginList *pluginList, } } -QStringList MorrowindGamePlugins::readPluginList(MOBase::IPluginList *pluginList) { +QStringList MorrowindGamePlugins::readPluginList(MOBase::IPluginList* pluginList) +{ QStringList primary = organizer()->managedGame()->primaryPlugins(); - for (const QString &pluginName : primary) { + for (const QString& pluginName : primary) { if (pluginList->state(pluginName) != IPluginList::STATE_MISSING) { pluginList->setState(pluginName, IPluginList::STATE_ACTIVE); } } QStringList plugins = pluginList->pluginNames(); - // Do not sort the primary plugins. Their load order should be locked as defined in "primaryPlugins". + // Do not sort the primary plugins. Their load order should be locked as defined in + // "primaryPlugins". const QStringList pluginsClone(plugins); for (QString plugin : pluginsClone) { if (primary.contains(plugin, Qt::CaseInsensitive)) @@ -141,24 +147,27 @@ QStringList MorrowindGamePlugins::readPluginList(MOBase::IPluginList *pluginList } // Always use filetime loadorder to get the actual load order - std::sort(plugins.begin(), plugins.end(), [&](const QString &lhs, const QString &rhs) { - MOBase::IModInterface *lhm = organizer()->modList()->getMod(pluginList->origin(lhs)); - MOBase::IModInterface *rhm = organizer()->modList()->getMod(pluginList->origin(rhs)); - QDir lhd = organizer()->managedGame()->dataDirectory(); - QDir rhd = organizer()->managedGame()->dataDirectory(); - if (lhm != nullptr) - lhd = lhm->absolutePath(); - if (rhm != nullptr) - rhd = rhm->absolutePath(); - QString lhp = lhd.absoluteFilePath(lhs); - QString rhp = rhd.absoluteFilePath(rhs); - return QFileInfo(lhp).lastModified() < - QFileInfo(rhp).lastModified(); - }); + std::sort(plugins.begin(), plugins.end(), + [&](const QString& lhs, const QString& rhs) { + MOBase::IModInterface* lhm = + organizer()->modList()->getMod(pluginList->origin(lhs)); + MOBase::IModInterface* rhm = + organizer()->modList()->getMod(pluginList->origin(rhs)); + QDir lhd = organizer()->managedGame()->dataDirectory(); + QDir rhd = organizer()->managedGame()->dataDirectory(); + if (lhm != nullptr) + lhd = lhm->absolutePath(); + if (rhm != nullptr) + rhd = rhm->absolutePath(); + QString lhp = lhd.absoluteFilePath(lhs); + QString rhp = rhd.absoluteFilePath(rhs); + return QFileInfo(lhp).lastModified() < QFileInfo(rhp).lastModified(); + }); QString filePath = organizer()->profile()->absolutePath() + "/Morrowind.ini"; if (!organizer()->profile()->localSettingsEnabled()) { - filePath = organizer()->managedGame()->gameDirectory().absolutePath() + "/Morrowind.ini"; + filePath = + organizer()->managedGame()->gameDirectory().absolutePath() + "/Morrowind.ini"; } wchar_t buffer[256]; QStringList result; @@ -169,9 +178,10 @@ QStringList MorrowindGamePlugins::readPluginList(MOBase::IPluginList *pluginList QStringList activePlugins; QStringList inactivePlugins; QString key = "GameFile"; - int i = 0; - while (::GetPrivateProfileStringW(L"Game Files", (key + QString::number(i)).toStdWString().c_str(), - L"", buffer, 256, iniFileW.c_str()) != 0) { + int i = 0; + while (::GetPrivateProfileStringW(L"Game Files", + (key + QString::number(i)).toStdWString().c_str(), + L"", buffer, 256, iniFileW.c_str()) != 0) { QString pluginName; pluginName = QString::fromStdWString(buffer).trimmed(); pluginList->setState(pluginName, IPluginList::STATE_ACTIVE); @@ -180,11 +190,11 @@ QStringList MorrowindGamePlugins::readPluginList(MOBase::IPluginList *pluginList } // we removed each plugin found in the file, so what's left are inactive mods - for (const QString &pluginName : plugins) + for (const QString& pluginName : plugins) if (!activePlugins.contains(pluginName)) inactivePlugins.push_back(pluginName); - for (const QString &pluginName : inactivePlugins) + for (const QString& pluginName : inactivePlugins) pluginList->setState(pluginName, IPluginList::STATE_INACTIVE); return primary + plugins; diff --git a/src/games/morrowind/src/morrowindgameplugins.h b/src/games/morrowind/src/morrowindgameplugins.h index 81c31a0c..37bc219b 100644 --- a/src/games/morrowind/src/morrowindgameplugins.h +++ b/src/games/morrowind/src/morrowindgameplugins.h @@ -7,22 +7,22 @@ class MorrowindGamePlugins : public GamebryoGamePlugins { public: - MorrowindGamePlugins(MOBase::IOrganizer *organizer); - - virtual void writePluginLists(const MOBase::IPluginList *pluginList) override; - virtual void readPluginLists(MOBase::IPluginList *pluginList) override; - + MorrowindGamePlugins(MOBase::IOrganizer* organizer); + + virtual void writePluginLists(const MOBase::IPluginList* pluginList) override; + virtual void readPluginLists(MOBase::IPluginList* pluginList) override; + protected: - virtual void writePluginList(const MOBase::IPluginList *pluginList, const QString &filePath) override; - virtual QStringList readPluginList(MOBase::IPluginList *pluginList) override; - + virtual void writePluginList(const MOBase::IPluginList* pluginList, + const QString& filePath) override; + virtual QStringList readPluginList(MOBase::IPluginList* pluginList) override; + private: - virtual void writeList(const MOBase::IPluginList *pluginList, const QString &filePath, - bool loadOrder); + virtual void writeList(const MOBase::IPluginList* pluginList, const QString& filePath, + bool loadOrder); private: QDateTime m_LastRead; - }; -#endif // MORROWINDGAMEPLUGINS_H \ No newline at end of file +#endif // MORROWINDGAMEPLUGINS_H diff --git a/src/games/morrowind/src/morrowindlocalsavegames.cpp b/src/games/morrowind/src/morrowindlocalsavegames.cpp index e4f2ce83..f33eb1d4 100644 --- a/src/games/morrowind/src/morrowindlocalsavegames.cpp +++ b/src/games/morrowind/src/morrowindlocalsavegames.cpp @@ -16,20 +16,18 @@ License along with this library; if not, write to the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA */ - #include "morrowindlocalsavegames.h" -#include #include -#include +#include #include #include +#include - -MorrowindLocalSavegames::MorrowindLocalSavegames(const MOBase::IPluginGame *game) - : m_GamePlugin(game) +MorrowindLocalSavegames::MorrowindLocalSavegames(const MOBase::IPluginGame* game) + : m_GamePlugin(game) {} -bool MorrowindLocalSavegames::prepareProfile(MOBase::IProfile *profile) +bool MorrowindLocalSavegames::prepareProfile(MOBase::IProfile* profile) { bool dirty = false; @@ -52,13 +50,8 @@ bool MorrowindLocalSavegames::prepareProfile(MOBase::IProfile *profile) return dirty; } - -MappingType MorrowindLocalSavegames::mappings(const QDir &profileSaveDir) const +MappingType MorrowindLocalSavegames::mappings(const QDir& profileSaveDir) const { - return {{ - profileSaveDir.absolutePath(), - m_GamePlugin->gameDirectory().absoluteFilePath("Saves"), - true, - true - }}; -} \ No newline at end of file + return {{profileSaveDir.absolutePath(), + m_GamePlugin->gameDirectory().absoluteFilePath("Saves"), true, true}}; +} diff --git a/src/games/morrowind/src/morrowindlocalsavegames.h b/src/games/morrowind/src/morrowindlocalsavegames.h index a91114e7..e391e123 100644 --- a/src/games/morrowind/src/morrowindlocalsavegames.h +++ b/src/games/morrowind/src/morrowindlocalsavegames.h @@ -16,31 +16,26 @@ License along with this library; if not, write to the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA */ - #ifndef MORROWINDLOCALSAVEGAMES_H #define MORROWINDLOCALSAVEGAMES_H - #include +#include "iplugingame.h" #include #include -#include "iplugingame.h" class MorrowindLocalSavegames : public MOBase::LocalSavegames { public: - MorrowindLocalSavegames(const MOBase::IPluginGame *game); + MorrowindLocalSavegames(const MOBase::IPluginGame* game); - virtual MappingType mappings(const QDir &profileSaveDir) const override; - virtual bool prepareProfile(MOBase::IProfile *profile) override; + virtual MappingType mappings(const QDir& profileSaveDir) const override; + virtual bool prepareProfile(MOBase::IProfile* profile) override; private: - - const MOBase::IPluginGame *m_GamePlugin; - + const MOBase::IPluginGame* m_GamePlugin; }; - -#endif // MORROWINDLOCALSAVEGAMES_H +#endif // MORROWINDLOCALSAVEGAMES_H diff --git a/src/games/morrowind/src/morrowindmoddatachecker.h b/src/games/morrowind/src/morrowindmoddatachecker.h index 68b5e066..a67c1a5c 100644 --- a/src/games/morrowind/src/morrowindmoddatachecker.h +++ b/src/games/morrowind/src/morrowindmoddatachecker.h @@ -9,19 +9,18 @@ public: using GamebryoModDataChecker::GamebryoModDataChecker; protected: - virtual const FileNameSet& possibleFolderNames() const override { - static FileNameSet result{ - "fonts", "meshes", "music", "shaders", "sound", "textures", "video", - "mwse", "distantland", "mits", "icons", "bookart", "splash" - }; + virtual const FileNameSet& possibleFolderNames() const override + { + static FileNameSet result{"fonts", "meshes", "music", "shaders", "sound", + "textures", "video", "mwse", "distantland", "mits", + "icons", "bookart", "splash"}; return result; } - virtual const FileNameSet& possibleFileExtensions() const override { - static FileNameSet result{ - "esp", "esm", "bsa", "modgroups" - }; + virtual const FileNameSet& possibleFileExtensions() const override + { + static FileNameSet result{"esp", "esm", "bsa", "modgroups"}; return result; } }; -#endif // MORROWIND_MODATACHECKER_H +#endif // MORROWIND_MODATACHECKER_H diff --git a/src/games/morrowind/src/morrowindmoddatacontent.h b/src/games/morrowind/src/morrowindmoddatacontent.h index 42c81b4c..b8c9af5e 100644 --- a/src/games/morrowind/src/morrowindmoddatacontent.h +++ b/src/games/morrowind/src/morrowindmoddatacontent.h @@ -4,20 +4,21 @@ #include #include -class MorrowindModDataContent : public GamebryoModDataContent { +class MorrowindModDataContent : public GamebryoModDataContent +{ public: - /** * */ - MorrowindModDataContent(MOBase::IGameFeatures const* gameFeatures) : GamebryoModDataContent(gameFeatures) { + MorrowindModDataContent(MOBase::IGameFeatures const* gameFeatures) + : GamebryoModDataContent(gameFeatures) + { // Just need to disable some contents: - m_Enabled[CONTENT_MCM] = false; - m_Enabled[CONTENT_SKYPROC] = false; + m_Enabled[CONTENT_MCM] = false; + m_Enabled[CONTENT_SKYPROC] = false; m_Enabled[CONTENT_INTERFACE] = false; - m_Enabled[CONTENT_SCRIPT] = false; + m_Enabled[CONTENT_SCRIPT] = false; } - }; -#endif // MORROWIND_MODDATACONTENT_H +#endif // MORROWIND_MODDATACONTENT_H diff --git a/src/games/morrowind/src/morrowindsavegame.cpp b/src/games/morrowind/src/morrowindsavegame.cpp index 79ea868c..97cecdc8 100644 --- a/src/games/morrowind/src/morrowindsavegame.cpp +++ b/src/games/morrowind/src/morrowindsavegame.cpp @@ -1,12 +1,12 @@ #include "morrowindsavegame.h" -#include #include #include +#include #include -MorrowindSaveGame::MorrowindSaveGame(QString const &fileName, GameMorrowind const *game) : - GamebryoSaveGame(fileName, game) +MorrowindSaveGame::MorrowindSaveGame(QString const& fileName, GameMorrowind const* game) + : GamebryoSaveGame(fileName, game) { std::filesystem::path realFile(fileName.toStdWString()); QString realFileName = QString::fromStdWString(realFile.filename().wstring()); @@ -14,16 +14,13 @@ MorrowindSaveGame::MorrowindSaveGame(QString const &fileName, GameMorrowind cons FileWrapper file(fileName, "TES3"); QStringList dummyPlugins; - fetchInformationFields(file, m_SaveName, dummyPlugins, - m_PCCurrentHealth, m_PCCMaxHealth, m_PCLocation, m_GameDays, m_PCName); + fetchInformationFields(file, m_SaveName, dummyPlugins, m_PCCurrentHealth, + m_PCCMaxHealth, m_PCLocation, m_GameDays, m_PCName); } QString MorrowindSaveGame::getName() const { - return QString("%1, #%2, %3") - .arg(m_PCName) - .arg(m_SaveNumber) - .arg(m_PCLocation); + return QString("%1, #%2, %3").arg(m_PCName).arg(m_SaveNumber).arg(m_PCLocation); } unsigned short MorrowindSaveGame::getPCLevel() const @@ -31,53 +28,53 @@ unsigned short MorrowindSaveGame::getPCLevel() const return dynamic_cast(m_DataFields.value().get())->PCLevel; } - - // Fetch easy-to-access information. -void MorrowindSaveGame::fetchInformationFields(FileWrapper& file, - QString& saveName, - QStringList& plugins, - float& playerCurrentHealth, - float& playerMaxHealth, - QString& playerLocation, - float& gameDays, - QString& playerName) const +void MorrowindSaveGame::fetchInformationFields(FileWrapper& file, QString& saveName, + QStringList& plugins, + float& playerCurrentHealth, + float& playerMaxHealth, + QString& playerLocation, float& gameDays, + QString& playerName) const { - file.skip(3); // data size - file.skip(4); // HEDR tag - file.skip(); // header size - file.skip(); // header version - file.skip(); // following data chunk size? seems to be 9 groupings of 32 bytes - file.skip(32); // Author empty for save files - std::vector saveNameBuffer(256); // 31 char save name with a null terminator + file.skip(3); // data size + file.skip(4); // HEDR tag + file.skip(); // header size + file.skip(); // header version + file.skip(); // following data chunk size? seems to be 9 groupings of 32 + // bytes + file.skip(32); // Author empty for save files + std::vector saveNameBuffer(256); // 31 char save name with a null terminator file.read(saveNameBuffer.data(), 256); - saveName = QString::fromLatin1(saveNameBuffer.data(), 256).trimmed(); // The defined save name. This is technically the description, but is likely only 31+\0 chars max. - file.skip(); // NumRecords (for the entire save) + saveName = QString::fromLatin1(saveNameBuffer.data(), 256) + .trimmed(); // The defined save name. This is technically the + // description, but is likely only 31+\0 chars max. + file.skip(); // NumRecords (for the entire save) std::vector buffer(255); file.read(buffer.data(), 4); // Parse the MAST/DATA records while (QString::fromLatin1(buffer.data(), 4) == "MAST") { uint32_t len; - file.read(len); // Length of master name - file.read(buffer.data(), len); // Name of master + file.read(len); // Length of master name + file.read(buffer.data(), len); // Name of master QString name = QString::fromLatin1(buffer.data(), len - 1); - file.skip(4); // DATA record - file.read(len); // Length - file.skip(len); // Typically size 8 - contains length of master data for version checking + file.skip(4); // DATA record + file.read(len); // Length + file.skip( + len); // Typically size 8 - contains length of master data for version checking - file.read(buffer.data(), 4); // Get next record type + file.read(buffer.data(), 4); // Get next record type plugins.push_back(name); } // Start of GMDT - file.skip(); // size of record + file.skip(); // size of record file.read(playerCurrentHealth); file.read(playerMaxHealth); - file.skip(); // current stam? - file.skip(); // max stam? - //file.skip(2); // unknown values + file.skip(); // current stam? + file.skip(); // max stam? + // file.skip(2); // unknown values file.read(buffer.data(), 64); playerLocation = QString::fromLatin1(buffer.data(), 64).trimmed(); @@ -100,29 +97,29 @@ std::unique_ptr MorrowindSaveGame::fetchDataFields { QString dummy; float dummyF; - fetchInformationFields(file, dummy, fields->Plugins, - dummyF, dummyF, dummy, dummyF, dummy); + fetchInformationFields(file, dummy, fields->Plugins, dummyF, dummyF, dummy, dummyF, + dummy); } - file.skip(28); // Skip the SCRD - // I believe this tells the engine what color each pixel represents and the bitness of the image + file.skip(28); // Skip the SCRD + // I believe this tells the engine what color each pixel represents and the bitness of + // the image // Start of screenshot - file.skip(4); // SCRS - file.skip(); // Size of screenshot always 65536 (128x128x4) RGBA8888 + file.skip(4); // SCRS + file.skip(); // Size of screenshot always 65536 (128x128x4) RGBA8888 - QImage image = readImageBGRA(file, 128, 128, 0, 1); + QImage image = readImageBGRA(file, 128, 128, 0, 1); fields->Screenshot = image.scaled(252, 192); - //definitively have to use another method to access the player level - //it is stored in the fifth byte of the NPDT subrecord of the first NPC_ record + // definitively have to use another method to access the player level + // it is stored in the fifth byte of the NPDT subrecord of the first NPC_ record - //Globals, Scripts, Regions - //file.skip(); + // Globals, Scripts, Regions + // file.skip(); std::vector buff(4); file.read(buff.data(), 4); - while (QString::fromLatin1(buff.data(), 4) != "NPC_") - { + while (QString::fromLatin1(buff.data(), 4) != "NPC_") { uint32_t len; file.read(len); file.skip(8 + len); @@ -137,8 +134,7 @@ std::unique_ptr MorrowindSaveGame::fetchDataFields file.read(buffer.data(), len); if (QString::fromLatin1(buffer.data(), len - 1) == "player") { file.read(buff.data(), 4); - while (QString::fromLatin1(buff.data(), 4) != "NPDT") - { + while (QString::fromLatin1(buff.data(), 4) != "NPDT") { uint32_t len; file.read(len); file.skip(len); @@ -146,9 +142,7 @@ std::unique_ptr MorrowindSaveGame::fetchDataFields } file.skip(); file.read(fields->PCLevel); - } - else - { + } else { file.skip(size - len - 8); } } @@ -156,7 +150,9 @@ std::unique_ptr MorrowindSaveGame::fetchDataFields return fields; } -QImage MorrowindSaveGame::readImageBGRA(GamebryoSaveGame::FileWrapper &file, unsigned long width, unsigned long height, int scale = 0, bool alpha = false) const +QImage MorrowindSaveGame::readImageBGRA(GamebryoSaveGame::FileWrapper& file, + unsigned long width, unsigned long height, + int scale = 0, bool alpha = false) const { QImage image(width, height, QImage::Format_RGBA8888); for (unsigned long h = 0; h < width; h++) { @@ -178,4 +174,4 @@ QImage MorrowindSaveGame::readImageBGRA(GamebryoSaveGame::FileWrapper &file, uns return image.copy().scaledToWidth(scale); else return image.copy(); -} \ No newline at end of file +} diff --git a/src/games/morrowind/src/morrowindsavegame.h b/src/games/morrowind/src/morrowindsavegame.h index 439f632f..b4ea9602 100644 --- a/src/games/morrowind/src/morrowindsavegame.h +++ b/src/games/morrowind/src/morrowindsavegame.h @@ -4,15 +4,17 @@ #include "gamebryosavegame.h" #include "gamemorrowind.h" -namespace MOBase { class IPluginGame; } +namespace MOBase +{ +class IPluginGame; +} class MorrowindSaveGame : public GamebryoSaveGame { public: - MorrowindSaveGame(QString const &fileName, GameMorrowind const *game); - -public: // ISaveGame interface + MorrowindSaveGame(QString const& fileName, GameMorrowind const* game); +public: // ISaveGame interface // We need to override getName() because we do not read the level at // the beginning. virtual QString getName() const override; @@ -21,7 +23,7 @@ public: // ISaveGame interface unsigned short getPCLevel() const override; public: - //Simple getters + // Simple getters QString getSaveName() const { return m_SaveName; } float getPCCurrentHealth() const { return m_PCCurrentHealth; } float getPCMaxHealth() const { return m_PCCMaxHealth; } @@ -34,28 +36,22 @@ protected: float m_GameDays; protected: - QImage readImageBGRA( - GamebryoSaveGame::FileWrapper &file, unsigned long width, - unsigned long height, int scale, bool alpha) const; + QImage readImageBGRA(GamebryoSaveGame::FileWrapper& file, unsigned long width, + unsigned long height, int scale, bool alpha) const; // We need to add the PC level here. - struct MorrowindDataFields : public DataFields { + struct MorrowindDataFields : public DataFields + { unsigned short PCLevel = 0; }; // Fetch easy-to-access information. - void fetchInformationFields( - FileWrapper& file, - QString& saveName, - QStringList& plugins, - float& playerCurrentHealth, - float& playerMaxHealth, - QString& playerLocation, - float& gameDays, - QString& playerName) const; + void fetchInformationFields(FileWrapper& file, QString& saveName, + QStringList& plugins, float& playerCurrentHealth, + float& playerMaxHealth, QString& playerLocation, + float& gameDays, QString& playerName) const; std::unique_ptr fetchDataFields() const override; - }; -#endif // MORROWINDSAVEGAME_H +#endif // MORROWINDSAVEGAME_H diff --git a/src/games/morrowind/src/morrowindsavegameinfo.cpp b/src/games/morrowind/src/morrowindsavegameinfo.cpp index 8a20aae2..746ea504 100644 --- a/src/games/morrowind/src/morrowindsavegameinfo.cpp +++ b/src/games/morrowind/src/morrowindsavegameinfo.cpp @@ -1,19 +1,18 @@ #include "morrowindsavegameinfo.h" -#include "morrowindsavegameinfowidget.h" -#include "morrowindsavegame.h" #include "gamegamebryo.h" +#include "morrowindsavegame.h" +#include "morrowindsavegameinfowidget.h" -MorrowindSaveGameInfo::MorrowindSaveGameInfo(GameGamebryo const *game) : - GamebryoSaveGameInfo(game) +MorrowindSaveGameInfo::MorrowindSaveGameInfo(GameGamebryo const* game) + : GamebryoSaveGameInfo(game) { - m_Game = dynamic_cast(game); + m_Game = dynamic_cast(game); } -MorrowindSaveGameInfo::~MorrowindSaveGameInfo() -{ -} +MorrowindSaveGameInfo::~MorrowindSaveGameInfo() {} -MOBase::ISaveGameInfoWidget *MorrowindSaveGameInfo::getSaveGameWidget(QWidget *parent) const +MOBase::ISaveGameInfoWidget* +MorrowindSaveGameInfo::getSaveGameWidget(QWidget* parent) const { return new MorrowindSaveGameInfoWidget(this, parent); } diff --git a/src/games/morrowind/src/morrowindsavegameinfo.h b/src/games/morrowind/src/morrowindsavegameinfo.h index 3a081a88..ff4bc55c 100644 --- a/src/games/morrowind/src/morrowindsavegameinfo.h +++ b/src/games/morrowind/src/morrowindsavegameinfo.h @@ -9,14 +9,14 @@ class GameGamebryo; class MorrowindSaveGameInfo : public GamebryoSaveGameInfo { public: - MorrowindSaveGameInfo(GameGamebryo const *game); + MorrowindSaveGameInfo(GameGamebryo const* game); ~MorrowindSaveGameInfo(); - virtual MOBase::ISaveGameInfoWidget *getSaveGameWidget(QWidget *) const override; + virtual MOBase::ISaveGameInfoWidget* getSaveGameWidget(QWidget*) const override; protected: friend class MorrowindSaveGameInfoWidget; - GameMorrowind const *m_Game; + GameMorrowind const* m_Game; }; -#endif // MORROWINDSAVEGAMEINFO_H +#endif // MORROWINDSAVEGAMEINFO_H diff --git a/src/games/morrowind/src/morrowindsavegameinfowidget.cpp b/src/games/morrowind/src/morrowindsavegameinfowidget.cpp index e61ef392..9e098fb1 100644 --- a/src/games/morrowind/src/morrowindsavegameinfowidget.cpp +++ b/src/games/morrowind/src/morrowindsavegameinfowidget.cpp @@ -2,15 +2,15 @@ #include "ui_morrowindsavegameinfowidget.h" #include "gamemorrowind.h" -#include "morrowindsavegame.h" -#include "morrowindsavegameinfo.h" #include "imoinfo.h" #include "ipluginlist.h" +#include "morrowindsavegame.h" +#include "morrowindsavegameinfo.h" #include #include -#include #include +#include #include #include #include @@ -25,42 +25,52 @@ #include -MorrowindSaveGameInfoWidget::MorrowindSaveGameInfoWidget(MorrowindSaveGameInfo const *info, - QWidget *parent) - : MOBase::ISaveGameInfoWidget(parent), ui(new Ui::MorrowindSaveGameInfoWidget), m_Info(info) { +MorrowindSaveGameInfoWidget::MorrowindSaveGameInfoWidget( + MorrowindSaveGameInfo const* info, QWidget* parent) + : MOBase::ISaveGameInfoWidget(parent), ui(new Ui::MorrowindSaveGameInfoWidget), + m_Info(info) +{ ui->setupUi(this); this->setWindowFlags(Qt::ToolTip | Qt::BypassGraphicsProxyWidget); - setWindowOpacity(style()->styleHint(QStyle::SH_ToolTipLabel_Opacity, 0, this) / qreal(255.0)); + setWindowOpacity(style()->styleHint(QStyle::SH_ToolTipLabel_Opacity, 0, this) / + qreal(255.0)); ui->gameFrame->setStyleSheet("background-color: transparent;"); - QVBoxLayout *gameLayout = new QVBoxLayout(); + QVBoxLayout* gameLayout = new QVBoxLayout(); gameLayout->setContentsMargins(0, 0, 0, 0); gameLayout->setSpacing(2); ui->gameFrame->setLayout(gameLayout); } -MorrowindSaveGameInfoWidget::~MorrowindSaveGameInfoWidget() { +MorrowindSaveGameInfoWidget::~MorrowindSaveGameInfoWidget() +{ delete ui; } -void MorrowindSaveGameInfoWidget::setSave(MOBase::ISaveGame const& save) { +void MorrowindSaveGameInfoWidget::setSave(MOBase::ISaveGame const& save) +{ auto const& morrowindSave = dynamic_cast(save); - ui->saveNameLabel->setText(QString("%1 (Day %2)").arg(morrowindSave.getSaveName()).arg(morrowindSave.getGameDays())); + ui->saveNameLabel->setText(QString("%1 (Day %2)") + .arg(morrowindSave.getSaveName()) + .arg(morrowindSave.getGameDays())); ui->saveNumLabel->setText(QString("%1").arg(morrowindSave.getSaveNumber())); - ui->healthLabel->setText(QString("%1 / %2").arg(round(morrowindSave.getPCCurrentHealth())).arg(morrowindSave.getPCMaxHealth())); + ui->healthLabel->setText(QString("%1 / %2") + .arg(round(morrowindSave.getPCCurrentHealth())) + .arg(morrowindSave.getPCMaxHealth())); ui->characterLabel->setText(morrowindSave.getPCName()); ui->locationLabel->setText(morrowindSave.getPCLocation()); ui->levelLabel->setText(QString("%1").arg(morrowindSave.getPCLevel())); - //This somewhat contorted code is because on my system at least, the - //old way of doing this appears to give short date and long time. + // This somewhat contorted code is because on my system at least, the + // old way of doing this appears to give short date and long time. QDateTime t = morrowindSave.getCreationTime(); - ui->dateLabel->setText(QLocale::system().toString(t.date(), QLocale::FormatType::ShortFormat) + " " + + ui->dateLabel->setText( + QLocale::system().toString(t.date(), QLocale::FormatType::ShortFormat) + " " + QLocale::system().toString(t.time(), QLocale::FormatType::ShortFormat)); ui->screenshotLabel->setPixmap(QPixmap::fromImage(morrowindSave.getScreenshot())); if (ui->gameFrame->layout() != nullptr) { - QLayoutItem *item = nullptr; + QLayoutItem* item = nullptr; while ((item = ui->gameFrame->layout()->takeAt(0)) != nullptr) { delete item->widget(); delete item; @@ -71,18 +81,18 @@ void MorrowindSaveGameInfoWidget::setSave(MOBase::ISaveGame const& save) { // Resize box to new content this->resize(0, 0); - QLayout *layout = ui->gameFrame->layout(); - QLabel *header = new QLabel(tr("Missing ESPs")); - QFont headerFont = header->font(); + QLayout* layout = ui->gameFrame->layout(); + QLabel* header = new QLabel(tr("Missing ESPs")); + QFont headerFont = header->font(); QFont contentFont = headerFont; headerFont.setItalic(true); contentFont.setBold(true); contentFont.setPointSize(7); header->setFont(headerFont); layout->addWidget(header); - int count = 0; - MOBase::IPluginList *pluginList = m_Info->m_Game->m_Organizer->pluginList(); - for (QString const &pluginName : morrowindSave.getPlugins()) { + int count = 0; + MOBase::IPluginList* pluginList = m_Info->m_Game->m_Organizer->pluginList(); + for (QString const& pluginName : morrowindSave.getPlugins()) { if (pluginList->state(pluginName) == MOBase::IPluginList::STATE_ACTIVE) { continue; } @@ -93,19 +103,19 @@ void MorrowindSaveGameInfoWidget::setSave(MOBase::ISaveGame const& save) { break; } - QLabel *pluginLabel = new QLabel(pluginName); + QLabel* pluginLabel = new QLabel(pluginName); pluginLabel->setIndent(10); pluginLabel->setFont(contentFont); layout->addWidget(pluginLabel); } if (count > 7) { - QLabel *dotDotLabel = new QLabel("..."); + QLabel* dotDotLabel = new QLabel("..."); dotDotLabel->setIndent(10); dotDotLabel->setFont(contentFont); layout->addWidget(dotDotLabel); } if (count == 0) { - QLabel *dotDotLabel = new QLabel(tr("None")); + QLabel* dotDotLabel = new QLabel(tr("None")); dotDotLabel->setIndent(10); dotDotLabel->setFont(contentFont); layout->addWidget(dotDotLabel); diff --git a/src/games/morrowind/src/morrowindsavegameinfowidget.h b/src/games/morrowind/src/morrowindsavegameinfowidget.h index df0628bd..af27bc3e 100644 --- a/src/games/morrowind/src/morrowindsavegameinfowidget.h +++ b/src/games/morrowind/src/morrowindsavegameinfowidget.h @@ -8,21 +8,24 @@ class GamebryoGame; -namespace Ui { class MorrowindSaveGameInfoWidget; } +namespace Ui +{ +class MorrowindSaveGameInfoWidget; +} class MorrowindSaveGameInfoWidget : public MOBase::ISaveGameInfoWidget { Q_OBJECT public: - MorrowindSaveGameInfoWidget(MorrowindSaveGameInfo const *info, QWidget *parent); + MorrowindSaveGameInfoWidget(MorrowindSaveGameInfo const* info, QWidget* parent); ~MorrowindSaveGameInfoWidget(); virtual void setSave(MOBase::ISaveGame const&) override; private: - Ui::MorrowindSaveGameInfoWidget *ui; - MorrowindSaveGameInfo const *m_Info; + Ui::MorrowindSaveGameInfoWidget* ui; + MorrowindSaveGameInfo const* m_Info; }; -#endif // MORROWINDSAVEGAMEINFOWIDGET_H +#endif // MORROWINDSAVEGAMEINFOWIDGET_H From a270dcf33777cae2bccc2bc2488763fc15077efa Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Mika=C3=ABl=20Capelle?= Date: Sun, 9 Jun 2024 13:29:34 +0200 Subject: [PATCH 1480/1544] [game_morrowind] Add .git-blame-ignore-revs. --- src/games/morrowind/.git-blame-ignore-revs | 1 + 1 file changed, 1 insertion(+) create mode 100644 src/games/morrowind/.git-blame-ignore-revs diff --git a/src/games/morrowind/.git-blame-ignore-revs b/src/games/morrowind/.git-blame-ignore-revs new file mode 100644 index 00000000..2f79742b --- /dev/null +++ b/src/games/morrowind/.git-blame-ignore-revs @@ -0,0 +1 @@ +ee98ea2db30bca29fc57d7abc96039ba7fe7ef94 From 121440e34e1d76c545fbc807594253ddca4af9be Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Mika=C3=ABl=20Capelle?= Date: Sun, 9 Jun 2024 13:29:34 +0200 Subject: [PATCH 1481/1544] [game_morrowind] Add github actions. --- src/games/morrowind/.github/workflows/build.yml | 16 ++++++++++++++++ .../morrowind/.github/workflows/linting.yml | 16 ++++++++++++++++ 2 files changed, 32 insertions(+) create mode 100644 src/games/morrowind/.github/workflows/build.yml create mode 100644 src/games/morrowind/.github/workflows/linting.yml diff --git a/src/games/morrowind/.github/workflows/build.yml b/src/games/morrowind/.github/workflows/build.yml new file mode 100644 index 00000000..e9c89a23 --- /dev/null +++ b/src/games/morrowind/.github/workflows/build.yml @@ -0,0 +1,16 @@ +name: Build Morrowind Plugin + +on: + push: + branches: master + pull_request: + types: [opened, synchronize, reopened] + +jobs: + build: + runs-on: windows-2022 + steps: + - name: Build Morrowind Plugin + uses: ModOrganizer2/build-with-mob-action@master + with: + mo2-dependencies: cmake_common uibase game_gamebryo diff --git a/src/games/morrowind/.github/workflows/linting.yml b/src/games/morrowind/.github/workflows/linting.yml new file mode 100644 index 00000000..e890595d --- /dev/null +++ b/src/games/morrowind/.github/workflows/linting.yml @@ -0,0 +1,16 @@ +name: Lint Morrowind Plugin + +on: + push: + pull_request: + types: [opened, synchronize, reopened] + +jobs: + lint: + runs-on: ubuntu-latest + steps: + - uses: actions/checkout@v3 + - name: Check format + uses: ModOrganizer2/check-formatting-action@master + with: + check-path: "." From 1026fe01f4f413901588491eb7cbf3f4b6ca5bf7 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Mika=C3=ABl=20Capelle?= Date: Sun, 9 Jun 2024 13:29:50 +0200 Subject: [PATCH 1482/1544] [game_oblivion] Remove appveyor.yml. --- src/games/oblivion/appveyor.yml | 40 --------------------------------- 1 file changed, 40 deletions(-) delete mode 100644 src/games/oblivion/appveyor.yml diff --git a/src/games/oblivion/appveyor.yml b/src/games/oblivion/appveyor.yml deleted file mode 100644 index 998a5f8b..00000000 --- a/src/games/oblivion/appveyor.yml +++ /dev/null @@ -1,40 +0,0 @@ -version: 1.0.{build} -skip_branch_with_pr: true -image: Visual Studio 2019 -environment: - WEBHOOK_URL: - secure: gOKbXaZM9ImtMD5XrYITvdyZUW/az082G9OIN1EC1Vbg57wBaeLhi49uGjxPw5GVujHku6kxN6ab89zhbS5GVeluR76GM83IbKV4Sh7udXzoYZZdg6YudtYHzdhCgUeiedpswbuczTq9ceIkkfSEWZuh/lMAAVVwvcGsJAnoPFw= -build_script: -- pwsh: >- - $ErrorActionPreference = 'Stop' - - git clone --depth=1 --no-single-branch https://github.com/ModOrganizer2/modorganizer-umbrella.git c:\projects\modorganizer-umbrella - - New-Item -ItemType Directory -Path c:\projects\modorganizer-build - - cd c:\projects\modorganizer-umbrella - - ($env:APPVEYOR_PULL_REQUEST_HEAD_REPO_BRANCH -eq $null) ? ($branch = $env:APPVEYOR_REPO_BRANCH) : ($branch = $env:APPVEYOR_PULL_REQUEST_HEAD_REPO_BRANCH) - - git checkout $(git show-ref --verify --quiet refs/remotes/origin/${branch} || echo '-b') ${branch} - - C:\Python37-x64\python.exe unimake.py -d c:\projects\modorganizer-build -s Appveyor_Build=True ${env:APPVEYOR_PROJECT_NAME} - - if($LastExitCode -ne 0) { $host.SetShouldExit($LastExitCode ) } -artifacts: -- path: vsbuild\src\RelWithDebInfo\game_oblivion.dll - name: game_oblivion_dll -- path: vsbuild\src\RelWithDebInfo\game_oblivion.pdb - name: game_oblivion_pdb -- path: vsbuild\src\RelWithDebInfo\game_oblivion.lib - name: game_oblivion_lib -on_success: - - ps: Set-Location -Path $env:APPVEYOR_BUILD_FOLDER - - ps: Invoke-RestMethod https://raw.githubusercontent.com/DiscordHooks/appveyor-discord-webhook/master/send.ps1 -o send.ps1 - - ps: ./send.ps1 success $env:WEBHOOK_URL -on_failure: - - ps: Set-Location -Path $env:APPVEYOR_BUILD_FOLDER - - ps: Push-AppveyorArtifact ${env:APPVEYOR_BUILD_FOLDER}\stdout.log - - ps: Push-AppveyorArtifact ${env:APPVEYOR_BUILD_FOLDER}\stderr.log - - ps: Invoke-RestMethod https://raw.githubusercontent.com/DiscordHooks/appveyor-discord-webhook/master/send.ps1 -o send.ps1 - - ps: ./send.ps1 failure $env:WEBHOOK_URL \ No newline at end of file From 4de55f38cd6f394e0266836a721c2d8000e38416 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Mika=C3=ABl=20Capelle?= Date: Sun, 9 Jun 2024 13:29:50 +0200 Subject: [PATCH 1483/1544] [game_oblivion] Format files and add .gitattributes and .clang-format. --- src/games/oblivion/.clang-format | 41 ++ src/games/oblivion/.gitattributes | 7 + src/games/oblivion/src/gameoblivion.cpp | 382 +++++++++--------- src/games/oblivion/src/gameoblivion.h | 103 +++-- .../oblivion/src/oblivionbsainvalidation.cpp | 33 +- .../oblivion/src/oblivionbsainvalidation.h | 43 +- .../oblivion/src/obliviondataarchives.cpp | 72 ++-- src/games/oblivion/src/obliviondataarchives.h | 53 ++- .../oblivion/src/oblivionmoddatachecker.cpp | 8 +- .../oblivion/src/oblivionmoddatachecker.h | 31 +- .../oblivion/src/oblivionmoddatacontent.h | 13 +- src/games/oblivion/src/oblivionsavegame.cpp | 47 +-- src/games/oblivion/src/oblivionsavegame.h | 14 +- .../oblivion/src/oblivionscriptextender.cpp | 43 +- .../oblivion/src/oblivionscriptextender.h | 37 +- 15 files changed, 483 insertions(+), 444 deletions(-) create mode 100644 src/games/oblivion/.clang-format create mode 100644 src/games/oblivion/.gitattributes diff --git a/src/games/oblivion/.clang-format b/src/games/oblivion/.clang-format new file mode 100644 index 00000000..6098e1f5 --- /dev/null +++ b/src/games/oblivion/.clang-format @@ -0,0 +1,41 @@ +--- +# We'll use defaults from the LLVM style, but with 4 columns indentation. +BasedOnStyle: LLVM +IndentWidth: 2 +--- +Language: Cpp +DeriveLineEnding: false +UseCRLF: true +DerivePointerAlignment: false +PointerAlignment: Left +AlignConsecutiveAssignments: true +AllowShortFunctionsOnASingleLine: Inline +AllowShortIfStatementsOnASingleLine: Never +AllowShortLambdasOnASingleLine: Empty +AlwaysBreakTemplateDeclarations: Yes +AccessModifierOffset: -2 +AlignTrailingComments: true +SpacesBeforeTrailingComments: 2 +NamespaceIndentation: Inner +MaxEmptyLinesToKeep: 1 +BreakBeforeBraces: Custom +BraceWrapping: + AfterCaseLabel: false + AfterClass: true + AfterControlStatement: false + AfterEnum: true + AfterFunction: true + AfterNamespace: true + AfterStruct: true + AfterUnion: true + AfterExternBlock: true + BeforeCatch: false + BeforeElse: false + BeforeLambdaBody: false + BeforeWhile: false + IndentBraces: false + SplitEmptyFunction: false + SplitEmptyRecord: false + SplitEmptyNamespace: true +ColumnLimit: 88 +ForEachMacros: ['Q_FOREACH', 'foreach'] diff --git a/src/games/oblivion/.gitattributes b/src/games/oblivion/.gitattributes new file mode 100644 index 00000000..f8697127 --- /dev/null +++ b/src/games/oblivion/.gitattributes @@ -0,0 +1,7 @@ +# Set the default behavior, in case people don't have core.autocrlf set. +* text=auto + +# Explicitly declare text files you want to always be normalized and converted +# to native line endings on checkout. +*.cpp text eol=crlf +*.h text eol=crlf diff --git a/src/games/oblivion/src/gameoblivion.cpp b/src/games/oblivion/src/gameoblivion.cpp index 6d8a1e9f..537948d5 100644 --- a/src/games/oblivion/src/gameoblivion.cpp +++ b/src/games/oblivion/src/gameoblivion.cpp @@ -1,189 +1,193 @@ -#include "gameoblivion.h" - -#include "oblivionbsainvalidation.h" -#include "obliviondataarchives.h" -#include "oblivionscriptextender.h" -#include "oblivionmoddatachecker.h" -#include "oblivionmoddatacontent.h" -#include "oblivionsavegame.h" - -#include "pluginsetting.h" -#include "executableinfo.h" -#include -#include -#include -#include - -#include -#include -#include - -#include - -using namespace MOBase; - -GameOblivion::GameOblivion() -{ -} - -bool GameOblivion::init(IOrganizer *moInfo) -{ - if (!GameGamebryo::init(moInfo)) { - return false; - } - - auto dataArchives = std::make_shared(myGamesPath()); - registerFeature(std::make_shared(this)); - registerFeature(dataArchives); - registerFeature(std::make_shared(dataArchives.get(), this)); - registerFeature(std::make_shared(this)); - registerFeature(std::make_shared(myGamesPath(), "oblivion.ini")); - 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 GameOblivion::gameName() const -{ - return "Oblivion"; -} - -QList GameOblivion::executables() const -{ - return QList() - << ExecutableInfo("Oblivion", findInGameFolder(binaryName())) - << ExecutableInfo("Oblivion Launcher", findInGameFolder(getLauncherName())) - << ExecutableInfo("Oblivion Mod Manager", findInGameFolder("OblivionModManager.exe")) - << ExecutableInfo("BOSS", findInGameFolder("BOSS/BOSS.exe")) - << ExecutableInfo("LOOT", QFileInfo(getLootPath())).withArgument("--game=\"Oblivion\"") - << ExecutableInfo("Construction Set", findInGameFolder("TESConstructionSet.exe")) - ; -} - -QList GameOblivion::executableForcedLoads() const -{ - return QList() - << ExecutableForcedLoadSetting("Oblivion.exe", "obse_1_2_416.dll").withForced().withEnabled() - << ExecutableForcedLoadSetting("TESConstructionSet.exe", "obse_editor_1_2.dll").withForced().withEnabled() - ; -} - -QString GameOblivion::name() const -{ - return "Oblivion Support Plugin"; -} - -QString GameOblivion::localizedName() const -{ - return tr("Oblivion Support Plugin"); -} - -QString GameOblivion::author() const -{ - return "Tannin & MO2 Team"; -} - -QString GameOblivion::description() const -{ - return tr("Adds support for the game Oblivion"); -} - -MOBase::VersionInfo GameOblivion::version() const -{ - return VersionInfo(1, 6, 1, VersionInfo::RELEASE_FINAL); -} - -QList GameOblivion::settings() const -{ - return { - PluginSetting("nehrim_downloads", "allow Nehrim downloads", QVariant(false)) - }; -} - -void GameOblivion::initializeProfile(const QDir &path, ProfileSettings settings) const -{ - if (settings.testFlag(IPluginGame::MODS)) { - copyToProfile(localAppFolder() + "/Oblivion", path, "plugins.txt"); - } - - if (settings.testFlag(IPluginGame::CONFIGURATION)) { - if (settings.testFlag(IPluginGame::PREFER_DEFAULTS) - || !QFileInfo(myGamesPath() + "/oblivion.ini").exists()) { - copyToProfile(gameDirectory().absolutePath(), path, "oblivion_default.ini", "oblivion.ini"); - } else { - copyToProfile(myGamesPath(), path, "oblivion.ini"); - } - - copyToProfile(myGamesPath(), path, "oblivionprefs.ini"); - } -} - -QString GameOblivion::savegameExtension() const -{ - return "ess"; -} - -QString GameOblivion::savegameSEExtension() const -{ - return "obse"; -} - -std::shared_ptr GameOblivion::makeSaveGame(QString filePath) const -{ - return std::make_shared(filePath, this); -} - -QString GameOblivion::steamAPPId() const -{ - return "22330"; -} - -QStringList GameOblivion::primaryPlugins() const -{ - return { "oblivion.esm", "update.esm" }; -} - -QString GameOblivion::gameShortName() const -{ - return "Oblivion"; -} - -QStringList GameOblivion::validShortNames() const -{ - QStringList shortNames; - if (m_Organizer->pluginSetting(name(), "nehrim_downloads").toBool()) { - shortNames.append( "Nehrim" ); - } - return shortNames; -} - -QString GameOblivion::gameNexusName() const -{ - return "Oblivion"; -} - - -QStringList GameOblivion::iniFiles() const -{ - return { "oblivion.ini", "oblivionprefs.ini" }; -} - -QStringList GameOblivion::DLCPlugins() const -{ - return { "DLCBattlehornCastle.esp", "DLCShiveringIsles.esp", "Knights.esp", "DLCFrostcrag.esp", - "DLCSpellTomes.esp", "DLCMehrunesRazor.esp", "DLCOrrery.esp", - "DLCThievesDen.esp", "DLCVileLair.esp", "DLCHorseArmor.esp" }; -} - - -int GameOblivion::nexusModOrganizerID() const -{ - return 38277; -} - -int GameOblivion::nexusGameID() const -{ - return 101; -} +#include "gameoblivion.h" + +#include "oblivionbsainvalidation.h" +#include "obliviondataarchives.h" +#include "oblivionmoddatachecker.h" +#include "oblivionmoddatacontent.h" +#include "oblivionsavegame.h" +#include "oblivionscriptextender.h" + +#include "executableinfo.h" +#include "pluginsetting.h" +#include +#include +#include +#include + +#include +#include +#include + +#include + +using namespace MOBase; + +GameOblivion::GameOblivion() {} + +bool GameOblivion::init(IOrganizer* moInfo) +{ + if (!GameGamebryo::init(moInfo)) { + return false; + } + + auto dataArchives = std::make_shared(myGamesPath()); + registerFeature(std::make_shared(this)); + registerFeature(dataArchives); + registerFeature(std::make_shared(dataArchives.get(), this)); + registerFeature(std::make_shared(this)); + registerFeature( + std::make_shared(myGamesPath(), "oblivion.ini")); + 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 GameOblivion::gameName() const +{ + return "Oblivion"; +} + +QList GameOblivion::executables() const +{ + return QList() + << ExecutableInfo("Oblivion", findInGameFolder(binaryName())) + << ExecutableInfo("Oblivion Launcher", findInGameFolder(getLauncherName())) + << ExecutableInfo("Oblivion Mod Manager", + findInGameFolder("OblivionModManager.exe")) + << ExecutableInfo("BOSS", findInGameFolder("BOSS/BOSS.exe")) + << ExecutableInfo("LOOT", QFileInfo(getLootPath())) + .withArgument("--game=\"Oblivion\"") + << ExecutableInfo("Construction Set", + findInGameFolder("TESConstructionSet.exe")); +} + +QList GameOblivion::executableForcedLoads() const +{ + return QList() + << ExecutableForcedLoadSetting("Oblivion.exe", "obse_1_2_416.dll") + .withForced() + .withEnabled() + << ExecutableForcedLoadSetting("TESConstructionSet.exe", "obse_editor_1_2.dll") + .withForced() + .withEnabled(); +} + +QString GameOblivion::name() const +{ + return "Oblivion Support Plugin"; +} + +QString GameOblivion::localizedName() const +{ + return tr("Oblivion Support Plugin"); +} + +QString GameOblivion::author() const +{ + return "Tannin & MO2 Team"; +} + +QString GameOblivion::description() const +{ + return tr("Adds support for the game Oblivion"); +} + +MOBase::VersionInfo GameOblivion::version() const +{ + return VersionInfo(1, 6, 1, VersionInfo::RELEASE_FINAL); +} + +QList GameOblivion::settings() const +{ + return {PluginSetting("nehrim_downloads", "allow Nehrim downloads", QVariant(false))}; +} + +void GameOblivion::initializeProfile(const QDir& path, ProfileSettings settings) const +{ + if (settings.testFlag(IPluginGame::MODS)) { + copyToProfile(localAppFolder() + "/Oblivion", path, "plugins.txt"); + } + + if (settings.testFlag(IPluginGame::CONFIGURATION)) { + if (settings.testFlag(IPluginGame::PREFER_DEFAULTS) || + !QFileInfo(myGamesPath() + "/oblivion.ini").exists()) { + copyToProfile(gameDirectory().absolutePath(), path, "oblivion_default.ini", + "oblivion.ini"); + } else { + copyToProfile(myGamesPath(), path, "oblivion.ini"); + } + + copyToProfile(myGamesPath(), path, "oblivionprefs.ini"); + } +} + +QString GameOblivion::savegameExtension() const +{ + return "ess"; +} + +QString GameOblivion::savegameSEExtension() const +{ + return "obse"; +} + +std::shared_ptr +GameOblivion::makeSaveGame(QString filePath) const +{ + return std::make_shared(filePath, this); +} + +QString GameOblivion::steamAPPId() const +{ + return "22330"; +} + +QStringList GameOblivion::primaryPlugins() const +{ + return {"oblivion.esm", "update.esm"}; +} + +QString GameOblivion::gameShortName() const +{ + return "Oblivion"; +} + +QStringList GameOblivion::validShortNames() const +{ + QStringList shortNames; + if (m_Organizer->pluginSetting(name(), "nehrim_downloads").toBool()) { + shortNames.append("Nehrim"); + } + return shortNames; +} + +QString GameOblivion::gameNexusName() const +{ + return "Oblivion"; +} + +QStringList GameOblivion::iniFiles() const +{ + return {"oblivion.ini", "oblivionprefs.ini"}; +} + +QStringList GameOblivion::DLCPlugins() const +{ + return {"DLCBattlehornCastle.esp", "DLCShiveringIsles.esp", "Knights.esp", + "DLCFrostcrag.esp", "DLCSpellTomes.esp", "DLCMehrunesRazor.esp", + "DLCOrrery.esp", "DLCThievesDen.esp", "DLCVileLair.esp", + "DLCHorseArmor.esp"}; +} + +int GameOblivion::nexusModOrganizerID() const +{ + return 38277; +} + +int GameOblivion::nexusGameID() const +{ + return 101; +} diff --git a/src/games/oblivion/src/gameoblivion.h b/src/games/oblivion/src/gameoblivion.h index 48b54f50..f68620dc 100644 --- a/src/games/oblivion/src/gameoblivion.h +++ b/src/games/oblivion/src/gameoblivion.h @@ -1,53 +1,50 @@ -#ifndef GAMEOBLIVION_H -#define GAMEOBLIVION_H - -#include "gamegamebryo.h" - -#include -#include - -class GameOblivion : public GameGamebryo -{ - Q_OBJECT - Q_PLUGIN_METADATA(IID "org.tannin.GameOblivion" FILE "gameoblivion.json") - -public: - - GameOblivion(); - - virtual bool init(MOBase::IOrganizer *moInfo) override; - -public: // IPluginGame interface - - virtual QString gameName() const override; - virtual QList executables() const override; - virtual QList executableForcedLoads() const override; - virtual void initializeProfile(const QDir &path, ProfileSettings settings) const override; - virtual QString steamAPPId() const override; - virtual QStringList primaryPlugins() 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; - -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 settings() const override; - -protected: - - std::shared_ptr makeSaveGame(QString filePath) const override; - QString savegameExtension() const override; - QString savegameSEExtension() const override; - -}; - -#endif // GAMEOBLIVION_H +#ifndef GAMEOBLIVION_H +#define GAMEOBLIVION_H + +#include "gamegamebryo.h" + +#include +#include + +class GameOblivion : public GameGamebryo +{ + Q_OBJECT + Q_PLUGIN_METADATA(IID "org.tannin.GameOblivion" FILE "gameoblivion.json") + +public: + GameOblivion(); + + virtual bool init(MOBase::IOrganizer* moInfo) override; + +public: // IPluginGame interface + virtual QString gameName() const override; + virtual QList executables() const override; + virtual QList + executableForcedLoads() const override; + virtual void initializeProfile(const QDir& path, + ProfileSettings settings) const override; + virtual QString steamAPPId() const override; + virtual QStringList primaryPlugins() 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; + +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 settings() const override; + +protected: + std::shared_ptr makeSaveGame(QString filePath) const override; + QString savegameExtension() const override; + QString savegameSEExtension() const override; +}; + +#endif // GAMEOBLIVION_H diff --git a/src/games/oblivion/src/oblivionbsainvalidation.cpp b/src/games/oblivion/src/oblivionbsainvalidation.cpp index 8000d08b..864d37c9 100644 --- a/src/games/oblivion/src/oblivionbsainvalidation.cpp +++ b/src/games/oblivion/src/oblivionbsainvalidation.cpp @@ -1,17 +1,16 @@ -#include "oblivionbsainvalidation.h" - - -OblivionBSAInvalidation::OblivionBSAInvalidation(MOBase::DataArchives *dataArchives, MOBase::IPluginGame const *game) - : GamebryoBSAInvalidation(dataArchives, "oblivion.ini", game) -{ -} - -QString OblivionBSAInvalidation::invalidationBSAName() const -{ - return "Oblivion - Invalidation.bsa"; -} - -unsigned long OblivionBSAInvalidation::bsaVersion() const -{ - return 0x67; -} +#include "oblivionbsainvalidation.h" + +OblivionBSAInvalidation::OblivionBSAInvalidation(MOBase::DataArchives* dataArchives, + MOBase::IPluginGame const* game) + : GamebryoBSAInvalidation(dataArchives, "oblivion.ini", game) +{} + +QString OblivionBSAInvalidation::invalidationBSAName() const +{ + return "Oblivion - Invalidation.bsa"; +} + +unsigned long OblivionBSAInvalidation::bsaVersion() const +{ + return 0x67; +} diff --git a/src/games/oblivion/src/oblivionbsainvalidation.h b/src/games/oblivion/src/oblivionbsainvalidation.h index 91bd4d10..68047481 100644 --- a/src/games/oblivion/src/oblivionbsainvalidation.h +++ b/src/games/oblivion/src/oblivionbsainvalidation.h @@ -1,23 +1,20 @@ -#ifndef OBLIVIONBSAINVALIDATION_H -#define OBLIVIONBSAINVALIDATION_H - - -#include "gamebryobsainvalidation.h" -#include "obliviondataarchives.h" - -#include - -class OblivionBSAInvalidation : public GamebryoBSAInvalidation -{ -public: - - OblivionBSAInvalidation(MOBase::DataArchives *dataArchives, MOBase::IPluginGame const *game); - -private: - - virtual QString invalidationBSAName() const override; - virtual unsigned long bsaVersion() const override; - -}; - -#endif // OBLIVIONBSAINVALIDATION_H +#ifndef OBLIVIONBSAINVALIDATION_H +#define OBLIVIONBSAINVALIDATION_H + +#include "gamebryobsainvalidation.h" +#include "obliviondataarchives.h" + +#include + +class OblivionBSAInvalidation : public GamebryoBSAInvalidation +{ +public: + OblivionBSAInvalidation(MOBase::DataArchives* dataArchives, + MOBase::IPluginGame const* game); + +private: + virtual QString invalidationBSAName() const override; + virtual unsigned long bsaVersion() const override; +}; + +#endif // OBLIVIONBSAINVALIDATION_H diff --git a/src/games/oblivion/src/obliviondataarchives.cpp b/src/games/oblivion/src/obliviondataarchives.cpp index 51d35e18..cb44de13 100644 --- a/src/games/oblivion/src/obliviondataarchives.cpp +++ b/src/games/oblivion/src/obliviondataarchives.cpp @@ -1,36 +1,36 @@ -#include "obliviondataarchives.h" -#include - -OblivionDataArchives::OblivionDataArchives(const QDir &myGamesDir) : - GamebryoDataArchives(myGamesDir) -{ -} - -QStringList OblivionDataArchives::vanillaArchives() const -{ - return { "Oblivion - Misc.bsa" - , "Oblivion - Textures - Compressed.bsa" - , "Oblivion - Meshes.bsa" - , "Oblivion - Sounds.bsa" - , "Oblivion - Voices1.bsa" - , "Oblivion - Voices2.bsa" - }; -} - -QStringList OblivionDataArchives::archives(const MOBase::IProfile *profile) const -{ - QStringList result; - - QString iniFile = profile->localSettingsEnabled() ? QDir(profile->absolutePath()).absoluteFilePath("oblivion.ini") : m_LocalGameDir.absoluteFilePath("oblivion.ini"); - result.append(getArchivesFromKey(iniFile, "SArchiveList")); - - return result; -} - -void OblivionDataArchives::writeArchiveList(MOBase::IProfile *profile, const QStringList &before) -{ - QString list = before.join(", "); - - QString iniFile = profile->localSettingsEnabled() ? QDir(profile->absolutePath()).absoluteFilePath("oblivion.ini") : m_LocalGameDir.absoluteFilePath("oblivion.ini"); - setArchivesToKey(iniFile, "SArchiveList", list); -} +#include "obliviondataarchives.h" +#include + +OblivionDataArchives::OblivionDataArchives(const QDir& myGamesDir) + : GamebryoDataArchives(myGamesDir) +{} + +QStringList OblivionDataArchives::vanillaArchives() const +{ + return {"Oblivion - Misc.bsa", "Oblivion - Textures - Compressed.bsa", + "Oblivion - Meshes.bsa", "Oblivion - Sounds.bsa", + "Oblivion - Voices1.bsa", "Oblivion - Voices2.bsa"}; +} + +QStringList OblivionDataArchives::archives(const MOBase::IProfile* profile) const +{ + QStringList result; + + QString iniFile = profile->localSettingsEnabled() + ? QDir(profile->absolutePath()).absoluteFilePath("oblivion.ini") + : m_LocalGameDir.absoluteFilePath("oblivion.ini"); + result.append(getArchivesFromKey(iniFile, "SArchiveList")); + + return result; +} + +void OblivionDataArchives::writeArchiveList(MOBase::IProfile* profile, + const QStringList& before) +{ + QString list = before.join(", "); + + QString iniFile = profile->localSettingsEnabled() + ? QDir(profile->absolutePath()).absoluteFilePath("oblivion.ini") + : m_LocalGameDir.absoluteFilePath("oblivion.ini"); + setArchivesToKey(iniFile, "SArchiveList", list); +} diff --git a/src/games/oblivion/src/obliviondataarchives.h b/src/games/oblivion/src/obliviondataarchives.h index c266831f..a89e2c51 100644 --- a/src/games/oblivion/src/obliviondataarchives.h +++ b/src/games/oblivion/src/obliviondataarchives.h @@ -1,28 +1,25 @@ -#ifndef OBLIVIONDATAARCHIVES_H -#define OBLIVIONDATAARCHIVES_H - - -#include -#include -#include -#include -#include - -class OblivionDataArchives : public GamebryoDataArchives -{ - -public: - OblivionDataArchives(const QDir &myGamesDir); - -public: - - 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 // OBLIVIONDATAARCHIVES_H +#ifndef OBLIVIONDATAARCHIVES_H +#define OBLIVIONDATAARCHIVES_H + +#include +#include +#include +#include +#include + +class OblivionDataArchives : public GamebryoDataArchives +{ + +public: + OblivionDataArchives(const QDir& myGamesDir); + +public: + 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 // OBLIVIONDATAARCHIVES_H diff --git a/src/games/oblivion/src/oblivionmoddatachecker.cpp b/src/games/oblivion/src/oblivionmoddatachecker.cpp index 58c4870f..30a74ee0 100644 --- a/src/games/oblivion/src/oblivionmoddatachecker.cpp +++ b/src/games/oblivion/src/oblivionmoddatachecker.cpp @@ -1,7 +1,7 @@ #include "oblivionmoddatachecker.h" MOBase::ModDataChecker::CheckReturn OblivionModDataChecker::dataLooksValid( - std::shared_ptr fileTree) const + std::shared_ptr fileTree) const { // Check with Gamebryo stuff: auto check = GamebryoModDataChecker::dataLooksValid(fileTree); @@ -19,12 +19,12 @@ MOBase::ModDataChecker::CheckReturn OblivionModDataChecker::dataLooksValid( return CheckReturn::FIXABLE; } -std::shared_ptr OblivionModDataChecker::fix( - std::shared_ptr fileTree) const +std::shared_ptr +OblivionModDataChecker::fix(std::shared_ptr fileTree) const { // If we arrive here, it means all files starts with OBSE. auto data = fileTree->createOrphanTree(); auto obse = data->addDirectory("OBSE/Plugins"); obse->merge(fileTree); return data; -} \ No newline at end of file +} diff --git a/src/games/oblivion/src/oblivionmoddatachecker.h b/src/games/oblivion/src/oblivionmoddatachecker.h index 5159dc09..f62d015f 100644 --- a/src/games/oblivion/src/oblivionmoddatachecker.h +++ b/src/games/oblivion/src/oblivionmoddatachecker.h @@ -8,25 +8,28 @@ class OblivionModDataChecker : public GamebryoModDataChecker public: using GamebryoModDataChecker::GamebryoModDataChecker; - CheckReturn dataLooksValid(std::shared_ptr fileTree) const override; - std::shared_ptr fix(std::shared_ptr fileTree) const override; + CheckReturn + dataLooksValid(std::shared_ptr fileTree) const override; + std::shared_ptr + fix(std::shared_ptr fileTree) const override; protected: - virtual const FileNameSet& possibleFolderNames() const override { - static FileNameSet result{ - "fonts", "interface", "menus", "meshes", "music", "scripts", "shaders", - "sound", "strings", "textures", "trees", "video", "facegen", - "obse", "distantlod", "asi", "distantland", "mits", "dllplugins", "CalienteTools", - "NetScriptFramework" - }; + virtual const FileNameSet& possibleFolderNames() const override + { + static FileNameSet result{"fonts", "interface", "menus", + "meshes", "music", "scripts", + "shaders", "sound", "strings", + "textures", "trees", "video", + "facegen", "obse", "distantlod", + "asi", "distantland", "mits", + "dllplugins", "CalienteTools", "NetScriptFramework"}; return result; } - virtual const FileNameSet& possibleFileExtensions() const override { - static FileNameSet result{ - "esp", "esm", "bsa", "modgroups", "ini" - }; + virtual const FileNameSet& possibleFileExtensions() const override + { + static FileNameSet result{"esp", "esm", "bsa", "modgroups", "ini"}; return result; } }; -#endif // OBLIVION_MODATACHECKER_H +#endif // OBLIVION_MODATACHECKER_H diff --git a/src/games/oblivion/src/oblivionmoddatacontent.h b/src/games/oblivion/src/oblivionmoddatacontent.h index 75f22bf0..4e412d0c 100644 --- a/src/games/oblivion/src/oblivionmoddatacontent.h +++ b/src/games/oblivion/src/oblivionmoddatacontent.h @@ -4,18 +4,19 @@ #include #include -class OblivionModDataContent : public GamebryoModDataContent { +class OblivionModDataContent : public GamebryoModDataContent +{ public: - /** * */ - OblivionModDataContent(const MOBase::IGameFeatures* gameFeatures) : GamebryoModDataContent(gameFeatures) { + OblivionModDataContent(const MOBase::IGameFeatures* gameFeatures) + : GamebryoModDataContent(gameFeatures) + { // Just need to disable some contents: - m_Enabled[CONTENT_MCM] = false; + m_Enabled[CONTENT_MCM] = false; m_Enabled[CONTENT_SKYPROC] = false; } - }; -#endif // OBLIVION_MODDATACONTENT_H +#endif // OBLIVION_MODDATACONTENT_H diff --git a/src/games/oblivion/src/oblivionsavegame.cpp b/src/games/oblivion/src/oblivionsavegame.cpp index 52089e86..01520dba 100644 --- a/src/games/oblivion/src/oblivionsavegame.cpp +++ b/src/games/oblivion/src/oblivionsavegame.cpp @@ -2,31 +2,32 @@ #include -OblivionSaveGame::OblivionSaveGame(QString const &fileName, GameOblivion const *game) : - GamebryoSaveGame(fileName, game) +OblivionSaveGame::OblivionSaveGame(QString const& fileName, GameOblivion const* game) + : GamebryoSaveGame(fileName, game) { FileWrapper file(getFilepath(), "TES4SAVEGAME"); file.setPluginString(GamebryoSaveGame::StringType::TYPE_BSTRING); SYSTEMTIME creationTime; - fetchInformationFields(file, m_SaveNumber, m_PCName, m_PCLevel, m_PCLocation, creationTime); + fetchInformationFields(file, m_SaveNumber, m_PCName, m_PCLevel, m_PCLocation, + creationTime); setCreationTime(creationTime); } void OblivionSaveGame::fetchInformationFields(FileWrapper& file, - unsigned long& saveNumber, - QString& playerName, - unsigned short& playerLevel, - QString& playerLocation, - SYSTEMTIME& creationTime) const + unsigned long& saveNumber, + QString& playerName, + unsigned short& playerLevel, + QString& playerLocation, + SYSTEMTIME& creationTime) const { - file.skip(); //Major version - file.skip(); //Minor version + file.skip(); // Major version + file.skip(); // Minor version file.skip(); // exe last modified (!) - file.skip(); //Header version - file.skip(); //Header size + file.skip(); // Header version + file.skip(); // Header size file.read(saveNumber); @@ -34,13 +35,13 @@ void OblivionSaveGame::fetchInformationFields(FileWrapper& file, file.read(playerLevel); file.read(playerLocation); - file.skip(); //game days - file.skip(); //game ticks + file.skip(); // game days + file.skip(); // game ticks - //there is a save time stored here. So use it rather than the file time, which - //could have been copied. - //Note: This says it uses getlocaltime api to obtain it which is u/s - if so - //we should ignore this. + // there is a save time stored here. So use it rather than the file time, which + // could have been copied. + // Note: This says it uses getlocaltime api to obtain it which is u/s - if so + // we should ignore this. file.read(creationTime); } @@ -57,13 +58,13 @@ std::unique_ptr OblivionSaveGame::fetchDataFields( unsigned long dummySaveNumber; SYSTEMTIME dummyTime; - fetchInformationFields(file, dummySaveNumber, dummyName, dummyLevel, - dummyLocation, dummyTime); + fetchInformationFields(file, dummySaveNumber, dummyName, dummyLevel, dummyLocation, + dummyTime); } - //Note that screenshot size, width, height and data are apparently the same - //structure - file.skip(); //Screenshot size. + // Note that screenshot size, width, height and data are apparently the same + // structure + file.skip(); // Screenshot size. fields->Screenshot = file.readImage(); diff --git a/src/games/oblivion/src/oblivionsavegame.h b/src/games/oblivion/src/oblivionsavegame.h index 0c9de37d..de7bfd1a 100644 --- a/src/games/oblivion/src/oblivionsavegame.h +++ b/src/games/oblivion/src/oblivionsavegame.h @@ -7,19 +7,15 @@ class OblivionSaveGame : public GamebryoSaveGame { public: - OblivionSaveGame(QString const &fileName, GameOblivion const *game); + OblivionSaveGame(QString const& fileName, GameOblivion const* game); protected: - // Fetch easy-to-access information. - void fetchInformationFields(FileWrapper& wrapper, - unsigned long& saveNumber, - QString& playerName, - unsigned short& playerLevel, - QString& playerLocation, - SYSTEMTIME& creationTime) const; + void fetchInformationFields(FileWrapper& wrapper, unsigned long& saveNumber, + QString& playerName, unsigned short& playerLevel, + QString& playerLocation, SYSTEMTIME& creationTime) const; std::unique_ptr fetchDataFields() const override; }; -#endif // OBLIVIONSAVEGAME_H +#endif // OBLIVIONSAVEGAME_H diff --git a/src/games/oblivion/src/oblivionscriptextender.cpp b/src/games/oblivion/src/oblivionscriptextender.cpp index 8d18c1d7..f021a2e7 100644 --- a/src/games/oblivion/src/oblivionscriptextender.cpp +++ b/src/games/oblivion/src/oblivionscriptextender.cpp @@ -1,23 +1,20 @@ -#include "oblivionscriptextender.h" - -#include -#include - -OblivionScriptExtender::OblivionScriptExtender(GameGamebryo const *game) : - GamebryoScriptExtender(game) -{ -} - -OblivionScriptExtender::~OblivionScriptExtender() -{ -} - -QString OblivionScriptExtender::BinaryName() const -{ - return "obse_loader.exe"; -} - -QString OblivionScriptExtender::PluginPath() const -{ - return "obse/plugins"; -} +#include "oblivionscriptextender.h" + +#include +#include + +OblivionScriptExtender::OblivionScriptExtender(GameGamebryo const* game) + : GamebryoScriptExtender(game) +{} + +OblivionScriptExtender::~OblivionScriptExtender() {} + +QString OblivionScriptExtender::BinaryName() const +{ + return "obse_loader.exe"; +} + +QString OblivionScriptExtender::PluginPath() const +{ + return "obse/plugins"; +} diff --git a/src/games/oblivion/src/oblivionscriptextender.h b/src/games/oblivion/src/oblivionscriptextender.h index 5155b552..1044bfaf 100644 --- a/src/games/oblivion/src/oblivionscriptextender.h +++ b/src/games/oblivion/src/oblivionscriptextender.h @@ -1,19 +1,18 @@ -#ifndef OBLIVIONSCRIPTEXTENDER_H -#define OBLIVIONSCRIPTEXTENDER_H - -#include "gamebryoscriptextender.h" - -class GameGamebryo; - -class OblivionScriptExtender : public GamebryoScriptExtender -{ -public: - OblivionScriptExtender(const GameGamebryo *game); - ~OblivionScriptExtender(); - - virtual QString BinaryName() const override; - virtual QString PluginPath() const override; - -}; - -#endif // OBLIVIONSCRIPTEXTENDER_H +#ifndef OBLIVIONSCRIPTEXTENDER_H +#define OBLIVIONSCRIPTEXTENDER_H + +#include "gamebryoscriptextender.h" + +class GameGamebryo; + +class OblivionScriptExtender : public GamebryoScriptExtender +{ +public: + OblivionScriptExtender(const GameGamebryo* game); + ~OblivionScriptExtender(); + + virtual QString BinaryName() const override; + virtual QString PluginPath() const override; +}; + +#endif // OBLIVIONSCRIPTEXTENDER_H From a9f9fabf66218f5d3813df2d11500c2c06052d53 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Mika=C3=ABl=20Capelle?= Date: Sun, 9 Jun 2024 13:29:50 +0200 Subject: [PATCH 1484/1544] [game_oblivion] Add .git-blame-ignore-revs. --- src/games/oblivion/.git-blame-ignore-revs | 1 + 1 file changed, 1 insertion(+) create mode 100644 src/games/oblivion/.git-blame-ignore-revs diff --git a/src/games/oblivion/.git-blame-ignore-revs b/src/games/oblivion/.git-blame-ignore-revs new file mode 100644 index 00000000..601bb6a8 --- /dev/null +++ b/src/games/oblivion/.git-blame-ignore-revs @@ -0,0 +1 @@ +788cc5afada952667f927f181715b7dd4af793e7 From ff19696445bc48d1b246514f36246a24d495c30a Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Mika=C3=ABl=20Capelle?= Date: Sun, 9 Jun 2024 13:29:50 +0200 Subject: [PATCH 1485/1544] [game_oblivion] Add github actions. --- src/games/oblivion/.github/workflows/build.yml | 16 ++++++++++++++++ src/games/oblivion/.github/workflows/linting.yml | 16 ++++++++++++++++ 2 files changed, 32 insertions(+) create mode 100644 src/games/oblivion/.github/workflows/build.yml create mode 100644 src/games/oblivion/.github/workflows/linting.yml diff --git a/src/games/oblivion/.github/workflows/build.yml b/src/games/oblivion/.github/workflows/build.yml new file mode 100644 index 00000000..311249cb --- /dev/null +++ b/src/games/oblivion/.github/workflows/build.yml @@ -0,0 +1,16 @@ +name: Build Oblivion Plugin + +on: + push: + branches: master + pull_request: + types: [opened, synchronize, reopened] + +jobs: + build: + runs-on: windows-2022 + steps: + - name: Build Oblivion Plugin + uses: ModOrganizer2/build-with-mob-action@master + with: + mo2-dependencies: cmake_common uibase game_gamebryo diff --git a/src/games/oblivion/.github/workflows/linting.yml b/src/games/oblivion/.github/workflows/linting.yml new file mode 100644 index 00000000..3983bbf1 --- /dev/null +++ b/src/games/oblivion/.github/workflows/linting.yml @@ -0,0 +1,16 @@ +name: Lint Oblivion Plugin + +on: + push: + pull_request: + types: [opened, synchronize, reopened] + +jobs: + lint: + runs-on: ubuntu-latest + steps: + - uses: actions/checkout@v3 + - name: Check format + uses: ModOrganizer2/check-formatting-action@master + with: + check-path: "." From 2538362bf0531bbefcc1c0b8f5df048498bf296b Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Mika=C3=ABl=20Capelle?= Date: Sun, 9 Jun 2024 13:30:22 +0200 Subject: [PATCH 1486/1544] [game_skyrim] Remove appveyor.yml. --- src/games/skyrim/appveyor.yml | 40 ----------------------------------- 1 file changed, 40 deletions(-) delete mode 100644 src/games/skyrim/appveyor.yml diff --git a/src/games/skyrim/appveyor.yml b/src/games/skyrim/appveyor.yml deleted file mode 100644 index 3bc4f719..00000000 --- a/src/games/skyrim/appveyor.yml +++ /dev/null @@ -1,40 +0,0 @@ -version: 1.0.{build} -skip_branch_with_pr: true -image: Visual Studio 2019 -environment: - WEBHOOK_URL: - secure: gOKbXaZM9ImtMD5XrYITvdyZUW/az082G9OIN1EC1Vbg57wBaeLhi49uGjxPw5GVujHku6kxN6ab89zhbS5GVeluR76GM83IbKV4Sh7udXzoYZZdg6YudtYHzdhCgUeiedpswbuczTq9ceIkkfSEWZuh/lMAAVVwvcGsJAnoPFw= -build_script: -- pwsh: >- - $ErrorActionPreference = 'Stop' - - git clone --depth=1 --no-single-branch https://github.com/ModOrganizer2/modorganizer-umbrella.git c:\projects\modorganizer-umbrella - - New-Item -ItemType Directory -Path c:\projects\modorganizer-build - - cd c:\projects\modorganizer-umbrella - - ($env:APPVEYOR_PULL_REQUEST_HEAD_REPO_BRANCH -eq $null) ? ($branch = $env:APPVEYOR_REPO_BRANCH) : ($branch = $env:APPVEYOR_PULL_REQUEST_HEAD_REPO_BRANCH) - - git checkout $(git show-ref --verify --quiet refs/remotes/origin/${branch} || echo '-b') ${branch} - - C:\Python37-x64\python.exe unimake.py -d c:\projects\modorganizer-build -s Appveyor_Build=True ${env:APPVEYOR_PROJECT_NAME} - - if($LastExitCode -ne 0) { $host.SetShouldExit($LastExitCode ) } -artifacts: -- path: vsbuild\src\RelWithDebInfo\game_skyrim.dll - name: game_skyrim_dll -- path: vsbuild\src\RelWithDebInfo\game_skyrim.pdb - name: game_skyrim_pdb -- path: vsbuild\src\RelWithDebInfo\game_skyrim.lib - name: game_skyrim_lib -on_success: - - ps: Set-Location -Path $env:APPVEYOR_BUILD_FOLDER - - ps: Invoke-RestMethod https://raw.githubusercontent.com/DiscordHooks/appveyor-discord-webhook/master/send.ps1 -o send.ps1 - - ps: ./send.ps1 success $env:WEBHOOK_URL -on_failure: - - ps: Set-Location -Path $env:APPVEYOR_BUILD_FOLDER - - ps: Push-AppveyorArtifact ${env:APPVEYOR_BUILD_FOLDER}\stdout.log - - ps: Push-AppveyorArtifact ${env:APPVEYOR_BUILD_FOLDER}\stderr.log - - ps: Invoke-RestMethod https://raw.githubusercontent.com/DiscordHooks/appveyor-discord-webhook/master/send.ps1 -o send.ps1 - - ps: ./send.ps1 failure $env:WEBHOOK_URL \ No newline at end of file From 73cd8774a1329a7782898225cf32283a90789f91 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Mika=C3=ABl=20Capelle?= Date: Sun, 9 Jun 2024 13:30:22 +0200 Subject: [PATCH 1487/1544] [game_skyrim] Format files and add .gitattributes and .clang-format. --- src/games/skyrim/.clang-format | 41 +++++ src/games/skyrim/.gitattributes | 7 + src/games/skyrim/src/gameskyrim.cpp | 92 +++++----- src/games/skyrim/src/gameskyrim.h | 111 ++++++------ .../skyrim/src/skyrimbsainvalidation.cpp | 32 ++-- src/games/skyrim/src/skyrimbsainvalidation.h | 43 +++-- src/games/skyrim/src/skyrimdataarchives.cpp | 95 +++++------ src/games/skyrim/src/skyrimdataarchives.h | 53 +++--- src/games/skyrim/src/skyrimgameplugins.cpp | 158 +++++++++--------- src/games/skyrim/src/skyrimgameplugins.h | 14 +- src/games/skyrim/src/skyrimmoddatachecker.h | 46 +++-- src/games/skyrim/src/skyrimmoddatacontent.h | 7 +- src/games/skyrim/src/skyrimsavegame.cpp | 96 +++++------ src/games/skyrim/src/skyrimsavegame.h | 19 +-- src/games/skyrim/src/skyrimscriptextender.cpp | 37 ++-- src/games/skyrim/src/skyrimscriptextender.h | 35 ++-- 16 files changed, 473 insertions(+), 413 deletions(-) create mode 100644 src/games/skyrim/.clang-format create mode 100644 src/games/skyrim/.gitattributes diff --git a/src/games/skyrim/.clang-format b/src/games/skyrim/.clang-format new file mode 100644 index 00000000..6098e1f5 --- /dev/null +++ b/src/games/skyrim/.clang-format @@ -0,0 +1,41 @@ +--- +# We'll use defaults from the LLVM style, but with 4 columns indentation. +BasedOnStyle: LLVM +IndentWidth: 2 +--- +Language: Cpp +DeriveLineEnding: false +UseCRLF: true +DerivePointerAlignment: false +PointerAlignment: Left +AlignConsecutiveAssignments: true +AllowShortFunctionsOnASingleLine: Inline +AllowShortIfStatementsOnASingleLine: Never +AllowShortLambdasOnASingleLine: Empty +AlwaysBreakTemplateDeclarations: Yes +AccessModifierOffset: -2 +AlignTrailingComments: true +SpacesBeforeTrailingComments: 2 +NamespaceIndentation: Inner +MaxEmptyLinesToKeep: 1 +BreakBeforeBraces: Custom +BraceWrapping: + AfterCaseLabel: false + AfterClass: true + AfterControlStatement: false + AfterEnum: true + AfterFunction: true + AfterNamespace: true + AfterStruct: true + AfterUnion: true + AfterExternBlock: true + BeforeCatch: false + BeforeElse: false + BeforeLambdaBody: false + BeforeWhile: false + IndentBraces: false + SplitEmptyFunction: false + SplitEmptyRecord: false + SplitEmptyNamespace: true +ColumnLimit: 88 +ForEachMacros: ['Q_FOREACH', 'foreach'] diff --git a/src/games/skyrim/.gitattributes b/src/games/skyrim/.gitattributes new file mode 100644 index 00000000..f8697127 --- /dev/null +++ b/src/games/skyrim/.gitattributes @@ -0,0 +1,7 @@ +# Set the default behavior, in case people don't have core.autocrlf set. +* text=auto + +# Explicitly declare text files you want to always be normalized and converted +# to native line endings on checkout. +*.cpp text eol=crlf +*.h text eol=crlf diff --git a/src/games/skyrim/src/gameskyrim.cpp b/src/games/skyrim/src/gameskyrim.cpp index a2edc928..0a9b3813 100644 --- a/src/games/skyrim/src/gameskyrim.cpp +++ b/src/games/skyrim/src/gameskyrim.cpp @@ -1,20 +1,20 @@ #include "gameskyrim.h" #include "skyrimbsainvalidation.h" -#include "skyrimscriptextender.h" #include "skyrimdataarchives.h" #include "skyrimgameplugins.h" #include "skyrimmoddatachecker.h" #include "skyrimmoddatacontent.h" #include "skyrimsavegame.h" +#include "skyrimscriptextender.h" #include "executableinfo.h" #include "pluginsetting.h" -#include #include -#include +#include #include +#include #include #include @@ -33,11 +33,9 @@ using namespace MOBase; -GameSkyrim::GameSkyrim() -{ -} +GameSkyrim::GameSkyrim() {} -bool GameSkyrim::init(IOrganizer *moInfo) +bool GameSkyrim::init(IOrganizer* moInfo) { if (!GameGamebryo::init(moInfo)) { return false; @@ -48,7 +46,8 @@ bool GameSkyrim::init(IOrganizer *moInfo) registerFeature(dataArchives); registerFeature(std::make_shared(dataArchives.get(), this)); registerFeature(std::make_shared(this)); - registerFeature(std::make_shared(myGamesPath(), "skyrim.ini")); + registerFeature( + std::make_shared(myGamesPath(), "skyrim.ini")); registerFeature(std::make_shared(this)); registerFeature(std::make_shared(m_Organizer->gameFeatures())); registerFeature(std::make_shared(moInfo)); @@ -65,14 +64,18 @@ QString GameSkyrim::gameName() const QList GameSkyrim::executables() const { return QList() - << ExecutableInfo("SKSE", findInGameFolder(m_Organizer->gameFeatures()->gameFeature()->loaderName())) - << ExecutableInfo("SBW", findInGameFolder("SBW.exe")) - << ExecutableInfo("Skyrim", findInGameFolder(binaryName())) - << ExecutableInfo("Skyrim Launcher", findInGameFolder(getLauncherName())) - << ExecutableInfo("BOSS", findInGameFolder("BOSS/BOSS.exe")) - << ExecutableInfo("LOOT", QFileInfo(getLootPath())).withArgument("--game=\"Skyrim\"") - << ExecutableInfo("Creation Kit", findInGameFolder("CreationKit.exe")).withSteamAppId("202480") - ; + << ExecutableInfo("SKSE", + findInGameFolder(m_Organizer->gameFeatures() + ->gameFeature() + ->loaderName())) + << ExecutableInfo("SBW", findInGameFolder("SBW.exe")) + << ExecutableInfo("Skyrim", findInGameFolder(binaryName())) + << ExecutableInfo("Skyrim Launcher", findInGameFolder(getLauncherName())) + << ExecutableInfo("BOSS", findInGameFolder("BOSS/BOSS.exe")) + << ExecutableInfo("LOOT", QFileInfo(getLootPath())) + .withArgument("--game=\"Skyrim\"") + << ExecutableInfo("Creation Kit", findInGameFolder("CreationKit.exe")) + .withSteamAppId("202480"); } QList GameSkyrim::executableForcedLoads() const @@ -108,20 +111,22 @@ MOBase::VersionInfo GameSkyrim::version() const QList GameSkyrim::settings() const { QList results; - results.push_back(PluginSetting("sse_downloads", "allow Skyrim SE downloads", QVariant(false))); + results.push_back( + PluginSetting("sse_downloads", "allow Skyrim SE downloads", QVariant(false))); return results; } -void GameSkyrim::initializeProfile(const QDir &path, ProfileSettings settings) const +void GameSkyrim::initializeProfile(const QDir& path, ProfileSettings settings) const { if (settings.testFlag(IPluginGame::MODS)) { copyToProfile(localAppFolder() + "/Skyrim", path, "plugins.txt"); } if (settings.testFlag(IPluginGame::CONFIGURATION)) { - if (settings.testFlag(IPluginGame::PREFER_DEFAULTS) - || !QFileInfo(myGamesPath() + "/skyrim.ini").exists()) { - copyToProfile(gameDirectory().absolutePath(), path, "skyrim_default.ini", "skyrim.ini"); + if (settings.testFlag(IPluginGame::PREFER_DEFAULTS) || + !QFileInfo(myGamesPath() + "/skyrim.ini").exists()) { + copyToProfile(gameDirectory().absolutePath(), path, "skyrim_default.ini", + "skyrim.ini"); } else { copyToProfile(myGamesPath(), path, "skyrim.ini"); } @@ -152,7 +157,7 @@ QString GameSkyrim::steamAPPId() const QStringList GameSkyrim::primaryPlugins() const { - return { "skyrim.esm", "update.esm" }; + return {"skyrim.esm", "update.esm"}; } QString GameSkyrim::binaryName() const @@ -173,33 +178,37 @@ QString GameSkyrim::gameNexusName() const QStringList GameSkyrim::validShortNames() const { QStringList results; - if (m_Organizer->pluginSetting(name(), "sse_downloads").toBool()) - { - results.push_back( "SkyrimSE" ); + if (m_Organizer->pluginSetting(name(), "sse_downloads").toBool()) { + results.push_back("SkyrimSE"); } return results; } QStringList GameSkyrim::iniFiles() const { - return { "skyrim.ini", "skyrimprefs.ini" }; + return {"skyrim.ini", "skyrimprefs.ini"}; } QStringList GameSkyrim::DLCPlugins() const { - return { "Dawnguard.esm", "Dragonborn.esm", "HearthFires.esm", - "HighResTexturePack01.esp", "HighResTexturePack02.esp", "HighResTexturePack03.esp" }; + return {"Dawnguard.esm", + "Dragonborn.esm", + "HearthFires.esm", + "HighResTexturePack01.esp", + "HighResTexturePack02.esp", + "HighResTexturePack03.esp"}; } -namespace { -//Note: This is ripped off from shared/util. And in an upcoming move, the fomod -//installer requires something similar. I suspect I should abstract this out -//into gamebryo (or lower level) +namespace +{ +// Note: This is ripped off from shared/util. And in an upcoming move, the fomod +// installer requires something similar. I suspect I should abstract this out +// into gamebryo (or lower level) -VS_FIXEDFILEINFO GetFileVersion(const std::wstring &fileName) +VS_FIXEDFILEINFO GetFileVersion(const std::wstring& fileName) { DWORD handle = 0UL; - DWORD size = ::GetFileVersionInfoSizeW(fileName.c_str(), &handle); + DWORD size = ::GetFileVersionInfoSizeW(fileName.c_str(), &handle); if (size == 0) { throw std::runtime_error("failed to determine file version info size"); } @@ -210,7 +219,7 @@ VS_FIXEDFILEINFO GetFileVersion(const std::wstring &fileName) throw std::runtime_error("failed to determine file version info"); } - void *versionInfoPtr = nullptr; + void* versionInfoPtr = nullptr; UINT versionInfoLength = 0; if (!::VerQueryValue(buffer.data(), L"\\", &versionInfoPtr, &versionInfoLength)) { throw std::runtime_error("failed to determine file version"); @@ -219,24 +228,25 @@ VS_FIXEDFILEINFO GetFileVersion(const std::wstring &fileName) return *static_cast(versionInfoPtr); } -} +} // namespace IPluginGame::LoadOrderMechanism GameSkyrim::loadOrderMechanism() const { try { - std::wstring fileName = gameDirectory().absoluteFilePath(binaryName()).toStdWString().c_str(); + std::wstring fileName = + gameDirectory().absoluteFilePath(binaryName()).toStdWString().c_str(); VS_FIXEDFILEINFO versionInfo = ::GetFileVersion(fileName); - if ((versionInfo.dwFileVersionMS > 0x10004) || // version >= 1.5.x? - ((versionInfo.dwFileVersionMS == 0x10004) && (versionInfo.dwFileVersionLS >= 0x1A0000))) { // version >= ?.4.26 + if ((versionInfo.dwFileVersionMS > 0x10004) || // version >= 1.5.x? + ((versionInfo.dwFileVersionMS == 0x10004) && + (versionInfo.dwFileVersionLS >= 0x1A0000))) { // version >= ?.4.26 return LoadOrderMechanism::PluginsTxt; } - } catch (const std::exception &e) { + } catch (const std::exception& e) { qCritical() << "TESV.exe is invalid: " << e.what(); } return LoadOrderMechanism::FileTime; } - int GameSkyrim::nexusModOrganizerID() const { return 0; diff --git a/src/games/skyrim/src/gameskyrim.h b/src/games/skyrim/src/gameskyrim.h index 6764777d..2fbc2c4a 100644 --- a/src/games/skyrim/src/gameskyrim.h +++ b/src/games/skyrim/src/gameskyrim.h @@ -1,56 +1,55 @@ -#ifndef GAMESKYRIM_H -#define GAMESKYRIM_H - -#include "gamegamebryo.h" - -#include -#include - -class GameSkyrim : public GameGamebryo -{ - Q_OBJECT -#if QT_VERSION >= QT_VERSION_CHECK(5,0,0) - Q_PLUGIN_METADATA(IID "org.tannin.GameSkyrim" FILE "gameskyrim.json") -#endif - -public: - - GameSkyrim(); - - virtual bool init(MOBase::IOrganizer *moInfo) override; - -public: // IPluginGame interface - - virtual QString gameName() const override; - virtual QList executables() const override; - virtual QList executableForcedLoads() const override; - virtual void initializeProfile(const QDir &path, ProfileSettings settings) const override; - virtual QString steamAPPId() const override; - virtual QStringList primaryPlugins() const override; - virtual QString binaryName() const override; - virtual QString gameShortName() const override; - virtual QString gameNexusName() const override; - virtual QStringList validShortNames() const override; - virtual QStringList iniFiles() const override; - virtual QStringList DLCPlugins() const override; - virtual LoadOrderMechanism loadOrderMechanism() const override; - virtual int nexusModOrganizerID() const override; - virtual int nexusGameID() 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 settings() const override; - -protected: - - virtual QString savegameExtension() const override; - virtual QString savegameSEExtension() const override; - virtual std::shared_ptr makeSaveGame(QString filepath) const override; -}; - -#endif // GAMESKYRIM_H +#ifndef GAMESKYRIM_H +#define GAMESKYRIM_H + +#include "gamegamebryo.h" + +#include +#include + +class GameSkyrim : public GameGamebryo +{ + Q_OBJECT +#if QT_VERSION >= QT_VERSION_CHECK(5, 0, 0) + Q_PLUGIN_METADATA(IID "org.tannin.GameSkyrim" FILE "gameskyrim.json") +#endif + +public: + GameSkyrim(); + + virtual bool init(MOBase::IOrganizer* moInfo) override; + +public: // IPluginGame interface + virtual QString gameName() const override; + virtual QList executables() const override; + virtual QList + executableForcedLoads() const override; + virtual void initializeProfile(const QDir& path, + ProfileSettings settings) const override; + virtual QString steamAPPId() const override; + virtual QStringList primaryPlugins() const override; + virtual QString binaryName() const override; + virtual QString gameShortName() const override; + virtual QString gameNexusName() const override; + virtual QStringList validShortNames() const override; + virtual QStringList iniFiles() const override; + virtual QStringList DLCPlugins() const override; + virtual LoadOrderMechanism loadOrderMechanism() const override; + virtual int nexusModOrganizerID() const override; + virtual int nexusGameID() 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 settings() const override; + +protected: + virtual QString savegameExtension() const override; + virtual QString savegameSEExtension() const override; + virtual std::shared_ptr + makeSaveGame(QString filepath) const override; +}; + +#endif // GAMESKYRIM_H diff --git a/src/games/skyrim/src/skyrimbsainvalidation.cpp b/src/games/skyrim/src/skyrimbsainvalidation.cpp index 6f6a814c..e056f10f 100644 --- a/src/games/skyrim/src/skyrimbsainvalidation.cpp +++ b/src/games/skyrim/src/skyrimbsainvalidation.cpp @@ -1,16 +1,16 @@ -#include "skyrimbsainvalidation.h" - -SkyrimBSAInvalidation::SkyrimBSAInvalidation(MOBase::DataArchives *dataArchives, MOBase::IPluginGame const *game) - : GamebryoBSAInvalidation(dataArchives, "skyrim.ini", game) -{ -} - -QString SkyrimBSAInvalidation::invalidationBSAName() const -{ - return "Skyrim - Invalidation.bsa"; -} - -unsigned long SkyrimBSAInvalidation::bsaVersion() const -{ - return 0x68; -} +#include "skyrimbsainvalidation.h" + +SkyrimBSAInvalidation::SkyrimBSAInvalidation(MOBase::DataArchives* dataArchives, + MOBase::IPluginGame const* game) + : GamebryoBSAInvalidation(dataArchives, "skyrim.ini", game) +{} + +QString SkyrimBSAInvalidation::invalidationBSAName() const +{ + return "Skyrim - Invalidation.bsa"; +} + +unsigned long SkyrimBSAInvalidation::bsaVersion() const +{ + return 0x68; +} diff --git a/src/games/skyrim/src/skyrimbsainvalidation.h b/src/games/skyrim/src/skyrimbsainvalidation.h index cf32964d..4937fe97 100644 --- a/src/games/skyrim/src/skyrimbsainvalidation.h +++ b/src/games/skyrim/src/skyrimbsainvalidation.h @@ -1,23 +1,20 @@ -#ifndef SKYRIMBSAINVALIDATION_H -#define SKYRIMBSAINVALIDATION_H - - -#include "gamebryobsainvalidation.h" -#include "skyrimdataarchives.h" - -#include - -class SkyrimBSAInvalidation : public GamebryoBSAInvalidation -{ -public: - - SkyrimBSAInvalidation(MOBase::DataArchives *dataArchives, MOBase::IPluginGame const *game); - -private: - - virtual QString invalidationBSAName() const override; - virtual unsigned long bsaVersion() const override; - -}; - -#endif // SKYRIMBSAINVALIDATION_H +#ifndef SKYRIMBSAINVALIDATION_H +#define SKYRIMBSAINVALIDATION_H + +#include "gamebryobsainvalidation.h" +#include "skyrimdataarchives.h" + +#include + +class SkyrimBSAInvalidation : public GamebryoBSAInvalidation +{ +public: + SkyrimBSAInvalidation(MOBase::DataArchives* dataArchives, + MOBase::IPluginGame const* game); + +private: + virtual QString invalidationBSAName() const override; + virtual unsigned long bsaVersion() const override; +}; + +#endif // SKYRIMBSAINVALIDATION_H diff --git a/src/games/skyrim/src/skyrimdataarchives.cpp b/src/games/skyrim/src/skyrimdataarchives.cpp index 1952809e..38551675 100644 --- a/src/games/skyrim/src/skyrimdataarchives.cpp +++ b/src/games/skyrim/src/skyrimdataarchives.cpp @@ -1,49 +1,46 @@ -#include "skyrimdataarchives.h" -#include - -SkyrimDataArchives::SkyrimDataArchives(const QDir &myGamesDir) : - GamebryoDataArchives(myGamesDir) -{ -} - -QStringList SkyrimDataArchives::vanillaArchives() const -{ - return { "Skyrim - Misc.bsa" - , "Skyrim - Shaders.bsa" - , "Skyrim - Textures.bsa" - , "HighResTexturePack01.bsa" - , "HighResTexturePack02.bsa" - , "HighResTexturePack03.bsa" - , "Skyrim - Interface.bsa" - , "Skyrim - Animations.bsa" - , "Skyrim - Meshes.bsa" - , "Skyrim - Sounds.bsa" - , "Skyrim - Voices.bsa" - , "Skyrim - VoicesExtra.bsa" }; -} - - -QStringList SkyrimDataArchives::archives(const MOBase::IProfile *profile) const -{ - QStringList result; - - QString iniFile = profile->localSettingsEnabled() ? QDir(profile->absolutePath()).absoluteFilePath("skyrim.ini") : m_LocalGameDir.absoluteFilePath("skyrim.ini"); - result.append(getArchivesFromKey(iniFile, "SResourceArchiveList")); - result.append(getArchivesFromKey(iniFile, "SResourceArchiveList2")); - - return result; -} - -void SkyrimDataArchives::writeArchiveList(MOBase::IProfile *profile, const QStringList &before) -{ - QString list = before.join(", "); - - QString iniFile = profile->localSettingsEnabled() ? QDir(profile->absolutePath()).absoluteFilePath("skyrim.ini") : m_LocalGameDir.absoluteFilePath("skyrim.ini"); - if (list.length() > 255) { - int splitIdx = list.lastIndexOf(",", 256); - setArchivesToKey(iniFile, "SResourceArchiveList", list.mid(0, splitIdx)); - setArchivesToKey(iniFile, "SResourceArchiveList2", list.mid(splitIdx + 2)); - } else { - setArchivesToKey(iniFile, "SResourceArchiveList", list); - } -} +#include "skyrimdataarchives.h" +#include + +SkyrimDataArchives::SkyrimDataArchives(const QDir& myGamesDir) + : GamebryoDataArchives(myGamesDir) +{} + +QStringList SkyrimDataArchives::vanillaArchives() const +{ + return {"Skyrim - Misc.bsa", "Skyrim - Shaders.bsa", + "Skyrim - Textures.bsa", "HighResTexturePack01.bsa", + "HighResTexturePack02.bsa", "HighResTexturePack03.bsa", + "Skyrim - Interface.bsa", "Skyrim - Animations.bsa", + "Skyrim - Meshes.bsa", "Skyrim - Sounds.bsa", + "Skyrim - Voices.bsa", "Skyrim - VoicesExtra.bsa"}; +} + +QStringList SkyrimDataArchives::archives(const MOBase::IProfile* profile) const +{ + QStringList result; + + QString iniFile = profile->localSettingsEnabled() + ? QDir(profile->absolutePath()).absoluteFilePath("skyrim.ini") + : m_LocalGameDir.absoluteFilePath("skyrim.ini"); + result.append(getArchivesFromKey(iniFile, "SResourceArchiveList")); + result.append(getArchivesFromKey(iniFile, "SResourceArchiveList2")); + + return result; +} + +void SkyrimDataArchives::writeArchiveList(MOBase::IProfile* profile, + const QStringList& before) +{ + QString list = before.join(", "); + + QString iniFile = profile->localSettingsEnabled() + ? QDir(profile->absolutePath()).absoluteFilePath("skyrim.ini") + : m_LocalGameDir.absoluteFilePath("skyrim.ini"); + if (list.length() > 255) { + int splitIdx = list.lastIndexOf(",", 256); + setArchivesToKey(iniFile, "SResourceArchiveList", list.mid(0, splitIdx)); + setArchivesToKey(iniFile, "SResourceArchiveList2", list.mid(splitIdx + 2)); + } else { + setArchivesToKey(iniFile, "SResourceArchiveList", list); + } +} diff --git a/src/games/skyrim/src/skyrimdataarchives.h b/src/games/skyrim/src/skyrimdataarchives.h index 35f5fb44..a6f074a1 100644 --- a/src/games/skyrim/src/skyrimdataarchives.h +++ b/src/games/skyrim/src/skyrimdataarchives.h @@ -1,28 +1,25 @@ -#ifndef SKYRIMDATAARCHIVES_H -#define SKYRIMDATAARCHIVES_H - - -#include -#include -#include -#include -#include - -class SkyrimDataArchives : public GamebryoDataArchives -{ - -public: - SkyrimDataArchives(const QDir &myGamesDir); - -public: - - 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 // SKYRIMDATAARCHIVES_H +#ifndef SKYRIMDATAARCHIVES_H +#define SKYRIMDATAARCHIVES_H + +#include +#include +#include +#include +#include + +class SkyrimDataArchives : public GamebryoDataArchives +{ + +public: + SkyrimDataArchives(const QDir& myGamesDir); + +public: + 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 // SKYRIMDATAARCHIVES_H diff --git a/src/games/skyrim/src/skyrimgameplugins.cpp b/src/games/skyrim/src/skyrimgameplugins.cpp index 562fff8e..88aac81d 100644 --- a/src/games/skyrim/src/skyrimgameplugins.cpp +++ b/src/games/skyrim/src/skyrimgameplugins.cpp @@ -1,44 +1,44 @@ #include "skyrimgameplugins.h" -#include -#include #include #include +#include #include #include -#include #include +#include - +using MOBase::IOrganizer; using MOBase::IPluginGame; using MOBase::IPluginList; -using MOBase::IOrganizer; -using MOBase::SafeWriteFile; using MOBase::reportError; +using MOBase::SafeWriteFile; -SkyrimGamePlugins::SkyrimGamePlugins(IOrganizer *organizer) +SkyrimGamePlugins::SkyrimGamePlugins(IOrganizer* organizer) : GamebryoGamePlugins(organizer) {} -void SkyrimGamePlugins::readPluginLists(MOBase::IPluginList *pluginList) { - QString loadOrderPath = - organizer()->profile()->absolutePath() + "/loadorder.txt"; - QString pluginsPath = organizer()->profile()->absolutePath() + "/plugins.txt"; +void SkyrimGamePlugins::readPluginLists(MOBase::IPluginList* pluginList) +{ + QString loadOrderPath = organizer()->profile()->absolutePath() + "/loadorder.txt"; + QString pluginsPath = organizer()->profile()->absolutePath() + "/plugins.txt"; - bool loadOrderIsNew = !m_LastRead.isValid() || - !QFileInfo(loadOrderPath).exists() || - QFileInfo(loadOrderPath).lastModified() > m_LastRead; - bool pluginsIsNew = !m_LastRead.isValid() || - QFileInfo(pluginsPath).lastModified() > m_LastRead; + bool loadOrderIsNew = !m_LastRead.isValid() || !QFileInfo(loadOrderPath).exists() || + QFileInfo(loadOrderPath).lastModified() > m_LastRead; + bool pluginsIsNew = + !m_LastRead.isValid() || QFileInfo(pluginsPath).lastModified() > m_LastRead; if (pluginsIsNew && !loadOrderIsNew) { - // If the plugins is new but not loadorder, we must reparse the load order from the plugin files + // If the plugins is new but not loadorder, we must reparse the load order from the + // plugin files - //removed because returned loadorder was incorrect and did not account for plugins that were already disabled before. + // removed because returned loadorder was incorrect and did not account for plugins + // that were already disabled before. /*QStringList loadOrder = readPluginList(pluginList); pluginList->setLoadOrder(loadOrder);*/ - //Fix me: we are ignoring order changes in plugins.txt favouring loadorder.txt in all cases (plugins.txt shuld have precedence) + // Fix me: we are ignoring order changes in plugins.txt favouring loadorder.txt in + // all cases (plugins.txt shuld have precedence) QStringList loadOrder = readLoadOrderList(pluginList, loadOrderPath); pluginList->setLoadOrder(loadOrder); readPluginList(pluginList); @@ -52,70 +52,72 @@ void SkyrimGamePlugins::readPluginLists(MOBase::IPluginList *pluginList) { m_LastRead = QDateTime::currentDateTime(); } -//TODO: return value is incorrect and should be ignored (it's not currently used -QStringList SkyrimGamePlugins::readPluginList(MOBase::IPluginList *pluginList) +// TODO: return value is incorrect and should be ignored (it's not currently used +QStringList SkyrimGamePlugins::readPluginList(MOBase::IPluginList* pluginList) { - QStringList plugins = pluginList->pluginNames(); - QStringList primaryPlugins = organizer()->managedGame()->primaryPlugins(); - QStringList loadOrder(plugins); + QStringList plugins = pluginList->pluginNames(); + QStringList primaryPlugins = organizer()->managedGame()->primaryPlugins(); + QStringList loadOrder(plugins); - for (const QString &pluginName : primaryPlugins) { - if (pluginList->state(pluginName) != IPluginList::STATE_MISSING) { - pluginList->setState(pluginName, IPluginList::STATE_ACTIVE); - } + for (const QString& pluginName : primaryPlugins) { + if (pluginList->state(pluginName) != IPluginList::STATE_MISSING) { + pluginList->setState(pluginName, IPluginList::STATE_ACTIVE); + } + } + + // Do not sort the primary plugins. Their load order should be locked as defined in + // "primaryPlugins". + const QStringList pluginsClone(plugins); + for (QString plugin : pluginsClone) { + if (primaryPlugins.contains(plugin, Qt::CaseInsensitive)) + plugins.removeAll(plugin); + } + + // Determine plugin active state by the plugins.txt file. + bool pluginsTxtExists = true; + QString filePath = organizer()->profile()->absolutePath() + "/plugins.txt"; + QFile file(filePath); + if (!file.open(QIODevice::ReadOnly)) { + pluginsTxtExists = false; + } + ON_BLOCK_EXIT([&]() { + qDebug("close %s", qUtf8Printable(filePath)); + file.close(); + }); + + if (file.size() == 0) { + // MO stores at least a header in the file. if it's completely empty the + // file is broken + pluginsTxtExists = false; + } + + if (pluginsTxtExists) { + while (!file.atEnd()) { + QByteArray line = file.readLine(); + QString pluginName; + if ((line.size() > 0) && (line.at(0) != '#')) { + pluginName = QStringEncoder(QStringConverter::Encoding::System) + .encode(line.trimmed().constData()); + } + if (pluginName.size() > 0) { + pluginList->setState(pluginName, IPluginList::STATE_ACTIVE); + plugins.removeAll(pluginName); + // we already have the old loadorder and we ignore the positions in plugins.txt + // (needs fix) loadOrder.append(pluginName); + } } - // Do not sort the primary plugins. Their load order should be locked as defined in "primaryPlugins". - const QStringList pluginsClone(plugins); - for (QString plugin : pluginsClone) { - if (primaryPlugins.contains(plugin, Qt::CaseInsensitive)) - plugins.removeAll(plugin); + file.close(); + + // we removed each plugin found in the file, so what's left are inactive mods + for (const QString& pluginName : plugins) { + pluginList->setState(pluginName, IPluginList::STATE_INACTIVE); } - - // Determine plugin active state by the plugins.txt file. - bool pluginsTxtExists = true; - QString filePath = organizer()->profile()->absolutePath() + "/plugins.txt"; - QFile file(filePath); - if (!file.open(QIODevice::ReadOnly)) { - pluginsTxtExists = false; + } else { + for (const QString& pluginName : plugins) { + pluginList->setState(pluginName, IPluginList::STATE_INACTIVE); } - ON_BLOCK_EXIT([&]() { - qDebug("close %s", qUtf8Printable(filePath)); - file.close(); - }); + } - if (file.size() == 0) { - // MO stores at least a header in the file. if it's completely empty the - // file is broken - pluginsTxtExists = false; - } - - if (pluginsTxtExists) { - while (!file.atEnd()) { - QByteArray line = file.readLine(); - QString pluginName; - if ((line.size() > 0) && (line.at(0) != '#')) { - pluginName = QStringEncoder(QStringConverter::Encoding::System).encode(line.trimmed().constData()); - } - if (pluginName.size() > 0) { - pluginList->setState(pluginName, IPluginList::STATE_ACTIVE); - plugins.removeAll(pluginName); - //we already have the old loadorder and we ignore the positions in plugins.txt (needs fix) - //loadOrder.append(pluginName); - } - } - - file.close(); - - // we removed each plugin found in the file, so what's left are inactive mods - for (const QString &pluginName : plugins) { - pluginList->setState(pluginName, IPluginList::STATE_INACTIVE); - } - } else { - for (const QString &pluginName : plugins) { - pluginList->setState(pluginName, IPluginList::STATE_INACTIVE); - } - } - - return loadOrder; + return loadOrder; } diff --git a/src/games/skyrim/src/skyrimgameplugins.h b/src/games/skyrim/src/skyrimgameplugins.h index 6fbdac91..8795c911 100644 --- a/src/games/skyrim/src/skyrimgameplugins.h +++ b/src/games/skyrim/src/skyrimgameplugins.h @@ -1,25 +1,23 @@ #ifndef _SKYRIMGAMEPLUGINS_H #define _SKYRIMGAMEPLUGINS_H - #include -#include #include +#include #include - class SkyrimGamePlugins : public GamebryoGamePlugins { public: - SkyrimGamePlugins(MOBase::IOrganizer *organizer); + SkyrimGamePlugins(MOBase::IOrganizer* organizer); - virtual void readPluginLists(MOBase::IPluginList *pluginList) override; + virtual void readPluginLists(MOBase::IPluginList* pluginList) override; protected: - virtual QStringList readPluginList(MOBase::IPluginList *pluginList) override; + virtual QStringList readPluginList(MOBase::IPluginList* pluginList) override; private: - std::map m_LastSaveHash; + std::map m_LastSaveHash; }; -#endif // _SKYRIMSEGAMEPLUGINS_H +#endif // _SKYRIMSEGAMEPLUGINS_H diff --git a/src/games/skyrim/src/skyrimmoddatachecker.h b/src/games/skyrim/src/skyrimmoddatachecker.h index a5c59392..4de6d6cb 100644 --- a/src/games/skyrim/src/skyrimmoddatachecker.h +++ b/src/games/skyrim/src/skyrimmoddatachecker.h @@ -9,22 +9,42 @@ 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", - "skse", "distantlod", "asi", "Tools", "MCM", "distantland", "mits", - "dllplugins", "SkyProc Patchers", "CalienteTools", "NetScriptFramework", - "shadersfx", "Nemesis_Engine" - }; + virtual const FileNameSet& possibleFolderNames() const override + { + static FileNameSet result{"fonts", + "interface", + "menus", + "meshes", + "music", + "scripts", + "shaders", + "sound", + "strings", + "textures", + "trees", + "video", + "facegen", + "materials", + "skse", + "distantlod", + "asi", + "Tools", + "MCM", + "distantland", + "mits", + "dllplugins", + "SkyProc Patchers", + "CalienteTools", + "NetScriptFramework", + "shadersfx", + "Nemesis_Engine"}; return result; } - virtual const FileNameSet& possibleFileExtensions() const override { - static FileNameSet result{ - "esp", "esm", "bsa", "modgroups", "ini" - }; + virtual const FileNameSet& possibleFileExtensions() const override + { + static FileNameSet result{"esp", "esm", "bsa", "modgroups", "ini"}; return result; } }; -#endif // SKYRIM_MODATACHECKER_H +#endif // SKYRIM_MODATACHECKER_H diff --git a/src/games/skyrim/src/skyrimmoddatacontent.h b/src/games/skyrim/src/skyrimmoddatacontent.h index 2a8948d4..96ec5a68 100644 --- a/src/games/skyrim/src/skyrimmoddatacontent.h +++ b/src/games/skyrim/src/skyrimmoddatacontent.h @@ -5,11 +5,10 @@ #include // Skyrim does not need any change from the default feature: -class SkyrimModDataContent : public GamebryoModDataContent { +class SkyrimModDataContent : public GamebryoModDataContent +{ public: - using GamebryoModDataContent::GamebryoModDataContent; - }; -#endif // SKYRIM_MODDATACONTENT_H +#endif // SKYRIM_MODDATACONTENT_H diff --git a/src/games/skyrim/src/skyrimsavegame.cpp b/src/games/skyrim/src/skyrimsavegame.cpp index dd9ef1f4..993cd18d 100644 --- a/src/games/skyrim/src/skyrimsavegame.cpp +++ b/src/games/skyrim/src/skyrimsavegame.cpp @@ -4,77 +4,73 @@ #include "gameskyrim.h" -SkyrimSaveGame::SkyrimSaveGame(QString const& fileName, GameSkyrim const* game) : - GamebryoSaveGame(fileName, game) +SkyrimSaveGame::SkyrimSaveGame(QString const& fileName, GameSkyrim const* game) + : GamebryoSaveGame(fileName, game) { - FileWrapper file(getFilepath(), "TESV_SAVEGAME"); + FileWrapper file(getFilepath(), "TESV_SAVEGAME"); - FILETIME ftime; - fetchInformationFields(file, m_SaveNumber, m_PCName, m_PCLevel, m_PCLocation, ftime); + FILETIME ftime; + fetchInformationFields(file, m_SaveNumber, m_PCName, m_PCLevel, m_PCLocation, ftime); - //A file time is a 64-bit value that represents the number of 100-nanosecond - //intervals that have elapsed since 12:00 A.M. January 1, 1601 Coordinated Universal Time (UTC). - //So we need to convert that to something useful - SYSTEMTIME ctime; - ::FileTimeToSystemTime(&ftime, &ctime); - setCreationTime(ctime); + // A file time is a 64-bit value that represents the number of 100-nanosecond + // intervals that have elapsed since 12:00 A.M. January 1, 1601 Coordinated Universal + // Time (UTC). So we need to convert that to something useful + SYSTEMTIME ctime; + ::FileTimeToSystemTime(&ftime, &ctime); + setCreationTime(ctime); } - -void SkyrimSaveGame::fetchInformationFields(FileWrapper& file, - unsigned long& saveNumber, - QString& playerName, - unsigned short& playerLevel, - QString& playerLocation, - FILETIME& creationTime) const +void SkyrimSaveGame::fetchInformationFields( + FileWrapper& file, unsigned long& saveNumber, QString& playerName, + unsigned short& playerLevel, QString& playerLocation, FILETIME& creationTime) const { - file.skip(); // header size - file.skip(); // header version - file.read(saveNumber); + file.skip(); // header size + file.skip(); // header version + file.read(saveNumber); - file.read(playerName); + file.read(playerName); - unsigned long temp; - file.read(temp); - playerLevel = static_cast(temp); + unsigned long temp; + file.read(temp); + playerLevel = static_cast(temp); - file.setPluginStringFormat(GamebryoSaveGame::StringFormat::LOCAL8BIT); - file.read(playerLocation); - file.setPluginStringFormat(GamebryoSaveGame::StringFormat::UTF8); + file.setPluginStringFormat(GamebryoSaveGame::StringFormat::LOCAL8BIT); + file.read(playerLocation); + file.setPluginStringFormat(GamebryoSaveGame::StringFormat::UTF8); - QString timeOfDay; - file.read(timeOfDay); + QString timeOfDay; + file.read(timeOfDay); - QString race; - file.read(race); // race name (i.e. BretonRace) + QString race; + file.read(race); // race name (i.e. BretonRace) - file.skip(); // Player gender (0 = male) - file.skip(2); // experience gathered, experience required + file.skip(); // Player gender (0 = male) + file.skip(2); // experience gathered, experience required - file.read(creationTime); + file.read(creationTime); } std::unique_ptr SkyrimSaveGame::fetchDataFields() const { - FileWrapper file(getFilepath(), "TESV_SAVEGAME"); - std::unique_ptr fields = std::make_unique(); + FileWrapper file(getFilepath(), "TESV_SAVEGAME"); + std::unique_ptr fields = std::make_unique(); - { - QString dummyName, dummyLocation; - unsigned short dummyLevel; - unsigned long dummySaveNumber; - FILETIME dummyTime; + { + QString dummyName, dummyLocation; + unsigned short dummyLevel; + unsigned long dummySaveNumber; + FILETIME dummyTime; - fetchInformationFields(file, dummySaveNumber, dummyName, dummyLevel, - dummyLocation, dummyTime); - } + fetchInformationFields(file, dummySaveNumber, dummyName, dummyLevel, dummyLocation, + dummyTime); + } - fields->Screenshot = file.readImage(); + fields->Screenshot = file.readImage(); - file.skip(); // form version - file.skip(); // plugin info size + file.skip(); // form version + file.skip(); // plugin info size - fields->Plugins = file.readPlugins(); + fields->Plugins = file.readPlugins(); - return fields; + return fields; } diff --git a/src/games/skyrim/src/skyrimsavegame.h b/src/games/skyrim/src/skyrimsavegame.h index 235f6dcd..2b26c3b1 100644 --- a/src/games/skyrim/src/skyrimsavegame.h +++ b/src/games/skyrim/src/skyrimsavegame.h @@ -5,26 +5,25 @@ #include -namespace MOBase { class IPluginGame; } +namespace MOBase +{ +class IPluginGame; +} class GameSkyrim; class SkyrimSaveGame : public GamebryoSaveGame { public: - SkyrimSaveGame(QString const &fileName, GameSkyrim const *game); + SkyrimSaveGame(QString const& fileName, GameSkyrim const* game); protected: - // Fetch easy-to-access information. - void fetchInformationFields(FileWrapper& wrapper, - unsigned long& saveNumber, - QString& playerName, - unsigned short& playerLevel, - QString& playerLocation, - FILETIME& creationTime) const; + void fetchInformationFields(FileWrapper& wrapper, unsigned long& saveNumber, + QString& playerName, unsigned short& playerLevel, + QString& playerLocation, FILETIME& creationTime) const; std::unique_ptr fetchDataFields() const override; }; -#endif // SKYRIMSAVEGAME_H +#endif // SKYRIMSAVEGAME_H diff --git a/src/games/skyrim/src/skyrimscriptextender.cpp b/src/games/skyrim/src/skyrimscriptextender.cpp index 62a7f669..38e17edf 100644 --- a/src/games/skyrim/src/skyrimscriptextender.cpp +++ b/src/games/skyrim/src/skyrimscriptextender.cpp @@ -1,19 +1,18 @@ -#include "skyrimscriptextender.h" - -#include -#include - -SkyrimScriptExtender::SkyrimScriptExtender(GameGamebryo const *game) : - GamebryoScriptExtender(game) -{ -} - -QString SkyrimScriptExtender::BinaryName() const -{ - return "skse_loader.exe"; -} - -QString SkyrimScriptExtender::PluginPath() const -{ - return "skse/plugins"; -} +#include "skyrimscriptextender.h" + +#include +#include + +SkyrimScriptExtender::SkyrimScriptExtender(GameGamebryo const* game) + : GamebryoScriptExtender(game) +{} + +QString SkyrimScriptExtender::BinaryName() const +{ + return "skse_loader.exe"; +} + +QString SkyrimScriptExtender::PluginPath() const +{ + return "skse/plugins"; +} diff --git a/src/games/skyrim/src/skyrimscriptextender.h b/src/games/skyrim/src/skyrimscriptextender.h index b1a370c1..6e952499 100644 --- a/src/games/skyrim/src/skyrimscriptextender.h +++ b/src/games/skyrim/src/skyrimscriptextender.h @@ -1,18 +1,17 @@ -#ifndef SKYRIMSCRIPTEXTENDER_H -#define SKYRIMSCRIPTEXTENDER_H - -#include "gamebryoscriptextender.h" - -class GameGamebryo; - -class SkyrimScriptExtender : public GamebryoScriptExtender -{ -public: - SkyrimScriptExtender(const GameGamebryo *game); - - virtual QString BinaryName() const override; - virtual QString PluginPath() const override; - -}; - -#endif // SKYRIMSCRIPTEXTENDER_H +#ifndef SKYRIMSCRIPTEXTENDER_H +#define SKYRIMSCRIPTEXTENDER_H + +#include "gamebryoscriptextender.h" + +class GameGamebryo; + +class SkyrimScriptExtender : public GamebryoScriptExtender +{ +public: + SkyrimScriptExtender(const GameGamebryo* game); + + virtual QString BinaryName() const override; + virtual QString PluginPath() const override; +}; + +#endif // SKYRIMSCRIPTEXTENDER_H From 1646013458eea0e48402ab108a33bf61cbcd2223 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Mika=C3=ABl=20Capelle?= Date: Sun, 9 Jun 2024 13:30:22 +0200 Subject: [PATCH 1488/1544] [game_skyrim] Add .git-blame-ignore-revs. --- src/games/skyrim/.git-blame-ignore-revs | 1 + 1 file changed, 1 insertion(+) create mode 100644 src/games/skyrim/.git-blame-ignore-revs diff --git a/src/games/skyrim/.git-blame-ignore-revs b/src/games/skyrim/.git-blame-ignore-revs new file mode 100644 index 00000000..088e8d92 --- /dev/null +++ b/src/games/skyrim/.git-blame-ignore-revs @@ -0,0 +1 @@ +130524f58eb58daa22e87727563254ce0025a35b From 4a3fdb12d0092b21fe0308944d86f3f45b79ce4e Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Mika=C3=ABl=20Capelle?= Date: Sun, 9 Jun 2024 13:30:22 +0200 Subject: [PATCH 1489/1544] [game_skyrim] Add github actions. --- src/games/skyrim/.github/workflows/build.yml | 16 ++++++++++++++++ src/games/skyrim/.github/workflows/linting.yml | 16 ++++++++++++++++ 2 files changed, 32 insertions(+) create mode 100644 src/games/skyrim/.github/workflows/build.yml create mode 100644 src/games/skyrim/.github/workflows/linting.yml diff --git a/src/games/skyrim/.github/workflows/build.yml b/src/games/skyrim/.github/workflows/build.yml new file mode 100644 index 00000000..d334d5cc --- /dev/null +++ b/src/games/skyrim/.github/workflows/build.yml @@ -0,0 +1,16 @@ +name: Build Skyrim Plugin + +on: + push: + branches: master + pull_request: + types: [opened, synchronize, reopened] + +jobs: + build: + runs-on: windows-2022 + steps: + - name: Build Skyrim Plugin + uses: ModOrganizer2/build-with-mob-action@master + with: + mo2-dependencies: cmake_common uibase game_gamebryo diff --git a/src/games/skyrim/.github/workflows/linting.yml b/src/games/skyrim/.github/workflows/linting.yml new file mode 100644 index 00000000..7a4ca469 --- /dev/null +++ b/src/games/skyrim/.github/workflows/linting.yml @@ -0,0 +1,16 @@ +name: Lint Skyrim Plugin + +on: + push: + pull_request: + types: [opened, synchronize, reopened] + +jobs: + lint: + runs-on: ubuntu-latest + steps: + - uses: actions/checkout@v3 + - name: Check format + uses: ModOrganizer2/check-formatting-action@master + with: + check-path: "." From a2ac5a2becfd0025ff01fe3199999b1fae490074 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Mika=C3=ABl=20Capelle?= Date: Sun, 9 Jun 2024 13:41:31 +0200 Subject: [PATCH 1490/1544] [game_skyrimvr] Remove appveyor.yml. --- src/games/skyrimvr/appveyor.yml | 40 --------------------------------- 1 file changed, 40 deletions(-) delete mode 100644 src/games/skyrimvr/appveyor.yml diff --git a/src/games/skyrimvr/appveyor.yml b/src/games/skyrimvr/appveyor.yml deleted file mode 100644 index 7707d706..00000000 --- a/src/games/skyrimvr/appveyor.yml +++ /dev/null @@ -1,40 +0,0 @@ -version: 1.0.{build} -skip_branch_with_pr: true -image: Visual Studio 2019 -environment: - WEBHOOK_URL: - secure: gOKbXaZM9ImtMD5XrYITvdyZUW/az082G9OIN1EC1Vbg57wBaeLhi49uGjxPw5GVujHku6kxN6ab89zhbS5GVeluR76GM83IbKV4Sh7udXzoYZZdg6YudtYHzdhCgUeiedpswbuczTq9ceIkkfSEWZuh/lMAAVVwvcGsJAnoPFw= -build_script: -- pwsh: >- - $ErrorActionPreference = 'Stop' - - git clone --depth=1 --no-single-branch https://github.com/ModOrganizer2/modorganizer-umbrella.git c:\projects\modorganizer-umbrella - - New-Item -ItemType Directory -Path c:\projects\modorganizer-build - - cd c:\projects\modorganizer-umbrella - - ($env:APPVEYOR_PULL_REQUEST_HEAD_REPO_BRANCH -eq $null) ? ($branch = $env:APPVEYOR_REPO_BRANCH) : ($branch = $env:APPVEYOR_PULL_REQUEST_HEAD_REPO_BRANCH) - - git checkout $(git show-ref --verify --quiet refs/remotes/origin/${branch} || echo '-b') ${branch} - - C:\Python37-x64\python.exe unimake.py -d c:\projects\modorganizer-build -s Appveyor_Build=True ${env:APPVEYOR_PROJECT_NAME} - - if($LastExitCode -ne 0) { $host.SetShouldExit($LastExitCode ) } -artifacts: -- path: vsbuild\src\RelWithDebInfo\game_skyrimvr.dll - name: game_skyrimvr_dll -- path: vsbuild\src\RelWithDebInfo\game_skyrimvr.pdb - name: game_skyrimvr_pdb -- path: vsbuild\src\RelWithDebInfo\game_skyrimvr.lib - name: game_skyrimvr_lib -on_success: - - ps: Set-Location -Path $env:APPVEYOR_BUILD_FOLDER - - ps: Invoke-RestMethod https://raw.githubusercontent.com/DiscordHooks/appveyor-discord-webhook/master/send.ps1 -o send.ps1 - - ps: ./send.ps1 success $env:WEBHOOK_URL -on_failure: - - ps: Set-Location -Path $env:APPVEYOR_BUILD_FOLDER - - ps: Push-AppveyorArtifact ${env:APPVEYOR_BUILD_FOLDER}\stdout.log - - ps: Push-AppveyorArtifact ${env:APPVEYOR_BUILD_FOLDER}\stderr.log - - ps: Invoke-RestMethod https://raw.githubusercontent.com/DiscordHooks/appveyor-discord-webhook/master/send.ps1 -o send.ps1 - - ps: ./send.ps1 failure $env:WEBHOOK_URL \ No newline at end of file From 8ed5f89b2a08811c9e9fa6a8a8e05abfca30e31d Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Mika=C3=ABl=20Capelle?= Date: Sun, 9 Jun 2024 13:41:31 +0200 Subject: [PATCH 1491/1544] [game_skyrimvr] Format files and add .gitattributes and .clang-format. --- src/games/skyrimvr/.clang-format | 41 ++++++++ src/games/skyrimvr/.gitattributes | 7 ++ src/games/skyrimvr/src/gameskyrimvr.cpp | 94 ++++++++++--------- src/games/skyrimvr/src/gameskyrimvr.h | 21 +++-- .../skyrimvr/src/skyrimvrdataarchives.cpp | 44 ++++----- src/games/skyrimvr/src/skyrimvrdataarchives.h | 21 ++--- .../skyrimvr/src/skyrimvrgameplugins.cpp | 16 ++-- src/games/skyrimvr/src/skyrimvrgameplugins.h | 9 +- .../skyrimvr/src/skyrimvrmoddatachecker.h | 25 ++--- .../skyrimvr/src/skyrimvrmoddatacontent.h | 11 ++- src/games/skyrimvr/src/skyrimvrsavegame.cpp | 58 ++++++------ src/games/skyrimvr/src/skyrimvrsavegame.h | 16 ++-- .../skyrimvr/src/skyrimvrscriptextender.cpp | 7 +- .../skyrimvr/src/skyrimvrscriptextender.h | 5 +- .../skyrimvr/src/skyrimvrunmanagedmods.cpp | 16 ++-- .../skyrimvr/src/skyrimvrunmanagedmods.h | 7 +- 16 files changed, 217 insertions(+), 181 deletions(-) create mode 100644 src/games/skyrimvr/.clang-format create mode 100644 src/games/skyrimvr/.gitattributes diff --git a/src/games/skyrimvr/.clang-format b/src/games/skyrimvr/.clang-format new file mode 100644 index 00000000..6098e1f5 --- /dev/null +++ b/src/games/skyrimvr/.clang-format @@ -0,0 +1,41 @@ +--- +# We'll use defaults from the LLVM style, but with 4 columns indentation. +BasedOnStyle: LLVM +IndentWidth: 2 +--- +Language: Cpp +DeriveLineEnding: false +UseCRLF: true +DerivePointerAlignment: false +PointerAlignment: Left +AlignConsecutiveAssignments: true +AllowShortFunctionsOnASingleLine: Inline +AllowShortIfStatementsOnASingleLine: Never +AllowShortLambdasOnASingleLine: Empty +AlwaysBreakTemplateDeclarations: Yes +AccessModifierOffset: -2 +AlignTrailingComments: true +SpacesBeforeTrailingComments: 2 +NamespaceIndentation: Inner +MaxEmptyLinesToKeep: 1 +BreakBeforeBraces: Custom +BraceWrapping: + AfterCaseLabel: false + AfterClass: true + AfterControlStatement: false + AfterEnum: true + AfterFunction: true + AfterNamespace: true + AfterStruct: true + AfterUnion: true + AfterExternBlock: true + BeforeCatch: false + BeforeElse: false + BeforeLambdaBody: false + BeforeWhile: false + IndentBraces: false + SplitEmptyFunction: false + SplitEmptyRecord: false + SplitEmptyNamespace: true +ColumnLimit: 88 +ForEachMacros: ['Q_FOREACH', 'foreach'] diff --git a/src/games/skyrimvr/.gitattributes b/src/games/skyrimvr/.gitattributes new file mode 100644 index 00000000..f8697127 --- /dev/null +++ b/src/games/skyrimvr/.gitattributes @@ -0,0 +1,7 @@ +# Set the default behavior, in case people don't have core.autocrlf set. +* text=auto + +# Explicitly declare text files you want to always be normalized and converted +# to native line endings on checkout. +*.cpp text eol=crlf +*.h text eol=crlf diff --git a/src/games/skyrimvr/src/gameskyrimvr.cpp b/src/games/skyrimvr/src/gameskyrimvr.cpp index 61f8a755..114ac311 100644 --- a/src/games/skyrimvr/src/gameskyrimvr.cpp +++ b/src/games/skyrimvr/src/gameskyrimvr.cpp @@ -1,18 +1,18 @@ #include "gameskyrimvr.h" #include "skyrimvrdataarchives.h" -#include "skyrimvrscriptextender.h" -#include "skyrimvrunmanagedmods.h" +#include "skyrimvrgameplugins.h" #include "skyrimvrmoddatachecker.h" #include "skyrimvrmoddatacontent.h" #include "skyrimvrsavegame.h" -#include "skyrimvrgameplugins.h" +#include "skyrimvrscriptextender.h" +#include "skyrimvrunmanagedmods.h" -#include +#include "versioninfo.h" #include #include #include -#include "versioninfo.h" +#include #include #include @@ -22,16 +22,14 @@ #include #include -#include #include "scopeguard.h" +#include using namespace MOBase; -GameSkyrimVR::GameSkyrimVR() -{ -} +GameSkyrimVR::GameSkyrimVR() {} -void GameSkyrimVR::setGamePath(const QString &path) +void GameSkyrimVR::setGamePath(const QString& path) { m_GamePath = path; } @@ -44,7 +42,8 @@ QDir GameSkyrimVR::documentsDirectory() const QString GameSkyrimVR::identifyGamePath() const { QString path = "Software\\Bethesda Softworks\\" + gameName(); - return findInRegistry(HKEY_LOCAL_MACHINE, path.toStdWString().c_str(), L"Installed Path"); + return findInRegistry(HKEY_LOCAL_MACHINE, path.toStdWString().c_str(), + L"Installed Path"); } QDir GameSkyrimVR::savesDirectory() const @@ -62,7 +61,7 @@ bool GameSkyrimVR::isInstalled() const return !m_GamePath.isEmpty(); } -bool GameSkyrimVR::init(IOrganizer *moInfo) +bool GameSkyrimVR::init(IOrganizer* moInfo) { if (!GameGamebryo::init(moInfo)) { return false; @@ -70,18 +69,18 @@ bool GameSkyrimVR::init(IOrganizer *moInfo) registerFeature(std::make_shared(this)); registerFeature(std::make_shared(myGamesPath())); - registerFeature(std::make_shared(myGamesPath(), "SkyrimVR.ini")); + registerFeature( + std::make_shared(myGamesPath(), "SkyrimVR.ini")); registerFeature(std::make_shared(this)); registerFeature(std::make_shared(this)); - registerFeature(std::make_shared(m_Organizer->gameFeatures())); + registerFeature( + std::make_shared(m_Organizer->gameFeatures())); registerFeature(std::make_shared(moInfo)); registerFeature(std::make_shared(this)); return true; } - - QString GameSkyrimVR::gameName() const { return "Skyrim VR"; @@ -90,11 +89,14 @@ QString GameSkyrimVR::gameName() const QList GameSkyrimVR::executables() const { return QList() - << ExecutableInfo("SKSE", findInGameFolder(m_Organizer->gameFeatures()->gameFeature()->loaderName())) - << ExecutableInfo("Skyrim VR", findInGameFolder(binaryName())) - << ExecutableInfo("Creation Kit", findInGameFolder("CreationKit.exe")) - << ExecutableInfo("LOOT", QFileInfo(getLootPath())).withArgument("--game=\"Skyrim VR\"") - ; + << ExecutableInfo("SKSE", + findInGameFolder(m_Organizer->gameFeatures() + ->gameFeature() + ->loaderName())) + << ExecutableInfo("Skyrim VR", findInGameFolder(binaryName())) + << ExecutableInfo("Creation Kit", findInGameFolder("CreationKit.exe")) + << ExecutableInfo("LOOT", QFileInfo(getLootPath())) + .withArgument("--game=\"Skyrim VR\""); } QList GameSkyrimVR::executableForcedLoads() const @@ -102,7 +104,7 @@ QList GameSkyrimVR::executableForcedLoads() const return QList(); } -QFileInfo GameSkyrimVR::findInGameFolder(const QString &relativePath) const +QFileInfo GameSkyrimVR::findInGameFolder(const QString& relativePath) const { return QFileInfo(m_GamePath + "/" + relativePath); } @@ -134,20 +136,19 @@ MOBase::VersionInfo GameSkyrimVR::version() const QList GameSkyrimVR::settings() const { - return { - PluginSetting("enderal_downloads", "allow Enderal and Enderal SE downloads", QVariant(false)) - }; + return {PluginSetting("enderal_downloads", "allow Enderal and Enderal SE downloads", + QVariant(false))}; } -void GameSkyrimVR::initializeProfile(const QDir &path, ProfileSettings settings) const +void GameSkyrimVR::initializeProfile(const QDir& path, ProfileSettings settings) const { if (settings.testFlag(IPluginGame::MODS)) { copyToProfile(localAppFolder() + "/Skyrim VR", path, "plugins.txt"); } if (settings.testFlag(IPluginGame::CONFIGURATION)) { - if (settings.testFlag(IPluginGame::PREFER_DEFAULTS) - || !QFileInfo(myGamesPath() + "/skyrimvr.ini").exists()) { + if (settings.testFlag(IPluginGame::PREFER_DEFAULTS) || + !QFileInfo(myGamesPath() + "/skyrimvr.ini").exists()) { copyToProfile(gameDirectory().absolutePath(), path, "skyrim.ini", "skyrimvr.ini"); } else { copyToProfile(myGamesPath(), path, "skyrimvr.ini"); @@ -167,19 +168,21 @@ QString GameSkyrimVR::savegameSEExtension() const return "skse"; } -std::shared_ptr GameSkyrimVR::makeSaveGame(QString filePath) const +std::shared_ptr +GameSkyrimVR::makeSaveGame(QString filePath) const { return std::make_shared(filePath, this); } - QString GameSkyrimVR::steamAPPId() const { return "611670"; } -QStringList GameSkyrimVR::primaryPlugins() const { - QStringList plugins = { "skyrim.esm", "update.esm", "dawnguard.esm", "hearthfires.esm", "dragonborn.esm", "skyrimvr.esm" }; +QStringList GameSkyrimVR::primaryPlugins() const +{ + QStringList plugins = {"skyrim.esm", "update.esm", "dawnguard.esm", + "hearthfires.esm", "dragonborn.esm", "skyrimvr.esm"}; plugins.append(CCPlugins()); @@ -188,7 +191,7 @@ QStringList GameSkyrimVR::primaryPlugins() const { QStringList GameSkyrimVR::gameVariants() const { - return{ "Regular" }; + return {"Regular"}; } QString GameSkyrimVR::gameShortName() const @@ -198,14 +201,14 @@ QString GameSkyrimVR::gameShortName() const QStringList GameSkyrimVR::primarySources() const { - return { "SkyrimSE" }; + return {"SkyrimSE"}; } QStringList GameSkyrimVR::validShortNames() const { - QStringList shortNames{ "Skyrim", "SkyrimSE" }; + QStringList shortNames{"Skyrim", "SkyrimSE"}; if (m_Organizer->pluginSetting(name(), "enderal_downloads").toBool()) { - shortNames.append({ "Enderal", "EnderalSE" }); + shortNames.append({"Enderal", "EnderalSE"}); } return shortNames; } @@ -215,15 +218,14 @@ QString GameSkyrimVR::gameNexusName() const return QString(); } - QStringList GameSkyrimVR::iniFiles() const { - return{ "skyrimvr.ini", "skyrimprefs.ini" }; + return {"skyrimvr.ini", "skyrimprefs.ini"}; } QStringList GameSkyrimVR::DLCPlugins() const { - return{ "dawnguard.esm", "hearthfires.esm", "dragonborn.esm" }; + return {"dawnguard.esm", "hearthfires.esm", "dragonborn.esm"}; } QStringList GameSkyrimVR::CCPlugins() const @@ -231,7 +233,9 @@ QStringList GameSkyrimVR::CCPlugins() const QStringList plugins = {}; QFile file(gameDirectory().filePath("Skyrim.ccc")); if (file.open(QIODevice::ReadOnly)) { - ON_BLOCK_EXIT([&file]() { file.close(); }); + ON_BLOCK_EXIT([&file]() { + file.close(); + }); if (file.size() == 0) { return plugins; @@ -275,7 +279,8 @@ int GameSkyrimVR::nexusGameID() const QString GameSkyrimVR::getLauncherName() const { - return binaryName(); // Skyrim VR has no Launcher, so we just return the name of the game binary + return binaryName(); // Skyrim VR has no Launcher, so we just return the name of the + // game binary } QDir GameSkyrimVR::gameDirectory() const @@ -288,10 +293,9 @@ MappingType GameSkyrimVR::mappings() const { MappingType result; - for (const QString &profileFile : { "plugins.txt", "loadorder.txt" }) { - result.push_back({ m_Organizer->profilePath() + "/" + profileFile, - localAppFolder() + "/" + gameName() + "/" + profileFile, - false }); + for (const QString& profileFile : {"plugins.txt", "loadorder.txt"}) { + result.push_back({m_Organizer->profilePath() + "/" + profileFile, + localAppFolder() + "/" + gameName() + "/" + profileFile, false}); } return result; diff --git a/src/games/skyrimvr/src/gameskyrimvr.h b/src/games/skyrimvr/src/gameskyrimvr.h index 6fd19ba9..ec4ccf81 100644 --- a/src/games/skyrimvr/src/gameskyrimvr.h +++ b/src/games/skyrimvr/src/gameskyrimvr.h @@ -14,14 +14,16 @@ class GameSkyrimVR : public GameGamebryo public: GameSkyrimVR(); - virtual bool init(MOBase::IOrganizer *moInfo) override; + virtual bool init(MOBase::IOrganizer* moInfo) override; -public: // IPluginGame interface +public: // IPluginGame interface virtual QString gameName() const override; virtual QList executables() const override; - virtual QList executableForcedLoads() const override; - virtual void initializeProfile(const QDir &path, ProfileSettings settings) const override; + virtual QList + 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; @@ -39,10 +41,10 @@ public: // IPluginGame interface virtual QString getLauncherName() const override; virtual bool isInstalled() const override; - virtual void setGamePath(const QString &path) override; + virtual void setGamePath(const QString& path) override; virtual QDir gameDirectory() const override; -public: // IPlugin interface +public: // IPlugin interface virtual QString name() const override; virtual QString localizedName() const override; virtual QString author() const override; @@ -50,20 +52,19 @@ public: // IPlugin interface virtual MOBase::VersionInfo version() const override; virtual QList settings() const override; -public: // IPluginFileMapper +public: // IPluginFileMapper virtual MappingType mappings() const override; protected: - std::shared_ptr makeSaveGame(QString filePath) const override; QString savegameExtension() const override; QString savegameSEExtension() const override; QDir documentsDirectory() const; QDir savesDirectory() const; - QFileInfo findInGameFolder(const QString &relativePath) const; + QFileInfo findInGameFolder(const QString& relativePath) const; QString myGamesPath() const; virtual QString identifyGamePath() const override; }; -#endif // _GAMESKYRIMVR_H +#endif // _GAMESKYRIMVR_H diff --git a/src/games/skyrimvr/src/skyrimvrdataarchives.cpp b/src/games/skyrimvr/src/skyrimvrdataarchives.cpp index 423f6242..40438f7d 100644 --- a/src/games/skyrimvr/src/skyrimvrdataarchives.cpp +++ b/src/games/skyrimvr/src/skyrimvrdataarchives.cpp @@ -3,50 +3,42 @@ #include "iprofile.h" #include -SkyrimVRDataArchives::SkyrimVRDataArchives(const QDir &myGamesDir) : - GamebryoDataArchives(myGamesDir) +SkyrimVRDataArchives::SkyrimVRDataArchives(const QDir& myGamesDir) + : GamebryoDataArchives(myGamesDir) {} QStringList SkyrimVRDataArchives::vanillaArchives() const { - return{ "Skyrim - Textures0.bsa" - , "Skyrim - Textures1.bsa" - , "Skyrim - Textures2.bsa" - , "Skyrim - Textures3.bsa" - , "Skyrim - Textures4.bsa" - , "Skyrim - Textures5.bsa" - , "Skyrim - Textures6.bsa" - , "Skyrim - Textures7.bsa" - , "Skyrim - Textures8.bsa" - , "Skyrim - Meshes0.bsa" - , "Skyrim - Meshes1.bsa" - , "Skyrim - Voices_en0.bsa" - , "Skyrim - Sounds.bsa" - , "Skyrim - Interface.bsa" - , "Skyrim - Animations.bsa" - , "Skyrim - Shaders.bsa" - , "Skyrim - Misc.bsa" - , "Skyrim - Patch.bsa" - , "Skyrim_VR - Main.bsa" }; + return {"Skyrim - Textures0.bsa", "Skyrim - Textures1.bsa", "Skyrim - Textures2.bsa", + "Skyrim - Textures3.bsa", "Skyrim - Textures4.bsa", "Skyrim - Textures5.bsa", + "Skyrim - Textures6.bsa", "Skyrim - Textures7.bsa", "Skyrim - Textures8.bsa", + "Skyrim - Meshes0.bsa", "Skyrim - Meshes1.bsa", "Skyrim - Voices_en0.bsa", + "Skyrim - Sounds.bsa", "Skyrim - Interface.bsa", "Skyrim - Animations.bsa", + "Skyrim - Shaders.bsa", "Skyrim - Misc.bsa", "Skyrim - Patch.bsa", + "Skyrim_VR - Main.bsa"}; } - -QStringList SkyrimVRDataArchives::archives(const MOBase::IProfile *profile) const +QStringList SkyrimVRDataArchives::archives(const MOBase::IProfile* profile) const { QStringList result; - QString iniFile = profile->localSettingsEnabled() ? QDir(profile->absolutePath()).absoluteFilePath("skyrimvr.ini") : m_LocalGameDir.absoluteFilePath("skyrimvr.ini"); + QString iniFile = profile->localSettingsEnabled() + ? QDir(profile->absolutePath()).absoluteFilePath("skyrimvr.ini") + : m_LocalGameDir.absoluteFilePath("skyrimvr.ini"); result.append(getArchivesFromKey(iniFile, "SResourceArchiveList")); result.append(getArchivesFromKey(iniFile, "SResourceArchiveList2")); return result; } -void SkyrimVRDataArchives::writeArchiveList(MOBase::IProfile *profile, const QStringList &before) +void SkyrimVRDataArchives::writeArchiveList(MOBase::IProfile* profile, + const QStringList& before) { QString list = before.join(", "); - QString iniFile = profile->localSettingsEnabled() ? QDir(profile->absolutePath()).absoluteFilePath("skyrimvr.ini") : m_LocalGameDir.absoluteFilePath("skyrimvr.ini"); + QString iniFile = profile->localSettingsEnabled() + ? QDir(profile->absolutePath()).absoluteFilePath("skyrimvr.ini") + : m_LocalGameDir.absoluteFilePath("skyrimvr.ini"); if (list.length() > 255) { int splitIdx = list.lastIndexOf(",", 256); setArchivesToKey(iniFile, "SResourceArchiveList", list.mid(0, splitIdx)); diff --git a/src/games/skyrimvr/src/skyrimvrdataarchives.h b/src/games/skyrimvr/src/skyrimvrdataarchives.h index 7ed603bb..e1519ca8 100644 --- a/src/games/skyrimvr/src/skyrimvrdataarchives.h +++ b/src/games/skyrimvr/src/skyrimvrdataarchives.h @@ -2,28 +2,27 @@ #define _SKYRIMVRDATAARCHIVES_H #include "gamebryodataarchives.h" -#include #include +#include -namespace MOBase { class IProfile; } - +namespace MOBase +{ +class IProfile; +} class SkyrimVRDataArchives : public GamebryoDataArchives { public: - - SkyrimVRDataArchives(const QDir &myGamesDir); + SkyrimVRDataArchives(const QDir& myGamesDir); public: - virtual QStringList vanillaArchives() const override; - virtual QStringList archives(const MOBase::IProfile *profile) const override; + virtual QStringList archives(const MOBase::IProfile* profile) const override; private: - - virtual void writeArchiveList(MOBase::IProfile *profile, const QStringList &before) override; - + virtual void writeArchiveList(MOBase::IProfile* profile, + const QStringList& before) override; }; -#endif // _SKYRIMVRDATAARCHIVES_H +#endif // _SKYRIMVRDATAARCHIVES_H diff --git a/src/games/skyrimvr/src/skyrimvrgameplugins.cpp b/src/games/skyrimvr/src/skyrimvrgameplugins.cpp index c5f5b55b..1524ffe3 100644 --- a/src/games/skyrimvr/src/skyrimvrgameplugins.cpp +++ b/src/games/skyrimvr/src/skyrimvrgameplugins.cpp @@ -2,14 +2,14 @@ using namespace MOBase; -SkyrimVRGamePlugins::SkyrimVRGamePlugins(MOBase::IOrganizer* organizer) : CreationGamePlugins(organizer) -{ -} +SkyrimVRGamePlugins::SkyrimVRGamePlugins(MOBase::IOrganizer* organizer) + : CreationGamePlugins(organizer) +{} bool SkyrimVRGamePlugins::lightPluginsAreSupported() { - auto files = m_Organizer->findFiles("skse\\plugins", { "skyrimvresl.dll" }); - if (files.isEmpty()) - return false; - return true; -} \ No newline at end of file + auto files = m_Organizer->findFiles("skse\\plugins", {"skyrimvresl.dll"}); + if (files.isEmpty()) + return false; + return true; +} diff --git a/src/games/skyrimvr/src/skyrimvrgameplugins.h b/src/games/skyrimvr/src/skyrimvrgameplugins.h index 97ee0fe7..6f9676f0 100644 --- a/src/games/skyrimvr/src/skyrimvrgameplugins.h +++ b/src/games/skyrimvr/src/skyrimvrgameplugins.h @@ -10,13 +10,10 @@ class SkyrimVRGamePlugins : public CreationGamePlugins { public: - - SkyrimVRGamePlugins(MOBase::IOrganizer* organizer); + SkyrimVRGamePlugins(MOBase::IOrganizer* organizer); protected: - - virtual bool lightPluginsAreSupported() override; - + virtual bool lightPluginsAreSupported() override; }; -#endif // _SKYRIMVRGAMEPLUGINS_H \ No newline at end of file +#endif // _SKYRIMVRGAMEPLUGINS_H diff --git a/src/games/skyrimvr/src/skyrimvrmoddatachecker.h b/src/games/skyrimvr/src/skyrimvrmoddatachecker.h index 377e8ced..0fef53fd 100644 --- a/src/games/skyrimvr/src/skyrimvrmoddatachecker.h +++ b/src/games/skyrimvr/src/skyrimvrmoddatachecker.h @@ -9,22 +9,23 @@ public: using GamebryoModDataChecker::GamebryoModDataChecker; protected: - virtual const FileNameSet& possibleFolderNames() const override { + virtual const FileNameSet& possibleFolderNames() const override + { static FileNameSet result{ - "fonts", "interface", "menus", "meshes", "music", "scripts", "shaders", - "sound", "strings", "textures", "trees", "video", "facegen", "materials", - "skse", "distantlod", "asi", "Tools", "MCM", "distantland", "mits", - "dllplugins", "CalienteTools", "NetScriptFramework", "shadersfx", - "Nemesis_Engine" - }; + "fonts", "interface", "menus", "meshes", + "music", "scripts", "shaders", "sound", + "strings", "textures", "trees", "video", + "facegen", "materials", "skse", "distantlod", + "asi", "Tools", "MCM", "distantland", + "mits", "dllplugins", "CalienteTools", "NetScriptFramework", + "shadersfx", "Nemesis_Engine"}; return result; } - virtual const FileNameSet& possibleFileExtensions() const override { - static FileNameSet result{ - "esp", "esm", "bsa", "modgroups", "ini" - }; + virtual const FileNameSet& possibleFileExtensions() const override + { + static FileNameSet result{"esp", "esm", "bsa", "modgroups", "ini"}; return result; } }; -#endif // SKYRIMVR_MODATACHECKER_H +#endif // SKYRIMVR_MODATACHECKER_H diff --git a/src/games/skyrimvr/src/skyrimvrmoddatacontent.h b/src/games/skyrimvr/src/skyrimvrmoddatacontent.h index 3a5dc9f6..36f56ffe 100644 --- a/src/games/skyrimvr/src/skyrimvrmoddatacontent.h +++ b/src/games/skyrimvr/src/skyrimvrmoddatacontent.h @@ -4,17 +4,18 @@ #include #include -class SkyrimVRModDataContent : public GamebryoModDataContent { +class SkyrimVRModDataContent : public GamebryoModDataContent +{ public: - /** * */ - SkyrimVRModDataContent(MOBase::IGameFeatures const* gameFeatures) : GamebryoModDataContent(gameFeatures) { + SkyrimVRModDataContent(MOBase::IGameFeatures const* gameFeatures) + : GamebryoModDataContent(gameFeatures) + { // Just need to disable some contents: m_Enabled[CONTENT_SKYPROC] = false; } - }; -#endif // SKYRIMVR_MODDATACONTENT_H +#endif // SKYRIMVR_MODDATACONTENT_H diff --git a/src/games/skyrimvr/src/skyrimvrsavegame.cpp b/src/games/skyrimvr/src/skyrimvrsavegame.cpp index 29d7a1c6..c1c29c74 100644 --- a/src/games/skyrimvr/src/skyrimvrsavegame.cpp +++ b/src/games/skyrimvr/src/skyrimvrsavegame.cpp @@ -4,27 +4,28 @@ #include "gameskyrimvr.h" -SkyrimVRSaveGame::SkyrimVRSaveGame(QString const &fileName, GameSkyrimVR const *game) : - GamebryoSaveGame(fileName, game, true) +SkyrimVRSaveGame::SkyrimVRSaveGame(QString const& fileName, GameSkyrimVR const* game) + : GamebryoSaveGame(fileName, game, true) { - FileWrapper file(fileName, "TESV_SAVEGAME"); //10bytes + FileWrapper file(fileName, "TESV_SAVEGAME"); // 10bytes unsigned long version; FILETIME ftime; - fetchInformationFields(file, version, m_PCName, m_PCLevel, m_PCLocation, m_SaveNumber, ftime); + fetchInformationFields(file, version, m_PCName, m_PCLevel, m_PCLocation, m_SaveNumber, + ftime); // A file time is a 64-bit value that represents the number of 100-nanosecond - // intervals that have elapsed since 12:00 A.M. January 1, 1601 Coordinated Universal Time (UTC). - // So we need to convert that to something useful + // intervals that have elapsed since 12:00 A.M. January 1, 1601 Coordinated Universal + // Time (UTC). So we need to convert that to something useful // For some reason, the file time is off by about 6 hours. // So we need to subtract those 6 hours from the filetime. _ULARGE_INTEGER time; - time.LowPart = ftime.dwLowDateTime; + time.LowPart = ftime.dwLowDateTime; time.HighPart = ftime.dwHighDateTime; time.QuadPart -= 2.16e11; ftime.dwHighDateTime = time.HighPart; - ftime.dwLowDateTime = time.LowPart; + ftime.dwLowDateTime = time.LowPart; SYSTEMTIME ctime; ::FileTimeToSystemTime(&ftime, &ctime); @@ -32,19 +33,16 @@ SkyrimVRSaveGame::SkyrimVRSaveGame(QString const &fileName, GameSkyrimVR const * setCreationTime(ctime); } - -void SkyrimVRSaveGame::fetchInformationFields( - FileWrapper& file, - unsigned long& version, - QString& playerName, - unsigned short& playerLevel, - QString& playerLocation, - unsigned long& saveNumber, - FILETIME& creationTime) const +void SkyrimVRSaveGame::fetchInformationFields(FileWrapper& file, unsigned long& version, + QString& playerName, + unsigned short& playerLevel, + QString& playerLocation, + unsigned long& saveNumber, + FILETIME& creationTime) const { unsigned long headerSize; - file.read(headerSize); // header size "TESV_SAVEGAME" - file.read(version); // header version 74 (original Skyrim is 79) + file.read(headerSize); // header size "TESV_SAVEGAME" + file.read(version); // header version 74 (original Skyrim is 79) file.read(saveNumber); file.read(playerName); @@ -59,17 +57,17 @@ void SkyrimVRSaveGame::fetchInformationFields( file.read(timeOfDay); QString race; - file.read(race); // race name (i.e. BretonRace) + file.read(race); // race name (i.e. BretonRace) - file.skip(); // Player gender (0 = male) - file.skip(2); // experience gathered, experience required + file.skip(); // Player gender (0 = male) + file.skip(2); // experience gathered, experience required - file.read(creationTime); //filetime + file.read(creationTime); // filetime } std::unique_ptr SkyrimVRSaveGame::fetchDataFields() const { - FileWrapper file(getFilepath(), "TESV_SAVEGAME"); //10bytes + FileWrapper file(getFilepath(), "TESV_SAVEGAME"); // 10bytes unsigned long version = 0; { @@ -78,8 +76,8 @@ std::unique_ptr SkyrimVRSaveGame::fetchDataFields( unsigned long dummySaveNumber; FILETIME dummyTime; - fetchInformationFields(file, version, dummyName, dummyLevel, - dummyLocation, dummySaveNumber, dummyTime); + fetchInformationFields(file, version, dummyName, dummyLevel, dummyLocation, + dummySaveNumber, dummyTime); } std::unique_ptr fields = std::make_unique(); @@ -98,10 +96,10 @@ std::unique_ptr SkyrimVRSaveGame::fetchDataFields( file.openCompressedData(); uint8_t saveGameVersion = file.readChar(); - uint8_t pluginInfoSize = file.readChar(); - uint16_t other = file.readShort(); //Unknown + uint8_t pluginInfoSize = file.readChar(); + uint16_t other = file.readShort(); // Unknown - fields->Plugins = file.readPlugins(1); // Just empty data + fields->Plugins = file.readPlugins(1); // Just empty data if (saveGameVersion >= 78) { fields->LightPlugins = file.readLightPlugins(); @@ -110,4 +108,4 @@ std::unique_ptr SkyrimVRSaveGame::fetchDataFields( file.closeCompressedData(); return fields; -} \ No newline at end of file +} diff --git a/src/games/skyrimvr/src/skyrimvrsavegame.h b/src/games/skyrimvr/src/skyrimvrsavegame.h index db8b95da..5ed5e965 100644 --- a/src/games/skyrimvr/src/skyrimvrsavegame.h +++ b/src/games/skyrimvr/src/skyrimvrsavegame.h @@ -10,20 +10,16 @@ class GameSkyrimVR; class SkyrimVRSaveGame : public GamebryoSaveGame { public: - SkyrimVRSaveGame(QString const &fileName, GameSkyrimVR const *game); + SkyrimVRSaveGame(QString const& fileName, GameSkyrimVR const* game); protected: - // Fetch easy-to-access information. - void fetchInformationFields(FileWrapper& wrapper, - unsigned long& version, - QString& playerName, - unsigned short& playerLevel, - QString& playerLocation, - unsigned long& saveNumber, - FILETIME& creationTime) const; + void fetchInformationFields(FileWrapper& wrapper, unsigned long& version, + QString& playerName, unsigned short& playerLevel, + QString& playerLocation, unsigned long& saveNumber, + FILETIME& creationTime) const; std::unique_ptr fetchDataFields() const override; }; -#endif // _SKYRIMVRSAVEGAME_H +#endif // _SKYRIMVRSAVEGAME_H diff --git a/src/games/skyrimvr/src/skyrimvrscriptextender.cpp b/src/games/skyrimvr/src/skyrimvrscriptextender.cpp index 8668a7ce..4d7433d1 100644 --- a/src/games/skyrimvr/src/skyrimvrscriptextender.cpp +++ b/src/games/skyrimvr/src/skyrimvrscriptextender.cpp @@ -3,10 +3,9 @@ #include #include -SkyrimVRScriptExtender::SkyrimVRScriptExtender(GameGamebryo const *game) : - GamebryoScriptExtender(game) -{ -} +SkyrimVRScriptExtender::SkyrimVRScriptExtender(GameGamebryo const* game) + : GamebryoScriptExtender(game) +{} QString SkyrimVRScriptExtender::BinaryName() const { diff --git a/src/games/skyrimvr/src/skyrimvrscriptextender.h b/src/games/skyrimvr/src/skyrimvrscriptextender.h index a3a580db..9bf3168e 100644 --- a/src/games/skyrimvr/src/skyrimvrscriptextender.h +++ b/src/games/skyrimvr/src/skyrimvrscriptextender.h @@ -8,11 +8,10 @@ class GameGamebryo; class SkyrimVRScriptExtender : public GamebryoScriptExtender { public: - SkyrimVRScriptExtender(GameGamebryo const *game); + SkyrimVRScriptExtender(GameGamebryo const* game); virtual QString BinaryName() const override; virtual QString PluginPath() const override; - }; -#endif // _SKYRIMVRSCRIPTEXTENDER_H +#endif // _SKYRIMVRSCRIPTEXTENDER_H diff --git a/src/games/skyrimvr/src/skyrimvrunmanagedmods.cpp b/src/games/skyrimvr/src/skyrimvrunmanagedmods.cpp index e79472e2..dd6a1588 100644 --- a/src/games/skyrimvr/src/skyrimvrunmanagedmods.cpp +++ b/src/games/skyrimvr/src/skyrimvrunmanagedmods.cpp @@ -1,26 +1,26 @@ #include "skyrimvrunmanagedmods.h" -SkyrimVRUnmangedMods::SkyrimVRUnmangedMods(const GameGamebryo *game) - : GamebryoUnmangedMods(game) +SkyrimVRUnmangedMods::SkyrimVRUnmangedMods(const GameGamebryo* game) + : GamebryoUnmangedMods(game) {} -SkyrimVRUnmangedMods::~SkyrimVRUnmangedMods() -{} +SkyrimVRUnmangedMods::~SkyrimVRUnmangedMods() {} -QStringList SkyrimVRUnmangedMods::mods(bool onlyOfficial) const { +QStringList SkyrimVRUnmangedMods::mods(bool onlyOfficial) const +{ QStringList result; - QStringList pluginList = game()->primaryPlugins(); + QStringList pluginList = game()->primaryPlugins(); QStringList otherPlugins = game()->DLCPlugins(); otherPlugins.append(game()->CCPlugins()); for (QString plugin : otherPlugins) { pluginList.removeAll(plugin); } QDir dataDir(game()->dataDirectory()); - for (const QString &fileName : dataDir.entryList({ "*.esp", "*.esl", "*.esm" })) { + for (const QString& fileName : dataDir.entryList({"*.esp", "*.esl", "*.esm"})) { if (!pluginList.contains(fileName, Qt::CaseInsensitive)) { if (!onlyOfficial || pluginList.contains(fileName, Qt::CaseInsensitive)) { - result.append(fileName.chopped(4)); // trims the extension off + result.append(fileName.chopped(4)); // trims the extension off } } } diff --git a/src/games/skyrimvr/src/skyrimvrunmanagedmods.h b/src/games/skyrimvr/src/skyrimvrunmanagedmods.h index 67846b63..7b019f96 100644 --- a/src/games/skyrimvr/src/skyrimvrunmanagedmods.h +++ b/src/games/skyrimvr/src/skyrimvrunmanagedmods.h @@ -4,12 +4,13 @@ #include "gamebryounmanagedmods.h" #include -class SkyrimVRUnmangedMods : public GamebryoUnmangedMods { +class SkyrimVRUnmangedMods : public GamebryoUnmangedMods +{ public: - SkyrimVRUnmangedMods(const GameGamebryo *game); + SkyrimVRUnmangedMods(const GameGamebryo* game); ~SkyrimVRUnmangedMods(); virtual QStringList mods(bool onlyOfficial) const override; }; -#endif // _SKYRIMVRUNMANAGEDMODS_H +#endif // _SKYRIMVRUNMANAGEDMODS_H From a20a06de47955ffd3b2a765050303097f8dea774 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Mika=C3=ABl=20Capelle?= Date: Sun, 9 Jun 2024 13:41:31 +0200 Subject: [PATCH 1492/1544] [game_skyrimvr] Add .git-blame-ignore-revs. --- src/games/skyrimvr/.git-blame-ignore-revs | 1 + 1 file changed, 1 insertion(+) create mode 100644 src/games/skyrimvr/.git-blame-ignore-revs diff --git a/src/games/skyrimvr/.git-blame-ignore-revs b/src/games/skyrimvr/.git-blame-ignore-revs new file mode 100644 index 00000000..deaf3b1c --- /dev/null +++ b/src/games/skyrimvr/.git-blame-ignore-revs @@ -0,0 +1 @@ +74d288c4ae0f507767a165936f154d5477079e8e From 4b29c8e8a900c45c6e5e7a62a3c67a6dc9d9be77 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Mika=C3=ABl=20Capelle?= Date: Sun, 9 Jun 2024 13:41:31 +0200 Subject: [PATCH 1493/1544] [game_skyrimvr] Add github actions. --- src/games/skyrimvr/.github/workflows/build.yml | 16 ++++++++++++++++ src/games/skyrimvr/.github/workflows/linting.yml | 16 ++++++++++++++++ 2 files changed, 32 insertions(+) create mode 100644 src/games/skyrimvr/.github/workflows/build.yml create mode 100644 src/games/skyrimvr/.github/workflows/linting.yml diff --git a/src/games/skyrimvr/.github/workflows/build.yml b/src/games/skyrimvr/.github/workflows/build.yml new file mode 100644 index 00000000..e659afce --- /dev/null +++ b/src/games/skyrimvr/.github/workflows/build.yml @@ -0,0 +1,16 @@ +name: Build Installed Path Plugin + +on: + push: + branches: master + pull_request: + types: [opened, synchronize, reopened] + +jobs: + build: + runs-on: windows-2022 + steps: + - name: Build Installed Path Plugin + uses: ModOrganizer2/build-with-mob-action@master + with: + mo2-dependencies: cmake_common uibase game_gamebryo diff --git a/src/games/skyrimvr/.github/workflows/linting.yml b/src/games/skyrimvr/.github/workflows/linting.yml new file mode 100644 index 00000000..240c316a --- /dev/null +++ b/src/games/skyrimvr/.github/workflows/linting.yml @@ -0,0 +1,16 @@ +name: Lint Installed Path Plugin + +on: + push: + pull_request: + types: [opened, synchronize, reopened] + +jobs: + lint: + runs-on: ubuntu-latest + steps: + - uses: actions/checkout@v3 + - name: Check format + uses: ModOrganizer2/check-formatting-action@master + with: + check-path: "." From 996bbd0d861eb6b1a308f45078029d02e82917d6 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Mika=C3=ABl=20Capelle?= Date: Sun, 9 Jun 2024 13:56:25 +0200 Subject: [PATCH 1494/1544] [game_falloutnv] Switch to MO2 check-format action. (#33) --- src/games/falloutnv/.github/workflows/linting.yml | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/src/games/falloutnv/.github/workflows/linting.yml b/src/games/falloutnv/.github/workflows/linting.yml index 5b9b6d71..fe50d6b6 100644 --- a/src/games/falloutnv/.github/workflows/linting.yml +++ b/src/games/falloutnv/.github/workflows/linting.yml @@ -10,8 +10,7 @@ jobs: runs-on: ubuntu-latest steps: - uses: actions/checkout@v3 - - name: Run clang-format - uses: jidicula/clang-format-action@v4.11.0 + - name: Check format + uses: ModOrganizer2/check-formatting-action@master with: - clang-format-version: "15" check-path: "." From fe45b651fde318dd1064c1998d31856b20d8e1e1 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Mika=C3=ABl=20Capelle?= Date: Sun, 9 Jun 2024 13:56:29 +0200 Subject: [PATCH 1495/1544] Switch to MO2 check-format action. (#55) --- .github/workflows/linting.yml | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/.github/workflows/linting.yml b/.github/workflows/linting.yml index 78ee0417..1b8fe2a6 100644 --- a/.github/workflows/linting.yml +++ b/.github/workflows/linting.yml @@ -10,8 +10,7 @@ jobs: runs-on: ubuntu-latest steps: - uses: actions/checkout@v3 - - name: Run clang-format - uses: jidicula/clang-format-action@v4.11.0 + - name: Check format + uses: ModOrganizer2/check-formatting-action@master with: - clang-format-version: "15" check-path: "." From a0bccadd60e3e9108aac0c81366af799e6bb5ed2 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Mika=C3=ABl=20Capelle?= Date: Sun, 9 Jun 2024 13:56:33 +0200 Subject: [PATCH 1496/1544] [game_starfield] Switch to MO2 check-format action. (#21) --- src/games/starfield/.github/workflows/linting.yml | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/src/games/starfield/.github/workflows/linting.yml b/src/games/starfield/.github/workflows/linting.yml index 620b27f7..c8e3e703 100644 --- a/src/games/starfield/.github/workflows/linting.yml +++ b/src/games/starfield/.github/workflows/linting.yml @@ -10,8 +10,7 @@ jobs: runs-on: ubuntu-latest steps: - uses: actions/checkout@v3 - - name: Run clang-format - uses: jidicula/clang-format-action@v4.11.0 + - name: Check format + uses: ModOrganizer2/check-formatting-action@master with: - clang-format-version: "15" check-path: "." From 472a0a843440311f7625b1bcf28a079e563c8957 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Mika=C3=ABl=20Capelle?= Date: Sun, 9 Jun 2024 13:56:36 +0200 Subject: [PATCH 1497/1544] [game_nehrim] Switch to MO2 check-format action. (#8) --- src/games/nehrim/.github/workflows/linting.yml | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/src/games/nehrim/.github/workflows/linting.yml b/src/games/nehrim/.github/workflows/linting.yml index 006464fa..4e2bdb39 100644 --- a/src/games/nehrim/.github/workflows/linting.yml +++ b/src/games/nehrim/.github/workflows/linting.yml @@ -10,8 +10,7 @@ jobs: runs-on: ubuntu-latest steps: - uses: actions/checkout@v3 - - name: Run clang-format - uses: jidicula/clang-format-action@v4.11.0 + - name: Check format + uses: ModOrganizer2/check-formatting-action@master with: - clang-format-version: "15" check-path: "." From 16110ee5868efaa49a34359b87c26a327fb16b9a Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Mika=C3=ABl=20Capelle?= Date: Mon, 10 Jun 2024 19:23:35 +0200 Subject: [PATCH 1498/1544] [game_fallout76] Add missing return statement. --- src/games/fallout76/src/fallout76savegame.cpp | 2 ++ src/games/fallout76/src/game_fallout76_en.ts | 2 +- 2 files changed, 3 insertions(+), 1 deletion(-) diff --git a/src/games/fallout76/src/fallout76savegame.cpp b/src/games/fallout76/src/fallout76savegame.cpp index bdda883c..7d00a815 100644 --- a/src/games/fallout76/src/fallout76savegame.cpp +++ b/src/games/fallout76/src/fallout76savegame.cpp @@ -72,4 +72,6 @@ std::unique_ptr Fallout76SaveGame::fetchDataFields if (saveGameVersion >= 68) { file.readLightPlugins(); } + + return fields; } diff --git a/src/games/fallout76/src/game_fallout76_en.ts b/src/games/fallout76/src/game_fallout76_en.ts index 451031f7..16887105 100644 --- a/src/games/fallout76/src/game_fallout76_en.ts +++ b/src/games/fallout76/src/game_fallout76_en.ts @@ -4,7 +4,7 @@ GameFallout76 - + Adds support for the game Fallout 76. Splash by %1 From e9acd6a4cf1640cc7afcb03401da7a77dc09ffaf Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Mika=C3=ABl=20Capelle?= Date: Mon, 10 Jun 2024 19:35:14 +0200 Subject: [PATCH 1499/1544] [game_starfield] Do not enable new contents manually in StarfieldModDataContent. (#22) --- src/games/starfield/src/game_starfield_en.ts | 42 +++++++++---------- .../starfield/src/starfieldmoddatacontent.h | 4 +- 2 files changed, 22 insertions(+), 24 deletions(-) diff --git a/src/games/starfield/src/game_starfield_en.ts b/src/games/starfield/src/game_starfield_en.ts index 4326b8ed..38326b0d 100644 --- a/src/games/starfield/src/game_starfield_en.ts +++ b/src/games/starfield/src/game_starfield_en.ts @@ -4,92 +4,92 @@ GameStarfield - + Starfield Support Plugin - + Adds support for the game Starfield. - + Show a warning when ESP plugins are enabled in the load order. - + Show a warning when light plugins are enabled in the load order. - + Show a warning when overlay-flagged plugins ar enabled in the load order. - + Show a warning when plugins.txt management is invalid. - + Bypass check for Plugins.txt Enabler. This may be useful if you use the ASI loader. - + As of this release LOOT Starfield support is minimal to nonexistant. Toggle this to enable it anyway. - + You have active ESP plugins in Starfield - + You have active ESL plugins in Starfield - + You have active overlay plugins - + sTestFile entries are present - + Plugins.txt Enabler missing - + <p>ESP plugins are not ideal for Starfield. In addition to being unable to sort them alongside ESM or master-flagged plugins, certain record references are always kept loaded by the game. This consumes unnecessary resources and limits the game's ability to load what it needs.</p><p>Ideally, plugins should be saved as ESM files upon release. It can also be released as an ESL plugin, however there are additional concerns with the way light plugins are currently handled and should only be used when absolutely certain about what you're doing.</p><p>Notably, xEdit does not currently support saving ESP files.</p><h4>Current ESPs:</h4><p>%1</p> - + <p>Light plugins work differently in Starfield. They use a different base form ID compared with standard plugin files.</p><p>What this means is that you can't just change a standard plugin to a light plugin at will, it can and will break any dependent plugin. If you do so, be absolutely certain no other plugins use that plugin as a master.</p><p>Notably, xEdit does not currently support saving or loading ESL files under these conditions.<p><h4>Current ESLs:</h4><p>%1</p> - + <p>Overlay-flagged plugins are not currently recommended. In theory, they should allow you to update existing records without utilizing additional load order slots. Unfortunately, it appears that the game still allocates the slots as if these were standard plugins. Therefore, at the moment there is no real use for this plugin flag.</p><p>Notably, xEdit does not currently support saving or loading overlay-flagged files under these conditions.</p><h4>Current Overlays:</h4><p>%1</p> - + <p>You have plugin managment enabled but you still have sTestFile settings in your StarfieldCustom.ini. These must be removed or the game will not read the plugins.txt file. Management is still disabled.</p> - + <p>You have plugin management turned on but do not have the Plugins.txt Enabler SFSE plugin installed. Plugin file management for Starfield will not work without this SFSE plugin.</p> @@ -97,17 +97,17 @@ StarfieldModDataContent - + Materials - + Geometries - + Video diff --git a/src/games/starfield/src/starfieldmoddatacontent.h b/src/games/starfield/src/starfieldmoddatacontent.h index 5d134569..d4b80144 100644 --- a/src/games/starfield/src/starfieldmoddatacontent.h +++ b/src/games/starfield/src/starfieldmoddatacontent.h @@ -18,9 +18,7 @@ public: StarfieldModDataContent(MOBase::IGameFeatures const* gameFeatures) : GamebryoModDataContent(gameFeatures) { - m_Enabled[CONTENT_SKYPROC] = false; - m_Enabled[CONTENT_MATERIAL] = true; - m_Enabled[CONTENT_GEOMETRIES] = true; + m_Enabled[CONTENT_SKYPROC] = false; } std::vector getAllContents() const override From 1a8838ead0d2919101ac63b0ff85a31bd978a597 Mon Sep 17 00:00:00 2001 From: Jeremy Rimpo Date: Thu, 13 Jun 2024 10:50:11 -0500 Subject: [PATCH 1500/1544] Starfield Creation Update (#56) * Convert overlay/override flags to medium flags * Updates for new starfield save data --- src/gamebryo/game_gamebryo_en.ts | 16 ++-- src/gamebryo/gamebryogameplugins.cpp | 2 +- src/gamebryo/gamebryogameplugins.h | 2 +- src/gamebryo/gamebryosavegame.cpp | 83 ++++++++++++++------- src/gamebryo/gamebryosavegame.h | 23 +++++- src/gamebryo/gamebryosavegameinfowidget.cpp | 39 ++++++++++ 6 files changed, 127 insertions(+), 38 deletions(-) diff --git a/src/gamebryo/game_gamebryo_en.ts b/src/gamebryo/game_gamebryo_en.ts index 2dcc143b..f924131c 100644 --- a/src/gamebryo/game_gamebryo_en.ts +++ b/src/gamebryo/game_gamebryo_en.ts @@ -119,11 +119,17 @@ + None + Missing ESHs + + + + Missing ESLs @@ -136,27 +142,27 @@ - + %1, #%2, Level %3, %4 - + failed to open %1 - + wrong file format - expected %1 got '%2' for %3 - + failed to query registry path (preflight): %1 - + failed to query registry path (read): %1 diff --git a/src/gamebryo/gamebryogameplugins.cpp b/src/gamebryo/gamebryogameplugins.cpp index 8b4cd053..fc28981c 100644 --- a/src/gamebryo/gamebryogameplugins.cpp +++ b/src/gamebryo/gamebryogameplugins.cpp @@ -252,7 +252,7 @@ bool GamebryoGamePlugins::lightPluginsAreSupported() return false; } -bool GamebryoGamePlugins::overridePluginsAreSupported() +bool GamebryoGamePlugins::mediumPluginsAreSupported() { return false; } diff --git a/src/gamebryo/gamebryogameplugins.h b/src/gamebryo/gamebryogameplugins.h index 43f12a96..c2a6140e 100644 --- a/src/gamebryo/gamebryogameplugins.h +++ b/src/gamebryo/gamebryogameplugins.h @@ -15,7 +15,7 @@ public: virtual void readPluginLists(MOBase::IPluginList* pluginList) override; virtual QStringList getLoadOrder() override; virtual bool lightPluginsAreSupported() override; - virtual bool overridePluginsAreSupported() override; + virtual bool mediumPluginsAreSupported() override; protected: MOBase::IOrganizer* organizer() const { return m_Organizer; } diff --git a/src/gamebryo/gamebryosavegame.cpp b/src/gamebryo/gamebryosavegame.cpp index 61750f44..978d3751 100644 --- a/src/gamebryo/gamebryosavegame.cpp +++ b/src/gamebryo/gamebryosavegame.cpp @@ -23,9 +23,10 @@ #define CHUNK 16384 GamebryoSaveGame::GamebryoSaveGame(QString const& file, GameGamebryo const* game, - bool const lightEnabled) + bool const lightEnabled, bool const mediumEnabled) : m_FileName(file), m_CreationTime(QFileInfo(file).lastModified()), m_Game(game), - m_LightEnabled(lightEnabled), m_DataFields([this]() { + m_MediumEnabled(mediumEnabled), m_LightEnabled(lightEnabled), + m_DataFields([this]() { return fetchDataFields(); }) {} @@ -508,60 +509,86 @@ float_t GamebryoSaveGame::FileWrapper::readFloat(int bytesToIgnore) } } -QStringList GamebryoSaveGame::FileWrapper::readPlugins(int bytesToIgnore) +QStringList GamebryoSaveGame::FileWrapper::readPlugins(int bytesToIgnore, + bool extraData, + const QStringList& corePlugins) { - QStringList plugins; if (m_CompressionType == 0) { if (bytesToIgnore > 0) // Just to make certain skip(bytesToIgnore); uint8_t count; read(count); - uint16_t finalCount = count; - plugins.reserve(finalCount); - for (std::size_t i = 0; i < finalCount; ++i) { - QString name; - read(name); - plugins.push_back(name); - } + return readPluginData(count, extraData, corePlugins); } else if (m_CompressionType == 1 || m_CompressionType == 2) { skipQDataStream(*m_Data, bytesToIgnore); uint8_t count; readQDataStream(*m_Data, count); - uint16_t finalCount = count; - plugins.reserve(finalCount); - for (std::size_t i = 0; i < finalCount; ++i) { - QString name; - read(name); - plugins.push_back(name); - } + return readPluginData(count, extraData, corePlugins); } - return plugins; + return {}; } -QStringList GamebryoSaveGame::FileWrapper::readLightPlugins(int bytesToIgnore) +QStringList +GamebryoSaveGame::FileWrapper::readLightPlugins(int bytesToIgnore, bool extraData, + const QStringList& corePlugins) { - QStringList plugins; if (m_CompressionType == 0) { if (bytesToIgnore > 0) // Just to make certain skip(bytesToIgnore); uint16_t count; read(count); - plugins.reserve(count); + return readPluginData(count, extraData, corePlugins); + } else if (m_CompressionType == 1 || m_CompressionType == 2) { + skipQDataStream(*m_Data, bytesToIgnore); + uint16_t count; + readQDataStream(*m_Data, count); + return readPluginData(count, extraData, corePlugins); + } + return {}; +} + +QStringList +GamebryoSaveGame::FileWrapper::readMediumPlugins(int bytesToIgnore, bool extraData, + const QStringList& corePlugins) +{ + if (m_CompressionType != 1) { + return {}; + } else { + skipQDataStream(*m_Data, bytesToIgnore); + uint32_t count; + readQDataStream(*m_Data, count); + return readPluginData(count, extraData, corePlugins); + } +} + +QStringList GamebryoSaveGame::FileWrapper::readPluginData(uint32_t count, + bool extraData, + const QStringList corePlugins) +{ + QStringList plugins; + plugins.reserve(count); + if (m_CompressionType == 0) { for (std::size_t i = 0; i < count; ++i) { QString name; read(name); plugins.push_back(name); } - } else if (m_CompressionType == 1 || m_CompressionType == 2) { - skipQDataStream(*m_Data, bytesToIgnore); - - uint16_t count; - readQDataStream(*m_Data, count); - plugins.reserve(count); + } else { for (std::size_t i = 0; i < count; ++i) { QString name; read(name); plugins.push_back(name); + if (extraData && !corePlugins.contains(name)) { + QString creationName; + QString creationId; + uint16_t flagsSize; + uint8_t isCreation; + read(creationName); + read(creationId); + readQDataStream(*m_Data, flagsSize); + skipQDataStream(*m_Data, flagsSize); + readQDataStream(*m_Data, isCreation); + } } } return plugins; diff --git a/src/gamebryo/gamebryosavegame.h b/src/gamebryo/gamebryosavegame.h index 07d34621..114a8e9b 100644 --- a/src/gamebryo/gamebryosavegame.h +++ b/src/gamebryo/gamebryosavegame.h @@ -26,7 +26,7 @@ class GamebryoSaveGame : public MOBase::ISaveGame { public: GamebryoSaveGame(QString const& file, GameGamebryo const* game, - bool const lightEnabled = false); + bool const lightEnabled = false, bool const mediumEnabled = false); virtual ~GamebryoSaveGame(); @@ -47,12 +47,18 @@ public: virtual unsigned long getSaveNumber() const { return m_SaveNumber; } QStringList const& getPlugins() const { return m_DataFields.value()->Plugins; } + QStringList const& getMediumPlugins() const + { + return m_DataFields.value()->MediumPlugins; + } QStringList const& getLightPlugins() const { return m_DataFields.value()->LightPlugins; } QImage const& getScreenshot() const { return m_DataFields.value()->Screenshot; } + bool isMediumEnabled() const { return m_MediumEnabled; } + bool isLightEnabled() const { return m_LightEnabled; } enum class StringType @@ -161,10 +167,16 @@ protected: float_t readFloat(int bytesToIgnore = 0); /* Read the plugin list */ - QStringList readPlugins(int bytesToIgnore = 0); + QStringList readPlugins(int bytesToIgnore = 0, bool extraData = false, + const QStringList& corePlugins = {}); /* Read the light plugin list */ - QStringList readLightPlugins(int bytesToIgnore = 0); + QStringList readLightPlugins(int bytesToIgnore = 0, bool extraData = false, + const QStringList& corePlugins = {}); + + /* Read the medium plugin list */ + QStringList readMediumPlugins(int bytesToIgnore = 0, bool extraData = false, + const QStringList& corePlugins = {}); void close(); @@ -185,11 +197,15 @@ protected: void readQDataStream(QDataStream& data, void* buff, std::size_t length); void skipQDataStream(QDataStream& data, std::size_t length); + + QStringList readPluginData(uint32_t count, bool extraData, + const QStringList corePlugins); }; void setCreationTime(_SYSTEMTIME const& time); GameGamebryo const* m_Game; + bool m_MediumEnabled; bool m_LightEnabled; QString m_FileName; @@ -208,6 +224,7 @@ protected: { QStringList Plugins; QStringList LightPlugins; + QStringList MediumPlugins; QImage Screenshot; // We need this constructor. diff --git a/src/gamebryo/gamebryosavegameinfowidget.cpp b/src/gamebryo/gamebryosavegameinfowidget.cpp index 853f2c2b..8c95dad4 100644 --- a/src/gamebryo/gamebryosavegameinfowidget.cpp +++ b/src/gamebryo/gamebryosavegameinfowidget.cpp @@ -118,6 +118,45 @@ void GamebryoSaveGameInfoWidget::setSave(MOBase::ISaveGame const& save) dotDotLabel->setFont(contentFont); layout->addWidget(dotDotLabel); } + if (gamebryoSave.isMediumEnabled()) { + QLabel* headerEsh = new QLabel(tr("Missing ESHs")); + QFont headerEshFont = headerEsh->font(); + QFont contentEshFont = headerEshFont; + headerEshFont.setItalic(true); + contentEshFont.setBold(true); + contentEshFont.setPointSize(7); + headerEsh->setFont(headerEshFont); + layout->addWidget(headerEsh); + int countEsh = 0; + for (QString const& pluginName : gamebryoSave.getMediumPlugins()) { + if (pluginList->state(pluginName) == MOBase::IPluginList::STATE_ACTIVE) { + continue; + } + + ++countEsh; + + if (countEsh > 7) { + break; + } + + QLabel* pluginLabel = new QLabel(pluginName); + pluginLabel->setIndent(10); + pluginLabel->setFont(contentFont); + layout->addWidget(pluginLabel); + } + if (countEsh > 7) { + QLabel* dotDotLabel = new QLabel("..."); + dotDotLabel->setIndent(10); + dotDotLabel->setFont(contentFont); + layout->addWidget(dotDotLabel); + } + if (countEsh == 0) { + QLabel* dotDotLabel = new QLabel(tr("None")); + dotDotLabel->setIndent(10); + dotDotLabel->setFont(contentFont); + layout->addWidget(dotDotLabel); + } + } if (gamebryoSave.isLightEnabled()) { QLabel* headerEsl = new QLabel(tr("Missing ESLs")); QFont headerEslFont = headerEsl->font(); From 700d886e751d0834994772f52d3afbb16b380e36 Mon Sep 17 00:00:00 2001 From: Jeremy Rimpo Date: Thu, 13 Jun 2024 10:50:38 -0500 Subject: [PATCH 1501/1544] [game_starfield] Starfield Creation Update: Convert overlay/override flags to medium flags (#23) * Various updates for the Creation update - Remove light warnings and plugins txt enabler checks - Remove overlay code for new 'medium' plugin type * Updates for new starfield save data * Add version check to parse medium plugins * Add creation kit to default executables * Move BlueprintShips-Starfield.esm to primary plugins --- src/games/starfield/src/gamestarfield.cpp | 142 ++---------------- src/games/starfield/src/gamestarfield.h | 12 +- .../starfield/src/starfieldgameplugins.cpp | 2 +- .../starfield/src/starfieldgameplugins.h | 2 +- src/games/starfield/src/starfieldsavegame.cpp | 39 ++--- src/games/starfield/src/starfieldsavegame.h | 5 +- 6 files changed, 38 insertions(+), 164 deletions(-) diff --git a/src/games/starfield/src/gamestarfield.cpp b/src/games/starfield/src/gamestarfield.cpp index b521587d..77781ca8 100644 --- a/src/games/starfield/src/gamestarfield.cpp +++ b/src/games/starfield/src/gamestarfield.cpp @@ -97,6 +97,8 @@ QList GameStarfield::executables() const ->gameFeature() ->loaderName())) << ExecutableInfo("Starfield", findInGameFolder(binaryName())) + << ExecutableInfo("Creation Kit", findInGameFolder("CreationKit.exe")) + .withSteamAppId("2722710") << ExecutableInfo("LOOT", QFileInfo(getLootPath())) .withArgument("--game=\"Starfield\""); } @@ -138,21 +140,9 @@ QList GameStarfield::settings() const "enable_esp_warning", tr("Show a warning when ESP plugins are enabled in the load order."), true) - << PluginSetting( - "enable_esl_warning", - tr("Show a warning when light plugins are enabled in the load order."), - true) - << PluginSetting("enable_overlay_warning", - tr("Show a warning when overlay-flagged plugins ar enabled " - "in the load order."), - true) << PluginSetting("enable_management_warnings", tr("Show a warning when plugins.txt management is invalid."), true) - << PluginSetting("bypass_plugins_enabler_check", - tr("Bypass check for Plugins.txt Enabler. This may be useful " - "if you use the ASI loader."), - false) << PluginSetting("enable_loot_sorting", tr("As of this release LOOT Starfield support is minimal to " "nonexistant. Toggle this to enable it anyway."), @@ -229,8 +219,10 @@ QStringList GameStarfield::testFilePlugins() const QStringList GameStarfield::primaryPlugins() const { - QStringList plugins = {"Starfield.esm", "Constellation.esm", "OldMars.esm", - "SFBGS006.esm", "SFBGS007.esm", "SFBGS008.esm"}; + QStringList plugins = {"Starfield.esm", "Constellation.esm", + "OldMars.esm", "BlueprintShips-Starfield.esm", + "SFBGS003.esm", "SFBGS006.esm", + "SFBGS007.esm", "SFBGS008.esm"}; auto testPlugins = testFilePlugins(); if (loadOrderMechanism() == LoadOrderMechanism::None) { @@ -245,7 +237,7 @@ QStringList GameStarfield::primaryPlugins() const QStringList GameStarfield::enabledPlugins() const { - return {"BlueprintShips-Starfield.esm"}; + return {}; } QStringList GameStarfield::gameVariants() const @@ -317,9 +309,7 @@ IPluginGame::SortMechanism GameStarfield::sortMechanism() const IPluginGame::LoadOrderMechanism GameStarfield::loadOrderMechanism() const { - if (!testFilePresent() && - (pluginsTxtEnablerPresent() || - m_Organizer->pluginSetting(name(), "bypass_plugins_enabler_check").toBool())) + if (!testFilePresent()) return IPluginGame::LoadOrderMechanism::PluginsTxt; return IPluginGame::LoadOrderMechanism::None; } @@ -342,17 +332,9 @@ std::vector GameStarfield::activeProblems() const if (m_Organizer->pluginSetting(name(), "enable_esp_warning").toBool() && activeESP()) result.push_back(PROBLEM_ESP); - if (m_Organizer->pluginSetting(name(), "enable_esl_warning").toBool() && - activeESL()) - result.push_back(PROBLEM_ESL); - if (m_Organizer->pluginSetting(name(), "enable_overlay_warning").toBool() && - activeOverlay()) - result.push_back(PROBLEM_OVERLAY); if (m_Organizer->pluginSetting(name(), "enable_management_warnings").toBool()) { if (testFilePresent()) result.push_back(PROBLEM_TEST_FILE); - else if (!pluginsTxtEnablerPresent()) - result.push_back(PROBLEM_PLUGINS_TXT); } } return result; @@ -379,59 +361,6 @@ bool GameStarfield::activeESP() const return false; } -bool GameStarfield::activeESL() const -{ - m_Active_ESLs.clear(); - std::set enabledPlugins; - - QStringList esps = m_Organizer->findFiles("", [](const QString& fileName) -> bool { - return fileName.endsWith(".esp", FileNameComparator::CaseSensitivity) || - fileName.endsWith(".esm", FileNameComparator::CaseSensitivity) || - fileName.endsWith(".esl", FileNameComparator::CaseSensitivity); - }); - - for (const QString& esp : esps) { - QString baseName = QFileInfo(esp).fileName(); - if (primaryPlugins().contains(baseName, Qt::CaseInsensitive)) - continue; - if (m_Organizer->pluginList()->state(baseName) == IPluginList::STATE_ACTIVE && - !m_Organizer->pluginList()->hasNoRecords(baseName)) - if (m_Organizer->pluginList()->hasLightExtension(baseName) || - m_Organizer->pluginList()->isLightFlagged(baseName)) - m_Active_ESLs.insert(baseName); - } - - if (!m_Active_ESLs.empty()) - return true; - return false; -} - -bool GameStarfield::activeOverlay() const -{ - m_Active_Overlays.clear(); - std::set enabledPlugins; - - QStringList esps = m_Organizer->findFiles("", [](const QString& fileName) -> bool { - return fileName.endsWith(".esp", FileNameComparator::CaseSensitivity) || - fileName.endsWith(".esm", FileNameComparator::CaseSensitivity) || - fileName.endsWith(".esl", FileNameComparator::CaseSensitivity); - }); - - for (const QString& esp : esps) { - QString baseName = QFileInfo(esp).fileName(); - if (primaryPlugins().contains(baseName, Qt::CaseInsensitive)) - continue; - if (m_Organizer->pluginList()->state(baseName) == IPluginList::STATE_ACTIVE) { - if (m_Organizer->pluginList()->isOverlayFlagged(baseName)) - m_Active_Overlays.insert(baseName); - } - } - - if (!m_Active_Overlays.empty()) - return true; - return false; -} - bool GameStarfield::testFilePresent() const { if (!testFilePlugins().isEmpty()) @@ -439,28 +368,13 @@ bool GameStarfield::testFilePresent() const return false; } -bool GameStarfield::pluginsTxtEnablerPresent() const -{ - auto files = m_Organizer->findFiles("sfse\\plugins", {"sfpluginstxtenabler.dll"}); - files += m_Organizer->findFiles("", {"sfpluginstxtenabler.asi"}); - if (files.isEmpty()) - return false; - return true; -} - QString GameStarfield::shortDescription(unsigned int key) const { switch (key) { case PROBLEM_ESP: return tr("You have active ESP plugins in Starfield"); - case PROBLEM_ESL: - return tr("You have active ESL plugins in Starfield"); - case PROBLEM_OVERLAY: - return tr("You have active overlay plugins"); case PROBLEM_TEST_FILE: return tr("sTestFile entries are present"); - case PROBLEM_PLUGINS_TXT: - return tr("Plugins.txt Enabler missing"); } return ""; } @@ -483,56 +397,18 @@ QString GameStarfield::fullDescription(unsigned int key) const "

Current ESPs:

%1

") .arg(espInfo); } - case PROBLEM_ESL: { - QString eslInfo = SetJoin(m_Active_ESLs, ", "); - return tr("

Light plugins work differently in Starfield. They use a different " - "base form ID compared with standard plugin files.

" - "

What this means is that you can't just change a standard plugin to a " - "light plugin at will, it can and will break any dependent plugin. If " - "you do so, be absolutely certain no other plugins use that plugin as a " - "master.

" - "

Notably, xEdit does not currently support saving or loading ESL " - "files under these conditions.

" - "

Current ESLs:

%1

") - .arg(eslInfo); - } - case PROBLEM_OVERLAY: { - QString overlayInfo = SetJoin(m_Active_Overlays, ", "); - return tr("

Overlay-flagged plugins are not currently recommended. In theory, " - "they should allow you to update existing records without utilizing " - "additional load order slots. Unfortunately, it appears that the game " - "still allocates the slots as if these were standard plugins. Therefore, " - "at the moment there is no real use for this plugin flag.

" - "

Notably, xEdit does not currently support saving or loading " - "overlay-flagged files under these conditions.

" - "

Current Overlays:

%1

") - .arg(overlayInfo); - } case PROBLEM_TEST_FILE: { return tr("

You have plugin managment enabled but you still have sTestFile " "settings in your StarfieldCustom.ini. These must be removed or the game " "will not read the plugins.txt file. Management is still disabled.

"); } - case PROBLEM_PLUGINS_TXT: { - return tr("

You have plugin management turned on but do not have the Plugins.txt " - "Enabler SFSE plugin installed. Plugin file management for Starfield " - "will not work without this SFSE plugin.

"); - } } return ""; } bool GameStarfield::hasGuidedFix(unsigned int key) const { - if (key == PROBLEM_PLUGINS_TXT) - return true; return false; } -void GameStarfield::startGuidedFix(unsigned int key) const -{ - if (key == PROBLEM_PLUGINS_TXT) { - QDesktopServices::openUrl( - QUrl("https://www.nexusmods.com/starfield/mods/4157?tab=files")); - } -} +void GameStarfield::startGuidedFix(unsigned int key) const {} diff --git a/src/games/starfield/src/gamestarfield.h b/src/games/starfield/src/gamestarfield.h index 7fde2e83..42e27487 100644 --- a/src/games/starfield/src/gamestarfield.h +++ b/src/games/starfield/src/gamestarfield.h @@ -70,21 +70,13 @@ protected: private: bool activeESP() const; - bool activeESL() const; - bool activeOverlay() const; bool testFilePresent() const; - bool pluginsTxtEnablerPresent() const; private: - static const unsigned int PROBLEM_ESP = 1; - static const unsigned int PROBLEM_ESL = 2; - static const unsigned int PROBLEM_OVERLAY = 3; - static const unsigned int PROBLEM_TEST_FILE = 4; - static const unsigned int PROBLEM_PLUGINS_TXT = 5; + static const unsigned int PROBLEM_ESP = 1; + static const unsigned int PROBLEM_TEST_FILE = 2; mutable std::set m_Active_ESPs; - mutable std::set m_Active_ESLs; - mutable std::set m_Active_Overlays; }; #endif // GAMEStarfield_H diff --git a/src/games/starfield/src/starfieldgameplugins.cpp b/src/games/starfield/src/starfieldgameplugins.cpp index 995aa58f..3653aca3 100644 --- a/src/games/starfield/src/starfieldgameplugins.cpp +++ b/src/games/starfield/src/starfieldgameplugins.cpp @@ -6,7 +6,7 @@ StarfieldGamePlugins::StarfieldGamePlugins(MOBase::IOrganizer* organizer) : CreationGamePlugins(organizer) {} -bool StarfieldGamePlugins::overridePluginsAreSupported() +bool StarfieldGamePlugins::mediumPluginsAreSupported() { return true; } diff --git a/src/games/starfield/src/starfieldgameplugins.h b/src/games/starfield/src/starfieldgameplugins.h index 652ef70e..c654306e 100644 --- a/src/games/starfield/src/starfieldgameplugins.h +++ b/src/games/starfield/src/starfieldgameplugins.h @@ -13,7 +13,7 @@ public: StarfieldGamePlugins(MOBase::IOrganizer* organizer); protected: - virtual bool overridePluginsAreSupported() override; + virtual bool mediumPluginsAreSupported() override; virtual void writePluginList(const MOBase::IPluginList* pluginList, const QString& filePath) override; virtual QStringList readPluginList(MOBase::IPluginList* pluginList) override; diff --git a/src/games/starfield/src/starfieldsavegame.cpp b/src/games/starfield/src/starfieldsavegame.cpp index 1b75c658..01d08229 100644 --- a/src/games/starfield/src/starfieldsavegame.cpp +++ b/src/games/starfield/src/starfieldsavegame.cpp @@ -5,14 +5,15 @@ #include "gamestarfield.h" StarfieldSaveGame::StarfieldSaveGame(QString const& fileName, GameStarfield const* game) - : GamebryoSaveGame(fileName, game, true) + : GamebryoSaveGame(fileName, game, true, true) { FileWrapper file(getFilepath(), "BCPS"); getData(file); FILETIME creationTime; - fetchInformationFields(file, m_SaveNumber, m_PCName, m_PCLevel, m_PCLocation, - creationTime); + unsigned char saveVersion; + fetchInformationFields(file, m_SaveNumber, saveVersion, m_PCName, m_PCLevel, + m_PCLocation, creationTime); file.closeCompressedData(); file.close(); @@ -51,18 +52,18 @@ void StarfieldSaveGame::getData(FileWrapper& file) const } void StarfieldSaveGame::fetchInformationFields( - FileWrapper& file, unsigned long& saveNumber, QString& playerName, - unsigned short& playerLevel, QString& playerLocation, FILETIME& creationTime) const + FileWrapper& file, unsigned long& saveNumber, unsigned char& saveVersion, + QString& playerName, unsigned short& playerLevel, QString& playerLocation, + FILETIME& creationTime) const { char fileID[12]; // SFS_SAVEGAME unsigned int headerSize; unsigned int version; - unsigned char unknown; // file.read(fileID, 12); - headerSize = file.readInt(12); - version = file.readInt(); - unknown = file.readChar(); - saveNumber = file.readInt(); + headerSize = file.readInt(12); + saveNumber = file.readInt(); + saveVersion = file.readChar(); + version = file.readInt(); file.read(playerName); unsigned int temp; @@ -91,6 +92,7 @@ std::unique_ptr StarfieldSaveGame::fetchDataFields getData(file); FILETIME creationTime; + unsigned char saveVersion; { QString dummyName, dummyLocation; @@ -98,22 +100,25 @@ std::unique_ptr StarfieldSaveGame::fetchDataFields unsigned long dummySaveNumber; FILETIME dummyTime; - fetchInformationFields(file, dummySaveNumber, dummyName, dummyLevel, dummyLocation, - dummyTime); + fetchInformationFields(file, dummySaveNumber, saveVersion, dummyName, dummyLevel, + dummyLocation, dummyTime); } + bool extraInfo = saveVersion >= 122; + QStringList gamePlugins = m_Game->primaryPlugins() + m_Game->enabledPlugins(); + QString ignore; std::unique_ptr fields = std::make_unique(); - // fields->Screenshot = file.readImage(384, true); - - uint8_t saveGameVersion = file.readChar(12); + file.readChar(12); file.read(ignore); // game version file.read(ignore); // game version again? file.readInt(); // plugin info size - fields->Plugins = file.readPlugins(); - fields->LightPlugins = file.readLightPlugins(); + fields->Plugins = file.readPlugins(0, extraInfo, gamePlugins); + fields->LightPlugins = file.readLightPlugins(0, extraInfo, gamePlugins); + if (saveVersion >= 122) + fields->MediumPlugins = file.readMediumPlugins(0, extraInfo, gamePlugins); file.closeCompressedData(); file.close(); diff --git a/src/games/starfield/src/starfieldsavegame.h b/src/games/starfield/src/starfieldsavegame.h index d8189bfe..3be0b276 100644 --- a/src/games/starfield/src/starfieldsavegame.h +++ b/src/games/starfield/src/starfieldsavegame.h @@ -18,8 +18,9 @@ protected: void getData(FileWrapper& file) const; void fetchInformationFields(FileWrapper& file, unsigned long& saveNumber, - QString& playerName, unsigned short& playerLevel, - QString& playerLocation, FILETIME& creationTime) const; + unsigned char& saveVersion, QString& playerName, + unsigned short& playerLevel, QString& playerLocation, + FILETIME& creationTime) const; std::unique_ptr fetchDataFields() const override; }; From 05c38350dd2b8b2d1cc22f7049ce58e7946e26bd Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Mika=C3=ABl=20Capelle?= Date: Sat, 22 Jun 2024 08:28:20 +0200 Subject: [PATCH 1502/1544] [game_morrowind] Fix save games for latest Qt. (#33) --- src/games/morrowind/src/morrowindsavegame.cpp | 31 ++++++++++++------- 1 file changed, 19 insertions(+), 12 deletions(-) diff --git a/src/games/morrowind/src/morrowindsavegame.cpp b/src/games/morrowind/src/morrowindsavegame.cpp index 97cecdc8..1b020281 100644 --- a/src/games/morrowind/src/morrowindsavegame.cpp +++ b/src/games/morrowind/src/morrowindsavegame.cpp @@ -42,13 +42,17 @@ void MorrowindSaveGame::fetchInformationFields(FileWrapper& file, QString& saveN file.skip(); // header version file.skip(); // following data chunk size? seems to be 9 groupings of 32 // bytes - file.skip(32); // Author empty for save files - std::vector saveNameBuffer(256); // 31 char save name with a null terminator - file.read(saveNameBuffer.data(), 256); - saveName = QString::fromLatin1(saveNameBuffer.data(), 256) - .trimmed(); // The defined save name. This is technically the - // description, but is likely only 31+\0 chars max. - file.skip(); // NumRecords (for the entire save) + file.skip(32); // Author empty for save files + + // The defined save name. This is technically the description, but is likely only + // 31+\0 chars max. + { + std::vector saveNameBuffer(256); // 31 char save name with a null terminator + file.read(saveNameBuffer.data(), 256); + saveName = QString::fromLatin1(saveNameBuffer.data(), -1).trimmed(); + } + + file.skip(); // NumRecords (for the entire save) std::vector buffer(255); file.read(buffer.data(), 4); // Parse the MAST/DATA records @@ -58,9 +62,10 @@ void MorrowindSaveGame::fetchInformationFields(FileWrapper& file, QString& saveN file.read(buffer.data(), len); // Name of master QString name = QString::fromLatin1(buffer.data(), len - 1); file.skip(4); // DATA record - file.read(len); // Length - file.skip( - len); // Typically size 8 - contains length of master data for version checking + + // Typically size 8 - contains length of master data for version checking + file.read(len); // Length + file.skip(len); file.read(buffer.data(), 4); // Get next record type plugins.push_back(name); @@ -76,13 +81,15 @@ void MorrowindSaveGame::fetchInformationFields(FileWrapper& file, QString& saveN file.skip(); // max stam? // file.skip(2); // unknown values + std::fill(buffer.begin(), buffer.end(), '\0'); file.read(buffer.data(), 64); - playerLocation = QString::fromLatin1(buffer.data(), 64).trimmed(); + playerLocation = QString::fromLatin1(buffer.data(), -1).trimmed(); file.read(gameDays); + std::fill(buffer.begin(), buffer.end(), '\0'); file.read(buffer.data(), 32); - playerName = QString::fromLatin1(buffer.data(), 32).trimmed(); + playerName = QString::fromLatin1(buffer.data(), -1).trimmed(); // End of GMDT } From 2def0c79528c0ba21690ba8d92da29da7d54768a Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Mika=C3=ABl=20Capelle?= Date: Sat, 22 Jun 2024 08:28:54 +0200 Subject: [PATCH 1503/1544] Use game plugin to obtain My Games path instead of passing it construction (#57) * Use game plugin to obtain My Games path instead of passing it during construction. * Add function to access the game directory from the data archive feature. * Add way to change the local saves dummy for local saves. --- src/gamebryo/gamebryodataarchives.cpp | 20 +++++++++++--- src/gamebryo/gamebryodataarchives.h | 13 ++++++--- src/gamebryo/gamebryolocalsavegames.cpp | 36 ++++++++++++++++++------- src/gamebryo/gamebryolocalsavegames.h | 18 ++++++++++--- src/gamebryo/gamegamebryo.cpp | 2 +- src/gamebryo/gamegamebryo.h | 4 ++- 6 files changed, 71 insertions(+), 22 deletions(-) diff --git a/src/gamebryo/gamebryodataarchives.cpp b/src/gamebryo/gamebryodataarchives.cpp index c24242dd..3dcba8a7 100644 --- a/src/gamebryo/gamebryodataarchives.cpp +++ b/src/gamebryo/gamebryodataarchives.cpp @@ -1,11 +1,23 @@ #include "gamebryodataarchives.h" -#include "registry.h" + #include + +#include #include -GamebryoDataArchives::GamebryoDataArchives(const QDir& myGamesDir) - : m_LocalGameDir(myGamesDir.absolutePath()) -{} +#include "gamegamebryo.h" + +GamebryoDataArchives::GamebryoDataArchives(const GameGamebryo* game) : m_Game{game} {} + +QDir GamebryoDataArchives::gameDirectory() const +{ + return QDir(m_Game->gameDirectory()).absolutePath(); +} + +QDir GamebryoDataArchives::localGameDirectory() const +{ + return QDir(m_Game->myGamesPath()).absolutePath(); +} QStringList GamebryoDataArchives::getArchivesFromKey(const QString& iniFile, const QString& key, diff --git a/src/gamebryo/gamebryodataarchives.h b/src/gamebryo/gamebryodataarchives.h index e119bc4f..13f4130e 100644 --- a/src/gamebryo/gamebryodataarchives.h +++ b/src/gamebryo/gamebryodataarchives.h @@ -1,14 +1,17 @@ #ifndef GAMEBRYODATAARCHIVES_H #define GAMEBRYODATAARCHIVES_H -#include "dataarchives.h" #include +#include "dataarchives.h" + +class GameGamebryo; + class GamebryoDataArchives : public MOBase::DataArchives { public: - GamebryoDataArchives(const QDir& myGamesDir); + GamebryoDataArchives(const GameGamebryo* game); virtual void addArchive(MOBase::IProfile* profile, int index, const QString& archiveName) override; @@ -16,13 +19,17 @@ public: const QString& archiveName) override; protected: - QDir m_LocalGameDir; + QDir gameDirectory() const; + QDir localGameDirectory() const; + QStringList getArchivesFromKey(const QString& iniFile, const QString& key, int size = 256) const; void setArchivesToKey(const QString& iniFile, const QString& key, const QString& value); private: + const GameGamebryo* m_Game; + virtual void writeArchiveList(MOBase::IProfile* profile, const QStringList& before) = 0; }; diff --git a/src/gamebryo/gamebryolocalsavegames.cpp b/src/gamebryo/gamebryolocalsavegames.cpp index 142cbf4f..cf78ebaf 100644 --- a/src/gamebryo/gamebryolocalsavegames.cpp +++ b/src/gamebryo/gamebryolocalsavegames.cpp @@ -24,25 +24,41 @@ Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA #include #include -static const QString LocalSavesDummy = "__MO_Saves\\"; +#include "gamegamebryo.h" -GamebryoLocalSavegames::GamebryoLocalSavegames(const QDir& myGamesDir, +GamebryoLocalSavegames::GamebryoLocalSavegames(const GameGamebryo* game, const QString& iniFileName) - : m_LocalSavesDir(myGamesDir.absoluteFilePath(LocalSavesDummy)), - m_LocalGameDir(myGamesDir.absolutePath()), m_IniFileName(iniFileName) + : m_Game{game}, m_IniFileName(iniFileName) {} MappingType GamebryoLocalSavegames::mappings(const QDir& profileSaveDir) const { - return {{profileSaveDir.absolutePath(), m_LocalSavesDir.absolutePath(), true, true}}; + return {{profileSaveDir.absolutePath(), localSavesDirectory().absolutePath(), true, + true}}; +} + +QString GamebryoLocalSavegames::localSavesDummy() const +{ + return "__MO_Saves\\"; +} + +QDir GamebryoLocalSavegames::localSavesDirectory() const +{ + return QDir(m_Game->myGamesPath()).absoluteFilePath(localSavesDummy()); +} + +QDir GamebryoLocalSavegames::localGameDirectory() const +{ + return QDir(m_Game->myGamesPath()).absolutePath(); } bool GamebryoLocalSavegames::prepareProfile(MOBase::IProfile* profile) { bool enable = profile->localSavesEnabled(); - QString basePath = profile->localSettingsEnabled() ? profile->absolutePath() - : m_LocalGameDir.absolutePath(); + QString basePath = profile->localSettingsEnabled() + ? profile->absolutePath() + : localGameDirectory().absolutePath(); QString iniFilePath = basePath + "/" + m_IniFileName; QString saveIni = profile->absolutePath() + "/" + "savepath.ini"; @@ -51,7 +67,7 @@ bool GamebryoLocalSavegames::prepareProfile(MOBase::IProfile* profile) GetPrivateProfileStringW(L"General", L"sLocalSavePath", L"SKIP_ME", currentPath, MAX_PATH, iniFilePath.toStdWString().c_str()); bool alreadyEnabled = - wcscmp(currentPath, LocalSavesDummy.toStdWString().c_str()) == 0; + wcscmp(currentPath, localSavesDummy().toStdWString().c_str()) == 0; // Get the current bUseMyGamesDirectory WCHAR currentMyGames[MAX_PATH]; @@ -61,7 +77,7 @@ bool GamebryoLocalSavegames::prepareProfile(MOBase::IProfile* profile) // Create the __MO_Saves directory if local saves are enabled and it doesn't exist if (enable) { - QDir saves = QDir(m_LocalGameDir.absolutePath() + "/" + LocalSavesDummy); + QDir saves = localSavesDirectory(); if (!saves.exists()) { saves.mkdir("."); } @@ -79,7 +95,7 @@ bool GamebryoLocalSavegames::prepareProfile(MOBase::IProfile* profile) saveIni.toStdWString().c_str()); } MOBase::WriteRegistryValue(L"General", L"sLocalSavePath", - LocalSavesDummy.toStdWString().c_str(), + localSavesDummy().toStdWString().c_str(), iniFilePath.toStdWString().c_str()); MOBase::WriteRegistryValue(L"General", L"bUseMyGamesDirectory", L"1", iniFilePath.toStdWString().c_str()); diff --git a/src/gamebryo/gamebryolocalsavegames.h b/src/gamebryo/gamebryolocalsavegames.h index 675d52ce..e5f2a920 100644 --- a/src/gamebryo/gamebryolocalsavegames.h +++ b/src/gamebryo/gamebryolocalsavegames.h @@ -24,18 +24,30 @@ Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA #include #include +class GameGamebryo; + class GamebryoLocalSavegames : public MOBase::LocalSavegames { public: - GamebryoLocalSavegames(const QDir& myGamesDir, const QString& iniFileName); + GamebryoLocalSavegames(const GameGamebryo* game, const QString& iniFileName); virtual MappingType mappings(const QDir& profileSaveDir) const override; virtual bool prepareProfile(MOBase::IProfile* profile) override; +protected: + // return the path from the local game directory to the local saves folder + // + // this is virtual so game plugins for complete game overhauld (Enderal, Nehrim, etc.) + // can override it properly + // + virtual QString localSavesDummy() const; + + QDir localSavesDirectory() const; + QDir localGameDirectory() const; + private: - QDir m_LocalSavesDir; - QDir m_LocalGameDir; + const GameGamebryo* m_Game; QString m_IniFileName; }; diff --git a/src/gamebryo/gamegamebryo.cpp b/src/gamebryo/gamegamebryo.cpp index 82a188cc..a4cb3043 100644 --- a/src/gamebryo/gamegamebryo.cpp +++ b/src/gamebryo/gamegamebryo.cpp @@ -83,7 +83,7 @@ QDir GameGamebryo::documentsDirectory() const QDir GameGamebryo::savesDirectory() const { - return QDir(m_MyGamesPath + "/Saves"); + return QDir(myGamesPath() + "/Saves"); } std::vector> diff --git a/src/gamebryo/gamegamebryo.h b/src/gamebryo/gamegamebryo.h index 38df69f7..2ff07db5 100644 --- a/src/gamebryo/gamegamebryo.h +++ b/src/gamebryo/gamegamebryo.h @@ -85,6 +85,9 @@ public: // IPluginGame interface public: // IPluginFileMapper interface virtual MappingType mappings() const; +public: // Other (e.g. for game features) + QString myGamesPath() const; + protected: // Retrieve the saves extension for the game. virtual QString savegameExtension() const = 0; @@ -95,7 +98,6 @@ protected: makeSaveGame(QString filepath) const = 0; QFileInfo findInGameFolder(const QString& relativePath) const; - QString myGamesPath() const; QString selectedVariant() const; WORD getArch(QString const& program) const; From 05e16f41913883b7f0c3c06d6aa8b02c1e7ea752 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Mika=C3=ABl=20Capelle?= Date: Sat, 22 Jun 2024 08:29:21 +0200 Subject: [PATCH 1504/1544] [game_enderalse] Update following gamebryo updates for myGamesPath() in game feature. (#11) --- .../enderalse/src/enderalsedataarchives.cpp | 8 +- .../enderalse/src/enderalsedataarchives.h | 4 +- .../enderalse/src/enderalselocalsavegames.cpp | 104 +----------------- .../enderalse/src/enderalselocalsavegames.h | 17 +-- src/games/enderalse/src/game_enderalse_en.ts | 4 +- src/games/enderalse/src/gameenderalse.cpp | 13 +-- src/games/enderalse/src/gameenderalse.h | 1 - 7 files changed, 14 insertions(+), 137 deletions(-) diff --git a/src/games/enderalse/src/enderalsedataarchives.cpp b/src/games/enderalse/src/enderalsedataarchives.cpp index 4082d4f2..9f15d3dd 100644 --- a/src/games/enderalse/src/enderalsedataarchives.cpp +++ b/src/games/enderalse/src/enderalsedataarchives.cpp @@ -3,10 +3,6 @@ #include "iprofile.h" #include -EnderalSEDataArchives::EnderalSEDataArchives(const QDir& myGamesDir) - : GamebryoDataArchives(myGamesDir) -{} - QStringList EnderalSEDataArchives::vanillaArchives() const { return {"Skyrim - Textures0.bsa", @@ -43,7 +39,7 @@ QStringList EnderalSEDataArchives::archives(const MOBase::IProfile* profile) con QString iniFile = profile->localSettingsEnabled() ? QDir(profile->absolutePath()).absoluteFilePath("enderal.ini") - : m_LocalGameDir.absoluteFilePath("enderal.ini"); + : localGameDirectory().absoluteFilePath("enderal.ini"); result.append(getArchivesFromKey(iniFile, "SResourceArchiveList", 512)); result.append(getArchivesFromKey(iniFile, "SResourceArchiveList2", 512)); @@ -57,7 +53,7 @@ void EnderalSEDataArchives::writeArchiveList(MOBase::IProfile* profile, QString iniFile = profile->localSettingsEnabled() ? QDir(profile->absolutePath()).absoluteFilePath("enderal.ini") - : m_LocalGameDir.absoluteFilePath("enderal.ini"); + : localGameDirectory().absoluteFilePath("enderal.ini"); if (list.length() > 511) { int splitIdx = list.lastIndexOf(",", 512); setArchivesToKey(iniFile, "SResourceArchiveList", list.mid(0, splitIdx)); diff --git a/src/games/enderalse/src/enderalsedataarchives.h b/src/games/enderalse/src/enderalsedataarchives.h index 4048444d..4c51e93d 100644 --- a/src/games/enderalse/src/enderalsedataarchives.h +++ b/src/games/enderalse/src/enderalsedataarchives.h @@ -12,11 +12,9 @@ class IProfile; class EnderalSEDataArchives : public GamebryoDataArchives { - public: - EnderalSEDataArchives(const QDir& myGamesDir); + using GamebryoDataArchives::GamebryoDataArchives; -public: virtual QStringList vanillaArchives() const override; virtual QStringList archives(const MOBase::IProfile* profile) const override; diff --git a/src/games/enderalse/src/enderalselocalsavegames.cpp b/src/games/enderalse/src/enderalselocalsavegames.cpp index b3aa2546..fafa7398 100644 --- a/src/games/enderalse/src/enderalselocalsavegames.cpp +++ b/src/games/enderalse/src/enderalselocalsavegames.cpp @@ -17,108 +17,8 @@ Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA */ #include "enderalselocalsavegames.h" -#include "registry.h" -#include -#include -#include -#include -#include -static const QString LocalSavesDummy = "..\\Enderal Special Edition\\__MO_Saves\\"; - -EnderalSELocalSavegames::EnderalSELocalSavegames(const QDir& myGamesDir, - const QString& iniFileName) - : m_LocalSavesDir(myGamesDir.absoluteFilePath(LocalSavesDummy)), - m_LocalGameDir(myGamesDir.absolutePath()), m_IniFileName(iniFileName) -{} - -MappingType EnderalSELocalSavegames::mappings(const QDir& profileSaveDir) const +QString EnderalSELocalSavegames::localSavesDummy() const { - return {{profileSaveDir.absolutePath(), m_LocalSavesDir.absolutePath(), true, true}}; -} - -bool EnderalSELocalSavegames::prepareProfile(MOBase::IProfile* profile) -{ - bool enable = profile->localSavesEnabled(); - - QString basePath = profile->localSettingsEnabled() ? profile->absolutePath() - : m_LocalGameDir.absolutePath(); - QString iniFilePath = basePath + "/" + m_IniFileName; - QString saveIni = profile->absolutePath() + "/" + "savepath.ini"; - - // Get the current sLocalSavePath - WCHAR currentPath[MAX_PATH]; - GetPrivateProfileStringW(L"General", L"sLocalSavePath", L"SKIP_ME", currentPath, - MAX_PATH, iniFilePath.toStdWString().c_str()); - bool alreadyEnabled = - wcscmp(currentPath, LocalSavesDummy.toStdWString().c_str()) == 0; - - // Get the current bUseMyGamesDirectory - WCHAR currentMyGames[MAX_PATH]; - GetPrivateProfileStringW(L"General", L"bUseMyGamesDirectory", L"SKIP_ME", - currentMyGames, MAX_PATH, - iniFilePath.toStdWString().c_str()); - - // Create the __MO_Saves directory if local saves are enabled and it doesn't exist - if (enable) { - QDir saves = QDir(m_LocalGameDir.absolutePath() + "/" + LocalSavesDummy); - if (!saves.exists()) { - saves.mkdir("."); - } - } - - // Set the path to __MO_Saves if it's not already - if (enable && !alreadyEnabled) { - // If the path is not blank, save it to savepath.ini - if (wcscmp(currentPath, L"SKIP_ME") != 0) { - MOBase::WriteRegistryValue(L"General", L"sLocalSavePath", currentPath, - saveIni.toStdWString().c_str()); - } - if (wcscmp(currentMyGames, L"SKIP_ME") != 0) { - MOBase::WriteRegistryValue(L"General", L"bUseMyGamesDirectory", currentMyGames, - saveIni.toStdWString().c_str()); - } - MOBase::WriteRegistryValue(L"General", L"sLocalSavePath", - LocalSavesDummy.toStdWString().c_str(), - iniFilePath.toStdWString().c_str()); - MOBase::WriteRegistryValue(L"General", L"bUseMyGamesDirectory", L"1", - iniFilePath.toStdWString().c_str()); - } - - // Get rid of the local saves setting if it's still there - if (!enable && alreadyEnabled) { - // If savepath.ini exists, use it and delete it - if (QFile::exists(saveIni)) { - WCHAR savedPath[MAX_PATH]; - WCHAR savedMyGames[MAX_PATH]; - GetPrivateProfileStringW(L"General", L"sLocalSavePath", L"DELETE_ME", savedPath, - MAX_PATH, saveIni.toStdWString().c_str()); - GetPrivateProfileStringW(L"General", L"bUseMyGamesDirectory", L"DELETE_ME", - savedMyGames, MAX_PATH, saveIni.toStdWString().c_str()); - if (wcscmp(savedPath, L"DELETE_ME") != 0) { - MOBase::WriteRegistryValue(L"General", L"sLocalSavePath", savedPath, - iniFilePath.toStdWString().c_str()); - } else { - MOBase::WriteRegistryValue(L"General", L"sLocalSavePath", NULL, - iniFilePath.toStdWString().c_str()); - } - if (wcscmp(savedMyGames, L"DELETE_ME") != 0) { - MOBase::WriteRegistryValue(L"General", L"bUseMyGamesDirectory", savedMyGames, - iniFilePath.toStdWString().c_str()); - } else { - MOBase::WriteRegistryValue(L"General", L"bUseMyGamesDirectory", NULL, - iniFilePath.toStdWString().c_str()); - } - QFile::remove(saveIni); - } - // Otherwise just delete the setting - else { - MOBase::WriteRegistryValue(L"General", L"sLocalSavePath", NULL, - iniFilePath.toStdWString().c_str()); - MOBase::WriteRegistryValue(L"General", L"bUseMyGamesDirectory", NULL, - iniFilePath.toStdWString().c_str()); - } - } - - return enable != alreadyEnabled; + return "..\\Enderal Special Edition\\__MO_Saves\\"; } diff --git a/src/games/enderalse/src/enderalselocalsavegames.h b/src/games/enderalse/src/enderalselocalsavegames.h index 78b4d04d..f0d14ad2 100644 --- a/src/games/enderalse/src/enderalselocalsavegames.h +++ b/src/games/enderalse/src/enderalselocalsavegames.h @@ -1,24 +1,17 @@ #ifndef ENDERALSELOCALSAVEGAMES_H #define ENDERALSELOCALSAVEGAMES_H -#include +#include -#include #include -class EnderalSELocalSavegames : public MOBase::LocalSavegames +class EnderalSELocalSavegames : public GamebryoLocalSavegames { - public: - EnderalSELocalSavegames(const QDir& myGamesDir, const QString& iniFileName); + using GamebryoLocalSavegames::GamebryoLocalSavegames; - virtual MappingType mappings(const QDir& profileSaveDir) const override; - virtual bool prepareProfile(MOBase::IProfile* profile) override; - -private: - QDir m_LocalSavesDir; - QDir m_LocalGameDir; - QString m_IniFileName; +protected: + QString localSavesDummy() const override; }; #endif // ENDERALSELOCALSAVEGAMES_H diff --git a/src/games/enderalse/src/game_enderalse_en.ts b/src/games/enderalse/src/game_enderalse_en.ts index 540fe0eb..4c8b5a24 100644 --- a/src/games/enderalse/src/game_enderalse_en.ts +++ b/src/games/enderalse/src/game_enderalse_en.ts @@ -4,12 +4,12 @@ GameEnderalSE - + Enderal Special Edition Support Plugin - + Adds support for the game Enderal Special Edition. diff --git a/src/games/enderalse/src/gameenderalse.cpp b/src/games/enderalse/src/gameenderalse.cpp index 8feed75e..3713fa26 100644 --- a/src/games/enderalse/src/gameenderalse.cpp +++ b/src/games/enderalse/src/gameenderalse.cpp @@ -84,9 +84,6 @@ void GameEnderalSE::setGamePath(const QString& path) m_GamePath = path; checkVariants(); m_MyGamesPath = determineMyGamesPath(gameDirectoryName()); - registerFeature(std::make_shared(myGamesPath())); - registerFeature( - std::make_shared(myGamesPath(), "Enderal.ini")); } QDir GameEnderalSE::savesDirectory() const @@ -94,11 +91,6 @@ QDir GameEnderalSE::savesDirectory() const return QDir(m_MyGamesPath + "/Saves"); } -QString GameEnderalSE::myGamesPath() const -{ - return m_MyGamesPath; -} - bool GameEnderalSE::isInstalled() const { return !m_GamePath.isEmpty(); @@ -110,11 +102,10 @@ bool GameEnderalSE::init(IOrganizer* moInfo) return false; } - auto dataArchives = std::make_shared(myGamesPath()); + auto dataArchives = std::make_shared(this); registerFeature(std::make_shared(this)); registerFeature(dataArchives); - registerFeature( - std::make_shared(myGamesPath(), "enderal.ini")); + registerFeature(std::make_shared(this, "enderal.ini")); registerFeature(std::make_shared(this)); registerFeature(std::make_shared(moInfo->gameFeatures())); registerFeature(std::make_shared(this)); diff --git a/src/games/enderalse/src/gameenderalse.h b/src/games/enderalse/src/gameenderalse.h index 51d77646..754951dd 100644 --- a/src/games/enderalse/src/gameenderalse.h +++ b/src/games/enderalse/src/gameenderalse.h @@ -65,7 +65,6 @@ protected: QDir documentsDirectory() const; QDir savesDirectory() const; QFileInfo findInGameFolder(const QString& relativePath) const; - QString myGamesPath() const; void checkVariants(); void setVariant(QString variant); From cfdc0e94f2a2ad90c61897d5048182d9a28dc37e Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Mika=C3=ABl=20Capelle?= Date: Sat, 22 Jun 2024 08:29:24 +0200 Subject: [PATCH 1505/1544] [game_fallout3] Update following gamebryo updates for myGamesPath() in game feature. (#24) --- src/games/fallout3/src/fallout3dataarchives.cpp | 8 ++------ src/games/fallout3/src/fallout3dataarchives.h | 4 +--- src/games/fallout3/src/game_fallout3_en.ts | 4 ++-- src/games/fallout3/src/gamefallout3.cpp | 7 +++---- 4 files changed, 8 insertions(+), 15 deletions(-) diff --git a/src/games/fallout3/src/fallout3dataarchives.cpp b/src/games/fallout3/src/fallout3dataarchives.cpp index 623b566a..ed6627ba 100644 --- a/src/games/fallout3/src/fallout3dataarchives.cpp +++ b/src/games/fallout3/src/fallout3dataarchives.cpp @@ -3,10 +3,6 @@ #include "iprofile.h" #include -Fallout3DataArchives::Fallout3DataArchives(const QDir& myGamesDir) - : GamebryoDataArchives(myGamesDir) -{} - QStringList Fallout3DataArchives::vanillaArchives() const { return {"Fallout - Textures.bsa", "Fallout - Meshes.bsa", "Fallout - Voices.bsa", @@ -19,7 +15,7 @@ QStringList Fallout3DataArchives::archives(const MOBase::IProfile* profile) cons QString iniFile = profile->localSettingsEnabled() ? QDir(profile->absolutePath()).absoluteFilePath("fallout.ini") - : m_LocalGameDir.absoluteFilePath("fallout.ini"); + : localGameDirectory().absoluteFilePath("fallout.ini"); result.append(getArchivesFromKey(iniFile, "SArchiveList")); return result; @@ -32,6 +28,6 @@ void Fallout3DataArchives::writeArchiveList(MOBase::IProfile* profile, QString iniFile = profile->localSettingsEnabled() ? QDir(profile->absolutePath()).absoluteFilePath("fallout.ini") - : m_LocalGameDir.absoluteFilePath("fallout.ini"); + : localGameDirectory().absoluteFilePath("fallout.ini"); setArchivesToKey(iniFile, "SArchiveList", list); } diff --git a/src/games/fallout3/src/fallout3dataarchives.h b/src/games/fallout3/src/fallout3dataarchives.h index 5522e08f..8ba45613 100644 --- a/src/games/fallout3/src/fallout3dataarchives.h +++ b/src/games/fallout3/src/fallout3dataarchives.h @@ -6,11 +6,9 @@ class Fallout3DataArchives : public GamebryoDataArchives { - public: - Fallout3DataArchives(const QDir& myGamesDir); + using GamebryoDataArchives::GamebryoDataArchives; -public: virtual QStringList vanillaArchives() const override; virtual QStringList archives(const MOBase::IProfile* profile) const override; diff --git a/src/games/fallout3/src/game_fallout3_en.ts b/src/games/fallout3/src/game_fallout3_en.ts index c404839d..e1912864 100644 --- a/src/games/fallout3/src/game_fallout3_en.ts +++ b/src/games/fallout3/src/game_fallout3_en.ts @@ -4,12 +4,12 @@ GameFallout3 - + Fallout 3 Support Plugin - + Adds support for the game Fallout 3. diff --git a/src/games/fallout3/src/gamefallout3.cpp b/src/games/fallout3/src/gamefallout3.cpp index 6de76cd9..3bd553be 100644 --- a/src/games/fallout3/src/gamefallout3.cpp +++ b/src/games/fallout3/src/gamefallout3.cpp @@ -35,13 +35,12 @@ bool GameFallout3::init(IOrganizer* moInfo) return false; } - auto dataArchives = std::make_shared(myGamesPath()); + auto dataArchives = std::make_shared(this); registerFeature(std::make_shared(this)); registerFeature(dataArchives); registerFeature(std::make_shared(dataArchives.get(), this)); registerFeature(std::make_shared(this)); - registerFeature( - std::make_shared(myGamesPath(), "fallout.ini")); + registerFeature(std::make_shared(this, "fallout.ini")); registerFeature(std::make_shared(this)); registerFeature( std::make_shared(m_Organizer->gameFeatures())); @@ -139,7 +138,7 @@ void GameFallout3::initializeProfile(const QDir& path, ProfileSettings settings) if (settings.testFlag(IPluginGame::CONFIGURATION)) { if (settings.testFlag(IPluginGame::PREFER_DEFAULTS) || - !QFileInfo(myGamesPath() + "/fallout.ini").exists()) { + !QFileInfo(myGamesPath(), "fallout.ini").exists()) { copyToProfile(gameDirectory().absolutePath(), path, "fallout_default.ini", "fallout.ini"); } else { From 45da5c70f749684121c6ff174ccac9c6f4c8243a Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Mika=C3=ABl=20Capelle?= Date: Sat, 22 Jun 2024 08:29:27 +0200 Subject: [PATCH 1506/1544] [game_fallout4] Update following gamebryo updates for myGamesPath() in game feature. (#28) --- src/games/fallout4/src/fallout4dataarchives.cpp | 8 ++------ src/games/fallout4/src/fallout4dataarchives.h | 4 +--- src/games/fallout4/src/game_fallout4_en.ts | 8 ++++---- src/games/fallout4/src/gamefallout4.cpp | 5 ++--- 4 files changed, 9 insertions(+), 16 deletions(-) diff --git a/src/games/fallout4/src/fallout4dataarchives.cpp b/src/games/fallout4/src/fallout4dataarchives.cpp index 5dccd793..c0931ce1 100644 --- a/src/games/fallout4/src/fallout4dataarchives.cpp +++ b/src/games/fallout4/src/fallout4dataarchives.cpp @@ -3,10 +3,6 @@ #include "iprofile.h" #include -Fallout4DataArchives::Fallout4DataArchives(const QDir& myGamesDir) - : GamebryoDataArchives(myGamesDir) -{} - QStringList Fallout4DataArchives::vanillaArchives() const { return {"Fallout4 - Textures1.ba2", "Fallout4 - Textures2.ba2", @@ -27,7 +23,7 @@ QStringList Fallout4DataArchives::archives(const MOBase::IProfile* profile) cons QString iniFile = profile->localSettingsEnabled() ? QDir(profile->absolutePath()).absoluteFilePath("fallout4.ini") - : m_LocalGameDir.absoluteFilePath("fallout4.ini"); + : localGameDirectory().absoluteFilePath("fallout4.ini"); result.append(getArchivesFromKey(iniFile, "SResourceArchiveList")); result.append(getArchivesFromKey(iniFile, "SResourceArchiveList2")); @@ -41,7 +37,7 @@ void Fallout4DataArchives::writeArchiveList(MOBase::IProfile* profile, QString iniFile = profile->localSettingsEnabled() ? QDir(profile->absolutePath()).absoluteFilePath("fallout4.ini") - : m_LocalGameDir.absoluteFilePath("fallout4.ini"); + : localGameDirectory().absoluteFilePath("fallout4.ini"); if (list.length() > 255) { int splitIdx = list.lastIndexOf(",", 256); setArchivesToKey(iniFile, "SResourceArchiveList", list.mid(0, splitIdx)); diff --git a/src/games/fallout4/src/fallout4dataarchives.h b/src/games/fallout4/src/fallout4dataarchives.h index 42695f65..c90711c2 100644 --- a/src/games/fallout4/src/fallout4dataarchives.h +++ b/src/games/fallout4/src/fallout4dataarchives.h @@ -13,11 +13,9 @@ class IProfile; class Fallout4DataArchives : public GamebryoDataArchives { - public: - Fallout4DataArchives(const QDir& myGamesDir); + using GamebryoDataArchives::GamebryoDataArchives; -public: virtual QStringList vanillaArchives() const override; virtual QStringList archives(const MOBase::IProfile* profile) const override; diff --git a/src/games/fallout4/src/game_fallout4_en.ts b/src/games/fallout4/src/game_fallout4_en.ts index f01109fb..1c57784f 100644 --- a/src/games/fallout4/src/game_fallout4_en.ts +++ b/src/games/fallout4/src/game_fallout4_en.ts @@ -4,23 +4,23 @@ GameFallout4 - + Fallout 4 Support Plugin - + Adds support for the game Fallout 4. Splash by %1 - + sTestFile entries are present - + <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> diff --git a/src/games/fallout4/src/gamefallout4.cpp b/src/games/fallout4/src/gamefallout4.cpp index cf7170ba..be94e727 100644 --- a/src/games/fallout4/src/gamefallout4.cpp +++ b/src/games/fallout4/src/gamefallout4.cpp @@ -37,12 +37,11 @@ bool GameFallout4::init(IOrganizer* moInfo) return false; } - auto dataArchives = std::make_shared(myGamesPath()); + auto dataArchives = std::make_shared(this); registerFeature(std::make_shared(this)); registerFeature(dataArchives); - registerFeature( - std::make_shared(myGamesPath(), "fallout4custom.ini")); + registerFeature(std::make_shared(this, "fallout4custom.ini")); registerFeature(std::make_shared(this)); registerFeature( std::make_shared(m_Organizer->gameFeatures())); From ae4f1ea9fc22d0d2e3d19becfce1b9baffe9ad9c Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Mika=C3=ABl=20Capelle?= Date: Sat, 22 Jun 2024 08:29:30 +0200 Subject: [PATCH 1507/1544] [game_fallout4vr] Update following gamebryo updates for myGamesPath() in game feature. (#27) --- src/games/fallout4vr/src/fallout4vrdataarchives.cpp | 8 ++------ src/games/fallout4vr/src/fallout4vrdataarchives.h | 4 +--- src/games/fallout4vr/src/game_fallout4vr_en.ts | 4 ++-- src/games/fallout4vr/src/gamefallout4vr.cpp | 5 ++--- 4 files changed, 7 insertions(+), 14 deletions(-) diff --git a/src/games/fallout4vr/src/fallout4vrdataarchives.cpp b/src/games/fallout4vr/src/fallout4vrdataarchives.cpp index b28d8783..58a9a09d 100644 --- a/src/games/fallout4vr/src/fallout4vrdataarchives.cpp +++ b/src/games/fallout4vr/src/fallout4vrdataarchives.cpp @@ -3,10 +3,6 @@ #include "iprofile.h" #include -Fallout4VRDataArchives::Fallout4VRDataArchives(const QDir& myGamesDir) - : GamebryoDataArchives(myGamesDir) -{} - QStringList Fallout4VRDataArchives::vanillaArchives() const { return {"Fallout4 - Textures1.ba2", "Fallout4 - Textures2.ba2", @@ -28,7 +24,7 @@ QStringList Fallout4VRDataArchives::archives(const MOBase::IProfile* profile) co QString iniFile = profile->localSettingsEnabled() ? QDir(profile->absolutePath()).absoluteFilePath("fallout4.ini") - : m_LocalGameDir.absoluteFilePath("fallout4.ini"); + : localGameDirectory().absoluteFilePath("fallout4.ini"); result.append(getArchivesFromKey(iniFile, "SResourceArchiveList")); result.append(getArchivesFromKey(iniFile, "SResourceArchiveList2")); @@ -42,7 +38,7 @@ void Fallout4VRDataArchives::writeArchiveList(MOBase::IProfile* profile, QString iniFile = profile->localSettingsEnabled() ? QDir(profile->absolutePath()).absoluteFilePath("fallout4.ini") - : m_LocalGameDir.absoluteFilePath("fallout4.ini"); + : localGameDirectory().absoluteFilePath("fallout4.ini"); if (list.length() > 255) { int splitIdx = list.lastIndexOf(",", 256); setArchivesToKey(iniFile, "SResourceArchiveList", list.mid(0, splitIdx)); diff --git a/src/games/fallout4vr/src/fallout4vrdataarchives.h b/src/games/fallout4vr/src/fallout4vrdataarchives.h index c7a6b796..71d0b3de 100644 --- a/src/games/fallout4vr/src/fallout4vrdataarchives.h +++ b/src/games/fallout4vr/src/fallout4vrdataarchives.h @@ -13,11 +13,9 @@ class IProfile; class Fallout4VRDataArchives : public GamebryoDataArchives { - public: - Fallout4VRDataArchives(const QDir& myGamesDir); + using GamebryoDataArchives::GamebryoDataArchives; -public: virtual QStringList vanillaArchives() const override; virtual QStringList archives(const MOBase::IProfile* profile) const override; diff --git a/src/games/fallout4vr/src/game_fallout4vr_en.ts b/src/games/fallout4vr/src/game_fallout4vr_en.ts index 6823bb92..4044f20a 100644 --- a/src/games/fallout4vr/src/game_fallout4vr_en.ts +++ b/src/games/fallout4vr/src/game_fallout4vr_en.ts @@ -4,12 +4,12 @@ GameFallout4VR - + Fallout 4 VR Support Plugin - + Adds support for the game Fallout 4 VR. Splash by %1 diff --git a/src/games/fallout4vr/src/gamefallout4vr.cpp b/src/games/fallout4vr/src/gamefallout4vr.cpp index 7374582a..0ce1f6d0 100644 --- a/src/games/fallout4vr/src/gamefallout4vr.cpp +++ b/src/games/fallout4vr/src/gamefallout4vr.cpp @@ -35,9 +35,8 @@ bool GameFallout4VR::init(IOrganizer* moInfo) return false; } - registerFeature(std::make_shared(myGamesPath())); - registerFeature( - std::make_shared(myGamesPath(), "fallout4custom.ini")); + registerFeature(std::make_shared(this)); + registerFeature(std::make_shared(this, "fallout4custom.ini")); registerFeature(std::make_shared(this)); registerFeature( std::make_shared(m_Organizer->gameFeatures())); From 331a9549846d449744029b5d321b9b24574bb018 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Mika=C3=ABl=20Capelle?= Date: Sat, 22 Jun 2024 08:29:32 +0200 Subject: [PATCH 1508/1544] [game_fallout76] Update following gamebryo updates for myGamesPath() in game feature. (#6) --- src/games/fallout76/src/fallout76dataarchives.cpp | 8 ++------ src/games/fallout76/src/fallout76dataarchives.h | 4 +--- src/games/fallout76/src/gamefallout76.cpp | 2 +- 3 files changed, 4 insertions(+), 10 deletions(-) diff --git a/src/games/fallout76/src/fallout76dataarchives.cpp b/src/games/fallout76/src/fallout76dataarchives.cpp index d9bff8dc..6827d085 100644 --- a/src/games/fallout76/src/fallout76dataarchives.cpp +++ b/src/games/fallout76/src/fallout76dataarchives.cpp @@ -5,10 +5,6 @@ #include -Fallout76DataArchives::Fallout76DataArchives(const QDir& myGamesDir) - : GamebryoDataArchives(myGamesDir) -{} - QStringList Fallout76DataArchives::vanillaArchives() const { return {"SeventySix - Animations.ba2", @@ -86,7 +82,7 @@ QStringList Fallout76DataArchives::archives(const MOBase::IProfile* profile) con QString iniFile = profile->localSettingsEnabled() ? QDir(profile->absolutePath()).absoluteFilePath("Fallout76.ini") - : m_LocalGameDir.absoluteFilePath("Fallout76.ini"); + : localGameDirectory().absoluteFilePath("Fallout76.ini"); result.append(getArchivesFromKey(iniFile, "sResourceIndexFileList")); result.append(getArchivesFromKey(iniFile, "sResourceStartUpArchiveList")); @@ -104,7 +100,7 @@ void Fallout76DataArchives::writeArchiveList(MOBase::IProfile* profile, QString iniFile = profile->localSettingsEnabled() ? QDir(profile->absolutePath()).absoluteFilePath("Fallout76.ini") - : m_LocalGameDir.absoluteFilePath("Fallout76.ini"); + : localGameDirectory().absoluteFilePath("Fallout76.ini"); QStringList sResourceIndexFileList = {}; QStringList sResourceStartUpArchiveList = {}; diff --git a/src/games/fallout76/src/fallout76dataarchives.h b/src/games/fallout76/src/fallout76dataarchives.h index b507d281..1cf91199 100644 --- a/src/games/fallout76/src/fallout76dataarchives.h +++ b/src/games/fallout76/src/fallout76dataarchives.h @@ -13,11 +13,9 @@ class IProfile; class Fallout76DataArchives : public GamebryoDataArchives { - public: - Fallout76DataArchives(const QDir& myGamesDir); + using GamebryoDataArchives::GamebryoDataArchives; -public: virtual QStringList vanillaArchives() const override; virtual QStringList sResourceIndexFileList() const; virtual QStringList sResourceStartUpArchiveList() const; diff --git a/src/games/fallout76/src/gamefallout76.cpp b/src/games/fallout76/src/gamefallout76.cpp index 1d7fd711..b0afc2ef 100644 --- a/src/games/fallout76/src/gamefallout76.cpp +++ b/src/games/fallout76/src/gamefallout76.cpp @@ -36,7 +36,7 @@ bool GameFallout76::init(IOrganizer* moInfo) } registerFeature(std::make_shared(this)); - registerFeature(std::make_shared(myGamesPath())); + registerFeature(std::make_shared(this)); registerFeature(std::make_shared(this)); registerFeature( std::make_shared(m_Organizer->gameFeatures())); From ae57b31f8acac3020a5ee9649ed86e4ef71c9c83 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Mika=C3=ABl=20Capelle?= Date: Sat, 22 Jun 2024 08:29:34 +0200 Subject: [PATCH 1509/1544] [game_falloutnv] Update following gamebryo updates for myGamesPath() in game feature. (#34) --- src/games/falloutnv/src/falloutnvdataarchives.cpp | 8 ++------ src/games/falloutnv/src/falloutnvdataarchives.h | 3 +-- src/games/falloutnv/src/game_falloutNV_en.ts | 6 +++--- src/games/falloutnv/src/gamefalloutnv.cpp | 11 ++--------- 4 files changed, 8 insertions(+), 20 deletions(-) diff --git a/src/games/falloutnv/src/falloutnvdataarchives.cpp b/src/games/falloutnv/src/falloutnvdataarchives.cpp index b9f83596..7314561f 100644 --- a/src/games/falloutnv/src/falloutnvdataarchives.cpp +++ b/src/games/falloutnv/src/falloutnvdataarchives.cpp @@ -1,10 +1,6 @@ #include "falloutnvdataarchives.h" #include -FalloutNVDataArchives::FalloutNVDataArchives(const QDir& myGamesDir) - : GamebryoDataArchives(myGamesDir) -{} - QStringList FalloutNVDataArchives::vanillaArchives() const { return {"Fallout - Textures.bsa", "Fallout - Textures2.bsa", "Fallout - Meshes.bsa", @@ -17,7 +13,7 @@ QStringList FalloutNVDataArchives::archives(const MOBase::IProfile* profile) con QString iniFile = profile->localSettingsEnabled() ? QDir(profile->absolutePath()).absoluteFilePath("fallout.ini") - : m_LocalGameDir.absoluteFilePath("fallout.ini"); + : localGameDirectory().absoluteFilePath("fallout.ini"); result.append(getArchivesFromKey(iniFile, "SArchiveList", 8192)); // NVAC expands the maximum string limit @@ -31,6 +27,6 @@ void FalloutNVDataArchives::writeArchiveList(MOBase::IProfile* profile, QString iniFile = profile->localSettingsEnabled() ? QDir(profile->absolutePath()).absoluteFilePath("fallout.ini") - : m_LocalGameDir.absoluteFilePath("fallout.ini"); + : localGameDirectory().absoluteFilePath("fallout.ini"); setArchivesToKey(iniFile, "SArchiveList", list); } diff --git a/src/games/falloutnv/src/falloutnvdataarchives.h b/src/games/falloutnv/src/falloutnvdataarchives.h index 8b7ca21f..07e64a13 100644 --- a/src/games/falloutnv/src/falloutnvdataarchives.h +++ b/src/games/falloutnv/src/falloutnvdataarchives.h @@ -10,9 +10,8 @@ class FalloutNVDataArchives : public GamebryoDataArchives { public: - FalloutNVDataArchives(const QDir& myGamesDir); + using GamebryoDataArchives::GamebryoDataArchives; -public: virtual QStringList vanillaArchives() const override; virtual QStringList archives(const MOBase::IProfile* profile) const override; diff --git a/src/games/falloutnv/src/game_falloutNV_en.ts b/src/games/falloutnv/src/game_falloutNV_en.ts index 00dc6987..8aa62ece 100644 --- a/src/games/falloutnv/src/game_falloutNV_en.ts +++ b/src/games/falloutnv/src/game_falloutNV_en.ts @@ -4,17 +4,17 @@ GameFalloutNV - + Fallout NV Support Plugin - + Adds support for the game Fallout New Vegas - + While not recommended by the FNV modding community, enables LOOT sorting diff --git a/src/games/falloutnv/src/gamefalloutnv.cpp b/src/games/falloutnv/src/gamefalloutnv.cpp index 9abba544..87b4119e 100644 --- a/src/games/falloutnv/src/gamefalloutnv.cpp +++ b/src/games/falloutnv/src/gamefalloutnv.cpp @@ -35,13 +35,12 @@ bool GameFalloutNV::init(IOrganizer* moInfo) return false; } - auto dataArchives = std::make_shared(myGamesPath()); + auto dataArchives = std::make_shared(this); registerFeature(std::make_shared(this)); registerFeature(dataArchives); registerFeature(std::make_shared(dataArchives.get(), this)); registerFeature(std::make_shared(this)); - registerFeature( - std::make_shared(myGamesPath(), "fallout.ini")); + registerFeature(std::make_shared(this, "fallout.ini")); registerFeature(std::make_shared(this)); registerFeature( std::make_shared(m_Organizer->gameFeatures())); @@ -104,12 +103,6 @@ void GameFalloutNV::setGamePath(const QString& path) m_GamePath = path; checkVariants(); m_MyGamesPath = determineMyGamesPath(gameDirectoryName()); - - auto dataArchives = std::make_shared(myGamesPath()); - registerFeature(dataArchives); - registerFeature(std::make_shared(dataArchives.get(), this)); - registerFeature( - std::make_shared(myGamesPath(), "fallout.ini")); } QDir GameFalloutNV::savesDirectory() const From 6085089ba46183dde5a015c8fee03f3ff2f095c8 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Mika=C3=ABl=20Capelle?= Date: Sat, 22 Jun 2024 08:29:40 +0200 Subject: [PATCH 1510/1544] [game_morrowind] Update following gamebryo updates for myGamesPath() in game feature. (#32) --- src/games/morrowind/src/game_morrowind_en.ts | 8 ++++---- src/games/morrowind/src/morrowinddataarchives.cpp | 11 +++-------- src/games/morrowind/src/morrowinddataarchives.h | 6 +----- 3 files changed, 8 insertions(+), 17 deletions(-) diff --git a/src/games/morrowind/src/game_morrowind_en.ts b/src/games/morrowind/src/game_morrowind_en.ts index 65bb4f28..c6961c4e 100644 --- a/src/games/morrowind/src/game_morrowind_en.ts +++ b/src/games/morrowind/src/game_morrowind_en.ts @@ -9,7 +9,7 @@ - + Adds support for the game Morrowind. Splash by %1 @@ -48,12 +48,12 @@ Splash by %1 - + Missing ESPs - + None @@ -61,7 +61,7 @@ Splash by %1 QObject - + Some of your plugins have invalid names! These plugins can not be loaded by the game. Please see mo_interface.log for a list of affected plugins and rename them. diff --git a/src/games/morrowind/src/morrowinddataarchives.cpp b/src/games/morrowind/src/morrowinddataarchives.cpp index 4a133a50..83e1b277 100644 --- a/src/games/morrowind/src/morrowinddataarchives.cpp +++ b/src/games/morrowind/src/morrowinddataarchives.cpp @@ -2,12 +2,7 @@ #include "registry.h" #include -MorrowindDataArchives::MorrowindDataArchives(const MOBase::IPluginGame* game) - : GamebryoDataArchives( - QDir()) // m_LocalGameDir is not used as it's determined too soon - , - m_GamePlugin(game) -{} +#include "gamegamebryo.h" QStringList MorrowindDataArchives::vanillaArchives() const { @@ -57,7 +52,7 @@ QStringList MorrowindDataArchives::archives(const MOBase::IProfile* profile) con QString iniFile = profile->localSettingsEnabled() ? QDir(profile->absolutePath()).absoluteFilePath("morrowind.ini") - : m_GamePlugin->gameDirectory().absoluteFilePath("morrowind.ini"); + : gameDirectory().absoluteFilePath("morrowind.ini"); result.append(getArchives(iniFile)); return result; @@ -69,6 +64,6 @@ void MorrowindDataArchives::writeArchiveList(MOBase::IProfile* profile, QString iniFile = profile->localSettingsEnabled() ? QDir(profile->absolutePath()).absoluteFilePath("morrowind.ini") - : m_GamePlugin->gameDirectory().absoluteFilePath("morrowind.ini"); + : gameDirectory().absoluteFilePath("morrowind.ini"); setArchives(iniFile, before); } diff --git a/src/games/morrowind/src/morrowinddataarchives.h b/src/games/morrowind/src/morrowinddataarchives.h index e03500cf..7ee0c1d9 100644 --- a/src/games/morrowind/src/morrowinddataarchives.h +++ b/src/games/morrowind/src/morrowinddataarchives.h @@ -10,11 +10,9 @@ class MorrowindDataArchives : public GamebryoDataArchives { - public: - MorrowindDataArchives(const MOBase::IPluginGame* game); + using GamebryoDataArchives::GamebryoDataArchives; -public: virtual QStringList vanillaArchives() const override; virtual QStringList archives(const MOBase::IProfile* profile) const override; @@ -25,8 +23,6 @@ protected: private: virtual void writeArchiveList(MOBase::IProfile* profile, const QStringList& before) override; - - const MOBase::IPluginGame* m_GamePlugin; }; #endif // MORROWINDDATAARCHIVES_H From e96f521945a95182c53fd0d541f73a0755c6cef3 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Mika=C3=ABl=20Capelle?= Date: Sat, 22 Jun 2024 08:29:42 +0200 Subject: [PATCH 1511/1544] [game_nehrim] Update following gamebryo updates for myGamesPath() in game feature. (#9) --- src/games/nehrim/src/game_nehrim_en.ts | 4 ++-- src/games/nehrim/src/gamenehrim.cpp | 5 ++--- src/games/nehrim/src/nehrimdataarchives.cpp | 8 ++------ src/games/nehrim/src/nehrimdataarchives.h | 4 +--- 4 files changed, 7 insertions(+), 14 deletions(-) diff --git a/src/games/nehrim/src/game_nehrim_en.ts b/src/games/nehrim/src/game_nehrim_en.ts index 54b8d5a5..b5c79e41 100644 --- a/src/games/nehrim/src/game_nehrim_en.ts +++ b/src/games/nehrim/src/game_nehrim_en.ts @@ -4,12 +4,12 @@ GameNehrim - + Nehrim Support Plugin - + Adds support for the game Nehrim diff --git a/src/games/nehrim/src/gamenehrim.cpp b/src/games/nehrim/src/gamenehrim.cpp index 595670fb..c6b28ebb 100644 --- a/src/games/nehrim/src/gamenehrim.cpp +++ b/src/games/nehrim/src/gamenehrim.cpp @@ -30,13 +30,12 @@ bool GameNehrim::init(IOrganizer* moInfo) return false; } - auto dataArchives = std::make_shared(myGamesPath()); + auto dataArchives = std::make_shared(this); registerFeature(std::make_shared(this)); registerFeature(dataArchives); registerFeature(std::make_shared(dataArchives.get(), this)); registerFeature(std::make_shared(this)); - registerFeature( - std::make_shared(myGamesPath(), "oblivion.ini")); + registerFeature(std::make_shared(this, "oblivion.ini")); registerFeature(std::make_shared(this)); registerFeature(std::make_shared(m_Organizer->gameFeatures())); registerFeature(std::make_shared(moInfo)); diff --git a/src/games/nehrim/src/nehrimdataarchives.cpp b/src/games/nehrim/src/nehrimdataarchives.cpp index 8673bb86..8fe5b06b 100644 --- a/src/games/nehrim/src/nehrimdataarchives.cpp +++ b/src/games/nehrim/src/nehrimdataarchives.cpp @@ -1,10 +1,6 @@ #include "nehrimdataarchives.h" #include -NehrimDataArchives::NehrimDataArchives(const QDir& myGamesDir) - : GamebryoDataArchives(myGamesDir) -{} - QStringList NehrimDataArchives::vanillaArchives() const { return {"N - Meshes.bsa", "N - Textures1.bsa", "N - Textures2.bsa", "N - Misc.bsa", @@ -17,7 +13,7 @@ QStringList NehrimDataArchives::archives(const MOBase::IProfile* profile) const QString iniFile = profile->localSettingsEnabled() ? QDir(profile->absolutePath()).absoluteFilePath("oblivion.ini") - : m_LocalGameDir.absoluteFilePath("oblivion.ini"); + : localGameDirectory().absoluteFilePath("oblivion.ini"); result.append(getArchivesFromKey(iniFile, "SArchiveList")); return result; @@ -30,6 +26,6 @@ void NehrimDataArchives::writeArchiveList(MOBase::IProfile* profile, QString iniFile = profile->localSettingsEnabled() ? QDir(profile->absolutePath()).absoluteFilePath("oblivion.ini") - : m_LocalGameDir.absoluteFilePath("oblivion.ini"); + : localGameDirectory().absoluteFilePath("oblivion.ini"); setArchivesToKey(iniFile, "SArchiveList", list); } diff --git a/src/games/nehrim/src/nehrimdataarchives.h b/src/games/nehrim/src/nehrimdataarchives.h index 9bfd5908..2b6425c6 100644 --- a/src/games/nehrim/src/nehrimdataarchives.h +++ b/src/games/nehrim/src/nehrimdataarchives.h @@ -9,11 +9,9 @@ class NehrimDataArchives : public GamebryoDataArchives { - public: - NehrimDataArchives(const QDir& myGamesDir); + using GamebryoDataArchives::GamebryoDataArchives; -public: virtual QStringList vanillaArchives() const override; virtual QStringList archives(const MOBase::IProfile* profile) const override; From 51e8f281beb7887055c3e360b5a671a46f88c3d0 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Mika=C3=ABl=20Capelle?= Date: Sat, 22 Jun 2024 08:29:45 +0200 Subject: [PATCH 1512/1544] [game_oblivion] Update following gamebryo updates for myGamesPath() in game feature. (#25) --- src/games/oblivion/src/game_oblivion_en.ts | 4 ++-- src/games/oblivion/src/gameoblivion.cpp | 5 ++--- src/games/oblivion/src/obliviondataarchives.cpp | 8 ++------ src/games/oblivion/src/obliviondataarchives.h | 4 +--- 4 files changed, 7 insertions(+), 14 deletions(-) diff --git a/src/games/oblivion/src/game_oblivion_en.ts b/src/games/oblivion/src/game_oblivion_en.ts index ad614a85..80b1dbb0 100644 --- a/src/games/oblivion/src/game_oblivion_en.ts +++ b/src/games/oblivion/src/game_oblivion_en.ts @@ -4,12 +4,12 @@ GameOblivion - + Oblivion Support Plugin - + Adds support for the game Oblivion diff --git a/src/games/oblivion/src/gameoblivion.cpp b/src/games/oblivion/src/gameoblivion.cpp index 537948d5..3c52868d 100644 --- a/src/games/oblivion/src/gameoblivion.cpp +++ b/src/games/oblivion/src/gameoblivion.cpp @@ -30,13 +30,12 @@ bool GameOblivion::init(IOrganizer* moInfo) return false; } - auto dataArchives = std::make_shared(myGamesPath()); + auto dataArchives = std::make_shared(this); registerFeature(std::make_shared(this)); registerFeature(dataArchives); registerFeature(std::make_shared(dataArchives.get(), this)); registerFeature(std::make_shared(this)); - registerFeature( - std::make_shared(myGamesPath(), "oblivion.ini")); + registerFeature(std::make_shared(this, "oblivion.ini")); registerFeature(std::make_shared(this)); registerFeature( std::make_shared(m_Organizer->gameFeatures())); diff --git a/src/games/oblivion/src/obliviondataarchives.cpp b/src/games/oblivion/src/obliviondataarchives.cpp index cb44de13..47c3dd4c 100644 --- a/src/games/oblivion/src/obliviondataarchives.cpp +++ b/src/games/oblivion/src/obliviondataarchives.cpp @@ -1,10 +1,6 @@ #include "obliviondataarchives.h" #include -OblivionDataArchives::OblivionDataArchives(const QDir& myGamesDir) - : GamebryoDataArchives(myGamesDir) -{} - QStringList OblivionDataArchives::vanillaArchives() const { return {"Oblivion - Misc.bsa", "Oblivion - Textures - Compressed.bsa", @@ -18,7 +14,7 @@ QStringList OblivionDataArchives::archives(const MOBase::IProfile* profile) cons QString iniFile = profile->localSettingsEnabled() ? QDir(profile->absolutePath()).absoluteFilePath("oblivion.ini") - : m_LocalGameDir.absoluteFilePath("oblivion.ini"); + : localGameDirectory().absoluteFilePath("oblivion.ini"); result.append(getArchivesFromKey(iniFile, "SArchiveList")); return result; @@ -31,6 +27,6 @@ void OblivionDataArchives::writeArchiveList(MOBase::IProfile* profile, QString iniFile = profile->localSettingsEnabled() ? QDir(profile->absolutePath()).absoluteFilePath("oblivion.ini") - : m_LocalGameDir.absoluteFilePath("oblivion.ini"); + : localGameDirectory().absoluteFilePath("oblivion.ini"); setArchivesToKey(iniFile, "SArchiveList", list); } diff --git a/src/games/oblivion/src/obliviondataarchives.h b/src/games/oblivion/src/obliviondataarchives.h index a89e2c51..380f3ca0 100644 --- a/src/games/oblivion/src/obliviondataarchives.h +++ b/src/games/oblivion/src/obliviondataarchives.h @@ -9,11 +9,9 @@ class OblivionDataArchives : public GamebryoDataArchives { - public: - OblivionDataArchives(const QDir& myGamesDir); + using GamebryoDataArchives::GamebryoDataArchives; -public: virtual QStringList vanillaArchives() const override; virtual QStringList archives(const MOBase::IProfile* profile) const override; From a52476f89d446fa0470381ad3927e9ed4445de32 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Mika=C3=ABl=20Capelle?= Date: Sat, 22 Jun 2024 08:29:47 +0200 Subject: [PATCH 1513/1544] [game_skyrim] Update following gamebryo updates for myGamesPath() in game feature. (#30) --- src/games/skyrim/src/game_skyrim_en.ts | 4 ++-- src/games/skyrim/src/gameskyrim.cpp | 5 ++--- src/games/skyrim/src/skyrimdataarchives.cpp | 8 ++------ src/games/skyrim/src/skyrimdataarchives.h | 4 +--- 4 files changed, 7 insertions(+), 14 deletions(-) diff --git a/src/games/skyrim/src/game_skyrim_en.ts b/src/games/skyrim/src/game_skyrim_en.ts index df224736..1ba702c1 100644 --- a/src/games/skyrim/src/game_skyrim_en.ts +++ b/src/games/skyrim/src/game_skyrim_en.ts @@ -4,12 +4,12 @@ GameSkyrim - + Skyrim Support Plugin - + Adds support for the game Skyrim diff --git a/src/games/skyrim/src/gameskyrim.cpp b/src/games/skyrim/src/gameskyrim.cpp index 0a9b3813..4f221f34 100644 --- a/src/games/skyrim/src/gameskyrim.cpp +++ b/src/games/skyrim/src/gameskyrim.cpp @@ -41,13 +41,12 @@ bool GameSkyrim::init(IOrganizer* moInfo) return false; } - auto dataArchives = std::make_shared(myGamesPath()); + auto dataArchives = std::make_shared(this); registerFeature(std::make_shared(this)); registerFeature(dataArchives); registerFeature(std::make_shared(dataArchives.get(), this)); registerFeature(std::make_shared(this)); - registerFeature( - std::make_shared(myGamesPath(), "skyrim.ini")); + registerFeature(std::make_shared(this, "skyrim.ini")); registerFeature(std::make_shared(this)); registerFeature(std::make_shared(m_Organizer->gameFeatures())); registerFeature(std::make_shared(moInfo)); diff --git a/src/games/skyrim/src/skyrimdataarchives.cpp b/src/games/skyrim/src/skyrimdataarchives.cpp index 38551675..64221759 100644 --- a/src/games/skyrim/src/skyrimdataarchives.cpp +++ b/src/games/skyrim/src/skyrimdataarchives.cpp @@ -1,10 +1,6 @@ #include "skyrimdataarchives.h" #include -SkyrimDataArchives::SkyrimDataArchives(const QDir& myGamesDir) - : GamebryoDataArchives(myGamesDir) -{} - QStringList SkyrimDataArchives::vanillaArchives() const { return {"Skyrim - Misc.bsa", "Skyrim - Shaders.bsa", @@ -21,7 +17,7 @@ QStringList SkyrimDataArchives::archives(const MOBase::IProfile* profile) const QString iniFile = profile->localSettingsEnabled() ? QDir(profile->absolutePath()).absoluteFilePath("skyrim.ini") - : m_LocalGameDir.absoluteFilePath("skyrim.ini"); + : localGameDirectory().absoluteFilePath("skyrim.ini"); result.append(getArchivesFromKey(iniFile, "SResourceArchiveList")); result.append(getArchivesFromKey(iniFile, "SResourceArchiveList2")); @@ -35,7 +31,7 @@ void SkyrimDataArchives::writeArchiveList(MOBase::IProfile* profile, QString iniFile = profile->localSettingsEnabled() ? QDir(profile->absolutePath()).absoluteFilePath("skyrim.ini") - : m_LocalGameDir.absoluteFilePath("skyrim.ini"); + : localGameDirectory().absoluteFilePath("skyrim.ini"); if (list.length() > 255) { int splitIdx = list.lastIndexOf(",", 256); setArchivesToKey(iniFile, "SResourceArchiveList", list.mid(0, splitIdx)); diff --git a/src/games/skyrim/src/skyrimdataarchives.h b/src/games/skyrim/src/skyrimdataarchives.h index a6f074a1..b8c2ae09 100644 --- a/src/games/skyrim/src/skyrimdataarchives.h +++ b/src/games/skyrim/src/skyrimdataarchives.h @@ -9,11 +9,9 @@ class SkyrimDataArchives : public GamebryoDataArchives { - public: - SkyrimDataArchives(const QDir& myGamesDir); + using GamebryoDataArchives::GamebryoDataArchives; -public: virtual QStringList vanillaArchives() const override; virtual QStringList archives(const MOBase::IProfile* profile) const override; From 14aa8bd1a0c5463c26285c873057e844bae7a669 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Mika=C3=ABl=20Capelle?= Date: Sat, 22 Jun 2024 08:29:50 +0200 Subject: [PATCH 1514/1544] [game_skyrimse] Update following gamebryo updates for myGamesPath() in game feature. (#37) --- src/games/skyrimse/src/game_skyrimse_en.ts | 4 ++-- src/games/skyrimse/src/gameskyrimse.cpp | 10 ++-------- src/games/skyrimse/src/skyrimsedataarchives.cpp | 8 ++------ src/games/skyrimse/src/skyrimsedataarchives.h | 5 +---- 4 files changed, 7 insertions(+), 20 deletions(-) diff --git a/src/games/skyrimse/src/game_skyrimse_en.ts b/src/games/skyrimse/src/game_skyrimse_en.ts index 903011a3..53d72ca6 100644 --- a/src/games/skyrimse/src/game_skyrimse_en.ts +++ b/src/games/skyrimse/src/game_skyrimse_en.ts @@ -4,12 +4,12 @@ GameSkyrimSE - + Skyrim Special Edition Support Plugin - + Adds support for the game Skyrim Special Edition. diff --git a/src/games/skyrimse/src/gameskyrimse.cpp b/src/games/skyrimse/src/gameskyrimse.cpp index f911b94c..75197cfc 100644 --- a/src/games/skyrimse/src/gameskyrimse.cpp +++ b/src/games/skyrimse/src/gameskyrimse.cpp @@ -93,10 +93,6 @@ void GameSkyrimSE::setGamePath(const QString& path) m_GamePath = path; checkVariants(); m_MyGamesPath = determineMyGamesPath(gameDirectoryName()); - - registerFeature(std::make_shared(myGamesPath())); - registerFeature( - std::make_shared(myGamesPath(), "Skyrimcustom.ini")); } QDir GameSkyrimSE::savesDirectory() const @@ -120,11 +116,9 @@ bool GameSkyrimSE::init(IOrganizer* moInfo) return false; } - registerFeature(std::make_shared(myGamesPath())); registerFeature(std::make_shared(this)); - registerFeature(std::make_shared(myGamesPath())); - registerFeature( - std::make_shared(myGamesPath(), "Skyrimcustom.ini")); + registerFeature(std::make_shared(this)); + registerFeature(std::make_shared(this, "Skyrimcustom.ini")); registerFeature(std::make_shared(this)); registerFeature( std::make_shared(m_Organizer->gameFeatures())); diff --git a/src/games/skyrimse/src/skyrimsedataarchives.cpp b/src/games/skyrimse/src/skyrimsedataarchives.cpp index b4d338fc..d92ad212 100644 --- a/src/games/skyrimse/src/skyrimsedataarchives.cpp +++ b/src/games/skyrimse/src/skyrimsedataarchives.cpp @@ -3,10 +3,6 @@ #include "iprofile.h" #include -SkyrimSEDataArchives::SkyrimSEDataArchives(const QDir& myGamesDir) - : GamebryoDataArchives(myGamesDir) -{} - QStringList SkyrimSEDataArchives::vanillaArchives() const { return {"Skyrim - Textures0.bsa", "Skyrim - Textures1.bsa", "Skyrim - Textures2.bsa", @@ -23,7 +19,7 @@ QStringList SkyrimSEDataArchives::archives(const MOBase::IProfile* profile) cons QString iniFile = profile->localSettingsEnabled() ? QDir(profile->absolutePath()).absoluteFilePath("skyrim.ini") - : m_LocalGameDir.absoluteFilePath("skyrim.ini"); + : localGameDirectory().absoluteFilePath("skyrim.ini"); result.append(getArchivesFromKey(iniFile, "SResourceArchiveList")); result.append(getArchivesFromKey(iniFile, "SResourceArchiveList2")); @@ -37,7 +33,7 @@ void SkyrimSEDataArchives::writeArchiveList(MOBase::IProfile* profile, QString iniFile = profile->localSettingsEnabled() ? QDir(profile->absolutePath()).absoluteFilePath("skyrim.ini") - : m_LocalGameDir.absoluteFilePath("skyrim.ini"); + : localGameDirectory().absoluteFilePath("skyrim.ini"); if (list.length() > 255) { int splitIdx = list.lastIndexOf(",", 256); setArchivesToKey(iniFile, "SResourceArchiveList", list.mid(0, splitIdx)); diff --git a/src/games/skyrimse/src/skyrimsedataarchives.h b/src/games/skyrimse/src/skyrimsedataarchives.h index edd58381..b3d70c16 100644 --- a/src/games/skyrimse/src/skyrimsedataarchives.h +++ b/src/games/skyrimse/src/skyrimsedataarchives.h @@ -12,11 +12,8 @@ class IProfile; class SkyrimSEDataArchives : public GamebryoDataArchives { + using GamebryoDataArchives::GamebryoDataArchives; -public: - SkyrimSEDataArchives(const QDir& myGamesDir); - -public: virtual QStringList vanillaArchives() const override; virtual QStringList archives(const MOBase::IProfile* profile) const override; From 1a591b6ad7d3942795a8b2d6a61ad14138ea2bf0 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Mika=C3=ABl=20Capelle?= Date: Sat, 22 Jun 2024 08:29:52 +0200 Subject: [PATCH 1515/1544] [game_skyrimvr] Update following gamebryo updates for myGamesPath() in game feature. (#33) --- src/games/skyrimvr/src/game_skyrimvr_en.ts | 4 ++-- src/games/skyrimvr/src/gameskyrimvr.cpp | 5 ++--- src/games/skyrimvr/src/skyrimvrdataarchives.cpp | 8 ++------ src/games/skyrimvr/src/skyrimvrdataarchives.h | 4 +--- 4 files changed, 7 insertions(+), 14 deletions(-) diff --git a/src/games/skyrimvr/src/game_skyrimvr_en.ts b/src/games/skyrimvr/src/game_skyrimvr_en.ts index ecc3f2a7..064fb579 100644 --- a/src/games/skyrimvr/src/game_skyrimvr_en.ts +++ b/src/games/skyrimvr/src/game_skyrimvr_en.ts @@ -4,12 +4,12 @@ GameSkyrimVR - + Skyrim VR Support Plugin - + Adds support for the game Skyrim VR. diff --git a/src/games/skyrimvr/src/gameskyrimvr.cpp b/src/games/skyrimvr/src/gameskyrimvr.cpp index 114ac311..c5513ce0 100644 --- a/src/games/skyrimvr/src/gameskyrimvr.cpp +++ b/src/games/skyrimvr/src/gameskyrimvr.cpp @@ -68,9 +68,8 @@ bool GameSkyrimVR::init(IOrganizer* moInfo) } registerFeature(std::make_shared(this)); - registerFeature(std::make_shared(myGamesPath())); - registerFeature( - std::make_shared(myGamesPath(), "SkyrimVR.ini")); + registerFeature(std::make_shared(this)); + registerFeature(std::make_shared(this, "SkyrimVR.ini")); registerFeature(std::make_shared(this)); registerFeature(std::make_shared(this)); registerFeature( diff --git a/src/games/skyrimvr/src/skyrimvrdataarchives.cpp b/src/games/skyrimvr/src/skyrimvrdataarchives.cpp index 40438f7d..752aa153 100644 --- a/src/games/skyrimvr/src/skyrimvrdataarchives.cpp +++ b/src/games/skyrimvr/src/skyrimvrdataarchives.cpp @@ -3,10 +3,6 @@ #include "iprofile.h" #include -SkyrimVRDataArchives::SkyrimVRDataArchives(const QDir& myGamesDir) - : GamebryoDataArchives(myGamesDir) -{} - QStringList SkyrimVRDataArchives::vanillaArchives() const { return {"Skyrim - Textures0.bsa", "Skyrim - Textures1.bsa", "Skyrim - Textures2.bsa", @@ -24,7 +20,7 @@ QStringList SkyrimVRDataArchives::archives(const MOBase::IProfile* profile) cons QString iniFile = profile->localSettingsEnabled() ? QDir(profile->absolutePath()).absoluteFilePath("skyrimvr.ini") - : m_LocalGameDir.absoluteFilePath("skyrimvr.ini"); + : localGameDirectory().absoluteFilePath("skyrimvr.ini"); result.append(getArchivesFromKey(iniFile, "SResourceArchiveList")); result.append(getArchivesFromKey(iniFile, "SResourceArchiveList2")); @@ -38,7 +34,7 @@ void SkyrimVRDataArchives::writeArchiveList(MOBase::IProfile* profile, QString iniFile = profile->localSettingsEnabled() ? QDir(profile->absolutePath()).absoluteFilePath("skyrimvr.ini") - : m_LocalGameDir.absoluteFilePath("skyrimvr.ini"); + : localGameDirectory().absoluteFilePath("skyrimvr.ini"); if (list.length() > 255) { int splitIdx = list.lastIndexOf(",", 256); setArchivesToKey(iniFile, "SResourceArchiveList", list.mid(0, splitIdx)); diff --git a/src/games/skyrimvr/src/skyrimvrdataarchives.h b/src/games/skyrimvr/src/skyrimvrdataarchives.h index e1519ca8..be85d57c 100644 --- a/src/games/skyrimvr/src/skyrimvrdataarchives.h +++ b/src/games/skyrimvr/src/skyrimvrdataarchives.h @@ -12,11 +12,9 @@ class IProfile; class SkyrimVRDataArchives : public GamebryoDataArchives { - public: - SkyrimVRDataArchives(const QDir& myGamesDir); + using GamebryoDataArchives::GamebryoDataArchives; -public: virtual QStringList vanillaArchives() const override; virtual QStringList archives(const MOBase::IProfile* profile) const override; From d2533f0eb5c78f2f7677216af0fc1cb063135303 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Mika=C3=ABl=20Capelle?= Date: Sat, 22 Jun 2024 08:29:54 +0200 Subject: [PATCH 1516/1544] [game_starfield] Update following gamebryo updates for myGamesPath() in game feature. (#24) --- src/games/starfield/src/game_starfield_en.ts | 61 +++---------------- src/games/starfield/src/gamestarfield.cpp | 5 +- .../starfield/src/starfielddataarchives.cpp | 9 +-- .../starfield/src/starfielddataarchives.h | 18 ++---- 4 files changed, 17 insertions(+), 76 deletions(-) diff --git a/src/games/starfield/src/game_starfield_en.ts b/src/games/starfield/src/game_starfield_en.ts index 38326b0d..3113ee9d 100644 --- a/src/games/starfield/src/game_starfield_en.ts +++ b/src/games/starfield/src/game_starfield_en.ts @@ -4,95 +4,50 @@ GameStarfield - + Starfield Support Plugin - + Adds support for the game Starfield. - + Show a warning when ESP plugins are enabled in the load order. - Show a warning when light plugins are enabled in the load order. - - - - - Show a warning when overlay-flagged plugins ar enabled in the load order. - - - - Show a warning when plugins.txt management is invalid. - - Bypass check for Plugins.txt Enabler. This may be useful if you use the ASI loader. - - - - + As of this release LOOT Starfield support is minimal to nonexistant. Toggle this to enable it anyway. - + You have active ESP plugins in Starfield - - You have active ESL plugins in Starfield - - - - - You have active overlay plugins - - - - + sTestFile entries are present - - Plugins.txt Enabler missing - - - - + <p>ESP plugins are not ideal for Starfield. In addition to being unable to sort them alongside ESM or master-flagged plugins, certain record references are always kept loaded by the game. This consumes unnecessary resources and limits the game's ability to load what it needs.</p><p>Ideally, plugins should be saved as ESM files upon release. It can also be released as an ESL plugin, however there are additional concerns with the way light plugins are currently handled and should only be used when absolutely certain about what you're doing.</p><p>Notably, xEdit does not currently support saving ESP files.</p><h4>Current ESPs:</h4><p>%1</p> - - <p>Light plugins work differently in Starfield. They use a different base form ID compared with standard plugin files.</p><p>What this means is that you can't just change a standard plugin to a light plugin at will, it can and will break any dependent plugin. If you do so, be absolutely certain no other plugins use that plugin as a master.</p><p>Notably, xEdit does not currently support saving or loading ESL files under these conditions.<p><h4>Current ESLs:</h4><p>%1</p> - - - - - <p>Overlay-flagged plugins are not currently recommended. In theory, they should allow you to update existing records without utilizing additional load order slots. Unfortunately, it appears that the game still allocates the slots as if these were standard plugins. Therefore, at the moment there is no real use for this plugin flag.</p><p>Notably, xEdit does not currently support saving or loading overlay-flagged files under these conditions.</p><h4>Current Overlays:</h4><p>%1</p> - - - - + <p>You have plugin managment enabled but you still have sTestFile settings in your StarfieldCustom.ini. These must be removed or the game will not read the plugins.txt file. Management is still disabled.</p> - - - <p>You have plugin management turned on but do not have the Plugins.txt Enabler SFSE plugin installed. Plugin file management for Starfield will not work without this SFSE plugin.</p> - - StarfieldModDataContent diff --git a/src/games/starfield/src/gamestarfield.cpp b/src/games/starfield/src/gamestarfield.cpp index 77781ca8..27aca4b4 100644 --- a/src/games/starfield/src/gamestarfield.cpp +++ b/src/games/starfield/src/gamestarfield.cpp @@ -41,12 +41,11 @@ bool GameStarfield::init(IOrganizer* moInfo) return false; } - auto dataArchives = - std::make_shared(myGamesPath(), gameDirectory()); + auto dataArchives = std::make_shared(this); registerFeature(std::make_shared(this)); registerFeature(dataArchives); registerFeature( - std::make_shared(myGamesPath(), "StarfieldCustom.ini")); + std::make_shared(this, "StarfieldCustom.ini")); registerFeature(std::make_shared(this)); registerFeature( std::make_shared(m_Organizer->gameFeatures())); diff --git a/src/games/starfield/src/starfielddataarchives.cpp b/src/games/starfield/src/starfielddataarchives.cpp index 175550a7..d7eadae9 100644 --- a/src/games/starfield/src/starfielddataarchives.cpp +++ b/src/games/starfield/src/starfielddataarchives.cpp @@ -3,11 +3,6 @@ #include "iprofile.h" #include -StarfieldDataArchives::StarfieldDataArchives(const QDir& myGamesDir, - const QDir& gamePath) - : GamebryoDataArchives(myGamesDir), m_GamePath(gamePath.absolutePath()) -{} - QStringList StarfieldDataArchives::vanillaArchives() const { return {"Starfield - Animations.ba2", @@ -71,11 +66,11 @@ QStringList StarfieldDataArchives::archives(const MOBase::IProfile* profile) con { QStringList result; - QString defaultIniFile = m_GamePath.absoluteFilePath("Starfield.ini"); + QString defaultIniFile = gameDirectory().absoluteFilePath("Starfield.ini"); QString customIniFile = profile->localSettingsEnabled() ? QDir(profile->absolutePath()).absoluteFilePath("StarfieldCustom.ini") - : m_LocalGameDir.absoluteFilePath("StarfieldCustom.ini"); + : localGameDirectory().absoluteFilePath("StarfieldCustom.ini"); QStringList archiveSettings = {"SResourceArchiveList", "sResourceIndexFileList", "SResourceArchiveMemoryCacheList", "sResourceStartUpArchiveList", diff --git a/src/games/starfield/src/starfielddataarchives.h b/src/games/starfield/src/starfielddataarchives.h index f889c009..c83943f4 100644 --- a/src/games/starfield/src/starfielddataarchives.h +++ b/src/games/starfield/src/starfielddataarchives.h @@ -1,23 +1,18 @@ #ifndef STARFIELDDATAARCHIVES_H #define STARFIELDDATAARCHIVES_H -#include "gamebryodataarchives.h" - -namespace MOBase -{ -class IProfile; -} - #include #include +#include "gamebryodataarchives.h" + +class GameGamebryo; + class StarfieldDataArchives : public GamebryoDataArchives { - public: - StarfieldDataArchives(const QDir& myGamesDir, const QDir& gamePath); + using GamebryoDataArchives::GamebryoDataArchives; -public: virtual QStringList vanillaArchives() const override; virtual QStringList archives(const MOBase::IProfile* profile) const override; virtual void addArchive(MOBase::IProfile* profile, int index, @@ -25,9 +20,6 @@ public: virtual void removeArchive(MOBase::IProfile* profile, const QString& archiveName) override; -protected: - const QDir m_GamePath; - private: virtual void writeArchiveList(MOBase::IProfile* profile, const QStringList& before) override; From a0521a50f0afaa70c2b5df37e5fd621eb561de11 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Mika=C3=ABl=20Capelle?= Date: Sat, 22 Jun 2024 08:29:56 +0200 Subject: [PATCH 1517/1544] [game_ttw] Update following gamebryo updates for myGamesPath() in game feature. (#40) --- src/games/ttw/src/falloutttwdataarchives.cpp | 8 ++------ src/games/ttw/src/falloutttwdataarchives.h | 3 +-- src/games/ttw/src/game_ttw_en.ts | 6 +++--- src/games/ttw/src/gamefalloutttw.cpp | 12 ++---------- 4 files changed, 8 insertions(+), 21 deletions(-) diff --git a/src/games/ttw/src/falloutttwdataarchives.cpp b/src/games/ttw/src/falloutttwdataarchives.cpp index 1008630f..3ffb0761 100644 --- a/src/games/ttw/src/falloutttwdataarchives.cpp +++ b/src/games/ttw/src/falloutttwdataarchives.cpp @@ -1,10 +1,6 @@ #include "falloutttwdataarchives.h" #include -FalloutTTWDataArchives::FalloutTTWDataArchives(const QDir& myGamesDir) - : GamebryoDataArchives(myGamesDir) -{} - QStringList FalloutTTWDataArchives::vanillaArchives() const { return {"Fallout - Textures.bsa", "Fallout - Textures2.bsa", "Fallout - Meshes.bsa", @@ -17,7 +13,7 @@ QStringList FalloutTTWDataArchives::archives(const MOBase::IProfile* profile) co QString iniFile = profile->localSettingsEnabled() ? QDir(profile->absolutePath()).absoluteFilePath("fallout.ini") - : m_LocalGameDir.absoluteFilePath("fallout.ini"); + : localGameDirectory().absoluteFilePath("fallout.ini"); result.append(getArchivesFromKey(iniFile, "SArchiveList")); return result; @@ -30,6 +26,6 @@ void FalloutTTWDataArchives::writeArchiveList(MOBase::IProfile* profile, QString iniFile = profile->localSettingsEnabled() ? QDir(profile->absolutePath()).absoluteFilePath("fallout.ini") - : m_LocalGameDir.absoluteFilePath("fallout.ini"); + : localGameDirectory().absoluteFilePath("fallout.ini"); setArchivesToKey(iniFile, "SArchiveList", list); } diff --git a/src/games/ttw/src/falloutttwdataarchives.h b/src/games/ttw/src/falloutttwdataarchives.h index 8cb8233e..eb9d7c7d 100644 --- a/src/games/ttw/src/falloutttwdataarchives.h +++ b/src/games/ttw/src/falloutttwdataarchives.h @@ -10,9 +10,8 @@ class FalloutTTWDataArchives : public GamebryoDataArchives { public: - FalloutTTWDataArchives(const QDir& myGamesDir); + using GamebryoDataArchives::GamebryoDataArchives; -public: virtual QStringList vanillaArchives() const override; virtual QStringList archives(const MOBase::IProfile* profile) const override; diff --git a/src/games/ttw/src/game_ttw_en.ts b/src/games/ttw/src/game_ttw_en.ts index 53e2efb2..9d967f91 100644 --- a/src/games/ttw/src/game_ttw_en.ts +++ b/src/games/ttw/src/game_ttw_en.ts @@ -4,17 +4,17 @@ GameFalloutTTW - + Fallout TTW Support Plugin - + Adds support for the game Fallout TTW - + While not recommended by the TTW modding community, enables LOOT sorting diff --git a/src/games/ttw/src/gamefalloutttw.cpp b/src/games/ttw/src/gamefalloutttw.cpp index c2ca3ba1..0cf2dcd3 100644 --- a/src/games/ttw/src/gamefalloutttw.cpp +++ b/src/games/ttw/src/gamefalloutttw.cpp @@ -35,14 +35,13 @@ bool GameFalloutTTW::init(IOrganizer* moInfo) return false; } - auto dataArchives = std::make_shared(myGamesPath()); + auto dataArchives = std::make_shared(this); registerFeature(std::make_shared(this)); registerFeature(dataArchives); registerFeature( std::make_shared(dataArchives.get(), this)); registerFeature(std::make_shared(this)); - registerFeature( - std::make_shared(myGamesPath(), "fallout.ini")); + registerFeature(std::make_shared(this, "fallout.ini")); registerFeature(std::make_shared(this)); registerFeature( std::make_shared(m_Organizer->gameFeatures())); @@ -107,13 +106,6 @@ void GameFalloutTTW::setGamePath(const QString& path) m_GamePath = path; checkVariants(); m_MyGamesPath = determineMyGamesPath(gameDirectoryName()); - - auto dataArchives = std::make_shared(myGamesPath()); - registerFeature(dataArchives); - registerFeature( - std::make_shared(dataArchives.get(), this)); - registerFeature( - std::make_shared(myGamesPath(), "fallout.ini")); } QDir GameFalloutTTW::savesDirectory() const From 9a1d7b87355646bee48828999a0ac8b51c3d219d Mon Sep 17 00:00:00 2001 From: Jeremy Rimpo Date: Sat, 22 Jun 2024 01:31:56 -0500 Subject: [PATCH 1518/1544] [game_starfield] Add Creation parsing and fix issues (#25) * Add Creation parsing and fix issues - Read creations from LocalAppData - Don't include CC files in primary plugins - Don't parse CCC file if sTestFile set - Fix parsing of secondary data directories * Implement Starfield.ccc virtualization - Fix issues with core plugin LO * Reorder primary plugins to better comport with base LO --- src/games/starfield/src/gamestarfield.cpp | 109 ++++++++++++---- src/games/starfield/src/gamestarfield.h | 1 + .../starfield/src/starfieldunmanagedmods.cpp | 117 +++++++++++++++--- .../starfield/src/starfieldunmanagedmods.h | 24 +++- 4 files changed, 205 insertions(+), 46 deletions(-) diff --git a/src/games/starfield/src/gamestarfield.cpp b/src/games/starfield/src/gamestarfield.cpp index 27aca4b4..8f65fb33 100644 --- a/src/games/starfield/src/gamestarfield.cpp +++ b/src/games/starfield/src/gamestarfield.cpp @@ -28,7 +28,6 @@ #include -#include "scopeguard.h" #include "utility.h" using namespace MOBase; @@ -51,12 +50,39 @@ bool GameStarfield::init(IOrganizer* moInfo) std::make_shared(m_Organizer->gameFeatures())); registerFeature(std::make_shared(this)); registerFeature(std::make_shared(moInfo)); - registerFeature(std::make_shared(this)); + registerFeature(std::make_shared(this, localAppFolder())); registerFeature(std::make_shared(dataArchives.get(), this)); + m_Organizer->pluginList()->onRefreshed([&]() { + setCCCFile(); + }); + return true; } +/* + * This is used to write the primary plugins to a profile-based Starfield.ccc file. We + * map this into the game directory with the VFS. The game does not currently ship with + * this file but does still read it like SkyrimSE and Fallout 4. We can make use of it + * to correct the current behavior where core plugins are loaded after parsing + * plugins.txt leading to ambiguous load orders. + */ +void GameStarfield::setCCCFile() const +{ + if (m_Organizer->profilePath().isEmpty()) + return; + if (m_Organizer->pluginSetting(name(), "enable_loadorder_fix").toBool()) { + QFile cccFile(m_Organizer->profilePath() + "/Starfield.ccc"); + if (cccFile.open(QIODevice::WriteOnly)) { + auto plugins = primaryPlugins(); + for (auto plugin : plugins) { + cccFile.write(plugin.toUtf8()); + cccFile.write("\n"); + } + } + } +} + QString GameStarfield::gameName() const { return "Starfield"; @@ -129,7 +155,7 @@ QString GameStarfield::description() const MOBase::VersionInfo GameStarfield::version() const { - return VersionInfo(1, 0, 0, VersionInfo::RELEASE_FINAL); + return VersionInfo(1, 1, 0, VersionInfo::RELEASE_CANDIDATE); } QList GameStarfield::settings() const @@ -145,11 +171,18 @@ QList GameStarfield::settings() const << PluginSetting("enable_loot_sorting", tr("As of this release LOOT Starfield support is minimal to " "nonexistant. Toggle this to enable it anyway."), - false); + false) + << PluginSetting("enable_loadorder_fix", + tr("Utilize Starfield.ccc to affix core plugin load order " + "(will override existing file)."), + true); } MappingType GameStarfield::mappings() const { + if (m_Organizer->pluginSetting(name(), "enable_loadorder_fix").toBool()) { + setCCCFile(); + } MappingType result; if (testFilePlugins().isEmpty()) { for (const QString& profileFile : {"plugins.txt", "loadorder.txt"}) { @@ -158,6 +191,10 @@ MappingType GameStarfield::mappings() const false}); } } + if (m_Organizer->pluginSetting(name(), "enable_loadorder_fix").toBool()) { + result.push_back({m_Organizer->profilePath() + "/" + "Starfield.ccc", + gameDirectory().absolutePath() + "/" + "Starfield.ccc", false}); + } return result; } @@ -220,15 +257,13 @@ QStringList GameStarfield::primaryPlugins() const { QStringList plugins = {"Starfield.esm", "Constellation.esm", "OldMars.esm", "BlueprintShips-Starfield.esm", - "SFBGS003.esm", "SFBGS006.esm", - "SFBGS007.esm", "SFBGS008.esm"}; + "SFBGS007.esm", "SFBGS008.esm", + "SFBGS006.esm", "SFBGS003.esm"}; auto testPlugins = testFilePlugins(); if (loadOrderMechanism() == LoadOrderMechanism::None) { plugins << enabledPlugins(); plugins << testPlugins; - } else { - plugins << CCPlugins(); } return plugins; @@ -271,30 +306,52 @@ QStringList GameStarfield::DLCPlugins() const QStringList GameStarfield::CCPlugins() const { - QStringList plugins = {}; - QFile file(gameDirectory().absoluteFilePath("Starfield.ccc")); - if (file.open(QIODevice::ReadOnly)) { - ON_BLOCK_EXIT([&file]() { - file.close(); - }); - - if (file.size() == 0) { - return plugins; + // While the CCC file appears to be mostly legacy, we need to parse it since the game + // will still read it and there are some compatibility reason to use it for + // force-loading the core game plugins. + QStringList plugins = {}; + QStringList corePlugins = primaryPlugins() + DLCPlugins(); + if (!testFilePresent()) { + QFile file(gameDirectory().absoluteFilePath("Starfield.ccc")); + if (m_Organizer->pluginSetting(name(), "enable_loadorder_fix").toBool() && + !m_Organizer->profilePath().isEmpty()) { + file.setFileName(m_Organizer->profilePath() + "/Starfield.ccc"); } - while (!file.atEnd()) { - QByteArray line = file.readLine().trimmed(); - QString modName; - if ((line.size() > 0) && (line.at(0) != '#')) { - modName = QString::fromUtf8(line.constData()).toLower(); - } + if (file.open(QIODevice::ReadOnly)) { + if (file.size() > 0) { + 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); + if (modName.size() > 0) { + if (!plugins.contains(modName, Qt::CaseInsensitive) && + !corePlugins.contains(modName, Qt::CaseInsensitive)) { + plugins.append(modName); + } + } } } } } + + std::shared_ptr unmanagedMods = + std::static_pointer_cast( + m_Organizer->gameFeatures()->gameFeature()); + + // The ContentCatalog.txt appears to be the main repository where Starfiled stores + // info about the installed Creations. We parse this to correctly mark unmanaged mods + // as Creations. The StarfieldUnmanagedMods class handles parsing mod names and files. + if (unmanagedMods.get()) { + auto contentCatalog = unmanagedMods->parseContentCatalog(); + for (const auto& mod : contentCatalog) { + if (!plugins.contains(mod.first, Qt::CaseInsensitive)) { + plugins.append(mod.first); + } + } + } return plugins; } diff --git a/src/games/starfield/src/gamestarfield.h b/src/games/starfield/src/gamestarfield.h index 42e27487..a9d612d8 100644 --- a/src/games/starfield/src/gamestarfield.h +++ b/src/games/starfield/src/gamestarfield.h @@ -71,6 +71,7 @@ protected: private: bool activeESP() const; bool testFilePresent() const; + void setCCCFile() const; private: static const unsigned int PROBLEM_ESP = 1; diff --git a/src/games/starfield/src/starfieldunmanagedmods.cpp b/src/games/starfield/src/starfieldunmanagedmods.cpp index 037d57c3..9e2a530e 100644 --- a/src/games/starfield/src/starfieldunmanagedmods.cpp +++ b/src/games/starfield/src/starfieldunmanagedmods.cpp @@ -1,12 +1,20 @@ #include "starfieldunmanagedmods.h" -StarfieldUnmangedMods::StarfieldUnmangedMods(const GameGamebryo* game) - : GamebryoUnmangedMods(game) +#include "log.h" + +#include +#include +#include +#include + +StarfieldUnmanagedMods::StarfieldUnmanagedMods(const GameStarfield* game, + const QString& appDataFolder) + : GamebryoUnmangedMods(game), m_AppDataFolder(appDataFolder) {} -StarfieldUnmangedMods::~StarfieldUnmangedMods() {} +StarfieldUnmanagedMods::~StarfieldUnmanagedMods() {} -QStringList StarfieldUnmangedMods::mods(bool onlyOfficial) const +QStringList StarfieldUnmanagedMods::mods(bool onlyOfficial) const { QStringList result; @@ -16,11 +24,14 @@ QStringList StarfieldUnmangedMods::mods(bool onlyOfficial) const for (QString plugin : otherPlugins) { pluginList.removeAll(plugin); } - QDir dataDir(game()->dataDirectory()); - for (const QString& fileName : dataDir.entryList({"*.esp", "*.esl", "*.esm"})) { - if (!pluginList.contains(fileName, Qt::CaseInsensitive)) { - if (!onlyOfficial || pluginList.contains(fileName, Qt::CaseInsensitive)) { - result.append(fileName.chopped(4)); // trims the extension off + QMap directories = {{"data", game()->dataDirectory()}}; + directories.insert(game()->secondaryDataDirectories()); + for (QDir directory : directories) { + for (const QString& fileName : directory.entryList({"*.esp", "*.esl", "*.esm"})) { + if (!pluginList.contains(fileName, Qt::CaseInsensitive)) { + if (!onlyOfficial || pluginList.contains(fileName, Qt::CaseInsensitive)) { + result.append(fileName.chopped(4)); // trims the extension off + } } } } @@ -28,19 +39,91 @@ QStringList StarfieldUnmangedMods::mods(bool onlyOfficial) const return result; } -QStringList StarfieldUnmangedMods::secondaryFiles(const QString& modName) const +QFileInfo StarfieldUnmanagedMods::referenceFile(const QString& modName) const { - // file extension in FO4 is .ba2 instead of bsa - QStringList archives; - QDir dataDir = game()->dataDirectory(); - for (const QString& archiveName : dataDir.entryList({modName + "*.ba2"})) { - archives.append(dataDir.absoluteFilePath(archiveName)); + QFileInfoList files; + QMap directories = {{"data", game()->dataDirectory()}}; + directories.insert(game()->secondaryDataDirectories()); + for (QDir directory : directories) { + files += directory.entryInfoList(QStringList() << modName + ".es*"); + } + if (files.size() > 0) { + return files.at(0); + } else { + return QFileInfo(); } - return archives; } -QString StarfieldUnmangedMods::displayName(const QString& modName) const +std::map +StarfieldUnmanagedMods::parseContentCatalog() const { + QFile content(m_AppDataFolder + "/" + game()->gameShortName() + + "/ContentCatalog.txt"); + std::map contentCatalog; + if (content.open(QIODevice::OpenModeFlag::ReadOnly)) { + auto contentData = content.readAll(); + QJsonParseError jsonError; + QJsonDocument contentDoc = QJsonDocument::fromJson(contentData, &jsonError); + if (jsonError.error) { + MOBase::log::warn(QObject::tr("ContentCatalog.txt appears to be corrupt: %1") + .arg(jsonError.errorString())); + } else { + QJsonObject contentObj = contentDoc.object(); + for (const auto& mod : contentObj.keys()) { + if (mod == "ContentCatalog") + continue; + auto modInfo = contentObj.value(mod).toObject(); + QStringList pluginList; + QStringList files; + for (const auto& file : modInfo.value("Files").toArray()) { + QString fileName = file.toString(); + files.append(fileName); + if (fileName.endsWith(".esm", Qt::CaseInsensitive) || + fileName.endsWith(".esl", Qt::CaseInsensitive) || + fileName.endsWith(".esp", Qt::CaseInsensitive)) { + pluginList.append(fileName); + } + } + for (const auto& plugin : pluginList) { + contentCatalog[plugin] = ContentCatalog(); + contentCatalog[plugin].files = files; + contentCatalog[plugin].name = modInfo.value("Title").toString(); + } + } + } + } + return contentCatalog; +} + +QStringList StarfieldUnmanagedMods::secondaryFiles(const QString& modName) const +{ + QStringList files; + auto contentCatalog = parseContentCatalog(); + for (const auto& mod : contentCatalog) { + if (mod.first.startsWith(modName, Qt::CaseInsensitive)) { + files += mod.second.files; + break; + } + } + // file extension in FO4 is .ba2 instead of bsa + QMap directories = {{"data", game()->dataDirectory()}}; + directories.insert(game()->secondaryDataDirectories()); + for (QDir directory : directories) { + for (const QString& archiveName : directory.entryList({modName + "*.ba2"})) { + files.append(directory.absoluteFilePath(archiveName)); + } + } + return files; +} + +QString StarfieldUnmanagedMods::displayName(const QString& modName) const +{ + auto contentCatalog = parseContentCatalog(); + for (const auto& mod : contentCatalog) { + if (mod.first.startsWith(modName, Qt::CaseInsensitive)) { + return mod.second.name; + } + } // unlike in earlier games, in fallout 4 the file name doesn't correspond to // the public name return modName; diff --git a/src/games/starfield/src/starfieldunmanagedmods.h b/src/games/starfield/src/starfieldunmanagedmods.h index 3b9f2e2d..abe14ef5 100644 --- a/src/games/starfield/src/starfieldunmanagedmods.h +++ b/src/games/starfield/src/starfieldunmanagedmods.h @@ -2,17 +2,35 @@ #define STARFIELDUNMANAGEDMODS_H #include "gamebryounmanagedmods.h" +#include "gamestarfield.h" #include -class StarfieldUnmangedMods : public GamebryoUnmangedMods +#include + +class StarfieldUnmanagedMods : public GamebryoUnmangedMods { + friend class GameStarfield; + + struct ContentCatalog + { + QString name; + QStringList files; + }; + public: - StarfieldUnmangedMods(const GameGamebryo* game); - ~StarfieldUnmangedMods(); + StarfieldUnmanagedMods(const GameStarfield* game, const QString& appDataFolder); + ~StarfieldUnmanagedMods(); virtual QStringList mods(bool onlyOfficial) const override; + virtual QFileInfo referenceFile(const QString& modName) const override; virtual QStringList secondaryFiles(const QString& modName) const override; virtual QString displayName(const QString& modName) const override; + +private: + std::map parseContentCatalog() const; + +private: + QString m_AppDataFolder; }; #endif // STARFIELDUNMANAGEDMODS_H From 1d1addc0183d4fae7ee2675427e77b5df998b486 Mon Sep 17 00:00:00 2001 From: Jeremy Rimpo Date: Sun, 23 Jun 2024 04:55:08 -0500 Subject: [PATCH 1519/1544] [game_starfield] Final updates (#26) - Revert save # parse change - Work around issues with corrupted ContentCatalog.txt - Set final version --- src/games/starfield/src/gamestarfield.cpp | 2 +- src/games/starfield/src/starfieldsavegame.cpp | 4 ++-- src/games/starfield/src/starfieldunmanagedmods.cpp | 4 +++- 3 files changed, 6 insertions(+), 4 deletions(-) diff --git a/src/games/starfield/src/gamestarfield.cpp b/src/games/starfield/src/gamestarfield.cpp index 8f65fb33..cced29b4 100644 --- a/src/games/starfield/src/gamestarfield.cpp +++ b/src/games/starfield/src/gamestarfield.cpp @@ -155,7 +155,7 @@ QString GameStarfield::description() const MOBase::VersionInfo GameStarfield::version() const { - return VersionInfo(1, 1, 0, VersionInfo::RELEASE_CANDIDATE); + return VersionInfo(1, 1, 0, VersionInfo::RELEASE_FINAL); } QList GameStarfield::settings() const diff --git a/src/games/starfield/src/starfieldsavegame.cpp b/src/games/starfield/src/starfieldsavegame.cpp index 01d08229..9d5af943 100644 --- a/src/games/starfield/src/starfieldsavegame.cpp +++ b/src/games/starfield/src/starfieldsavegame.cpp @@ -61,9 +61,9 @@ void StarfieldSaveGame::fetchInformationFields( unsigned int version; // file.read(fileID, 12); headerSize = file.readInt(12); - saveNumber = file.readInt(); - saveVersion = file.readChar(); version = file.readInt(); + saveVersion = file.readChar(); + saveNumber = file.readInt(); file.read(playerName); unsigned int temp; diff --git a/src/games/starfield/src/starfieldunmanagedmods.cpp b/src/games/starfield/src/starfieldunmanagedmods.cpp index 9e2a530e..30abb389 100644 --- a/src/games/starfield/src/starfieldunmanagedmods.cpp +++ b/src/games/starfield/src/starfieldunmanagedmods.cpp @@ -61,7 +61,9 @@ StarfieldUnmanagedMods::parseContentCatalog() const "/ContentCatalog.txt"); std::map contentCatalog; if (content.open(QIODevice::OpenModeFlag::ReadOnly)) { - auto contentData = content.readAll(); + auto contentData = content.readAll(); + QString convertedData = QString::fromLatin1(contentData); + contentData = convertedData.toUtf8(); QJsonParseError jsonError; QJsonDocument contentDoc = QJsonDocument::fromJson(contentData, &jsonError); if (jsonError.error) { From 010f4d1188610c73f0ad66de4ef438d53f9dc599 Mon Sep 17 00:00:00 2001 From: Jeremy Rimpo Date: Thu, 11 Jul 2024 00:20:30 -0500 Subject: [PATCH 1520/1544] [game_starfield] Make LOOT support default (#27) --- src/games/starfield/src/gamestarfield.cpp | 9 +-------- 1 file changed, 1 insertion(+), 8 deletions(-) diff --git a/src/games/starfield/src/gamestarfield.cpp b/src/games/starfield/src/gamestarfield.cpp index cced29b4..8ee604bf 100644 --- a/src/games/starfield/src/gamestarfield.cpp +++ b/src/games/starfield/src/gamestarfield.cpp @@ -168,10 +168,6 @@ QList GameStarfield::settings() const << PluginSetting("enable_management_warnings", tr("Show a warning when plugins.txt management is invalid."), true) - << PluginSetting("enable_loot_sorting", - tr("As of this release LOOT Starfield support is minimal to " - "nonexistant. Toggle this to enable it anyway."), - false) << PluginSetting("enable_loadorder_fix", tr("Utilize Starfield.ccc to affix core plugin load order " "(will override existing file)."), @@ -357,10 +353,7 @@ QStringList GameStarfield::CCPlugins() const IPluginGame::SortMechanism GameStarfield::sortMechanism() const { - if (!testFilePresent() && - m_Organizer->pluginSetting(name(), "enable_loot_sorting").toBool()) - return IPluginGame::SortMechanism::LOOT; - return IPluginGame::SortMechanism::NONE; + return IPluginGame::SortMechanism::LOOT; } IPluginGame::LoadOrderMechanism GameStarfield::loadOrderMechanism() const From 9569c46a79f4615682bf70c327e4558f0dd0baf7 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Mika=C3=ABl=20Capelle?= Date: Fri, 19 Jul 2024 09:50:10 +0200 Subject: [PATCH 1521/1544] [game_starfield] Map Starfield.ccc to 'My Games' alongside game folder. (#28) --- src/games/starfield/src/gamestarfield.cpp | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/src/games/starfield/src/gamestarfield.cpp b/src/games/starfield/src/gamestarfield.cpp index 8ee604bf..0ab6f251 100644 --- a/src/games/starfield/src/gamestarfield.cpp +++ b/src/games/starfield/src/gamestarfield.cpp @@ -188,8 +188,12 @@ MappingType GameStarfield::mappings() const } } if (m_Organizer->pluginSetting(name(), "enable_loadorder_fix").toBool()) { + // map the Starfield.ccc from the profile to both the game folder and the My Games + // folder (used by LOOT for instance) result.push_back({m_Organizer->profilePath() + "/" + "Starfield.ccc", gameDirectory().absolutePath() + "/" + "Starfield.ccc", false}); + result.push_back({m_Organizer->profilePath() + "/" + "Starfield.ccc", + myGamesPath() + "/" + "Starfield.ccc", false}); } return result; } From fbc11d524133fd4dca15cf190e278b9a273dc376 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Mika=C3=ABl=20Capelle?= Date: Sun, 21 Jul 2024 17:04:44 +0200 Subject: [PATCH 1522/1544] [game_starfield] Update translations. (#29) --- src/games/starfield/src/game_starfield_en.ts | 28 +++++++++++++------- 1 file changed, 18 insertions(+), 10 deletions(-) diff --git a/src/games/starfield/src/game_starfield_en.ts b/src/games/starfield/src/game_starfield_en.ts index 3113ee9d..9e3e6053 100644 --- a/src/games/starfield/src/game_starfield_en.ts +++ b/src/games/starfield/src/game_starfield_en.ts @@ -4,51 +4,59 @@ GameStarfield - + Starfield Support Plugin - + Adds support for the game Starfield. - + Show a warning when ESP plugins are enabled in the load order. - + Show a warning when plugins.txt management is invalid. - - As of this release LOOT Starfield support is minimal to nonexistant. Toggle this to enable it anyway. + + Utilize Starfield.ccc to affix core plugin load order (will override existing file). - + You have active ESP plugins in Starfield - + sTestFile entries are present - + <p>ESP plugins are not ideal for Starfield. In addition to being unable to sort them alongside ESM or master-flagged plugins, certain record references are always kept loaded by the game. This consumes unnecessary resources and limits the game's ability to load what it needs.</p><p>Ideally, plugins should be saved as ESM files upon release. It can also be released as an ESL plugin, however there are additional concerns with the way light plugins are currently handled and should only be used when absolutely certain about what you're doing.</p><p>Notably, xEdit does not currently support saving ESP files.</p><h4>Current ESPs:</h4><p>%1</p> - + <p>You have plugin managment enabled but you still have sTestFile settings in your StarfieldCustom.ini. These must be removed or the game will not read the plugins.txt file. Management is still disabled.</p> + + QObject + + + ContentCatalog.txt appears to be corrupt: %1 + + + StarfieldModDataContent From 54d65a5574fdccbfa2ccea19886fe927f3fdac05 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Mika=C3=ABl=20Capelle?= Date: Mon, 29 Jul 2024 18:37:54 +0200 Subject: [PATCH 1523/1544] [game_starfield] Remove 'root' as a valid folder. (#30) --- src/games/starfield/src/starfieldmoddatachecker.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/games/starfield/src/starfieldmoddatachecker.h b/src/games/starfield/src/starfieldmoddatachecker.h index fa63e5a7..13c1fcc8 100644 --- a/src/games/starfield/src/starfieldmoddatachecker.h +++ b/src/games/starfield/src/starfieldmoddatachecker.h @@ -15,7 +15,7 @@ protected: "interface", "meshes", "geometries", "music", "scripts", "sound", "strings", "textures", "trees", "video", "materials", "sfse", "distantlod", "asi", "Tools", "MCM", "distantland", "mits", - "dllplugins", "CalienteTools", "shadersfx", "aaf", "root"}; + "dllplugins", "CalienteTools", "shadersfx", "aaf"}; return result; } virtual const FileNameSet& possibleFileExtensions() const override From f22378ca70bf8026390c478b7f0855437d62ca44 Mon Sep 17 00:00:00 2001 From: Jeremy Rimpo Date: Thu, 1 Aug 2024 21:08:42 -0500 Subject: [PATCH 1524/1544] [game_fallout4london] Initial migration from original FO4 plugin --- src/games/fallout4london/.clang-format | 41 +++ src/games/fallout4london/.gitattributes | 7 + .../.github/workflows/build.yml | 16 + .../.github/workflows/linting.yml | 16 + src/games/fallout4london/.gitignore | 5 + src/games/fallout4london/CMakeLists.txt | 10 + src/games/fallout4london/src/CMakeLists.txt | 7 + src/games/fallout4london/src/SConscript | 14 + src/games/fallout4london/src/fo4london.qrc | 5 + .../src/fo4londonbsainvalidation.cpp | 68 ++++ .../src/fo4londonbsainvalidation.h | 33 ++ .../src/fo4londondataarchives.cpp | 48 +++ .../src/fo4londondataarchives.h | 27 ++ .../src/fo4londonmoddatachecker.h | 29 ++ .../src/fo4londonmoddatacontent.h | 44 +++ .../fallout4london/src/fo4londonsavegame.cpp | 79 +++++ .../fallout4london/src/fo4londonsavegame.h | 24 ++ .../src/fo4londonscriptextender.cpp | 18 + .../src/fo4londonscriptextender.h | 17 + .../src/fo4londonunmanagedmods.cpp | 63 ++++ .../src/fo4londonunmanagedmods.h | 18 + .../fallout4london/src/game_fo4london_en.ts | 28 ++ .../fallout4london/src/gamefo4london.cpp | 335 ++++++++++++++++++ src/games/fallout4london/src/gamefo4london.h | 73 ++++ .../fallout4london/src/gamefo4london.json | 1 + .../fallout4london/src/gamefo4london.pro | 50 +++ src/games/fallout4london/src/splash.png | Bin 0 -> 52981 bytes 27 files changed, 1076 insertions(+) create mode 100644 src/games/fallout4london/.clang-format create mode 100644 src/games/fallout4london/.gitattributes create mode 100644 src/games/fallout4london/.github/workflows/build.yml create mode 100644 src/games/fallout4london/.github/workflows/linting.yml create mode 100644 src/games/fallout4london/.gitignore create mode 100644 src/games/fallout4london/CMakeLists.txt create mode 100644 src/games/fallout4london/src/CMakeLists.txt create mode 100644 src/games/fallout4london/src/SConscript create mode 100644 src/games/fallout4london/src/fo4london.qrc create mode 100644 src/games/fallout4london/src/fo4londonbsainvalidation.cpp create mode 100644 src/games/fallout4london/src/fo4londonbsainvalidation.h create mode 100644 src/games/fallout4london/src/fo4londondataarchives.cpp create mode 100644 src/games/fallout4london/src/fo4londondataarchives.h create mode 100644 src/games/fallout4london/src/fo4londonmoddatachecker.h create mode 100644 src/games/fallout4london/src/fo4londonmoddatacontent.h create mode 100644 src/games/fallout4london/src/fo4londonsavegame.cpp create mode 100644 src/games/fallout4london/src/fo4londonsavegame.h create mode 100644 src/games/fallout4london/src/fo4londonscriptextender.cpp create mode 100644 src/games/fallout4london/src/fo4londonscriptextender.h create mode 100644 src/games/fallout4london/src/fo4londonunmanagedmods.cpp create mode 100644 src/games/fallout4london/src/fo4londonunmanagedmods.h create mode 100644 src/games/fallout4london/src/game_fo4london_en.ts create mode 100644 src/games/fallout4london/src/gamefo4london.cpp create mode 100644 src/games/fallout4london/src/gamefo4london.h create mode 100644 src/games/fallout4london/src/gamefo4london.json create mode 100644 src/games/fallout4london/src/gamefo4london.pro create mode 100644 src/games/fallout4london/src/splash.png diff --git a/src/games/fallout4london/.clang-format b/src/games/fallout4london/.clang-format new file mode 100644 index 00000000..6098e1f5 --- /dev/null +++ b/src/games/fallout4london/.clang-format @@ -0,0 +1,41 @@ +--- +# We'll use defaults from the LLVM style, but with 4 columns indentation. +BasedOnStyle: LLVM +IndentWidth: 2 +--- +Language: Cpp +DeriveLineEnding: false +UseCRLF: true +DerivePointerAlignment: false +PointerAlignment: Left +AlignConsecutiveAssignments: true +AllowShortFunctionsOnASingleLine: Inline +AllowShortIfStatementsOnASingleLine: Never +AllowShortLambdasOnASingleLine: Empty +AlwaysBreakTemplateDeclarations: Yes +AccessModifierOffset: -2 +AlignTrailingComments: true +SpacesBeforeTrailingComments: 2 +NamespaceIndentation: Inner +MaxEmptyLinesToKeep: 1 +BreakBeforeBraces: Custom +BraceWrapping: + AfterCaseLabel: false + AfterClass: true + AfterControlStatement: false + AfterEnum: true + AfterFunction: true + AfterNamespace: true + AfterStruct: true + AfterUnion: true + AfterExternBlock: true + BeforeCatch: false + BeforeElse: false + BeforeLambdaBody: false + BeforeWhile: false + IndentBraces: false + SplitEmptyFunction: false + SplitEmptyRecord: false + SplitEmptyNamespace: true +ColumnLimit: 88 +ForEachMacros: ['Q_FOREACH', 'foreach'] diff --git a/src/games/fallout4london/.gitattributes b/src/games/fallout4london/.gitattributes new file mode 100644 index 00000000..f8697127 --- /dev/null +++ b/src/games/fallout4london/.gitattributes @@ -0,0 +1,7 @@ +# Set the default behavior, in case people don't have core.autocrlf set. +* text=auto + +# Explicitly declare text files you want to always be normalized and converted +# to native line endings on checkout. +*.cpp text eol=crlf +*.h text eol=crlf diff --git a/src/games/fallout4london/.github/workflows/build.yml b/src/games/fallout4london/.github/workflows/build.yml new file mode 100644 index 00000000..f84cac79 --- /dev/null +++ b/src/games/fallout4london/.github/workflows/build.yml @@ -0,0 +1,16 @@ +name: Build Fallout 4 London Plugin + +on: + push: + branches: master + pull_request: + types: [opened, synchronize, reopened] + +jobs: + build: + runs-on: windows-2022 + steps: + - name: Build Fallout 4 London Plugin + uses: ModOrganizer2/build-with-mob-action@master + with: + mo2-dependencies: cmake_common uibase game_gamebryo diff --git a/src/games/fallout4london/.github/workflows/linting.yml b/src/games/fallout4london/.github/workflows/linting.yml new file mode 100644 index 00000000..dce73090 --- /dev/null +++ b/src/games/fallout4london/.github/workflows/linting.yml @@ -0,0 +1,16 @@ +name: Lint Fallout 4 London Plugin + +on: + push: + pull_request: + types: [opened, synchronize, reopened] + +jobs: + lint: + runs-on: ubuntu-latest + steps: + - uses: actions/checkout@v3 + - name: Check format + uses: ModOrganizer2/check-formatting-action@master + with: + check-path: "." diff --git a/src/games/fallout4london/.gitignore b/src/games/fallout4london/.gitignore new file mode 100644 index 00000000..cf71be77 --- /dev/null +++ b/src/games/fallout4london/.gitignore @@ -0,0 +1,5 @@ +edit +CMakeLists.txt.user +/msbuild.log +/*std*.log +/*build diff --git a/src/games/fallout4london/CMakeLists.txt b/src/games/fallout4london/CMakeLists.txt new file mode 100644 index 00000000..31c1c8d7 --- /dev/null +++ b/src/games/fallout4london/CMakeLists.txt @@ -0,0 +1,10 @@ +cmake_minimum_required(VERSION 3.16) + +if(DEFINED DEPENDENCIES_DIR) + include(${DEPENDENCIES_DIR}/modorganizer_super/cmake_common/mo2.cmake) +else() + include(${CMAKE_CURRENT_LIST_DIR}/cmake_common/mo2.cmake) +endif() + +project(game_fallout4london) +add_subdirectory(src) diff --git a/src/games/fallout4london/src/CMakeLists.txt b/src/games/fallout4london/src/CMakeLists.txt new file mode 100644 index 00000000..6730e1d6 --- /dev/null +++ b/src/games/fallout4london/src/CMakeLists.txt @@ -0,0 +1,7 @@ +cmake_minimum_required(VERSION 3.16) + +add_library(game_fallout4london SHARED) +mo2_configure_plugin(game_fallout4london + WARNINGS OFF + PRIVATE_DEPENDS creation) +mo2_install_target(game_fallout4london) diff --git a/src/games/fallout4london/src/SConscript b/src/games/fallout4london/src/SConscript new file mode 100644 index 00000000..696562d4 --- /dev/null +++ b/src/games/fallout4london/src/SConscript @@ -0,0 +1,14 @@ +Import('qt_env') + +env = qt_env.Clone() + +# Shouldn't this be GAMEFALLOUT3_LIBRARY +env.AppendUnique(CPPDEFINES = [ 'GAMEFALLOUT4_LIBRARY' ]) + +env.RequiresGamebryo() + +lib = env.SharedLibrary('gameFallout4London', env.Glob('*.cpp')) +env.InstallModule(lib) + +res = env['QT_USED_MODULES'] +Return('res') diff --git a/src/games/fallout4london/src/fo4london.qrc b/src/games/fallout4london/src/fo4london.qrc new file mode 100644 index 00000000..8f7bb2b7 --- /dev/null +++ b/src/games/fallout4london/src/fo4london.qrc @@ -0,0 +1,5 @@ + + + splash.png + + diff --git a/src/games/fallout4london/src/fo4londonbsainvalidation.cpp b/src/games/fallout4london/src/fo4londonbsainvalidation.cpp new file mode 100644 index 00000000..32e58d53 --- /dev/null +++ b/src/games/fallout4london/src/fo4londonbsainvalidation.cpp @@ -0,0 +1,68 @@ +#include "fallout4bsainvalidation.h" + +#include "dummybsa.h" +#include "iplugingame.h" +#include "iprofile.h" +#include "registry.h" +#include +#include + +Fallout4LondonBSAInvalidation::Fallout4LondonBSAInvalidation(MOBase::DataArchives* dataArchives, + MOBase::IPluginGame const* game) + : GamebryoBSAInvalidation(dataArchives, "Fallout4Custom.ini", game) +{ + m_IniFileName = "Fallout4Custom.ini"; + m_Game = game; +} + +bool Fallout4LondonBSAInvalidation::isInvalidationBSA(const QString& bsaName) +{ + return false; +} + +QString Fallout4LondonBSAInvalidation::invalidationBSAName() const +{ + return ""; +} + +unsigned long Fallout4LondonBSAInvalidation::bsaVersion() const +{ + return 0x68; +} + +bool Fallout4LondonBSAInvalidation::prepareProfile(MOBase::IProfile* profile) +{ + bool dirty = false; + QString basePath = profile->localSettingsEnabled() + ? profile->absolutePath() + : m_Game->documentsDirectory().absolutePath(); + QString iniFilePath = basePath + "/" + m_IniFileName; + WCHAR setting[MAX_PATH]; + + if (profile->invalidationActive(nullptr)) { + // write bInvalidateOlderFiles = 1, if needed + if (!::GetPrivateProfileStringW(L"Archive", L"bInvalidateOlderFiles", L"0", setting, + MAX_PATH, iniFilePath.toStdWString().c_str()) || + wcstol(setting, nullptr, 10) != 1) { + dirty = true; + if (!MOBase::WriteRegistryValue(L"Archive", L"bInvalidateOlderFiles", L"1", + iniFilePath.toStdWString().c_str())) { + qWarning("failed to override data directory in \"%s\"", + qUtf8Printable(m_IniFileName)); + } + } + if (!::GetPrivateProfileStringW(L"Archive", L"sResourceDataDirsFinal", L"STRINGS\\", + setting, MAX_PATH, + iniFilePath.toStdWString().c_str()) || + wcscmp(setting, L"") != 0) { + dirty = true; + if (!MOBase::WriteRegistryValue(L"Archive", L"sResourceDataDirsFinal", L"", + iniFilePath.toStdWString().c_str())) { + qWarning("failed to override data directory in \"%s\"", + qUtf8Printable(m_IniFileName)); + } + } + } + + return dirty; +} diff --git a/src/games/fallout4london/src/fo4londonbsainvalidation.h b/src/games/fallout4london/src/fo4londonbsainvalidation.h new file mode 100644 index 00000000..fc5d3197 --- /dev/null +++ b/src/games/fallout4london/src/fo4londonbsainvalidation.h @@ -0,0 +1,33 @@ +#ifndef FALLOUT4BSAINVALIDATION_H +#define FALLOUT4BSAINVALIDATION_H + +#include "fallout4dataarchives.h" +#include "gamebryobsainvalidation.h" +#include +#include + +#include + +namespace MOBase +{ +class IPluginGame; +} + +class Fallout4LondonBSAInvalidation : public GamebryoBSAInvalidation +{ +public: + Fallout4LondonBSAInvalidation(MOBase::DataArchives* dataArchives, + MOBase::IPluginGame const* game); + virtual bool isInvalidationBSA(const QString& bsaName) override; + virtual bool prepareProfile(MOBase::IProfile* profile) override; + +private: + virtual QString invalidationBSAName() const override; + virtual unsigned long bsaVersion() const override; + +private: + QString m_IniFileName; + MOBase::IPluginGame const* m_Game; +}; + +#endif // FALLOUT4BSAINVALIDATION_H diff --git a/src/games/fallout4london/src/fo4londondataarchives.cpp b/src/games/fallout4london/src/fo4londondataarchives.cpp new file mode 100644 index 00000000..9320f262 --- /dev/null +++ b/src/games/fallout4london/src/fo4londondataarchives.cpp @@ -0,0 +1,48 @@ +#include "fallout4dataarchives.h" + +#include "iprofile.h" +#include + +QStringList Fallout4LondonDataArchives::vanillaArchives() const +{ + return {"Fallout4 - Textures1.ba2", "Fallout4 - Textures2.ba2", + "Fallout4 - Textures3.ba2", "Fallout4 - Textures4.ba2", + "Fallout4 - Textures5.ba2", "Fallout4 - Textures6.ba2", + "Fallout4 - Textures7.ba2", "Fallout4 - Textures8.ba2", + "Fallout4 - Textures9.ba2", "Fallout4 - Meshes.ba2", + "Fallout4 - MeshesExtra.ba2", "Fallout4 - Voices.ba2", + "Fallout4 - Sounds.ba2", "Fallout4 - Interface.ba2", + "Fallout4 - Animations.ba2", "Fallout4 - Materials.ba2", + "Fallout4 - Shaders.ba2", "Fallout4 - Startup.ba2", + "Fallout4 - Misc.ba2"}; +} + +QStringList Fallout4LondonDataArchives::archives(const MOBase::IProfile* profile) const +{ + QStringList result; + + QString iniFile = profile->localSettingsEnabled() + ? QDir(profile->absolutePath()).absoluteFilePath("fallout4.ini") + : localGameDirectory().absoluteFilePath("fallout4.ini"); + result.append(getArchivesFromKey(iniFile, "SResourceArchiveList")); + result.append(getArchivesFromKey(iniFile, "SResourceArchiveList2")); + + return result; +} + +void Fallout4LondonDataArchives::writeArchiveList(MOBase::IProfile* profile, + const QStringList& before) +{ + QString list = before.join(", "); + + QString iniFile = profile->localSettingsEnabled() + ? QDir(profile->absolutePath()).absoluteFilePath("fallout4.ini") + : localGameDirectory().absoluteFilePath("fallout4.ini"); + if (list.length() > 255) { + int splitIdx = list.lastIndexOf(",", 256); + setArchivesToKey(iniFile, "SResourceArchiveList", list.mid(0, splitIdx)); + setArchivesToKey(iniFile, "SResourceArchiveList2", list.mid(splitIdx + 2)); + } else { + setArchivesToKey(iniFile, "SResourceArchiveList", list); + } +} diff --git a/src/games/fallout4london/src/fo4londondataarchives.h b/src/games/fallout4london/src/fo4londondataarchives.h new file mode 100644 index 00000000..a9d0ef9d --- /dev/null +++ b/src/games/fallout4london/src/fo4londondataarchives.h @@ -0,0 +1,27 @@ +#ifndef FALLOUT4DATAARCHIVES_H +#define FALLOUT4DATAARCHIVES_H + +#include "gamebryodataarchives.h" + +namespace MOBase +{ +class IProfile; +} + +#include +#include + +class Fallout4LondonDataArchives : 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 // FALLOUT4DATAARCHIVES_H diff --git a/src/games/fallout4london/src/fo4londonmoddatachecker.h b/src/games/fallout4london/src/fo4londonmoddatachecker.h new file mode 100644 index 00000000..4a65789a --- /dev/null +++ b/src/games/fallout4london/src/fo4londonmoddatachecker.h @@ -0,0 +1,29 @@ +#ifndef FALLOUT4_MODATACHECKER_H +#define FALLOUT4_MODATACHECKER_H + +#include + +class Fallout4LondonModDataChecker : public GamebryoModDataChecker +{ +public: + using GamebryoModDataChecker::GamebryoModDataChecker; + +protected: + virtual const FileNameSet& possibleFolderNames() const override + { + static FileNameSet result{ + "interface", "meshes", "music", "scripts", "sound", "strings", + "textures", "trees", "video", "materials", "f4se", "distantlod", + "asi", "Tools", "MCM", "distantland", "mits", "dllplugins", + "CalienteTools", "shadersfx", "aaf"}; + return result; + } + virtual const FileNameSet& possibleFileExtensions() const override + { + static FileNameSet result{"esp", "esm", "esl", "ba2", + "modgroups", "ini", "csg", "cdx"}; + return result; + } +}; + +#endif // FALLOUT4_MODATACHECKER_H diff --git a/src/games/fallout4london/src/fo4londonmoddatacontent.h b/src/games/fallout4london/src/fo4londonmoddatacontent.h new file mode 100644 index 00000000..b1938ba9 --- /dev/null +++ b/src/games/fallout4london/src/fo4londonmoddatacontent.h @@ -0,0 +1,44 @@ +#ifndef FALLOUT4_MODDATACONTENT_H +#define FALLOUT4_MODDATACONTENT_H + +#include +#include + +class Fallout4LondonModDataContent : public GamebryoModDataContent +{ +protected: + enum Fallout4LondonContent + { + CONTENT_MATERIAL = CONTENT_NEXT_VALUE + }; + +public: + Fallout4LondonModDataContent(const MOBase::IGameFeatures* gameFeatures) + : GamebryoModDataContent(gameFeatures) + { + m_Enabled[CONTENT_SKYPROC] = false; + } + + std::vector getAllContents() const override + { + auto contents = GamebryoModDataContent::getAllContents(); + contents.push_back( + Content(CONTENT_MATERIAL, "Materials", ":/MO/gui/content/material")); + return contents; + } + + std::vector + getContentsFor(std::shared_ptr fileTree) const override + { + auto contents = GamebryoModDataContent::getContentsFor(fileTree); + for (auto e : *fileTree) { + if (e->compare("materials") == 0) { + contents.push_back(CONTENT_MATERIAL); + break; // Early break if you have nothing else to check. + } + } + return contents; + } +}; + +#endif // FALLOUT4_MODDATACONTENT_H diff --git a/src/games/fallout4london/src/fo4londonsavegame.cpp b/src/games/fallout4london/src/fo4londonsavegame.cpp new file mode 100644 index 00000000..bb8d833d --- /dev/null +++ b/src/games/fallout4london/src/fo4londonsavegame.cpp @@ -0,0 +1,79 @@ +#include "fallout4savegame.h" + +#include + +#include "gamefallout4.h" + +Fallout4LondonSaveGame::Fallout4LondonSaveGame(QString const& fileName, GameFallout4London const* game) + : GamebryoSaveGame(fileName, game, true) +{ + FileWrapper file(getFilepath(), "FO4_SAVEGAME"); + + FILETIME creationTime; + fetchInformationFields(file, m_SaveNumber, m_PCName, m_PCLevel, m_PCLocation, + creationTime); + + // A file time is a 64-bit value that represents the number of 100-nanosecond + // intervals that have elapsed since 12:00 A.M. January 1, 1601 Coordinated Universal + // Time (UTC). So we need to convert that to something useful + SYSTEMTIME ctime; + ::FileTimeToSystemTime(&creationTime, &ctime); + + setCreationTime(ctime); +} + +void Fallout4LondonSaveGame::fetchInformationFields( + FileWrapper& file, unsigned long& saveNumber, QString& playerName, + unsigned short& playerLevel, QString& playerLocation, FILETIME& creationTime) const +{ + file.skip(); // header size + file.skip(); // header version + file.read(saveNumber); + + file.read(playerName); + + unsigned long temp; + file.read(temp); + playerLevel = static_cast(temp); + file.read(playerLocation); + + QString ignore; + file.read(ignore); // playtime as ascii hh.mm.ss + file.read(ignore); // race name (i.e. BretonRace) + + file.skip(); // Player gender (0 = male) + file.skip(2); // experience gathered, experience required + + file.read(creationTime); +} + +std::unique_ptr Fallout4LondonSaveGame::fetchDataFields() const +{ + FileWrapper file(getFilepath(), "FO4_SAVEGAME"); // 10bytes + + { + QString dummyName, dummyLocation; + unsigned short dummyLevel; + unsigned long dummySaveNumber; + FILETIME dummyTime; + + fetchInformationFields(file, dummySaveNumber, dummyName, dummyLevel, dummyLocation, + dummyTime); + } + + QString ignore; + std::unique_ptr fields = std::make_unique(); + + fields->Screenshot = file.readImage(384, true); + + uint8_t saveGameVersion = file.readChar(); + file.read(ignore); // game version + file.skip(); // plugin info size + + fields->Plugins = file.readPlugins(); + if (saveGameVersion >= 68) { + fields->LightPlugins = file.readLightPlugins(); + } + + return fields; +} diff --git a/src/games/fallout4london/src/fo4londonsavegame.h b/src/games/fallout4london/src/fo4londonsavegame.h new file mode 100644 index 00000000..8b00d338 --- /dev/null +++ b/src/games/fallout4london/src/fo4londonsavegame.h @@ -0,0 +1,24 @@ +#ifndef FALLOUT4SAVEGAME_H +#define FALLOUT4SAVEGAME_H + +#include "gamebryosavegame.h" + +#include + +class GameFallout4London; + +class Fallout4LondonSaveGame : public GamebryoSaveGame +{ +public: + Fallout4LondonSaveGame(QString const& fileName, GameFallout4London const* game); + +protected: + // Fetch easy-to-access information. + void fetchInformationFields(FileWrapper& file, unsigned long& saveNumber, + QString& playerName, unsigned short& playerLevel, + QString& playerLocation, FILETIME& creationTime) const; + + std::unique_ptr fetchDataFields() const override; +}; + +#endif // FALLOUT4SAVEGAME_H diff --git a/src/games/fallout4london/src/fo4londonscriptextender.cpp b/src/games/fallout4london/src/fo4londonscriptextender.cpp new file mode 100644 index 00000000..6658d4e3 --- /dev/null +++ b/src/games/fallout4london/src/fo4londonscriptextender.cpp @@ -0,0 +1,18 @@ +#include "fallout4scriptextender.h" + +#include +#include + +Fallout4LondonScriptExtender::Fallout4LondonScriptExtender(GameGamebryo const* game) + : GamebryoScriptExtender(game) +{} + +QString Fallout4LondonScriptExtender::BinaryName() const +{ + return "f4se_loader.exe"; +} + +QString Fallout4LondonScriptExtender::PluginPath() const +{ + return "f4se/plugins"; +} diff --git a/src/games/fallout4london/src/fo4londonscriptextender.h b/src/games/fallout4london/src/fo4londonscriptextender.h new file mode 100644 index 00000000..c6e462bc --- /dev/null +++ b/src/games/fallout4london/src/fo4londonscriptextender.h @@ -0,0 +1,17 @@ +#ifndef FALLOUT4SCRIPTEXTENDER_H +#define FALLOUT4SCRIPTEXTENDER_H + +#include "gamebryoscriptextender.h" + +class GameGamebryo; + +class Fallout4LondonScriptExtender : public GamebryoScriptExtender +{ +public: + Fallout4LondonScriptExtender(GameGamebryo const* game); + + virtual QString BinaryName() const override; + virtual QString PluginPath() const override; +}; + +#endif // FALLOUT4SCRIPTEXTENDER_H diff --git a/src/games/fallout4london/src/fo4londonunmanagedmods.cpp b/src/games/fallout4london/src/fo4londonunmanagedmods.cpp new file mode 100644 index 00000000..42392aba --- /dev/null +++ b/src/games/fallout4london/src/fo4londonunmanagedmods.cpp @@ -0,0 +1,63 @@ +#include "fallout4unmanagedmods.h" + +Fallout4LondonUnmangedMods::Fallout4LondonUnmangedMods(const GameGamebryo* game) + : GamebryoUnmangedMods(game) +{} + +Fallout4LondonUnmangedMods::~Fallout4LondonUnmangedMods() {} + +QStringList Fallout4LondonUnmangedMods::mods(bool onlyOfficial) const +{ + QStringList result; + + QStringList pluginList = game()->primaryPlugins(); + QStringList otherPlugins = game()->DLCPlugins(); + otherPlugins.append(game()->CCPlugins()); + for (QString plugin : otherPlugins) { + pluginList.removeAll(plugin); + } + QDir dataDir(game()->dataDirectory()); + for (const QString& fileName : dataDir.entryList({"*.esp", "*.esl", "*.esm"})) { + if (!pluginList.contains(fileName, Qt::CaseInsensitive)) { + if (!onlyOfficial || pluginList.contains(fileName, Qt::CaseInsensitive)) { + result.append(fileName.chopped(4)); // trims the extension off + } + } + } + + return result; +} + +QStringList Fallout4LondonUnmangedMods::secondaryFiles(const QString& modName) const +{ + // file extension in FO4 is .ba2 instead of bsa + QStringList archives; + QDir dataDir = game()->dataDirectory(); + for (const QString& archiveName : dataDir.entryList({modName + "*.ba2"})) { + archives.append(dataDir.absoluteFilePath(archiveName)); + } + return archives; +} + +QString Fallout4LondonUnmangedMods::displayName(const QString& modName) const +{ + // unlike in earlier games, in fallout 4 the file name doesn't correspond to + // the public name + if (modName.compare("dlcrobot", Qt::CaseInsensitive) == 0) { + return "Automatron"; + } else if (modName.compare("dlcworkshop01", Qt::CaseInsensitive) == 0) { + return "Wasteland Workshop"; + } else if (modName.compare("dlccoast", Qt::CaseInsensitive) == 0) { + return "Far Harbor"; + } else if (modName.compare("dlcworkshop02", Qt::CaseInsensitive) == 0) { + return "Contraptions Workshop"; + } else if (modName.compare("dlcworkshop03", Qt::CaseInsensitive) == 0) { + return "Vault-Tec Workshop"; + } else if (modName.compare("dlcnukaworld", Qt::CaseInsensitive) == 0) { + return "Nuka-World"; + } else if (modName.compare("dlcultrahighresolution", Qt::CaseInsensitive) == 0) { + return "Ultra High Resolution Texture Pack"; + } else { + return modName; + } +} diff --git a/src/games/fallout4london/src/fo4londonunmanagedmods.h b/src/games/fallout4london/src/fo4londonunmanagedmods.h new file mode 100644 index 00000000..55568c9d --- /dev/null +++ b/src/games/fallout4london/src/fo4londonunmanagedmods.h @@ -0,0 +1,18 @@ +#ifndef FALLOUT4UNMANAGEDMODS_H +#define FALLOUT4UNMANAGEDMODS_H + +#include "gamebryounmanagedmods.h" +#include + +class Fallout4LondonUnmangedMods : public GamebryoUnmangedMods +{ +public: + Fallout4LondonUnmangedMods(const GameGamebryo* game); + ~Fallout4LondonUnmangedMods(); + + virtual QStringList mods(bool onlyOfficial) const override; + virtual QStringList secondaryFiles(const QString& modName) const override; + virtual QString displayName(const QString& modName) const override; +}; + +#endif // FALLOUT4UNMANAGEDMODS_H diff --git a/src/games/fallout4london/src/game_fo4london_en.ts b/src/games/fallout4london/src/game_fo4london_en.ts new file mode 100644 index 00000000..51ac1518 --- /dev/null +++ b/src/games/fallout4london/src/game_fo4london_en.ts @@ -0,0 +1,28 @@ + + + + + GameFallout4London + + + Fallout 4 Support Plugin + + + + + Adds support for the game Fallout 4. +Splash by %1 + + + + + sTestFile entries are present + + + + + <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> + + + + diff --git a/src/games/fallout4london/src/gamefo4london.cpp b/src/games/fallout4london/src/gamefo4london.cpp new file mode 100644 index 00000000..c50a40c1 --- /dev/null +++ b/src/games/fallout4london/src/gamefo4london.cpp @@ -0,0 +1,335 @@ +#include "gameFallout4London.h" + +#include "fallout4bsainvalidation.h" +#include "fallout4dataarchives.h" +#include "fallout4moddatachecker.h" +#include "fallout4moddatacontent.h" +#include "fallout4savegame.h" +#include "fallout4scriptextender.h" +#include "fallout4unmanagedmods.h" + +#include "versioninfo.h" +#include +#include +#include +#include +#include + +#include +#include +#include +#include +#include +#include +#include + +#include + +#include "scopeguard.h" + +using namespace MOBase; + +GameFallout4London::GameFallout4London() {} + +bool GameFallout4London::init(IOrganizer* moInfo) +{ + if (!GameGamebryo::init(moInfo)) { + return false; + } + + auto dataArchives = std::make_shared(this); + + registerFeature(std::make_shared(this)); + registerFeature(dataArchives); + registerFeature(std::make_shared(this, "fallout4custom.ini")); + registerFeature(std::make_shared(this)); + registerFeature( + std::make_shared(m_Organizer->gameFeatures())); + registerFeature(std::make_shared(this)); + registerFeature(std::make_shared(moInfo)); + registerFeature(std::make_shared(this)); + registerFeature(std::make_shared(dataArchives.get(), this)); + + return true; +} + +QString GameFallout4London::gameName() const +{ + return "Fallout 4"; +} + +void GameFallout4London::detectGame() +{ + m_GamePath = identifyGamePath(); + m_MyGamesPath = determineMyGamesPath("Fallout4London"); +} + +QList GameFallout4London::executables() const +{ + return QList() + << ExecutableInfo("F4SE", + findInGameFolder(m_Organizer->gameFeatures() + ->gameFeature() + ->loaderName())) + << ExecutableInfo("Fallout 4", findInGameFolder(binaryName())) + << ExecutableInfo("Fallout Launcher", findInGameFolder(getLauncherName())) + << ExecutableInfo("Creation Kit", findInGameFolder("CreationKit.exe")) + .withSteamAppId("1946160") + << ExecutableInfo("LOOT", QFileInfo(getLootPath())) + .withArgument("--game=\"Fallout4\""); +} + +QList GameFallout4London::executableForcedLoads() const +{ + return QList(); +} + +QString GameFallout4London::name() const +{ + return "Fallout 4 Support Plugin"; +} + +QString GameFallout4London::localizedName() const +{ + return tr("Fallout 4 Support Plugin"); +} + +QString GameFallout4London::author() const +{ + return "Tannin & MO2 Team"; +} + +QString GameFallout4London::description() const +{ + return tr("Adds support for the game Fallout 4.\n" + "Splash by %1") + .arg("nekoyoubi"); +} + +MOBase::VersionInfo GameFallout4London::version() const +{ + return VersionInfo(1, 8, 0, VersionInfo::RELEASE_FINAL); +} + +QList GameFallout4London::settings() const +{ + return QList(); +} + +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() + "/" + gameShortName() + "/" + 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 +GameFallout4London::makeSaveGame(QString filePath) const +{ + return std::make_shared(filePath, this); +} + +QString GameFallout4London::steamAPPId() const +{ + return "377160"; +} + +QStringList GameFallout4::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); + WCHAR value[MAX_PATH]; + DWORD length = ::GetPrivateProfileStringW( + L"General", setting.toStdWString().c_str(), L"", value, MAX_PATH, + customIni.toStdWString().c_str()); + if (length && wcscmp(value, L"") != 0) { + QString plugin = QString::fromWCharArray(value, length); + if (!plugin.isEmpty() && !plugins.contains(plugin)) + plugins.append(plugin); + } + } + } + } + return plugins; +} + +QStringList GameFallout4::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 GameFallout4::gameVariants() const +{ + return {"Regular"}; +} + +QString GameFallout4::gameShortName() const +{ + return "Fallout4"; +} + +QString GameFallout4::gameNexusName() const +{ + return "fallout4"; +} + +QStringList GameFallout4::iniFiles() const +{ + return {"fallout4.ini", "fallout4prefs.ini", "fallout4custom.ini"}; +} + +QStringList GameFallout4::DLCPlugins() const +{ + return {"dlcrobot.esm", + "dlcworkshop01.esm", + "dlccoast.esm", + "dlcworkshop02.esm", + "dlcworkshop03.esm", + "dlcnukaworld.esm", + "dlcultrahighresolution.esm"}; +} + +QStringList GameFallout4::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 GameFallout4::sortMechanism() const +{ + if (!testFilePresent()) + return IPluginGame::SortMechanism::LOOT; + return IPluginGame::SortMechanism::NONE; +} + +IPluginGame::LoadOrderMechanism GameFallout4::loadOrderMechanism() const +{ + if (!testFilePresent()) + return IPluginGame::LoadOrderMechanism::PluginsTxt; + return IPluginGame::LoadOrderMechanism::None; +} + +int GameFallout4::nexusModOrganizerID() const +{ + return 28715; +} + +int GameFallout4::nexusGameID() const +{ + return 1151; +} + +// Start Diagnose +std::vector GameFallout4::activeProblems() const +{ + std::vector result; + if (m_Organizer->managedGame() == this) { + if (testFilePresent()) + result.push_back(PROBLEM_TEST_FILE); + } + return result; +} + +bool GameFallout4::testFilePresent() const +{ + if (!testFilePlugins().isEmpty()) + return true; + return false; +} + +QString GameFallout4::shortDescription(unsigned int key) const +{ + switch (key) { + case PROBLEM_TEST_FILE: + return tr("sTestFile entries are present"); + } +} + +QString GameFallout4::fullDescription(unsigned int key) const +{ + switch (key) { + case PROBLEM_TEST_FILE: { + return tr("

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.

"); + } + } +} diff --git a/src/games/fallout4london/src/gamefo4london.h b/src/games/fallout4london/src/gamefo4london.h new file mode 100644 index 00000000..1c0856b0 --- /dev/null +++ b/src/games/fallout4london/src/gamefo4london.h @@ -0,0 +1,73 @@ +#ifndef GAMEFALLOUT4_H +#define GAMEFALLOUT4_H + +#include "gamegamebryo.h" +#include "iplugindiagnose.h" + +#include +#include + +class GameFallout4London : public GameGamebryo, public MOBase::IPluginDiagnose +{ + Q_OBJECT + Q_INTERFACES(MOBase::IPlugin MOBase::IPluginGame MOBase::IPluginDiagnose) + Q_PLUGIN_METADATA(IID "org.tannin.GameFallout4London" FILE "gamefallout4.json") + +public: + GameFallout4London(); + + virtual bool init(MOBase::IOrganizer* moInfo) override; + +public: + QStringList testFilePlugins() const; + +public: // IPluginGame interface + virtual QString gameName() const override; + virtual void detectGame() override; + virtual QList executables() const override; + virtual QList + 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 gameShortName() const override; + virtual QString gameNexusName() const override; + virtual QStringList iniFiles() const override; + virtual QStringList DLCPlugins() const override; + virtual QStringList CCPlugins() const override; + virtual SortMechanism sortMechanism() const override; + virtual LoadOrderMechanism loadOrderMechanism() const override; + virtual int nexusModOrganizerID() const override; + virtual int nexusGameID() const override; + +public: // IPluginDiagnose interface + virtual std::vector activeProblems() const override; + virtual QString shortDescription(unsigned int key) const override; + virtual QString fullDescription(unsigned int key) const override; + virtual bool hasGuidedFix(unsigned int key) const override { return false; } + virtual void startGuidedFix(unsigned int key) 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 settings() const override; + virtual MappingType mappings() const override; + +protected: + std::shared_ptr makeSaveGame(QString filePath) const override; + QString savegameExtension() const override; + QString savegameSEExtension() const override; + +private: + bool testFilePresent() const; + +private: + static const unsigned int PROBLEM_TEST_FILE = 1; +}; + +#endif // GAMEFallout4London_H diff --git a/src/games/fallout4london/src/gamefo4london.json b/src/games/fallout4london/src/gamefo4london.json new file mode 100644 index 00000000..0967ef42 --- /dev/null +++ b/src/games/fallout4london/src/gamefo4london.json @@ -0,0 +1 @@ +{} diff --git a/src/games/fallout4london/src/gamefo4london.pro b/src/games/fallout4london/src/gamefo4london.pro new file mode 100644 index 00000000..f78bc45f --- /dev/null +++ b/src/games/fallout4london/src/gamefo4london.pro @@ -0,0 +1,50 @@ +#------------------------------------------------- +# +# Project created by QtCreator 2014-11-15T15:36:33 +# +#------------------------------------------------- + + +TARGET = gameFallout3 +TEMPLATE = lib + +CONFIG += plugins +CONFIG += dll + +DEFINES += GAMEFALLOUT4_LIBRARY + +SOURCES += gamefallout4.cpp \ + fallout4bsainvalidation.cpp \ + fallout4scriptextender.cpp \ + fallout4dataarchives.cpp \ + fallout4savegame.cpp \ + fallout4savegameinfo.cpp + +HEADERS += gamefallout4.h \ + fallout4bsainvalidation.h \ + fallout4scriptextender.h \ + fallout4dataarchives.h \ + fallout4savegame.h \ + fallout4savegameinfo.h + +CONFIG(debug, debug|release) { + LIBS += -L"$${OUT_PWD}/../gameGamebryo/debug" + PRE_TARGETDEPS += \ + $$OUT_PWD/../gameGamebryo/debug/gameGamebryo.lib +} else { + LIBS += -L"$${OUT_PWD}/../gameGamebryo/release" + PRE_TARGETDEPS += \ + $$OUT_PWD/../gameGamebryo/release/gameGamebryo.lib +} + +include(../plugin_template.pri) + +INCLUDEPATH += "$${BOOSTPATH}" "$${PWD}/../gamefeatures" "$${PWD}/../gamegamebryo" + +LIBS += -ladvapi32 -lole32 -lgameGamebryo + +OTHER_FILES += \ + gamefallout4.json\ + SConscript \ + CMakeLists.txt + diff --git a/src/games/fallout4london/src/splash.png b/src/games/fallout4london/src/splash.png new file mode 100644 index 0000000000000000000000000000000000000000..d612e7b86367b35b49a4d682bb8e7abd086f3f5e GIT binary patch literal 52981 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 Ad;kCd literal 0 HcmV?d00001 From 206df2598241a9efce98a988842b108fc4083008 Mon Sep 17 00:00:00 2001 From: Jeremy Rimpo Date: Thu, 1 Aug 2024 22:37:08 -0500 Subject: [PATCH 1525/1544] [game_fallout4london] Initial implementation --- src/games/fallout4london/CMakeLists.txt | 2 +- src/games/fallout4london/src/CMakeLists.txt | 6 +- .../src/fo4londonbsainvalidation.cpp | 2 +- .../src/fo4londonbsainvalidation.h | 8 +- .../src/fo4londondataarchives.cpp | 2 +- .../src/fo4londondataarchives.h | 6 +- .../src/fo4londonmoddatachecker.h | 6 +- .../src/fo4londonmoddatacontent.h | 6 +- .../fallout4london/src/fo4londonsavegame.cpp | 4 +- .../fallout4london/src/fo4londonsavegame.h | 6 +- .../src/fo4londonscriptextender.cpp | 2 +- .../src/fo4londonscriptextender.h | 6 +- .../src/fo4londonunmanagedmods.cpp | 2 +- .../src/fo4londonunmanagedmods.h | 6 +- .../fallout4london/src/game_fo4london_en.ts | 13 +-- .../fallout4london/src/gamefo4london.cpp | 109 +++++++++++------- src/games/fallout4london/src/gamefo4london.h | 11 +- 17 files changed, 115 insertions(+), 82 deletions(-) diff --git a/src/games/fallout4london/CMakeLists.txt b/src/games/fallout4london/CMakeLists.txt index 31c1c8d7..37293c92 100644 --- a/src/games/fallout4london/CMakeLists.txt +++ b/src/games/fallout4london/CMakeLists.txt @@ -6,5 +6,5 @@ else() include(${CMAKE_CURRENT_LIST_DIR}/cmake_common/mo2.cmake) endif() -project(game_fallout4london) +project(game_fo4london) add_subdirectory(src) diff --git a/src/games/fallout4london/src/CMakeLists.txt b/src/games/fallout4london/src/CMakeLists.txt index 6730e1d6..d6e818f8 100644 --- a/src/games/fallout4london/src/CMakeLists.txt +++ b/src/games/fallout4london/src/CMakeLists.txt @@ -1,7 +1,7 @@ cmake_minimum_required(VERSION 3.16) -add_library(game_fallout4london SHARED) -mo2_configure_plugin(game_fallout4london +add_library(game_fo4london SHARED) +mo2_configure_plugin(game_fo4london WARNINGS OFF PRIVATE_DEPENDS creation) -mo2_install_target(game_fallout4london) +mo2_install_target(game_fo4london) diff --git a/src/games/fallout4london/src/fo4londonbsainvalidation.cpp b/src/games/fallout4london/src/fo4londonbsainvalidation.cpp index 32e58d53..31be0293 100644 --- a/src/games/fallout4london/src/fo4londonbsainvalidation.cpp +++ b/src/games/fallout4london/src/fo4londonbsainvalidation.cpp @@ -1,4 +1,4 @@ -#include "fallout4bsainvalidation.h" +#include "fo4londonbsainvalidation.h" #include "dummybsa.h" #include "iplugingame.h" diff --git a/src/games/fallout4london/src/fo4londonbsainvalidation.h b/src/games/fallout4london/src/fo4londonbsainvalidation.h index fc5d3197..572b211e 100644 --- a/src/games/fallout4london/src/fo4londonbsainvalidation.h +++ b/src/games/fallout4london/src/fo4londonbsainvalidation.h @@ -1,7 +1,7 @@ -#ifndef FALLOUT4BSAINVALIDATION_H -#define FALLOUT4BSAINVALIDATION_H +#ifndef FO4LONDONBSAINVALIDATION_H +#define FO4LONDONBSAINVALIDATION_H -#include "fallout4dataarchives.h" +#include "fo4londondataarchives.h" #include "gamebryobsainvalidation.h" #include #include @@ -30,4 +30,4 @@ private: MOBase::IPluginGame const* m_Game; }; -#endif // FALLOUT4BSAINVALIDATION_H +#endif // FO4LONDONBSAINVALIDATION_H diff --git a/src/games/fallout4london/src/fo4londondataarchives.cpp b/src/games/fallout4london/src/fo4londondataarchives.cpp index 9320f262..329f566a 100644 --- a/src/games/fallout4london/src/fo4londondataarchives.cpp +++ b/src/games/fallout4london/src/fo4londondataarchives.cpp @@ -1,4 +1,4 @@ -#include "fallout4dataarchives.h" +#include "fo4londondataarchives.h" #include "iprofile.h" #include diff --git a/src/games/fallout4london/src/fo4londondataarchives.h b/src/games/fallout4london/src/fo4londondataarchives.h index a9d0ef9d..7e12b83f 100644 --- a/src/games/fallout4london/src/fo4londondataarchives.h +++ b/src/games/fallout4london/src/fo4londondataarchives.h @@ -1,5 +1,5 @@ -#ifndef FALLOUT4DATAARCHIVES_H -#define FALLOUT4DATAARCHIVES_H +#ifndef FO4LONDONDATAARCHIVES_H +#define FO4LONDONDATAARCHIVES_H #include "gamebryodataarchives.h" @@ -24,4 +24,4 @@ private: const QStringList& before) override; }; -#endif // FALLOUT4DATAARCHIVES_H +#endif // FO4LONDONDATAARCHIVES_H diff --git a/src/games/fallout4london/src/fo4londonmoddatachecker.h b/src/games/fallout4london/src/fo4londonmoddatachecker.h index 4a65789a..c2762810 100644 --- a/src/games/fallout4london/src/fo4londonmoddatachecker.h +++ b/src/games/fallout4london/src/fo4londonmoddatachecker.h @@ -1,5 +1,5 @@ -#ifndef FALLOUT4_MODATACHECKER_H -#define FALLOUT4_MODATACHECKER_H +#ifndef FO4LONDON_MODATACHECKER_H +#define FO4LONDON_MODATACHECKER_H #include @@ -26,4 +26,4 @@ protected: } }; -#endif // FALLOUT4_MODATACHECKER_H +#endif // FO4LONDON_MODATACHECKER_H diff --git a/src/games/fallout4london/src/fo4londonmoddatacontent.h b/src/games/fallout4london/src/fo4londonmoddatacontent.h index b1938ba9..91838da9 100644 --- a/src/games/fallout4london/src/fo4londonmoddatacontent.h +++ b/src/games/fallout4london/src/fo4londonmoddatacontent.h @@ -1,5 +1,5 @@ -#ifndef FALLOUT4_MODDATACONTENT_H -#define FALLOUT4_MODDATACONTENT_H +#ifndef FO4LONDON_MODDATACONTENT_H +#define FO4LONDON_MODDATACONTENT_H #include #include @@ -41,4 +41,4 @@ public: } }; -#endif // FALLOUT4_MODDATACONTENT_H +#endif // FO4LONDON_MODDATACONTENT_H diff --git a/src/games/fallout4london/src/fo4londonsavegame.cpp b/src/games/fallout4london/src/fo4londonsavegame.cpp index bb8d833d..9d42f73d 100644 --- a/src/games/fallout4london/src/fo4londonsavegame.cpp +++ b/src/games/fallout4london/src/fo4londonsavegame.cpp @@ -1,8 +1,8 @@ -#include "fallout4savegame.h" +#include "fo4londonsavegame.h" #include -#include "gamefallout4.h" +#include "gamefo4london.h" Fallout4LondonSaveGame::Fallout4LondonSaveGame(QString const& fileName, GameFallout4London const* game) : GamebryoSaveGame(fileName, game, true) diff --git a/src/games/fallout4london/src/fo4londonsavegame.h b/src/games/fallout4london/src/fo4londonsavegame.h index 8b00d338..6bcdbdc6 100644 --- a/src/games/fallout4london/src/fo4londonsavegame.h +++ b/src/games/fallout4london/src/fo4londonsavegame.h @@ -1,5 +1,5 @@ -#ifndef FALLOUT4SAVEGAME_H -#define FALLOUT4SAVEGAME_H +#ifndef FO4LONDONSAVEGAME_H +#define FO4LONDONSAVEGAME_H #include "gamebryosavegame.h" @@ -21,4 +21,4 @@ protected: std::unique_ptr fetchDataFields() const override; }; -#endif // FALLOUT4SAVEGAME_H +#endif // FO4LONDONSAVEGAME_H diff --git a/src/games/fallout4london/src/fo4londonscriptextender.cpp b/src/games/fallout4london/src/fo4londonscriptextender.cpp index 6658d4e3..109ca512 100644 --- a/src/games/fallout4london/src/fo4londonscriptextender.cpp +++ b/src/games/fallout4london/src/fo4londonscriptextender.cpp @@ -1,4 +1,4 @@ -#include "fallout4scriptextender.h" +#include "fo4londonscriptextender.h" #include #include diff --git a/src/games/fallout4london/src/fo4londonscriptextender.h b/src/games/fallout4london/src/fo4londonscriptextender.h index c6e462bc..20a57e53 100644 --- a/src/games/fallout4london/src/fo4londonscriptextender.h +++ b/src/games/fallout4london/src/fo4londonscriptextender.h @@ -1,5 +1,5 @@ -#ifndef FALLOUT4SCRIPTEXTENDER_H -#define FALLOUT4SCRIPTEXTENDER_H +#ifndef FO4LONDONSCRIPTEXTENDER_H +#define FO4LONDONSCRIPTEXTENDER_H #include "gamebryoscriptextender.h" @@ -14,4 +14,4 @@ public: virtual QString PluginPath() const override; }; -#endif // FALLOUT4SCRIPTEXTENDER_H +#endif // FO4LONDONSCRIPTEXTENDER_H diff --git a/src/games/fallout4london/src/fo4londonunmanagedmods.cpp b/src/games/fallout4london/src/fo4londonunmanagedmods.cpp index 42392aba..f9a66311 100644 --- a/src/games/fallout4london/src/fo4londonunmanagedmods.cpp +++ b/src/games/fallout4london/src/fo4londonunmanagedmods.cpp @@ -1,4 +1,4 @@ -#include "fallout4unmanagedmods.h" +#include "fo4londonunmanagedmods.h" Fallout4LondonUnmangedMods::Fallout4LondonUnmangedMods(const GameGamebryo* game) : GamebryoUnmangedMods(game) diff --git a/src/games/fallout4london/src/fo4londonunmanagedmods.h b/src/games/fallout4london/src/fo4londonunmanagedmods.h index 55568c9d..1d98fea8 100644 --- a/src/games/fallout4london/src/fo4londonunmanagedmods.h +++ b/src/games/fallout4london/src/fo4londonunmanagedmods.h @@ -1,5 +1,5 @@ -#ifndef FALLOUT4UNMANAGEDMODS_H -#define FALLOUT4UNMANAGEDMODS_H +#ifndef FO4LONDONUNMANAGEDMODS_H +#define FO4LONDONUNMANAGEDMODS_H #include "gamebryounmanagedmods.h" #include @@ -15,4 +15,4 @@ public: virtual QString displayName(const QString& modName) const override; }; -#endif // FALLOUT4UNMANAGEDMODS_H +#endif // FO4LONDONUNMANAGEDMODS_H diff --git a/src/games/fallout4london/src/game_fo4london_en.ts b/src/games/fallout4london/src/game_fo4london_en.ts index 51ac1518..2e3d1dbb 100644 --- a/src/games/fallout4london/src/game_fo4london_en.ts +++ b/src/games/fallout4london/src/game_fo4london_en.ts @@ -4,23 +4,22 @@ GameFallout4London - - Fallout 4 Support Plugin + + Fallout 4 London Support Plugin - - Adds support for the game Fallout 4. -Splash by %1 + + Adds support for the game Fallout 4 London. - + sTestFile entries are present - + <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> diff --git a/src/games/fallout4london/src/gamefo4london.cpp b/src/games/fallout4london/src/gamefo4london.cpp index c50a40c1..1de84c84 100644 --- a/src/games/fallout4london/src/gamefo4london.cpp +++ b/src/games/fallout4london/src/gamefo4london.cpp @@ -1,12 +1,12 @@ -#include "gameFallout4London.h" +#include "gamefo4london.h" -#include "fallout4bsainvalidation.h" -#include "fallout4dataarchives.h" -#include "fallout4moddatachecker.h" -#include "fallout4moddatacontent.h" -#include "fallout4savegame.h" -#include "fallout4scriptextender.h" -#include "fallout4unmanagedmods.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 @@ -41,27 +41,37 @@ bool GameFallout4London::init(IOrganizer* moInfo) registerFeature(std::make_shared(this)); registerFeature(dataArchives); - registerFeature(std::make_shared(this, "fallout4custom.ini")); + registerFeature( + std::make_shared(this, "fo4londoncustom.ini")); registerFeature(std::make_shared(this)); registerFeature( std::make_shared(m_Organizer->gameFeatures())); registerFeature(std::make_shared(this)); registerFeature(std::make_shared(moInfo)); registerFeature(std::make_shared(this)); - registerFeature(std::make_shared(dataArchives.get(), this)); + registerFeature( + std::make_shared(dataArchives.get(), this)); return true; } QString GameFallout4London::gameName() const { - return "Fallout 4"; + return "Fallout 4 London"; } void GameFallout4London::detectGame() { m_GamePath = identifyGamePath(); - m_MyGamesPath = determineMyGamesPath("Fallout4London"); + m_MyGamesPath = determineMyGamesPath("Fallout4"); +} + +QString GameFallout4London::identifyGamePath() const +{ + // TODO: Add GOG support + QString path = "Software\\Bethesda Softworks\\Fallout4"; + return findInRegistry(HKEY_LOCAL_MACHINE, path.toStdWString().c_str(), + L"Installed Path"); } QList GameFallout4London::executables() const @@ -71,7 +81,7 @@ QList GameFallout4London::executables() const findInGameFolder(m_Organizer->gameFeatures() ->gameFeature() ->loaderName())) - << ExecutableInfo("Fallout 4", findInGameFolder(binaryName())) + << ExecutableInfo("Fallout 4 London", findInGameFolder(binaryName())) << ExecutableInfo("Fallout Launcher", findInGameFolder(getLauncherName())) << ExecutableInfo("Creation Kit", findInGameFolder("CreationKit.exe")) .withSteamAppId("1946160") @@ -86,29 +96,27 @@ QList GameFallout4London::executableForcedLoads() c QString GameFallout4London::name() const { - return "Fallout 4 Support Plugin"; + return "Fallout 4 London Support Plugin"; } QString GameFallout4London::localizedName() const { - return tr("Fallout 4 Support Plugin"); + return tr("Fallout 4 London Support Plugin"); } QString GameFallout4London::author() const { - return "Tannin & MO2 Team"; + return "MO2 Team"; } QString GameFallout4London::description() const { - return tr("Adds support for the game Fallout 4.\n" - "Splash by %1") - .arg("nekoyoubi"); + return tr("Adds support for the game Fallout 4 London."); } MOBase::VersionInfo GameFallout4London::version() const { - return VersionInfo(1, 8, 0, VersionInfo::RELEASE_FINAL); + return VersionInfo(0, 0, 1, VersionInfo::RELEASE_PREALPHA); } QList GameFallout4London::settings() const @@ -122,14 +130,15 @@ MappingType GameFallout4London::mappings() const if (testFilePlugins().isEmpty()) { for (const QString& profileFile : {"plugins.txt", "loadorder.txt"}) { result.push_back({m_Organizer->profilePath() + "/" + profileFile, - localAppFolder() + "/" + gameShortName() + "/" + profileFile, + localAppFolder() + "/Fallout4/" + profileFile, false}); } } return result; } -void GameFallout4London::initializeProfile(const QDir& path, ProfileSettings settings) const +void GameFallout4London::initializeProfile(const QDir& path, + ProfileSettings settings) const { if (settings.testFlag(IPluginGame::MODS)) { copyToProfile(localAppFolder() + "/Fallout4", path, "plugins.txt"); @@ -170,7 +179,7 @@ QString GameFallout4London::steamAPPId() const return "377160"; } -QStringList GameFallout4::testFilePlugins() const +QStringList GameFallout4London::testFilePlugins() const { QStringList plugins; if (m_Organizer != nullptr && m_Organizer->profile() != nullptr) { @@ -195,7 +204,7 @@ QStringList GameFallout4::testFilePlugins() const return plugins; } -QStringList GameFallout4::primaryPlugins() const +QStringList GameFallout4London::primaryPlugins() const { QStringList plugins = {"fallout4.esm", "dlcrobot.esm", "dlcworkshop01.esm", "dlccoast.esm", @@ -212,27 +221,47 @@ QStringList GameFallout4::primaryPlugins() const return plugins; } -QStringList GameFallout4::gameVariants() const +QStringList GameFallout4London::enabledPlugins() const +{ + return {"bakaframework.esm", "londonworldspace.esm", "londonworldspace-dlcblock.esp"}; +} + +QStringList GameFallout4London::gameVariants() const { return {"Regular"}; } -QString GameFallout4::gameShortName() const +QString GameFallout4London::gameShortName() const { - return "Fallout4"; + return "Fallout4London"; } -QString GameFallout4::gameNexusName() const +QStringList GameFallout4London::validShortNames() const { - return "fallout4"; + return {"Fallout4"}; } -QStringList GameFallout4::iniFiles() const +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 GameFallout4::DLCPlugins() const +QStringList GameFallout4London::DLCPlugins() const { return {"dlcrobot.esm", "dlcworkshop01.esm", @@ -243,7 +272,7 @@ QStringList GameFallout4::DLCPlugins() const "dlcultrahighresolution.esm"}; } -QStringList GameFallout4::CCPlugins() const +QStringList GameFallout4London::CCPlugins() const { QStringList plugins = {}; QFile file(gameDirectory().absoluteFilePath("Fallout4.ccc")); @@ -272,32 +301,32 @@ QStringList GameFallout4::CCPlugins() const return plugins; } -IPluginGame::SortMechanism GameFallout4::sortMechanism() const +IPluginGame::SortMechanism GameFallout4London::sortMechanism() const { if (!testFilePresent()) return IPluginGame::SortMechanism::LOOT; return IPluginGame::SortMechanism::NONE; } -IPluginGame::LoadOrderMechanism GameFallout4::loadOrderMechanism() const +IPluginGame::LoadOrderMechanism GameFallout4London::loadOrderMechanism() const { if (!testFilePresent()) return IPluginGame::LoadOrderMechanism::PluginsTxt; return IPluginGame::LoadOrderMechanism::None; } -int GameFallout4::nexusModOrganizerID() const +int GameFallout4London::nexusModOrganizerID() const { return 28715; } -int GameFallout4::nexusGameID() const +int GameFallout4London::nexusGameID() const { return 1151; } // Start Diagnose -std::vector GameFallout4::activeProblems() const +std::vector GameFallout4London::activeProblems() const { std::vector result; if (m_Organizer->managedGame() == this) { @@ -307,14 +336,14 @@ std::vector GameFallout4::activeProblems() const return result; } -bool GameFallout4::testFilePresent() const +bool GameFallout4London::testFilePresent() const { if (!testFilePlugins().isEmpty()) return true; return false; } -QString GameFallout4::shortDescription(unsigned int key) const +QString GameFallout4London::shortDescription(unsigned int key) const { switch (key) { case PROBLEM_TEST_FILE: @@ -322,7 +351,7 @@ QString GameFallout4::shortDescription(unsigned int key) const } } -QString GameFallout4::fullDescription(unsigned int key) const +QString GameFallout4London::fullDescription(unsigned int key) const { switch (key) { case PROBLEM_TEST_FILE: { diff --git a/src/games/fallout4london/src/gamefo4london.h b/src/games/fallout4london/src/gamefo4london.h index 1c0856b0..fc0c85f2 100644 --- a/src/games/fallout4london/src/gamefo4london.h +++ b/src/games/fallout4london/src/gamefo4london.h @@ -1,5 +1,5 @@ -#ifndef GAMEFALLOUT4_H -#define GAMEFALLOUT4_H +#ifndef GAMEFO4LONDON_H +#define GAMEFO4LONDON_H #include "gamegamebryo.h" #include "iplugindiagnose.h" @@ -11,7 +11,7 @@ class GameFallout4London : public GameGamebryo, public MOBase::IPluginDiagnose { Q_OBJECT Q_INTERFACES(MOBase::IPlugin MOBase::IPluginGame MOBase::IPluginDiagnose) - Q_PLUGIN_METADATA(IID "org.tannin.GameFallout4London" FILE "gamefallout4.json") + Q_PLUGIN_METADATA(IID "org.tannin.GameFallout4London" FILE "gamefo4london.json") public: GameFallout4London(); @@ -23,6 +23,7 @@ public: public: // IPluginGame interface virtual QString gameName() const override; + virtual QString identifyGamePath() const override; virtual void detectGame() override; virtual QList executables() const override; virtual QList @@ -31,9 +32,13 @@ public: // IPluginGame interface ProfileSettings settings) const override; virtual QString steamAPPId() const override; virtual QStringList primaryPlugins() const override; + virtual QStringList enabledPlugins() const override; virtual QStringList gameVariants() const override; virtual QString gameShortName() const override; + virtual QStringList validShortNames() const override; virtual QString gameNexusName() const override; + virtual QString binaryName() const override; + virtual QString getLauncherName() const override; virtual QStringList iniFiles() const override; virtual QStringList DLCPlugins() const override; virtual QStringList CCPlugins() const override; From 1f7a68f1f542eae30619fbb624d04c820a145191 Mon Sep 17 00:00:00 2001 From: Jeremy Rimpo Date: Thu, 1 Aug 2024 22:38:59 -0500 Subject: [PATCH 1526/1544] [game_fallout4london] Clang pass --- src/games/fallout4london/src/fo4londonbsainvalidation.cpp | 4 ++-- src/games/fallout4london/src/fo4londonbsainvalidation.h | 2 +- src/games/fallout4london/src/fo4londondataarchives.cpp | 2 +- src/games/fallout4london/src/fo4londonsavegame.cpp | 6 ++++-- src/games/fallout4london/src/gamefo4london.cpp | 3 +-- 5 files changed, 9 insertions(+), 8 deletions(-) diff --git a/src/games/fallout4london/src/fo4londonbsainvalidation.cpp b/src/games/fallout4london/src/fo4londonbsainvalidation.cpp index 31be0293..41192fc7 100644 --- a/src/games/fallout4london/src/fo4londonbsainvalidation.cpp +++ b/src/games/fallout4london/src/fo4londonbsainvalidation.cpp @@ -7,8 +7,8 @@ #include #include -Fallout4LondonBSAInvalidation::Fallout4LondonBSAInvalidation(MOBase::DataArchives* dataArchives, - MOBase::IPluginGame const* game) +Fallout4LondonBSAInvalidation::Fallout4LondonBSAInvalidation( + MOBase::DataArchives* dataArchives, MOBase::IPluginGame const* game) : GamebryoBSAInvalidation(dataArchives, "Fallout4Custom.ini", game) { m_IniFileName = "Fallout4Custom.ini"; diff --git a/src/games/fallout4london/src/fo4londonbsainvalidation.h b/src/games/fallout4london/src/fo4londonbsainvalidation.h index 572b211e..5f5294bf 100644 --- a/src/games/fallout4london/src/fo4londonbsainvalidation.h +++ b/src/games/fallout4london/src/fo4londonbsainvalidation.h @@ -17,7 +17,7 @@ class Fallout4LondonBSAInvalidation : public GamebryoBSAInvalidation { public: Fallout4LondonBSAInvalidation(MOBase::DataArchives* dataArchives, - MOBase::IPluginGame const* game); + MOBase::IPluginGame const* game); virtual bool isInvalidationBSA(const QString& bsaName) override; virtual bool prepareProfile(MOBase::IProfile* profile) override; diff --git a/src/games/fallout4london/src/fo4londondataarchives.cpp b/src/games/fallout4london/src/fo4londondataarchives.cpp index 329f566a..e631f757 100644 --- a/src/games/fallout4london/src/fo4londondataarchives.cpp +++ b/src/games/fallout4london/src/fo4londondataarchives.cpp @@ -31,7 +31,7 @@ QStringList Fallout4LondonDataArchives::archives(const MOBase::IProfile* profile } void Fallout4LondonDataArchives::writeArchiveList(MOBase::IProfile* profile, - const QStringList& before) + const QStringList& before) { QString list = before.join(", "); diff --git a/src/games/fallout4london/src/fo4londonsavegame.cpp b/src/games/fallout4london/src/fo4londonsavegame.cpp index 9d42f73d..b1c7528e 100644 --- a/src/games/fallout4london/src/fo4londonsavegame.cpp +++ b/src/games/fallout4london/src/fo4londonsavegame.cpp @@ -4,7 +4,8 @@ #include "gamefo4london.h" -Fallout4LondonSaveGame::Fallout4LondonSaveGame(QString const& fileName, GameFallout4London const* game) +Fallout4LondonSaveGame::Fallout4LondonSaveGame(QString const& fileName, + GameFallout4London const* game) : GamebryoSaveGame(fileName, game, true) { FileWrapper file(getFilepath(), "FO4_SAVEGAME"); @@ -47,7 +48,8 @@ void Fallout4LondonSaveGame::fetchInformationFields( file.read(creationTime); } -std::unique_ptr Fallout4LondonSaveGame::fetchDataFields() const +std::unique_ptr +Fallout4LondonSaveGame::fetchDataFields() const { FileWrapper file(getFilepath(), "FO4_SAVEGAME"); // 10bytes diff --git a/src/games/fallout4london/src/gamefo4london.cpp b/src/games/fallout4london/src/gamefo4london.cpp index 1de84c84..ad0522d5 100644 --- a/src/games/fallout4london/src/gamefo4london.cpp +++ b/src/games/fallout4london/src/gamefo4london.cpp @@ -130,8 +130,7 @@ MappingType GameFallout4London::mappings() const if (testFilePlugins().isEmpty()) { for (const QString& profileFile : {"plugins.txt", "loadorder.txt"}) { result.push_back({m_Organizer->profilePath() + "/" + profileFile, - localAppFolder() + "/Fallout4/" + profileFile, - false}); + localAppFolder() + "/Fallout4/" + profileFile, false}); } } return result; From 0b0c9bfc77e09bfadb6d10fb2b6ef4ef8b9a2d42 Mon Sep 17 00:00:00 2001 From: Jeremy Rimpo Date: Sat, 28 Sep 2024 12:59:03 -0500 Subject: [PATCH 1527/1544] [game_starfield] Add support for the vehicle update (#31) - New save format (v140) which adds another plugin list flag for 'is custom plugin'; remaining changes are compatible with existing parser - New core plugin (SFBGS004.esm) --- src/games/starfield/src/game_starfield_en.ts | 8 ++++---- src/games/starfield/src/gamestarfield.cpp | 3 ++- src/games/starfield/src/starfieldsavegame.cpp | 6 +++++- 3 files changed, 11 insertions(+), 6 deletions(-) diff --git a/src/games/starfield/src/game_starfield_en.ts b/src/games/starfield/src/game_starfield_en.ts index 9e3e6053..bedbe796 100644 --- a/src/games/starfield/src/game_starfield_en.ts +++ b/src/games/starfield/src/game_starfield_en.ts @@ -29,22 +29,22 @@
- + You have active ESP plugins in Starfield - + sTestFile entries are present - + <p>ESP plugins are not ideal for Starfield. In addition to being unable to sort them alongside ESM or master-flagged plugins, certain record references are always kept loaded by the game. This consumes unnecessary resources and limits the game's ability to load what it needs.</p><p>Ideally, plugins should be saved as ESM files upon release. It can also be released as an ESL plugin, however there are additional concerns with the way light plugins are currently handled and should only be used when absolutely certain about what you're doing.</p><p>Notably, xEdit does not currently support saving ESP files.</p><h4>Current ESPs:</h4><p>%1</p> - + <p>You have plugin managment enabled but you still have sTestFile settings in your StarfieldCustom.ini. These must be removed or the game will not read the plugins.txt file. Management is still disabled.</p> diff --git a/src/games/starfield/src/gamestarfield.cpp b/src/games/starfield/src/gamestarfield.cpp index 0ab6f251..e4984421 100644 --- a/src/games/starfield/src/gamestarfield.cpp +++ b/src/games/starfield/src/gamestarfield.cpp @@ -258,7 +258,8 @@ QStringList GameStarfield::primaryPlugins() const QStringList plugins = {"Starfield.esm", "Constellation.esm", "OldMars.esm", "BlueprintShips-Starfield.esm", "SFBGS007.esm", "SFBGS008.esm", - "SFBGS006.esm", "SFBGS003.esm"}; + "SFBGS006.esm", "SFBGS003.esm", + "SFBGS004.esm"}; auto testPlugins = testFilePlugins(); if (loadOrderMechanism() == LoadOrderMechanism::None) { diff --git a/src/games/starfield/src/starfieldsavegame.cpp b/src/games/starfield/src/starfieldsavegame.cpp index 9d5af943..5240837e 100644 --- a/src/games/starfield/src/starfieldsavegame.cpp +++ b/src/games/starfield/src/starfieldsavegame.cpp @@ -104,7 +104,11 @@ std::unique_ptr StarfieldSaveGame::fetchDataFields dummyLocation, dummyTime); } - bool extraInfo = saveVersion >= 122; + int extraInfo = 0; + if (saveVersion >= 122) + extraInfo = 1; + if (saveVersion >= 140) + extraInfo = 2; QStringList gamePlugins = m_Game->primaryPlugins() + m_Game->enabledPlugins(); QString ignore; From 758c20a625cd3dc23971be6f9280a09438ff9f8d Mon Sep 17 00:00:00 2001 From: Jeremy Rimpo Date: Tue, 1 Oct 2024 03:13:55 -0500 Subject: [PATCH 1528/1544] [game_fallout4london] Fix cmake for mob build --- src/games/fallout4london/CMakeLists.txt | 2 +- src/games/fallout4london/src/game_fo4london_en.ts | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/src/games/fallout4london/CMakeLists.txt b/src/games/fallout4london/CMakeLists.txt index 37293c92..31c1c8d7 100644 --- a/src/games/fallout4london/CMakeLists.txt +++ b/src/games/fallout4london/CMakeLists.txt @@ -6,5 +6,5 @@ else() include(${CMAKE_CURRENT_LIST_DIR}/cmake_common/mo2.cmake) endif() -project(game_fo4london) +project(game_fallout4london) add_subdirectory(src) diff --git a/src/games/fallout4london/src/game_fo4london_en.ts b/src/games/fallout4london/src/game_fo4london_en.ts index 2e3d1dbb..73a7ac21 100644 --- a/src/games/fallout4london/src/game_fo4london_en.ts +++ b/src/games/fallout4london/src/game_fo4london_en.ts @@ -14,12 +14,12 @@ - + sTestFile entries are present - + <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> From a8ad92c1d534607875575350234e5bb0bf527094 Mon Sep 17 00:00:00 2001 From: Jeremy Rimpo Date: Thu, 3 Oct 2024 02:48:33 -0500 Subject: [PATCH 1529/1544] Blueprint plugin support (#59) * Add support for the vehicle update * New save format (v140) which adds another plugin list flag for 'is custom plugin'; remaining changes are compatible with existing parser --- src/gamebryo/gamebryogameplugins.cpp | 10 -------- src/gamebryo/gamebryogameplugins.h | 2 -- src/gamebryo/gamebryosavegame.cpp | 38 ++++++++++++++++------------ src/gamebryo/gamebryosavegame.h | 8 +++--- 4 files changed, 26 insertions(+), 32 deletions(-) diff --git a/src/gamebryo/gamebryogameplugins.cpp b/src/gamebryo/gamebryogameplugins.cpp index fc28981c..9910f118 100644 --- a/src/gamebryo/gamebryogameplugins.cpp +++ b/src/gamebryo/gamebryogameplugins.cpp @@ -246,13 +246,3 @@ QStringList GamebryoGamePlugins::readPluginList(MOBase::IPluginList* pluginList) return primary + plugins; } - -bool GamebryoGamePlugins::lightPluginsAreSupported() -{ - return false; -} - -bool GamebryoGamePlugins::mediumPluginsAreSupported() -{ - return false; -} diff --git a/src/gamebryo/gamebryogameplugins.h b/src/gamebryo/gamebryogameplugins.h index c2a6140e..01879b76 100644 --- a/src/gamebryo/gamebryogameplugins.h +++ b/src/gamebryo/gamebryogameplugins.h @@ -14,8 +14,6 @@ public: virtual void writePluginLists(const MOBase::IPluginList* pluginList) override; virtual void readPluginLists(MOBase::IPluginList* pluginList) override; virtual QStringList getLoadOrder() override; - virtual bool lightPluginsAreSupported() override; - virtual bool mediumPluginsAreSupported() override; protected: MOBase::IOrganizer* organizer() const { return m_Organizer; } diff --git a/src/gamebryo/gamebryosavegame.cpp b/src/gamebryo/gamebryosavegame.cpp index 978d3751..596b19b5 100644 --- a/src/gamebryo/gamebryosavegame.cpp +++ b/src/gamebryo/gamebryosavegame.cpp @@ -509,8 +509,7 @@ float_t GamebryoSaveGame::FileWrapper::readFloat(int bytesToIgnore) } } -QStringList GamebryoSaveGame::FileWrapper::readPlugins(int bytesToIgnore, - bool extraData, +QStringList GamebryoSaveGame::FileWrapper::readPlugins(int bytesToIgnore, int extraData, const QStringList& corePlugins) { if (m_CompressionType == 0) { @@ -529,7 +528,7 @@ QStringList GamebryoSaveGame::FileWrapper::readPlugins(int bytesToIgnore, } QStringList -GamebryoSaveGame::FileWrapper::readLightPlugins(int bytesToIgnore, bool extraData, +GamebryoSaveGame::FileWrapper::readLightPlugins(int bytesToIgnore, int extraData, const QStringList& corePlugins) { if (m_CompressionType == 0) { @@ -548,7 +547,7 @@ GamebryoSaveGame::FileWrapper::readLightPlugins(int bytesToIgnore, bool extraDat } QStringList -GamebryoSaveGame::FileWrapper::readMediumPlugins(int bytesToIgnore, bool extraData, +GamebryoSaveGame::FileWrapper::readMediumPlugins(int bytesToIgnore, int extraData, const QStringList& corePlugins) { if (m_CompressionType != 1) { @@ -561,8 +560,7 @@ GamebryoSaveGame::FileWrapper::readMediumPlugins(int bytesToIgnore, bool extraDa } } -QStringList GamebryoSaveGame::FileWrapper::readPluginData(uint32_t count, - bool extraData, +QStringList GamebryoSaveGame::FileWrapper::readPluginData(uint32_t count, int extraData, const QStringList corePlugins) { QStringList plugins; @@ -578,16 +576,24 @@ QStringList GamebryoSaveGame::FileWrapper::readPluginData(uint32_t count, QString name; read(name); plugins.push_back(name); - if (extraData && !corePlugins.contains(name)) { - QString creationName; - QString creationId; - uint16_t flagsSize; - uint8_t isCreation; - read(creationName); - read(creationId); - readQDataStream(*m_Data, flagsSize); - skipQDataStream(*m_Data, flagsSize); - readQDataStream(*m_Data, isCreation); + bool isCustomPlugin; + if (extraData) { + if (extraData > 1) { + readQDataStream(*m_Data, isCustomPlugin); + } else { + isCustomPlugin = !corePlugins.contains(name); + } + if (isCustomPlugin) { + QString creationName; + QString creationId; + uint16_t flagsSize; + uint8_t isCreation; + read(creationName); + read(creationId); + readQDataStream(*m_Data, flagsSize); + skipQDataStream(*m_Data, flagsSize); + readQDataStream(*m_Data, isCreation); + } } } } diff --git a/src/gamebryo/gamebryosavegame.h b/src/gamebryo/gamebryosavegame.h index 114a8e9b..44d05848 100644 --- a/src/gamebryo/gamebryosavegame.h +++ b/src/gamebryo/gamebryosavegame.h @@ -167,15 +167,15 @@ protected: float_t readFloat(int bytesToIgnore = 0); /* Read the plugin list */ - QStringList readPlugins(int bytesToIgnore = 0, bool extraData = false, + QStringList readPlugins(int bytesToIgnore = 0, int extraData = 0, const QStringList& corePlugins = {}); /* Read the light plugin list */ - QStringList readLightPlugins(int bytesToIgnore = 0, bool extraData = false, + QStringList readLightPlugins(int bytesToIgnore = 0, int extraData = 0, const QStringList& corePlugins = {}); /* Read the medium plugin list */ - QStringList readMediumPlugins(int bytesToIgnore = 0, bool extraData = false, + QStringList readMediumPlugins(int bytesToIgnore = 0, int extraData = 0, const QStringList& corePlugins = {}); void close(); @@ -198,7 +198,7 @@ protected: void skipQDataStream(QDataStream& data, std::size_t length); - QStringList readPluginData(uint32_t count, bool extraData, + QStringList readPluginData(uint32_t count, int extraData, const QStringList corePlugins); }; From 3416f9436affad943f3f0a5aa9e2bd34da03188a Mon Sep 17 00:00:00 2001 From: RJ <122295667+Liderate@users.noreply.github.com> Date: Thu, 3 Oct 2024 03:51:11 -0400 Subject: [PATCH 1530/1544] [game_fallout76] General Plugin Cleanup (#7) * Add steamAPPId, install path detection, disable sort button, remove references to script extender * Remove save game files * Rename some Fallout 4 plugin leftovers, remove f4se as valid folder --------- Co-authored-by: RJ --- .../fallout76/src/fallout76moddatachecker.h | 34 +++++--- .../fallout76/src/fallout76moddatacontent.h | 8 +- src/games/fallout76/src/fallout76savegame.cpp | 77 ------------------- src/games/fallout76/src/fallout76savegame.h | 24 ------ .../fallout76/src/fallout76savegameinfo.cpp | 10 --- .../fallout76/src/fallout76savegameinfo.h | 15 ---- .../fallout76/src/fallout76scriptextender.cpp | 18 ----- .../fallout76/src/fallout76scriptextender.h | 17 ---- src/games/fallout76/src/gamefallout76.cpp | 36 +++++---- src/games/fallout76/src/gamefallout76.h | 5 +- 10 files changed, 52 insertions(+), 192 deletions(-) delete mode 100644 src/games/fallout76/src/fallout76savegame.cpp delete mode 100644 src/games/fallout76/src/fallout76savegame.h delete mode 100644 src/games/fallout76/src/fallout76savegameinfo.cpp delete mode 100644 src/games/fallout76/src/fallout76savegameinfo.h delete mode 100644 src/games/fallout76/src/fallout76scriptextender.cpp delete mode 100644 src/games/fallout76/src/fallout76scriptextender.h diff --git a/src/games/fallout76/src/fallout76moddatachecker.h b/src/games/fallout76/src/fallout76moddatachecker.h index 4ccf6f31..26acc2a3 100644 --- a/src/games/fallout76/src/fallout76moddatachecker.h +++ b/src/games/fallout76/src/fallout76moddatachecker.h @@ -1,5 +1,5 @@ -#ifndef FALLOUT4_MODATACHECKER_H -#define FALLOUT4_MODATACHECKER_H +#ifndef FALLOUT76_MODATACHECKER_H +#define FALLOUT76_MODATACHECKER_H #include @@ -11,13 +11,27 @@ public: protected: virtual const FileNameSet& possibleFolderNames() const override { - static FileNameSet result{ - "interface", "meshes", "music", "scripts", - "sound", "strings", "textures", "trees", - "video", "materials", "f4se", "distantlod", - "asi", "Tools", "MCM", "distantland", - "mits", "dllplugins", "CalienteTools", "NetScriptFramework", - "shadersfx", "aaf"}; + static FileNameSet result{"interface", + "meshes", + "music", + "scripts", + "sound", + "strings", + "textures", + "trees", + "video", + "materials", + "distantlod", + "asi", + "Tools", + "MCM", + "distantland", + "mits", + "dllplugins", + "CalienteTools", + "NetScriptFramework", + "shadersfx", + "aaf"}; return result; } virtual const FileNameSet& possibleFileExtensions() const override @@ -27,4 +41,4 @@ protected: } }; -#endif // FALLOUT4_MODATACHECKER_H +#endif // FALLOUT76_MODATACHECKER_H diff --git a/src/games/fallout76/src/fallout76moddatacontent.h b/src/games/fallout76/src/fallout76moddatacontent.h index 54ba419f..df9f5752 100644 --- a/src/games/fallout76/src/fallout76moddatacontent.h +++ b/src/games/fallout76/src/fallout76moddatacontent.h @@ -1,5 +1,5 @@ -#ifndef FALLOUT4_MODDATACONTENT_H -#define FALLOUT4_MODDATACONTENT_H +#ifndef FALLOUT76_MODDATACONTENT_H +#define FALLOUT76_MODDATACONTENT_H #include #include @@ -7,7 +7,7 @@ class Fallout76ModDataContent : public GamebryoModDataContent { protected: - enum Fallout4Content + enum Fallout76Content { CONTENT_MATERIAL = CONTENT_NEXT_VALUE }; @@ -41,4 +41,4 @@ public: } }; -#endif // FALLOUT4_MODDATACONTENT_H +#endif // FALLOUT76_MODDATACONTENT_H diff --git a/src/games/fallout76/src/fallout76savegame.cpp b/src/games/fallout76/src/fallout76savegame.cpp deleted file mode 100644 index 7d00a815..00000000 --- a/src/games/fallout76/src/fallout76savegame.cpp +++ /dev/null @@ -1,77 +0,0 @@ -#include "fallout76savegame.h" - -#include "gamefallout76.h" - -Fallout76SaveGame::Fallout76SaveGame(QString const& fileName, GameFallout76 const* game) - : GamebryoSaveGame(fileName, game, true) -{ - FileWrapper file(fileName, "FO76_SAVEGAME"); - - FILETIME ftime; - fetchInformationFields(file, m_PCName, m_PCLevel, m_PCLocation, m_SaveNumber, ftime); - - // A file time is a 64-bit value that represents the number of 100-nanosecond - // intervals that have elapsed since 12:00 A.M. January 1, 1601 Coordinated Universal - // Time (UTC). So we need to convert that to something useful - SYSTEMTIME ctime; - ::FileTimeToSystemTime(&ftime, &ctime); - - setCreationTime(ctime); -} - -void Fallout76SaveGame::fetchInformationFields(FileWrapper& file, QString playerName, - unsigned short playerLevel, - QString playerLocation, - unsigned long saveNumber, - FILETIME& creationTime) const -{ - - file.skip(); // header size - file.skip(); // header version - file.read(saveNumber); - - file.read(playerName); - - unsigned long temp; - file.read(temp); - playerLevel = static_cast(temp); - file.read(playerLocation); - - QString ignore; - file.read(ignore); // playtime as ascii hh.mm.ss - file.read(ignore); // race name (i.e. BretonRace) - - file.skip(); // Player gender (0 = male) - file.skip(2); // experience gathered, experience required - - FILETIME ftime; - file.read(ftime); -} - -std::unique_ptr Fallout76SaveGame::fetchDataFields() const -{ - - FileWrapper file(getFilepath(), "TESV_SAVEGAME"); // 10bytes - { - - FILETIME ftime; - fetchInformationFields(file, m_PCName, m_PCLevel, m_PCLocation, m_SaveNumber, - ftime); - } - - std::unique_ptr fields = std::make_unique(); - - file.readImage(384, true); - - uint8_t saveGameVersion = file.readChar(); - QString ignore; - file.read(ignore); // game version - file.skip(); // plugin info size - - file.readPlugins(); - if (saveGameVersion >= 68) { - file.readLightPlugins(); - } - - return fields; -} diff --git a/src/games/fallout76/src/fallout76savegame.h b/src/games/fallout76/src/fallout76savegame.h deleted file mode 100644 index 232e7582..00000000 --- a/src/games/fallout76/src/fallout76savegame.h +++ /dev/null @@ -1,24 +0,0 @@ -#ifndef FALLOUT76SAVEGAME_H -#define FALLOUT76SAVEGAME_H - -#include - -#include "gamebryosavegame.h" - -class GameFallout76; - -class Fallout76SaveGame : public GamebryoSaveGame -{ -public: - Fallout76SaveGame(QString const& fileName, GameFallout76 const* game); - -protected: - // Fetch easy-to-access information. - void fetchInformationFields(FileWrapper& wrapper, QString playerName, - unsigned short playerLevel, QString playerLocation, - unsigned long saveNumber, FILETIME& creationTime) const; - - std::unique_ptr fetchDataFields() const override; -}; - -#endif // FALLOUT76SAVEGAME_H diff --git a/src/games/fallout76/src/fallout76savegameinfo.cpp b/src/games/fallout76/src/fallout76savegameinfo.cpp deleted file mode 100644 index c6cb6213..00000000 --- a/src/games/fallout76/src/fallout76savegameinfo.cpp +++ /dev/null @@ -1,10 +0,0 @@ -#include "fallout76savegameinfo.h" - -#include "fallout76savegame.h" -#include "gamegamebryo.h" - -Fallout76SaveGameInfo::Fallout76SaveGameInfo(GameGamebryo const* game) - : GamebryoSaveGameInfo(game) -{} - -Fallout76SaveGameInfo::~Fallout76SaveGameInfo() {} diff --git a/src/games/fallout76/src/fallout76savegameinfo.h b/src/games/fallout76/src/fallout76savegameinfo.h deleted file mode 100644 index 457777c1..00000000 --- a/src/games/fallout76/src/fallout76savegameinfo.h +++ /dev/null @@ -1,15 +0,0 @@ -#ifndef FALLOUT76SAVEGAMEINFO_H -#define FALLOUT76SAVEGAMEINFO_H - -#include "gamebryosavegameinfo.h" - -class GameGamebryo; - -class Fallout76SaveGameInfo : public GamebryoSaveGameInfo -{ -public: - Fallout76SaveGameInfo(GameGamebryo const* game); - ~Fallout76SaveGameInfo(); -}; - -#endif // FALLOUT76SAVEGAMEINFO_H diff --git a/src/games/fallout76/src/fallout76scriptextender.cpp b/src/games/fallout76/src/fallout76scriptextender.cpp deleted file mode 100644 index 8a46c5ef..00000000 --- a/src/games/fallout76/src/fallout76scriptextender.cpp +++ /dev/null @@ -1,18 +0,0 @@ -#include "fallout76scriptextender.h" - -#include -#include - -Fallout76ScriptExtender::Fallout76ScriptExtender(GameGamebryo const* game) - : GamebryoScriptExtender(game) -{} - -QString Fallout76ScriptExtender::BinaryName() const -{ - return "f76se_loader.exe"; -} - -QString Fallout76ScriptExtender::PluginPath() const -{ - return "f76se/plugins"; -} diff --git a/src/games/fallout76/src/fallout76scriptextender.h b/src/games/fallout76/src/fallout76scriptextender.h deleted file mode 100644 index 206d5978..00000000 --- a/src/games/fallout76/src/fallout76scriptextender.h +++ /dev/null @@ -1,17 +0,0 @@ -#ifndef FALLOUT76SCRIPTEXTENDER_H -#define FALLOUT76SCRIPTEXTENDER_H - -#include "gamebryoscriptextender.h" - -class GameGamebryo; - -class Fallout76ScriptExtender : public GamebryoScriptExtender -{ -public: - Fallout76ScriptExtender(GameGamebryo const* game); - - virtual QString BinaryName() const override; - virtual QString PluginPath() const override; -}; - -#endif // FALLOUT76SCRIPTEXTENDER_H diff --git a/src/games/fallout76/src/gamefallout76.cpp b/src/games/fallout76/src/gamefallout76.cpp index b0afc2ef..45af2f66 100644 --- a/src/games/fallout76/src/gamefallout76.cpp +++ b/src/games/fallout76/src/gamefallout76.cpp @@ -3,14 +3,11 @@ #include "fallout76dataarchives.h" #include "fallout76moddatachecker.h" #include "fallout76moddatacontent.h" -#include "fallout76savegameinfo.h" -#include "fallout76scriptextender.h" #include "fallout76unmanagedmods.h" #include "versioninfo.h" #include #include -#include #include #include @@ -35,7 +32,6 @@ bool GameFallout76::init(IOrganizer* moInfo) return false; } - registerFeature(std::make_shared(this)); registerFeature(std::make_shared(this)); registerFeature(std::make_shared(this)); registerFeature( @@ -51,18 +47,16 @@ QString GameFallout76::gameName() const return "Fallout 76"; } +void GameFallout76::detectGame() +{ + m_GamePath = identifyGamePath(); + m_MyGamesPath = determineMyGamesPath(gameName()); +} + QList GameFallout76::executables() const { return QList() - << ExecutableInfo("F76SE", - findInGameFolder(m_Organizer->gameFeatures() - ->gameFeature() - ->loaderName())) - << ExecutableInfo("Fallout 76", findInGameFolder(binaryName())) - << ExecutableInfo("Fallout Launcher", findInGameFolder(getLauncherName())) - << ExecutableInfo("Creation Kit", findInGameFolder("CreationKit.exe")) - << ExecutableInfo("LOOT", QFileInfo(getLootPath())) - .withArgument("--game=\"Fallout76\""); + << ExecutableInfo("Fallout 76", findInGameFolder(binaryName())); } QList GameFallout76::executableForcedLoads() const @@ -120,12 +114,12 @@ void GameFallout76::initializeProfile(const QDir& path, ProfileSettings settings QString GameFallout76::savegameExtension() const { - return "bgs"; + return ""; } QString GameFallout76::savegameSEExtension() const { - return "f76se"; + return ""; } std::vector> @@ -134,6 +128,11 @@ GameFallout76::listSaves(QDir folder) const return {}; } +QString GameFallout76::identifyGamePath() const +{ + return parseSteamLocation(steamAPPId(), gameShortName()); +} + std::shared_ptr GameFallout76::makeSaveGame(QString) const { return nullptr; @@ -141,7 +140,7 @@ std::shared_ptr GameFallout76::makeSaveGame(QString) con QString GameFallout76::steamAPPId() const { - return "n/a"; + return "1151340"; } QStringList GameFallout76::primaryPlugins() const @@ -207,6 +206,11 @@ QStringList GameFallout76::CCPlugins() const return plugins; } +IPluginGame::SortMechanism GameFallout76::sortMechanism() const +{ + return IPluginGame::SortMechanism::NONE; +} + IPluginGame::LoadOrderMechanism GameFallout76::loadOrderMechanism() const { return IPluginGame::LoadOrderMechanism::PluginsTxt; diff --git a/src/games/fallout76/src/gamefallout76.h b/src/games/fallout76/src/gamefallout76.h index 3386dc0c..418ad23f 100644 --- a/src/games/fallout76/src/gamefallout76.h +++ b/src/games/fallout76/src/gamefallout76.h @@ -19,6 +19,7 @@ public: public: // IPluginGame interface QString gameName() const override; + void detectGame() override; QList executables() const override; QList executableForcedLoads() const override; void initializeProfile(const QDir& path, ProfileSettings settings) const override; @@ -30,6 +31,7 @@ public: // IPluginGame interface QStringList iniFiles() const override; QStringList DLCPlugins() const override; QStringList CCPlugins() const override; + SortMechanism sortMechanism() const override; LoadOrderMechanism loadOrderMechanism() const override; int nexusModOrganizerID() const override; int nexusGameID() const override; @@ -44,7 +46,8 @@ public: // IPlugin interface QList settings() const override; protected: - std::shared_ptr makeSaveGame(QString) const; + QString identifyGamePath() const override; + std::shared_ptr makeSaveGame(QString) const override; QString savegameExtension() const override; QString savegameSEExtension() const override; }; From bde402a24a8066b113ff73f5eae4ec113b9e3933 Mon Sep 17 00:00:00 2001 From: Jeremy Rimpo Date: Thu, 3 Oct 2024 03:01:07 -0500 Subject: [PATCH 1531/1544] [game_starfield] Shattered space update (#32) * Add support for the vehicle update * New save format (v140) which adds another plugin list flag for 'is custom plugin'; remaining changes are compatible with existing parser * New core plugin (SFBGS004.esm) * Remove obsolete CCC primary plugin fix * Update CCC parsing to ignore duplicate plugins --- src/games/starfield/src/gamestarfield.cpp | 99 +++++++------------ src/games/starfield/src/gamestarfield.h | 2 +- .../starfield/src/starfieldgameplugins.cpp | 5 + .../starfield/src/starfieldgameplugins.h | 1 + 4 files changed, 41 insertions(+), 66 deletions(-) diff --git a/src/games/starfield/src/gamestarfield.cpp b/src/games/starfield/src/gamestarfield.cpp index e4984421..ac1b15b2 100644 --- a/src/games/starfield/src/gamestarfield.cpp +++ b/src/games/starfield/src/gamestarfield.cpp @@ -53,36 +53,9 @@ bool GameStarfield::init(IOrganizer* moInfo) registerFeature(std::make_shared(this, localAppFolder())); registerFeature(std::make_shared(dataArchives.get(), this)); - m_Organizer->pluginList()->onRefreshed([&]() { - setCCCFile(); - }); - return true; } -/* - * This is used to write the primary plugins to a profile-based Starfield.ccc file. We - * map this into the game directory with the VFS. The game does not currently ship with - * this file but does still read it like SkyrimSE and Fallout 4. We can make use of it - * to correct the current behavior where core plugins are loaded after parsing - * plugins.txt leading to ambiguous load orders. - */ -void GameStarfield::setCCCFile() const -{ - if (m_Organizer->profilePath().isEmpty()) - return; - if (m_Organizer->pluginSetting(name(), "enable_loadorder_fix").toBool()) { - QFile cccFile(m_Organizer->profilePath() + "/Starfield.ccc"); - if (cccFile.open(QIODevice::WriteOnly)) { - auto plugins = primaryPlugins(); - for (auto plugin : plugins) { - cccFile.write(plugin.toUtf8()); - cccFile.write("\n"); - } - } - } -} - QString GameStarfield::gameName() const { return "Starfield"; @@ -167,18 +140,11 @@ QList GameStarfield::settings() const true) << PluginSetting("enable_management_warnings", tr("Show a warning when plugins.txt management is invalid."), - true) - << PluginSetting("enable_loadorder_fix", - tr("Utilize Starfield.ccc to affix core plugin load order " - "(will override existing file)."), true); } MappingType GameStarfield::mappings() const { - if (m_Organizer->pluginSetting(name(), "enable_loadorder_fix").toBool()) { - setCCCFile(); - } MappingType result; if (testFilePlugins().isEmpty()) { for (const QString& profileFile : {"plugins.txt", "loadorder.txt"}) { @@ -187,14 +153,6 @@ MappingType GameStarfield::mappings() const false}); } } - if (m_Organizer->pluginSetting(name(), "enable_loadorder_fix").toBool()) { - // map the Starfield.ccc from the profile to both the game folder and the My Games - // folder (used by LOOT for instance) - result.push_back({m_Organizer->profilePath() + "/" + "Starfield.ccc", - gameDirectory().absolutePath() + "/" + "Starfield.ccc", false}); - result.push_back({m_Organizer->profilePath() + "/" + "Starfield.ccc", - myGamesPath() + "/" + "Starfield.ccc", false}); - } return result; } @@ -255,11 +213,17 @@ QStringList GameStarfield::testFilePlugins() const QStringList GameStarfield::primaryPlugins() const { - QStringList plugins = {"Starfield.esm", "Constellation.esm", - "OldMars.esm", "BlueprintShips-Starfield.esm", - "SFBGS007.esm", "SFBGS008.esm", - "SFBGS006.esm", "SFBGS003.esm", - "SFBGS004.esm"}; + QStringList plugins = {"Starfield.esm", "Constellation.esm", + "ShatteredSpace.esm", "OldMars.esm", + "SFBGS003.esm", "SFBGS004.esm", + "SFBGS006.esm", "SFBGS007.esm", + "SFBGS008.esm", "BlueprintShips-Starfield.esm"}; + + for (auto plugin : CCCPlugins()) { + if (!plugins.contains(plugin, Qt::CaseInsensitive)) { + plugins.append(plugin); + } + } auto testPlugins = testFilePlugins(); if (loadOrderMechanism() == LoadOrderMechanism::None) { @@ -267,6 +231,8 @@ QStringList GameStarfield::primaryPlugins() const plugins << testPlugins; } + plugins.removeDuplicates(); + return plugins; } @@ -302,42 +268,45 @@ bool GameStarfield::prepareIni(const QString& exec) QStringList GameStarfield::DLCPlugins() const { - return {}; + return {"Constellation.esm", "ShatteredSpace.esm"}; } -QStringList GameStarfield::CCPlugins() const +QStringList GameStarfield::CCCPlugins() const { // While the CCC file appears to be mostly legacy, we need to parse it since the game // will still read it and there are some compatibility reason to use it for // force-loading the core game plugins. - QStringList plugins = {}; - QStringList corePlugins = primaryPlugins() + DLCPlugins(); + QStringList plugins = {}; if (!testFilePresent()) { - QFile file(gameDirectory().absoluteFilePath("Starfield.ccc")); - if (m_Organizer->pluginSetting(name(), "enable_loadorder_fix").toBool() && - !m_Organizer->profilePath().isEmpty()) { - file.setFileName(m_Organizer->profilePath() + "/Starfield.ccc"); + QFile myDocsCCCFile(myGamesPath() + "\Starfield.ccc"); + QFile gameCCCFile(gameDirectory().absoluteFilePath("Starfield.ccc")); + QFile* file; + if (myDocsCCCFile.exists()) { + file = &myDocsCCCFile; + } else { + file = &gameCCCFile; } - if (file.open(QIODevice::ReadOnly)) { - if (file.size() > 0) { - while (!file.atEnd()) { - QByteArray line = file.readLine().trimmed(); + if (file->open(QIODevice::ReadOnly)) { + if (file->size() > 0) { + while (!file->atEnd()) { + QByteArray line = file->readLine().trimmed(); QString modName; if ((line.size() > 0) && (line.at(0) != '#')) { - modName = QString::fromUtf8(line.constData()).toLower(); + modName = QString::fromUtf8(line.constData()); } - if (modName.size() > 0) { - if (!plugins.contains(modName, Qt::CaseInsensitive) && - !corePlugins.contains(modName, Qt::CaseInsensitive)) { - plugins.append(modName); - } + plugins.append(modName); } } } } } + return plugins; +} +QStringList GameStarfield::CCPlugins() const +{ + QStringList plugins = {}; std::shared_ptr unmanagedMods = std::static_pointer_cast( m_Organizer->gameFeatures()->gameFeature()); diff --git a/src/games/starfield/src/gamestarfield.h b/src/games/starfield/src/gamestarfield.h index a9d612d8..f9724c06 100644 --- a/src/games/starfield/src/gamestarfield.h +++ b/src/games/starfield/src/gamestarfield.h @@ -69,9 +69,9 @@ protected: QString savegameSEExtension() const override; private: + QStringList CCCPlugins() const; bool activeESP() const; bool testFilePresent() const; - void setCCCFile() const; private: static const unsigned int PROBLEM_ESP = 1; diff --git a/src/games/starfield/src/starfieldgameplugins.cpp b/src/games/starfield/src/starfieldgameplugins.cpp index 3653aca3..6b4e6ab0 100644 --- a/src/games/starfield/src/starfieldgameplugins.cpp +++ b/src/games/starfield/src/starfieldgameplugins.cpp @@ -11,6 +11,11 @@ bool StarfieldGamePlugins::mediumPluginsAreSupported() return true; } +bool StarfieldGamePlugins::blueprintPluginsAreSupported() +{ + return true; +} + void StarfieldGamePlugins::writePluginList(const IPluginList* pluginList, const QString& filePath) { diff --git a/src/games/starfield/src/starfieldgameplugins.h b/src/games/starfield/src/starfieldgameplugins.h index c654306e..a957b13f 100644 --- a/src/games/starfield/src/starfieldgameplugins.h +++ b/src/games/starfield/src/starfieldgameplugins.h @@ -14,6 +14,7 @@ public: protected: virtual bool mediumPluginsAreSupported() override; + virtual bool blueprintPluginsAreSupported() override; virtual void writePluginList(const MOBase::IPluginList* pluginList, const QString& filePath) override; virtual QStringList readPluginList(MOBase::IPluginList* pluginList) override; From d7f0a9d2f13639df5832f262db3d58abf6ed0e30 Mon Sep 17 00:00:00 2001 From: RJ <122295667+Liderate@users.noreply.github.com> Date: Tue, 5 Nov 2024 08:22:46 -0500 Subject: [PATCH 1532/1544] [game_starfield] Handle IPluginGame::CONFIGURATION flag and use forward slash for QFile (#33) * Handle IPluginGame::CONFIGURATION in initializeProfile --------- Co-authored-by: RJ --- src/games/starfield/src/gamestarfield.cpp | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/src/games/starfield/src/gamestarfield.cpp b/src/games/starfield/src/gamestarfield.cpp index ac1b15b2..882552a5 100644 --- a/src/games/starfield/src/gamestarfield.cpp +++ b/src/games/starfield/src/gamestarfield.cpp @@ -160,6 +160,9 @@ void GameStarfield::initializeProfile(const QDir& path, ProfileSettings settings { if (settings.testFlag(IPluginGame::MODS)) { copyToProfile(localAppFolder() + "/Starfield", path, "plugins.txt"); + } + + if (settings.testFlag(IPluginGame::CONFIGURATION)) { copyToProfile(myGamesPath(), path, "StarfieldPrefs.ini"); copyToProfile(myGamesPath(), path, "StarfieldCustom.ini"); } @@ -278,7 +281,7 @@ QStringList GameStarfield::CCCPlugins() const // force-loading the core game plugins. QStringList plugins = {}; if (!testFilePresent()) { - QFile myDocsCCCFile(myGamesPath() + "\Starfield.ccc"); + QFile myDocsCCCFile(myGamesPath() + "/Starfield.ccc"); QFile gameCCCFile(gameDirectory().absoluteFilePath("Starfield.ccc")); QFile* file; if (myDocsCCCFile.exists()) { From 8d88a165a860fc26a75be778f7ff4f303ebb92cd Mon Sep 17 00:00:00 2001 From: RJ <122295667+Liderate@users.noreply.github.com> Date: Fri, 13 Dec 2024 04:13:00 -0500 Subject: [PATCH 1533/1544] [game_fallout3] Add variants and remove custom.ini (#25) * Add variants to handle launcher name differences and remove custom.ini * Add Low Violence variant * Prefer functional style when setting variant --------- Co-authored-by: RJ --- src/games/fallout3/src/gamefallout3.cpp | 66 +++++++++++++++++++++---- src/games/fallout3/src/gamefallout3.h | 4 ++ 2 files changed, 61 insertions(+), 9 deletions(-) diff --git a/src/games/fallout3/src/gamefallout3.cpp b/src/games/fallout3/src/gamefallout3.cpp index 3bd553be..f2f45625 100644 --- a/src/games/fallout3/src/gamefallout3.cpp +++ b/src/games/fallout3/src/gamefallout3.cpp @@ -49,10 +49,32 @@ bool GameFallout3::init(IOrganizer* moInfo) return true; } +QString GameFallout3::identifyVariant() const +{ + if (QFile::exists(m_GamePath + "/Fallout3ng.exe")) { + return "Low Violence"; + } else if (QFile::exists(m_GamePath + "/Galaxy.dll")) { + return "GOG"; + } else if (QFile::exists(m_GamePath + "/FalloutLauncherEpic.exe")) { + return "Epic Games"; + } else if (m_GamePath.endsWith("Fallout 3 goty")) { + return "Steam (Game of the Year)"; + } else { + return "Steam (Regular)"; + } +} + QString GameFallout3::identifyGamePath() const { - auto result = GameGamebryo::identifyGamePath(); // Default registry path - // EPIC Game Store + // Steam (Regular) + auto result = parseSteamLocation("22300", "Fallout 3"); + + // Steam (Game of the Year) + if (result.isEmpty()) { + result = parseSteamLocation("22370", "Fallout 3 goty"); + } + + // Epic Games if (result.isEmpty()) { // Fallout 3: Game of the Year Edition: adeae8bbfc94427db57c7dfecce3f1d4 result = parseEpicGamesLocation({"adeae8bbfc94427db57c7dfecce3f1d4"}); @@ -64,6 +86,12 @@ QString GameFallout3::identifyGamePath() const result = startPath.absoluteFilePath(subDirs.first()); } } + + // GOG (and Steam) + if (result.isEmpty()) { + result = GameGamebryo::identifyGamePath(); + } + return result; } @@ -74,7 +102,8 @@ QString GameFallout3::gameName() const void GameFallout3::detectGame() { - m_GamePath = identifyGamePath(); + m_GamePath = identifyGamePath(); + setGameVariant(identifyVariant()); m_MyGamesPath = determineMyGamesPath("Fallout3"); } @@ -171,10 +200,12 @@ GameFallout3::makeSaveGame(QString filePath) const QString GameFallout3::steamAPPId() const { - if (selectedVariant() == "Game Of The Year") { + if (selectedVariant() == "Steam (Game Of The Year)") { return "22370"; - } else { + } else if (selectedVariant() == "Steam (Regular)") { return "22300"; + } else { + return ""; } } @@ -185,7 +216,17 @@ QStringList GameFallout3::primaryPlugins() const QStringList GameFallout3::gameVariants() const { - return {"Regular", "Game Of The Year"}; + return {"Steam (Regular)", "Steam (Game Of The Year)", "Epic Games", "GOG", + "Low Violence"}; +} + +QString GameFallout3::binaryName() const +{ + if (selectedVariant() == "Low Violence") { + return "Fallout3ng.exe"; + } else { + return GameGamebryo::binaryName(); + } } QString GameFallout3::gameShortName() const @@ -205,8 +246,8 @@ QString GameFallout3::gameNexusName() const QStringList GameFallout3::iniFiles() const { - return {"fallout.ini", "falloutprefs.ini", "custom.ini", - "FalloutCustom.ini", "GECKCustom.ini", "GECKPrefs.ini"}; + return {"fallout.ini", "falloutprefs.ini", "FalloutCustom.ini", "GECKCustom.ini", + "GECKPrefs.ini"}; } QStringList GameFallout3::DLCPlugins() const @@ -227,5 +268,12 @@ int GameFallout3::nexusGameID() const QString GameFallout3::getLauncherName() const { - return "FalloutLauncher.exe"; + const QMap names = { + {"Steam (Regular)", "Fallout3Launcher.exe"}, + {"Steam (Game of the Year)", "Fallout3Launcher.exe"}, + {"Epic Games", "FalloutLauncherEpic.exe"}, + {"GOG", "FalloutLauncher.exe"}, + {"Low Violence", "Fallout3Launcher.exe"}}; + + return names.value(selectedVariant()); } diff --git a/src/games/fallout3/src/gamefallout3.h b/src/games/fallout3/src/gamefallout3.h index 8533f579..a6dce27b 100644 --- a/src/games/fallout3/src/gamefallout3.h +++ b/src/games/fallout3/src/gamefallout3.h @@ -27,6 +27,7 @@ public: // IPluginGame interface virtual QString steamAPPId() const override; virtual QStringList primaryPlugins() const override; virtual QStringList gameVariants() const; + QString binaryName() const override; virtual QString gameShortName() const override; virtual QStringList validShortNames() const override; virtual QString gameNexusName() const override; @@ -49,6 +50,9 @@ protected: virtual QString savegameExtension() const override; virtual QString savegameSEExtension() const override; std::shared_ptr makeSaveGame(QString filePath) const override; + +private: + QString identifyVariant() const; }; #endif // GAMEFALLOUT3_H From 3b399e00be3f33bb664eb152a12af9b29b1aa3f1 Mon Sep 17 00:00:00 2001 From: metacubed <7028125+metacubed@users.noreply.github.com> Date: Sat, 4 Jan 2025 09:37:36 -0800 Subject: [PATCH 1534/1544] [game_skyrimvr] Add "LightPlacer" to the list of valid top level folders. (#34) This is intended to support the LightPlacer mod by @powerof3. --- src/games/skyrimvr/src/skyrimvrmoddatachecker.h | 14 +++++++------- 1 file changed, 7 insertions(+), 7 deletions(-) diff --git a/src/games/skyrimvr/src/skyrimvrmoddatachecker.h b/src/games/skyrimvr/src/skyrimvrmoddatachecker.h index 0fef53fd..f44d941a 100644 --- a/src/games/skyrimvr/src/skyrimvrmoddatachecker.h +++ b/src/games/skyrimvr/src/skyrimvrmoddatachecker.h @@ -12,13 +12,13 @@ protected: virtual const FileNameSet& possibleFolderNames() const override { static FileNameSet result{ - "fonts", "interface", "menus", "meshes", - "music", "scripts", "shaders", "sound", - "strings", "textures", "trees", "video", - "facegen", "materials", "skse", "distantlod", - "asi", "Tools", "MCM", "distantland", - "mits", "dllplugins", "CalienteTools", "NetScriptFramework", - "shadersfx", "Nemesis_Engine"}; + "fonts", "interface", "menus", "meshes", + "music", "scripts", "shaders", "sound", + "strings", "textures", "trees", "video", + "facegen", "materials", "skse", "distantlod", + "asi", "Tools", "MCM", "distantland", + "mits", "dllplugins", "CalienteTools", "NetScriptFramework", + "shadersfx", "Nemesis_Engine", "LightPlacer"}; return result; } virtual const FileNameSet& possibleFileExtensions() const override From 6fc7a61e0964cdf60514bb22960c138de79a36df Mon Sep 17 00:00:00 2001 From: metacubed <7028125+metacubed@users.noreply.github.com> Date: Sat, 4 Jan 2025 09:37:49 -0800 Subject: [PATCH 1535/1544] [game_skyrimse] Add "LightPlacer" to the list of valid top level folders. (#39) This is intended to support the LightPlacer mod by @powerof3. --- src/games/skyrimse/src/skyrimsemoddatachecker.h | 15 ++++++++------- 1 file changed, 8 insertions(+), 7 deletions(-) diff --git a/src/games/skyrimse/src/skyrimsemoddatachecker.h b/src/games/skyrimse/src/skyrimsemoddatachecker.h index d93a7894..15073a39 100644 --- a/src/games/skyrimse/src/skyrimsemoddatachecker.h +++ b/src/games/skyrimse/src/skyrimsemoddatachecker.h @@ -12,13 +12,14 @@ protected: virtual const FileNameSet& possibleFolderNames() const override { static FileNameSet result{ - "fonts", "interface", "menus", "meshes", - "music", "scripts", "shaders", "sound", - "strings", "textures", "trees", "video", - "facegen", "materials", "skse", "distantlod", - "asi", "Tools", "MCM", "distantland", - "mits", "dllplugins", "CalienteTools", "NetScriptFramework", - "shadersfx", "Nemesis_Engine", "Platform", "grass"}; + "fonts", "interface", "menus", "meshes", + "music", "scripts", "shaders", "sound", + "strings", "textures", "trees", "video", + "facegen", "materials", "skse", "distantlod", + "asi", "Tools", "MCM", "distantland", + "mits", "dllplugins", "CalienteTools", "NetScriptFramework", + "shadersfx", "Nemesis_Engine", "Platform", "grass", + "LightPlacer"}; return result; } virtual const FileNameSet& possibleFileExtensions() const override From 8d663d5b17fe3dbdb8b2d435b764276e6c1812d1 Mon Sep 17 00:00:00 2001 From: RJ <122295667+Liderate@users.noreply.github.com> Date: Sun, 12 Jan 2025 06:15:57 -0500 Subject: [PATCH 1536/1544] [game_falloutnv] Add PCR Steam App ID (#35) Co-authored-by: RJ --- src/games/falloutnv/src/gamefalloutnv.cpp | 9 ++++++++- 1 file changed, 8 insertions(+), 1 deletion(-) diff --git a/src/games/falloutnv/src/gamefalloutnv.cpp b/src/games/falloutnv/src/gamefalloutnv.cpp index 87b4119e..1e8e9e97 100644 --- a/src/games/falloutnv/src/gamefalloutnv.cpp +++ b/src/games/falloutnv/src/gamefalloutnv.cpp @@ -245,7 +245,14 @@ GameFalloutNV::makeSaveGame(QString filePath) const QString GameFalloutNV::steamAPPId() const { - return "22380"; + if (selectedVariant() == "Steam") { + if (m_GamePath.endsWith("enplczru")) { + return "22490"; + } else { + return "22380"; + } + } + return QString(); } QStringList GameFalloutNV::primaryPlugins() const From 079a3c9180a3a0aea92c0865170d77c60ed66f9c Mon Sep 17 00:00:00 2001 From: RJ <122295667+Liderate@users.noreply.github.com> Date: Sun, 12 Jan 2025 06:16:05 -0500 Subject: [PATCH 1537/1544] [game_ttw] Add PCR Steam App ID (#41) Co-authored-by: RJ --- src/games/ttw/src/gamefalloutttw.cpp | 9 ++++++++- 1 file changed, 8 insertions(+), 1 deletion(-) diff --git a/src/games/ttw/src/gamefalloutttw.cpp b/src/games/ttw/src/gamefalloutttw.cpp index 0cf2dcd3..5872e1d2 100644 --- a/src/games/ttw/src/gamefalloutttw.cpp +++ b/src/games/ttw/src/gamefalloutttw.cpp @@ -249,7 +249,14 @@ GameFalloutTTW::makeSaveGame(QString filePath) const QString GameFalloutTTW::steamAPPId() const { - return "22380"; + if (selectedVariant() == "Steam") { + if (m_GamePath.endsWith("enplczru")) { + return "22490"; + } else { + return "22380"; + } + } + return QString(); } QStringList GameFalloutTTW::primaryPlugins() const From cc58342adddcfab408fb225597c6622a87564a76 Mon Sep 17 00:00:00 2001 From: Chris Djali Date: Wed, 21 May 2025 17:57:37 +0100 Subject: [PATCH 1538/1544] [game_morrowind] Support openmw animation overrides (#34) --- src/games/morrowind/src/morrowindmoddatachecker.h | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/src/games/morrowind/src/morrowindmoddatachecker.h b/src/games/morrowind/src/morrowindmoddatachecker.h index a67c1a5c..bd158e09 100644 --- a/src/games/morrowind/src/morrowindmoddatachecker.h +++ b/src/games/morrowind/src/morrowindmoddatachecker.h @@ -11,9 +11,9 @@ public: protected: virtual const FileNameSet& possibleFolderNames() const override { - static FileNameSet result{"fonts", "meshes", "music", "shaders", "sound", - "textures", "video", "mwse", "distantland", "mits", - "icons", "bookart", "splash"}; + static FileNameSet result{"fonts", "meshes", "music", "shaders", "sound", + "textures", "video", "mwse", "distantland", "mits", + "icons", "bookart", "splash", "animations"}; return result; } virtual const FileNameSet& possibleFileExtensions() const override From 7f11b105f1848d3f1727c4f25d8b5a1b33b6ea56 Mon Sep 17 00:00:00 2001 From: Jeremy Rimpo Date: Thu, 22 May 2025 03:36:59 -0500 Subject: [PATCH 1539/1544] Fix compile issue (#61) --- src/gamebryo/gamegamebryo.cpp | 1 + 1 file changed, 1 insertion(+) diff --git a/src/gamebryo/gamegamebryo.cpp b/src/gamebryo/gamegamebryo.cpp index a4cb3043..347c2d8f 100644 --- a/src/gamebryo/gamegamebryo.cpp +++ b/src/gamebryo/gamegamebryo.cpp @@ -20,6 +20,7 @@ #include #include #include +#include #include #include From afe4d4d767ba036fb9baff063d12396a73287bd6 Mon Sep 17 00:00:00 2001 From: Raezroth <47491977+Raezroth@users.noreply.github.com> Date: Thu, 22 May 2025 01:37:26 -0700 Subject: [PATCH 1540/1544] [game_fallout4vr] Re-Enable ESL Plugins, Fallout 4 VR has experimental ESL thanks to rollingrock (#28) --- src/games/fallout4vr/src/fallout4vrgameplugins.cpp | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) diff --git a/src/games/fallout4vr/src/fallout4vrgameplugins.cpp b/src/games/fallout4vr/src/fallout4vrgameplugins.cpp index 187a4410..0c3c5cc9 100644 --- a/src/games/fallout4vr/src/fallout4vrgameplugins.cpp +++ b/src/games/fallout4vr/src/fallout4vrgameplugins.cpp @@ -7,6 +7,9 @@ Fallout4VRGamePlugins::Fallout4VRGamePlugins(MOBase::IOrganizer* organizer) {} bool Fallout4VRGamePlugins::lightPluginsAreSupported() -{ - return false; +{ + auto files = m_Organizer->findFiles("f4se\\plugins", { "falloutvresl.dll" }); + if (files.isEmpty()) + return false; + return true; } From 8d46470cdddd109bee734b9a63a188bf10cce3d6 Mon Sep 17 00:00:00 2001 From: Jeremy Rimpo Date: Thu, 22 May 2025 13:54:32 -0500 Subject: [PATCH 1541/1544] [game_oblivion] Save files with no image are valid but break the parser (#26) --- src/games/oblivion/src/oblivionsavegame.cpp | 8 +++++--- 1 file changed, 5 insertions(+), 3 deletions(-) diff --git a/src/games/oblivion/src/oblivionsavegame.cpp b/src/games/oblivion/src/oblivionsavegame.cpp index 01520dba..7c1f3f21 100644 --- a/src/games/oblivion/src/oblivionsavegame.cpp +++ b/src/games/oblivion/src/oblivionsavegame.cpp @@ -64,9 +64,11 @@ std::unique_ptr OblivionSaveGame::fetchDataFields( // Note that screenshot size, width, height and data are apparently the same // structure - file.skip(); // Screenshot size. - - fields->Screenshot = file.readImage(); + unsigned long imageSize; + file.read(imageSize); // Screenshot size. + if (imageSize > 0) { + fields->Screenshot = file.readImage(); + } fields->Plugins = file.readPlugins(); From d86c84fad7d38699031399de8af01f7fe2bc8441 Mon Sep 17 00:00:00 2001 From: RJ <122295667+Liderate@users.noreply.github.com> Date: Fri, 23 May 2025 03:18:07 -0400 Subject: [PATCH 1542/1544] [game_enderalse] Update following SafeWriteFile changes (#12) Co-authored-by: RJ --- src/games/enderalse/src/enderalsegameplugins.cpp | 2 +- src/games/enderalse/src/enderalsegameplugins.h | 3 --- 2 files changed, 1 insertion(+), 4 deletions(-) diff --git a/src/games/enderalse/src/enderalsegameplugins.cpp b/src/games/enderalse/src/enderalsegameplugins.cpp index 653ba100..d7be8cec 100644 --- a/src/games/enderalse/src/enderalsegameplugins.cpp +++ b/src/games/enderalse/src/enderalsegameplugins.cpp @@ -78,5 +78,5 @@ void EnderalSEGamePlugins::writePluginList(const MOBase::IPluginList* pluginList "and rename them.")); } - file.commitIfDifferent(m_LastSaveHash[filePath]); + file->commit(); } diff --git a/src/games/enderalse/src/enderalsegameplugins.h b/src/games/enderalse/src/enderalsegameplugins.h index 275733c1..700a074e 100644 --- a/src/games/enderalse/src/enderalsegameplugins.h +++ b/src/games/enderalse/src/enderalsegameplugins.h @@ -14,9 +14,6 @@ public: protected: void writePluginList(const MOBase::IPluginList* pluginList, const QString& filePath) override; - -private: - std::map m_LastSaveHash; }; #endif // ENDERALSEGAMEPLUGINS_H From cf8de004bf26a6582061689508841950cb6fe0a8 Mon Sep 17 00:00:00 2001 From: RJ <122295667+Liderate@users.noreply.github.com> Date: Fri, 23 May 2025 03:18:11 -0400 Subject: [PATCH 1543/1544] Update following SafeWriteFile changes (#60) Co-authored-by: RJ --- src/creation/creationgameplugins.cpp | 2 +- src/creation/creationgameplugins.h | 3 --- src/gamebryo/gamebryogameplugins.cpp | 2 +- src/gamebryo/gamebryogameplugins.h | 3 --- 4 files changed, 2 insertions(+), 8 deletions(-) diff --git a/src/creation/creationgameplugins.cpp b/src/creation/creationgameplugins.cpp index 8c3c3a16..f5cef62e 100644 --- a/src/creation/creationgameplugins.cpp +++ b/src/creation/creationgameplugins.cpp @@ -100,7 +100,7 @@ void CreationGamePlugins::writePluginList(const IPluginList* pluginList, "and rename them.")); } - file.commitIfDifferent(m_LastSaveHash[filePath]); + file->commit(); } QStringList CreationGamePlugins::readPluginList(MOBase::IPluginList* pluginList) diff --git a/src/creation/creationgameplugins.h b/src/creation/creationgameplugins.h index 26dc805b..f7afd804 100644 --- a/src/creation/creationgameplugins.h +++ b/src/creation/creationgameplugins.h @@ -17,9 +17,6 @@ protected: virtual QStringList readPluginList(MOBase::IPluginList* pluginList) override; virtual QStringList getLoadOrder() override; virtual bool lightPluginsAreSupported() override; - -private: - std::map m_LastSaveHash; }; #endif // CREATIONGAMEPLUGINS_H diff --git a/src/gamebryo/gamebryogameplugins.cpp b/src/gamebryo/gamebryogameplugins.cpp index 9910f118..83ad50f2 100644 --- a/src/gamebryo/gamebryogameplugins.cpp +++ b/src/gamebryo/gamebryogameplugins.cpp @@ -137,7 +137,7 @@ void GamebryoGamePlugins::writeList(const IPluginList* pluginList, qWarning("plugin list would be empty, this is almost certainly wrong. Not " "saving."); } else { - file.commitIfDifferent(m_LastSaveHash[filePath]); + file->commit(); } } diff --git a/src/gamebryo/gamebryogameplugins.h b/src/gamebryo/gamebryogameplugins.h index 01879b76..ca70c759 100644 --- a/src/gamebryo/gamebryogameplugins.h +++ b/src/gamebryo/gamebryogameplugins.h @@ -33,9 +33,6 @@ protected: private: void writeList(const MOBase::IPluginList* pluginList, const QString& filePath, bool loadOrder); - -private: - std::map m_LastSaveHash; }; #endif // GAMEBRYOGAMEPLUGINS_H From 325770841fb1d0e90078d829288f389f3626e58e Mon Sep 17 00:00:00 2001 From: Michael-wigontherun <43317302+Michael-wigontherun@users.noreply.github.com> Date: Fri, 23 May 2025 14:01:58 +0200 Subject: [PATCH 1544/1544] [game_skyrimse] Added mainmenuwallpapers to the valid folder list. --- .../skyrimse/src/skyrimsemoddatachecker.h | 24 ++++++++++++------- 1 file changed, 16 insertions(+), 8 deletions(-) diff --git a/src/games/skyrimse/src/skyrimsemoddatachecker.h b/src/games/skyrimse/src/skyrimsemoddatachecker.h index 15073a39..1eaf3256 100644 --- a/src/games/skyrimse/src/skyrimsemoddatachecker.h +++ b/src/games/skyrimse/src/skyrimsemoddatachecker.h @@ -12,14 +12,22 @@ protected: virtual const FileNameSet& possibleFolderNames() const override { static FileNameSet result{ - "fonts", "interface", "menus", "meshes", - "music", "scripts", "shaders", "sound", - "strings", "textures", "trees", "video", - "facegen", "materials", "skse", "distantlod", - "asi", "Tools", "MCM", "distantland", - "mits", "dllplugins", "CalienteTools", "NetScriptFramework", - "shadersfx", "Nemesis_Engine", "Platform", "grass", - "LightPlacer"}; + + "fonts", "interface", + "menus", "meshes", + "music", "scripts", + "shaders", "sound", + "strings", "textures", + "trees", "video", + "facegen", "materials", + "skse", "distantlod", + "asi", "Tools", + "MCM", "distantland", + "mits", "dllplugins", + "CalienteTools", "NetScriptFramework", + "shadersfx", "Nemesis_Engine", + "Platform", "grass", + "LightPlacer", "mainmenuwallpapers"}; return result; } virtual const FileNameSet& possibleFileExtensions() const override