From 9cae7882dd53480bc75fa00de0954d00eeef20ce Mon Sep 17 00:00:00 2001 From: fredzio Date: Wed, 31 Mar 2021 19:34:06 +0200 Subject: [PATCH] Fix a bug that was triggered with multi mark mod. When a script calls SetPos for x,y,z in sequence on an actor, we need to make sure that the actor will not spawn under ground at x,y coordinates. Now that change of coordinates are cumulated and applied all at once, we need to account for the whole offset. To this end move the terrain height check inside of Actor class. --- apps/openmw/mwphysics/actor.cpp | 11 +++++++++++ apps/openmw/mwscript/transformationextensions.cpp | 11 ----------- 2 files changed, 11 insertions(+), 11 deletions(-) diff --git a/apps/openmw/mwphysics/actor.cpp b/apps/openmw/mwphysics/actor.cpp index a2454345b..776212ede 100644 --- a/apps/openmw/mwphysics/actor.cpp +++ b/apps/openmw/mwphysics/actor.cpp @@ -3,6 +3,8 @@ #include #include +#include +#include #include #include #include @@ -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::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 e8b406977..6b92378c7 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::max(); - if (ptr.getCell()->isExterior()) - terrainHeight = MWBase::Environment::get().getWorld()->getTerrainHeightAt(curPos); - - if (pos < terrainHeight) - pos = terrainHeight; - } - newPos[2] = pos; } else