From b79f6ac808e71f7ee1fed5cbe46ce718491fc51c Mon Sep 17 00:00:00 2001 From: fredzio Date: Sun, 6 Dec 2020 13:20:37 +0100 Subject: [PATCH 1/3] Force reset position of actor after snapping to the ground. Otherwise the interpolation calculation would kick in and make the actor goes upward if the spawn point is higher than summoner or downward if lower. The actor would then either jump or fall through terrain. --- apps/openmw/mwworld/worldimp.cpp | 2 ++ 1 file changed, 2 insertions(+) diff --git a/apps/openmw/mwworld/worldimp.cpp b/apps/openmw/mwworld/worldimp.cpp index 224925dd55..05051f3003 100644 --- a/apps/openmw/mwworld/worldimp.cpp +++ b/apps/openmw/mwworld/worldimp.cpp @@ -1351,6 +1351,8 @@ namespace MWWorld } moveObject(ptr, ptr.getCell(), pos.x(), pos.y(), pos.z()); + if (force) // force physics to use the new position + mPhysics->getActor(ptr)->resetPosition(); } void World::fixPosition() From 08e73a09ec41fc791166473acdf91a3c0b39c0bb Mon Sep 17 00:00:00 2001 From: fredzio Date: Sun, 6 Dec 2020 13:24:42 +0100 Subject: [PATCH 2/3] Make the code more compact by mean of std::min / max and ternary operator. --- apps/openmw/mwworld/worldimp.cpp | 13 +++---------- 1 file changed, 3 insertions(+), 10 deletions(-) diff --git a/apps/openmw/mwworld/worldimp.cpp b/apps/openmw/mwworld/worldimp.cpp index 05051f3003..265e45d37f 100644 --- a/apps/openmw/mwworld/worldimp.cpp +++ b/apps/openmw/mwworld/worldimp.cpp @@ -1332,22 +1332,15 @@ namespace MWWorld return; } - float terrainHeight = -std::numeric_limits::max(); - if (ptr.getCell()->isExterior()) - terrainHeight = getTerrainHeightAt(pos); - - if (pos.z() < terrainHeight) - pos.z() = terrainHeight; - - pos.z() += 20; // place slightly above. will snap down to ground with code below + const float terrainHeight = ptr.getCell()->isExterior() ? getTerrainHeightAt(pos) : -std::numeric_limits::max(); + pos.z() = std::max(pos.z(), terrainHeight + 20); // place slightly above terrain. will snap down to ground with code below // We still should trace down dead persistent actors - they do not use the "swimdeath" animation. bool swims = ptr.getClass().isActor() && isSwimming(ptr) && !(ptr.getClass().isPersistent(ptr) && ptr.getClass().getCreatureStats(ptr).isDeathAnimationFinished()); if (force || !ptr.getClass().isActor() || (!isFlying(ptr) && !swims && isActorCollisionEnabled(ptr))) { osg::Vec3f traced = mPhysics->traceDown(ptr, pos, Constants::CellSizeInUnits); - if (traced.z() < pos.z()) - pos.z() = traced.z(); + pos.z() = std::min(pos.z(), traced.z()); } moveObject(ptr, ptr.getCell(), pos.x(), pos.y(), pos.z()); From c6c02a6f16384533d1c09a32bb81e5f0ad554cb4 Mon Sep 17 00:00:00 2001 From: fredzio Date: Sun, 6 Dec 2020 13:26:43 +0100 Subject: [PATCH 3/3] Remove useless code. ipos is already initialized with the correct values. --- apps/openmw/mwworld/worldimp.cpp | 8 +------- 1 file changed, 1 insertion(+), 7 deletions(-) diff --git a/apps/openmw/mwworld/worldimp.cpp b/apps/openmw/mwworld/worldimp.cpp index 265e45d37f..49e6a729a8 100644 --- a/apps/openmw/mwworld/worldimp.cpp +++ b/apps/openmw/mwworld/worldimp.cpp @@ -1444,17 +1444,11 @@ namespace MWWorld ipos.pos[1] = spawnPoint.y(); ipos.pos[2] = spawnPoint.z(); - if (!referenceObject.getClass().isActor()) - { - ipos.rot[0] = referenceObject.getRefData().getPosition().rot[0]; - ipos.rot[1] = referenceObject.getRefData().getPosition().rot[1]; - } - else + if (referenceObject.getClass().isActor()) { ipos.rot[0] = 0; ipos.rot[1] = 0; } - ipos.rot[2] = referenceObject.getRefData().getPosition().rot[2]; MWWorld::Ptr placed = copyObjectToCell(ptr, referenceCell, ipos, ptr.getRefData().getCount(), false); adjustPosition(placed, true); // snap to ground