aboutsummaryrefslogtreecommitdiff
path: root/libs/game_bethesda/src/games/starfield/starfieldunmanagedmods.cpp
diff options
context:
space:
mode:
authorSulfurNitride <SulfurNitride@users.noreply.github.com>2026-05-16 19:51:40 -0500
committerSulfurNitride <SulfurNitride@users.noreply.github.com>2026-05-16 19:51:40 -0500
commit549b84b0f8815737c93913b200dde3821a062cb0 (patch)
treef6bfd96729016847438beda9416c93f447838077 /libs/game_bethesda/src/games/starfield/starfieldunmanagedmods.cpp
parenta0747cabb420d699be3a1dd4c63f47c5153bd7b9 (diff)
mo2: catch up to upstream 2.5.3 Betas 3-11
Multi-area sync against the upstream MO2 2.5.3 beta line. Roughly three logical sections share the diff: Catch-up (Betas 3-11): - nxmaccessmanager: drop "supporter" from validRoles so non-premium supporters get the right download path (Beta 10) - mainwindow: disable tutorial triggers at the trigger sites; Qt 6.11 lockup on child windows (Beta 4) - basic_games: add Kingdom Come Deliverance 2, Slay the Spire 2 (Betas 11, 6) - uibase: add NXM collections parsing fields/accessors + (?:nxm|modl) scheme support in NXMUrl (Beta 9) - Starfield: blueprintPrefix() on IPluginGame; plugins.txt write suppression for blueprint plugins; hasInvalidBlueprint / hasUnpairedBlueprint diagnoses; Title-keyed content catalog consolidation (Betas 3-5) - downloadmanager + systemtraymanager + organizercore + iuserinterface + settings: add Beta 11 "show notifications when downloads complete or fail" toggle and the showNotification plumbing - nxmaccessmanager: restore upstream re-entry guard for OAuth refresh and the styled OAuth response page (Beta 11) - organizer_en.ts and game-bethesda *_en.ts: pull upstream HEAD strings Workarounds tab removed: - Delete settingsdialogworkarounds.{h,cpp}; drop the tab in settingsdialog.ui; move "Enable archives parsing" into General - Hardcode GameSettings::forceEnableCoreFiles() to true so the primary-master toggle-off bug (DLCs unchecked on tab refresh) can't recur; setter becomes a no-op - No-op stubs for offlineMode, useProxy, useCustomBrowser, Steam appID/credentials, executablesBlacklist, skipFileSuffixes, skipDirectories — UI gone, accessors keep call sites green - settingsdialognexus drops the custom-browser wiring; spawn drops the "Change the blacklist" Retry path Beta 9 download manager port: - fileID-first match in nxmFilesAvailable and nxmFileInfoFromMd5Available; filename remains the fallback - NexusInterface::isActiveFileStatus() helper; rewrite of nxmUpdatesAvailable to use pickNewestVersion / findUpdateChainSuccessors / resolveInstalledFileId. ARCHIVED_HIDDEN now correctly treated as inactive - std::optional<unsigned int> reservedID on DownloadInfo factories and on the three addDownload overloads; startDownloadURLs and startDownloadURLWithMeta return the canonical DownloadID instead of m_ActiveDownloads.size()-1 (which was the index, not an ID) - QHash<unsigned int, DownloadInfo*> m_ByID maintained alongside m_ActiveDownloads at every mutation site; downloadInfoByID is now O(1) via m_ByID.value(id, nullptr) LOOT remains intentionally stripped (lootcli build cruft cleaned up separately). BSA wide-path skipped — Linux UTF-8 paths already work. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
Diffstat (limited to 'libs/game_bethesda/src/games/starfield/starfieldunmanagedmods.cpp')
-rw-r--r--libs/game_bethesda/src/games/starfield/starfieldunmanagedmods.cpp65
1 files changed, 43 insertions, 22 deletions
diff --git a/libs/game_bethesda/src/games/starfield/starfieldunmanagedmods.cpp b/libs/game_bethesda/src/games/starfield/starfieldunmanagedmods.cpp
index 30abb38..82207c3 100644
--- a/libs/game_bethesda/src/games/starfield/starfieldunmanagedmods.cpp
+++ b/libs/game_bethesda/src/games/starfield/starfieldunmanagedmods.cpp
@@ -9,7 +9,7 @@
StarfieldUnmanagedMods::StarfieldUnmanagedMods(const GameStarfield* game,
const QString& appDataFolder)
- : GamebryoUnmangedMods(game), m_AppDataFolder(appDataFolder)
+ : GamebryoUnmangedMods(game), m_Game(game), m_AppDataFolder(appDataFolder)
{}
StarfieldUnmanagedMods::~StarfieldUnmanagedMods() {}
@@ -25,29 +25,52 @@ QStringList StarfieldUnmanagedMods::mods(bool onlyOfficial) const
pluginList.removeAll(plugin);
}
QMap<QString, QDir> directories = {{"data", game()->dataDirectory()}};
+ auto contentCatalog = parseContentCatalog();
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
+ bool found = false;
+ for (const auto& mod : contentCatalog) {
+ if (mod.second.files.contains(fileName, Qt::CaseInsensitive)) {
+ result.append(mod.second.name);
+ found = true;
+ }
+ }
+ if (!found && !fileName.startsWith("blueprintships-", Qt::CaseInsensitive)) {
+ result.append(fileName.chopped(4)); // trims the extension off
+ }
}
}
}
}
-
+ result.removeDuplicates();
return result;
}
QFileInfo StarfieldUnmanagedMods::referenceFile(const QString& modName) const
{
- QFileInfoList files;
+ QStringList modFiles;
+ auto contentCatalog = parseContentCatalog();
+ if (contentCatalog.contains(modName)) {
+ modFiles = contentCatalog[modName].files;
+ }
+ QDir dataDir = m_Game->secondaryDataDirectories().first();
+ QStringList plugins = modFiles.filter(
+ QRegularExpression("\\.es(m|p|l)$", QRegularExpression::CaseInsensitiveOption));
QMap<QString, QDir> directories = {{"data", game()->dataDirectory()}};
directories.insert(game()->secondaryDataDirectories());
+ QFileInfoList pluginFiles;
+ QFileInfoList files;
for (QDir directory : directories) {
+ if (!plugins.isEmpty())
+ pluginFiles += dataDir.entryInfoList(plugins);
files += directory.entryInfoList(QStringList() << modName + ".es*");
}
- if (files.size() > 0) {
+ if (!pluginFiles.isEmpty()) {
+ return pluginFiles.at(0);
+ } else if (!files.isEmpty()) {
return files.at(0);
} else {
return QFileInfo();
@@ -86,11 +109,10 @@ StarfieldUnmanagedMods::parseContentCatalog() const
pluginList.append(fileName);
}
}
- for (const auto& plugin : pluginList) {
- contentCatalog[plugin] = ContentCatalog();
- contentCatalog[plugin].files = files;
- contentCatalog[plugin].name = modInfo.value("Title").toString();
- }
+ QString name = modInfo.value("Title").toString();
+ contentCatalog[name] = ContentCatalog();
+ contentCatalog[name].files = files;
+ contentCatalog[name].name = name;
}
}
}
@@ -101,17 +123,16 @@ 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;
- }
+ if (contentCatalog.contains(modName)) {
+ return contentCatalog[modName].files;
}
// file extension in FO4 is .ba2 instead of bsa
QMap<QString, QDir> directories = {{"data", game()->dataDirectory()}};
directories.insert(game()->secondaryDataDirectories());
for (QDir directory : directories) {
- for (const QString& archiveName : directory.entryList({modName + "*.ba2"})) {
+ for (const QString& archiveName :
+ directory.entryList({modName + "*.ba2", "blueprintships-" + modName + ".esm",
+ "blueprintships-" + modName + "*.ba2"})) {
files.append(directory.absoluteFilePath(archiveName));
}
}
@@ -121,12 +142,12 @@ QStringList StarfieldUnmanagedMods::secondaryFiles(const QString& modName) const
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;
- }
+ if (contentCatalog.contains(modName)) {
+ return contentCatalog[modName].name;
}
- // unlike in earlier games, in fallout 4 the file name doesn't correspond to
- // the public name
+ if (modName == "ShatteredSpace")
+ return "Shattered Space";
+ else if (modName == "SFBGS050")
+ return "Terran Armada";
return modName;
}