forked from mirror/openmw-tes3mp
Merge pull request #840 from scrawl/movedrefs
Object movement between cells
This commit is contained in:
commit
bdae572264
32 changed files with 638 additions and 332 deletions
|
@ -62,7 +62,7 @@ add_openmw_dir (mwsound
|
||||||
|
|
||||||
add_openmw_dir (mwworld
|
add_openmw_dir (mwworld
|
||||||
refdata worldimp scene globals class action nullaction actionteleport
|
refdata worldimp scene globals class action nullaction actionteleport
|
||||||
containerstore actiontalk actiontake manualref player cellfunctors failedaction
|
containerstore actiontalk actiontake manualref player cellvisitors failedaction
|
||||||
cells localscripts customdata inventorystore ptr actionopen actionread
|
cells localscripts customdata inventorystore ptr actionopen actionread
|
||||||
actionequip timestamp actionalchemy cellstore actionapply actioneat
|
actionequip timestamp actionalchemy cellstore actionapply actioneat
|
||||||
store esmstore recordcmp fallback actionrepair actionsoulgem livecellref actiondoor
|
store esmstore recordcmp fallback actionrepair actionsoulgem livecellref actiondoor
|
||||||
|
|
|
@ -130,6 +130,6 @@ namespace MWClass
|
||||||
MWWorld::LiveCellRef<ESM::Activator> *ref =
|
MWWorld::LiveCellRef<ESM::Activator> *ref =
|
||||||
ptr.get<ESM::Activator>();
|
ptr.get<ESM::Activator>();
|
||||||
|
|
||||||
return MWWorld::Ptr(&cell.get<ESM::Activator>().insert(*ref), &cell);
|
return MWWorld::Ptr(cell.insert(ref), &cell);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -148,7 +148,7 @@ namespace MWClass
|
||||||
MWWorld::LiveCellRef<ESM::Apparatus> *ref =
|
MWWorld::LiveCellRef<ESM::Apparatus> *ref =
|
||||||
ptr.get<ESM::Apparatus>();
|
ptr.get<ESM::Apparatus>();
|
||||||
|
|
||||||
return MWWorld::Ptr(&cell.get<ESM::Apparatus>().insert(*ref), &cell);
|
return MWWorld::Ptr(cell.insert(ref), &cell);
|
||||||
}
|
}
|
||||||
|
|
||||||
bool Apparatus::canSell (const MWWorld::Ptr& item, int npcServices) const
|
bool Apparatus::canSell (const MWWorld::Ptr& item, int npcServices) const
|
||||||
|
|
|
@ -382,7 +382,7 @@ namespace MWClass
|
||||||
MWWorld::LiveCellRef<ESM::Armor> *ref =
|
MWWorld::LiveCellRef<ESM::Armor> *ref =
|
||||||
ptr.get<ESM::Armor>();
|
ptr.get<ESM::Armor>();
|
||||||
|
|
||||||
return MWWorld::Ptr(&cell.get<ESM::Armor>().insert(*ref), &cell);
|
return MWWorld::Ptr(cell.insert(ref), &cell);
|
||||||
}
|
}
|
||||||
|
|
||||||
int Armor::getEnchantmentPoints (const MWWorld::Ptr& ptr) const
|
int Armor::getEnchantmentPoints (const MWWorld::Ptr& ptr) const
|
||||||
|
|
|
@ -187,7 +187,7 @@ namespace MWClass
|
||||||
MWWorld::LiveCellRef<ESM::Book> *ref =
|
MWWorld::LiveCellRef<ESM::Book> *ref =
|
||||||
ptr.get<ESM::Book>();
|
ptr.get<ESM::Book>();
|
||||||
|
|
||||||
return MWWorld::Ptr(&cell.get<ESM::Book>().insert(*ref), &cell);
|
return MWWorld::Ptr(cell.insert(ref), &cell);
|
||||||
}
|
}
|
||||||
|
|
||||||
int Book::getEnchantmentPoints (const MWWorld::Ptr& ptr) const
|
int Book::getEnchantmentPoints (const MWWorld::Ptr& ptr) const
|
||||||
|
|
|
@ -276,7 +276,7 @@ namespace MWClass
|
||||||
MWWorld::LiveCellRef<ESM::Clothing> *ref =
|
MWWorld::LiveCellRef<ESM::Clothing> *ref =
|
||||||
ptr.get<ESM::Clothing>();
|
ptr.get<ESM::Clothing>();
|
||||||
|
|
||||||
return MWWorld::Ptr(&cell.get<ESM::Clothing>().insert(*ref), &cell);
|
return MWWorld::Ptr(cell.insert(ref), &cell);
|
||||||
}
|
}
|
||||||
|
|
||||||
int Clothing::getEnchantmentPoints (const MWWorld::Ptr& ptr) const
|
int Clothing::getEnchantmentPoints (const MWWorld::Ptr& ptr) const
|
||||||
|
|
|
@ -293,7 +293,7 @@ namespace MWClass
|
||||||
MWWorld::LiveCellRef<ESM::Container> *ref =
|
MWWorld::LiveCellRef<ESM::Container> *ref =
|
||||||
ptr.get<ESM::Container>();
|
ptr.get<ESM::Container>();
|
||||||
|
|
||||||
return MWWorld::Ptr(&cell.get<ESM::Container>().insert(*ref), &cell);
|
return MWWorld::Ptr(cell.insert(ref), &cell);
|
||||||
}
|
}
|
||||||
|
|
||||||
void Container::readAdditionalState (const MWWorld::Ptr& ptr, const ESM::ObjectState& state) const
|
void Container::readAdditionalState (const MWWorld::Ptr& ptr, const ESM::ObjectState& state) const
|
||||||
|
|
|
@ -600,7 +600,7 @@ namespace MWClass
|
||||||
MWWorld::LiveCellRef<ESM::Creature> *ref =
|
MWWorld::LiveCellRef<ESM::Creature> *ref =
|
||||||
ptr.get<ESM::Creature>();
|
ptr.get<ESM::Creature>();
|
||||||
|
|
||||||
return MWWorld::Ptr(&cell.get<ESM::Creature>().insert(*ref), &cell);
|
return MWWorld::Ptr(cell.insert(ref), &cell);
|
||||||
}
|
}
|
||||||
|
|
||||||
bool Creature::isBipedal(const MWWorld::Ptr &ptr) const
|
bool Creature::isBipedal(const MWWorld::Ptr &ptr) const
|
||||||
|
|
|
@ -310,7 +310,7 @@ namespace MWClass
|
||||||
MWWorld::LiveCellRef<ESM::Door> *ref =
|
MWWorld::LiveCellRef<ESM::Door> *ref =
|
||||||
ptr.get<ESM::Door>();
|
ptr.get<ESM::Door>();
|
||||||
|
|
||||||
return MWWorld::Ptr(&cell.get<ESM::Door>().insert(*ref), &cell);
|
return MWWorld::Ptr(cell.insert(ref), &cell);
|
||||||
}
|
}
|
||||||
|
|
||||||
void Door::ensureCustomData(const MWWorld::Ptr &ptr) const
|
void Door::ensureCustomData(const MWWorld::Ptr &ptr) const
|
||||||
|
|
|
@ -185,7 +185,7 @@ namespace MWClass
|
||||||
MWWorld::LiveCellRef<ESM::Ingredient> *ref =
|
MWWorld::LiveCellRef<ESM::Ingredient> *ref =
|
||||||
ptr.get<ESM::Ingredient>();
|
ptr.get<ESM::Ingredient>();
|
||||||
|
|
||||||
return MWWorld::Ptr(&cell.get<ESM::Ingredient>().insert(*ref), &cell);
|
return MWWorld::Ptr(cell.insert(ref), &cell);
|
||||||
}
|
}
|
||||||
|
|
||||||
bool Ingredient::canSell (const MWWorld::Ptr& item, int npcServices) const
|
bool Ingredient::canSell (const MWWorld::Ptr& item, int npcServices) const
|
||||||
|
|
|
@ -217,7 +217,7 @@ namespace MWClass
|
||||||
MWWorld::LiveCellRef<ESM::Light> *ref =
|
MWWorld::LiveCellRef<ESM::Light> *ref =
|
||||||
ptr.get<ESM::Light>();
|
ptr.get<ESM::Light>();
|
||||||
|
|
||||||
return MWWorld::Ptr(&cell.get<ESM::Light>().insert(*ref), &cell);
|
return MWWorld::Ptr(cell.insert(ref), &cell);
|
||||||
}
|
}
|
||||||
|
|
||||||
bool Light::canSell (const MWWorld::Ptr& item, int npcServices) const
|
bool Light::canSell (const MWWorld::Ptr& item, int npcServices) const
|
||||||
|
|
|
@ -166,7 +166,7 @@ namespace MWClass
|
||||||
MWWorld::LiveCellRef<ESM::Lockpick> *ref =
|
MWWorld::LiveCellRef<ESM::Lockpick> *ref =
|
||||||
ptr.get<ESM::Lockpick>();
|
ptr.get<ESM::Lockpick>();
|
||||||
|
|
||||||
return MWWorld::Ptr(&cell.get<ESM::Lockpick>().insert(*ref), &cell);
|
return MWWorld::Ptr(cell.insert(ref), &cell);
|
||||||
}
|
}
|
||||||
|
|
||||||
bool Lockpick::canSell (const MWWorld::Ptr& item, int npcServices) const
|
bool Lockpick::canSell (const MWWorld::Ptr& item, int npcServices) const
|
||||||
|
|
|
@ -215,13 +215,14 @@ namespace MWClass
|
||||||
MWWorld::ManualRef newRef(store, base);
|
MWWorld::ManualRef newRef(store, base);
|
||||||
MWWorld::LiveCellRef<ESM::Miscellaneous> *ref =
|
MWWorld::LiveCellRef<ESM::Miscellaneous> *ref =
|
||||||
newRef.getPtr().get<ESM::Miscellaneous>();
|
newRef.getPtr().get<ESM::Miscellaneous>();
|
||||||
newPtr = MWWorld::Ptr(&cell.get<ESM::Miscellaneous>().insert(*ref), &cell);
|
|
||||||
|
newPtr = MWWorld::Ptr(cell.insert(ref), &cell);
|
||||||
newPtr.getCellRef().setGoldValue(goldAmount);
|
newPtr.getCellRef().setGoldValue(goldAmount);
|
||||||
newPtr.getRefData().setCount(1);
|
newPtr.getRefData().setCount(1);
|
||||||
} else {
|
} else {
|
||||||
MWWorld::LiveCellRef<ESM::Miscellaneous> *ref =
|
MWWorld::LiveCellRef<ESM::Miscellaneous> *ref =
|
||||||
ptr.get<ESM::Miscellaneous>();
|
ptr.get<ESM::Miscellaneous>();
|
||||||
newPtr = MWWorld::Ptr(&cell.get<ESM::Miscellaneous>().insert(*ref), &cell);
|
newPtr = MWWorld::Ptr(cell.insert(ref), &cell);
|
||||||
}
|
}
|
||||||
return newPtr;
|
return newPtr;
|
||||||
}
|
}
|
||||||
|
|
|
@ -1130,7 +1130,7 @@ namespace MWClass
|
||||||
MWWorld::LiveCellRef<ESM::NPC> *ref =
|
MWWorld::LiveCellRef<ESM::NPC> *ref =
|
||||||
ptr.get<ESM::NPC>();
|
ptr.get<ESM::NPC>();
|
||||||
|
|
||||||
return MWWorld::Ptr(&cell.get<ESM::NPC>().insert(*ref), &cell);
|
return MWWorld::Ptr(cell.insert(ref), &cell);
|
||||||
}
|
}
|
||||||
|
|
||||||
int Npc::getSkill(const MWWorld::Ptr& ptr, int skill) const
|
int Npc::getSkill(const MWWorld::Ptr& ptr, int skill) const
|
||||||
|
|
|
@ -178,7 +178,7 @@ namespace MWClass
|
||||||
MWWorld::LiveCellRef<ESM::Potion> *ref =
|
MWWorld::LiveCellRef<ESM::Potion> *ref =
|
||||||
ptr.get<ESM::Potion>();
|
ptr.get<ESM::Potion>();
|
||||||
|
|
||||||
return MWWorld::Ptr(&cell.get<ESM::Potion>().insert(*ref), &cell);
|
return MWWorld::Ptr(cell.insert(ref), &cell);
|
||||||
}
|
}
|
||||||
|
|
||||||
bool Potion::canSell (const MWWorld::Ptr& item, int npcServices) const
|
bool Potion::canSell (const MWWorld::Ptr& item, int npcServices) const
|
||||||
|
|
|
@ -165,7 +165,7 @@ namespace MWClass
|
||||||
MWWorld::LiveCellRef<ESM::Probe> *ref =
|
MWWorld::LiveCellRef<ESM::Probe> *ref =
|
||||||
ptr.get<ESM::Probe>();
|
ptr.get<ESM::Probe>();
|
||||||
|
|
||||||
return MWWorld::Ptr(&cell.get<ESM::Probe>().insert(*ref), &cell);
|
return MWWorld::Ptr(cell.insert(ref), &cell);
|
||||||
}
|
}
|
||||||
|
|
||||||
bool Probe::canSell (const MWWorld::Ptr& item, int npcServices) const
|
bool Probe::canSell (const MWWorld::Ptr& item, int npcServices) const
|
||||||
|
|
|
@ -160,7 +160,7 @@ namespace MWClass
|
||||||
MWWorld::LiveCellRef<ESM::Repair> *ref =
|
MWWorld::LiveCellRef<ESM::Repair> *ref =
|
||||||
ptr.get<ESM::Repair>();
|
ptr.get<ESM::Repair>();
|
||||||
|
|
||||||
return MWWorld::Ptr(&cell.get<ESM::Repair>().insert(*ref), &cell);
|
return MWWorld::Ptr(cell.insert(ref), &cell);
|
||||||
}
|
}
|
||||||
|
|
||||||
boost::shared_ptr<MWWorld::Action> Repair::use (const MWWorld::Ptr& ptr) const
|
boost::shared_ptr<MWWorld::Action> Repair::use (const MWWorld::Ptr& ptr) const
|
||||||
|
|
|
@ -60,6 +60,6 @@ namespace MWClass
|
||||||
MWWorld::LiveCellRef<ESM::Static> *ref =
|
MWWorld::LiveCellRef<ESM::Static> *ref =
|
||||||
ptr.get<ESM::Static>();
|
ptr.get<ESM::Static>();
|
||||||
|
|
||||||
return MWWorld::Ptr(&cell.get<ESM::Static>().insert(*ref), &cell);
|
return MWWorld::Ptr(cell.insert(ref), &cell);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -417,7 +417,7 @@ namespace MWClass
|
||||||
MWWorld::LiveCellRef<ESM::Weapon> *ref =
|
MWWorld::LiveCellRef<ESM::Weapon> *ref =
|
||||||
ptr.get<ESM::Weapon>();
|
ptr.get<ESM::Weapon>();
|
||||||
|
|
||||||
return MWWorld::Ptr(&cell.get<ESM::Weapon>().insert(*ref), &cell);
|
return MWWorld::Ptr(cell.insert(ref), &cell);
|
||||||
}
|
}
|
||||||
|
|
||||||
int Weapon::getEnchantmentPoints (const MWWorld::Ptr& ptr) const
|
int Weapon::getEnchantmentPoints (const MWWorld::Ptr& ptr) const
|
||||||
|
|
|
@ -44,9 +44,9 @@ namespace MWMechanics
|
||||||
return MWWorld::Ptr(); // check interior cells only
|
return MWWorld::Ptr(); // check interior cells only
|
||||||
|
|
||||||
// Check all the doors in this cell
|
// Check all the doors in this cell
|
||||||
MWWorld::CellRefList<ESM::Door>& doors = cell->get<ESM::Door>();
|
const MWWorld::CellRefList<ESM::Door>& doors = cell->getReadOnlyDoors();
|
||||||
MWWorld::CellRefList<ESM::Door>::List& refList = doors.mList;
|
const MWWorld::CellRefList<ESM::Door>::List& refList = doors.mList;
|
||||||
MWWorld::CellRefList<ESM::Door>::List::iterator it = refList.begin();
|
MWWorld::CellRefList<ESM::Door>::List::const_iterator it = refList.begin();
|
||||||
osg::Vec3f pos(actor.getRefData().getPosition().asVec3());
|
osg::Vec3f pos(actor.getRefData().getPosition().asVec3());
|
||||||
|
|
||||||
/// TODO: How to check whether the actor is facing a door? Below code is for
|
/// TODO: How to check whether the actor is facing a door? Below code is for
|
||||||
|
@ -59,11 +59,12 @@ namespace MWMechanics
|
||||||
/// opposite of the code in World::activateDoor() ::confused::
|
/// opposite of the code in World::activateDoor() ::confused::
|
||||||
for (; it != refList.end(); ++it)
|
for (; it != refList.end(); ++it)
|
||||||
{
|
{
|
||||||
MWWorld::LiveCellRef<ESM::Door>& ref = *it;
|
const MWWorld::LiveCellRef<ESM::Door>& ref = *it;
|
||||||
if((pos - ref.mData.getPosition().asVec3()).length2() < minSqr
|
if((pos - ref.mData.getPosition().asVec3()).length2() < minSqr
|
||||||
&& ref.mData.getPosition().rot[2] == ref.mRef.getPosition().rot[2])
|
&& ref.mData.getPosition().rot[2] == ref.mRef.getPosition().rot[2])
|
||||||
{
|
{
|
||||||
return MWWorld::Ptr(&ref, actor.getCell()); // found, stop searching
|
// FIXME cast
|
||||||
|
return MWWorld::Ptr(&const_cast<MWWorld::LiveCellRef<ESM::Door> &>(ref), actor.getCell()); // found, stop searching
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return MWWorld::Ptr(); // none found
|
return MWWorld::Ptr(); // none found
|
||||||
|
|
|
@ -300,14 +300,16 @@ namespace MWScript
|
||||||
}
|
}
|
||||||
catch(std::exception&)
|
catch(std::exception&)
|
||||||
{
|
{
|
||||||
|
// cell not found, move to exterior instead (vanilla PositionCell compatibility)
|
||||||
const ESM::Cell* cell = MWBase::Environment::get().getWorld()->getExterior(cellID);
|
const ESM::Cell* cell = MWBase::Environment::get().getWorld()->getExterior(cellID);
|
||||||
int cx,cy;
|
int cx,cy;
|
||||||
MWBase::Environment::get().getWorld()->positionToIndex(x,y,cx,cy);
|
MWBase::Environment::get().getWorld()->positionToIndex(x,y,cx,cy);
|
||||||
store = MWBase::Environment::get().getWorld()->getExterior(cx,cy);
|
store = MWBase::Environment::get().getWorld()->getExterior(cx,cy);
|
||||||
if(!cell)
|
if(!cell)
|
||||||
{
|
{
|
||||||
runtime.getContext().report ("unknown cell (" + cellID + ")");
|
std::string error = "PositionCell: unknown interior cell (" + cellID + "), moving to exterior instead";
|
||||||
std::cerr << "unknown cell (" << cellID << ")\n";
|
runtime.getContext().report (error);
|
||||||
|
std::cerr << error << std::endl;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if(store)
|
if(store)
|
||||||
|
|
|
@ -1,5 +1,7 @@
|
||||||
#include "cells.hpp"
|
#include "cells.hpp"
|
||||||
|
|
||||||
|
#include <iostream>
|
||||||
|
|
||||||
#include <components/esm/esmreader.hpp>
|
#include <components/esm/esmreader.hpp>
|
||||||
#include <components/esm/esmwriter.hpp>
|
#include <components/esm/esmwriter.hpp>
|
||||||
#include <components/esm/defs.hpp>
|
#include <components/esm/defs.hpp>
|
||||||
|
@ -23,7 +25,7 @@ MWWorld::CellStore *MWWorld::Cells::getCellStore (const ESM::Cell *cell)
|
||||||
|
|
||||||
if (result==mInteriors.end())
|
if (result==mInteriors.end())
|
||||||
{
|
{
|
||||||
result = mInteriors.insert (std::make_pair (lowerName, CellStore (cell))).first;
|
result = mInteriors.insert (std::make_pair (lowerName, CellStore (cell, mStore, mReader))).first;
|
||||||
}
|
}
|
||||||
|
|
||||||
return &result->second;
|
return &result->second;
|
||||||
|
@ -36,7 +38,7 @@ MWWorld::CellStore *MWWorld::Cells::getCellStore (const ESM::Cell *cell)
|
||||||
if (result==mExteriors.end())
|
if (result==mExteriors.end())
|
||||||
{
|
{
|
||||||
result = mExteriors.insert (std::make_pair (
|
result = mExteriors.insert (std::make_pair (
|
||||||
std::make_pair (cell->getGridX(), cell->getGridY()), CellStore (cell))).first;
|
std::make_pair (cell->getGridX(), cell->getGridY()), CellStore (cell, mStore, mReader))).first;
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -70,7 +72,7 @@ MWWorld::Ptr MWWorld::Cells::getPtrAndCache (const std::string& name, CellStore&
|
||||||
void MWWorld::Cells::writeCell (ESM::ESMWriter& writer, CellStore& cell) const
|
void MWWorld::Cells::writeCell (ESM::ESMWriter& writer, CellStore& cell) const
|
||||||
{
|
{
|
||||||
if (cell.getState()!=CellStore::State_Loaded)
|
if (cell.getState()!=CellStore::State_Loaded)
|
||||||
cell.load (mStore, mReader);
|
cell.load ();
|
||||||
|
|
||||||
ESM::CellState cellState;
|
ESM::CellState cellState;
|
||||||
|
|
||||||
|
@ -114,13 +116,12 @@ MWWorld::CellStore *MWWorld::Cells::getExterior (int x, int y)
|
||||||
}
|
}
|
||||||
|
|
||||||
result = mExteriors.insert (std::make_pair (
|
result = mExteriors.insert (std::make_pair (
|
||||||
std::make_pair (x, y), CellStore (cell))).first;
|
std::make_pair (x, y), CellStore (cell, mStore, mReader))).first;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (result->second.getState()!=CellStore::State_Loaded)
|
if (result->second.getState()!=CellStore::State_Loaded)
|
||||||
{
|
{
|
||||||
// Multiple plugin support for landscape data is much easier than for references. The last plugin wins.
|
result->second.load ();
|
||||||
result->second.load (mStore, mReader);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
return &result->second;
|
return &result->second;
|
||||||
|
@ -135,12 +136,12 @@ MWWorld::CellStore *MWWorld::Cells::getInterior (const std::string& name)
|
||||||
{
|
{
|
||||||
const ESM::Cell *cell = mStore.get<ESM::Cell>().find(lowerName);
|
const ESM::Cell *cell = mStore.get<ESM::Cell>().find(lowerName);
|
||||||
|
|
||||||
result = mInteriors.insert (std::make_pair (lowerName, CellStore (cell))).first;
|
result = mInteriors.insert (std::make_pair (lowerName, CellStore (cell, mStore, mReader))).first;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (result->second.getState()!=CellStore::State_Loaded)
|
if (result->second.getState()!=CellStore::State_Loaded)
|
||||||
{
|
{
|
||||||
result->second.load (mStore, mReader);
|
result->second.load ();
|
||||||
}
|
}
|
||||||
|
|
||||||
return &result->second;
|
return &result->second;
|
||||||
|
@ -158,13 +159,13 @@ MWWorld::Ptr MWWorld::Cells::getPtr (const std::string& name, CellStore& cell,
|
||||||
bool searchInContainers)
|
bool searchInContainers)
|
||||||
{
|
{
|
||||||
if (cell.getState()==CellStore::State_Unloaded)
|
if (cell.getState()==CellStore::State_Unloaded)
|
||||||
cell.preload (mStore, mReader);
|
cell.preload ();
|
||||||
|
|
||||||
if (cell.getState()==CellStore::State_Preloaded)
|
if (cell.getState()==CellStore::State_Preloaded)
|
||||||
{
|
{
|
||||||
if (cell.hasId (name))
|
if (cell.hasId (name))
|
||||||
{
|
{
|
||||||
cell.load (mStore, mReader);
|
cell.load ();
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
return Ptr();
|
return Ptr();
|
||||||
|
@ -304,6 +305,29 @@ void MWWorld::Cells::write (ESM::ESMWriter& writer, Loading::Listener& progress)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
struct GetCellStoreCallback : public MWWorld::CellStore::GetCellStoreCallback
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
GetCellStoreCallback(MWWorld::Cells& cells)
|
||||||
|
: mCells(cells)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
MWWorld::Cells& mCells;
|
||||||
|
|
||||||
|
virtual MWWorld::CellStore* getCellStore(const ESM::CellId& cellId)
|
||||||
|
{
|
||||||
|
try
|
||||||
|
{
|
||||||
|
return mCells.getCell(cellId);
|
||||||
|
}
|
||||||
|
catch (...)
|
||||||
|
{
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
bool MWWorld::Cells::readRecord (ESM::ESMReader& reader, uint32_t type,
|
bool MWWorld::Cells::readRecord (ESM::ESMReader& reader, uint32_t type,
|
||||||
const std::map<int, int>& contentFileMap)
|
const std::map<int, int>& contentFileMap)
|
||||||
{
|
{
|
||||||
|
@ -321,9 +345,9 @@ bool MWWorld::Cells::readRecord (ESM::ESMReader& reader, uint32_t type,
|
||||||
catch (...)
|
catch (...)
|
||||||
{
|
{
|
||||||
// silently drop cells that don't exist anymore
|
// silently drop cells that don't exist anymore
|
||||||
|
std::cerr << "Dropping state for cell " << state.mId.mWorldspace << " (cell no longer exists)" << std::endl;
|
||||||
reader.skipRecord();
|
reader.skipRecord();
|
||||||
return true;
|
return true;
|
||||||
/// \todo log
|
|
||||||
}
|
}
|
||||||
|
|
||||||
state.load (reader);
|
state.load (reader);
|
||||||
|
@ -333,9 +357,11 @@ bool MWWorld::Cells::readRecord (ESM::ESMReader& reader, uint32_t type,
|
||||||
cellStore->readFog(reader);
|
cellStore->readFog(reader);
|
||||||
|
|
||||||
if (cellStore->getState()!=CellStore::State_Loaded)
|
if (cellStore->getState()!=CellStore::State_Loaded)
|
||||||
cellStore->load (mStore, mReader);
|
cellStore->load ();
|
||||||
|
|
||||||
cellStore->readReferences (reader, contentFileMap);
|
GetCellStoreCallback callback(*this);
|
||||||
|
|
||||||
|
cellStore->readReferences (reader, contentFileMap, &callback);
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
|
@ -47,13 +47,16 @@ namespace
|
||||||
|
|
||||||
template<typename T>
|
template<typename T>
|
||||||
MWWorld::Ptr searchViaActorId (MWWorld::CellRefList<T>& actorList, int actorId,
|
MWWorld::Ptr searchViaActorId (MWWorld::CellRefList<T>& actorList, int actorId,
|
||||||
MWWorld::CellStore *cell)
|
MWWorld::CellStore *cell, const std::map<MWWorld::LiveCellRefBase*, MWWorld::CellStore*>& toIgnore)
|
||||||
{
|
{
|
||||||
for (typename MWWorld::CellRefList<T>::List::iterator iter (actorList.mList.begin());
|
for (typename MWWorld::CellRefList<T>::List::iterator iter (actorList.mList.begin());
|
||||||
iter!=actorList.mList.end(); ++iter)
|
iter!=actorList.mList.end(); ++iter)
|
||||||
{
|
{
|
||||||
MWWorld::Ptr actor (&*iter, cell);
|
MWWorld::Ptr actor (&*iter, cell);
|
||||||
|
|
||||||
|
if (toIgnore.find(&*iter) != toIgnore.end())
|
||||||
|
continue;
|
||||||
|
|
||||||
if (actor.getClass().getCreatureStats (actor).matchesActorId (actorId) && actor.getRefData().getCount() > 0)
|
if (actor.getClass().getCreatureStats (actor).matchesActorId (actorId) && actor.getRefData().getCount() > 0)
|
||||||
return actor;
|
return actor;
|
||||||
}
|
}
|
||||||
|
@ -141,6 +144,28 @@ namespace
|
||||||
ref.load (state);
|
ref.load (state);
|
||||||
collection.mList.push_back (ref);
|
collection.mList.push_back (ref);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
struct SearchByRefNumVisitor
|
||||||
|
{
|
||||||
|
MWWorld::LiveCellRefBase* mFound;
|
||||||
|
ESM::RefNum mRefNumToFind;
|
||||||
|
|
||||||
|
SearchByRefNumVisitor(const ESM::RefNum& toFind)
|
||||||
|
: mFound(NULL)
|
||||||
|
, mRefNumToFind(toFind)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
bool operator()(const MWWorld::Ptr& ptr)
|
||||||
|
{
|
||||||
|
if (ptr.getCellRef().getRefNum() == mRefNumToFind)
|
||||||
|
{
|
||||||
|
mFound = ptr.getBase();
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
namespace MWWorld
|
namespace MWWorld
|
||||||
|
@ -179,8 +204,121 @@ namespace MWWorld
|
||||||
return (ref.mRef.mRefnum == pRefnum);
|
return (ref.mRef.mRefnum == pRefnum);
|
||||||
}
|
}
|
||||||
|
|
||||||
CellStore::CellStore (const ESM::Cell *cell)
|
void CellStore::moveFrom(const Ptr &object, CellStore *from)
|
||||||
: mCell (cell), mState (State_Unloaded), mHasState (false), mLastRespawn(0,0)
|
{
|
||||||
|
if (mState != State_Loaded)
|
||||||
|
load();
|
||||||
|
|
||||||
|
mHasState = true;
|
||||||
|
MovedRefTracker::iterator found = mMovedToAnotherCell.find(object.getBase());
|
||||||
|
if (found != mMovedToAnotherCell.end())
|
||||||
|
{
|
||||||
|
// A cell we had previously moved an object to is returning it to us.
|
||||||
|
assert (found->second == from);
|
||||||
|
mMovedToAnotherCell.erase(found);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
mMovedHere.insert(std::make_pair(object.getBase(), from));
|
||||||
|
}
|
||||||
|
updateMergedRefs();
|
||||||
|
}
|
||||||
|
|
||||||
|
MWWorld::Ptr CellStore::moveTo(const Ptr &object, CellStore *cellToMoveTo)
|
||||||
|
{
|
||||||
|
if (cellToMoveTo == this)
|
||||||
|
throw std::runtime_error("moveTo: object is already in this cell");
|
||||||
|
|
||||||
|
// We assume that *this is in State_Loaded since we could hardly have reference to a live object otherwise.
|
||||||
|
if (mState != State_Loaded)
|
||||||
|
throw std::runtime_error("moveTo: can't move object from a non-loaded cell (how did you get this object anyway?)");
|
||||||
|
|
||||||
|
// Ensure that the object actually exists in the cell
|
||||||
|
SearchByRefNumVisitor searchVisitor(object.getCellRef().getRefNum());
|
||||||
|
forEach(searchVisitor);
|
||||||
|
if (!searchVisitor.mFound)
|
||||||
|
throw std::runtime_error("moveTo: object is not in this cell");
|
||||||
|
|
||||||
|
|
||||||
|
// Objects with no refnum can't be handled correctly in the merging process that happens
|
||||||
|
// on a save/load, so do a simple copy & delete for these objects.
|
||||||
|
if (!object.getCellRef().getRefNum().hasContentFile())
|
||||||
|
{
|
||||||
|
MWWorld::Ptr copied = object.getClass().copyToCell(object, *cellToMoveTo);
|
||||||
|
object.getRefData().setCount(0);
|
||||||
|
object.getRefData().setBaseNode(NULL);
|
||||||
|
return copied;
|
||||||
|
}
|
||||||
|
|
||||||
|
MovedRefTracker::iterator found = mMovedHere.find(object.getBase());
|
||||||
|
if (found != mMovedHere.end())
|
||||||
|
{
|
||||||
|
// Special case - object didn't originate in this cell
|
||||||
|
// Move it back to its original cell first
|
||||||
|
CellStore* originalCell = found->second;
|
||||||
|
assert (originalCell != this);
|
||||||
|
originalCell->moveFrom(object, this);
|
||||||
|
|
||||||
|
mMovedHere.erase(found);
|
||||||
|
|
||||||
|
// Now that object is back to its rightful owner, we can move it
|
||||||
|
if (cellToMoveTo != originalCell)
|
||||||
|
{
|
||||||
|
originalCell->moveTo(object, cellToMoveTo);
|
||||||
|
}
|
||||||
|
|
||||||
|
updateMergedRefs();
|
||||||
|
return MWWorld::Ptr(object.getBase(), cellToMoveTo);
|
||||||
|
}
|
||||||
|
|
||||||
|
cellToMoveTo->moveFrom(object, this);
|
||||||
|
mMovedToAnotherCell.insert(std::make_pair(object.getBase(), cellToMoveTo));
|
||||||
|
|
||||||
|
updateMergedRefs();
|
||||||
|
return MWWorld::Ptr(object.getBase(), cellToMoveTo);
|
||||||
|
}
|
||||||
|
|
||||||
|
struct MergeVisitor
|
||||||
|
{
|
||||||
|
MergeVisitor(std::vector<LiveCellRefBase*>& mergeTo, const std::map<LiveCellRefBase*, MWWorld::CellStore*>& movedHere,
|
||||||
|
const std::map<LiveCellRefBase*, MWWorld::CellStore*>& movedToAnotherCell)
|
||||||
|
: mMergeTo(mergeTo)
|
||||||
|
, mMovedHere(movedHere)
|
||||||
|
, mMovedToAnotherCell(movedToAnotherCell)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
bool operator() (const MWWorld::Ptr& ptr)
|
||||||
|
{
|
||||||
|
if (mMovedToAnotherCell.find(ptr.getBase()) != mMovedToAnotherCell.end())
|
||||||
|
return true;
|
||||||
|
mMergeTo.push_back(ptr.getBase());
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
void merge()
|
||||||
|
{
|
||||||
|
for (std::map<LiveCellRefBase*, MWWorld::CellStore*>::const_iterator it = mMovedHere.begin(); it != mMovedHere.end(); ++it)
|
||||||
|
mMergeTo.push_back(it->first);
|
||||||
|
}
|
||||||
|
|
||||||
|
private:
|
||||||
|
std::vector<LiveCellRefBase*>& mMergeTo;
|
||||||
|
|
||||||
|
const std::map<LiveCellRefBase*, MWWorld::CellStore*>& mMovedHere;
|
||||||
|
const std::map<LiveCellRefBase*, MWWorld::CellStore*>& mMovedToAnotherCell;
|
||||||
|
};
|
||||||
|
|
||||||
|
void CellStore::updateMergedRefs()
|
||||||
|
{
|
||||||
|
mMergedRefs.clear();
|
||||||
|
MergeVisitor visitor(mMergedRefs, mMovedHere, mMovedToAnotherCell);
|
||||||
|
forEachInternal(visitor);
|
||||||
|
visitor.merge();
|
||||||
|
}
|
||||||
|
|
||||||
|
CellStore::CellStore (const ESM::Cell *cell, const MWWorld::ESMStore& esmStore, std::vector<ESM::ESMReader>& readerList)
|
||||||
|
: mStore(esmStore), mReader(readerList), mCell (cell), mState (State_Unloaded), mHasState (false), mLastRespawn(0,0)
|
||||||
{
|
{
|
||||||
mWaterLevel = cell->mWater;
|
mWaterLevel = cell->mWater;
|
||||||
}
|
}
|
||||||
|
@ -212,85 +350,50 @@ namespace MWWorld
|
||||||
return const_cast<CellStore *> (this)->search (id).isEmpty();
|
return const_cast<CellStore *> (this)->search (id).isEmpty();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
struct SearchVisitor
|
||||||
|
{
|
||||||
|
MWWorld::Ptr mFound;
|
||||||
|
std::string mIdToFind;
|
||||||
|
bool operator()(const MWWorld::Ptr& ptr)
|
||||||
|
{
|
||||||
|
if (ptr.getCellRef().getRefId() == mIdToFind)
|
||||||
|
{
|
||||||
|
mFound = ptr;
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
Ptr CellStore::search (const std::string& id)
|
Ptr CellStore::search (const std::string& id)
|
||||||
{
|
{
|
||||||
bool oldState = mHasState;
|
bool oldState = mHasState;
|
||||||
|
|
||||||
mHasState = true;
|
SearchVisitor searchVisitor;
|
||||||
|
searchVisitor.mIdToFind = id;
|
||||||
if (LiveCellRef<ESM::Activator> *ref = mActivators.find (id))
|
forEach(searchVisitor);
|
||||||
return Ptr (ref, this);
|
|
||||||
|
|
||||||
if (LiveCellRef<ESM::Potion> *ref = mPotions.find (id))
|
|
||||||
return Ptr (ref, this);
|
|
||||||
|
|
||||||
if (LiveCellRef<ESM::Apparatus> *ref = mAppas.find (id))
|
|
||||||
return Ptr (ref, this);
|
|
||||||
|
|
||||||
if (LiveCellRef<ESM::Armor> *ref = mArmors.find (id))
|
|
||||||
return Ptr (ref, this);
|
|
||||||
|
|
||||||
if (LiveCellRef<ESM::Book> *ref = mBooks.find (id))
|
|
||||||
return Ptr (ref, this);
|
|
||||||
|
|
||||||
if (LiveCellRef<ESM::Clothing> *ref = mClothes.find (id))
|
|
||||||
return Ptr (ref, this);
|
|
||||||
|
|
||||||
if (LiveCellRef<ESM::Container> *ref = mContainers.find (id))
|
|
||||||
return Ptr (ref, this);
|
|
||||||
|
|
||||||
if (LiveCellRef<ESM::Creature> *ref = mCreatures.find (id))
|
|
||||||
return Ptr (ref, this);
|
|
||||||
|
|
||||||
if (LiveCellRef<ESM::Door> *ref = mDoors.find (id))
|
|
||||||
return Ptr (ref, this);
|
|
||||||
|
|
||||||
if (LiveCellRef<ESM::Ingredient> *ref = mIngreds.find (id))
|
|
||||||
return Ptr (ref, this);
|
|
||||||
|
|
||||||
if (LiveCellRef<ESM::CreatureLevList> *ref = mCreatureLists.find (id))
|
|
||||||
return Ptr (ref, this);
|
|
||||||
|
|
||||||
if (LiveCellRef<ESM::ItemLevList> *ref = mItemLists.find (id))
|
|
||||||
return Ptr (ref, this);
|
|
||||||
|
|
||||||
if (LiveCellRef<ESM::Light> *ref = mLights.find (id))
|
|
||||||
return Ptr (ref, this);
|
|
||||||
|
|
||||||
if (LiveCellRef<ESM::Lockpick> *ref = mLockpicks.find (id))
|
|
||||||
return Ptr (ref, this);
|
|
||||||
|
|
||||||
if (LiveCellRef<ESM::Miscellaneous> *ref = mMiscItems.find (id))
|
|
||||||
return Ptr (ref, this);
|
|
||||||
|
|
||||||
if (LiveCellRef<ESM::NPC> *ref = mNpcs.find (id))
|
|
||||||
return Ptr (ref, this);
|
|
||||||
|
|
||||||
if (LiveCellRef<ESM::Probe> *ref = mProbes.find (id))
|
|
||||||
return Ptr (ref, this);
|
|
||||||
|
|
||||||
if (LiveCellRef<ESM::Repair> *ref = mRepairs.find (id))
|
|
||||||
return Ptr (ref, this);
|
|
||||||
|
|
||||||
if (LiveCellRef<ESM::Static> *ref = mStatics.find (id))
|
|
||||||
return Ptr (ref, this);
|
|
||||||
|
|
||||||
if (LiveCellRef<ESM::Weapon> *ref = mWeapons.find (id))
|
|
||||||
return Ptr (ref, this);
|
|
||||||
|
|
||||||
mHasState = oldState;
|
mHasState = oldState;
|
||||||
|
return searchVisitor.mFound;
|
||||||
return Ptr();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
Ptr CellStore::searchViaActorId (int id)
|
Ptr CellStore::searchViaActorId (int id)
|
||||||
{
|
{
|
||||||
if (Ptr ptr = ::searchViaActorId (mNpcs, id, this))
|
if (Ptr ptr = ::searchViaActorId (mNpcs, id, this, mMovedToAnotherCell))
|
||||||
return ptr;
|
return ptr;
|
||||||
|
|
||||||
if (Ptr ptr = ::searchViaActorId (mCreatures, id, this))
|
if (Ptr ptr = ::searchViaActorId (mCreatures, id, this, mMovedToAnotherCell))
|
||||||
return ptr;
|
return ptr;
|
||||||
|
|
||||||
|
for (MovedRefTracker::const_iterator it = mMovedHere.begin(); it != mMovedHere.end(); ++it)
|
||||||
|
{
|
||||||
|
MWWorld::Ptr actor (it->first, this);
|
||||||
|
if (!actor.getClass().isActor())
|
||||||
|
continue;
|
||||||
|
if (actor.getClass().getCreatureStats (actor).matchesActorId (id) && actor.getRefData().getCount() > 0)
|
||||||
|
return actor;
|
||||||
|
}
|
||||||
|
|
||||||
return Ptr();
|
return Ptr();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -309,37 +412,17 @@ namespace MWWorld
|
||||||
|
|
||||||
int CellStore::count() const
|
int CellStore::count() const
|
||||||
{
|
{
|
||||||
return
|
return mMergedRefs.size();
|
||||||
mActivators.mList.size()
|
|
||||||
+ mPotions.mList.size()
|
|
||||||
+ mAppas.mList.size()
|
|
||||||
+ mArmors.mList.size()
|
|
||||||
+ mBooks.mList.size()
|
|
||||||
+ mClothes.mList.size()
|
|
||||||
+ mContainers.mList.size()
|
|
||||||
+ mDoors.mList.size()
|
|
||||||
+ mIngreds.mList.size()
|
|
||||||
+ mCreatureLists.mList.size()
|
|
||||||
+ mItemLists.mList.size()
|
|
||||||
+ mLights.mList.size()
|
|
||||||
+ mLockpicks.mList.size()
|
|
||||||
+ mMiscItems.mList.size()
|
|
||||||
+ mProbes.mList.size()
|
|
||||||
+ mRepairs.mList.size()
|
|
||||||
+ mStatics.mList.size()
|
|
||||||
+ mWeapons.mList.size()
|
|
||||||
+ mCreatures.mList.size()
|
|
||||||
+ mNpcs.mList.size();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void CellStore::load (const MWWorld::ESMStore &store, std::vector<ESM::ESMReader> &esm)
|
void CellStore::load ()
|
||||||
{
|
{
|
||||||
if (mState!=State_Loaded)
|
if (mState!=State_Loaded)
|
||||||
{
|
{
|
||||||
if (mState==State_Preloaded)
|
if (mState==State_Preloaded)
|
||||||
mIds.clear();
|
mIds.clear();
|
||||||
|
|
||||||
loadRefs (store, esm);
|
loadRefs ();
|
||||||
|
|
||||||
mState = State_Loaded;
|
mState = State_Loaded;
|
||||||
|
|
||||||
|
@ -349,18 +432,20 @@ namespace MWWorld
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void CellStore::preload (const MWWorld::ESMStore &store, std::vector<ESM::ESMReader> &esm)
|
void CellStore::preload ()
|
||||||
{
|
{
|
||||||
if (mState==State_Unloaded)
|
if (mState==State_Unloaded)
|
||||||
{
|
{
|
||||||
listRefs (store, esm);
|
listRefs ();
|
||||||
|
|
||||||
mState = State_Preloaded;
|
mState = State_Preloaded;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void CellStore::listRefs(const MWWorld::ESMStore &store, std::vector<ESM::ESMReader> &esm)
|
void CellStore::listRefs()
|
||||||
{
|
{
|
||||||
|
std::vector<ESM::ESMReader>& esm = mReader;
|
||||||
|
|
||||||
assert (mCell);
|
assert (mCell);
|
||||||
|
|
||||||
if (mCell->mContextList.empty())
|
if (mCell->mContextList.empty())
|
||||||
|
@ -404,8 +489,10 @@ namespace MWWorld
|
||||||
std::sort (mIds.begin(), mIds.end());
|
std::sort (mIds.begin(), mIds.end());
|
||||||
}
|
}
|
||||||
|
|
||||||
void CellStore::loadRefs(const MWWorld::ESMStore &store, std::vector<ESM::ESMReader> &esm)
|
void CellStore::loadRefs()
|
||||||
{
|
{
|
||||||
|
std::vector<ESM::ESMReader>& esm = mReader;
|
||||||
|
|
||||||
assert (mCell);
|
assert (mCell);
|
||||||
|
|
||||||
if (mCell->mContextList.empty())
|
if (mCell->mContextList.empty())
|
||||||
|
@ -432,7 +519,7 @@ namespace MWWorld
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
loadRef (ref, deleted, store);
|
loadRef (ref, deleted);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -441,8 +528,10 @@ namespace MWWorld
|
||||||
{
|
{
|
||||||
ESM::CellRef &ref = const_cast<ESM::CellRef&>(*it);
|
ESM::CellRef &ref = const_cast<ESM::CellRef&>(*it);
|
||||||
|
|
||||||
loadRef (ref, false, store);
|
loadRef (ref, false);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
updateMergedRefs();
|
||||||
}
|
}
|
||||||
|
|
||||||
bool CellStore::isExterior() const
|
bool CellStore::isExterior() const
|
||||||
|
@ -470,10 +559,12 @@ namespace MWWorld
|
||||||
return Ptr();
|
return Ptr();
|
||||||
}
|
}
|
||||||
|
|
||||||
void CellStore::loadRef (ESM::CellRef& ref, bool deleted, const ESMStore& store)
|
void CellStore::loadRef (ESM::CellRef& ref, bool deleted)
|
||||||
{
|
{
|
||||||
Misc::StringUtils::lowerCaseInPlace (ref.mRefID);
|
Misc::StringUtils::lowerCaseInPlace (ref.mRefID);
|
||||||
|
|
||||||
|
const MWWorld::ESMStore& store = mStore;
|
||||||
|
|
||||||
switch (store.find (ref.mRefID))
|
switch (store.find (ref.mRefID))
|
||||||
{
|
{
|
||||||
case ESM::REC_ACTI: mActivators.load(ref, deleted, store); break;
|
case ESM::REC_ACTI: mActivators.load(ref, deleted, store); break;
|
||||||
|
@ -564,10 +655,19 @@ namespace MWWorld
|
||||||
writeReferenceCollection<ESM::ObjectState> (writer, mRepairs);
|
writeReferenceCollection<ESM::ObjectState> (writer, mRepairs);
|
||||||
writeReferenceCollection<ESM::ObjectState> (writer, mStatics);
|
writeReferenceCollection<ESM::ObjectState> (writer, mStatics);
|
||||||
writeReferenceCollection<ESM::ObjectState> (writer, mWeapons);
|
writeReferenceCollection<ESM::ObjectState> (writer, mWeapons);
|
||||||
|
|
||||||
|
for (MovedRefTracker::const_iterator it = mMovedToAnotherCell.begin(); it != mMovedToAnotherCell.end(); ++it)
|
||||||
|
{
|
||||||
|
LiveCellRefBase* base = it->first;
|
||||||
|
ESM::RefNum refNum = base->mRef.getRefNum();
|
||||||
|
ESM::CellId movedTo = it->second->getCell()->getCellId();
|
||||||
|
|
||||||
|
refNum.save(writer, true, "MVRF");
|
||||||
|
movedTo.save(writer);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void CellStore::readReferences (ESM::ESMReader& reader,
|
void CellStore::readReferences (ESM::ESMReader& reader, const std::map<int, int>& contentFileMap, GetCellStoreCallback* callback)
|
||||||
const std::map<int, int>& contentFileMap)
|
|
||||||
{
|
{
|
||||||
mHasState = true;
|
mHasState = true;
|
||||||
|
|
||||||
|
@ -695,6 +795,48 @@ namespace MWWorld
|
||||||
throw std::runtime_error ("unknown type in cell reference section");
|
throw std::runtime_error ("unknown type in cell reference section");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
while (reader.isNextSub("MVRF"))
|
||||||
|
{
|
||||||
|
reader.cacheSubName();
|
||||||
|
ESM::RefNum refnum;
|
||||||
|
ESM::CellId movedTo;
|
||||||
|
refnum.load(reader, true, "MVRF");
|
||||||
|
movedTo.load(reader);
|
||||||
|
|
||||||
|
// Search for the reference. It might no longer exist if its content file was removed.
|
||||||
|
SearchByRefNumVisitor visitor(refnum);
|
||||||
|
forEachInternal(visitor);
|
||||||
|
|
||||||
|
if (!visitor.mFound)
|
||||||
|
{
|
||||||
|
std::cout << "Dropping moved ref tag for " << visitor.mFound->mRef.getRefId() << " (moved object no longer exists)" << std::endl;
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
CellStore* otherCell = callback->getCellStore(movedTo);
|
||||||
|
|
||||||
|
if (otherCell == NULL)
|
||||||
|
{
|
||||||
|
std::cerr << "Dropping moved ref tag for " << visitor.mFound->mRef.getRefId()
|
||||||
|
<< " (target cell " << movedTo.mWorldspace << " no longer exists). Reference moved back to its original location." << std::endl;
|
||||||
|
// Note by dropping tag the object will automatically re-appear in its original cell, though potentially at inapproriate coordinates.
|
||||||
|
// Restore original coordinates:
|
||||||
|
visitor.mFound->mData.setPosition(visitor.mFound->mRef.getPosition());
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (otherCell == this)
|
||||||
|
{
|
||||||
|
// Should never happen unless someone's tampering with files.
|
||||||
|
std::cerr << "Found invalid moved ref, ignoring" << std::endl;
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
moveTo(MWWorld::Ptr(visitor.mFound, this), otherCell);
|
||||||
|
}
|
||||||
|
|
||||||
|
updateMergedRefs();
|
||||||
}
|
}
|
||||||
|
|
||||||
bool operator== (const CellStore& left, const CellStore& right)
|
bool operator== (const CellStore& left, const CellStore& right)
|
||||||
|
|
|
@ -40,6 +40,7 @@ namespace ESM
|
||||||
{
|
{
|
||||||
struct CellState;
|
struct CellState;
|
||||||
struct FogState;
|
struct FogState;
|
||||||
|
struct CellId;
|
||||||
}
|
}
|
||||||
|
|
||||||
namespace MWWorld
|
namespace MWWorld
|
||||||
|
@ -60,6 +61,9 @@ namespace MWWorld
|
||||||
|
|
||||||
private:
|
private:
|
||||||
|
|
||||||
|
const MWWorld::ESMStore& mStore;
|
||||||
|
std::vector<ESM::ESMReader>& mReader;
|
||||||
|
|
||||||
// Even though fog actually belongs to the player and not cells,
|
// Even though fog actually belongs to the player and not cells,
|
||||||
// it makes sense to store it here since we need it once for each cell.
|
// it makes sense to store it here since we need it once for each cell.
|
||||||
// Note this is NULL until the cell is explored to save some memory
|
// Note this is NULL until the cell is explored to save some memory
|
||||||
|
@ -73,6 +77,7 @@ namespace MWWorld
|
||||||
|
|
||||||
MWWorld::TimeStamp mLastRespawn;
|
MWWorld::TimeStamp mLastRespawn;
|
||||||
|
|
||||||
|
// List of refs owned by this cell
|
||||||
CellRefList<ESM::Activator> mActivators;
|
CellRefList<ESM::Activator> mActivators;
|
||||||
CellRefList<ESM::Potion> mPotions;
|
CellRefList<ESM::Potion> mPotions;
|
||||||
CellRefList<ESM::Apparatus> mAppas;
|
CellRefList<ESM::Apparatus> mAppas;
|
||||||
|
@ -94,9 +99,95 @@ namespace MWWorld
|
||||||
CellRefList<ESM::Static> mStatics;
|
CellRefList<ESM::Static> mStatics;
|
||||||
CellRefList<ESM::Weapon> mWeapons;
|
CellRefList<ESM::Weapon> mWeapons;
|
||||||
|
|
||||||
|
typedef std::map<LiveCellRefBase*, MWWorld::CellStore*> MovedRefTracker;
|
||||||
|
// References owned by a different cell that have been moved here.
|
||||||
|
// <reference, cell the reference originally came from>
|
||||||
|
MovedRefTracker mMovedHere;
|
||||||
|
// References owned by this cell that have been moved to another cell.
|
||||||
|
// <reference, cell the reference was moved to>
|
||||||
|
MovedRefTracker mMovedToAnotherCell;
|
||||||
|
|
||||||
|
// Merged list of ref's currently in this cell - i.e. with added refs from mMovedHere, removed refs from mMovedToAnotherCell
|
||||||
|
std::vector<LiveCellRefBase*> mMergedRefs;
|
||||||
|
|
||||||
|
/// Moves object from the given cell to this cell.
|
||||||
|
void moveFrom(const MWWorld::Ptr& object, MWWorld::CellStore* from);
|
||||||
|
|
||||||
|
/// Repopulate mMergedRefs.
|
||||||
|
void updateMergedRefs();
|
||||||
|
|
||||||
|
// helper function for forEachInternal
|
||||||
|
template<class Visitor, class List>
|
||||||
|
bool forEachImp (Visitor& visitor, List& list)
|
||||||
|
{
|
||||||
|
for (typename List::List::iterator iter (list.mList.begin()); iter!=list.mList.end();
|
||||||
|
++iter)
|
||||||
|
{
|
||||||
|
if (iter->mData.isDeletedByContentFile())
|
||||||
|
continue;
|
||||||
|
if (!visitor (MWWorld::Ptr(&*iter, this)))
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
// listing only objects owned by this cell. Internal use only, you probably want to use forEach() so that moved objects are accounted for.
|
||||||
|
template<class Visitor>
|
||||||
|
bool forEachInternal (Visitor& visitor)
|
||||||
|
{
|
||||||
|
return
|
||||||
|
forEachImp (visitor, mActivators) &&
|
||||||
|
forEachImp (visitor, mPotions) &&
|
||||||
|
forEachImp (visitor, mAppas) &&
|
||||||
|
forEachImp (visitor, mArmors) &&
|
||||||
|
forEachImp (visitor, mBooks) &&
|
||||||
|
forEachImp (visitor, mClothes) &&
|
||||||
|
forEachImp (visitor, mContainers) &&
|
||||||
|
forEachImp (visitor, mDoors) &&
|
||||||
|
forEachImp (visitor, mIngreds) &&
|
||||||
|
forEachImp (visitor, mItemLists) &&
|
||||||
|
forEachImp (visitor, mLights) &&
|
||||||
|
forEachImp (visitor, mLockpicks) &&
|
||||||
|
forEachImp (visitor, mMiscItems) &&
|
||||||
|
forEachImp (visitor, mProbes) &&
|
||||||
|
forEachImp (visitor, mRepairs) &&
|
||||||
|
forEachImp (visitor, mStatics) &&
|
||||||
|
forEachImp (visitor, mWeapons) &&
|
||||||
|
forEachImp (visitor, mCreatures) &&
|
||||||
|
forEachImp (visitor, mNpcs) &&
|
||||||
|
forEachImp (visitor, mCreatureLists);
|
||||||
|
}
|
||||||
|
|
||||||
|
/// @note If you get a linker error here, this means the given type can not be stored in a cell. The supported types are
|
||||||
|
/// defined at the bottom of this file.
|
||||||
|
template <class T>
|
||||||
|
CellRefList<T>& get();
|
||||||
|
|
||||||
public:
|
public:
|
||||||
|
|
||||||
CellStore (const ESM::Cell *cell_);
|
/// Moves object from this cell to the given cell.
|
||||||
|
/// @note automatically updates given cell by calling cellToMoveTo->moveFrom(...)
|
||||||
|
/// @note throws exception if cellToMoveTo == this
|
||||||
|
/// @return updated MWWorld::Ptr with the new CellStore pointer set.
|
||||||
|
MWWorld::Ptr moveTo(const MWWorld::Ptr& object, MWWorld::CellStore* cellToMoveTo);
|
||||||
|
|
||||||
|
/// Make a copy of the given object and insert it into this cell.
|
||||||
|
/// @note If you get a linker error here, this means the given type can not be inserted into a cell.
|
||||||
|
/// The supported types are defined at the bottom of this file.
|
||||||
|
template <typename T>
|
||||||
|
LiveCellRefBase* insert(const LiveCellRef<T>* ref)
|
||||||
|
{
|
||||||
|
mHasState = true;
|
||||||
|
CellRefList<T>& list = get<T>();
|
||||||
|
LiveCellRefBase* ret = &list.insert(*ref);
|
||||||
|
updateMergedRefs();
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
|
/// @param readerList The readers to use for loading of the cell on-demand.
|
||||||
|
CellStore (const ESM::Cell *cell_,
|
||||||
|
const MWWorld::ESMStore& store,
|
||||||
|
std::vector<ESM::ESMReader>& readerList);
|
||||||
|
|
||||||
const ESM::Cell *getCell() const;
|
const ESM::Cell *getCell() const;
|
||||||
|
|
||||||
|
@ -108,6 +199,7 @@ namespace MWWorld
|
||||||
bool hasId (const std::string& id) const;
|
bool hasId (const std::string& id) const;
|
||||||
///< May return true for deleted IDs when in preload state. Will return false, if cell is
|
///< May return true for deleted IDs when in preload state. Will return false, if cell is
|
||||||
/// unloaded.
|
/// unloaded.
|
||||||
|
/// @note Will not account for moved references which may exist in Loaded state. Use search() instead if the cell is loaded.
|
||||||
|
|
||||||
Ptr search (const std::string& id);
|
Ptr search (const std::string& id);
|
||||||
///< Will return an empty Ptr if cell is not loaded. Does not check references in
|
///< Will return an empty Ptr if cell is not loaded. Does not check references in
|
||||||
|
@ -128,55 +220,82 @@ namespace MWWorld
|
||||||
int count() const;
|
int count() const;
|
||||||
///< Return total number of references, including deleted ones.
|
///< Return total number of references, including deleted ones.
|
||||||
|
|
||||||
void load (const MWWorld::ESMStore &store, std::vector<ESM::ESMReader> &esm);
|
void load ();
|
||||||
///< Load references from content file.
|
///< Load references from content file.
|
||||||
|
|
||||||
void preload (const MWWorld::ESMStore &store, std::vector<ESM::ESMReader> &esm);
|
void preload ();
|
||||||
///< Build ID list from content file.
|
///< Build ID list from content file.
|
||||||
|
|
||||||
/// Call functor (ref) for each reference. functor must return a bool. Returning
|
/// Call visitor (ref) for each reference. visitor must return a bool. Returning
|
||||||
/// false will abort the iteration.
|
/// false will abort the iteration.
|
||||||
/// \attention This function also lists deleted (count 0) objects!
|
/// \attention This function also lists deleted (count 0) objects!
|
||||||
/// \return Iteration completed?
|
/// \return Iteration completed?
|
||||||
///
|
template<class Visitor>
|
||||||
/// \note Creatures and NPCs are handled last.
|
bool forEach (Visitor& visitor)
|
||||||
template<class Functor>
|
|
||||||
bool forEach (Functor& functor)
|
|
||||||
{
|
{
|
||||||
|
if (mState != State_Loaded)
|
||||||
|
return false;
|
||||||
|
|
||||||
mHasState = true;
|
mHasState = true;
|
||||||
|
|
||||||
return
|
for (unsigned int i=0; i<mMergedRefs.size(); ++i)
|
||||||
forEachImp (functor, mActivators) &&
|
{
|
||||||
forEachImp (functor, mPotions) &&
|
if (mMergedRefs[i]->mData.isDeletedByContentFile())
|
||||||
forEachImp (functor, mAppas) &&
|
continue;
|
||||||
forEachImp (functor, mArmors) &&
|
|
||||||
forEachImp (functor, mBooks) &&
|
if (!visitor(MWWorld::Ptr(mMergedRefs[i], this)))
|
||||||
forEachImp (functor, mClothes) &&
|
return false;
|
||||||
forEachImp (functor, mContainers) &&
|
}
|
||||||
forEachImp (functor, mDoors) &&
|
return true;
|
||||||
forEachImp (functor, mIngreds) &&
|
|
||||||
forEachImp (functor, mItemLists) &&
|
|
||||||
forEachImp (functor, mLights) &&
|
|
||||||
forEachImp (functor, mLockpicks) &&
|
|
||||||
forEachImp (functor, mMiscItems) &&
|
|
||||||
forEachImp (functor, mProbes) &&
|
|
||||||
forEachImp (functor, mRepairs) &&
|
|
||||||
forEachImp (functor, mStatics) &&
|
|
||||||
forEachImp (functor, mWeapons) &&
|
|
||||||
forEachImp (functor, mCreatures) &&
|
|
||||||
forEachImp (functor, mNpcs) &&
|
|
||||||
forEachImp (functor, mCreatureLists);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
template<class Functor>
|
/// Call visitor (ref) for each reference of given type. visitor must return a bool. Returning
|
||||||
bool forEachContainer (Functor& functor)
|
/// false will abort the iteration.
|
||||||
|
/// \attention This function also lists deleted (count 0) objects!
|
||||||
|
/// \return Iteration completed?
|
||||||
|
template <class T, class Visitor>
|
||||||
|
bool forEachType(Visitor& visitor)
|
||||||
{
|
{
|
||||||
|
if (mState != State_Loaded)
|
||||||
|
return false;
|
||||||
|
|
||||||
mHasState = true;
|
mHasState = true;
|
||||||
|
|
||||||
return
|
CellRefList<T>& list = get<T>();
|
||||||
forEachImp (functor, mContainers) &&
|
|
||||||
forEachImp (functor, mCreatures) &&
|
for (typename CellRefList<T>::List::iterator it (list.mList.begin()); it!=list.mList.end(); ++it)
|
||||||
forEachImp (functor, mNpcs);
|
{
|
||||||
|
LiveCellRefBase* base = &*it;
|
||||||
|
if (mMovedToAnotherCell.find(base) != mMovedToAnotherCell.end())
|
||||||
|
continue;
|
||||||
|
if (base->mData.isDeletedByContentFile())
|
||||||
|
continue;
|
||||||
|
if (!visitor(MWWorld::Ptr(base, this)))
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
for (MovedRefTracker::const_iterator it = mMovedHere.begin(); it != mMovedHere.end(); ++it)
|
||||||
|
{
|
||||||
|
LiveCellRefBase* base = it->first;
|
||||||
|
if (dynamic_cast<LiveCellRef<T>*>(base))
|
||||||
|
if (!visitor(MWWorld::Ptr(base, this)))
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
/// \todo add const version of forEach
|
||||||
|
|
||||||
|
|
||||||
|
// NOTE: does not account for moved references
|
||||||
|
// Should be phased out when we have const version of forEach
|
||||||
|
inline const CellRefList<ESM::Door>& getReadOnlyDoors() const
|
||||||
|
{
|
||||||
|
return mDoors;
|
||||||
|
}
|
||||||
|
inline const CellRefList<ESM::Static>& getReadOnlyStatics() const
|
||||||
|
{
|
||||||
|
return mStatics;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool isExterior() const;
|
bool isExterior() const;
|
||||||
|
@ -193,47 +312,31 @@ namespace MWWorld
|
||||||
|
|
||||||
void writeReferences (ESM::ESMWriter& writer) const;
|
void writeReferences (ESM::ESMWriter& writer) const;
|
||||||
|
|
||||||
void readReferences (ESM::ESMReader& reader, const std::map<int, int>& contentFileMap);
|
struct GetCellStoreCallback
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
///@note must return NULL if the cell is not found
|
||||||
|
virtual CellStore* getCellStore(const ESM::CellId& cellId) = 0;
|
||||||
|
};
|
||||||
|
|
||||||
|
/// @param callback to use for retrieving of additional CellStore objects by ID (required for resolving moved references)
|
||||||
|
void readReferences (ESM::ESMReader& reader, const std::map<int, int>& contentFileMap, GetCellStoreCallback* callback);
|
||||||
|
|
||||||
void respawn ();
|
void respawn ();
|
||||||
///< Check mLastRespawn and respawn references if necessary. This is a no-op if the cell is not loaded.
|
///< Check mLastRespawn and respawn references if necessary. This is a no-op if the cell is not loaded.
|
||||||
|
|
||||||
template <class T>
|
|
||||||
CellRefList<T>& get() {
|
|
||||||
throw std::runtime_error ("Storage for type " + std::string(typeid(T).name())+ " does not exist in cells");
|
|
||||||
}
|
|
||||||
|
|
||||||
template <class T>
|
|
||||||
const CellRefList<T>& getReadOnly() {
|
|
||||||
throw std::runtime_error ("Read Only CellRefList access not available for type " + std::string(typeid(T).name()) );
|
|
||||||
}
|
|
||||||
|
|
||||||
bool isPointConnected(const int start, const int end) const;
|
bool isPointConnected(const int start, const int end) const;
|
||||||
|
|
||||||
std::list<ESM::Pathgrid::Point> aStarSearch(const int start, const int end) const;
|
std::list<ESM::Pathgrid::Point> aStarSearch(const int start, const int end) const;
|
||||||
|
|
||||||
private:
|
private:
|
||||||
|
|
||||||
template<class Functor, class List>
|
|
||||||
bool forEachImp (Functor& functor, List& list)
|
|
||||||
{
|
|
||||||
for (typename List::List::iterator iter (list.mList.begin()); iter!=list.mList.end();
|
|
||||||
++iter)
|
|
||||||
{
|
|
||||||
if (iter->mData.isDeletedByContentFile())
|
|
||||||
continue;
|
|
||||||
if (!functor (MWWorld::Ptr(&*iter, this)))
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
/// Run through references and store IDs
|
/// Run through references and store IDs
|
||||||
void listRefs(const MWWorld::ESMStore &store, std::vector<ESM::ESMReader> &esm);
|
void listRefs();
|
||||||
|
|
||||||
void loadRefs(const MWWorld::ESMStore &store, std::vector<ESM::ESMReader> &esm);
|
void loadRefs();
|
||||||
|
|
||||||
void loadRef (ESM::CellRef& ref, bool deleted, const ESMStore& store);
|
void loadRef (ESM::CellRef& ref, bool deleted);
|
||||||
///< Make case-adjustments to \a ref and insert it into the respective container.
|
///< Make case-adjustments to \a ref and insert it into the respective container.
|
||||||
///
|
///
|
||||||
/// Invalid \a ref objects are silently dropped.
|
/// Invalid \a ref objects are silently dropped.
|
||||||
|
@ -381,12 +484,6 @@ namespace MWWorld
|
||||||
return mWeapons;
|
return mWeapons;
|
||||||
}
|
}
|
||||||
|
|
||||||
template<>
|
|
||||||
inline const CellRefList<ESM::Door>& CellStore::getReadOnly<ESM::Door>()
|
|
||||||
{
|
|
||||||
return mDoors;
|
|
||||||
}
|
|
||||||
|
|
||||||
bool operator== (const CellStore& left, const CellStore& right);
|
bool operator== (const CellStore& left, const CellStore& right);
|
||||||
bool operator!= (const CellStore& left, const CellStore& right);
|
bool operator!= (const CellStore& left, const CellStore& right);
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,5 +1,5 @@
|
||||||
#ifndef GAME_MWWORLD_CELLFUNCTORS_H
|
#ifndef GAME_MWWORLD_CELLVISITORS_H
|
||||||
#define GAME_MWWORLD_CELLFUNCTORS_H
|
#define GAME_MWWORLD_CELLVISITORS_H
|
||||||
|
|
||||||
#include <vector>
|
#include <vector>
|
||||||
#include <string>
|
#include <string>
|
||||||
|
@ -9,7 +9,7 @@
|
||||||
|
|
||||||
namespace MWWorld
|
namespace MWWorld
|
||||||
{
|
{
|
||||||
struct ListAndResetObjects
|
struct ListAndResetObjectsVisitor
|
||||||
{
|
{
|
||||||
std::vector<MWWorld::Ptr> mObjects;
|
std::vector<MWWorld::Ptr> mObjects;
|
||||||
|
|
|
@ -11,46 +11,54 @@
|
||||||
|
|
||||||
namespace
|
namespace
|
||||||
{
|
{
|
||||||
template<typename T>
|
|
||||||
void listCellScripts (MWWorld::LocalScripts& localScripts,
|
|
||||||
MWWorld::CellRefList<T>& cellRefList, MWWorld::CellStore *cell)
|
|
||||||
{
|
|
||||||
for (typename MWWorld::CellRefList<T>::List::iterator iter (
|
|
||||||
cellRefList.mList.begin());
|
|
||||||
iter!=cellRefList.mList.end(); ++iter)
|
|
||||||
{
|
|
||||||
if (!iter->mBase->mScript.empty() && !iter->mData.isDeleted())
|
|
||||||
{
|
|
||||||
localScripts.add (iter->mBase->mScript, MWWorld::Ptr (&*iter, cell));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// Adds scripts for items in containers (containers/npcs/creatures)
|
struct AddScriptsVisitor
|
||||||
template<typename T>
|
|
||||||
void listCellScriptsCont (MWWorld::LocalScripts& localScripts,
|
|
||||||
MWWorld::CellRefList<T>& cellRefList, MWWorld::CellStore *cell)
|
|
||||||
{
|
{
|
||||||
for (typename MWWorld::CellRefList<T>::List::iterator iter (
|
AddScriptsVisitor(MWWorld::LocalScripts& scripts)
|
||||||
cellRefList.mList.begin());
|
: mScripts(scripts)
|
||||||
iter!=cellRefList.mList.end(); ++iter)
|
|
||||||
{
|
{
|
||||||
|
}
|
||||||
|
MWWorld::LocalScripts& mScripts;
|
||||||
|
|
||||||
MWWorld::Ptr containerPtr (&*iter, cell);
|
bool operator()(const MWWorld::Ptr& ptr)
|
||||||
|
{
|
||||||
|
if (ptr.getRefData().isDeleted())
|
||||||
|
return true;
|
||||||
|
|
||||||
|
std::string script = ptr.getClass().getScript(ptr);
|
||||||
|
|
||||||
|
if (!script.empty())
|
||||||
|
mScripts.add(script, ptr);
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
struct AddContainerItemScriptsVisitor
|
||||||
|
{
|
||||||
|
AddContainerItemScriptsVisitor(MWWorld::LocalScripts& scripts)
|
||||||
|
: mScripts(scripts)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
MWWorld::LocalScripts& mScripts;
|
||||||
|
|
||||||
|
bool operator()(const MWWorld::Ptr& containerPtr)
|
||||||
|
{
|
||||||
MWWorld::ContainerStore& container = containerPtr.getClass().getContainerStore(containerPtr);
|
MWWorld::ContainerStore& container = containerPtr.getClass().getContainerStore(containerPtr);
|
||||||
for(MWWorld::ContainerStoreIterator it3 = container.begin(); it3 != container.end(); ++it3)
|
for(MWWorld::ContainerStoreIterator it = container.begin(); it != container.end(); ++it)
|
||||||
{
|
{
|
||||||
std::string script = it3->getClass().getScript(*it3);
|
std::string script = it->getClass().getScript(*it);
|
||||||
if(script != "")
|
if(script != "")
|
||||||
{
|
{
|
||||||
MWWorld::Ptr item = *it3;
|
MWWorld::Ptr item = *it;
|
||||||
item.mCell = cell;
|
item.mCell = containerPtr.getCell();
|
||||||
localScripts.add (script, item);
|
mScripts.add (script, item);
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
return true;
|
||||||
}
|
}
|
||||||
|
};
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
MWWorld::LocalScripts::LocalScripts (const MWWorld::ESMStore& store) : mStore (store) {}
|
MWWorld::LocalScripts::LocalScripts (const MWWorld::ESMStore& store) : mStore (store) {}
|
||||||
|
@ -116,26 +124,13 @@ void MWWorld::LocalScripts::add (const std::string& scriptName, const Ptr& ptr)
|
||||||
|
|
||||||
void MWWorld::LocalScripts::addCell (CellStore *cell)
|
void MWWorld::LocalScripts::addCell (CellStore *cell)
|
||||||
{
|
{
|
||||||
listCellScripts (*this, cell->get<ESM::Activator>(), cell);
|
AddScriptsVisitor addScriptsVisitor(*this);
|
||||||
listCellScripts (*this, cell->get<ESM::Potion>(), cell);
|
cell->forEach(addScriptsVisitor);
|
||||||
listCellScripts (*this, cell->get<ESM::Apparatus>(), cell);
|
|
||||||
listCellScripts (*this, cell->get<ESM::Armor>(), cell);
|
AddContainerItemScriptsVisitor addContainerItemScriptsVisitor(*this);
|
||||||
listCellScripts (*this, cell->get<ESM::Book>(), cell);
|
cell->forEachType<ESM::NPC>(addContainerItemScriptsVisitor);
|
||||||
listCellScripts (*this, cell->get<ESM::Clothing>(), cell);
|
cell->forEachType<ESM::Creature>(addContainerItemScriptsVisitor);
|
||||||
listCellScripts (*this, cell->get<ESM::Container>(), cell);
|
cell->forEachType<ESM::Container>(addContainerItemScriptsVisitor);
|
||||||
listCellScriptsCont (*this, cell->get<ESM::Container>(), cell);
|
|
||||||
listCellScripts (*this, cell->get<ESM::Creature>(), cell);
|
|
||||||
listCellScriptsCont (*this, cell->get<ESM::Creature>(), cell);
|
|
||||||
listCellScripts (*this, cell->get<ESM::Door>(), cell);
|
|
||||||
listCellScripts (*this, cell->get<ESM::Ingredient>(), cell);
|
|
||||||
listCellScripts (*this, cell->get<ESM::Light>(), cell);
|
|
||||||
listCellScripts (*this, cell->get<ESM::Lockpick>(), cell);
|
|
||||||
listCellScripts (*this, cell->get<ESM::Miscellaneous>(), cell);
|
|
||||||
listCellScripts (*this, cell->get<ESM::NPC>(), cell);
|
|
||||||
listCellScriptsCont (*this, cell->get<ESM::NPC>(), cell);
|
|
||||||
listCellScripts (*this, cell->get<ESM::Probe>(), cell);
|
|
||||||
listCellScripts (*this, cell->get<ESM::Repair>(), cell);
|
|
||||||
listCellScripts (*this, cell->get<ESM::Weapon>(), cell);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void MWWorld::LocalScripts::clear()
|
void MWWorld::LocalScripts::clear()
|
||||||
|
|
|
@ -182,7 +182,7 @@ namespace MWWorld
|
||||||
mPosition = pos;
|
mPosition = pos;
|
||||||
}
|
}
|
||||||
|
|
||||||
const ESM::Position& RefData::getPosition()
|
const ESM::Position& RefData::getPosition() const
|
||||||
{
|
{
|
||||||
return mPosition;
|
return mPosition;
|
||||||
}
|
}
|
||||||
|
|
|
@ -103,7 +103,7 @@ namespace MWWorld
|
||||||
void disable();
|
void disable();
|
||||||
|
|
||||||
void setPosition (const ESM::Position& pos);
|
void setPosition (const ESM::Position& pos);
|
||||||
const ESM::Position& getPosition();
|
const ESM::Position& getPosition() const;
|
||||||
|
|
||||||
void setCustomData (CustomData *data);
|
void setCustomData (CustomData *data);
|
||||||
///< Set custom data (potentially replacing old custom data). The ownership of \a data is
|
///< Set custom data (potentially replacing old custom data). The ownership of \a data is
|
||||||
|
|
|
@ -22,7 +22,7 @@
|
||||||
#include "localscripts.hpp"
|
#include "localscripts.hpp"
|
||||||
#include "esmstore.hpp"
|
#include "esmstore.hpp"
|
||||||
#include "class.hpp"
|
#include "class.hpp"
|
||||||
#include "cellfunctors.hpp"
|
#include "cellvisitors.hpp"
|
||||||
#include "cellstore.hpp"
|
#include "cellstore.hpp"
|
||||||
|
|
||||||
namespace
|
namespace
|
||||||
|
@ -78,7 +78,7 @@ namespace
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
struct InsertFunctor
|
struct InsertVisitor
|
||||||
{
|
{
|
||||||
MWWorld::CellStore& mCell;
|
MWWorld::CellStore& mCell;
|
||||||
bool mRescale;
|
bool mRescale;
|
||||||
|
@ -86,13 +86,13 @@ namespace
|
||||||
MWPhysics::PhysicsSystem& mPhysics;
|
MWPhysics::PhysicsSystem& mPhysics;
|
||||||
MWRender::RenderingManager& mRendering;
|
MWRender::RenderingManager& mRendering;
|
||||||
|
|
||||||
InsertFunctor (MWWorld::CellStore& cell, bool rescale, Loading::Listener& loadingListener,
|
InsertVisitor (MWWorld::CellStore& cell, bool rescale, Loading::Listener& loadingListener,
|
||||||
MWPhysics::PhysicsSystem& physics, MWRender::RenderingManager& rendering);
|
MWPhysics::PhysicsSystem& physics, MWRender::RenderingManager& rendering);
|
||||||
|
|
||||||
bool operator() (const MWWorld::Ptr& ptr);
|
bool operator() (const MWWorld::Ptr& ptr);
|
||||||
};
|
};
|
||||||
|
|
||||||
InsertFunctor::InsertFunctor (MWWorld::CellStore& cell, bool rescale,
|
InsertVisitor::InsertVisitor (MWWorld::CellStore& cell, bool rescale,
|
||||||
Loading::Listener& loadingListener, MWPhysics::PhysicsSystem& physics,
|
Loading::Listener& loadingListener, MWPhysics::PhysicsSystem& physics,
|
||||||
MWRender::RenderingManager& rendering)
|
MWRender::RenderingManager& rendering)
|
||||||
: mCell (cell), mRescale (rescale), mLoadingListener (loadingListener),
|
: mCell (cell), mRescale (rescale), mLoadingListener (loadingListener),
|
||||||
|
@ -100,7 +100,7 @@ namespace
|
||||||
mRendering (rendering)
|
mRendering (rendering)
|
||||||
{}
|
{}
|
||||||
|
|
||||||
bool InsertFunctor::operator() (const MWWorld::Ptr& ptr)
|
bool InsertVisitor::operator() (const MWWorld::Ptr& ptr)
|
||||||
{
|
{
|
||||||
if (mRescale)
|
if (mRescale)
|
||||||
{
|
{
|
||||||
|
@ -116,7 +116,6 @@ namespace
|
||||||
{
|
{
|
||||||
addObject(ptr, mPhysics, mRendering);
|
addObject(ptr, mPhysics, mRendering);
|
||||||
updateObjectRotation(ptr, mPhysics, mRendering, false);
|
updateObjectRotation(ptr, mPhysics, mRendering, false);
|
||||||
ptr.getClass().adjustPosition (ptr, false);
|
|
||||||
}
|
}
|
||||||
catch (const std::exception& e)
|
catch (const std::exception& e)
|
||||||
{
|
{
|
||||||
|
@ -129,6 +128,17 @@ namespace
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
struct AdjustPositionVisitor
|
||||||
|
{
|
||||||
|
bool operator() (const MWWorld::Ptr& ptr)
|
||||||
|
{
|
||||||
|
if (!ptr.getRefData().isDeleted() && ptr.getRefData().isEnabled())
|
||||||
|
ptr.getClass().adjustPosition (ptr, false);
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@ -196,11 +206,11 @@ namespace MWWorld
|
||||||
void Scene::unloadCell (CellStoreCollection::iterator iter)
|
void Scene::unloadCell (CellStoreCollection::iterator iter)
|
||||||
{
|
{
|
||||||
std::cout << "Unloading cell\n";
|
std::cout << "Unloading cell\n";
|
||||||
ListAndResetObjects functor;
|
ListAndResetObjectsVisitor visitor;
|
||||||
|
|
||||||
(*iter)->forEach<ListAndResetObjects>(functor);
|
(*iter)->forEach<ListAndResetObjectsVisitor>(visitor);
|
||||||
for (std::vector<MWWorld::Ptr>::const_iterator iter2 (functor.mObjects.begin());
|
for (std::vector<MWWorld::Ptr>::const_iterator iter2 (visitor.mObjects.begin());
|
||||||
iter2!=functor.mObjects.end(); ++iter2)
|
iter2!=visitor.mObjects.end(); ++iter2)
|
||||||
{
|
{
|
||||||
mPhysics->remove(*iter2);
|
mPhysics->remove(*iter2);
|
||||||
}
|
}
|
||||||
|
@ -551,8 +561,12 @@ namespace MWWorld
|
||||||
|
|
||||||
void Scene::insertCell (CellStore &cell, bool rescale, Loading::Listener* loadingListener)
|
void Scene::insertCell (CellStore &cell, bool rescale, Loading::Listener* loadingListener)
|
||||||
{
|
{
|
||||||
InsertFunctor functor (cell, rescale, *loadingListener, *mPhysics, mRendering);
|
InsertVisitor insertVisitor (cell, rescale, *loadingListener, *mPhysics, mRendering);
|
||||||
cell.forEach (functor);
|
cell.forEach (insertVisitor);
|
||||||
|
|
||||||
|
// do adjustPosition (snapping actors to ground) after objects are loaded, so we don't depend on the loading order
|
||||||
|
AdjustPositionVisitor adjustPosVisitor;
|
||||||
|
cell.forEach (adjustPosVisitor);
|
||||||
}
|
}
|
||||||
|
|
||||||
void Scene::addObjectToScene (const Ptr& ptr)
|
void Scene::addObjectToScene (const Ptr& ptr)
|
||||||
|
|
|
@ -54,7 +54,6 @@
|
||||||
#include "player.hpp"
|
#include "player.hpp"
|
||||||
#include "manualref.hpp"
|
#include "manualref.hpp"
|
||||||
#include "cellstore.hpp"
|
#include "cellstore.hpp"
|
||||||
#include "cellfunctors.hpp"
|
|
||||||
#include "containerstore.hpp"
|
#include "containerstore.hpp"
|
||||||
#include "inventorystore.hpp"
|
#include "inventorystore.hpp"
|
||||||
#include "actionteleport.hpp"
|
#include "actionteleport.hpp"
|
||||||
|
@ -690,12 +689,12 @@ namespace MWWorld
|
||||||
return mWorldScene->searchPtrViaActorId (actorId);
|
return mWorldScene->searchPtrViaActorId (actorId);
|
||||||
}
|
}
|
||||||
|
|
||||||
struct FindContainerFunctor
|
struct FindContainerVisitor
|
||||||
{
|
{
|
||||||
Ptr mContainedPtr;
|
Ptr mContainedPtr;
|
||||||
Ptr mResult;
|
Ptr mResult;
|
||||||
|
|
||||||
FindContainerFunctor(const Ptr& containedPtr) : mContainedPtr(containedPtr) {}
|
FindContainerVisitor(const Ptr& containedPtr) : mContainedPtr(containedPtr) {}
|
||||||
|
|
||||||
bool operator() (Ptr ptr)
|
bool operator() (Ptr ptr)
|
||||||
{
|
{
|
||||||
|
@ -721,11 +720,15 @@ namespace MWWorld
|
||||||
const Scene::CellStoreCollection& collection = mWorldScene->getActiveCells();
|
const Scene::CellStoreCollection& collection = mWorldScene->getActiveCells();
|
||||||
for (Scene::CellStoreCollection::const_iterator cellIt = collection.begin(); cellIt != collection.end(); ++cellIt)
|
for (Scene::CellStoreCollection::const_iterator cellIt = collection.begin(); cellIt != collection.end(); ++cellIt)
|
||||||
{
|
{
|
||||||
FindContainerFunctor functor(ptr);
|
FindContainerVisitor visitor(ptr);
|
||||||
(*cellIt)->forEachContainer(functor);
|
(*cellIt)->forEachType<ESM::Container>(visitor);
|
||||||
|
if (visitor.mResult.isEmpty())
|
||||||
|
(*cellIt)->forEachType<ESM::Creature>(visitor);
|
||||||
|
if (visitor.mResult.isEmpty())
|
||||||
|
(*cellIt)->forEachType<ESM::NPC>(visitor);
|
||||||
|
|
||||||
if (!functor.mResult.isEmpty())
|
if (!visitor.mResult.isEmpty())
|
||||||
return functor.mResult;
|
return visitor.mResult;
|
||||||
}
|
}
|
||||||
|
|
||||||
return Ptr();
|
return Ptr();
|
||||||
|
@ -1149,7 +1152,7 @@ namespace MWWorld
|
||||||
bool newCellActive = mWorldScene->isCellActive(*newCell);
|
bool newCellActive = mWorldScene->isCellActive(*newCell);
|
||||||
if (!currCellActive && newCellActive)
|
if (!currCellActive && newCellActive)
|
||||||
{
|
{
|
||||||
newPtr = ptr.getClass().copyToCell(ptr, *newCell, pos);
|
newPtr = currCell->moveTo(ptr, newCell);
|
||||||
mWorldScene->addObjectToScene(newPtr);
|
mWorldScene->addObjectToScene(newPtr);
|
||||||
|
|
||||||
std::string script = newPtr.getClass().getScript(newPtr);
|
std::string script = newPtr.getClass().getScript(newPtr);
|
||||||
|
@ -1165,17 +1168,16 @@ namespace MWWorld
|
||||||
removeContainerScripts (ptr);
|
removeContainerScripts (ptr);
|
||||||
haveToMove = false;
|
haveToMove = false;
|
||||||
|
|
||||||
newPtr = ptr.getClass().copyToCell(ptr, *newCell);
|
newPtr = currCell->moveTo(ptr, newCell);
|
||||||
newPtr.getRefData().setBaseNode(0);
|
newPtr.getRefData().setBaseNode(0);
|
||||||
}
|
}
|
||||||
else if (!currCellActive && !newCellActive)
|
else if (!currCellActive && !newCellActive)
|
||||||
newPtr = ptr.getClass().copyToCell(ptr, *newCell);
|
newPtr = currCell->moveTo(ptr, newCell);
|
||||||
else // both cells active
|
else // both cells active
|
||||||
{
|
{
|
||||||
newPtr = ptr.getClass().copyToCell(ptr, *newCell, pos);
|
newPtr = currCell->moveTo(ptr, newCell);
|
||||||
|
|
||||||
mRendering->updatePtr(ptr, newPtr);
|
mRendering->updatePtr(ptr, newPtr);
|
||||||
ptr.getRefData().setBaseNode(NULL);
|
|
||||||
MWBase::Environment::get().getSoundManager()->updatePtr (ptr, newPtr);
|
MWBase::Environment::get().getSoundManager()->updatePtr (ptr, newPtr);
|
||||||
mPhysics->updatePtr(ptr, newPtr);
|
mPhysics->updatePtr(ptr, newPtr);
|
||||||
|
|
||||||
|
@ -1192,7 +1194,6 @@ namespace MWWorld
|
||||||
addContainerScripts (newPtr, newCell);
|
addContainerScripts (newPtr, newCell);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
ptr.getRefData().setCount(0);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if (haveToMove && newPtr.getRefData().getBaseNode())
|
if (haveToMove && newPtr.getRefData().getBaseNode())
|
||||||
|
@ -1708,27 +1709,32 @@ namespace MWWorld
|
||||||
|
|
||||||
osg::Vec2f World::getNorthVector (CellStore* cell)
|
osg::Vec2f World::getNorthVector (CellStore* cell)
|
||||||
{
|
{
|
||||||
MWWorld::CellRefList<ESM::Static>& statics = cell->get<ESM::Static>();
|
MWWorld::Ptr northmarker = cell->search("northmarker");
|
||||||
MWWorld::LiveCellRef<ESM::Static>* ref = statics.find("northmarker");
|
|
||||||
if (!ref)
|
if (northmarker.isEmpty())
|
||||||
return osg::Vec2f(0, 1);
|
return osg::Vec2f(0, 1);
|
||||||
|
|
||||||
osg::Quat orient (-ref->mData.getPosition().rot[2], osg::Vec3f(0,0,1));
|
osg::Quat orient (-northmarker.getRefData().getPosition().rot[2], osg::Vec3f(0,0,1));
|
||||||
osg::Vec3f dir = orient * osg::Vec3f(0,1,0);
|
osg::Vec3f dir = orient * osg::Vec3f(0,1,0);
|
||||||
osg::Vec2f d (dir.x(), dir.y());
|
osg::Vec2f d (dir.x(), dir.y());
|
||||||
return d;
|
return d;
|
||||||
}
|
}
|
||||||
|
|
||||||
void World::getDoorMarkers (CellStore* cell, std::vector<World::DoorMarker>& out)
|
struct GetDoorMarkerVisitor
|
||||||
{
|
{
|
||||||
MWWorld::CellRefList<ESM::Door>& doors = cell->get<ESM::Door>();
|
GetDoorMarkerVisitor(std::vector<World::DoorMarker>& out)
|
||||||
CellRefList<ESM::Door>::List& refList = doors.mList;
|
: mOut(out)
|
||||||
for (CellRefList<ESM::Door>::List::iterator it = refList.begin(); it != refList.end(); ++it)
|
|
||||||
{
|
{
|
||||||
MWWorld::LiveCellRef<ESM::Door>& ref = *it;
|
}
|
||||||
|
|
||||||
if (!ref.mData.isEnabled())
|
std::vector<World::DoorMarker>& mOut;
|
||||||
continue;
|
|
||||||
|
bool operator()(const MWWorld::Ptr& ptr)
|
||||||
|
{
|
||||||
|
MWWorld::LiveCellRef<ESM::Door>& ref = *static_cast<MWWorld::LiveCellRef<ESM::Door>* >(ptr.getBase());
|
||||||
|
|
||||||
|
if (!ref.mData.isEnabled() || ref.mData.isDeleted())
|
||||||
|
return true;
|
||||||
|
|
||||||
if (ref.mRef.getTeleport())
|
if (ref.mRef.getTeleport())
|
||||||
{
|
{
|
||||||
|
@ -1744,7 +1750,7 @@ namespace MWWorld
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
cellid.mPaged = true;
|
cellid.mPaged = true;
|
||||||
positionToIndex(
|
MWBase::Environment::get().getWorld()->positionToIndex(
|
||||||
ref.mRef.getDoorDest().pos[0],
|
ref.mRef.getDoorDest().pos[0],
|
||||||
ref.mRef.getDoorDest().pos[1],
|
ref.mRef.getDoorDest().pos[1],
|
||||||
cellid.mIndex.mX,
|
cellid.mIndex.mX,
|
||||||
|
@ -1756,9 +1762,16 @@ namespace MWWorld
|
||||||
|
|
||||||
newMarker.x = pos.pos[0];
|
newMarker.x = pos.pos[0];
|
||||||
newMarker.y = pos.pos[1];
|
newMarker.y = pos.pos[1];
|
||||||
out.push_back(newMarker);
|
mOut.push_back(newMarker);
|
||||||
}
|
}
|
||||||
|
return true;
|
||||||
}
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
void World::getDoorMarkers (CellStore* cell, std::vector<World::DoorMarker>& out)
|
||||||
|
{
|
||||||
|
GetDoorMarkerVisitor visitor(out);
|
||||||
|
cell->forEachType<ESM::Door>(visitor);
|
||||||
}
|
}
|
||||||
|
|
||||||
void World::setWaterHeight(const float height)
|
void World::setWaterHeight(const float height)
|
||||||
|
@ -2253,25 +2266,40 @@ namespace MWWorld
|
||||||
return osg::Vec3f(0,1,0);
|
return osg::Vec3f(0,1,0);
|
||||||
}
|
}
|
||||||
|
|
||||||
void World::getContainersOwnedBy (const MWWorld::Ptr& npc, std::vector<MWWorld::Ptr>& out)
|
struct GetContainersOwnedByVisitor
|
||||||
|
{
|
||||||
|
GetContainersOwnedByVisitor(const MWWorld::Ptr& owner, std::vector<MWWorld::Ptr>& out)
|
||||||
|
: mOwner(owner)
|
||||||
|
, mOut(out)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
MWWorld::Ptr mOwner;
|
||||||
|
std::vector<MWWorld::Ptr>& mOut;
|
||||||
|
|
||||||
|
bool operator()(const MWWorld::Ptr& ptr)
|
||||||
|
{
|
||||||
|
if (ptr.getRefData().isDeleted())
|
||||||
|
return true;
|
||||||
|
|
||||||
|
if (Misc::StringUtils::ciEqual(ptr.getCellRef().getOwner(), mOwner.getCellRef().getRefId()))
|
||||||
|
mOut.push_back(ptr);
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
void World::getContainersOwnedBy (const MWWorld::Ptr& owner, std::vector<MWWorld::Ptr>& out)
|
||||||
{
|
{
|
||||||
const Scene::CellStoreCollection& collection = mWorldScene->getActiveCells();
|
const Scene::CellStoreCollection& collection = mWorldScene->getActiveCells();
|
||||||
for (Scene::CellStoreCollection::const_iterator cellIt = collection.begin(); cellIt != collection.end(); ++cellIt)
|
for (Scene::CellStoreCollection::const_iterator cellIt = collection.begin(); cellIt != collection.end(); ++cellIt)
|
||||||
{
|
{
|
||||||
MWWorld::CellRefList<ESM::Container>& containers = (*cellIt)->get<ESM::Container>();
|
GetContainersOwnedByVisitor visitor (owner, out);
|
||||||
CellRefList<ESM::Container>::List& refList = containers.mList;
|
(*cellIt)->forEachType<ESM::Container>(visitor);
|
||||||
for (CellRefList<ESM::Container>::List::iterator container = refList.begin(); container != refList.end(); ++container)
|
|
||||||
{
|
|
||||||
MWWorld::Ptr ptr (&*container, *cellIt);
|
|
||||||
if (ptr.getRefData().isDeleted())
|
|
||||||
continue;
|
|
||||||
if (Misc::StringUtils::ciEqual(ptr.getCellRef().getOwner(), npc.getCellRef().getRefId()))
|
|
||||||
out.push_back(ptr);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
struct ListObjectsFunctor
|
struct ListObjectsVisitor
|
||||||
{
|
{
|
||||||
std::vector<MWWorld::Ptr> mObjects;
|
std::vector<MWWorld::Ptr> mObjects;
|
||||||
|
|
||||||
|
@ -2288,10 +2316,10 @@ namespace MWWorld
|
||||||
const Scene::CellStoreCollection& collection = mWorldScene->getActiveCells();
|
const Scene::CellStoreCollection& collection = mWorldScene->getActiveCells();
|
||||||
for (Scene::CellStoreCollection::const_iterator cellIt = collection.begin(); cellIt != collection.end(); ++cellIt)
|
for (Scene::CellStoreCollection::const_iterator cellIt = collection.begin(); cellIt != collection.end(); ++cellIt)
|
||||||
{
|
{
|
||||||
ListObjectsFunctor functor;
|
ListObjectsVisitor visitor;
|
||||||
(*cellIt)->forEach<ListObjectsFunctor>(functor);
|
(*cellIt)->forEach(visitor);
|
||||||
|
|
||||||
for (std::vector<MWWorld::Ptr>::iterator it = functor.mObjects.begin(); it != functor.mObjects.end(); ++it)
|
for (std::vector<MWWorld::Ptr>::iterator it = visitor.mObjects.begin(); it != visitor.mObjects.end(); ++it)
|
||||||
if (Misc::StringUtils::ciEqual(it->getCellRef().getOwner(), npc.getCellRef().getRefId()))
|
if (Misc::StringUtils::ciEqual(it->getCellRef().getOwner(), npc.getCellRef().getRefId()))
|
||||||
out.push_back(*it);
|
out.push_back(*it);
|
||||||
}
|
}
|
||||||
|
@ -2342,7 +2370,8 @@ namespace MWWorld
|
||||||
if (0 == cellStore) {
|
if (0 == cellStore) {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
const DoorList &doors = cellStore->get<ESM::Door>().mList;
|
|
||||||
|
const DoorList &doors = cellStore->getReadOnlyDoors().mList;
|
||||||
for (DoorList::const_iterator it = doors.begin(); it != doors.end(); ++it) {
|
for (DoorList::const_iterator it = doors.begin(); it != doors.end(); ++it) {
|
||||||
if (!it->mRef.getTeleport()) {
|
if (!it->mRef.getTeleport()) {
|
||||||
continue;
|
continue;
|
||||||
|
@ -2364,7 +2393,7 @@ namespace MWWorld
|
||||||
if (0 != source) {
|
if (0 != source) {
|
||||||
// Find door leading to our current teleport door
|
// Find door leading to our current teleport door
|
||||||
// and use it destination to position inside cell.
|
// and use it destination to position inside cell.
|
||||||
const DoorList &doors = source->get<ESM::Door>().mList;
|
const DoorList &doors = source->getReadOnlyDoors().mList;
|
||||||
for (DoorList::const_iterator jt = doors.begin(); jt != doors.end(); ++jt) {
|
for (DoorList::const_iterator jt = doors.begin(); jt != doors.end(); ++jt) {
|
||||||
if (it->mRef.getTeleport() &&
|
if (it->mRef.getTeleport() &&
|
||||||
Misc::StringUtils::ciEqual(name, jt->mRef.getDestCell()))
|
Misc::StringUtils::ciEqual(name, jt->mRef.getDestCell()))
|
||||||
|
@ -2378,7 +2407,7 @@ namespace MWWorld
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
// Fall back to the first static location.
|
// Fall back to the first static location.
|
||||||
const StaticList &statics = cellStore->get<ESM::Static>().mList;
|
const StaticList &statics = cellStore->getReadOnlyStatics().mList;
|
||||||
if ( statics.begin() != statics.end() ) {
|
if ( statics.begin() != statics.end() ) {
|
||||||
pos = statics.begin()->mRef.getPosition();
|
pos = statics.begin()->mRef.getPosition();
|
||||||
return true;
|
return true;
|
||||||
|
@ -2747,7 +2776,7 @@ namespace MWWorld
|
||||||
MWWorld::CellStore *next = getInterior( *i );
|
MWWorld::CellStore *next = getInterior( *i );
|
||||||
if ( !next ) continue;
|
if ( !next ) continue;
|
||||||
|
|
||||||
const MWWorld::CellRefList<ESM::Door>& doors = next->getReadOnly<ESM::Door>();
|
const MWWorld::CellRefList<ESM::Door>& doors = next->getReadOnlyDoors();
|
||||||
const CellRefList<ESM::Door>::List& refList = doors.mList;
|
const CellRefList<ESM::Door>::List& refList = doors.mList;
|
||||||
|
|
||||||
// Check if any door in the cell leads to an exterior directly
|
// Check if any door in the cell leads to an exterior directly
|
||||||
|
@ -2807,7 +2836,7 @@ namespace MWWorld
|
||||||
return closestMarker;
|
return closestMarker;
|
||||||
}
|
}
|
||||||
|
|
||||||
const MWWorld::CellRefList<ESM::Door>& doors = next->getReadOnly<ESM::Door>();
|
const MWWorld::CellRefList<ESM::Door>& doors = next->getReadOnlyDoors();
|
||||||
const CellRefList<ESM::Door>::List& doorList = doors.mList;
|
const CellRefList<ESM::Door>::List& doorList = doors.mList;
|
||||||
|
|
||||||
// Check if any door in the cell leads to an exterior directly
|
// Check if any door in the cell leads to an exterior directly
|
||||||
|
@ -2831,7 +2860,6 @@ namespace MWWorld
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return MWWorld::Ptr();
|
return MWWorld::Ptr();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -2888,9 +2916,9 @@ namespace MWWorld
|
||||||
mWeatherManager->update(duration, paused);
|
mWeatherManager->update(duration, paused);
|
||||||
}
|
}
|
||||||
|
|
||||||
struct AddDetectedReference
|
struct AddDetectedReferenceVisitor
|
||||||
{
|
{
|
||||||
AddDetectedReference(std::vector<Ptr>& out, Ptr detector, World::DetectionType type, float squaredDist)
|
AddDetectedReferenceVisitor(std::vector<Ptr>& out, Ptr detector, World::DetectionType type, float squaredDist)
|
||||||
: mOut(out), mDetector(detector), mSquaredDist(squaredDist), mType(type)
|
: mOut(out), mDetector(detector), mSquaredDist(squaredDist), mType(type)
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
@ -2899,7 +2927,7 @@ namespace MWWorld
|
||||||
Ptr mDetector;
|
Ptr mDetector;
|
||||||
float mSquaredDist;
|
float mSquaredDist;
|
||||||
World::DetectionType mType;
|
World::DetectionType mType;
|
||||||
bool operator() (MWWorld::Ptr ptr)
|
bool operator() (const MWWorld::Ptr& ptr)
|
||||||
{
|
{
|
||||||
if ((ptr.getRefData().getPosition().asVec3() - mDetector.getRefData().getPosition().asVec3()).length2() >= mSquaredDist)
|
if ((ptr.getRefData().getPosition().asVec3() - mDetector.getRefData().getPosition().asVec3()).length2() >= mSquaredDist)
|
||||||
return true;
|
return true;
|
||||||
|
@ -2930,7 +2958,7 @@ namespace MWWorld
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool needToAdd (MWWorld::Ptr ptr, MWWorld::Ptr detector)
|
bool needToAdd (const MWWorld::Ptr& ptr, const MWWorld::Ptr& detector)
|
||||||
{
|
{
|
||||||
if (mType == World::Detect_Creature)
|
if (mType == World::Detect_Creature)
|
||||||
{
|
{
|
||||||
|
@ -2970,13 +2998,13 @@ namespace MWWorld
|
||||||
|
|
||||||
dist = feetToGameUnits(dist);
|
dist = feetToGameUnits(dist);
|
||||||
|
|
||||||
AddDetectedReference functor (out, ptr, type, dist*dist);
|
AddDetectedReferenceVisitor visitor (out, ptr, type, dist*dist);
|
||||||
|
|
||||||
const Scene::CellStoreCollection& active = mWorldScene->getActiveCells();
|
const Scene::CellStoreCollection& active = mWorldScene->getActiveCells();
|
||||||
for (Scene::CellStoreCollection::const_iterator it = active.begin(); it != active.end(); ++it)
|
for (Scene::CellStoreCollection::const_iterator it = active.begin(); it != active.end(); ++it)
|
||||||
{
|
{
|
||||||
MWWorld::CellStore* cellStore = *it;
|
MWWorld::CellStore* cellStore = *it;
|
||||||
cellStore->forEach(functor);
|
cellStore->forEach(visitor);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -3232,7 +3260,7 @@ namespace MWWorld
|
||||||
interpreterContext.executeActivation(object, actor);
|
interpreterContext.executeActivation(object, actor);
|
||||||
}
|
}
|
||||||
|
|
||||||
struct ResetActorsFunctor
|
struct ResetActorsVisitor
|
||||||
{
|
{
|
||||||
bool operator() (Ptr ptr)
|
bool operator() (Ptr ptr)
|
||||||
{
|
{
|
||||||
|
@ -3254,8 +3282,8 @@ namespace MWWorld
|
||||||
iter!=mWorldScene->getActiveCells().end(); ++iter)
|
iter!=mWorldScene->getActiveCells().end(); ++iter)
|
||||||
{
|
{
|
||||||
CellStore* cellstore = *iter;
|
CellStore* cellstore = *iter;
|
||||||
ResetActorsFunctor functor;
|
ResetActorsVisitor visitor;
|
||||||
cellstore->forEach(functor);
|
cellstore->forEach(visitor);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -3,12 +3,12 @@
|
||||||
#include "esmreader.hpp"
|
#include "esmreader.hpp"
|
||||||
#include "esmwriter.hpp"
|
#include "esmwriter.hpp"
|
||||||
|
|
||||||
void ESM::RefNum::load (ESMReader& esm, bool wide)
|
void ESM::RefNum::load (ESMReader& esm, bool wide, const std::string& tag)
|
||||||
{
|
{
|
||||||
if (wide)
|
if (wide)
|
||||||
esm.getHNT (*this, "FRMR", 8);
|
esm.getHNT (*this, tag.c_str(), 8);
|
||||||
else
|
else
|
||||||
esm.getHNT (mIndex, "FRMR");
|
esm.getHNT (mIndex, tag.c_str());
|
||||||
}
|
}
|
||||||
|
|
||||||
void ESM::RefNum::save (ESMWriter &esm, bool wide, const std::string& tag) const
|
void ESM::RefNum::save (ESMWriter &esm, bool wide, const std::string& tag) const
|
||||||
|
|
|
@ -16,7 +16,7 @@ namespace ESM
|
||||||
unsigned int mIndex;
|
unsigned int mIndex;
|
||||||
int mContentFile;
|
int mContentFile;
|
||||||
|
|
||||||
void load (ESMReader& esm, bool wide = false);
|
void load (ESMReader& esm, bool wide = false, const std::string& tag = "FRMR");
|
||||||
|
|
||||||
void save (ESMWriter &esm, bool wide = false, const std::string& tag = "FRMR") const;
|
void save (ESMWriter &esm, bool wide = false, const std::string& tag = "FRMR") const;
|
||||||
|
|
||||||
|
|
Loading…
Reference in a new issue