diff --git a/CMakeLists.txt b/CMakeLists.txt index b2f2db5590..7d66cee80e 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -168,7 +168,7 @@ set(ESM ${COMP_DIR}/esm/loadsscr.cpp ${COMP_DIR}/esm/loadstat.cpp ${COMP_DIR}/esm/loadweap.cpp - + ) source_group(components\\esm FILES ${ESM_HEADER} ${ESM}) @@ -181,6 +181,14 @@ set(MISC_HEADER ${COMP_DIR}/misc/stringops.hpp) source_group(components\\misc FILES ${MISC} ${MISC_HEADER}) +set(FILES + ${COMP_DIR}/files/path.cpp + ) +set(FILES_HEADER + ${COMP_DIR}/files/path.hpp + ) +source_group(components\\files FILES ${FILES} ${FILES_HEADER}) + file(GLOB COMPILER ${COMP_DIR}/compiler/*.cpp) file(GLOB COMPILER_HEADER ${COMP_DIR}/compiler/*.hpp) source_group(components\\compiler FILES ${COMPILER} ${COMPILER_HEADER}) @@ -190,10 +198,10 @@ file(GLOB INTERPRETER_HEADER ${COMP_DIR}/interpreter/*.hpp) source_group(components\\interpreter FILES ${INTERPRETER} ${INTERPRETER_HEADER}) set(COMPONENTS ${BSA} ${NIF} ${NIFOGRE} ${ESM_STORE} ${MISC} ${TO_UTF8} - ${COMPILER} ${INTERPRETER} ${ESM} ${FILE_FINDER} ${NIFBULLET}) + ${COMPILER} ${INTERPRETER} ${ESM} ${FILE_FINDER} ${NIFBULLET} ${FILES}) set(COMPONENTS_HEADER ${BSA_HEADER} ${NIF_HEADER} ${NIFOGRE_HEADER} ${ESM_STORE_HEADER} ${ESM_HEADER} ${MISC_HEADER} ${COMPILER_HEADER} ${TO_UTF8_HEADER} - ${INTERPRETER_HEADER} ${FILE_FINDER_HEADER} ${NIFBULLET_HEADER}) + ${INTERPRETER_HEADER} ${FILE_FINDER_HEADER} ${NIFBULLET_HEADER} ${FILES_HEADER}) # source directory: libs @@ -337,8 +345,9 @@ endif (APPLE) # Other files configure_file(${OpenMW_SOURCE_DIR}/files/openmw.cfg.local - "${OpenMW_BINARY_DIR}/openmw.cfg" COPYONLY) - + "${OpenMW_BINARY_DIR}/openmw.cfg") +configure_file(${OpenMW_SOURCE_DIR}/files/openmw.cfg + "${OpenMW_BINARY_DIR}/openmw.cfg.install") if (WIN32) configure_file(${OpenMW_SOURCE_DIR}/files/plugins.cfg.win32 @@ -353,28 +362,29 @@ endif() if (APPLE) configure_file(${OpenMW_SOURCE_DIR}/files/plugins.cfg.mac "${APP_BUNDLE_DIR}/Contents/MacOS/plugins.cfg") - + configure_file(${OpenMW_SOURCE_DIR}/files/mac/Info.plist "${APP_BUNDLE_DIR}/Contents/Info.plist" COPYONLY) - + configure_file(${OpenMW_SOURCE_DIR}/files/mac/openmw.icns "${APP_BUNDLE_DIR}/Contents/Resources/OpenMW.icns" COPYONLY) - + # prepare plugins configure_file(${OGRE_PLUGIN_DIR}/RenderSystem_GL.dylib "${APP_BUNDLE_DIR}/Contents/Plugins/RenderSystem_GL.dylib" COPYONLY) - + configure_file(${OGRE_PLUGIN_DIR}/Plugin_OctreeSceneManager.dylib "${APP_BUNDLE_DIR}/Contents/Plugins/Plugin_OctreeSceneManager.dylib" COPYONLY) - + configure_file(${OGRE_PLUGIN_DIR}/Plugin_ParticleFX.dylib "${APP_BUNDLE_DIR}/Contents/Plugins/Plugin_ParticleFX.dylib" COPYONLY) - + + configure_file(${OpenMW_SOURCE_DIR}/files/openmw.cfg + "${APP_BUNDLE_DIR}/Contents/MacOS/openmw.cfg") + endif (APPLE) -configure_file(${OpenMW_SOURCE_DIR}/files/openmw.cfg - "${APP_BUNDLE_DIR}/Contents/MacOS/openmw.cfg") # Compiler settings if (CMAKE_COMPILER_IS_GNUCC) @@ -384,13 +394,13 @@ endif (CMAKE_COMPILER_IS_GNUCC) # Apple bundling if (APPLE) - set(MISC_FILES + set(MISC_FILES ${APP_BUNDLE_DIR}/Contents/MacOS/openmw.cfg ${APP_BUNDLE_DIR}/Contents/MacOS/plugins.cfg) - - set(OGRE_PLUGINS - ${APP_BUNDLE_DIR}/Contents/Plugins/*) - + + set(OGRE_PLUGINS + ${APP_BUNDLE_DIR}/Contents/Plugins/*) + install(FILES ${MISC_FILES} DESTINATION ../MacOS) install(DIRECTORY "${APP_BUNDLE_DIR}/Contents/Plugins" DESTINATION ..) install(DIRECTORY "${APP_BUNDLE_DIR}/Contents/Resources/resources" DESTINATION ../Resources) @@ -427,7 +437,7 @@ if(DPKG_PROGRAM) endif() #Install global configuration files - INSTALL(FILES "${OpenMW_SOURCE_DIR}/openmw.cfg" DESTINATION "../etc/openmw/" PERMISSIONS OWNER_READ OWNER_WRITE GROUP_READ WORLD_READ COMPONENT "openmw") + INSTALL(FILES "${OpenMW_BINARY_DIR}/openmw.cfg.install" DESTINATION "../etc/openmw/" RENAME "openmw.cfg" PERMISSIONS OWNER_READ OWNER_WRITE GROUP_READ WORLD_READ COMPONENT "openmw") INSTALL(FILES "${OpenMW_BINARY_DIR}/plugins.cfg" DESTINATION "../etc/openmw/" PERMISSIONS OWNER_READ OWNER_WRITE GROUP_READ WORLD_READ COMPONENT "openmw") #Install resources diff --git a/apps/openmw/CMakeLists.txt b/apps/openmw/CMakeLists.txt index 0fa027f0c6..b206934179 100644 --- a/apps/openmw/CMakeLists.txt +++ b/apps/openmw/CMakeLists.txt @@ -5,7 +5,7 @@ project(OpenMW) set(GAME main.cpp engine.cpp - path.cpp) + ) set(GAME_HEADER engine.hpp) source_group(game FILES ${GAME} ${GAME_HEADER}) @@ -70,9 +70,17 @@ source_group(apps\\openmw\\mwgui FILES ${GAMEGUI_HEADER} ${GAMEGUI}) set(GAMEDIALOGUE_HEADER mwdialogue/dialoguemanager.hpp + mwdialogue/journal.hpp + mwdialogue/journalentry.hpp + mwdialogue/quest.hpp + mwdialogue/topic.hpp ) set(GAMEDIALOGUE mwdialogue/dialoguemanager.cpp + mwdialogue/journal.cpp + mwdialogue/journalentry.cpp + mwdialogue/quest.cpp + mwdialogue/topic.cpp ) source_group(apps\\openmw\\mwdialogue FILES ${GAMEDIALOGUE_HEADER} ${GAMEDIALOGUE}) @@ -91,6 +99,7 @@ set(GAMESCRIPT mwscript/controlextensions.cpp mwscript/extensions.cpp mwscript/globalscripts.cpp + mwscript/dialogueextensions.cpp ) set(GAMESCRIPT_HEADER mwscript/locals.hpp @@ -109,6 +118,7 @@ set(GAMESCRIPT_HEADER mwscript/extensions.hpp mwscript/globalscripts.hpp mwscript/ref.hpp + mwscript/dialogueextensions.hpp ) source_group(apps\\openmw\\mwscript FILES ${GAMESCRIPT} ${GAMESCRIPT_HEADER}) diff --git a/apps/openmw/engine.cpp b/apps/openmw/engine.cpp index 78ddffbe8c..1ca5c68b45 100644 --- a/apps/openmw/engine.cpp +++ b/apps/openmw/engine.cpp @@ -14,6 +14,8 @@ #include #include #include +#include + #include #include "mwgui/window_manager.hpp" @@ -36,6 +38,7 @@ #include "mwclass/classes.hpp" #include "mwdialogue/dialoguemanager.hpp" +#include "mwdialogue/journal.hpp" #include "mwmechanics/mechanicsmanager.hpp" @@ -47,7 +50,6 @@ #include #include "mwgui/class.hpp" -#include "path.hpp" #include "components/nifbullet/bullet_nif_loader.hpp" @@ -228,6 +230,7 @@ OMW::Engine::~Engine() delete mEnvironment.mGlobalScripts; delete mEnvironment.mMechanicsManager; delete mEnvironment.mDialogueManager; + delete mEnvironment.mJournal; delete mScriptManager; delete mScriptContext; delete mPhysicEngine; @@ -322,12 +325,10 @@ void OMW::Engine::go() test.name = ""; total = 0; - - std::cout << "Data directory: " << mDataDir << "\n"; - std::string cfgDir = OMW::Path::getPath(OMW::Path::GLOBAL_CFG_PATH, "openmw", ""); - std::string cfgUserDir = OMW::Path::getPath(OMW::Path::USER_CFG_PATH, "openmw", ""); + std::string cfgDir = Files::getPath (Files::Path_ConfigGlobal, "openmw", ""); + std::string cfgUserDir = Files::getPath (Files::Path_ConfigUser, "openmw", ""); std::string plugCfg = "plugins.cfg"; std::string ogreCfg = "ogre.cfg"; ogreCfg.insert(0, cfgUserDir); @@ -396,6 +397,7 @@ void OMW::Engine::go() mEnvironment.mMechanicsManager = new MWMechanics::MechanicsManager (mEnvironment); // Create dialog system + mEnvironment.mJournal = new MWDialogue::Journal (mEnvironment); mEnvironment.mDialogueManager = new MWDialogue::DialogueManager (mEnvironment); // load cell diff --git a/apps/openmw/main.cpp b/apps/openmw/main.cpp index 7ba3fb4d6e..c5f53d7b56 100644 --- a/apps/openmw/main.cpp +++ b/apps/openmw/main.cpp @@ -6,8 +6,9 @@ #include #include +#include + #include "engine.hpp" -#include "path.hpp" #if defined(_WIN32) && !defined(_CONSOLE) #include @@ -78,12 +79,12 @@ bool parseOptions (int argc, char**argv, OMW::Engine& engine) std::string cfgFile = "openmw.cfg"; if(!isFile(cfgFile.c_str())) { - cfgFile = OMW::Path::getPath(OMW::Path::GLOBAL_CFG_PATH, "openmw", "openmw.cfg"); + cfgFile = Files::getPath (Files::Path_ConfigGlobal, "openmw", "openmw.cfg"); } std::cout << "Using global config file: " << cfgFile << std::endl; std::ifstream globalConfigFile(cfgFile.c_str()); - cfgFile = OMW::Path::getPath(OMW::Path::USER_CFG_PATH, "openmw", "openmw.cfg"); + cfgFile = Files::getPath (Files::Path_ConfigUser, "openmw", "openmw.cfg"); std::cout << "Using user config file: " << cfgFile << std::endl; std::ifstream userConfigFile(cfgFile.c_str()); diff --git a/apps/openmw/mwdialogue/journal.cpp b/apps/openmw/mwdialogue/journal.cpp new file mode 100644 index 0000000000..42cce5cf55 --- /dev/null +++ b/apps/openmw/mwdialogue/journal.cpp @@ -0,0 +1,95 @@ + +#include "journal.hpp" + +#include "../mwworld/environment.hpp" + +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) + { + 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) + { + Quest& quest = getQuest (id); + + quest.setIndex (index, *mEnvironment.mWorld); + } + + void Journal::addTopic (const std::string& topicId, const std::string& infoId) + { + TTopicContainer::iterator iter = mTopics.find (topicId); + + if (iter==mTopics.end()) + { + std::pair result + = mTopics.insert (std::make_pair (topicId, Topic (topicId))); + + iter = result.first; + } + + iter->second.addEntry (JournalEntry (topicId, infoId), *mEnvironment.mWorld); + } + + int Journal::getJournalIndex (const std::string& id) const + { + return 0; + } + + Journal::TEntryIter Journal::begin() const + { + return mJournal.begin(); + } + + Journal::TEntryIter Journal::end() const + { + return mJournal.end(); + } + + Journal::TQuestIter Journal::questBegin() const + { + return mQuests.begin(); + } + + Journal::TQuestIter Journal::questEnd() const + { + return mQuests.end(); + } + + Journal::TTopicIter Journal::topicBegin() const + { + return mTopics.begin(); + } + + Journal::TTopicIter Journal::topicEnd() const + { + return mTopics.end(); + } +} diff --git a/apps/openmw/mwdialogue/journal.hpp b/apps/openmw/mwdialogue/journal.hpp new file mode 100644 index 0000000000..ff1343945d --- /dev/null +++ b/apps/openmw/mwdialogue/journal.hpp @@ -0,0 +1,78 @@ +#ifndef GAME_MMDIALOG_JOURNAL_H +#define GAME_MWDIALOG_JOURNAL_H + +#include +#include +#include + +#include "journalentry.hpp" +#include "quest.hpp" + +namespace MWWorld +{ + struct Environment; +} + +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; + typedef std::map TTopicContainer; // topic-id, topic-content + typedef TTopicContainer::const_iterator TTopicIter; + + private: + + MWWorld::Environment& mEnvironment; + TEntryContainer mJournal; + TQuestContainer mQuests; + TTopicContainer mTopics; + + Quest& getQuest (const std::string& id); + + public: + + Journal (MWWorld::Environment& environment); + + void addEntry (const std::string& id, int index); + ///< Add a journal entry. + + void setJournalIndex (const std::string& id, int index); + ///< Set the journal index without adding an entry. + + int getJournalIndex (const std::string& id) const; + ///< Get the journal index. + + void addTopic (const std::string& topicId, const std::string& infoId); + + TEntryIter begin() const; + ///< Iterator pointing to the begin of the main journal. + /// + /// \note Iterators to main journal entries will never become invalid. + + 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. + + TTopicIter topicBegin() const; + ///< Iterator pointing to the first topic (sorted by topic ID) + /// + /// \note The topic ID is identical with the user-visible topic string. + + TTopicIter topicEnd() const; + ///< Iterator pointing past the last topic. + }; +} + +#endif diff --git a/apps/openmw/mwdialogue/journalentry.cpp b/apps/openmw/mwdialogue/journalentry.cpp new file mode 100644 index 0000000000..5e9dfa674a --- /dev/null +++ b/apps/openmw/mwdialogue/journalentry.cpp @@ -0,0 +1,69 @@ + +#include "journalentry.hpp" + +#include + +#include + +#include "../mwworld/world.hpp" + +namespace MWDialogue +{ + JournalEntry::JournalEntry() {} + + JournalEntry::JournalEntry (const std::string& topic, const std::string& infoId) + : mTopic (topic), mInfoId (infoId) + {} + + std::string JournalEntry::getText (const ESMS::ESMStore& store) const + { + const ESM::Dialogue *dialogue = store.dialogs.find (mTopic); + + for (std::vector::const_iterator iter (dialogue->mInfo.begin()); + iter!=dialogue->mInfo.end(); ++iter) + if (iter->id==mInfoId) + return iter->response; + + throw std::runtime_error ("unknown info ID " + mInfoId + " for topic " + mTopic); + } + + JournalEntry JournalEntry::makeFromQuest (const std::string& topic, int index, + const MWWorld::World& world) + { + return JournalEntry (topic, idFromIndex (topic, index, world)); + } + + std::string JournalEntry::idFromIndex (const std::string& topic, int index, + const MWWorld::World& world) + { + const ESM::Dialogue *dialogue = world.getStore().dialogs.find (topic); + + for (std::vector::const_iterator iter (dialogue->mInfo.begin()); + iter!=dialogue->mInfo.end(); ++iter) + if (iter->data.disposition==index) /// \todo cleanup info structure + { + iter->id; + } + + throw std::runtime_error ("unknown journal index for topic " + topic); + } + + StampedJournalEntry::StampedJournalEntry() + : mDay (0), mMonth (0), mDayOfMonth (0) + {} + + StampedJournalEntry::StampedJournalEntry (const std::string& topic, const std::string& infoId, + int day, int month, int dayOfMonth) + : JournalEntry (topic, infoId), mDay (day), mMonth (month), mDayOfMonth (dayOfMonth) + {} + + StampedJournalEntry StampedJournalEntry::makeFromQuest (const std::string& topic, int index, + const MWWorld::World& world) + { + int day = world.getGlobalVariable ("dayspassed").mLong; + int month = world.getGlobalVariable ("day").mLong; + int dayOfMonth = world.getGlobalVariable ("month").mLong; + + return StampedJournalEntry (topic, idFromIndex (topic, index, world), day, month, dayOfMonth); + } +} diff --git a/apps/openmw/mwdialogue/journalentry.hpp b/apps/openmw/mwdialogue/journalentry.hpp new file mode 100644 index 0000000000..11b7156301 --- /dev/null +++ b/apps/openmw/mwdialogue/journalentry.hpp @@ -0,0 +1,54 @@ +#ifndef GAME_MMDIALOGUE_JOURNALENTRY_H +#define GAME_MMDIALOGUE_JOURNALENTRY_H + +#include + +namespace ESMS +{ + struct ESMStore; +} + +namespace MWWorld +{ + class World; +} + +namespace MWDialogue +{ + /// \brief A quest or dialogue entry + struct JournalEntry + { + std::string mTopic; + std::string mInfoId; + + JournalEntry(); + + JournalEntry (const std::string& topic, const std::string& infoId); + + std::string getText (const ESMS::ESMStore& store) const; + + static JournalEntry makeFromQuest (const std::string& topic, int index, + const MWWorld::World& world); + + static std::string idFromIndex (const std::string& topic, int index, + const MWWorld::World& world); + }; + + /// \biref A quest entry with a timestamp. + struct StampedJournalEntry : public JournalEntry + { + int mDay; + int mMonth; + int mDayOfMonth; + + StampedJournalEntry(); + + StampedJournalEntry (const std::string& topic, const std::string& infoId, + int day, int month, int dayOfMonth); + + static StampedJournalEntry makeFromQuest (const std::string& topic, int index, + const MWWorld::World& world); + }; +} + +#endif diff --git a/apps/openmw/mwdialogue/quest.cpp b/apps/openmw/mwdialogue/quest.cpp new file mode 100644 index 0000000000..1f387e8621 --- /dev/null +++ b/apps/openmw/mwdialogue/quest.cpp @@ -0,0 +1,86 @@ + +#include "quest.hpp" + +#include + +#include "../mwworld/world.hpp" + +namespace MWDialogue +{ + Quest::Quest() + : Topic(), mIndex (0), mFinished (false) + {} + + Quest::Quest (const std::string& topic) + : Topic (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==entry.mInfoId) + return; + + mEntries.push_back (entry.mInfoId); + } +} diff --git a/apps/openmw/mwdialogue/quest.hpp b/apps/openmw/mwdialogue/quest.hpp new file mode 100644 index 0000000000..c162c03f45 --- /dev/null +++ b/apps/openmw/mwdialogue/quest.hpp @@ -0,0 +1,37 @@ +#ifndef GAME_MMDIALOG_QUEST_H +#define GAME_MWDIALOG_QUEST_H + +#include "topic.hpp" + +namespace MWDialogue +{ + /// \brief A quest in progress or a compelted quest + class Quest : public Topic + { + int mIndex; + 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; + + virtual 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. + }; +} + +#endif diff --git a/apps/openmw/mwdialogue/topic.cpp b/apps/openmw/mwdialogue/topic.cpp new file mode 100644 index 0000000000..8f165d3c8a --- /dev/null +++ b/apps/openmw/mwdialogue/topic.cpp @@ -0,0 +1,46 @@ + +#include "topic.hpp" + +#include + +#include "../mwworld/world.hpp" + +namespace MWDialogue +{ + Topic::Topic() + {} + + Topic::Topic (const std::string& topic) + : mTopic (topic) + {} + + Topic::~Topic() + {} + + void Topic::addEntry (const JournalEntry& entry, const MWWorld::World& world) + { + if (entry.mTopic!=mTopic) + throw std::runtime_error ("topic does not match: " + mTopic); + + for (TEntryIter iter = begin(); iter!=end(); ++iter) + if (*iter==entry.mInfoId) + return; + + mEntries.push_back (entry.mInfoId); + } + + Topic::TEntryIter Topic::begin() + { + return mEntries.begin(); + } + + Topic::TEntryIter Topic::end() + { + return mEntries.end(); + } + + JournalEntry Topic::getEntry (const std::string& infoId) + { + return JournalEntry (mTopic, infoId); + } +} diff --git a/apps/openmw/mwdialogue/topic.hpp b/apps/openmw/mwdialogue/topic.hpp new file mode 100644 index 0000000000..c085f1ed98 --- /dev/null +++ b/apps/openmw/mwdialogue/topic.hpp @@ -0,0 +1,52 @@ +#ifndef GAME_MMDIALOG_TOPIC_H +#define GAME_MWDIALOG_TOPIC_H + +#include +#include + +#include "journalentry.hpp" + +namespace MWWorld +{ + class World; +} + +namespace MWDialogue +{ + /// \brief Collection of seen responses for a topic + class Topic + { + public: + + typedef std::vector TEntryContainer; + typedef TEntryContainer::const_iterator TEntryIter; + + protected: + + std::string mTopic; + TEntryContainer mEntries; // info-IDs + + public: + + Topic(); + + Topic (const std::string& topic); + + virtual ~Topic(); + + virtual void addEntry (const JournalEntry& entry, const MWWorld::World& world); + ///< Add entry + /// + /// \note Redundant entries are ignored. + + TEntryIter begin(); + ///< Iterator pointing to the begin of the journal for this topic. + + TEntryIter end(); + ///< Iterator pointing past the end of the journal for this topic. + + JournalEntry getEntry (const std::string& infoId); + }; +} + +#endif diff --git a/apps/openmw/mwgui/birth.cpp b/apps/openmw/mwgui/birth.cpp index 7db93a5087..93dde9f1bf 100644 --- a/apps/openmw/mwgui/birth.cpp +++ b/apps/openmw/mwgui/birth.cpp @@ -119,8 +119,8 @@ void BirthDialog::updateBirths() { birthList->removeAllItems(); - ESMS::ESMStore &store = mWindowManager.getStore(); - + const ESMS::ESMStore &store = mWindowManager.getStore(); + ESMS::RecListT::MapType::const_iterator it = store.birthSigns.list.begin(); ESMS::RecListT::MapType::const_iterator end = store.birthSigns.list.end(); int index = 0; @@ -149,7 +149,7 @@ void BirthDialog::updateSpells() const int lineHeight = 18; MyGUI::IntCoord coord(0, 0, spellArea->getWidth(), 18); - ESMS::ESMStore &store = mWindowManager.getStore(); + const ESMS::ESMStore &store = mWindowManager.getStore(); const ESM::BirthSign *birth = store.birthSigns.find(currentBirthId); std::string texturePath = std::string("textures\\") + birth->texture; diff --git a/apps/openmw/mwgui/class.cpp b/apps/openmw/mwgui/class.cpp index 01516cfe25..ad94f30b1e 100644 --- a/apps/openmw/mwgui/class.cpp +++ b/apps/openmw/mwgui/class.cpp @@ -50,7 +50,7 @@ void GenerateClassResultDialog::setClassId(const std::string &classId) { currentClassId = classId; classImage->setImageTexture(std::string("textures\\levelup\\") + currentClassId + ".dds"); - ESMS::ESMStore &store = mWindowManager.getStore(); + const ESMS::ESMStore &store = mWindowManager.getStore(); className->setCaption(store.classes.find(currentClassId)->name); } @@ -196,8 +196,8 @@ void PickClassDialog::updateClasses() { classList->removeAllItems(); - ESMS::ESMStore &store = mWindowManager.getStore(); - + const ESMS::ESMStore &store = mWindowManager.getStore(); + ESMS::RecListT::MapType::const_iterator it = store.classes.list.begin(); ESMS::RecListT::MapType::const_iterator end = store.classes.list.end(); int index = 0; @@ -220,7 +220,7 @@ void PickClassDialog::updateStats() { if (currentClassId.empty()) return; - ESMS::ESMStore &store = mWindowManager.getStore(); + const ESMS::ESMStore &store = mWindowManager.getStore(); const ESM::Class *klass = store.classes.search(currentClassId); if (!klass) return; @@ -767,7 +767,7 @@ SelectSkillDialog::SelectSkillDialog(WindowManager& parWindowManager) { char theIndex = '0'+i; getWidget(combatSkill[i], std::string("CombatSkill").append(1, theIndex)); - getWidget(magicSkill[i], std::string("MagicSkill").append(1, theIndex)); + getWidget(magicSkill[i], std::string("MagicSkill").append(1, theIndex)); getWidget(stealthSkill[i], std::string("StealthSkill").append(1, theIndex)); } @@ -782,8 +782,8 @@ SelectSkillDialog::SelectSkillDialog(WindowManager& parWindowManager) {combatSkill[6], ESM::Skill::Axe}, {combatSkill[7], ESM::Skill::Spear}, {combatSkill[8], ESM::Skill::Athletics} - }, - { + }, + { {magicSkill[0], ESM::Skill::Enchant}, {magicSkill[1], ESM::Skill::Destruction}, {magicSkill[2], ESM::Skill::Alteration}, @@ -793,8 +793,8 @@ SelectSkillDialog::SelectSkillDialog(WindowManager& parWindowManager) {magicSkill[6], ESM::Skill::Restoration}, {magicSkill[7], ESM::Skill::Alchemy}, {magicSkill[8], ESM::Skill::Unarmored} - }, - { + }, + { {stealthSkill[0], ESM::Skill::Security}, {stealthSkill[1], ESM::Skill::Sneak}, {stealthSkill[2], ESM::Skill::Acrobatics}, diff --git a/apps/openmw/mwgui/console.cpp b/apps/openmw/mwgui/console.cpp index 836a0f0db9..0421dc370f 100644 --- a/apps/openmw/mwgui/console.cpp +++ b/apps/openmw/mwgui/console.cpp @@ -17,6 +17,8 @@ namespace MWGui ConsoleInterpreterContext (Console& console, MWWorld::Environment& environment, MWWorld::Ptr reference); + + virtual void report (const std::string& message); }; ConsoleInterpreterContext::ConsoleInterpreterContext (Console& console, @@ -26,6 +28,11 @@ namespace MWGui mConsole (console) {} + void ConsoleInterpreterContext::report (const std::string& message) + { + mConsole.printOK (message); + } + bool Console::compile (const std::string& cmd, Compiler::Output& output) { try diff --git a/apps/openmw/mwgui/race.cpp b/apps/openmw/mwgui/race.cpp index 65e6afd2ea..037f97fc36 100644 --- a/apps/openmw/mwgui/race.cpp +++ b/apps/openmw/mwgui/race.cpp @@ -212,8 +212,8 @@ void RaceDialog::updateRaces() { raceList->removeAllItems(); - ESMS::ESMStore &store = mWindowManager.getStore(); - + const ESMS::ESMStore &store = mWindowManager.getStore(); + ESMS::RecListT::MapType::const_iterator it = store.races.list.begin(); ESMS::RecListT::MapType::const_iterator end = store.races.list.end(); int index = 0; @@ -246,7 +246,7 @@ void RaceDialog::updateSkills() const int lineHeight = 18; MyGUI::IntCoord coord1(0, 0, skillList->getWidth(), 18); - ESMS::ESMStore &store = mWindowManager.getStore(); + const ESMS::ESMStore &store = mWindowManager.getStore(); const ESM::Race *race = store.races.find(currentRaceId); int count = sizeof(race->data.bonus)/sizeof(race->data.bonus[0]); // TODO: Find a portable macro for this ARRAYSIZE? for (int i = 0; i < count; ++i) @@ -282,7 +282,7 @@ void RaceDialog::updateSpellPowers() const int lineHeight = 18; MyGUI::IntCoord coord(0, 0, spellPowerList->getWidth(), 18); - ESMS::ESMStore &store = mWindowManager.getStore(); + const ESMS::ESMStore &store = mWindowManager.getStore(); const ESM::Race *race = store.races.find(currentRaceId); std::vector::const_iterator it = race->powers.list.begin(); diff --git a/apps/openmw/mwgui/stats_window.cpp b/apps/openmw/mwgui/stats_window.cpp index d08e6384d2..30a4015e33 100644 --- a/apps/openmw/mwgui/stats_window.cpp +++ b/apps/openmw/mwgui/stats_window.cpp @@ -323,7 +323,7 @@ void StatsWindow::updateSkillArea() if (!miscSkills.empty()) addSkills(miscSkills, "sSkillClassMisc", "Misc Skills", coord1, coord2); - ESMS::ESMStore &store = mWindowManager.getStore(); + const ESMS::ESMStore &store = mWindowManager.getStore(); if (!factions.empty()) { diff --git a/apps/openmw/mwgui/widgets.cpp b/apps/openmw/mwgui/widgets.cpp index 861939b7ed..f62da2bab9 100644 --- a/apps/openmw/mwgui/widgets.cpp +++ b/apps/openmw/mwgui/widgets.cpp @@ -278,7 +278,7 @@ void MWSpell::setSpellId(const std::string &spellId) void MWSpell::createEffectWidgets(std::vector &effects, MyGUI::WidgetPtr creator, MyGUI::IntCoord &coord) { - ESMS::ESMStore &store = mWindowManager->getStore(); + const ESMS::ESMStore &store = mWindowManager->getStore(); const ESM::Spell *spell = store.spells.search(id); MYGUI_ASSERT(spell, "spell with id '" << id << "' not found"); @@ -298,7 +298,7 @@ void MWSpell::updateWidgets() { if (spellNameWidget && mWindowManager) { - ESMS::ESMStore &store = mWindowManager->getStore(); + const ESMS::ESMStore &store = mWindowManager->getStore(); const ESM::Spell *spell = store.spells.search(id); if (spell) spellNameWidget->setCaption(spell->name); @@ -363,7 +363,7 @@ void MWSpellEffect::updateWidgets() if (!mWindowManager) return; - ESMS::ESMStore &store = mWindowManager->getStore(); + const ESMS::ESMStore &store = mWindowManager->getStore(); const ESM::MagicEffect *magicEffect = store.magicEffects.search(effect.effectID); if (textWidget) { diff --git a/apps/openmw/mwgui/window_manager.cpp b/apps/openmw/mwgui/window_manager.cpp index f0c409cbe3..2d7f70ef86 100644 --- a/apps/openmw/mwgui/window_manager.cpp +++ b/apps/openmw/mwgui/window_manager.cpp @@ -940,7 +940,7 @@ void WindowManager::onReviewActivateDialog(int parDialog) }; } -ESMS::ESMStore& WindowManager::getStore() +const ESMS::ESMStore& WindowManager::getStore() const { return environment.mWorld->getStore(); } diff --git a/apps/openmw/mwgui/window_manager.hpp b/apps/openmw/mwgui/window_manager.hpp index 1bf6204969..d3fbf3ea31 100644 --- a/apps/openmw/mwgui/window_manager.hpp +++ b/apps/openmw/mwgui/window_manager.hpp @@ -257,7 +257,7 @@ namespace MWGui */ const std::string &getGameSettingString(const std::string &id, const std::string &default_); - ESMS::ESMStore& getStore(); + const ESMS::ESMStore& getStore() const; private: diff --git a/apps/openmw/mwrender/mwscene.cpp b/apps/openmw/mwrender/mwscene.cpp index 890bf2cd6c..e4d449bf21 100644 --- a/apps/openmw/mwrender/mwscene.cpp +++ b/apps/openmw/mwrender/mwscene.cpp @@ -191,7 +191,7 @@ void MWScene::scaleObject (const std::string& handle, float scale) } -void MWScene::toggleCollisionMode() +bool MWScene::toggleCollisionMode() { for(std::map::iterator it = eng->PhysicActorMap.begin(); it != eng->PhysicActorMap.end();it++) { @@ -203,6 +203,7 @@ void MWScene::toggleCollisionMode() act->setGravity(0.); act->setVerticalVelocity(0); mFreeFly = true; + return false; } else { @@ -210,11 +211,15 @@ void MWScene::toggleCollisionMode() act->enableCollisions(true); act->setGravity(4.); act->setVerticalVelocity(0); + return true; } } + + return false; // This should never happen, but it shall not bother us now, since + // this part of the code needs a rewrite anyway. } -void MWScene::toggleRenderMode (int mode) +bool MWScene::toggleRenderMode (int mode) { switch (mode) { @@ -223,6 +228,8 @@ void MWScene::toggleRenderMode (int mode) // TODO use a proper function instead of accessing the member variable // directly. eng->setDebugRenderingMode (!eng->isDebugCreated); - break; + return eng->isDebugCreated; } + + return false; } diff --git a/apps/openmw/mwrender/mwscene.hpp b/apps/openmw/mwrender/mwscene.hpp index fd14fcce01..7429ff21e8 100644 --- a/apps/openmw/mwrender/mwscene.hpp +++ b/apps/openmw/mwrender/mwscene.hpp @@ -91,12 +91,14 @@ namespace MWRender /// Toggle collision mode for player. If disabled player object should ignore /// collisions and gravity. - void toggleCollisionMode(); + /// \return Resulting mode + bool toggleCollisionMode(); /// Toggle render mode /// \todo Using an int instead of a enum here to avoid cyclic includes. Will be fixed /// when the mw*-refactoring is done. - void toggleRenderMode (int mode); + /// \return Resulting mode + bool toggleRenderMode (int mode); }; } diff --git a/apps/openmw/mwscript/cellextensions.cpp b/apps/openmw/mwscript/cellextensions.cpp index 9c756e11f0..bb52632032 100644 --- a/apps/openmw/mwscript/cellextensions.cpp +++ b/apps/openmw/mwscript/cellextensions.cpp @@ -102,10 +102,42 @@ namespace MWScript } }; + class OpGetPCCell : public Interpreter::Opcode0 + { + public: + + virtual void execute (Interpreter::Runtime& runtime) + { + InterpreterContext& context + = static_cast (runtime.getContext()); + + std::string name = runtime.getStringLiteral (runtime[0].mInteger); + runtime.pop(); + + const ESM::Cell *cell = context.getWorld().getPlayer().getPlayer().getCell()->cell; + + std::string current = cell->name; + + if (!(cell->data.flags & ESM::Cell::Interior) && current.empty()) + { + const ESM::Region *region = + context.getWorld().getStore().regions.find (cell->region); + + current = region->name; + } + + bool match = current.length()>=name.length() && + current.substr (0, name.length())==name; + + runtime.push (match ? 1 : 0); + } + }; + const int opcodeCellChanged = 0x2000000; const int opcodeCOC = 0x2000026; const int opcodeCOE = 0x200008e; const int opcodeGetInterior = 0x2000131; + const int opcodeGetPCCell = 0x2000136; void registerExtensions (Compiler::Extensions& extensions) { @@ -115,6 +147,7 @@ namespace MWScript extensions.registerInstruction ("coe", "ll", opcodeCOE); extensions.registerInstruction ("centeronexterior", "ll", opcodeCOE); extensions.registerFunction ("getinterior", 'l', "", opcodeGetInterior); + extensions.registerFunction ("getpccell", 'l', "c", opcodeGetPCCell); } void installOpcodes (Interpreter::Interpreter& interpreter) @@ -123,6 +156,7 @@ namespace MWScript interpreter.installSegment5 (opcodeCOC, new OpCOC); interpreter.installSegment5 (opcodeCOE, new OpCOE); interpreter.installSegment5 (opcodeGetInterior, new OpGetInterior); + interpreter.installSegment5 (opcodeGetPCCell, new OpGetPCCell); } } } diff --git a/apps/openmw/mwscript/controlextensions.cpp b/apps/openmw/mwscript/controlextensions.cpp index f5a5c08a43..893af259fc 100644 --- a/apps/openmw/mwscript/controlextensions.cpp +++ b/apps/openmw/mwscript/controlextensions.cpp @@ -46,7 +46,9 @@ namespace MWScript InterpreterContext& context = static_cast (runtime.getContext()); - context.getWorld().toggleCollisionMode(); + bool enabled = context.getWorld().toggleCollisionMode(); + + context.report (enabled ? "Collsion -> On" : "Collision -> Off"); } }; @@ -74,6 +76,7 @@ namespace MWScript } extensions.registerInstruction ("togglecollision", "", opcodeToggleCollision); + extensions.registerInstruction ("tcl", "", opcodeToggleCollision); } void installOpcodes (Interpreter::Interpreter& interpreter) diff --git a/apps/openmw/mwscript/dialogueextensions.cpp b/apps/openmw/mwscript/dialogueextensions.cpp new file mode 100644 index 0000000000..c2ff9ed8bd --- /dev/null +++ b/apps/openmw/mwscript/dialogueextensions.cpp @@ -0,0 +1,94 @@ + +#include "dialogueextensions.hpp" + +#include + +#include +#include +#include + +#include "../mwdialogue/journal.hpp" + +#include "interpretercontext.hpp" + +namespace MWScript +{ + namespace Dialogue + { + class OpJournal : public Interpreter::Opcode0 + { + public: + + virtual void execute (Interpreter::Runtime& runtime) + { + MWScript::InterpreterContext& context + = static_cast (runtime.getContext()); + + std::string quest = runtime.getStringLiteral (runtime[0].mInteger); + runtime.pop(); + + Interpreter::Type_Integer index = runtime[0].mInteger; + runtime.pop(); + + context.getEnvironment().mJournal->addEntry (quest, index); + } + }; + + class OpSetJournalIndex : public Interpreter::Opcode0 + { + public: + + virtual void execute (Interpreter::Runtime& runtime) + { + MWScript::InterpreterContext& context + = static_cast (runtime.getContext()); + + std::string quest = runtime.getStringLiteral (runtime[0].mInteger); + runtime.pop(); + + Interpreter::Type_Integer index = runtime[0].mInteger; + runtime.pop(); + + context.getEnvironment().mJournal->setJournalIndex (quest, index); + } + }; + + class OpGetJournalIndex : public Interpreter::Opcode0 + { + public: + + virtual void execute (Interpreter::Runtime& runtime) + { + MWScript::InterpreterContext& context + = static_cast (runtime.getContext()); + + std::string quest = runtime.getStringLiteral (runtime[0].mInteger); + runtime.pop(); + + int index = context.getEnvironment().mJournal->getJournalIndex (quest); + + runtime.push (index); + + } + }; + + const int opcodeJournal = 0x2000133; + const int opcodeSetJournalIndex = 0x2000134; + const int opcodeGetJournalIndex = 0x2000135; + + void registerExtensions (Compiler::Extensions& extensions) + { + extensions.registerInstruction ("journal", "cl", opcodeJournal); + extensions.registerInstruction ("setjournalindex", "cl", opcodeSetJournalIndex); + extensions.registerFunction ("getjournalindex", 'l', "c", opcodeGetJournalIndex); + } + + void installOpcodes (Interpreter::Interpreter& interpreter) + { + interpreter.installSegment5 (opcodeJournal, new OpJournal); + interpreter.installSegment5 (opcodeSetJournalIndex, new OpSetJournalIndex); + interpreter.installSegment5 (opcodeGetJournalIndex, new OpGetJournalIndex); + } + } + +} diff --git a/apps/openmw/mwscript/dialogueextensions.hpp b/apps/openmw/mwscript/dialogueextensions.hpp new file mode 100644 index 0000000000..ece7d62ce8 --- /dev/null +++ b/apps/openmw/mwscript/dialogueextensions.hpp @@ -0,0 +1,25 @@ +#ifndef GAME_SCRIPT_DIALOGUEEXTENSIONS_H +#define GAME_SCRIPT_DIALOGUEEXTENSIONS_H + +namespace Compiler +{ + class Extensions; +} + +namespace Interpreter +{ + class Interpreter; +} + +namespace MWScript +{ + /// \brief Dialogue/Journal-related script functionality + namespace Dialogue + { + void registerExtensions (Compiler::Extensions& extensions); + + void installOpcodes (Interpreter::Interpreter& interpreter); + } +} + +#endif diff --git a/apps/openmw/mwscript/docs/vmformat.txt b/apps/openmw/mwscript/docs/vmformat.txt index d803d0bac2..fcebaae2be 100644 --- a/apps/openmw/mwscript/docs/vmformat.txt +++ b/apps/openmw/mwscript/docs/vmformat.txt @@ -104,4 +104,8 @@ op 0x2000115-0x200012f: ModSKill, explicit reference op 0x2000130: ToggleCollision op 0x2000131: GetInterior op 0x2000132: ToggleCollsionDebug -opcodes 0x2000133-0x3ffffff unused +op 0x2000133: Journal +op 0x2000134: SetJournalIndex +op 0x2000135: GetJournalIndex +op 0x2000136: GetPCCell +opcodes 0x2000137-0x3ffffff unused diff --git a/apps/openmw/mwscript/extensions.cpp b/apps/openmw/mwscript/extensions.cpp index 15d482fc19..86161d2b18 100644 --- a/apps/openmw/mwscript/extensions.cpp +++ b/apps/openmw/mwscript/extensions.cpp @@ -13,6 +13,7 @@ #include "containerextensions.hpp" #include "aiextensions.hpp" #include "controlextensions.hpp" +#include "dialogueextensions.hpp" namespace MWScript { @@ -27,6 +28,7 @@ namespace MWScript Container::registerExtensions (extensions); Ai::registerExtensions (extensions); Control::registerExtensions (extensions); + Dialogue::registerExtensions (extensions); } void installOpcodes (Interpreter::Interpreter& interpreter) @@ -41,5 +43,6 @@ namespace MWScript Container::installOpcodes (interpreter); Ai::installOpcodes (interpreter); Control::installOpcodes (interpreter); + Dialogue::installOpcodes (interpreter); } } diff --git a/apps/openmw/mwscript/interpretercontext.cpp b/apps/openmw/mwscript/interpretercontext.cpp index f2f1e6e104..77a71a1d4d 100644 --- a/apps/openmw/mwscript/interpretercontext.cpp +++ b/apps/openmw/mwscript/interpretercontext.cpp @@ -110,6 +110,11 @@ namespace MWScript mEnvironment.mWindowManager->messageBox (message, buttons); } + void InterpreterContext::report (const std::string& message) + { + messageBox (message); + } + bool InterpreterContext::menuMode() { return mEnvironment.mWindowManager->isGuiMode(); @@ -260,6 +265,11 @@ namespace MWScript mEnvironment.mWorld->disable (ref); } + MWWorld::Environment& InterpreterContext::getEnvironment() + { + return mEnvironment; + } + MWGui::WindowManager& InterpreterContext::getWindowManager() { return *mEnvironment.mWindowManager; diff --git a/apps/openmw/mwscript/interpretercontext.hpp b/apps/openmw/mwscript/interpretercontext.hpp index 031820d5dd..35b4a169d2 100644 --- a/apps/openmw/mwscript/interpretercontext.hpp +++ b/apps/openmw/mwscript/interpretercontext.hpp @@ -57,9 +57,13 @@ namespace MWScript virtual void setLocalFloat (int index, float value); using Interpreter::Context::messageBox; + virtual void messageBox (const std::string& message, const std::vector& buttons); + virtual void report (const std::string& message); + ///< By default echo via messageBox. + virtual bool menuMode(); virtual int getGlobalShort (const std::string& name) const; @@ -106,6 +110,10 @@ namespace MWScript virtual void disable (const std::string& id = ""); + MWWorld::Environment& getEnvironment(); + + /// \todo remove the following functions (extentions should use getEnvironment instead) + MWWorld::World& getWorld(); MWSound::SoundManager& getSoundManager(); diff --git a/apps/openmw/mwscript/miscextensions.cpp b/apps/openmw/mwscript/miscextensions.cpp index 9bfb8774d1..d8dfbdde47 100644 --- a/apps/openmw/mwscript/miscextensions.cpp +++ b/apps/openmw/mwscript/miscextensions.cpp @@ -99,7 +99,11 @@ namespace MWScript InterpreterContext& context = static_cast (runtime.getContext()); - context.getWorld().toggleRenderMode (MWWorld::World::Render_CollisionDebug); + bool enabled = + context.getWorld().toggleRenderMode (MWWorld::World::Render_CollisionDebug); + + context.report (enabled ? + "Collsion Mesh Rendering -> On" : "Collision Mesh Rendering -> Off"); } }; diff --git a/apps/openmw/mwscript/skyextensions.cpp b/apps/openmw/mwscript/skyextensions.cpp index f53168240d..caa07c0952 100644 --- a/apps/openmw/mwscript/skyextensions.cpp +++ b/apps/openmw/mwscript/skyextensions.cpp @@ -16,68 +16,70 @@ namespace MWScript class OpToggleSky : public Interpreter::Opcode0 { public: - + virtual void execute (Interpreter::Runtime& runtime) { InterpreterContext& context = static_cast (runtime.getContext()); - - context.getWorld().toggleSky(); - } - }; - + + bool enabled = context.getWorld().toggleSky(); + + context.report (enabled ? "Sky -> On" : "Sky -> Off"); + } + }; + class OpTurnMoonWhite : public Interpreter::Opcode0 { public: - + virtual void execute (Interpreter::Runtime& runtime) { InterpreterContext& context = static_cast (runtime.getContext()); - + context.getWorld().setMoonColour (false); - } - }; + } + }; class OpTurnMoonRed : public Interpreter::Opcode0 { public: - + virtual void execute (Interpreter::Runtime& runtime) { InterpreterContext& context = static_cast (runtime.getContext()); - + context.getWorld().setMoonColour (true); - } - }; - + } + }; + class OpGetMasserPhase : public Interpreter::Opcode0 { public: - + virtual void execute (Interpreter::Runtime& runtime) { InterpreterContext& context = static_cast (runtime.getContext()); - + runtime.push (context.getWorld().getMasserPhase()); - } - }; + } + }; class OpGetSecundaPhase : public Interpreter::Opcode0 { public: - + virtual void execute (Interpreter::Runtime& runtime) { InterpreterContext& context = static_cast (runtime.getContext()); - + runtime.push (context.getWorld().getSecundaPhase()); - } - }; - + } + }; + const int opcodeToggleSky = 0x2000021; const int opcodeTurnMoonWhite = 0x2000022; const int opcodeTurnMoonRed = 0x2000023; @@ -93,7 +95,7 @@ namespace MWScript extensions.registerFunction ("getmasserphase", 'l', "", opcodeGetMasserPhase); extensions.registerFunction ("getsecundaphase", 'l', "", opcodeGetSecundaPhase); } - + void installOpcodes (Interpreter::Interpreter& interpreter) { interpreter.installSegment5 (opcodeToggleSky, new OpToggleSky); @@ -101,7 +103,6 @@ namespace MWScript interpreter.installSegment5 (opcodeTurnMoonRed, new OpTurnMoonRed); interpreter.installSegment5 (opcodeGetMasserPhase, new OpGetMasserPhase); interpreter.installSegment5 (opcodeGetSecundaPhase, new OpGetSecundaPhase); - } + } } } - diff --git a/apps/openmw/mwworld/environment.hpp b/apps/openmw/mwworld/environment.hpp index c04dfcbf10..a403ee1657 100644 --- a/apps/openmw/mwworld/environment.hpp +++ b/apps/openmw/mwworld/environment.hpp @@ -24,6 +24,7 @@ namespace MWMechanics namespace MWDialogue { class DialogueManager; + class Journal; } namespace MWInput @@ -41,7 +42,7 @@ namespace MWWorld public: Environment() : mWorld (0), mSoundManager (0), mGlobalScripts (0), mWindowManager (0), - mMechanicsManager (0), mDialogueManager (0), mFrameDuration (0), + mMechanicsManager (0), mDialogueManager (0), mJournal (0), mFrameDuration (0), mInputManager (0) {} @@ -51,6 +52,7 @@ namespace MWWorld MWGui::WindowManager *mWindowManager; MWMechanics::MechanicsManager *mMechanicsManager; MWDialogue::DialogueManager *mDialogueManager; + MWDialogue::Journal *mJournal; float mFrameDuration; // For setting GUI mode diff --git a/apps/openmw/mwworld/world.cpp b/apps/openmw/mwworld/world.cpp index 63019349c8..81151ccdc0 100644 --- a/apps/openmw/mwworld/world.cpp +++ b/apps/openmw/mwworld/world.cpp @@ -460,7 +460,7 @@ namespace MWWorld return *mPlayer; } - ESMS::ESMStore& World::getStore() + const ESMS::ESMStore& World::getStore() const { return mStore; } @@ -480,6 +480,11 @@ namespace MWWorld return (*mGlobalVariables)[name]; } + Globals::Data World::getGlobalVariable (const std::string& name) const + { + return (*mGlobalVariables)[name]; + } + char World::getGlobalVariableType (const std::string& name) const { return mGlobalVariables->getType (name); @@ -645,12 +650,13 @@ namespace MWWorld mSkyManager->setDate (mGlobalVariables->getInt ("day"), month); } - void World::toggleSky() + bool World::toggleSky() { if (mSky) { mSky = false; mSkyManager->disable(); + return false; } else { @@ -660,6 +666,7 @@ namespace MWWorld mSkyManager->setDate (mGlobalVariables->getInt ("day"), mGlobalVariables->getInt ("month")); mSkyManager->enable(); + return true; } } @@ -853,13 +860,13 @@ namespace MWWorld mScene.doPhysics (duration, *this, actors); } - void World::toggleCollisionMode() + bool World::toggleCollisionMode() { - mScene.toggleCollisionMode(); + return mScene.toggleCollisionMode(); } - void World::toggleRenderMode (RenderMode mode) + bool World::toggleRenderMode (RenderMode mode) { - mScene.toggleRenderMode (mode); + return mScene.toggleRenderMode (mode); } } diff --git a/apps/openmw/mwworld/world.hpp b/apps/openmw/mwworld/world.hpp index 6965aebc6a..d722eb166b 100644 --- a/apps/openmw/mwworld/world.hpp +++ b/apps/openmw/mwworld/world.hpp @@ -115,7 +115,7 @@ namespace MWWorld MWWorld::Player& getPlayer(); - ESMS::ESMStore& getStore(); + const ESMS::ESMStore& getStore() const; const ScriptList& getLocalScripts() const; ///< Names and local variable state of all local scripts in active cells. @@ -125,6 +125,8 @@ namespace MWWorld Globals::Data& getGlobalVariable (const std::string& name); + Globals::Data getGlobalVariable (const std::string& name) const; + char getGlobalVariableType (const std::string& name) const; ///< Return ' ', if there is no global variable with this name. @@ -147,7 +149,8 @@ namespace MWWorld void setDay (int day); - void toggleSky(); + bool toggleSky(); + ///< \return Resulting mode int getMasserPhase() const; @@ -185,12 +188,14 @@ namespace MWWorld float duration); ///< Run physics simulation and modify \a world accordingly. - void toggleCollisionMode(); + bool toggleCollisionMode(); ///< Toggle collision mode for player. If disabled player object should ignore /// collisions and gravity. + ///< \return Resulting mode - void toggleRenderMode (RenderMode mode); + bool toggleRenderMode (RenderMode mode); ///< Toggle a render mode. + ///< \return Resulting mode }; } diff --git a/apps/openmw/path.hpp b/apps/openmw/path.hpp deleted file mode 100644 index 84ff9ecab3..0000000000 --- a/apps/openmw/path.hpp +++ /dev/null @@ -1,25 +0,0 @@ -#ifndef PATH__HPP -#define PATH__HPP - -#include -#include - -#if OGRE_PLATFORM == OGRE_PLATFORM_APPLE -#include -#endif - -namespace OMW -{ - class Path - { - public: - enum PathTypeEnum - { - USER_CFG_PATH, - GLOBAL_CFG_PATH - }; - - static std::string getPath(PathTypeEnum parType, const std::string parApp, const std::string parFile); - }; -} -#endif diff --git a/components/compiler/generator.cpp b/components/compiler/generator.cpp index 3d3b21d650..ee9876a147 100644 --- a/components/compiler/generator.cpp +++ b/components/compiler/generator.cpp @@ -125,6 +125,11 @@ namespace code.push_back (Compiler::Generator::segment3 (0, buttons)); } + void opReport (Compiler::Generator::CodeContainer& code) + { + code.push_back (Compiler::Generator::segment5 (58)); + } + void opFetchLocalShort (Compiler::Generator::CodeContainer& code) { code.push_back (Compiler::Generator::segment5 (21)); @@ -516,6 +521,14 @@ namespace Compiler opMessageBox (code, buttons); } + void report (CodeContainer& code, Literals& literals, const std::string& message) + { + int index = literals.addString (message); + + opPushInt (code, index); + opReport (code); + } + void fetchLocal (CodeContainer& code, char localType, int localIndex) { opPushInt (code, localIndex); diff --git a/components/compiler/generator.hpp b/components/compiler/generator.hpp index 5671949f20..fd1f954cad 100644 --- a/components/compiler/generator.hpp +++ b/components/compiler/generator.hpp @@ -81,6 +81,8 @@ namespace Compiler void message (CodeContainer& code, Literals& literals, const std::string& message, int buttons); + void report (CodeContainer& code, Literals& literals, const std::string& message); + void fetchLocal (CodeContainer& code, char localType, int localIndex); void jump (CodeContainer& code, int offset); diff --git a/components/compiler/lineparser.cpp b/components/compiler/lineparser.cpp index 5462f77886..834cd27b48 100644 --- a/components/compiler/lineparser.cpp +++ b/components/compiler/lineparser.cpp @@ -30,12 +30,12 @@ namespace Compiler { case 'l': - Generator::message (mCode, mLiterals, "%g", 0); + Generator::report (mCode, mLiterals, "%g"); break; case 'f': - Generator::message (mCode, mLiterals, "%f", 0); + Generator::report (mCode, mLiterals, "%f"); break; default: diff --git a/components/esm/defs.hpp b/components/esm/defs.hpp index 0fdbe45aa9..917c1031fe 100644 --- a/components/esm/defs.hpp +++ b/components/esm/defs.hpp @@ -23,12 +23,16 @@ enum VarType enum Specialization { - SPC_Combat = 0, SPC_Magic = 1, SPC_Stealth = 2 + SPC_Combat = 0, + SPC_Magic = 1, + SPC_Stealth = 2 }; enum RangeType { - RT_Self = 0, RT_Touch = 1, RT_Target = 2 + RT_Self = 0, + RT_Touch = 1, + RT_Target = 2 }; /** A list of references to spells and spell effects. This is shared diff --git a/components/esm/loadappa.hpp b/components/esm/loadappa.hpp index bbb4aefdea..2caca32b3d 100644 --- a/components/esm/loadappa.hpp +++ b/components/esm/loadappa.hpp @@ -14,7 +14,10 @@ struct Apparatus { enum AppaType { - MortarPestle = 0, Albemic = 1, Calcinator = 2, Retort = 3 + MortarPestle = 0, + Albemic = 1, + Calcinator = 2, + Retort = 3 }; struct AADTstruct diff --git a/components/esm/loadbody.hpp b/components/esm/loadbody.hpp index 14e28f59c4..de3db40fcd 100644 --- a/components/esm/loadbody.hpp +++ b/components/esm/loadbody.hpp @@ -29,12 +29,15 @@ struct BodyPart enum Flags { - BPF_Female = 1, BPF_Playable = 2 + BPF_Female = 1, + BPF_Playable = 2 }; enum MeshType { - MT_Skin = 0, MT_Clothing = 1, MT_Armor = 2 + MT_Skin = 0, + MT_Clothing = 1, + MT_Armor = 2 }; struct BYDTstruct diff --git a/components/esm/loadclas.hpp b/components/esm/loadclas.hpp index 5fc44abe52..08412c8384 100644 --- a/components/esm/loadclas.hpp +++ b/components/esm/loadclas.hpp @@ -38,7 +38,9 @@ struct Class enum Specialization { - Combat = 0, Magic = 1, Stealth = 2 + Combat = 0, + Magic = 1, + Stealth = 2 }; static const Specialization specializationIds[3]; diff --git a/components/esm/loadcrea.hpp b/components/esm/loadcrea.hpp index 40c9292136..3c334ebbd4 100644 --- a/components/esm/loadcrea.hpp +++ b/components/esm/loadcrea.hpp @@ -30,7 +30,10 @@ struct Creature enum Type { - Creatures = 0, Deadra = 1, Undead = 2, Humanoid = 3 + Creatures = 0, + Deadra = 1, + Undead = 2, + Humanoid = 3 }; struct NPDTstruct diff --git a/components/esm/loadsndg.hpp b/components/esm/loadsndg.hpp index f8803f8c0f..2953369c4c 100644 --- a/components/esm/loadsndg.hpp +++ b/components/esm/loadsndg.hpp @@ -3,7 +3,8 @@ #include "esm_reader.hpp" -namespace ESM { +namespace ESM +{ /* * Sound generator. This describes the sounds a creature make. @@ -11,24 +12,24 @@ namespace ESM { struct SoundGenerator { - enum Type + enum Type { - LeftFoot = 0, - RightFoot = 1, - SwimLeft = 2, - SwimRight = 3, - Moan = 4, - Roar = 5, - Scream = 6, - Land = 7 + LeftFoot = 0, + RightFoot = 1, + SwimLeft = 2, + SwimRight = 3, + Moan = 4, + Roar = 5, + Scream = 6, + Land = 7 }; - // Type - int type; + // Type + int type; - std::string creature, sound; + std::string creature, sound; - void load(ESMReader &esm); + void load(ESMReader &esm); }; } #endif diff --git a/apps/openmw/path.cpp b/components/files/path.cpp similarity index 82% rename from apps/openmw/path.cpp rename to components/files/path.cpp index e7dbc04715..a7b66822fd 100644 --- a/apps/openmw/path.cpp +++ b/components/files/path.cpp @@ -2,15 +2,21 @@ #include +#include +#include + +#if OGRE_PLATFORM == OGRE_PLATFORM_APPLE +#include +#endif + #if OGRE_PLATFORM == OGRE_PLATFORM_LINUX #include //getenv #endif - -std::string OMW::Path::getPath(PathTypeEnum parType, const std::string parApp, const std::string parFile) +std::string Files::getPath (PathTypeEnum parType, const std::string parApp, const std::string parFile) { std::string theBasePath; - if(parType == GLOBAL_CFG_PATH) + if (parType==Path_ConfigGlobal) { #if OGRE_PLATFORM == OGRE_PLATFORM_APPLE theBasePath = Ogre::macBundlePath() + "/Contents/MacOS/"; //FIXME do we have global/local with OSX? @@ -21,7 +27,7 @@ std::string OMW::Path::getPath(PathTypeEnum parType, const std::string parApp, c #endif } - else + else if (parType==Path_ConfigUser) { #if OGRE_PLATFORM == OGRE_PLATFORM_APPLE theBasePath = Ogre::macBundlePath() + "/Contents/MacOS/"; //FIXME do we have global/local with OSX? @@ -53,4 +59,3 @@ std::string OMW::Path::getPath(PathTypeEnum parType, const std::string parApp, c theBasePath.append(parFile); return theBasePath; } - diff --git a/components/files/path.hpp b/components/files/path.hpp new file mode 100644 index 0000000000..a426464040 --- /dev/null +++ b/components/files/path.hpp @@ -0,0 +1,17 @@ +#ifndef COMPONENTS_FILES_PATH_HPP +#define COMPONENTS_FILES_PATH_HPP + +#include + +namespace Files +{ + enum PathTypeEnum + { + Path_ConfigUser, + Path_ConfigGlobal + }; + + std::string getPath (PathTypeEnum parType, const std::string parApp, const std::string parFile); +} + +#endif diff --git a/components/interpreter/context.hpp b/components/interpreter/context.hpp index 0d77903f42..973b22d350 100644 --- a/components/interpreter/context.hpp +++ b/components/interpreter/context.hpp @@ -18,21 +18,23 @@ namespace Interpreter virtual float getLocalFloat (int index) const = 0; - virtual void setLocalShort (int index, int value) = 0; + virtual void setLocalShort (int index, int value) = 0; - virtual void setLocalLong (int index, int value) = 0; + virtual void setLocalLong (int index, int value) = 0; virtual void setLocalFloat (int index, float value) = 0; - + virtual void messageBox (const std::string& message, - const std::vector& buttons) = 0; - + const std::vector& buttons) = 0; + void messageBox (const std::string& message) { std::vector empty; messageBox (message, empty); } - + + virtual void report (const std::string& message) = 0; + virtual bool menuMode() = 0; virtual int getGlobalShort (const std::string& name) const = 0; @@ -41,31 +43,29 @@ namespace Interpreter virtual float getGlobalFloat (const std::string& name) const = 0; - virtual void setGlobalShort (const std::string& name, int value) = 0; + virtual void setGlobalShort (const std::string& name, int value) = 0; - virtual void setGlobalLong (const std::string& name, int value) = 0; + virtual void setGlobalLong (const std::string& name, int value) = 0; + + virtual void setGlobalFloat (const std::string& name, float value) = 0; - virtual void setGlobalFloat (const std::string& name, float value) = 0; - virtual bool isScriptRunning (const std::string& name) const = 0; - + virtual void startScript (const std::string& name) = 0; - + virtual void stopScript (const std::string& name) = 0; - + virtual float getDistance (const std::string& name, const std::string& id = "") const - = 0; - + = 0; + virtual float getSecondsPassed() const = 0; - + virtual bool isDisabled (const std::string& id = "") const = 0; - + virtual void enable (const std::string& id = "") = 0; - - virtual void disable (const std::string& id = "") = 0; + + virtual void disable (const std::string& id = "") = 0; }; } #endif - - diff --git a/components/interpreter/docs/vmformat.txt b/components/interpreter/docs/vmformat.txt index 6619fc30a1..3e513aa44e 100644 --- a/components/interpreter/docs/vmformat.txt +++ b/components/interpreter/docs/vmformat.txt @@ -117,5 +117,9 @@ op 55: explicit reference = stack[0]; pop; disable explicit reference op 56: explicit reference = stack[0]; pop; push 1, if explicit reference is disabled, 0 else op 57: explicit reference = stack[0]; pop; replace stack[0] with distance between explicit reference and a reference of ID stack[0] -opcodes 58-33554431 unused +op 58: report string literal index in stack[0]; + additional arguments (if any) in stack[n]..stack[1]; + n is determined according to the message string + all arguments are removed from stack +opcodes 59-33554431 unused opcodes 33554432-67108863 reserved for extensions diff --git a/components/interpreter/installopcodes.cpp b/components/interpreter/installopcodes.cpp index f383ff47c2..556477af25 100644 --- a/components/interpreter/installopcodes.cpp +++ b/components/interpreter/installopcodes.cpp @@ -95,6 +95,7 @@ namespace Interpreter interpreter.installSegment5 (54, new OpEnableExplicit); interpreter.installSegment5 (55, new OpDisableExplicit); interpreter.installSegment5 (56, new OpGetDisabledExplicit); + interpreter.installSegment5 (58, new OpReport); // script control interpreter.installSegment5 (46, new OpScriptRunning); @@ -106,4 +107,3 @@ namespace Interpreter interpreter.installSegment5 (57, new OpGetDistanceExplicit); } } - diff --git a/components/interpreter/miscopcodes.hpp b/components/interpreter/miscopcodes.hpp index fbee0aa266..37c38fc306 100644 --- a/components/interpreter/miscopcodes.hpp +++ b/components/interpreter/miscopcodes.hpp @@ -13,6 +13,66 @@ namespace Interpreter { + inline std::string formatMessage (const std::string& message, Runtime& runtime) + { + std::string formattedMessage; + + for (std::size_t i=0; i