diff --git a/apps/openmw/mwphysics/actor.cpp b/apps/openmw/mwphysics/actor.cpp
index a2454345bf..776212ede9 100644
--- a/apps/openmw/mwphysics/actor.cpp
+++ b/apps/openmw/mwphysics/actor.cpp
@@ -3,6 +3,8 @@
 #include <BulletCollision/CollisionShapes/btBoxShape.h>
 #include <BulletCollision/CollisionDispatch/btCollisionWorld.h>
 
+#include <apps/openmw/mwmechanics/actorutil.hpp>
+#include <apps/openmw/mwworld/cellstore.hpp>
 #include <components/sceneutil/positionattitudetransform.hpp>
 #include <components/resource/bulletshape.hpp>
 #include <components/debug/debuglog.hpp>
@@ -195,6 +197,15 @@ void Actor::applyOffsetChange()
 {
     if (mPositionOffset.length() == 0)
         return;
+    if (mPositionOffset.z() != 0)
+    {
+        // Often, offset are set in sequence x, y, z
+        // We don't want actors to be moved under the ground
+        // Check terrain height at new coordinate and update z offset if necessary
+        const auto pos = mWorldPosition + mPositionOffset;
+        const auto terrainHeight = mPtr.getCell()->isExterior() ? MWBase::Environment::get().getWorld()->getTerrainHeightAt(pos) : -std::numeric_limits<float>::max();
+        mPositionOffset.z() = std::max(pos.z(), terrainHeight) - mWorldPosition.z();
+    }
     mWorldPosition += mPositionOffset;
     mPosition += mPositionOffset;
     mPreviousPosition += mPositionOffset;
diff --git a/apps/openmw/mwscript/transformationextensions.cpp b/apps/openmw/mwscript/transformationextensions.cpp
index e8b4069775..6b92378c70 100644
--- a/apps/openmw/mwscript/transformationextensions.cpp
+++ b/apps/openmw/mwscript/transformationextensions.cpp
@@ -284,17 +284,6 @@ namespace MWScript
                     }
                     else if(axis == "z")
                     {
-                        // We should not place actors under ground
-                        if (ptr.getClass().isActor())
-                        {
-                            float terrainHeight = -std::numeric_limits<float>::max();
-                            if (ptr.getCell()->isExterior())
-                                terrainHeight = MWBase::Environment::get().getWorld()->getTerrainHeightAt(curPos);
-
-                            if (pos < terrainHeight)
-                                pos = terrainHeight;
-                        }
-
                         newPos[2] = pos;
                     }
                     else