Merge remote-tracking branch 'zini/master' into animation2

This commit is contained in:
Chris Robinson 2013-01-26 04:54:52 -08:00
commit 0cd3880b20
27 changed files with 345 additions and 86 deletions

2
.gitignore vendored
View file

@ -15,3 +15,5 @@ makefile
data
*.kdev4
CMakeLists.txt.user
*.swp
*.swo

View file

@ -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)

View file

@ -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() {}

View file

@ -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;

View file

@ -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
{

View file

@ -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();
}

View file

@ -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)

View file

@ -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:

View file

@ -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()));
}

View file

@ -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.

View file

@ -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);

View file

@ -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;

View file

@ -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;
}

View file

@ -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)
};
}

View file

@ -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);
}

View file

@ -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);

View file

@ -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);
}

View file

@ -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;
};
}

View file

@ -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();

View file

@ -52,6 +52,7 @@ namespace MWWorld
int mStateId;
mutable float mCachedWeight;
mutable bool mWeightUpToDate;
ContainerStoreIterator addImp (const Ptr& ptr);
public:

View file

@ -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();

View file

@ -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).

View file

@ -74,7 +74,7 @@ namespace MWWorld
bool isInCell() const
{
return (mCell != 0);
return (mContainerStore == 0);
}
void setContainerStore (ContainerStore *store);

View file

@ -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;
}

View file

@ -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);
}
}

View file

@ -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.

View file

@ -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 -->