mirror of
https://github.com/TES3MP/openmw-tes3mp.git
synced 2025-02-01 20:15:33 +00:00
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)
This commit is contained in:
parent
5bfd953dd4
commit
10778d8c3e
8 changed files with 152 additions and 49 deletions
|
@ -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)
|
||||
{
|
||||
if (mIgnoreLocalPtr.isEmpty() || mIgnoreLocalPtr!=iter->second)
|
||||
{
|
||||
MWScript::InterpreterContext interpreterContext (mEnvironment,
|
||||
&iter->second.getRefData().getLocals(), MWWorld::Ptr (iter->second));
|
||||
mScriptManager->run (iter->first, interpreterContext);
|
||||
MWWorld::LocalScripts& localScripts = mEnvironment.mWorld->getLocalScripts();
|
||||
|
||||
if (mEnvironment.mWorld->hasCellChanged())
|
||||
break;
|
||||
}
|
||||
localScripts.startIteration();
|
||||
|
||||
while (!localScripts.isFinished())
|
||||
{
|
||||
std::pair<std::string, MWWorld::Ptr> script = localScripts.getNext();
|
||||
|
||||
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;
|
||||
|
||||
|
|
80
apps/openmw/mwworld/localscripts.cpp
Normal file
80
apps/openmw/mwworld/localscripts.cpp
Normal 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;
|
||||
}
|
||||
}
|
47
apps/openmw/mwworld/localscripts.hpp
Normal file
47
apps/openmw/mwworld/localscripts.hpp
Normal 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
|
|
@ -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…
Reference in a new issue