1
0
Fork 0
mirror of https://github.com/OpenMW/openmw.git synced 2025-02-22 18:39:42 +00:00

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.
This commit is contained in:
scrawl 2014-12-06 21:08:18 +01:00
parent 2952a0e2aa
commit f49fde3d5d
9 changed files with 36 additions and 3 deletions

View file

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

View file

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

View file

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

View file

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

View file

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

View file

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

View file

@ -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();

View file

@ -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();

View file

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