Issue #19: factored out local script handling into a separate class

This also fixes a bug related to self-destructing references (introduced during the cell handling improvements)
actorid
Marc Zinnschlag 13 years ago
parent 5bfd953dd4
commit 10778d8c3e

@ -149,6 +149,7 @@ set(GAMEWORLD
mwworld/containerutil.cpp
mwworld/player.cpp
mwworld/cells.cpp
mwworld/localscripts.cpp
)
set(GAMEWORLD_HEADER
mwworld/refdata.hpp
@ -170,6 +171,7 @@ set(GAMEWORLD_HEADER
mwworld/player.hpp
mwworld/cellfunctors.hpp
mwworld/cells.hpp
mwworld/localscripts.hpp
)
source_group(apps\\openmw\\mwworld FILES ${GAMEWORLD} ${GAMEWORLD_HEADER})

@ -54,22 +54,23 @@
void OMW::Engine::executeLocalScripts()
{
for (MWWorld::World::ScriptList::const_iterator iter (
mEnvironment.mWorld->getLocalScripts().begin());
iter!=mEnvironment.mWorld->getLocalScripts().end(); ++iter)
MWWorld::LocalScripts& localScripts = mEnvironment.mWorld->getLocalScripts();
localScripts.startIteration();
while (!localScripts.isFinished())
{
if (mIgnoreLocalPtr.isEmpty() || mIgnoreLocalPtr!=iter->second)
{
MWScript::InterpreterContext interpreterContext (mEnvironment,
&iter->second.getRefData().getLocals(), MWWorld::Ptr (iter->second));
mScriptManager->run (iter->first, interpreterContext);
std::pair<std::string, MWWorld::Ptr> script = localScripts.getNext();
if (mEnvironment.mWorld->hasCellChanged())
break;
}
MWScript::InterpreterContext interpreterContext (mEnvironment,
&script.second.getRefData().getLocals(), script.second);
mScriptManager->run (script.first, interpreterContext);
if (mEnvironment.mWorld->hasCellChanged())
break;
}
mIgnoreLocalPtr = MWWorld::Ptr();
mEnvironment.mWorld->getLocalScripts().setIgnore (MWWorld::Ptr());
}
@ -488,7 +489,7 @@ void OMW::Engine::activate()
if (!script.empty())
{
mIgnoreLocalPtr = ptr;
mEnvironment.mWorld->getLocalScripts().setIgnore (ptr);
mScriptManager->run (script, interpreterContext);
}

@ -81,8 +81,6 @@ namespace OMW
int focusFrameCounter;
static const int focusUpdateFrame = 10;
MWWorld::Ptr mIgnoreLocalPtr;
Files::Collections mFileCollections;
bool mFSStrict;

@ -0,0 +1,80 @@
#include "localscripts.hpp"
void MWWorld::LocalScripts::setIgnore (const Ptr& ptr)
{
mIgnore = ptr;
}
void MWWorld::LocalScripts::startIteration()
{
mIter = mScripts.begin();
}
bool MWWorld::LocalScripts::isFinished() const
{
if (mIter==mScripts.end())
return true;
if (!mIgnore.isEmpty() && mIter->second==mIgnore)
{
std::list<std::pair<std::string, Ptr> >::iterator iter = mIter;
return ++iter==mScripts.end();
}
return false;
}
std::pair<std::string, MWWorld::Ptr> MWWorld::LocalScripts::getNext()
{
assert (!isFinished());
std::list<std::pair<std::string, Ptr> >::iterator iter = mIter++;
if (mIgnore.isEmpty() || iter->second!=mIgnore)
return *iter;
return getNext();
}
void MWWorld::LocalScripts::add (const std::string& scriptName, const Ptr& ptr)
{
mScripts.push_back (std::make_pair (scriptName, ptr));
}
void MWWorld::LocalScripts::clear()
{
mScripts.clear();
}
void MWWorld::LocalScripts::clearCell (Ptr::CellStore *cell)
{
std::list<std::pair<std::string, Ptr> >::iterator iter = mScripts.begin();
while (iter!=mScripts.end())
{
if (iter->second.getCell()==cell)
{
if (iter==mIter)
++mIter;
mScripts.erase (iter++);
}
else
++iter;
}
}
void MWWorld::LocalScripts::remove (const Ptr& ptr)
{
for (std::list<std::pair<std::string, Ptr> >::iterator iter = mScripts.begin();
iter!=mScripts.end(); ++iter)
if (iter->second==ptr)
{
if (iter==mIter)
++mIter;
mScripts.erase (iter);
break;
}
}

@ -0,0 +1,47 @@
#ifndef GAME_MWWORLD_LOCALSCRIPTS_H
#define GAME_MWWORLD_LOCALSCRIPTS_H
#include <list>
#include <string>
#include "ptr.hpp"
namespace MWWorld
{
/// \brief List of active local scripts
class LocalScripts
{
std::list<std::pair<std::string, Ptr> > mScripts;
std::list<std::pair<std::string, Ptr> >::iterator mIter;
MWWorld::Ptr mIgnore;
public:
void setIgnore (const Ptr& ptr);
///< Mark a single reference for ignoring during iteration over local scripts (will revoke
/// previous ignores).
void startIteration();
///< Set the iterator to the begin of the script list.
bool isFinished() const;
///< Is iteration finished?
std::pair<std::string, Ptr> getNext();
///< Get next local script (must not be called if isFinished())
void add (const std::string& scriptName, const Ptr& ptr);
///< Add script to collection of active local scripts.
void clear();
///< Clear active local scripts collection.
void clearCell (Ptr::CellStore *cell);
///< Remove all scripts belonging to \a cell.
void remove (const Ptr& ptr);
///< Remove script for given reference (ignored if reference does not have a scirpt listed).
};
}
#endif

@ -57,7 +57,7 @@ namespace MWWorld
mPhysics->removeObject (*iter);
}
mWorld->removeScripts (iter->first);
mWorld->getLocalScripts().clearCell (iter->first);
mEnvironment.mMechanicsManager->dropActors (iter->first);
mEnvironment.mSoundManager->stopSound (iter->first);

@ -27,7 +27,7 @@ namespace
{
template<typename T>
void listCellScripts (const ESMS::ESMStore& store,
ESMS::CellRefList<T, MWWorld::RefData>& cellRefList, MWWorld::World::ScriptList& scriptList,
ESMS::CellRefList<T, MWWorld::RefData>& cellRefList, MWWorld::LocalScripts& localScripts,
MWWorld::Ptr::CellStore *cell)
{
for (typename ESMS::CellRefList<T, MWWorld::RefData>::List::iterator iter (
@ -40,8 +40,7 @@ namespace
{
iter->mData.setLocals (*script);
scriptList.push_back (
std::make_pair (iter->base->script, MWWorld::Ptr (&*iter, cell)));
localScripts.add (iter->base->script, MWWorld::Ptr (&*iter, cell));
}
}
}
@ -185,20 +184,6 @@ namespace MWWorld
throw std::runtime_error ("month out of range");
}
void World::removeScripts (Ptr::CellStore *cell)
{
ScriptList::iterator iter = mLocalScripts.begin();
while (iter!=mLocalScripts.end())
{
if (iter->second.getCell()==cell)
mLocalScripts.erase (iter++);
else
++iter;
}
}
void World::adjustSky()
{
if (mSky)
@ -306,7 +291,7 @@ namespace MWWorld
return mEsm;
}
const World::ScriptList& World::getLocalScripts() const
LocalScripts& World::getLocalScripts()
{
return mLocalScripts;
}
@ -575,13 +560,7 @@ namespace MWWorld
mPhysics->removeObject (ptr.getRefData().getHandle());
for (ScriptList::iterator iter = mLocalScripts.begin(); iter!=mLocalScripts.end();
++iter)
if (ptr==iter->second)
{
mLocalScripts.erase (iter);
break;
}
mLocalScripts.remove (ptr);
}
render->deleteObject (ptr.getRefData().getHandle());

@ -17,6 +17,7 @@
#include "scene.hpp"
#include "physicssystem.hpp"
#include "cells.hpp"
#include "localscripts.hpp"
#include <openengine/bullet/physic.hpp>
@ -55,9 +56,7 @@ namespace MWWorld
class World
{
public:
typedef std::list<std::pair<std::string, Ptr> > ScriptList;
enum RenderMode
{
@ -71,7 +70,7 @@ namespace MWWorld
MWWorld::Player *mPlayer;
ESM::ESMReader mEsm;
ESMS::ESMStore mStore;
ScriptList mLocalScripts;
LocalScripts mLocalScripts;
MWWorld::Globals *mGlobalVariables;
MWWorld::PhysicsSystem *mPhysics;
bool mSky;
@ -108,8 +107,6 @@ namespace MWWorld
Ptr::CellStore *getInterior (const std::string& name);
void removeScripts (Ptr::CellStore *cell);
void insertInteriorScripts (ESMS::CellStore<RefData>& cell);
void adjustSky();
@ -120,8 +117,7 @@ namespace MWWorld
ESM::ESMReader& getEsmReader();
const ScriptList& getLocalScripts() const;
///< Names and local variable state of all local scripts in active cells.
LocalScripts& getLocalScripts();
bool hasCellChanged() const;
///< Has the player moved to a different cell, since the last frame?

Loading…
Cancel
Save