mirror of
				https://github.com/OpenMW/openmw.git
				synced 2025-10-31 17:26:38 +00:00 
			
		
		
		
	Merge remote-tracking branch 'zini/master' into animation2
This commit is contained in:
		
						commit
						0cd3880b20
					
				
					 27 changed files with 345 additions and 86 deletions
				
			
		
							
								
								
									
										2
									
								
								.gitignore
									
									
									
									
										vendored
									
									
								
							
							
						
						
									
										2
									
								
								.gitignore
									
									
									
									
										vendored
									
									
								
							|  | @ -15,3 +15,5 @@ makefile | |||
| data | ||||
| *.kdev4 | ||||
| CMakeLists.txt.user | ||||
| *.swp | ||||
| *.swo | ||||
|  |  | |||
|  | @ -67,35 +67,6 @@ endif() | |||
| # We probably support older versions than this. | ||||
| cmake_minimum_required(VERSION 2.6) | ||||
| 
 | ||||
| # | ||||
| # Pre-built binaries being used? | ||||
| # | ||||
| IF(EXISTS "${CMAKE_SOURCE_DIR}/prebuilt/vc100-mt-gd/ogre_1_7_1") | ||||
|     set(PREBUILT_DIR "${CMAKE_SOURCE_DIR}/prebuilt/vc100-mt-gd") | ||||
|     message (STATUS "OpenMW pre-built binaries found at ${PREBUILT_DIR}.") | ||||
| 
 | ||||
|     SET(ENV{OGRE_HOME} "${PREBUILT_DIR}/ogre_1_7_1") | ||||
| 
 | ||||
|     SET(ENV{BOOST_ROOT} "${PREBUILT_DIR}/boost_1_42_0") | ||||
|     set(Boost_USE_STATIC_LIBS   ON) | ||||
|     set(Boost_USE_MULTITHREADED ON) | ||||
|     set(ENV{BOOST_INCLUDEDIR} "${BOOST_ROOT}/include") | ||||
|     set(ENV{BOOST_LIBRARYDIR} "${BOOST_ROOT}/lib") | ||||
| 
 | ||||
|     set(ENV{FREETYPE_DIR} "${PREBUILT_DIR}/freetype-2.3.5-1") | ||||
| 
 | ||||
|     set(USE_MPG123 OFF) | ||||
|     set(USE_AUDIERE ON) | ||||
|     set(AUDIERE_INCLUDE_DIR "${PREBUILT_DIR}/audiere-1.9.4/include") | ||||
|     set(AUDIERE_LIBRARY "${PREBUILT_DIR}/audiere-1.9.4/lib/audiere.lib") | ||||
| 
 | ||||
|     set(ENV{OPENALDIR} "${PREBUILT_DIR}/OpenAL 1.1 SDK") | ||||
| 
 | ||||
|     set(BULLET_ROOT "${PREBUILT_DIR}/bullet") | ||||
| ELSE() | ||||
|     message (STATUS "OpenMW pre-built binaries not found.  Using standard locations.") | ||||
| ENDIF() | ||||
| 
 | ||||
| # source directory: libs | ||||
| 
 | ||||
| set(LIBDIR ${CMAKE_SOURCE_DIR}/libs) | ||||
|  |  | |||
|  | @ -1,8 +1,8 @@ | |||
| 
 | ||||
| #include "columnbase.hpp" | ||||
| 
 | ||||
| CSMWorld::ColumnBase::ColumnBase (const std::string& title, int flags) | ||||
| : mTitle (title), mFlags (flags) | ||||
| CSMWorld::ColumnBase::ColumnBase (const std::string& title, Display displayType, int flags) | ||||
| : mTitle (title), mDisplayType (displayType), mFlags (flags) | ||||
| {} | ||||
| 
 | ||||
| CSMWorld::ColumnBase::~ColumnBase() {} | ||||
|  |  | |||
|  | @ -14,7 +14,8 @@ namespace CSMWorld | |||
|     { | ||||
|         enum Roles | ||||
|         { | ||||
|             Role_Flags = Qt::UserRole | ||||
|             Role_Flags = Qt::UserRole, | ||||
|             Role_Display = Qt::UserRole+1 | ||||
|         }; | ||||
| 
 | ||||
|         enum Flags | ||||
|  | @ -23,10 +24,18 @@ namespace CSMWorld | |||
|             Flag_Dialogue = 2 // column should be displayed in dialogue view
 | ||||
|         }; | ||||
| 
 | ||||
|         enum Display | ||||
|         { | ||||
|             Display_String, | ||||
|             Display_Integer, | ||||
|             Display_Float | ||||
|         }; | ||||
| 
 | ||||
|         std::string mTitle; | ||||
|         int mFlags; | ||||
|         Display mDisplayType; | ||||
| 
 | ||||
|         ColumnBase (const std::string& title, int flag); | ||||
|         ColumnBase (const std::string& title, Display displayType, int flag); | ||||
| 
 | ||||
|         virtual ~ColumnBase(); | ||||
| 
 | ||||
|  | @ -34,6 +43,7 @@ namespace CSMWorld | |||
| 
 | ||||
|         virtual bool isUserEditable() const; | ||||
|         ///< Can this column be edited directly by the user?
 | ||||
| 
 | ||||
|     }; | ||||
| 
 | ||||
|     template<typename ESXRecordT> | ||||
|  | @ -42,8 +52,8 @@ namespace CSMWorld | |||
|         std::string mTitle; | ||||
|         int mFlags; | ||||
| 
 | ||||
|         Column (const std::string& title, int flags = Flag_Table | Flag_Dialogue) | ||||
|         : ColumnBase (title, flags) {} | ||||
|         Column (const std::string& title, Display displayType, int flags = Flag_Table | Flag_Dialogue) | ||||
|         : ColumnBase (title, displayType, flags) {} | ||||
| 
 | ||||
|         virtual QVariant get (const Record<ESXRecordT>& record) const = 0; | ||||
| 
 | ||||
|  |  | |||
|  | @ -8,7 +8,7 @@ namespace CSMWorld | |||
|     template<typename ESXRecordT> | ||||
|     struct FloatValueColumn : public Column<ESXRecordT> | ||||
|     { | ||||
|         FloatValueColumn() : Column<ESXRecordT> ("Value") {} | ||||
|         FloatValueColumn() : Column<ESXRecordT> ("Value", ColumnBase::Display_Float) {} | ||||
| 
 | ||||
|         virtual QVariant get (const Record<ESXRecordT>& record) const | ||||
|         { | ||||
|  | @ -31,7 +31,7 @@ namespace CSMWorld | |||
|     template<typename ESXRecordT> | ||||
|     struct StringIdColumn : public Column<ESXRecordT> | ||||
|     { | ||||
|         StringIdColumn() : Column<ESXRecordT> ("ID") {} | ||||
|         StringIdColumn() : Column<ESXRecordT> ("ID", ColumnBase::Display_String) {} | ||||
| 
 | ||||
|         virtual QVariant get (const Record<ESXRecordT>& record) const | ||||
|         { | ||||
|  | @ -47,7 +47,7 @@ namespace CSMWorld | |||
|     template<typename ESXRecordT> | ||||
|     struct RecordStateColumn : public Column<ESXRecordT> | ||||
|     { | ||||
|         RecordStateColumn() : Column<ESXRecordT> ("*") {} | ||||
|         RecordStateColumn() : Column<ESXRecordT> ("*", ColumnBase::Display_Integer) {} | ||||
| 
 | ||||
|         virtual QVariant get (const Record<ESXRecordT>& record) const | ||||
|         { | ||||
|  | @ -78,7 +78,8 @@ namespace CSMWorld | |||
|     { | ||||
|         int mType; | ||||
| 
 | ||||
|         FixedRecordTypeColumn (int type) : Column<ESXRecordT> ("Type", 0), mType (type) {} | ||||
|         FixedRecordTypeColumn (int type) | ||||
|         : Column<ESXRecordT> ("Type", ColumnBase::Display_Integer, 0), mType (type) {} | ||||
| 
 | ||||
|         virtual QVariant get (const Record<ESXRecordT>& record) const | ||||
|         { | ||||
|  |  | |||
|  | @ -51,6 +51,9 @@ QVariant CSMWorld::IdTable::headerData (int section, Qt::Orientation orientation | |||
|     if (role==ColumnBase::Role_Flags) | ||||
|         return mIdCollection->getColumn (section).mFlags; | ||||
| 
 | ||||
|     if (role==ColumnBase::Role_Display) | ||||
|         return mIdCollection->getColumn (section).mDisplayType; | ||||
| 
 | ||||
|     return QVariant(); | ||||
| } | ||||
| 
 | ||||
|  |  | |||
|  | @ -4,8 +4,13 @@ | |||
| #include <QGridLayout> | ||||
| #include <QLabel> | ||||
| #include <QAbstractTableModel> | ||||
| #include <QDoubleSpinBox> | ||||
| #include <QSpinBox> | ||||
| #include <QLineEdit> | ||||
| #include <QDataWidgetMapper> | ||||
| 
 | ||||
| #include "../../model/world/columnbase.hpp" | ||||
| #include "../../model/world/idtable.hpp" | ||||
| 
 | ||||
| CSVWorld::DialogueSubView::DialogueSubView (const CSMWorld::UniversalId& id, CSMDoc::Document& document, | ||||
|     bool createAndDelete) | ||||
|  | @ -23,6 +28,9 @@ CSVWorld::DialogueSubView::DialogueSubView (const CSMWorld::UniversalId& id, CSM | |||
| 
 | ||||
|     int columns = model->columnCount(); | ||||
| 
 | ||||
|     mWidgetMapper = new QDataWidgetMapper (this); | ||||
|     mWidgetMapper->setModel (model); | ||||
| 
 | ||||
|     for (int i=0; i<columns; ++i) | ||||
|     { | ||||
|         int flags = model->headerData (i, Qt::Horizontal, CSMWorld::ColumnBase::Role_Flags).toInt(); | ||||
|  | @ -30,8 +38,54 @@ CSVWorld::DialogueSubView::DialogueSubView (const CSMWorld::UniversalId& id, CSM | |||
|         if (flags & CSMWorld::ColumnBase::Flag_Dialogue) | ||||
|         { | ||||
|             layout->addWidget (new QLabel (model->headerData (i, Qt::Horizontal).toString()), i, 0); | ||||
| 
 | ||||
|             CSMWorld::ColumnBase::Display display = static_cast<CSMWorld::ColumnBase::Display> | ||||
|                 (model->headerData (i, Qt::Horizontal, CSMWorld::ColumnBase::Role_Display).toInt()); | ||||
| 
 | ||||
|             QWidget *widget = 0; | ||||
| 
 | ||||
|             if (model->flags (model->index (0, i)) & Qt::ItemIsEditable) | ||||
|             { | ||||
|                 switch (display) | ||||
|                 { | ||||
|                     case CSMWorld::ColumnBase::Display_String: | ||||
| 
 | ||||
|                         layout->addWidget (widget = new QLineEdit, i, 1); | ||||
|                         break; | ||||
| 
 | ||||
|                     case CSMWorld::ColumnBase::Display_Integer: | ||||
| 
 | ||||
|                         /// \todo configure widget properly (range)
 | ||||
|                         layout->addWidget (widget = new QSpinBox, i, 1); | ||||
|                         break; | ||||
| 
 | ||||
|                     case CSMWorld::ColumnBase::Display_Float: | ||||
| 
 | ||||
|                         /// \todo configure widget properly (range, format?)
 | ||||
|                         layout->addWidget (widget = new QDoubleSpinBox, i, 1); | ||||
|                         break; | ||||
|                 } | ||||
|             } | ||||
|             else | ||||
|             { | ||||
|                 switch (display) | ||||
|                 { | ||||
|                     case CSMWorld::ColumnBase::Display_String: | ||||
|                     case CSMWorld::ColumnBase::Display_Integer: | ||||
|                     case CSMWorld::ColumnBase::Display_Float: | ||||
| 
 | ||||
|                         layout->addWidget (widget = new QLabel, i, 1); | ||||
|                         break; | ||||
|                 } | ||||
|             } | ||||
| 
 | ||||
|             if (widget) | ||||
|                 mWidgetMapper->addMapping (widget, i); | ||||
|         } | ||||
|     } | ||||
| 
 | ||||
|     mWidgetMapper->setCurrentModelIndex ( | ||||
|         dynamic_cast<CSMWorld::IdTable&> (*model).getModelIndex (id.getId(), 0)); | ||||
| } | ||||
| 
 | ||||
| void CSVWorld::DialogueSubView::setEditLock (bool locked) | ||||
|  |  | |||
|  | @ -3,6 +3,8 @@ | |||
| 
 | ||||
| #include "../doc/subview.hpp" | ||||
| 
 | ||||
| class QDataWidgetMapper; | ||||
| 
 | ||||
| namespace CSMDoc | ||||
| { | ||||
|     class Document; | ||||
|  | @ -12,6 +14,7 @@ namespace CSVWorld | |||
| { | ||||
|     class DialogueSubView : public CSVDoc::SubView | ||||
|     { | ||||
|             QDataWidgetMapper *mWidgetMapper; | ||||
| 
 | ||||
|         public: | ||||
| 
 | ||||
|  |  | |||
|  | @ -21,5 +21,6 @@ void CSVWorld::TableSubView::setEditLock (bool locked) | |||
| 
 | ||||
| void CSVWorld::TableSubView::rowActivated (const QModelIndex& index) | ||||
| { | ||||
|     focusId (mTable->getUniversalId (index.row())); | ||||
|     /// \todo re-enable, after dialogue sub views have been fixed up
 | ||||
| //    focusId (mTable->getUniversalId (index.row()));
 | ||||
| } | ||||
|  | @ -46,6 +46,7 @@ namespace MWWorld | |||
|     class LocalScripts; | ||||
|     class TimeStamp; | ||||
|     class ESMStore; | ||||
|     class RefData; | ||||
| } | ||||
| 
 | ||||
| namespace MWBase | ||||
|  | @ -139,6 +140,9 @@ namespace MWBase | |||
| 
 | ||||
|             virtual std::string getCurrentCellName() const = 0; | ||||
| 
 | ||||
|             virtual void removeRefScript (MWWorld::RefData *ref) = 0; | ||||
|             //< Remove the script attached to ref from mLocalScripts
 | ||||
| 
 | ||||
|             virtual MWWorld::Ptr getPtr (const std::string& name, bool activeOnly) = 0; | ||||
|             ///< Return a pointer to a liveCellRef with the given name.
 | ||||
|             /// \param activeOnly do non search inactive cells.
 | ||||
|  |  | |||
|  | @ -100,14 +100,15 @@ namespace MWClass | |||
|             } | ||||
|             else | ||||
|             { | ||||
|                 /// \todo do something with mNpdt12 maybe:p
 | ||||
|                 for (int i=0; i<8; ++i) | ||||
|                     data->mCreatureStats.getAttribute (i).set (10); | ||||
| 
 | ||||
|                 for (int i=0; i<3; ++i) | ||||
|                     data->mCreatureStats.setDynamic (i, 10); | ||||
| 
 | ||||
|                 data->mCreatureStats.setLevel (1); | ||||
|                 data->mCreatureStats.setLevel(ref->mBase->mNpdt12.mLevel); | ||||
|                 data->mNpcStats.setBaseDisposition(ref->mBase->mNpdt12.mDisposition); | ||||
|                 data->mNpcStats.setReputation(ref->mBase->mNpdt12.mReputation); | ||||
|             } | ||||
| 
 | ||||
|             data->mCreatureStats.setAiSetting (0, ref->mBase->mAiData.mHello); | ||||
|  |  | |||
|  | @ -20,6 +20,7 @@ | |||
| 
 | ||||
| #include "../mwbase/environment.hpp" | ||||
| #include "../mwbase/world.hpp" | ||||
| #include "../mwbase/journal.hpp" | ||||
| #include "../mwbase/scriptmanager.hpp" | ||||
| #include "../mwbase/windowmanager.hpp" | ||||
| #include "../mwbase/mechanicsmanager.hpp" | ||||
|  | @ -138,7 +139,8 @@ namespace MWDialogue | |||
|         { | ||||
|             if(it->mType == ESM::Dialogue::Greeting) | ||||
|             { | ||||
|                 if (const ESM::DialInfo *info = filter.search (*it)) | ||||
|                 // Search a response (we do not accept a fallback to "Info refusal" here)
 | ||||
|                 if (const ESM::DialInfo *info = filter.search (*it, false)) | ||||
|                 { | ||||
|                     //initialise the GUI
 | ||||
|                     MWBase::Environment::get().getWindowManager()->pushGuiMode(MWGui::GM_Dialogue); | ||||
|  | @ -247,12 +249,12 @@ namespace MWDialogue | |||
| 
 | ||||
|         const ESM::Dialogue& dialogue = *dialogues.find (topic); | ||||
| 
 | ||||
|         if (const ESM::DialInfo *info = filter.search (dialogue)) | ||||
|         MWGui::DialogueWindow* win = MWBase::Environment::get().getWindowManager()->getDialogueWindow(); | ||||
| 
 | ||||
|         if (const ESM::DialInfo *info = filter.search (dialogue, true)) | ||||
|         { | ||||
|             parseText (info->mResponse); | ||||
| 
 | ||||
|             MWGui::DialogueWindow* win = MWBase::Environment::get().getWindowManager()->getDialogueWindow(); | ||||
| 
 | ||||
|             if (dialogue.mType==ESM::Dialogue::Persuasion) | ||||
|             { | ||||
|                 std::string modifiedTopic = "s" + topic; | ||||
|  | @ -269,12 +271,20 @@ namespace MWDialogue | |||
| 
 | ||||
|             MWScript::InterpreterContext interpreterContext(&mActor.getRefData().getLocals(),mActor); | ||||
|             win->addText (Interpreter::fixDefinesDialog(info->mResponse, interpreterContext)); | ||||
|             MWBase::Environment::get().getJournal()->addTopic (topic, info->mId); | ||||
| 
 | ||||
|             executeScript (info->mResultScript); | ||||
| 
 | ||||
|             mLastTopic = topic; | ||||
|             mLastDialogue = *info; | ||||
|         } | ||||
|         else | ||||
|         { | ||||
|             // no response found, print a fallback text
 | ||||
|             win->addTitle (topic); | ||||
|             win->addText ("…"); | ||||
| 
 | ||||
|         } | ||||
|     } | ||||
| 
 | ||||
|     void DialogueManager::updateTopics() | ||||
|  | @ -293,7 +303,7 @@ namespace MWDialogue | |||
|         { | ||||
|             if (iter->mType == ESM::Dialogue::Topic) | ||||
|             { | ||||
|                 if (filter.search (*iter)) | ||||
|                 if (filter.responseAvailable (*iter)) | ||||
|                 { | ||||
|                     std::string lower = Misc::StringUtils::lowerCase(iter->mId); | ||||
|                     mActorKnownTopics.push_back (lower); | ||||
|  | @ -410,7 +420,7 @@ namespace MWDialogue | |||
|                 { | ||||
|                     Filter filter (mActor, mChoice, mTalkedTo); | ||||
| 
 | ||||
|                     if (const ESM::DialInfo *info = filter.search (mDialogueMap[mLastTopic])) | ||||
|                     if (const ESM::DialInfo *info = filter.search (mDialogueMap[mLastTopic], true)) | ||||
|                     { | ||||
|                         mChoiceMap.clear(); | ||||
|                         mChoice = -1; | ||||
|  | @ -420,6 +430,7 @@ namespace MWDialogue | |||
| 
 | ||||
|                         MWScript::InterpreterContext interpreterContext(&mActor.getRefData().getLocals(),mActor); | ||||
|                         MWBase::Environment::get().getWindowManager()->getDialogueWindow()->addText (Interpreter::fixDefinesDialog(text, interpreterContext)); | ||||
|                         MWBase::Environment::get().getJournal()->addTopic (mLastTopic, info->mId); | ||||
|                         executeScript (info->mResultScript); | ||||
|                         mLastTopic = mLastTopic; | ||||
|                         mLastDialogue = *info; | ||||
|  |  | |||
|  | @ -121,6 +121,18 @@ bool MWDialogue::Filter::testSelectStructs (const ESM::DialInfo& info) const | |||
|     return true; | ||||
| } | ||||
| 
 | ||||
| bool MWDialogue::Filter::testDisposition (const ESM::DialInfo& info) const | ||||
| { | ||||
|     bool isCreature = (mActor.getTypeName() != typeid (ESM::NPC).name()); | ||||
| 
 | ||||
|     if (isCreature) | ||||
|         return true; | ||||
| 
 | ||||
|     int actorDisposition = MWBase::Environment::get().getMechanicsManager()->getDerivedDisposition(mActor); | ||||
| 
 | ||||
|     return actorDisposition >= info.mData.mDisposition; | ||||
| } | ||||
| 
 | ||||
| bool MWDialogue::Filter::testSelectStruct (const SelectWrapper& select) const | ||||
| { | ||||
|     if (select.isNpcOnly() && mActor.getTypeName()!=typeid (ESM::NPC).name()) | ||||
|  | @ -162,7 +174,7 @@ bool MWDialogue::Filter::testSelectStructNumeric (const SelectWrapper& select) c | |||
|             int i = 0; | ||||
| 
 | ||||
|             for (; i<static_cast<int> (script->mVarNames.size()); ++i) | ||||
|                 if (script->mVarNames[i]==name) | ||||
|                 if (Misc::StringUtils::lowerCase(script->mVarNames[i]) == name) | ||||
|                     break; | ||||
| 
 | ||||
|             if (i>=static_cast<int> (script->mVarNames.size())) | ||||
|  | @ -547,18 +559,50 @@ MWDialogue::Filter::Filter (const MWWorld::Ptr& actor, int choice, bool talkedTo | |||
| : mActor (actor), mChoice (choice), mTalkedToPlayer (talkedToPlayer) | ||||
| {} | ||||
| 
 | ||||
| bool MWDialogue::Filter::operator() (const ESM::DialInfo& info) const | ||||
| const ESM::DialInfo *MWDialogue::Filter::search (const ESM::Dialogue& dialogue, const bool fallbackToInfoRefusal) const | ||||
| { | ||||
|     return testActor (info) && testPlayer (info) && testSelectStructs (info); | ||||
| } | ||||
|     bool infoRefusal = false; | ||||
| 
 | ||||
| const ESM::DialInfo *MWDialogue::Filter::search (const ESM::Dialogue& dialogue) const | ||||
| { | ||||
|     // Iterate over topic responses to find a matching one
 | ||||
|     for (std::vector<ESM::DialInfo>::const_iterator iter = dialogue.mInfo.begin(); | ||||
|         iter!=dialogue.mInfo.end(); ++iter) | ||||
|         if ((*this) (*iter)) | ||||
|             return &*iter; | ||||
|     { | ||||
|         if (testActor (*iter) && testPlayer (*iter) && testSelectStructs (*iter)) | ||||
|         { | ||||
|             if (testDisposition (*iter)) | ||||
|                 return &*iter; | ||||
|             else | ||||
|                 infoRefusal = true; | ||||
|         } | ||||
|     } | ||||
| 
 | ||||
|     if (infoRefusal && fallbackToInfoRefusal) | ||||
|     { | ||||
|         // No response is valid because of low NPC disposition,
 | ||||
|         // search a response in the topic "Info Refusal"
 | ||||
| 
 | ||||
|         const MWWorld::Store<ESM::Dialogue> &dialogues = | ||||
|             MWBase::Environment::get().getWorld()->getStore().get<ESM::Dialogue>(); | ||||
| 
 | ||||
|         const ESM::Dialogue& infoRefusalDialogue = *dialogues.find ("Info Refusal"); | ||||
| 
 | ||||
|         for (std::vector<ESM::DialInfo>::const_iterator iter = infoRefusalDialogue.mInfo.begin(); | ||||
|             iter!=infoRefusalDialogue.mInfo.end(); ++iter) | ||||
|             if (testActor (*iter) && testPlayer (*iter) && testSelectStructs (*iter) && testDisposition(*iter)) | ||||
|                 return &*iter; | ||||
|     } | ||||
| 
 | ||||
|     return 0; | ||||
| } | ||||
| 
 | ||||
| bool MWDialogue::Filter::responseAvailable (const ESM::Dialogue& dialogue) const | ||||
| { | ||||
|     for (std::vector<ESM::DialInfo>::const_iterator iter = dialogue.mInfo.begin(); | ||||
|         iter!=dialogue.mInfo.end(); ++iter) | ||||
|     { | ||||
|         if (testActor (*iter) && testPlayer (*iter) && testSelectStructs (*iter)) | ||||
|             return true; | ||||
|     } | ||||
| 
 | ||||
|     return false; | ||||
| } | ||||
|  |  | |||
|  | @ -18,40 +18,45 @@ namespace MWDialogue | |||
|             MWWorld::Ptr mActor; | ||||
|             int mChoice; | ||||
|             bool mTalkedToPlayer; | ||||
|      | ||||
| 
 | ||||
|             bool testActor (const ESM::DialInfo& info) const; | ||||
|             ///< Is this the right actor for this \a info?
 | ||||
|      | ||||
| 
 | ||||
|             bool testPlayer (const ESM::DialInfo& info) const; | ||||
|             ///< Do the player and the cell the player is currently in match \a info?
 | ||||
|      | ||||
| 
 | ||||
|             bool testSelectStructs (const ESM::DialInfo& info) const; | ||||
|             ///< Are all select structs matching?
 | ||||
|      | ||||
| 
 | ||||
|             bool testDisposition (const ESM::DialInfo& info) const; | ||||
|             ///< Is the actor disposition toward the player high enough?
 | ||||
| 
 | ||||
|             bool testSelectStruct (const SelectWrapper& select) const; | ||||
|      | ||||
| 
 | ||||
|             bool testSelectStructNumeric (const SelectWrapper& select) const; | ||||
|              | ||||
| 
 | ||||
|             int getSelectStructInteger (const SelectWrapper& select) const; | ||||
|              | ||||
| 
 | ||||
|             bool getSelectStructBoolean (const SelectWrapper& select) const; | ||||
|      | ||||
| 
 | ||||
|             int getFactionRank (const MWWorld::Ptr& actor, const std::string& factionId) const; | ||||
|              | ||||
| 
 | ||||
|             bool hasFactionRankSkillRequirements (const MWWorld::Ptr& actor, const std::string& factionId, | ||||
|                 int rank) const; | ||||
| 
 | ||||
|             bool hasFactionRankReputationRequirements (const MWWorld::Ptr& actor, const std::string& factionId, | ||||
|                 int rank) const; | ||||
|      | ||||
|         public: | ||||
|          | ||||
|             Filter (const MWWorld::Ptr& actor, int choice, bool talkedToPlayer);     | ||||
| 
 | ||||
|             bool operator() (const ESM::DialInfo& info) const;     | ||||
|             ///< \return does the dialogue match?
 | ||||
|              | ||||
|             const ESM::DialInfo *search (const ESM::Dialogue& dialogue) const; | ||||
|         public: | ||||
| 
 | ||||
|             Filter (const MWWorld::Ptr& actor, int choice, bool talkedToPlayer); | ||||
| 
 | ||||
|             const ESM::DialInfo *search (const ESM::Dialogue& dialogue, const bool fallbackToInfoRefusal) const; | ||||
|             ///< Get a matching response for the requested dialogue.
 | ||||
|             ///  Redirect to "Info Refusal" topic if a response fulfills all conditions but disposition.
 | ||||
| 
 | ||||
|             bool responseAvailable (const ESM::Dialogue& dialogue) const; | ||||
|             ///< Does a matching response exist? (disposition is ignored for this check)
 | ||||
|     }; | ||||
| } | ||||
| 
 | ||||
|  |  | |||
|  | @ -61,8 +61,8 @@ namespace MWDialogue | |||
|     StampedJournalEntry StampedJournalEntry::makeFromQuest (const std::string& topic, int index) | ||||
|     { | ||||
|         int day = MWBase::Environment::get().getWorld()->getGlobalVariable ("dayspassed").mLong; | ||||
|         int month = MWBase::Environment::get().getWorld()->getGlobalVariable ("day").mLong; | ||||
|         int dayOfMonth = MWBase::Environment::get().getWorld()->getGlobalVariable ("month").mLong; | ||||
|         int month = MWBase::Environment::get().getWorld()->getGlobalVariable ("month").mLong; | ||||
|         int dayOfMonth = MWBase::Environment::get().getWorld()->getGlobalVariable ("day").mLong; | ||||
| 
 | ||||
|         return StampedJournalEntry (topic, idFromIndex (topic, index), day, month, dayOfMonth); | ||||
|     } | ||||
|  |  | |||
|  | @ -31,6 +31,12 @@ namespace MWDialogue | |||
| 
 | ||||
|     void Journal::addEntry (const std::string& id, int index) | ||||
|     { | ||||
|         // bail out of we already have heard this...
 | ||||
|         std::string infoId = JournalEntry::idFromIndex (id, index); | ||||
|         for (TEntryIter i = mJournal.begin (); i != mJournal.end (); ++i) | ||||
|             if (i->mTopic == id && i->mInfoId == infoId) | ||||
|                 return; | ||||
| 
 | ||||
|         StampedJournalEntry entry = StampedJournalEntry::makeFromQuest (id, index); | ||||
| 
 | ||||
|         mJournal.push_back (entry); | ||||
|  |  | |||
|  | @ -27,17 +27,17 @@ namespace MWDialogue | |||
|         mEntries.push_back (entry.mInfoId); | ||||
|     } | ||||
| 
 | ||||
|     Topic::TEntryIter Topic::begin() | ||||
|     Topic::TEntryIter Topic::begin() const | ||||
|     { | ||||
|         return mEntries.begin(); | ||||
|     } | ||||
| 
 | ||||
|     Topic::TEntryIter Topic::end() | ||||
|     Topic::TEntryIter Topic::end() const | ||||
|     { | ||||
|         return mEntries.end(); | ||||
|     } | ||||
| 
 | ||||
|     JournalEntry Topic::getEntry (const std::string& infoId) | ||||
|     JournalEntry Topic::getEntry (const std::string& infoId) const | ||||
|     { | ||||
|         return JournalEntry (mTopic, infoId); | ||||
|     } | ||||
|  |  | |||
|  | @ -34,13 +34,15 @@ namespace MWDialogue | |||
|             ///
 | ||||
|             /// \note Redundant entries are ignored.
 | ||||
| 
 | ||||
|             TEntryIter begin(); | ||||
|             std::string const & getName () const { return mTopic; } | ||||
| 
 | ||||
|             TEntryIter begin() const; | ||||
|             ///< Iterator pointing to the begin of the journal for this topic.
 | ||||
| 
 | ||||
|             TEntryIter end(); | ||||
|             TEntryIter end() const; | ||||
|             ///< Iterator pointing past the end of the journal for this topic.
 | ||||
| 
 | ||||
|             JournalEntry getEntry (const std::string& infoId); | ||||
|             JournalEntry getEntry (const std::string& infoId) const; | ||||
|     }; | ||||
| } | ||||
| 
 | ||||
|  |  | |||
|  | @ -15,6 +15,8 @@ | |||
| #include "manualref.hpp" | ||||
| #include "refdata.hpp" | ||||
| #include "class.hpp" | ||||
| #include "localscripts.hpp" | ||||
| #include "player.hpp" | ||||
| 
 | ||||
| namespace | ||||
| { | ||||
|  | @ -71,6 +73,31 @@ bool MWWorld::ContainerStore::stacks(const Ptr& ptr1, const Ptr& ptr2) | |||
| } | ||||
| 
 | ||||
| MWWorld::ContainerStoreIterator MWWorld::ContainerStore::add (const Ptr& ptr) | ||||
| { | ||||
|     MWWorld::ContainerStoreIterator it = addImp(ptr); | ||||
|     MWWorld::Ptr item = *it; | ||||
| 
 | ||||
|     std::string script = MWWorld::Class::get(item).getScript(item); | ||||
|     if(script != "") | ||||
|     { | ||||
|         CellStore *cell; | ||||
| 
 | ||||
|         Ptr player = MWBase::Environment::get().getWorld ()->getPlayer().getPlayer(); | ||||
|         // Items in players inventory have cell set to 0, so their scripts will never be removed
 | ||||
|         if(&(MWWorld::Class::get (player).getContainerStore (player)) == this) | ||||
|             cell = 0; | ||||
|         else | ||||
|             cell = player.getCell(); | ||||
| 
 | ||||
|         item.mCell = cell; | ||||
|         item.mContainerStore = 0; | ||||
|         MWBase::Environment::get().getWorld()->getLocalScripts().add(script, item); | ||||
|     } | ||||
| 
 | ||||
|     return it; | ||||
| } | ||||
| 
 | ||||
| MWWorld::ContainerStoreIterator MWWorld::ContainerStore::addImp (const Ptr& ptr) | ||||
| { | ||||
|     int type = getType(ptr); | ||||
| 
 | ||||
|  | @ -162,7 +189,7 @@ void MWWorld::ContainerStore::fill (const ESM::InventoryList& items, const MWWor | |||
|         } | ||||
| 
 | ||||
|         ref.getPtr().getRefData().setCount (std::abs(iter->mCount)); /// \todo implement item restocking (indicated by negative count)
 | ||||
|         add (ref.getPtr()); | ||||
|         addImp (ref.getPtr()); | ||||
|     } | ||||
| 
 | ||||
|     flagAsModified(); | ||||
|  |  | |||
|  | @ -52,6 +52,7 @@ namespace MWWorld | |||
|             int mStateId; | ||||
|             mutable float mCachedWeight; | ||||
|             mutable bool mWeightUpToDate; | ||||
|             ContainerStoreIterator addImp (const Ptr& ptr); | ||||
| 
 | ||||
|         public: | ||||
| 
 | ||||
|  |  | |||
|  | @ -3,6 +3,10 @@ | |||
| #include "esmstore.hpp" | ||||
| #include "cellstore.hpp" | ||||
| 
 | ||||
| #include "class.hpp" | ||||
| #include "containerstore.hpp" | ||||
| 
 | ||||
| 
 | ||||
| namespace | ||||
| { | ||||
|     template<typename T> | ||||
|  | @ -19,6 +23,32 @@ namespace | |||
|             } | ||||
|         } | ||||
|     } | ||||
| 
 | ||||
|     // Adds scripts for items in containers (containers/npcs/creatures)
 | ||||
|     template<typename T> | ||||
|     void listCellScriptsCont (MWWorld::LocalScripts& localScripts, | ||||
|         MWWorld::CellRefList<T>& cellRefList,  MWWorld::Ptr::CellStore *cell) | ||||
|     { | ||||
|         for (typename MWWorld::CellRefList<T>::List::iterator iter ( | ||||
|             cellRefList.mList.begin()); | ||||
|             iter!=cellRefList.mList.end(); ++iter) | ||||
|         { | ||||
|             | ||||
|             MWWorld::Ptr containerPtr (&*iter, cell);  | ||||
|              | ||||
|             MWWorld::ContainerStore& container = MWWorld::Class::get(containerPtr).getContainerStore(containerPtr); | ||||
|             for(MWWorld::ContainerStoreIterator it3 = container.begin(); it3 != container.end(); ++it3) | ||||
|             { | ||||
|                 std::string script = MWWorld::Class::get(*it3).getScript(*it3); | ||||
|                 if(script != "") | ||||
|                 { | ||||
|                     MWWorld::Ptr item = *it3; | ||||
|                     item.mCell = cell; | ||||
|                     localScripts.add (script, item); | ||||
|                 } | ||||
|             } | ||||
|         } | ||||
|     } | ||||
| } | ||||
| 
 | ||||
| MWWorld::LocalScripts::LocalScripts (const MWWorld::ESMStore& store) : mStore (store) {} | ||||
|  | @ -78,13 +108,16 @@ void MWWorld::LocalScripts::addCell (Ptr::CellStore *cell) | |||
|     listCellScripts (*this, cell->mBooks, cell); | ||||
|     listCellScripts (*this, cell->mClothes, cell); | ||||
|     listCellScripts (*this, cell->mContainers, cell); | ||||
|     listCellScriptsCont (*this, cell->mContainers, cell); | ||||
|     listCellScripts (*this, cell->mCreatures, cell); | ||||
|     listCellScriptsCont (*this, cell->mCreatures, cell); | ||||
|     listCellScripts (*this, cell->mDoors, cell); | ||||
|     listCellScripts (*this, cell->mIngreds, cell); | ||||
|     listCellScripts (*this, cell->mLights, cell); | ||||
|     listCellScripts (*this, cell->mLockpicks, cell); | ||||
|     listCellScripts (*this, cell->mMiscItems, cell); | ||||
|     listCellScripts (*this, cell->mNpcs, cell); | ||||
|     listCellScriptsCont (*this, cell->mNpcs, cell); | ||||
|     listCellScripts (*this, cell->mProbes, cell); | ||||
|     listCellScripts (*this, cell->mRepairs, cell); | ||||
|     listCellScripts (*this, cell->mWeapons, cell); | ||||
|  | @ -101,7 +134,7 @@ void MWWorld::LocalScripts::clearCell (Ptr::CellStore *cell) | |||
| 
 | ||||
|     while (iter!=mScripts.end()) | ||||
|     { | ||||
|         if (iter->second.getCell()==cell) | ||||
|         if (iter->second.mCell==cell) | ||||
|         { | ||||
|             if (iter==mIter) | ||||
|                ++mIter; | ||||
|  | @ -113,6 +146,20 @@ void MWWorld::LocalScripts::clearCell (Ptr::CellStore *cell) | |||
|     } | ||||
| } | ||||
| 
 | ||||
| void MWWorld::LocalScripts::remove (RefData *ref) | ||||
| { | ||||
|     for (std::list<std::pair<std::string, Ptr> >::iterator iter = mScripts.begin(); | ||||
|         iter!=mScripts.end(); ++iter) | ||||
|         if (&(iter->second.getRefData()) == ref) | ||||
|         { | ||||
|             if (iter==mIter) | ||||
|                 ++mIter; | ||||
| 
 | ||||
|             mScripts.erase (iter); | ||||
|             break; | ||||
|         } | ||||
| } | ||||
| 
 | ||||
| void MWWorld::LocalScripts::remove (const Ptr& ptr) | ||||
| { | ||||
|     for (std::list<std::pair<std::string, Ptr> >::iterator iter = mScripts.begin(); | ||||
|  |  | |||
|  | @ -10,6 +10,7 @@ namespace MWWorld | |||
| { | ||||
|     struct ESMStore; | ||||
|     class CellStore; | ||||
|     class RefData; | ||||
| 
 | ||||
|     /// \brief List of active local scripts
 | ||||
|     class LocalScripts | ||||
|  | @ -47,6 +48,8 @@ namespace MWWorld | |||
| 
 | ||||
|             void clearCell (CellStore *cell); | ||||
|             ///< Remove all scripts belonging to \a cell.
 | ||||
|              | ||||
|             void remove (RefData *ref); | ||||
| 
 | ||||
|             void remove (const Ptr& ptr); | ||||
|             ///< Remove script for given reference (ignored if reference does not have a scirpt listed).
 | ||||
|  |  | |||
|  | @ -74,7 +74,7 @@ namespace MWWorld | |||
| 
 | ||||
|             bool isInCell() const | ||||
|             { | ||||
|                 return (mCell != 0); | ||||
|                 return (mContainerStore == 0); | ||||
|             } | ||||
| 
 | ||||
|             void setContainerStore (ContainerStore *store); | ||||
|  |  | |||
|  | @ -6,6 +6,9 @@ | |||
| #include "customdata.hpp" | ||||
| #include "cellstore.hpp" | ||||
| 
 | ||||
| #include "../mwbase/environment.hpp" | ||||
| #include "../mwbase/world.hpp" | ||||
| 
 | ||||
| namespace MWWorld | ||||
| { | ||||
|     void RefData::copy (const RefData& refData) | ||||
|  | @ -107,6 +110,9 @@ namespace MWWorld | |||
| 
 | ||||
|     void RefData::setCount (int count) | ||||
|     { | ||||
|         if(count == 0) | ||||
|             MWBase::Environment::get().getWorld()->removeRefScript(this); | ||||
|          | ||||
|         mCount = count; | ||||
|     } | ||||
| 
 | ||||
|  |  | |||
|  | @ -341,6 +341,11 @@ namespace MWWorld | |||
|         return name; | ||||
|     } | ||||
| 
 | ||||
|     void World::removeRefScript (MWWorld::RefData *ref) | ||||
|     { | ||||
|         mLocalScripts.remove (ref); | ||||
|     } | ||||
| 
 | ||||
|     Ptr World::getPtr (const std::string& name, bool activeOnly) | ||||
|     { | ||||
|         // the player is always in an active cell.
 | ||||
|  | @ -396,23 +401,62 @@ namespace MWWorld | |||
|         return MWWorld::Ptr(); | ||||
|     } | ||||
| 
 | ||||
|     void World::addContainerScripts(const Ptr& reference, Ptr::CellStore * cell) | ||||
|     { | ||||
|         if( reference.getTypeName()==typeid (ESM::Container).name() || | ||||
|             reference.getTypeName()==typeid (ESM::NPC).name() || | ||||
|             reference.getTypeName()==typeid (ESM::Creature).name()) | ||||
|         { | ||||
|             MWWorld::ContainerStore& container = MWWorld::Class::get(reference).getContainerStore(reference); | ||||
|             for(MWWorld::ContainerStoreIterator it = container.begin(); it != container.end(); ++it) | ||||
|             { | ||||
|                 std::string script = MWWorld::Class::get(*it).getScript(*it); | ||||
|                 if(script != "") | ||||
|                 { | ||||
|                     MWWorld::Ptr item = *it; | ||||
|                     item.mCell = cell; | ||||
|                     mLocalScripts.add (script, item); | ||||
|                 } | ||||
|             } | ||||
|         } | ||||
|     } | ||||
| 
 | ||||
|     void World::enable (const Ptr& reference) | ||||
|     { | ||||
|         if (!reference.getRefData().isEnabled()) | ||||
|         { | ||||
|             reference.getRefData().enable(); | ||||
| 
 | ||||
|              | ||||
|             if(mWorldScene->getActiveCells().find (reference.getCell()) != mWorldScene->getActiveCells().end() && reference.getRefData().getCount()) | ||||
|                 mWorldScene->addObjectToScene (reference); | ||||
|         } | ||||
|     } | ||||
|      | ||||
|     void World::removeContainerScripts(const Ptr& reference) | ||||
|     { | ||||
|         if( reference.getTypeName()==typeid (ESM::Container).name() || | ||||
|             reference.getTypeName()==typeid (ESM::NPC).name() || | ||||
|             reference.getTypeName()==typeid (ESM::Creature).name()) | ||||
|         { | ||||
|             MWWorld::ContainerStore& container = MWWorld::Class::get(reference).getContainerStore(reference); | ||||
|             for(MWWorld::ContainerStoreIterator it = container.begin(); it != container.end(); ++it) | ||||
|             { | ||||
|                 std::string script = MWWorld::Class::get(*it).getScript(*it); | ||||
|                 if(script != "") | ||||
|                 { | ||||
|                     MWWorld::Ptr item = *it; | ||||
|                     mLocalScripts.remove (item); | ||||
|                 } | ||||
|             } | ||||
|         } | ||||
|     } | ||||
| 
 | ||||
|     void World::disable (const Ptr& reference) | ||||
|     { | ||||
|         if (reference.getRefData().isEnabled()) | ||||
|         { | ||||
|             reference.getRefData().disable(); | ||||
| 
 | ||||
|              | ||||
|             if(mWorldScene->getActiveCells().find (reference.getCell())!=mWorldScene->getActiveCells().end() && reference.getRefData().getCount()) | ||||
|                 mWorldScene->removeObjectFromScene (reference); | ||||
|         } | ||||
|  | @ -635,6 +679,7 @@ namespace MWWorld | |||
|             { | ||||
|                 mWorldScene->removeObjectFromScene (ptr); | ||||
|                 mLocalScripts.remove (ptr); | ||||
|                 removeContainerScripts (ptr); | ||||
|             } | ||||
|         } | ||||
|     } | ||||
|  | @ -648,6 +693,8 @@ namespace MWWorld | |||
|         CellStore *currCell = ptr.getCell(); | ||||
|         bool isPlayer = ptr == mPlayer->getPlayer(); | ||||
|         bool haveToMove = mWorldScene->isCellActive(*currCell) || isPlayer; | ||||
|          | ||||
|         removeContainerScripts(ptr); | ||||
| 
 | ||||
|         if (*currCell != newCell) | ||||
|         { | ||||
|  | @ -675,6 +722,8 @@ namespace MWWorld | |||
|                     MWWorld::Ptr copy = | ||||
|                         MWWorld::Class::get(ptr).copyToCell(ptr, newCell); | ||||
| 
 | ||||
|                     addContainerScripts(copy, &newCell); | ||||
| 
 | ||||
|                     mRendering->moveObjectToCell(copy, vec, currCell); | ||||
| 
 | ||||
|                     if (MWWorld::Class::get(ptr).isActor()) | ||||
|  | @ -1272,6 +1321,7 @@ namespace MWWorld | |||
|             if (!script.empty()) { | ||||
|                 mLocalScripts.add(script, dropped); | ||||
|             } | ||||
|             addContainerScripts(dropped, &cell); | ||||
|         } | ||||
|     } | ||||
| 
 | ||||
|  |  | |||
|  | @ -106,6 +106,9 @@ namespace MWWorld | |||
|             float getNpcActivationDistance (); | ||||
|             float getObjectActivationDistance (); | ||||
| 
 | ||||
|             void removeContainerScripts(const Ptr& reference); | ||||
|             void addContainerScripts(const Ptr& reference, Ptr::CellStore* cell); | ||||
| 
 | ||||
|         public: | ||||
| 
 | ||||
|             World (OEngine::Render::OgreRenderer& renderer, | ||||
|  | @ -173,6 +176,9 @@ namespace MWWorld | |||
|             virtual std::vector<std::string> getGlobals () const; | ||||
|              | ||||
|             virtual std::string getCurrentCellName () const; | ||||
|              | ||||
|             virtual void removeRefScript (MWWorld::RefData *ref); | ||||
|             //< Remove the script attached to ref from mLocalScripts
 | ||||
| 
 | ||||
|             virtual Ptr getPtr (const std::string& name, bool activeOnly); | ||||
|             ///< Return a pointer to a liveCellRef with the given name.
 | ||||
|  |  | |||
|  | @ -11,6 +11,7 @@ | |||
|             <Code range="33 126"/> | ||||
|             <Code range="192 382"/> <!-- Central and Eastern European languages glyphs --> | ||||
|             <Code range="1025 1105"/> | ||||
|             <Code range="2026"/> <!-- Ellipsis --> | ||||
|             <Code range="8470"/> | ||||
|             <Code range="8211"/>   <!-- Minus --> | ||||
|             <Code range="8216 8217"/> <!-- Single quotes --> | ||||
|  |  | |||
		Loading…
	
		Reference in a new issue