1
0
Fork 1
mirror of https://github.com/TES3MP/openmw-tes3mp.git synced 2025-04-01 15:36:42 +00:00

Issue : 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)
This commit is contained in:
Marc Zinnschlag 2011-10-06 12:29:59 +02:00
parent 5bfd953dd4
commit 10778d8c3e
8 changed files with 152 additions and 49 deletions

View file

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

View file

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

View file

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

View file

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

View file

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

View file

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

View file

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

View file

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