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