diff --git a/apps/openmw/CMakeLists.txt b/apps/openmw/CMakeLists.txt index 63add2fce..8fa6d6591 100644 --- a/apps/openmw/CMakeLists.txt +++ b/apps/openmw/CMakeLists.txt @@ -72,11 +72,13 @@ set(GAMEDIALOGUE_HEADER mwdialogue/dialoguemanager.hpp mwdialogue/journal.hpp mwdialogue/journalentry.hpp + mwdialogue/quest.hpp ) set(GAMEDIALOGUE mwdialogue/dialoguemanager.cpp mwdialogue/journal.cpp mwdialogue/journalentry.cpp + mwdialogue/quest.cpp ) source_group(apps\\openmw\\mwdialogue FILES ${GAMEDIALOGUE_HEADER} ${GAMEDIALOGUE}) diff --git a/apps/openmw/mwdialogue/journal.cpp b/apps/openmw/mwdialogue/journal.cpp index 570d32d36..b1d85f729 100644 --- a/apps/openmw/mwdialogue/journal.cpp +++ b/apps/openmw/mwdialogue/journal.cpp @@ -3,22 +3,44 @@ #include "../mwworld/environment.hpp" -#include namespace MWDialogue { + Quest& Journal::getQuest (const std::string& id) + { + TQuestContainer::iterator iter = mQuests.find (id); + + if (iter==mQuests.end()) + { + std::pair result = + mQuests.insert (std::make_pair (id, Quest (id))); + + iter = result.first; + } + + return iter->second; + } + Journal::Journal (MWWorld::Environment& environment) : mEnvironment (environment) {} void Journal::addEntry (const std::string& id, int index) { - mJournal.push_back (StampedJournalEntry::makeFromQuest (id, index, *mEnvironment.mWorld)); - std::cout << "journal: " << id << " at " << index << std::endl; + StampedJournalEntry entry = + StampedJournalEntry::makeFromQuest (id, index, *mEnvironment.mWorld); + + mJournal.push_back (entry); + + Quest& quest = getQuest (id); + + quest.addEntry (entry, *mEnvironment.mWorld); // we are doing slicing on purpose here } void Journal::setJournalIndex (const std::string& id, int index) { - std::cout << "journal (no entry): " << id << " at " << index << std::endl; + Quest& quest = getQuest (id); + + quest.setIndex (index, *mEnvironment.mWorld); } int Journal::getJournalIndex (const std::string& id) const @@ -35,4 +57,14 @@ namespace MWDialogue { return mJournal.end(); } + + Journal::TQuestIter Journal::questBegin() const + { + return mQuests.begin(); + } + + Journal::TQuestIter Journal::questEnd() const + { + return mQuests.end(); + } } diff --git a/apps/openmw/mwdialogue/journal.hpp b/apps/openmw/mwdialogue/journal.hpp index 6b2b12cac..5477ae5a5 100644 --- a/apps/openmw/mwdialogue/journal.hpp +++ b/apps/openmw/mwdialogue/journal.hpp @@ -3,8 +3,10 @@ #include #include +#include #include "journalentry.hpp" +#include "quest.hpp" namespace MWWorld { @@ -13,17 +15,23 @@ namespace MWWorld namespace MWDialogue { + /// \brief The player's journal class Journal { public: typedef std::deque TEntryContainer; typedef TEntryContainer::const_iterator TEntryIter; + typedef std::map TQuestContainer; // topc, quest + typedef TQuestContainer::const_iterator TQuestIter; private: MWWorld::Environment& mEnvironment; TEntryContainer mJournal; + TQuestContainer mQuests; + + Quest& getQuest (const std::string& id); public: @@ -45,6 +53,12 @@ namespace MWDialogue TEntryIter end() const; ///< Iterator pointing past the end of the main journal. + + TQuestIter questBegin() const; + ///< Iterator pointing to the first quest (sorted by topic ID) + + TQuestIter questEnd() const; + ///< Iterator pointing past the last quest. }; } diff --git a/apps/openmw/mwdialogue/journalentry.hpp b/apps/openmw/mwdialogue/journalentry.hpp index 058843008..11b715630 100644 --- a/apps/openmw/mwdialogue/journalentry.hpp +++ b/apps/openmw/mwdialogue/journalentry.hpp @@ -1,5 +1,5 @@ #ifndef GAME_MMDIALOGUE_JOURNALENTRY_H -#define GAME_MWDIALOGUE_JOURNALENTRY_H +#define GAME_MMDIALOGUE_JOURNALENTRY_H #include diff --git a/apps/openmw/mwdialogue/quest.cpp b/apps/openmw/mwdialogue/quest.cpp new file mode 100644 index 000000000..13e432762 --- /dev/null +++ b/apps/openmw/mwdialogue/quest.cpp @@ -0,0 +1,96 @@ + +#include "quest.hpp" + +#include + +#include "../mwworld/world.hpp" + +namespace MWDialogue +{ + Quest::Quest() + : mIndex (0), mFinished (false) + {} + + Quest::Quest (const std::string& topic) + : mTopic (topic), mIndex (0), mFinished (false) + {} + + const std::string Quest::getName (const MWWorld::World& world) const + { + const ESM::Dialogue *dialogue = world.getStore().dialogs.find (mTopic); + + for (std::vector::const_iterator iter (dialogue->mInfo.begin()); + iter!=dialogue->mInfo.end(); ++iter) + if (iter->questStatus==ESM::DialInfo::QS_Name) + return iter->response; + + return ""; + } + + int Quest::getIndex() const + { + return mIndex; + } + + void Quest::setIndex (int index, const MWWorld::World& world) + { + const ESM::Dialogue *dialogue = world.getStore().dialogs.find (mTopic); + + for (std::vector::const_iterator iter (dialogue->mInfo.begin()); + iter!=dialogue->mInfo.end(); ++iter) + if (iter->data.disposition==index && iter->questStatus!=ESM::DialInfo::QS_Name) + { + mIndex = index; + + if (iter->questStatus==ESM::DialInfo::QS_Finished) + mFinished = true; + else if (iter->questStatus==ESM::DialInfo::QS_Restart) + mFinished = false; + + return; + } + + throw std::runtime_error ("unknown journal index for topic " + mTopic); + } + + bool Quest::isFinished() const + { + return mFinished; + } + + void Quest::addEntry (const JournalEntry& entry, const MWWorld::World& world) + { + int index = -1; + + const ESM::Dialogue *dialogue = world.getStore().dialogs.find (entry.mTopic); + + for (std::vector::const_iterator iter (dialogue->mInfo.begin()); + iter!=dialogue->mInfo.end(); ++iter) + if (iter->id==entry.mInfoId) + { + index = iter->data.disposition; /// \todo cleanup info structure + break; + } + + if (index==-1) + throw std::runtime_error ("unknown journal entry for topic " + mTopic); + + setIndex (index, world); + + for (TEntryIter iter (mEntries.begin()); iter!=mEntries.end(); ++iter) + if (iter->mInfoId==entry.mInfoId) + return; + + mEntries.push_back (entry); + } + + Quest::TEntryIter Quest::begin() + { + return mEntries.begin(); + } + + Quest::TEntryIter Quest::end() + { + return mEntries.end(); + } +} diff --git a/apps/openmw/mwdialogue/quest.hpp b/apps/openmw/mwdialogue/quest.hpp new file mode 100644 index 000000000..f484dfaf7 --- /dev/null +++ b/apps/openmw/mwdialogue/quest.hpp @@ -0,0 +1,60 @@ +#ifndef GAME_MMDIALOG_QUEST_H +#define GAME_MWDIALOG_QUEST_H + +#include +#include + +#include "journalentry.hpp" + +namespace MWWorld +{ + class World; +} + +namespace MWDialogue +{ + /// \brief A quest in progress or a compelted quest + class Quest + { + public: + + typedef std::vector TEntryContainer; + typedef TEntryContainer::const_iterator TEntryIter; + + private: + + std::string mTopic; + int mIndex; + std::vector mEntries; + bool mFinished; + + public: + + Quest(); + + Quest (const std::string& topic); + + const std::string getName (const MWWorld::World& world) const; + ///< May be an empty string + + int getIndex() const; + + void setIndex (int index, const MWWorld::World& world); + ///< Calling this function with a non-existant index while throw an exception. + + bool isFinished() const; + + void addEntry (const JournalEntry& entry, const MWWorld::World& world); + ///< Add entry and adjust index accordingly. + /// + /// \note Redundant entries are ignored, but the index is still adjusted. + + TEntryIter begin(); + ///< Iterator pointing to the begin of the journal for this quest. + + TEntryIter end(); + ///< Iterator pointing past the end of the journal for this quest. + }; +} + +#endif