Add support for undeleting references (Fixes #2193)

Deleted references should be accessible via an explicit reference, and can be undeleted using "setdelete 0". Also the Resurrect function implicitely undeletes the given reference.
moveref
scrawl 10 years ago
parent 2952a0e2aa
commit f49fde3d5d

@ -279,6 +279,7 @@ namespace MWBase
///< Attempt to fix position so that the Ptr is no longer inside collision geometry.
virtual void deleteObject (const MWWorld::Ptr& ptr) = 0;
virtual void undeleteObject (const MWWorld::Ptr& ptr) = 0;
virtual void moveObject (const MWWorld::Ptr& ptr, float x, float y, float z) = 0;

@ -571,6 +571,10 @@ namespace MWScript
if (parameter == 1)
MWBase::Environment::get().getWorld()->deleteObject(ptr);
else if (parameter == 0)
MWBase::Environment::get().getWorld()->undeleteObject(ptr);
else
throw std::runtime_error("SetDelete: unexpected parameter");
}
};

@ -1184,6 +1184,7 @@ namespace MWScript
ptr.getClass().getCreatureStats(ptr).resurrect();
else if (ptr.getClass().getCreatureStats(ptr).isDead())
{
MWBase::Environment::get().getWorld()->undeleteObject(ptr);
// resets runtime state such as inventory, stats and AI. does not reset position in the world
ptr.getRefData().setCustomData(NULL);
}

@ -27,7 +27,7 @@ namespace MWWorld
LiveRef *find (const std::string& name)
{
for (typename List::iterator iter (mList.begin()); iter!=mList.end(); ++iter)
if (iter->mData.getCount() > 0 && iter->mRef.getRefId() == name)
if (iter->mRef.getRefId() == name)
return &*iter;
return 0;
@ -42,7 +42,7 @@ namespace MWWorld
LiveCellRef<X> *searchViaHandle (const std::string& handle)
{
for (typename List::iterator iter (mList.begin()); iter!=mList.end(); ++iter)
if (iter->mData.getCount()>0 && iter->mData.getBaseNode() &&
if (iter->mData.getBaseNode() &&
iter->mData.getHandle()==handle)
return &*iter;

@ -196,7 +196,7 @@ namespace MWWorld
for (typename List::List::iterator iter (list.mList.begin()); iter!=list.mList.end();
++iter)
{
if (iter->mData.isDeleted())
if (iter->mData.isDeletedByContentFile())
continue;
if (!functor (MWWorld::Ptr(&*iter, this)))
return false;

@ -180,6 +180,11 @@ namespace MWWorld
return mDeleted || mCount == 0;
}
bool RefData::isDeletedByContentFile() const
{
return mDeleted;
}
MWScript::Locals& RefData::getLocals()
{
return mLocals;

@ -100,6 +100,8 @@ namespace MWWorld
/// Returns true if the object was either deleted by the content file or by gameplay.
bool isDeleted() const;
/// Returns true if the object was deleted by a content file.
bool isDeletedByContentFile() const;
MWScript::Locals& getLocals();

@ -1072,6 +1072,25 @@ namespace MWWorld
}
}
void World::undeleteObject(const Ptr& ptr)
{
if (ptr.getCellRef().getRefNum().mContentFile == -1)
return;
if (ptr.getRefData().isDeleted())
{
ptr.getRefData().setCount(1);
if (mWorldScene->getActiveCells().find(ptr.getCell()) != mWorldScene->getActiveCells().end()
&& ptr.getRefData().isEnabled())
{
mWorldScene->addObjectToScene(ptr);
std::string script = ptr.getClass().getScript(ptr);
if (!script.empty())
mLocalScripts.add(script, ptr);
addContainerScripts(ptr, ptr.getCell());
}
}
}
void World::moveObject(const Ptr &ptr, CellStore* newCell, float x, float y, float z)
{
ESM::Position pos = ptr.getRefData().getPosition();

@ -338,6 +338,7 @@ namespace MWWorld
virtual std::pair<MWWorld::Ptr,Ogre::Vector3> getHitContact(const MWWorld::Ptr &ptr, float distance);
virtual void deleteObject (const Ptr& ptr);
virtual void undeleteObject (const Ptr& ptr);
virtual void moveObject (const Ptr& ptr, float x, float y, float z);
virtual void moveObject (const Ptr& ptr, CellStore* newCell, float x, float y, float z);

Loading…
Cancel
Save