1
0
mirror of https://gitlab.com/OpenMW/openmw.git synced 2025-04-01 13:20:29 +00:00

Merge branch 'quest_redo' into 'master'

Restart all quests with the same name when a quest is restarted

Closes #6606

See merge request OpenMW/openmw!1651
This commit is contained in:
psi29a 2022-02-13 15:31:18 +00:00
commit bd8c75daee
6 changed files with 35 additions and 28 deletions

View File

@ -274,6 +274,7 @@
Bug #6142: Groundcover plugins change cells flags
Bug #6276: Deleted groundcover instances are not deleted in game
Bug #6294: Game crashes with empty pathgrid
Bug #6606: Quests with multiple IDs cannot always be restarted
Feature #390: 3rd person look "over the shoulder"
Feature #832: OpenMW-CS: Handle deleted references
Feature #1536: Show more information about level on menu

View File

@ -7,6 +7,8 @@
#include <components/esm3/queststate.hpp>
#include <components/esm3/journalentry.hpp>
#include <components/misc/stringops.hpp>
#include "../mwworld/esmstore.hpp"
#include "../mwworld/class.hpp"
@ -93,7 +95,16 @@ namespace MWDialogue
StampedJournalEntry entry = StampedJournalEntry::makeFromQuest (id, index, actor);
Quest& quest = getQuest (id);
quest.addEntry (entry); // we are doing slicing on purpose here
if(quest.addEntry(entry)) // we are doing slicing on purpose here
{
// Restart all "other" quests with the same name as well
std::string name = quest.getName();
for(auto& it : mQuests)
{
if(it.second.isFinished() && Misc::StringUtils::ciEqual(it.second.getName(), name))
it.second.setFinished(false);
}
}
// there is no need to show empty entries in journal
if (!entry.getText().empty())

View File

@ -1,5 +1,7 @@
#include "quest.hpp"
#include <algorithm>
#include <components/esm3/queststate.hpp>
#include "../mwworld/esmstore.hpp"
@ -50,42 +52,33 @@ namespace MWDialogue
return mFinished;
}
void Quest::addEntry (const JournalEntry& entry)
void Quest::setFinished(bool finished)
{
int index = -1;
mFinished = finished;
}
bool Quest::addEntry (const JournalEntry& entry)
{
const ESM::Dialogue *dialogue =
MWBase::Environment::get().getWorld()->getStore().get<ESM::Dialogue>().find (entry.mTopic);
for (ESM::Dialogue::InfoContainer::const_iterator iter (dialogue->mInfo.begin());
iter!=dialogue->mInfo.end(); ++iter)
if (iter->mId == entry.mInfoId)
{
index = iter->mData.mJournalIndex;
break;
}
auto info = std::find_if(dialogue->mInfo.begin(), dialogue->mInfo.end(), [&](const auto& info) { return info.mId == entry.mInfoId; });
if (index==-1)
if (info == dialogue->mInfo.end() || info->mData.mJournalIndex == -1)
throw std::runtime_error ("unknown journal entry for topic " + mTopic);
for (auto &info : dialogue->mInfo)
{
if (info.mData.mJournalIndex == index
&& (info.mQuestStatus == ESM::DialInfo::QS_Finished || info.mQuestStatus == ESM::DialInfo::QS_Restart))
{
mFinished = (info.mQuestStatus == ESM::DialInfo::QS_Finished);
break;
}
}
if (info->mQuestStatus == ESM::DialInfo::QS_Finished || info->mQuestStatus == ESM::DialInfo::QS_Restart)
mFinished = info->mQuestStatus == ESM::DialInfo::QS_Finished;
if (index > mIndex)
mIndex = index;
if (info->mData.mJournalIndex > mIndex)
mIndex = info->mData.mJournalIndex;
for (TEntryIter iter (mEntries.begin()); iter!=mEntries.end(); ++iter)
if (iter->mInfoId==entry.mInfoId)
return;
return info->mQuestStatus == ESM::DialInfo::QS_Restart;
mEntries.push_back (entry); // we want slicing here
return info->mQuestStatus == ESM::DialInfo::QS_Restart;
}
void Quest::write (ESM::QuestState& state) const

View File

@ -33,9 +33,10 @@ namespace MWDialogue
///< Calling this function with a non-existent index will throw an exception.
bool isFinished() const;
void setFinished(bool finished);
void addEntry (const JournalEntry& entry) override;
///< Add entry and adjust index accordingly.
bool addEntry (const JournalEntry& entry) override;
///< Add entry and adjust index accordingly. Returns true if the quest should be restarted.
///
/// \note Redundant entries are ignored, but the index is still adjusted.

View File

@ -18,7 +18,7 @@ namespace MWDialogue
Topic::~Topic()
{}
void Topic::addEntry (const JournalEntry& entry)
bool Topic::addEntry (const JournalEntry& entry)
{
if (entry.mTopic!=mTopic)
throw std::runtime_error ("topic does not match: " + mTopic);
@ -27,10 +27,11 @@ namespace MWDialogue
for (Topic::TEntryIter it = mEntries.begin(); it != mEntries.end(); ++it)
{
if (it->mInfoId == entry.mInfoId)
return;
return false;
}
mEntries.push_back (entry); // we want slicing here
return false;
}
void Topic::insertEntry (const ESM::JournalEntry& entry)

View File

@ -35,7 +35,7 @@ namespace MWDialogue
virtual ~Topic();
virtual void addEntry (const JournalEntry& entry);
virtual bool addEntry (const JournalEntry& entry);
///< Add entry
///
/// \note Redundant entries are ignored.