Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Starfield Updates: Shattered Space & Blueprint Support #2131

Merged
merged 5 commits into from
Oct 3, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
174 changes: 129 additions & 45 deletions src/pluginlist.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -182,6 +182,8 @@ void PluginList::refresh(const QString& profileName,
gamePlugins ? gamePlugins->lightPluginsAreSupported() : false;
const bool mediumPluginsAreSupported =
gamePlugins ? gamePlugins->mediumPluginsAreSupported() : false;
const bool blueprintPluginsAreSupported =
gamePlugins ? gamePlugins->blueprintPluginsAreSupported() : false;
const bool loadOrderMechanismNone =
m_GamePlugin->loadOrderMechanism() == IPluginGame::LoadOrderMechanism::None;

Expand Down Expand Up @@ -245,7 +247,7 @@ void PluginList::refresh(const QString& profileName,
m_ESPs.emplace_back(filename, forceLoaded, forceEnabled, forceDisabled,
originName, ToQString(current->getFullPath()), hasIni,
loadedArchives, lightPluginsAreSupported,
mediumPluginsAreSupported);
mediumPluginsAreSupported, blueprintPluginsAreSupported);
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")
Expand Down Expand Up @@ -304,18 +306,33 @@ void PluginList::fixPrimaryPlugins()
// This function ensures that the primary plugins are first and in the correct order
QStringList primaryPlugins = m_Organizer.managedGame()->primaryPlugins();
int prio = 0;
int prioBlueprint = 0;
bool somethingChanged = false;
for (auto esp : m_ESPs) {
if (!esp.isBlueprintFlagged)
prioBlueprint++;
}
for (QString plugin : primaryPlugins) {
std::map<QString, int>::iterator iter = m_ESPsByName.find(plugin);
// Plugin is present?
if (iter != m_ESPsByName.end()) {
if (prio != m_ESPs[iter->second].priority) {
// Priority is wrong! Fix it!
int newPrio = prio;
setPluginPriority(iter->second, newPrio, true /* isForced */);
somethingChanged = true;
if (!m_ESPs[iter->second].isBlueprintFlagged) {
if (prio != m_ESPs[iter->second].priority) {
// Priority is wrong! Fix it!
int newPrio = prio;
setPluginPriority(iter->second, newPrio, true /* isForced */);
somethingChanged = true;
}
prio++;
} else {
if (prioBlueprint != m_ESPs[iter->second].priority) {
// Priority is wrong! Fix it!
int newPrio = prioBlueprint;
setPluginPriority(iter->second, newPrio, true /* isForced */);
somethingChanged = true;
}
prioBlueprint++;
}
prio++;
}
}

Expand All @@ -329,11 +346,20 @@ void PluginList::fixPluginRelationships()
TimeThis timer("PluginList::fixPluginRelationships");

// Count the types of plugins
int masterCount = 0;
int standardCount = 0;
int masterCount = 0;
int blueprintMasterCount = 0;
for (auto plugin : m_ESPs) {
if (plugin.hasLightExtension || plugin.hasMasterExtension ||
plugin.isMasterFlagged) {
masterCount++;
if (plugin.isBlueprintFlagged) {
blueprintMasterCount++;
} else {
masterCount++;
}
}
if (!plugin.isBlueprintFlagged) {
standardCount++;
}
}

Expand All @@ -342,14 +368,28 @@ void PluginList::fixPluginRelationships()
ESPInfo& plugin = m_ESPs[i];
if (plugin.hasLightExtension || plugin.hasMasterExtension ||
plugin.isMasterFlagged) {
if (plugin.priority > masterCount) {
int newPriority = masterCount + 1;
setPluginPriority(i, newPriority);
if (plugin.isBlueprintFlagged) {
if (plugin.priority > standardCount + blueprintMasterCount) {
int newPriority = standardCount + blueprintMasterCount;
setPluginPriority(i, newPriority);
}
} else {
if (plugin.priority > masterCount) {
int newPriority = masterCount;
setPluginPriority(i, newPriority);
}
}
} else {
if (plugin.priority < masterCount) {
int newPriority = masterCount + 1;
setPluginPriority(i, newPriority);
if (plugin.isBlueprintFlagged) {
if (plugin.priority < standardCount + blueprintMasterCount) {
int newPriority = standardCount + blueprintMasterCount + 1;
setPluginPriority(i, newPriority);
}
} else {
if (plugin.priority < masterCount) {
int newPriority = masterCount + 1;
setPluginPriority(i, newPriority);
}
}
}
}
Expand All @@ -361,7 +401,9 @@ void PluginList::fixPluginRelationships()
for (auto master : plugin.masters) {
auto iter = m_ESPsByName.find(master);
if (iter != m_ESPsByName.end()) {
newPriority = std::max(newPriority, m_ESPs[iter->second].priority);
if (m_ESPs.at(iter->second).isBlueprintFlagged == plugin.isBlueprintFlagged) {
newPriority = std::max(newPriority, m_ESPs[iter->second].priority);
}
}
}
if (newPriority != plugin.priority) {
Expand Down Expand Up @@ -1018,6 +1060,16 @@ bool PluginList::isLightFlagged(const QString& name) const
}
}

bool PluginList::isBlueprintFlagged(const QString& name) const
{
auto iter = m_ESPsByName.find(name);
if (iter == m_ESPsByName.end()) {
return false;
} else {
return m_ESPs[iter->second].isBlueprintFlagged;
}
}

bool PluginList::hasNoRecords(const QString& name) const
{
auto iter = m_ESPsByName.find(name);
Expand Down Expand Up @@ -1276,6 +1328,8 @@ QVariant PluginList::fontData(const QModelIndex& modelIndex) const
result.setItalic(true);
else if (m_ESPs[index].isMediumFlagged)
result.setUnderline(true);
if (m_ESPs[index].isBlueprintFlagged)
result.setLetterSpacing(QFont::SpacingType::AbsoluteSpacing, 2);

return result;
}
Expand Down Expand Up @@ -1376,6 +1430,13 @@ QVariant PluginList::tooltipData(const QModelIndex& modelIndex) const
"medium plugins in addition to other plugin types.");
}

if (esp.isBlueprintFlagged) {
toolTip += "<br><br>" +
tr("This plugin has the blueprint flag. This forces it to load after "
"every other non-blueprint plugin. Blueprint plugins will adhere to "
"standard load order rules with other blueprint plugins.");
}

if (esp.isLightFlagged && esp.isMediumFlagged) {
toolTip +=
"<br><br>" +
Expand Down Expand Up @@ -1521,6 +1582,10 @@ QVariant PluginList::iconData(const QModelIndex& modelIndex) const
}
}

if (esp.isBlueprintFlagged) {
result.append(":/MO/gui/resources/go-down.png");
}

if (esp.hasNoRecords) {
result.append(":/MO/gui/unchecked-checkbox");
}
Expand Down Expand Up @@ -1658,25 +1723,48 @@ void PluginList::setPluginPriority(int row, int& newPriority, bool isForced)
else if (newPriorityTemp >= static_cast<int>(m_ESPsByPriority.size()))
newPriorityTemp = static_cast<int>(m_ESPsByPriority.size()) - 1;

int blueprintStartPos = 0;
for (auto esp : m_ESPs) {
if (!esp.isBlueprintFlagged) {
blueprintStartPos++;
}
}

bool isBlueprint = m_ESPs[row].isBlueprintFlagged;
int lowerLimit = 0;
int upperLimit = 0;
if (isBlueprint) {
if (newPriorityTemp < blueprintStartPos) {
newPriorityTemp = blueprintStartPos;
}
lowerLimit = blueprintStartPos;
upperLimit = static_cast<int>(m_ESPsByPriority.size() - 1);
}
if (!isBlueprint) {
if (newPriorityTemp >= blueprintStartPos) {
newPriorityTemp = blueprintStartPos - 1;
}
upperLimit = blueprintStartPos - 1;
}
if (!m_ESPs[row].isMasterFlagged && !m_ESPs[row].hasLightExtension &&
!m_ESPs[row].hasMasterExtension) {
// don't allow esps to be moved above esms
while ((newPriorityTemp < static_cast<int>(m_ESPsByPriority.size() - 1)) &&
while ((newPriorityTemp < upperLimit) &&
(m_ESPs.at(m_ESPsByPriority.at(newPriorityTemp)).isMasterFlagged ||
m_ESPs.at(m_ESPsByPriority.at(newPriorityTemp)).hasLightExtension ||
m_ESPs.at(m_ESPsByPriority.at(newPriorityTemp)).hasMasterExtension)) {
++newPriorityTemp;
}
} else {
// don't allow esms to be moved below esps
while ((newPriorityTemp > 0) &&
while ((newPriorityTemp > lowerLimit) &&
!m_ESPs.at(m_ESPsByPriority.at(newPriorityTemp)).isMasterFlagged &&
!m_ESPs.at(m_ESPsByPriority.at(newPriorityTemp)).hasLightExtension &&
!m_ESPs.at(m_ESPsByPriority.at(newPriorityTemp)).hasMasterExtension) {
--newPriorityTemp;
}
// also don't allow "regular" esms to be moved above primary plugins
while ((newPriorityTemp < static_cast<int>(m_ESPsByPriority.size() - 1)) &&
while ((newPriorityTemp < upperLimit) &&
(m_ESPs.at(m_ESPsByPriority.at(newPriorityTemp)).forceLoaded)) {
++newPriorityTemp;
}
Expand All @@ -1688,9 +1776,12 @@ void PluginList::setPluginPriority(int row, int& newPriority, bool isForced)
for (auto master : m_ESPs[row].masters) {
auto iter = m_ESPsByName.find(master);
if (iter != m_ESPsByName.end()) {
int masterPriority = m_ESPs[iter->second].priority;
if (masterPriority >= newPriorityTemp) {
newPriorityTemp = masterPriority + 1;
if (m_ESPs[iter->second].isBlueprintFlagged ==
m_ESPs.at(row).isBlueprintFlagged) {
int masterPriority = m_ESPs[iter->second].priority;
if (masterPriority >= newPriorityTemp) {
newPriorityTemp = masterPriority + 1;
}
}
}
}
Expand All @@ -1699,9 +1790,15 @@ void PluginList::setPluginPriority(int row, int& newPriority, bool isForced)
for (int i = oldPriority + 1; i <= newPriorityTemp; i++) {
PluginList::ESPInfo* otherInfo = &m_ESPs.at(m_ESPsByPriority[i]);
for (auto master : otherInfo->masters) {
if (master.compare(m_ESPs[row].name, Qt::CaseInsensitive) == 0) {
newPriorityTemp = otherInfo->priority - 1;
break;
auto iter = m_ESPsByName.find(master);
if (iter != m_ESPsByName.end()) {
if (m_ESPs[iter->second].isBlueprintFlagged ==
otherInfo->isBlueprintFlagged) {
if (master.compare(m_ESPs[row].name, Qt::CaseInsensitive) == 0) {
newPriorityTemp = otherInfo->priority - 1;
break;
}
}
}
}
}
Expand Down Expand Up @@ -1741,23 +1838,6 @@ void PluginList::changePluginPriority(std::vector<int> rows, int newPriority)
ChangeBracket<PluginList> layoutChange(this);
const std::vector<ESPInfo>& esp = m_ESPs;

int minPriority = INT_MAX;
int maxPriority = INT_MIN;

// don't try to move plugins before force-enabled plugins
for (std::vector<ESPInfo>::const_iterator iter = m_ESPs.begin(); iter != m_ESPs.end();
++iter) {
if (iter->forceLoaded) {
newPriority = std::max(newPriority, iter->priority + 1);
}
maxPriority = std::max(maxPriority, iter->priority + 1);
minPriority = std::min(minPriority, iter->priority);
}

// limit the new priority to existing priorities
newPriority = std::min(newPriority, maxPriority);
newPriority = std::max(newPriority, minPriority);

// sort the moving plugins by ascending priorities
std::sort(rows.begin(), rows.end(), [&esp](const int& LHS, const int& RHS) {
return esp[LHS].priority < esp[RHS].priority;
Expand Down Expand Up @@ -1837,7 +1917,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 mediumSupported)
bool mediumSupported, bool blueprintSupported)
: name(name), fullPath(fullPath), enabled(forceLoaded), forceLoaded(forceLoaded),
forceEnabled(forceEnabled), forceDisabled(forceDisabled), priority(0),
loadOrder(-1), originName(originName), hasIni(hasIni),
Expand All @@ -1851,7 +1931,10 @@ PluginList::ESPInfo::ESPInfo(const QString& name, bool forceLoaded, bool forceEn
isMasterFlagged = file.isMaster();
isLightFlagged = lightSupported && file.isLight(mediumSupported);
isMediumFlagged = mediumSupported && file.isMedium();
hasNoRecords = file.isDummy();
isBlueprintFlagged = blueprintSupported &&
(isMasterFlagged || hasMasterExtension || hasLightExtension) &&
file.isBlueprint();
hasNoRecords = file.isDummy();

author = QString::fromLatin1(file.author().c_str());
description = QString::fromLatin1(file.description().c_str());
Expand All @@ -1864,8 +1947,9 @@ PluginList::ESPInfo::ESPInfo(const QString& name, bool forceLoaded, bool forceEn
hasMasterExtension = false;
hasLightExtension = false;
isMasterFlagged = false;
isMediumFlagged = false;
isLightFlagged = false;
isMediumFlagged = false;
isBlueprintFlagged = false;
hasNoRecords = false;
}
}
Expand Down
4 changes: 3 additions & 1 deletion src/pluginlist.h
Original file line number Diff line number Diff line change
Expand Up @@ -242,6 +242,7 @@ class PluginList : public QAbstractItemModel
bool isMasterFlagged(const QString& name) const;
bool isMediumFlagged(const QString& name) const;
bool isLightFlagged(const QString& name) const;
bool isBlueprintFlagged(const QString& name) const;
bool hasNoRecords(const QString& name) const;

QString author(const QString& name) const;
Expand Down Expand Up @@ -320,7 +321,7 @@ public slots:
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 mediumSupported);
bool mediumSupported, bool blueprintSupported);

QString name;
QString fullPath;
Expand All @@ -338,6 +339,7 @@ public slots:
bool isMasterFlagged;
bool isMediumFlagged;
bool isLightFlagged;
bool isBlueprintFlagged;
bool hasNoRecords;
bool modSelected;
QString author;
Expand Down
5 changes: 5 additions & 0 deletions src/pluginlistproxy.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -124,6 +124,11 @@ bool PluginListProxy::isLightFlagged(const QString& name) const
return m_Proxied->isLightFlagged(name);
}

bool PluginListProxy::isBlueprintFlagged(const QString& name) const
{
return m_Proxied->isBlueprintFlagged(name);
}

bool PluginListProxy::hasNoRecords(const QString& name) const
{
return m_Proxied->hasNoRecords(name);
Expand Down
1 change: 1 addition & 0 deletions src/pluginlistproxy.h
Original file line number Diff line number Diff line change
Expand Up @@ -34,6 +34,7 @@ class PluginListProxy : public MOBase::IPluginList
bool isMasterFlagged(const QString& name) const override;
bool isMediumFlagged(const QString& name) const override;
bool isLightFlagged(const QString& name) const override;
bool isBlueprintFlagged(const QString& name) const override;
bool hasNoRecords(const QString& name) const override;

QString author(const QString& name) const override;
Expand Down
Loading