From 8bcfac1ea3779ad3ac18b2dfedecb291f5c98418 Mon Sep 17 00:00:00 2001
From: scrawl <scrawl@baseoftrash.de>
Date: Sun, 17 May 2015 16:25:13 +0200
Subject: [PATCH] Fix adjustPosition not always working correctly (Fixes #2563)

moveObject was returning an incorrect Ptr for cell movements.
---
 apps/openmw/mwbase/world.hpp                  |  4 +-
 .../mwscript/transformationextensions.cpp     |  7 ++--
 apps/openmw/mwworld/worldimp.cpp              | 37 +++++++++----------
 apps/openmw/mwworld/worldimp.hpp              |  4 +-
 4 files changed, 25 insertions(+), 27 deletions(-)

diff --git a/apps/openmw/mwbase/world.hpp b/apps/openmw/mwbase/world.hpp
index 9e6c6d9bf3..c110e94d61 100644
--- a/apps/openmw/mwbase/world.hpp
+++ b/apps/openmw/mwbase/world.hpp
@@ -286,8 +286,8 @@ namespace MWBase
             virtual MWWorld::Ptr moveObject (const MWWorld::Ptr& ptr, float x, float y, float z) = 0;
             ///< @return an updated Ptr in case the Ptr's cell changes
 
-            virtual void
-            moveObject(const MWWorld::Ptr &ptr, MWWorld::CellStore* newCell, float x, float y, float z) = 0;
+            virtual MWWorld::Ptr moveObject(const MWWorld::Ptr &ptr, MWWorld::CellStore* newCell, float x, float y, float z) = 0;
+            ///< @return an updated Ptr
 
             virtual void scaleObject (const MWWorld::Ptr& ptr, float scale) = 0;
 
diff --git a/apps/openmw/mwscript/transformationextensions.cpp b/apps/openmw/mwscript/transformationextensions.cpp
index f87983ce88..414ef7fb7d 100644
--- a/apps/openmw/mwscript/transformationextensions.cpp
+++ b/apps/openmw/mwscript/transformationextensions.cpp
@@ -370,18 +370,17 @@ namespace MWScript
 
                     // another morrowind oddity: player will be moved to the exterior cell at this location,
                     // non-player actors will move within the cell they are in.
-                    MWWorld::Ptr updated;
                     if (ptr == MWBase::Environment::get().getWorld()->getPlayerPtr())
                     {
                         MWWorld::CellStore* cell = MWBase::Environment::get().getWorld()->getExterior(cx,cy);
                         MWBase::Environment::get().getWorld()->moveObject(ptr,cell,x,y,z);
-                        updated = MWWorld::Ptr(ptr.getBase(), cell);
+                        ptr = MWWorld::Ptr(ptr.getBase(), cell);
                     }
                     else
                     {
-                        updated = MWBase::Environment::get().getWorld()->moveObject(ptr, x, y, z);
+                        ptr = MWBase::Environment::get().getWorld()->moveObject(ptr, x, y, z);
                     }
-                    dynamic_cast<MWScript::InterpreterContext&>(runtime.getContext()).updatePtr(updated);
+                    dynamic_cast<MWScript::InterpreterContext&>(runtime.getContext()).updatePtr(ptr);
 
                     float ax = Ogre::Radian(ptr.getRefData().getPosition().rot[0]).valueDegrees();
                     float ay = Ogre::Radian(ptr.getRefData().getPosition().rot[1]).valueDegrees();
diff --git a/apps/openmw/mwworld/worldimp.cpp b/apps/openmw/mwworld/worldimp.cpp
index 0f81106248..bb0402c4e5 100644
--- a/apps/openmw/mwworld/worldimp.cpp
+++ b/apps/openmw/mwworld/worldimp.cpp
@@ -1108,7 +1108,7 @@ namespace MWWorld
         }
     }
 
-    void World::moveObject(const Ptr &ptr, CellStore* newCell, float x, float y, float z)
+    MWWorld::Ptr World::moveObject(const Ptr &ptr, CellStore* newCell, float x, float y, float z)
     {
         ESM::Position pos = ptr.getRefData().getPosition();
 
@@ -1123,6 +1123,7 @@ namespace MWWorld
         CellStore *currCell = ptr.isInCell() ? ptr.getCell() : NULL; // currCell == NULL should only happen for player, during initial startup
         bool isPlayer = ptr == mPlayer->getPlayer();
         bool haveToMove = isPlayer || (currCell && mWorldScene->isCellActive(*currCell));
+        MWWorld::Ptr newPtr = ptr;
 
         if (currCell != newCell)
         {
@@ -1140,6 +1141,7 @@ namespace MWWorld
                         mWorldScene->changeToExteriorCell(pos, false);
                 }
                 addContainerScripts (getPlayerPtr(), newCell);
+                newPtr = getPlayerPtr();
             }
             else
             {
@@ -1147,7 +1149,7 @@ namespace MWWorld
                 bool newCellActive = mWorldScene->isCellActive(*newCell);
                 if (!currCellActive && newCellActive)
                 {
-                    MWWorld::Ptr newPtr = ptr.getClass().copyToCell(ptr, *newCell, pos);
+                    newPtr = ptr.getClass().copyToCell(ptr, *newCell, pos);
                     mWorldScene->addObjectToScene(newPtr);
 
                     std::string script = newPtr.getClass().getScript(newPtr);
@@ -1163,23 +1165,21 @@ namespace MWWorld
                     removeContainerScripts (ptr);
                     haveToMove = false;
 
-                    MWWorld::Ptr newPtr = ptr.getClass()
-                            .copyToCell(ptr, *newCell);
+                    newPtr = ptr.getClass().copyToCell(ptr, *newCell);
                     newPtr.getRefData().setBaseNode(0);
                 }
                 else if (!currCellActive && !newCellActive)
-                    ptr.getClass().copyToCell(ptr, *newCell);
+                    newPtr = ptr.getClass().copyToCell(ptr, *newCell);
                 else // both cells active
                 {
-                    MWWorld::Ptr copy =
-                        ptr.getClass().copyToCell(ptr, *newCell, pos);
+                    newPtr = ptr.getClass().copyToCell(ptr, *newCell, pos);
 
-                    mRendering->updateObjectCell(ptr, copy);
+                    mRendering->updateObjectCell(ptr, newPtr);
                     ptr.getRefData().setBaseNode(NULL);
-                    MWBase::Environment::get().getSoundManager()->updatePtr (ptr, copy);
+                    MWBase::Environment::get().getSoundManager()->updatePtr (ptr, newPtr);
 
                     MWBase::MechanicsManager *mechMgr = MWBase::Environment::get().getMechanicsManager();
-                    mechMgr->updateCell(ptr, copy);
+                    mechMgr->updateCell(ptr, newPtr);
 
                     std::string script =
                         ptr.getClass().getScript(ptr);
@@ -1187,22 +1187,23 @@ namespace MWWorld
                     {
                         mLocalScripts.remove(ptr);
                         removeContainerScripts (ptr);
-                        mLocalScripts.add(script, copy);
-                        addContainerScripts (copy, newCell);
+                        mLocalScripts.add(script, newPtr);
+                        addContainerScripts (newPtr, newCell);
                     }
                 }
                 ptr.getRefData().setCount(0);
             }
         }
-        if (haveToMove && ptr.getRefData().getBaseNode())
+        if (haveToMove && newPtr.getRefData().getBaseNode())
         {
-            mRendering->moveObject(ptr, vec);
-            mPhysics->moveObject (ptr);
+            mRendering->moveObject(newPtr, vec);
+            mPhysics->moveObject (newPtr);
         }
         if (isPlayer)
         {
             mWorldScene->playerMoved (vec);
         }
+        return newPtr;
     }
 
     MWWorld::Ptr World::moveObjectImp(const Ptr& ptr, float x, float y, float z)
@@ -1216,11 +1217,7 @@ namespace MWWorld
             cell = getExterior(cellX, cellY);
         }
 
-        moveObject(ptr, cell, x, y, z);
-
-        MWWorld::Ptr updated = ptr;
-        updated.mCell = cell;
-        return updated;
+        return moveObject(ptr, cell, x, y, z);
     }
 
     MWWorld::Ptr World::moveObject (const Ptr& ptr, float x, float y, float z)
diff --git a/apps/openmw/mwworld/worldimp.hpp b/apps/openmw/mwworld/worldimp.hpp
index 63d6506de0..bf25c20bbd 100644
--- a/apps/openmw/mwworld/worldimp.hpp
+++ b/apps/openmw/mwworld/worldimp.hpp
@@ -348,7 +348,9 @@ namespace MWWorld
 
             virtual MWWorld::Ptr moveObject (const Ptr& ptr, float x, float y, float z);
             ///< @return an updated Ptr in case the Ptr's cell changes
-            virtual void moveObject (const Ptr& ptr, CellStore* newCell, float x, float y, float z);
+
+            virtual MWWorld::Ptr moveObject (const Ptr& ptr, CellStore* newCell, float x, float y, float z);
+            ///< @return an updated Ptr
 
             virtual void scaleObject (const Ptr& ptr, float scale);