summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorJeremy Rimpo <jeremy.rimpo@servermonkey.com>2024-06-13 10:51:09 -0500
committerGitHub <noreply@github.com>2024-06-13 17:51:09 +0200
commit6d08d434a8a5a4471a620974a52550ada05ab663 (patch)
tree85b436568338199724a8b920a2323b94c67ef11a
parent3d8bfdd1d4bf4539f3c3b991cf226b47dd582a91 (diff)
Add medium plugin support (Starfield) (#2048)
* Add medium plugin support (Starfield) - Coopt the overlay support for the new 'medium' / ESH plugin flag - Update various displays to include ESH info * Rework address display for SF weirdness * Fix core ESH display
-rw-r--r--src/pluginlist.cpp122
-rw-r--r--src/pluginlist.h6
-rw-r--r--src/pluginlistproxy.cpp8
-rw-r--r--src/pluginlistproxy.h2
-rw-r--r--src/pluginlistview.cpp40
5 files changed, 108 insertions, 70 deletions
diff --git a/src/pluginlist.cpp b/src/pluginlist.cpp
index 5b056f83..9f99ff60 100644
--- a/src/pluginlist.cpp
+++ b/src/pluginlist.cpp
@@ -180,8 +180,8 @@ void PluginList::refresh(const QString& profileName,
auto gamePlugins = m_Organizer.gameFeatures().gameFeature<GamePlugins>();
const bool lightPluginsAreSupported =
gamePlugins ? gamePlugins->lightPluginsAreSupported() : false;
- const bool overridePluginsAreSupported =
- gamePlugins ? gamePlugins->overridePluginsAreSupported() : false;
+ const bool mediumPluginsAreSupported =
+ gamePlugins ? gamePlugins->mediumPluginsAreSupported() : false;
const bool loadOrderMechanismNone =
m_GamePlugin->loadOrderMechanism() == IPluginGame::LoadOrderMechanism::None;
@@ -245,7 +245,7 @@ void PluginList::refresh(const QString& profileName,
m_ESPs.emplace_back(filename, forceLoaded, forceEnabled, forceDisabled,
originName, ToQString(current->getFullPath()), hasIni,
loadedArchives, lightPluginsAreSupported,
- overridePluginsAreSupported);
+ mediumPluginsAreSupported);
m_ESPs.rbegin()->priority = -1;
} catch (const std::exception& e) {
reportError(tr("failed to update esp info for file %1 (source id: %2), error: %3")
@@ -998,23 +998,23 @@ bool PluginList::isMasterFlagged(const QString& name) const
}
}
-bool PluginList::isLightFlagged(const QString& name) const
+bool PluginList::isMediumFlagged(const QString& name) const
{
auto iter = m_ESPsByName.find(name);
if (iter == m_ESPsByName.end()) {
return false;
} else {
- return m_ESPs[iter->second].isLightFlagged;
+ return m_ESPs[iter->second].isMediumFlagged;
}
}
-bool PluginList::isOverlayFlagged(const QString& name) const
+bool PluginList::isLightFlagged(const QString& name) const
{
auto iter = m_ESPsByName.find(name);
if (iter == m_ESPsByName.end()) {
return false;
} else {
- return m_ESPs[iter->second].isOverlayFlagged;
+ return m_ESPs[iter->second].isLightFlagged;
}
}
@@ -1082,13 +1082,17 @@ void PluginList::updateIndices()
void PluginList::generatePluginIndexes()
{
int numESLs = 0;
+ int numESHs = 0;
int numSkipped = 0;
auto gamePlugins = m_Organizer.gameFeatures().gameFeature<GamePlugins>();
const bool lightPluginsSupported =
gamePlugins ? gamePlugins->lightPluginsAreSupported() : false;
- const bool overridePluginsSupported =
- gamePlugins ? gamePlugins->overridePluginsAreSupported() : false;
+ const bool mediumPluginsSupported =
+ gamePlugins ? gamePlugins->mediumPluginsAreSupported() : false;
+
+ std::vector<int> coreLightPlugins;
+ std::vector<int> coreMediumPlugins;
for (int l = 0; l < m_ESPs.size(); ++l) {
int i = m_ESPsByPriority.at(l);
@@ -1097,25 +1101,59 @@ void PluginList::generatePluginIndexes()
++numSkipped;
continue;
}
- if (lightPluginsSupported &&
- (m_ESPs[i].hasLightExtension || m_ESPs[i].isLightFlagged)) {
+ if (mediumPluginsSupported && m_ESPs[i].isMediumFlagged) {
+ if (mediumPluginsSupported && m_ESPs[i].forceLoaded) {
+ // Starfield core medium plugins are loaded in memory addresses after custom
+ // medium plugins
+ coreMediumPlugins.push_back(i);
+ ++numSkipped;
+ continue;
+ }
+ int ESHpos = 253 + ((numESHs + 1) / 256);
+ m_ESPs[i].index = QString("%1:%2")
+ .arg(ESHpos, 2, 16, QChar('0'))
+ .arg(numESHs % 256, 2, 16, QChar('0'))
+ .toUpper();
+ ++numESHs;
+
+ } else if (lightPluginsSupported &&
+ (m_ESPs[i].hasLightExtension || m_ESPs[i].isLightFlagged)) {
+ // Starfield core light plugins are loaded in memory addresses after custom light
+ // plugins
+ if (mediumPluginsSupported && m_ESPs[i].forceLoaded) {
+ coreLightPlugins.push_back(i);
+ ++numSkipped;
+ continue;
+ }
+
int ESLpos = 254 + ((numESLs + 1) / 4096);
m_ESPs[i].index = QString("%1:%2")
.arg(ESLpos, 2, 16, QChar('0'))
- .arg((numESLs) % 4096, 3, 16, QChar('0'))
+ .arg(numESLs % 4096, 3, 16, QChar('0'))
.toUpper();
++numESLs;
- // This logic may still be used if overlay plugins are fixed to longer consume a
- // load order slot
- //
- //} else if (overridePluginsSupported && m_ESPs[i].isOverlayFlagged) {
- // m_ESPs[i].index = QString("XX");
- // ++numSkipped;
} else {
- m_ESPs[i].index =
- QString("%1").arg(l - numESLs - numSkipped, 2, 16, QChar('0')).toUpper();
+ m_ESPs[i].index = QString("%1")
+ .arg(l - numESHs - numESLs - numSkipped, 2, 16, QChar('0'))
+ .toUpper();
}
}
+ for (auto pluginIndex : coreMediumPlugins) {
+ int ESHpos = 253 + ((numESHs + 1) / 4096);
+ m_ESPs[pluginIndex].index = QString("%1:%2")
+ .arg(ESHpos, 2, 16, QChar('0'))
+ .arg(numESHs % 256, 2, 16, QChar('0'))
+ .toUpper();
+ ++numESHs;
+ }
+ for (auto pluginIndex : coreLightPlugins) {
+ int ESLpos = 254 + ((numESLs + 1) / 4096);
+ m_ESPs[pluginIndex].index = QString("%1:%2")
+ .arg(ESLpos, 2, 16, QChar('0'))
+ .arg(numESLs % 4096, 3, 16, QChar('0'))
+ .toUpper();
+ ++numESLs;
+ }
emit esplist_changed();
}
@@ -1245,6 +1283,8 @@ QVariant PluginList::fontData(const QModelIndex& modelIndex) const
if (m_ESPs[index].hasMasterExtension || m_ESPs[index].isMasterFlagged ||
m_ESPs[index].hasLightExtension)
result.setWeight(QFont::Bold);
+ if (m_ESPs[index].isMediumFlagged)
+ result.setUnderline(true);
if (m_ESPs[index].isLightFlagged || m_ESPs[index].hasLightExtension)
result.setItalic(true);
@@ -1332,25 +1372,23 @@ QVariant PluginList::tooltipData(const QModelIndex& modelIndex) const
"be added to your game settings, overwriting in case of conflicts.");
}
+ if (esp.isMediumFlagged && esp.hasMasterExtension) {
+ toolTip += "<br><br>" +
+ tr("This ESM is flagged as a medium plugin (ESH). It adheres to the ESM "
+ "load order but loads records in ESH space (FD). You can have 256 "
+ "medium plugins in addition to other plugin types.");
+ }
+
if (esp.isLightFlagged && !esp.hasLightExtension) {
QString type = esp.hasMasterExtension ? "ESM" : "ESP";
toolTip +=
- "<br><br>" + tr("This %1 is flagged as an ESL. It will adhere to the %1 load "
- "order but the records will be loaded in ESL space.")
- .arg(type);
+ "<br><br>" +
+ tr("This %1 is flagged as a light plugin (ESL). It will adhere to the %1 load "
+ "order but the records will be loaded in ESL space (FE/FF). You can have up "
+ "to 4096 light plugins in addition to other plugin types.")
+ .arg(type);
}
- // This logic may still be used if overlay plugins are fixed to longer consume a load
- // order slot
- //
- // if (esp.isOverlayFlagged) {
- // toolTip +=
- // "<br><br>" + tr("This plugin is flagged as an overlay plugin. It contains
- // only "
- // "modified records and will overlay those changes onto the "
- // "existing records in memory. It takes no memory space.");
- // }
-
if (esp.hasNoRecords) {
toolTip += "<br><br>" + tr("This is a dummy plugin. It contains no records and is "
"typically used to load a paired archive file.");
@@ -1477,6 +1515,10 @@ QVariant PluginList::iconData(const QModelIndex& modelIndex) const
result.append(":/MO/gui/archive_conflict_neutral");
}
+ if (esp.isMediumFlagged) {
+ result.append(":/MO/gui/run");
+ }
+
if (esp.isLightFlagged && !esp.hasLightExtension) {
result.append(":/MO/gui/awaiting");
}
@@ -1485,10 +1527,6 @@ QVariant PluginList::iconData(const QModelIndex& modelIndex) const
result.append(":/MO/gui/unchecked-checkbox");
}
- if (esp.isOverlayFlagged) {
- result.append(":/MO/gui/instance_switch");
- }
-
if (info && !info->loot.dirty.empty()) {
result.append(":/MO/gui/edit_clear");
}
@@ -1801,7 +1839,7 @@ PluginList::ESPInfo::ESPInfo(const QString& name, bool forceLoaded, bool forceEn
bool forceDisabled, const QString& originName,
const QString& fullPath, bool hasIni,
std::set<QString> archives, bool lightSupported,
- bool overlaySupported)
+ bool mediumSupported)
: name(name), fullPath(fullPath), enabled(forceLoaded), forceLoaded(forceLoaded),
forceEnabled(forceEnabled), forceDisabled(forceDisabled), priority(0),
loadOrder(-1), originName(originName), hasIni(hasIni),
@@ -1813,9 +1851,9 @@ PluginList::ESPInfo::ESPInfo(const QString& name, bool forceLoaded, bool forceEn
hasMasterExtension = (extension == "esm");
hasLightExtension = (extension == "esl");
isMasterFlagged = file.isMaster();
- isOverlayFlagged = overlaySupported && file.isOverlay();
+ isMediumFlagged = mediumSupported && file.isMedium();
isLightFlagged =
- lightSupported && !isOverlayFlagged && file.isLight(overlaySupported);
+ lightSupported && !isMediumFlagged && file.isLight(mediumSupported);
hasNoRecords = file.isDummy();
author = QString::fromLatin1(file.author().c_str());
@@ -1829,7 +1867,7 @@ PluginList::ESPInfo::ESPInfo(const QString& name, bool forceLoaded, bool forceEn
hasMasterExtension = false;
hasLightExtension = false;
isMasterFlagged = false;
- isOverlayFlagged = false;
+ isMediumFlagged = false;
isLightFlagged = false;
hasNoRecords = false;
}
diff --git a/src/pluginlist.h b/src/pluginlist.h
index 3f4542fc..89c05141 100644
--- a/src/pluginlist.h
+++ b/src/pluginlist.h
@@ -240,8 +240,8 @@ public:
bool hasMasterExtension(const QString& name) const;
bool hasLightExtension(const QString& name) const;
bool isMasterFlagged(const QString& name) const;
+ bool isMediumFlagged(const QString& name) const;
bool isLightFlagged(const QString& name) const;
- bool isOverlayFlagged(const QString& name) const;
bool hasNoRecords(const QString& name) const;
boost::signals2::connection onRefreshed(const std::function<void()>& callback);
@@ -317,7 +317,7 @@ private:
ESPInfo(const QString& name, bool forceLoaded, bool forceEnabled,
bool forceDisabled, const QString& originName, const QString& fullPath,
bool hasIni, std::set<QString> archives, bool lightSupported,
- bool overrideSupported);
+ bool mediumSupported);
QString name;
QString fullPath;
@@ -333,8 +333,8 @@ private:
bool hasMasterExtension;
bool hasLightExtension;
bool isMasterFlagged;
+ bool isMediumFlagged;
bool isLightFlagged;
- bool isOverlayFlagged;
bool hasNoRecords;
bool modSelected;
QString author;
diff --git a/src/pluginlistproxy.cpp b/src/pluginlistproxy.cpp
index fa3960a8..8b826a81 100644
--- a/src/pluginlistproxy.cpp
+++ b/src/pluginlistproxy.cpp
@@ -114,14 +114,14 @@ bool PluginListProxy::isMasterFlagged(const QString& name) const
return m_Proxied->isMasterFlagged(name);
}
-bool PluginListProxy::isLightFlagged(const QString& name) const
+bool PluginListProxy::isMediumFlagged(const QString& name) const
{
- return m_Proxied->isLightFlagged(name);
+ return m_Proxied->isMediumFlagged(name);
}
-bool PluginListProxy::isOverlayFlagged(const QString& name) const
+bool PluginListProxy::isLightFlagged(const QString& name) const
{
- return m_Proxied->isOverlayFlagged(name);
+ return m_Proxied->isLightFlagged(name);
}
bool PluginListProxy::hasNoRecords(const QString& name) const
diff --git a/src/pluginlistproxy.h b/src/pluginlistproxy.h
index 397d786d..6865004a 100644
--- a/src/pluginlistproxy.h
+++ b/src/pluginlistproxy.h
@@ -32,8 +32,8 @@ public:
bool hasMasterExtension(const QString& name) const override;
bool hasLightExtension(const QString& name) const override;
bool isMasterFlagged(const QString& name) const override;
+ bool isMediumFlagged(const QString& name) const override;
bool isLightFlagged(const QString& name) const override;
- bool isOverlayFlagged(const QString& name) const override;
bool hasNoRecords(const QString& name) const override;
private:
diff --git a/src/pluginlistview.cpp b/src/pluginlistview.cpp
index 28f77821..8b34f75d 100644
--- a/src/pluginlistview.cpp
+++ b/src/pluginlistview.cpp
@@ -56,15 +56,15 @@ QModelIndexList PluginListView::indexViewToModel(const QModelIndexList& index) c
void PluginListView::updatePluginCount()
{
- int activeMasterCount = 0;
- int activeLightMasterCount = 0;
- int activeOverlayCount = 0;
- int activeRegularCount = 0;
- int masterCount = 0;
- int lightMasterCount = 0;
- int overlayCount = 0;
- int regularCount = 0;
- int activeVisibleCount = 0;
+ int activeMasterCount = 0;
+ int activeMediumMasterCount = 0;
+ int activeLightMasterCount = 0;
+ int activeRegularCount = 0;
+ int masterCount = 0;
+ int mediumMasterCount = 0;
+ int lightMasterCount = 0;
+ int regularCount = 0;
+ int activeVisibleCount = 0;
PluginList* list = m_core->pluginList();
QString filter = ui.filter->text();
@@ -72,7 +72,11 @@ void PluginListView::updatePluginCount()
for (QString plugin : list->pluginNames()) {
bool active = list->isEnabled(plugin);
bool visible = m_sortProxy->filterMatchesPlugin(plugin);
- if (list->hasLightExtension(plugin) || list->isLightFlagged(plugin)) {
+ if (list->isMediumFlagged(plugin)) {
+ mediumMasterCount++;
+ activeMediumMasterCount += active;
+ activeVisibleCount += visible && active;
+ } else if (list->hasLightExtension(plugin) || list->isLightFlagged(plugin)) {
lightMasterCount++;
activeLightMasterCount += active;
activeVisibleCount += visible && active;
@@ -80,10 +84,6 @@ void PluginListView::updatePluginCount()
masterCount++;
activeMasterCount += active;
activeVisibleCount += visible && active;
- } else if (list->isOverlayFlagged(plugin)) {
- overlayCount++;
- activeOverlayCount += active;
- activeVisibleCount += visible && active;
} else {
regularCount++;
activeRegularCount += active;
@@ -91,9 +91,9 @@ void PluginListView::updatePluginCount()
}
}
- int activeCount = activeMasterCount + activeLightMasterCount + activeOverlayCount +
- activeRegularCount;
- int totalCount = masterCount + lightMasterCount + overlayCount + regularCount;
+ int activeCount = activeMasterCount + activeMediumMasterCount +
+ activeLightMasterCount + activeRegularCount;
+ int totalCount = masterCount + mediumMasterCount + lightMasterCount + regularCount;
ui.counter->display(activeVisibleCount);
ui.counter->setToolTip(
@@ -105,8 +105,8 @@ void PluginListView::updatePluginCount()
"<tr><td>ESPs:</td><td align=right>%7 </td><td align=right>%8</td></tr>"
"<tr><td>ESMs+ESPs:</td><td align=right>%9 </td><td "
"align=right>%10</td></tr>"
+ "<tr><td>ESHs:</td><td align=right>%11 </td><td align=right>%12</td></tr>"
"<tr><td>ESLs:</td><td align=right>%5 </td><td align=right>%6</td></tr>"
- "<tr><td>Overlay:</td><td align=right>%11 </td><td align=right>%12</td></tr>"
"</table>")
.arg(activeCount)
.arg(totalCount)
@@ -118,8 +118,8 @@ void PluginListView::updatePluginCount()
.arg(regularCount)
.arg(activeMasterCount + activeRegularCount)
.arg(masterCount + regularCount)
- .arg(activeOverlayCount)
- .arg(overlayCount));
+ .arg(activeMediumMasterCount)
+ .arg(mediumMasterCount));
}
void PluginListView::onFilterChanged(const QString& filter)