reworked cell changing mechanism

actorid
Marc Zinnschlag 14 years ago
parent f773cf27cb
commit 9a3158675a

@ -393,7 +393,7 @@ void OMW::Engine::go()
else
{
pos.pos[0] = pos.pos[1] = 0;
mEnvironment.mWorld->changeCell (mCellName, pos);
mEnvironment.mWorld->changeToInteriorCell (mCellName, pos);
}
// Sets up the input system

@ -234,11 +234,17 @@ namespace MWMechanics
void MechanicsManager::removeActor (const MWWorld::Ptr& ptr)
{
if (ptr==mWatched)
mWatched = MWWorld::Ptr();
mActors.erase (ptr);
}
void MechanicsManager::dropActors (const MWWorld::Ptr::CellStore *cellStore)
{
if (!mWatched.isEmpty() && mWatched.getCell()==cellStore)
mWatched = MWWorld::Ptr();
std::set<MWWorld::Ptr>::iterator iter = mActors.begin();
while (iter!=mActors.end())

@ -53,7 +53,7 @@ namespace MWScript
else
{
pos.pos[0] = pos.pos[1] = 0;
context.getWorld().changeCell (cell, pos);
context.getWorld().changeToInteriorCell (cell, pos);
}
}
};

@ -16,6 +16,6 @@ namespace MWWorld
if (mCellName.empty())
environment.mWorld->changeToExteriorCell (mPosition);
else
environment.mWorld->changeCell (mCellName, mPosition);
environment.mWorld->changeToInteriorCell (mCellName, mPosition);
}
}

@ -305,9 +305,12 @@ namespace MWWorld
}
}
void World::playerCellChange (Ptr::CellStore *cell, const ESM::Position& position)
void World::playerCellChange (Ptr::CellStore *cell, const ESM::Position& position,
bool adjustPlayerPos)
{
mPlayer->setPos (position.pos[0], position.pos[1], position.pos[2], true);
if (adjustPlayerPos)
mPlayer->setPos (position.pos[0], position.pos[1], position.pos[2], true);
mPlayer->setCell (cell);
// TODO orientation
@ -326,8 +329,87 @@ namespace MWWorld
}
}
void World::changeCell (int X, int Y, const ESM::Position& position, bool adjustPlayerPos)
{
SuppressDoingPhysics scopeGuard;
// remove active
mEnvironment.mMechanicsManager->removeActor (mPlayer->getPlayer());
CellRenderCollection::iterator active = mActiveCells.begin();
while (active!=mActiveCells.end())
{
if (!(active->first->cell->data.flags & ESM::Cell::Interior))
{
if (std::abs (X-active->first->cell->data.gridX)<=1 &&
std::abs (Y-active->first->cell->data.gridY)<=1)
{
// keep cells within the new 3x3 grid
++active;
continue;
}
}
unloadCell (active++);
}
// Load cells
for (int x=X-1; x<=X+1; ++x)
for (int y=Y-1; y<=Y+1; ++y)
{
CellRenderCollection::iterator iter = mActiveCells.begin();
while (iter!=mActiveCells.end())
{
assert (!(iter->first->cell->data.flags & ESM::Cell::Interior));
if (x==iter->first->cell->data.gridX &&
y==iter->first->cell->data.gridY)
break;
++iter;
}
if (iter==mActiveCells.end())
{
mExteriors[std::make_pair (x, y)].loadExt (x, y, mStore, mEsm);
Ptr::CellStore *cell = &mExteriors[std::make_pair (x, y)];
loadCell (cell, new MWRender::ExteriorCellRender (*cell, mEnvironment, mScene));
}
}
// find current cell
CellRenderCollection::iterator iter = mActiveCells.begin();
while (iter!=mActiveCells.end())
{
assert (!(iter->first->cell->data.flags & ESM::Cell::Interior));
if (X==iter->first->cell->data.gridX &&
Y==iter->first->cell->data.gridY)
break;
++iter;
}
assert (iter!=mActiveCells.end());
mCurrentCell = iter->first;
// adjust player
playerCellChange (&mExteriors[std::make_pair (X, Y)], position, adjustPlayerPos);
// Sky system
adjustSky();
mCellChanged = true;
}
World::World (OEngine::Render::OgreRenderer& renderer, const boost::filesystem::path& dataDir,
const std::string& master, const boost::filesystem::path& resDir, bool newGame, Environment& environment)
const std::string& master, const boost::filesystem::path& resDir,
bool newGame, Environment& environment)
: mSkyManager (0), mScene (renderer), mPlayer (0), mCurrentCell (0), mGlobalVariables (0),
mSky (false), mCellChanged (false), mEnvironment (environment)
{
@ -597,8 +679,10 @@ namespace MWWorld
return mGlobalVariables->getInt ("timescale");
}
void World::changeCell (const std::string& cellName, const ESM::Position& position)
void World::changeToInteriorCell (const std::string& cellName, const ESM::Position& position)
{
SuppressDoingPhysics scopeGuard;
// remove active
CellRenderCollection::iterator active = mActiveCells.begin();
@ -624,91 +708,14 @@ namespace MWWorld
//currentRegion->name = "";
}
void World::changeCell (int X, int Y, const ESM::Position& position)
{
SuppressDoingPhysics scopeGuard;
// remove active
CellRenderCollection::iterator active = mActiveCells.begin();
while (active!=mActiveCells.end())
{
if (!(active->first->cell->data.flags & ESM::Cell::Interior))
{
if (std::abs (X-active->first->cell->data.gridX)<=1 &&
std::abs (Y-active->first->cell->data.gridY)<=1)
{
// keep cells within the new 3x3 grid
++active;
continue;
}
}
unloadCell (active++);
}
// Load cells
for (int x=X-1; x<=X+1; ++x)
for (int y=Y-1; y<=Y+1; ++y)
{
CellRenderCollection::iterator iter = mActiveCells.begin();
while (iter!=mActiveCells.end())
{
assert (!(iter->first->cell->data.flags & ESM::Cell::Interior));
if (x==iter->first->cell->data.gridX &&
y==iter->first->cell->data.gridY)
break;
++iter;
}
if (iter==mActiveCells.end())
{
mExteriors[std::make_pair (x, y)].loadExt (x, y, mStore, mEsm);
Ptr::CellStore *cell = &mExteriors[std::make_pair (x, y)];
loadCell (cell, new MWRender::ExteriorCellRender (*cell, mEnvironment, mScene));
}
}
// find current cell
CellRenderCollection::iterator iter = mActiveCells.begin();
while (iter!=mActiveCells.end())
{
assert (!(iter->first->cell->data.flags & ESM::Cell::Interior));
if (X==iter->first->cell->data.gridX &&
Y==iter->first->cell->data.gridY)
break;
++iter;
}
assert (iter!=mActiveCells.end());
mCurrentCell = iter->first;
// adjust player
playerCellChange (&mExteriors[std::make_pair (X, Y)], position);
// Sky system
adjustSky();
mCellChanged = true;
}
void World::changeToExteriorCell (const ESM::Position& position)
void World::changeToExteriorCell (const ESM::Position& position)
{
int x = 0;
int y = 0;
positionToIndex (position.pos[0], position.pos[1], x, y);
changeCell (x, y, position);
changeCell (x, y, position, true);
}
const ESM::Cell *World::getExterior (const std::string& cellName) const
@ -734,6 +741,7 @@ namespace MWWorld
return 0;
}
void World::markCellAsUnchanged()
{
mCellChanged = false;
@ -793,7 +801,7 @@ namespace MWWorld
if (mCurrentCell->cell->data.gridX!=cellX || mCurrentCell->cell->data.gridY!=cellY)
{
changeCell (cellX, cellY, mPlayer->getPlayer().getCellRef().pos);
changeCell (cellX, cellY, mPlayer->getPlayer().getCellRef().pos, false);
}
if (!DoingPhysics::isDoingPhysics())

@ -88,14 +88,19 @@ namespace MWWorld
void loadCell (Ptr::CellStore *cell, MWRender::CellRender *render);
void playerCellChange (Ptr::CellStore *cell, const ESM::Position& position);
void playerCellChange (Ptr::CellStore *cell, const ESM::Position& position,
bool adjustPlayerPos = true);
void adjustSky();
void changeCell (int X, int Y, const ESM::Position& position, bool adjustPlayerPos);
///< Move from exterior to interior or from interior cell to a different
/// interior cell.
public:
World (OEngine::Render::OgreRenderer& renderer, const boost::filesystem::path& dataDir,
const std::string& master, const boost::filesystem::path& resDir, bool newGame, Environment& environment);
const std::string& master, const boost::filesystem::path& resDir, bool newGame,
Environment& environment);
~World();
@ -143,12 +148,11 @@ namespace MWWorld
float getTimeScaleFactor() const;
void changeCell (const std::string& cellName, const ESM::Position& position);
///< works only for interior cells currently.
void changeCell (int X, int Y, const ESM::Position& position);
void changeToInteriorCell (const std::string& cellName, const ESM::Position& position);
///< Move to interior cell.
void changeToExteriorCell (const ESM::Position& position);
///< Move to exterior cell.
const ESM::Cell *getExterior (const std::string& cellName) const;
///< Return a cell matching the given name or a 0-pointer, if there is no such cell.

Loading…
Cancel
Save