summaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
Diffstat (limited to 'src')
-rw-r--r--src/mainwindow.cpp77
-rw-r--r--src/mainwindow.h2
-rw-r--r--src/modinfo.cpp15
-rw-r--r--src/modinfo.h10
-rw-r--r--src/modlist.cpp8
-rw-r--r--src/modlist.h9
-rw-r--r--src/modlistsortproxy.cpp8
-rw-r--r--src/organizer.pro7
-rw-r--r--src/pluginlist.cpp4
-rw-r--r--src/pluginlist.h16
-rw-r--r--src/profile.cpp21
-rw-r--r--src/settings.cpp12
-rw-r--r--src/settings.h10
-rw-r--r--src/settingsdialog.ui19
-rw-r--r--src/shared/fallout3info.cpp10
-rw-r--r--src/shared/fallout3info.h1
-rw-r--r--src/shared/falloutnvinfo.cpp15
-rw-r--r--src/shared/falloutnvinfo.h1
-rw-r--r--src/shared/gameinfo.cpp8
-rw-r--r--src/shared/gameinfo.h3
-rw-r--r--src/shared/oblivioninfo.cpp16
-rw-r--r--src/shared/oblivioninfo.h1
-rw-r--r--src/shared/skyriminfo.cpp16
-rw-r--r--src/shared/skyriminfo.h1
-rw-r--r--src/version.rc4
25 files changed, 230 insertions, 64 deletions
diff --git a/src/mainwindow.cpp b/src/mainwindow.cpp
index 8fcd4024..b12f0706 100644
--- a/src/mainwindow.cpp
+++ b/src/mainwindow.cpp
@@ -164,7 +164,7 @@ MainWindow::MainWindow(const QString &exeName, QSettings &initSettings, QWidget
m_Updater(NexusInterface::instance(), this), m_CategoryFactory(CategoryFactory::instance()),
m_CurrentProfile(NULL), m_AskForNexusPW(false),
m_ArchivesInit(false), m_ContextItem(NULL), m_ContextAction(NULL), m_CurrentSaveView(NULL),
- m_GameInfo(new GameInfoImpl()), m_AboutToRun(), m_ModInstalled()
+ m_GameInfo(new GameInfoImpl()), m_AboutToRun(), m_ModInstalled(), m_DidUpdateMasterList(false)
{
ui->setupUi(this);
this->setWindowTitle(ToQString(GameInfo::instance().getGameName()) + " Mod Organizer v" + m_Updater.getVersion().displayString());
@@ -193,7 +193,7 @@ MainWindow::MainWindow(const QString &exeName, QSettings &initSettings, QWidget
updateToolBar();
- ModInfo::updateFromDisc(m_Settings.getModDirectory(), &m_DirectoryStructure);
+ ModInfo::updateFromDisc(m_Settings.getModDirectory(), &m_DirectoryStructure, m_Settings.displayForeign());
// set up mod list
m_ModListSortProxy = new ModListSortProxy(m_CurrentProfile, this);
@@ -1034,31 +1034,48 @@ void MainWindow::toolPluginInvoke()
void MainWindow::requestDownload(const QUrl &url, QNetworkReply *reply)
{
QToolButton *browserBtn = qobject_cast<QToolButton*>(ui->toolBar->widgetForAction(ui->actionNexus));
-
- QList<QAction*> browserActions = browserBtn->menu()->actions();
- foreach (QAction *action, browserActions) {
- // the nexus action doesn't have a plugin connected currently
- if (action->data().isValid()) {
- IPluginModPage *plugin = qobject_cast<IPluginModPage*>(qvariant_cast<QObject*>(action->data()));
- if (plugin == NULL) {
- qCritical("invalid mod page. This is a bug");
- continue;
- }
- ModRepositoryFileInfo *fileInfo = new ModRepositoryFileInfo();
- if (plugin->handlesDownload(url, reply->url(), *fileInfo)) {
- fileInfo->repository = plugin->name();
- m_DownloadManager.addDownload(reply, fileInfo);
- return;
+ if (browserBtn->menu() != NULL) {
+ // go through modpage plugins, find one to handle the download.
+ QList<QAction*> browserActions = browserBtn->menu()->actions();
+ foreach (QAction *action, browserActions) {
+ // the nexus action doesn't have a plugin connected currently
+ if (action->data().isValid()) {
+ IPluginModPage *plugin = qobject_cast<IPluginModPage*>(qvariant_cast<QObject*>(action->data()));
+ if (plugin == NULL) {
+ qCritical("invalid mod page. This is a bug");
+ continue;
+ }
+ ModRepositoryFileInfo *fileInfo = new ModRepositoryFileInfo();
+ if (plugin->handlesDownload(url, reply->url(), *fileInfo)) {
+ fileInfo->repository = plugin->name();
+ m_DownloadManager.addDownload(reply, fileInfo);
+ return;
+ }
}
}
}
- if (QMessageBox::question(this, tr("Download?"),
- tr("A download has been started but no installed page plugin recognizes it.\n"
- "If you download anyway no information (i.e. version) will be associated with the download.\n"
- "Continue?"),
- QMessageBox::Yes | QMessageBox::No) == QMessageBox::Yes) {
- m_DownloadManager.addDownload(reply, new ModRepositoryFileInfo());
+ // no mod found that could handle the download. Is it a nexus mod?
+ if (url.host() == "www.nexusmods.com") {
+ int modID = 0;
+ int fileID = 0;
+ QRegExp modExp("mods/(\\d+)");
+ if (modExp.indexIn(url.toString()) != -1) {
+ modID = modExp.cap(1).toInt();
+ }
+ QRegExp fileExp("fid=(\\d+)");
+ if (fileExp.indexIn(reply->url().toString()) != -1) {
+ fileID = fileExp.cap(1).toInt();
+ }
+ m_DownloadManager.addDownload(reply, new ModRepositoryFileInfo(modID, fileID));
+ } else {
+ if (QMessageBox::question(this, tr("Download?"),
+ tr("A download has been started but no installed page plugin recognizes it.\n"
+ "If you download anyway no information (i.e. version) will be associated with the download.\n"
+ "Continue?"),
+ QMessageBox::Yes | QMessageBox::No) == QMessageBox::Yes) {
+ m_DownloadManager.addDownload(reply, new ModRepositoryFileInfo());
+ }
}
}
@@ -1788,7 +1805,7 @@ void MainWindow::refreshModList(bool saveChanges)
if (saveChanges) {
m_CurrentProfile->writeModlistNow(true);
}
- ModInfo::updateFromDisc(m_Settings.getModDirectory(), &m_DirectoryStructure);
+ ModInfo::updateFromDisc(m_Settings.getModDirectory(), &m_DirectoryStructure, m_Settings.displayForeign());
m_CurrentProfile->refreshModStatus();
m_ModList.notifyChange(-1);
@@ -3707,7 +3724,7 @@ void addMenuAsPushButton(QMenu *menu, QMenu *subMenu)
QMenu *MainWindow::modListContextMenu()
{
- QMenu *menu = new QMenu();
+ QMenu *menu = new QMenu(this);
menu->addAction(tr("Install Mod..."), this, SLOT(installMod_clicked()));
menu->addAction(tr("Enable all visible"), this, SLOT(enableVisibleMods()));
@@ -3734,7 +3751,6 @@ void MainWindow::on_modList_customContextMenuRequested(const QPoint &pos)
if (m_ContextRow == -1) {
// no selection
menu = allMods;
- menu->setParent(this);
} else {
menu = new QMenu(this);
allMods->setTitle(tr("All Mods"));
@@ -4057,6 +4073,7 @@ void MainWindow::on_actionSettings_triggered()
{
QString oldModDirectory(m_Settings.getModDirectory());
QString oldCacheDirectory(m_Settings.getCacheDirectory());
+ bool oldDisplayForeign(m_Settings.displayForeign());
bool proxy = m_Settings.useProxy();
m_Settings.query(this);
m_InstallationManager.setModsDirectory(m_Settings.getModDirectory());
@@ -4072,7 +4089,8 @@ void MainWindow::on_actionSettings_triggered()
}
m_DownloadManager.setPreferredServers(m_Settings.getPreferredServers());
- if (m_Settings.getModDirectory() != oldModDirectory) {
+ if ((m_Settings.getModDirectory() != oldModDirectory)
+ || (m_Settings.displayForeign() != oldDisplayForeign)) {
refreshModList();
refreshLists();
}
@@ -5254,6 +5272,11 @@ void MainWindow::on_bossButton_clicked()
parameters << "--game" << ToQString(GameInfo::instance().getGameShortName())
<< "--gamePath" << QString("\"%1\"").arg(ToQString(GameInfo::instance().getGameDirectory()));
+ if (!m_DidUpdateMasterList) {
+ parameters << "--updateMasterlist";
+ m_DidUpdateMasterList = true;
+ }
+
HANDLE stdOutWrite = INVALID_HANDLE_VALUE;
HANDLE stdOutRead = INVALID_HANDLE_VALUE;
createStdoutPipe(&stdOutRead, &stdOutWrite);
diff --git a/src/mainwindow.h b/src/mainwindow.h
index f55a7f8f..da6f4330 100644
--- a/src/mainwindow.h
+++ b/src/mainwindow.h
@@ -383,6 +383,8 @@ private:
uint m_ArchiveListHash;
+ bool m_DidUpdateMasterList;
+
private slots:
void showMessage(const QString &message);
diff --git a/src/modinfo.cpp b/src/modinfo.cpp
index 87321b69..d58e83b2 100644
--- a/src/modinfo.cpp
+++ b/src/modinfo.cpp
@@ -184,7 +184,7 @@ unsigned int ModInfo::findMod(const boost::function<bool (ModInfo::Ptr)> &filter
}
-void ModInfo::updateFromDisc(const QString &modDirectory, DirectoryEntry **directoryStructure)
+void ModInfo::updateFromDisc(const QString &modDirectory, DirectoryEntry **directoryStructure, bool displayForeign)
{
QMutexLocker lock(&s_Mutex);
s_Collection.clear();
@@ -200,10 +200,13 @@ void ModInfo::updateFromDisc(const QString &modDirectory, DirectoryEntry **direc
}
{ // list plugins in the data directory and make a foreign-managed mod out of each
+ std::vector<std::wstring> dlcPlugins = GameInfo::instance().getDLCPlugins();
QDir dataDir(QDir::fromNativeSeparators(ToQString(GameInfo::instance().getGameDirectory())) + "/data");
foreach (const QFileInfo &file, dataDir.entryInfoList(QStringList() << "*.esp" << "*.esm")) {
- if ((file.baseName() != "Update")
- && (file.baseName() != ToQString(GameInfo::instance().getGameName()))) {
+ if ((file.baseName() != "Update") // hide update
+ && (file.baseName() != ToQString(GameInfo::instance().getGameName())) // hide the game esp
+ && (displayForeign // show non-dlc bundles only if the user wants them
+ || std::find(dlcPlugins.begin(), dlcPlugins.end(), ToWString(file.fileName())) != dlcPlugins.end())) {
QStringList archives;
foreach (const QString archiveName, dataDir.entryList(QStringList() << file.baseName() + "*.bsa")) {
archives.append(dataDir.absoluteFilePath(archiveName));
@@ -279,6 +282,12 @@ void ModInfo::setVersion(const VersionInfo &version)
m_Version = version;
}
+bool ModInfo::hasFlag(ModInfo::EFlag flag) const
+{
+ std::vector<EFlag> flags = getFlags();
+ return std::find(flags.begin(), flags.end(), flag) != flags.end();
+}
+
bool ModInfo::categorySet(int categoryID) const
{
diff --git a/src/modinfo.h b/src/modinfo.h
index 21267068..ef647eab 100644
--- a/src/modinfo.h
+++ b/src/modinfo.h
@@ -87,7 +87,7 @@ public:
/**
* @brief read the mod directory and Mod ModInfo objects for all subdirectories
**/
- static void updateFromDisc(const QString &modDirectory, MOShared::DirectoryEntry **directoryStructure);
+ static void updateFromDisc(const QString &modDirectory, MOShared::DirectoryEntry **directoryStructure, bool displayForeign);
static void clear() { s_Collection.clear(); s_ModsByName.clear(); s_ModsByModID.clear(); }
@@ -369,6 +369,13 @@ public:
virtual std::vector<EFlag> getFlags() const = 0;
/**
+ * @brief test if the specified flag is set for this mod
+ * @param flag the flag to test
+ * @return true if the flag is set, false otherwise
+ */
+ bool hasFlag(EFlag flag) const;
+
+ /**
* @return an indicator if and how this mod should be highlighted by the UI
*/
virtual int getHighlight() const { return HIGHLIGHT_NONE; }
@@ -911,6 +918,7 @@ public:
virtual void setNeverEndorse() {}
virtual bool remove() { return false; }
virtual void endorse(bool) {}
+ virtual bool alwaysEnabled() const { return true; }
virtual bool isEmpty() const;
virtual QString name() const { return "Overwrite"; }
virtual QString notes() const { return ""; }
diff --git a/src/modlist.cpp b/src/modlist.cpp
index 66bc66b4..e4728618 100644
--- a/src/modlist.cpp
+++ b/src/modlist.cpp
@@ -547,7 +547,9 @@ void ModList::changeModPriority(std::vector<int> sourceIndices, int newPriority)
for (std::vector<int>::const_iterator iter = sourceIndices.begin();
iter != sourceIndices.end(); ++iter) {
+ int oldPriority = m_Profile->getModPriority(*iter);
m_Profile->setModPriority(*iter, newPriority);
+ m_ModMoved(ModInfo::getByIndex(*iter)->name(), oldPriority, newPriority);
}
emit layoutChanged();
@@ -655,6 +657,12 @@ bool ModList::onModStateChanged(const std::function<void (const QString &, IModL
return conn.connected();
}
+bool ModList::onModMoved(const std::function<void (const QString &, int, int)> &func)
+{
+ auto conn = m_ModMoved.connect(func);
+ return conn.connected();
+}
+
bool ModList::dropURLs(const QMimeData *mimeData, int row, const QModelIndex &parent)
{
QStringList source;
diff --git a/src/modlist.h b/src/modlist.h
index e0bc9df9..b946e009 100644
--- a/src/modlist.h
+++ b/src/modlist.h
@@ -62,6 +62,7 @@ public:
};
typedef boost::signals2::signal<void (const QString &, ModStates)> SignalModStateChanged;
+ typedef boost::signals2::signal<void (const QString &, int, int)> SignalModMoved;
public:
@@ -113,6 +114,9 @@ public:
/// \copydoc MOBase::IModList::onModStateChanged
virtual bool onModStateChanged(const std::function<void (const QString &, ModStates)> &func);
+ /// \copydoc MOBase::IModList::onModMoved
+ virtual bool onModMoved(const std::function<void (const QString &, int, int)> &func);
+
public: // implementation of virtual functions of QAbstractItemModel
virtual int rowCount(const QModelIndex &parent = QModelIndex()) const;
@@ -276,11 +280,8 @@ private:
TModInfoChange m_ChangeInfo;
SignalModStateChanged m_ModStateChanged;
+ SignalModMoved m_ModMoved;
-
- // QAbstractItemModel interface
-
- // IModList interface
};
#endif // MODLIST_H
diff --git a/src/modlistsortproxy.cpp b/src/modlistsortproxy.cpp
index 052e65b2..3aadaa53 100644
--- a/src/modlistsortproxy.cpp
+++ b/src/modlistsortproxy.cpp
@@ -230,10 +230,10 @@ bool ModListSortProxy::filterMatchesModAnd(ModInfo::Ptr info, bool enabled) cons
for (auto iter = m_CategoryFilter.begin(); iter != m_CategoryFilter.end(); ++iter) {
switch (*iter) {
case CategoryFactory::CATEGORY_SPECIAL_CHECKED: {
- if (!enabled) return false;
+ if (!enabled && !info->alwaysEnabled()) return false;
} break;
case CategoryFactory::CATEGORY_SPECIAL_UNCHECKED: {
- if (enabled) return false;
+ if (enabled || info->alwaysEnabled()) return false;
} break;
case CategoryFactory::CATEGORY_SPECIAL_UPDATEAVAILABLE: {
if (!info->updateAvailable() && !info->downgradeAvailable()) return false;
@@ -261,10 +261,10 @@ bool ModListSortProxy::filterMatchesModOr(ModInfo::Ptr info, bool enabled) const
for (auto iter = m_CategoryFilter.begin(); iter != m_CategoryFilter.end(); ++iter) {
switch (*iter) {
case CategoryFactory::CATEGORY_SPECIAL_CHECKED: {
- if (enabled) return true;
+ if (enabled || info->alwaysEnabled()) return true;
} break;
case CategoryFactory::CATEGORY_SPECIAL_UNCHECKED: {
- if (!enabled) return true;
+ if (!enabled && !info->alwaysEnabled()) return true;
} break;
case CategoryFactory::CATEGORY_SPECIAL_UPDATEAVAILABLE: {
if (info->updateAvailable() || info->downgradeAvailable()) return true;
diff --git a/src/organizer.pro b/src/organizer.pro
index c16196d7..70d8e021 100644
--- a/src/organizer.pro
+++ b/src/organizer.pro
@@ -221,9 +221,9 @@ CONFIG(debug, debug|release) {
LIBS += -L$$OUT_PWD/../bsatk/release
LIBS += -L$$OUT_PWD/../uibase/release
LIBS += -L$$OUT_PWD/../boss_modified/release
- QMAKE_CXXFLAGS += /Zi /GL
+ QMAKE_CXXFLAGS += /Zi# /GL
# QMAKE_CXXFLAGS -= -O2
- QMAKE_LFLAGS += /DEBUG /LTCG /OPT:REF /OPT:ICF
+ QMAKE_LFLAGS += /DEBUG# /LTCG /OPT:REF /OPT:ICF
}
#QMAKE_CXXFLAGS_WARN_ON -= -W3
@@ -275,9 +275,6 @@ DEFINES += BOOST_DISABLE_ASSERTS NDEBUG
HGID = $$system(hg id -i)
DEFINES += HGID=\\\"$${HGID}\\\"
-load(moc)
-include(../common.pri)
-QMAKE_MOC += $$MOCDEFINES
SRCDIR = $$PWD
SRCDIR ~= s,/,$$QMAKE_DIR_SEP,g
diff --git a/src/pluginlist.cpp b/src/pluginlist.cpp
index 0a28a45f..79df08ae 100644
--- a/src/pluginlist.cpp
+++ b/src/pluginlist.cpp
@@ -814,8 +814,8 @@ QVariant PluginList::data(const QModelIndex &modelIndex, int role) const
text += "<br>There is an ini file connected to this esp. Its settings will be added to your game settings, overwriting "
"in case of conflicts.";
} else if (m_ESPs[index].m_IsDummy) {
- text += "<br>This file is a dummy! It exists only so the bsa with the same name gets loaded. With MO you don't need this: "
- "If you enable the archive with the same name in the \"Archive\" tab you can disable this plugin.";
+ text += "<br>This file is a dummy! It exists only so the bsa with the same name gets loaded. If you let MO manage archives you "
+ "don't need this: Enable the archive with the same name in the \"Archive\" tab and disable this plugin.";
}
toolTip += text;
}
diff --git a/src/pluginlist.h b/src/pluginlist.h
index d041172f..9421d894 100644
--- a/src/pluginlist.h
+++ b/src/pluginlist.h
@@ -103,9 +103,16 @@ public:
*
* @param profileName name of the current profile
* @param baseDirectory the root directory structure representing the virtual data directory
+ * @param pluginsFile file that stores the list of enabled plugins
+ * @param loadOrderFile file that stored the load order (not an official file but used by many tools for skyrim)
+ * @param lockedOrderFile list of plugins that shouldn't change load order
* @todo the profile is not used? If it was, we should pass the Profile-object instead
**/
- void refresh(const QString &profileName, const MOShared::DirectoryEntry &baseDirectory, const QString &pluginsFile, const QString &loadOrderFile, const QString &lockedOrderFile);
+ void refresh(const QString &profileName
+ , const MOShared::DirectoryEntry &baseDirectory
+ , const QString &pluginsFile
+ , const QString &loadOrderFile
+ , const QString &lockedOrderFile);
/**
* @brief enable a plugin based on its name
@@ -166,8 +173,11 @@ public:
* @param deleterFileName file to receive a list of files to hide from the virtual data tree. This is used to hide unchecked plugins if "hideUnchecked" is true
* @param hideUnchecked if true, plugins that aren't enabled will be hidden from the virtual data directory
**/
- void saveTo(const QString &pluginFileName, const QString &loadOrderFileName, const QString &lockedOrderFileName,
- const QString &deleterFileName, bool hideUnchecked) const;
+ void saveTo(const QString &pluginFileName
+ , const QString &loadOrderFileName
+ , const QString &lockedOrderFileName
+ , const QString &deleterFileName
+ , bool hideUnchecked) const;
/**
* @brief save the current load order
diff --git a/src/profile.cpp b/src/profile.cpp
index 2d982790..c3d9a0c4 100644
--- a/src/profile.cpp
+++ b/src/profile.cpp
@@ -296,6 +296,8 @@ void Profile::refreshModStatus()
int numKnownMods = index;
+ int topInsert = 0;
+
// invert priority order to match that of the pluginlist. Also
// give priorities to mods not referenced in the profile
for (size_t i = 0; i < m_ModStatus.size(); ++i) {
@@ -310,11 +312,28 @@ void Profile::refreshModStatus()
if (static_cast<size_t>(index) >= m_ModStatus.size()) {
throw MyException(tr("invalid index %1").arg(index));
}
- m_ModStatus[i].m_Priority = index++;
+ if (modInfo->hasFlag(ModInfo::FLAG_FOREIGN)) {
+ m_ModStatus[i].m_Priority = --topInsert;
+ } else {
+ m_ModStatus[i].m_Priority = index++;
+ }
// also, mark the mod-list as changed
modStatusModified = true;
}
}
+ // to support insertion of new mods at the top we may now have mods with negative priority. shift them all up
+ // to align priority with 0
+ if (topInsert < 0) {
+ int offset = topInsert * -1;
+ for (size_t i = 0; i < m_ModStatus.size(); ++i) {
+ ModInfo::Ptr modInfo = ModInfo::getByIndex(i);
+ if (modInfo->getFixedPriority() == INT_MAX) {
+ continue;
+ }
+
+ m_ModStatus[i].m_Priority += offset;
+ }
+ }
file.close();
updateIndices();
diff --git a/src/settings.cpp b/src/settings.cpp
index d63aabe4..9c53af71 100644
--- a/src/settings.cpp
+++ b/src/settings.cpp
@@ -288,16 +288,15 @@ void Settings::setupLoadMechanism()
}
-bool Settings::enableQuickInstaller()
-{
- return m_Settings.value("Settings/enable_quick_installer").toBool();
-}
-
bool Settings::useProxy()
{
return m_Settings.value("Settings/use_proxy", false).toBool();
}
+bool Settings::displayForeign()
+{
+ return m_Settings.value("Settings/display_foreign", true).toBool();
+}
void Settings::setMotDHash(uint hash)
{
@@ -545,6 +544,7 @@ void Settings::query(QWidget *parent)
QLineEdit *appIDEdit = dialog.findChild<QLineEdit*>("appIDEdit");
QLineEdit *nmmVersionEdit = dialog.findChild<QLineEdit*>("nmmVersionEdit");
QCheckBox *hideUncheckedBox = dialog.findChild<QCheckBox*>("hideUncheckedBox");
+ QCheckBox *displayForeignBox = dialog.findChild<QCheckBox*>("displayForeignBox");
//
@@ -602,6 +602,7 @@ void Settings::query(QWidget *parent)
showMetaBox->setChecked(metaDownloads());
hideUncheckedBox->setChecked(hideUncheckedPlugins());
+ displayForeignBox->setChecked(displayForeign());
forceEnableBox->setChecked(forceEnableCoreFiles());
appIDEdit->setText(getSteamAppID());
@@ -716,6 +717,7 @@ void Settings::query(QWidget *parent)
}
m_Settings.setValue("Settings/offline_mode", offlineBox->isChecked());
m_Settings.setValue("Settings/use_proxy", proxyBox->isChecked());
+ m_Settings.setValue("Settings/display_foreign", displayForeignBox->isChecked());
m_Settings.setValue("Settings/nmm_version", nmmVersionEdit->text());
diff --git a/src/settings.h b/src/settings.h
index ccb70d8a..0b051831 100644
--- a/src/settings.h
+++ b/src/settings.h
@@ -176,16 +176,16 @@ public:
void setupLoadMechanism();
/**
- * @return true if the user has enabled the quick installer (default true)
- **/
- bool enableQuickInstaller();
-
- /**
* @return true if the user configured the use of a network proxy
*/
bool useProxy();
/**
+ * @return true if the user wants to see non-official plugins installed outside MO in his mod list
+ */
+ bool displayForeign();
+
+ /**
* @brief sets the new motd hash
**/
void setMotDHash(uint hash);
diff --git a/src/settingsdialog.ui b/src/settingsdialog.ui
index 2e0ffae1..f04e4d7a 100644
--- a/src/settingsdialog.ui
+++ b/src/settingsdialog.ui
@@ -749,6 +749,25 @@ Uncheck this if you want to use Mod Organizer with total conversions (like Nehri
</widget>
</item>
<item>
+ <widget class="QCheckBox" name="displayForeignBox">
+ <property name="toolTip">
+ <string>Disable this to no longer display mods installed outside MO in the mod list (left pane). Assets from those mods will then be treated as having lowest mod priority together with the original game content.</string>
+ </property>
+ <property name="whatsThis">
+ <string>By default Mod Organizer will display esp+bsa bundles installed with foreign tools as mods (left pane). This allows you to control their priority in relation to other mods. This is particularly useful if you also use Steam Workshop to install mods.
+However, if you installed loose file mods outside MO which conflict with BSAs also installed outside MO those conflicts can't be resolved correctly.
+
+If you disable this feature, MO will only display official DLCs this way. Please note that plugins (esps and esms) displayed in the right pane are completely unaffected by this feature.</string>
+ </property>
+ <property name="text">
+ <string>Display mods installed outside MO</string>
+ </property>
+ <property name="checked">
+ <bool>true</bool>
+ </property>
+ </widget>
+ </item>
+ <item>
<widget class="QPushButton" name="bsaDateBtn">
<property name="toolTip">
<string>For Skyrim, this can be used instead of Archive Invalidation. It should make AI redundant for all Profiles.
diff --git a/src/shared/fallout3info.cpp b/src/shared/fallout3info.cpp
index 1808d1d9..68fd515e 100644
--- a/src/shared/fallout3info.cpp
+++ b/src/shared/fallout3info.cpp
@@ -112,6 +112,16 @@ std::vector<std::wstring> Fallout3Info::getVanillaBSAs()
(L"Fallout - Misc.bsa");
}
+std::vector<std::wstring> Fallout3Info::getDLCPlugins()
+{
+ return boost::assign::list_of (L"ThePitt.esm")
+ (L"Anchorage.esm")
+ (L"BrokenSteel.esm")
+ (L"PointLookout.esm")
+ (L"Zeta.esm")
+ ;
+}
+
std::vector<std::wstring> Fallout3Info::getIniFileNames()
{
return boost::assign::list_of(L"fallout.ini")(L"falloutprefs.ini");
diff --git a/src/shared/fallout3info.h b/src/shared/fallout3info.h
index 9575103b..e9a818e2 100644
--- a/src/shared/fallout3info.h
+++ b/src/shared/fallout3info.h
@@ -58,6 +58,7 @@ public:
virtual std::vector<std::wstring> getPrimaryPlugins();
virtual std::vector<std::wstring> getVanillaBSAs();
+ virtual std::vector<std::wstring> getDLCPlugins();
// file name of this games ini (no path)
virtual std::vector<std::wstring> getIniFileNames();
diff --git a/src/shared/falloutnvinfo.cpp b/src/shared/falloutnvinfo.cpp
index e7e747e2..366c72c3 100644
--- a/src/shared/falloutnvinfo.cpp
+++ b/src/shared/falloutnvinfo.cpp
@@ -113,6 +113,21 @@ std::vector<std::wstring> FalloutNVInfo::getVanillaBSAs()
(L"Fallout - Misc.bsa");
}
+std::vector<std::wstring> FalloutNVInfo::getDLCPlugins()
+{
+ return boost::assign::list_of (L"DeadMoney.esm")
+ (L"HonestHearts.esm")
+ (L"OldWorldBlues.esm")
+ (L"LonesomeRoad.esm")
+ (L"GunRunnersArsenal.esm")
+ (L"CaravanPack.esm")
+ (L"ClassicPack.esm")
+ (L"MercenaryPack.esm")
+ (L"TribalPack.esm")
+ ;
+}
+
+
std::vector<std::wstring> FalloutNVInfo::getIniFileNames()
{
return boost::assign::list_of(L"fallout.ini")(L"falloutprefs.ini");
diff --git a/src/shared/falloutnvinfo.h b/src/shared/falloutnvinfo.h
index 8767fdb0..e6f6b5d0 100644
--- a/src/shared/falloutnvinfo.h
+++ b/src/shared/falloutnvinfo.h
@@ -60,6 +60,7 @@ public:
virtual std::vector<std::wstring> getPrimaryPlugins();
virtual std::vector<std::wstring> getVanillaBSAs();
+ virtual std::vector<std::wstring> getDLCPlugins();
// file name of this games ini (no path)
virtual std::vector<std::wstring> getIniFileNames();
diff --git a/src/shared/gameinfo.cpp b/src/shared/gameinfo.cpp
index b580a226..ebeff55a 100644
--- a/src/shared/gameinfo.cpp
+++ b/src/shared/gameinfo.cpp
@@ -222,7 +222,13 @@ std::wstring GameInfo::getSpecialPath(LPCWSTR name) const
throw windows_error("failed to look up special folder", errorcode);
}
- return temp;
+ WCHAR temp2[MAX_PATH];
+ // try to expand variables in the path, if any
+ if (::ExpandEnvironmentStringsW(temp, temp2, MAX_PATH) != 0) {
+ return temp2;
+ } else {
+ return temp;
+ }
}
} // namespace MOShared
diff --git a/src/shared/gameinfo.h b/src/shared/gameinfo.h
index 89c9402d..69cd38f6 100644
--- a/src/shared/gameinfo.h
+++ b/src/shared/gameinfo.h
@@ -130,6 +130,9 @@ public:
virtual std::vector<std::wstring> getVanillaBSAs() = 0;
+ // get a set of esp/esm files that are part of known dlcs
+ virtual std::vector<std::wstring> getDLCPlugins() = 0;
+
// file name of this games ini file(s)
virtual std::vector<std::wstring> getIniFileNames() = 0;
diff --git a/src/shared/oblivioninfo.cpp b/src/shared/oblivioninfo.cpp
index d8daa0f7..85f31042 100644
--- a/src/shared/oblivioninfo.cpp
+++ b/src/shared/oblivioninfo.cpp
@@ -117,6 +117,22 @@ std::vector<std::wstring> OblivionInfo::getVanillaBSAs()
}
+std::vector<std::wstring> OblivionInfo::getDLCPlugins()
+{
+ return boost::assign::list_of (L"DLCShiveringIsles.esp")
+ (L"Knights.esp")
+ (L"DLCFrostcrag.esp")
+ (L"DLCSpellTomes.esp")
+ (L"DLCMehrunesRazor.esp")
+ (L"DLCOrrery.esp")
+ (L"DLCSpellTomes.esp")
+ (L"DLCThievesDen.esp")
+ (L"DLCVileLair.esp")
+ (L"DLCHorseArmor.esp")
+ ;
+}
+
+
std::vector<std::wstring> OblivionInfo::getIniFileNames()
{
return boost::assign::list_of(L"oblivion.ini")(L"oblivionprefs.ini");
diff --git a/src/shared/oblivioninfo.h b/src/shared/oblivioninfo.h
index ba27aa40..f9c8fa47 100644
--- a/src/shared/oblivioninfo.h
+++ b/src/shared/oblivioninfo.h
@@ -56,6 +56,7 @@ public:
virtual std::vector<std::wstring> getPrimaryPlugins();
virtual std::vector<std::wstring> getVanillaBSAs();
+ virtual std::vector<std::wstring> getDLCPlugins();
// file name of this games ini (no path)
virtual std::vector<std::wstring> getIniFileNames();
diff --git a/src/shared/skyriminfo.cpp b/src/shared/skyriminfo.cpp
index bf7500e6..00cdd4d0 100644
--- a/src/shared/skyriminfo.cpp
+++ b/src/shared/skyriminfo.cpp
@@ -144,7 +144,18 @@ std::vector<std::wstring> SkyrimInfo::getVanillaBSAs()
(L"Skyrim - Meshes.bsa")
(L"Skyrim - Sounds.bsa")
(L"Skyrim - Voices.bsa")
- (L"Skyrim - VoicesExtra.bsa");
+ (L"Skyrim - VoicesExtra.bsa");
+}
+
+std::vector<std::wstring> SkyrimInfo::getDLCPlugins()
+{
+ return boost::assign::list_of (L"Dawnguard.esm")
+ (L"Dragonborn.esm")
+ (L"HearthFires.esm")
+ (L"HighResTexturePack01.esp")
+ (L"HighResTexturePack02.esp")
+ (L"HighResTexturePack03.esp")
+ ;
}
std::vector<std::wstring> SkyrimInfo::getIniFileNames()
@@ -210,7 +221,9 @@ void SkyrimInfo::createProfile(const std::wstring &directory, bool useDefaults)
if (!FileExists(target)) {
std::wostringstream source;
source << getLocalAppFolder() << "\\Skyrim\\plugins.txt";
+printf("copy %ls -> %ls\n", source.str().c_str(), target.c_str());
if (!::CopyFileW(source.str().c_str(), target.c_str(), true)) {
+printf("failed to copy plugins.txt!");
HANDLE file = ::CreateFileW(target.c_str(), GENERIC_WRITE, 0, NULL, CREATE_NEW, FILE_ATTRIBUTE_NORMAL, NULL);
::CloseHandle(file);
}
@@ -305,4 +318,5 @@ std::vector<ExecutableInfo> SkyrimInfo::getExecutables()
return result;
}
+
} // namespace MOShared
diff --git a/src/shared/skyriminfo.h b/src/shared/skyriminfo.h
index 438beb41..61fb3fa2 100644
--- a/src/shared/skyriminfo.h
+++ b/src/shared/skyriminfo.h
@@ -63,6 +63,7 @@ public:
virtual std::vector<std::wstring> getPrimaryPlugins();
virtual std::vector<std::wstring> getVanillaBSAs();
+ virtual std::vector<std::wstring> getDLCPlugins();
// file name of this games ini (no path)
virtual std::vector<std::wstring> getIniFileNames();
diff --git a/src/version.rc b/src/version.rc
index 5e9b62c5..82484925 100644
--- a/src/version.rc
+++ b/src/version.rc
@@ -1,7 +1,7 @@
#include "Winver.h"
-#define VER_FILEVERSION 1,2,2,0
-#define VER_FILEVERSION_STR "1,2,2,0\0"
+#define VER_FILEVERSION 1,2,3,0
+#define VER_FILEVERSION_STR "1,2,3,0\0"
VS_VERSION_INFO VERSIONINFO
FILEVERSION VER_FILEVERSION