From 617cd4ceb6c4d754fe09da225038f97d75256ced Mon Sep 17 00:00:00 2001 From: elsid Date: Tue, 24 May 2022 23:24:52 +0200 Subject: [PATCH 1/2] Make sure physics simulation does not reset flags for nonprocessed actors Actor::getOnGround and Actor::getOnSlope is used to initialize ActorFrameData. After a physics simulation the result is copied back. But when actor is outside processing range, Actor::mInternalCollisionMode is false and physics simulation does not recalculate OnGround and OnSlope flags. So the flags are always set to false that makes actor play landing animation when they exit and then enter actors processing range. --- apps/openmw/mwphysics/actor.hpp | 10 ++-------- apps/openmw/mwphysics/physicssystem.cpp | 4 ++-- 2 files changed, 4 insertions(+), 10 deletions(-) diff --git a/apps/openmw/mwphysics/actor.hpp b/apps/openmw/mwphysics/actor.hpp index 01d8037f6b..d19211d49e 100644 --- a/apps/openmw/mwphysics/actor.hpp +++ b/apps/openmw/mwphysics/actor.hpp @@ -116,17 +116,11 @@ namespace MWPhysics void setOnGround(bool grounded); - bool getOnGround() const - { - return mInternalCollisionMode && mOnGround; - } + bool getOnGround() const { return mOnGround; } void setOnSlope(bool slope); - bool getOnSlope() const - { - return mInternalCollisionMode && mOnSlope; - } + bool getOnSlope() const { return mOnSlope; } /// Sets whether this actor should be able to collide with the water surface void setCanWaterWalk(bool waterWalk); diff --git a/apps/openmw/mwphysics/physicssystem.cpp b/apps/openmw/mwphysics/physicssystem.cpp index 1c1a2d6fbd..4de60f4900 100644 --- a/apps/openmw/mwphysics/physicssystem.cpp +++ b/apps/openmw/mwphysics/physicssystem.cpp @@ -176,7 +176,7 @@ namespace MWPhysics bool PhysicsSystem::isOnSolidGround (const MWWorld::Ptr& actor) const { const Actor* physactor = getActor(actor); - if (!physactor || !physactor->getOnGround()) + if (!physactor || !physactor->getOnGround() || !physactor->getCollisionMode()) return false; const auto obj = physactor->getStandingOnPtr(); @@ -374,7 +374,7 @@ namespace MWPhysics bool PhysicsSystem::isOnGround(const MWWorld::Ptr &actor) { Actor* physactor = getActor(actor); - return physactor && physactor->getOnGround(); + return physactor && physactor->getOnGround() && physactor->getCollisionMode(); } bool PhysicsSystem::canMoveToWaterSurface(const MWWorld::ConstPtr &actor, const float waterlevel) From 85c79d382c328e1484357206e98d4586b7ab3465 Mon Sep 17 00:00:00 2001 From: elsid Date: Tue, 24 May 2022 23:25:23 +0200 Subject: [PATCH 2/2] Enable collisions for actor before adjusting position Otherwise adjustPosition does not call traceDown and actor appears flying for the first physics simulation. --- apps/openmw/mwmechanics/actors.cpp | 19 +++++++++---------- 1 file changed, 9 insertions(+), 10 deletions(-) diff --git a/apps/openmw/mwmechanics/actors.cpp b/apps/openmw/mwmechanics/actors.cpp index c063748bdc..7dfad96126 100644 --- a/apps/openmw/mwmechanics/actors.cpp +++ b/apps/openmw/mwmechanics/actors.cpp @@ -1596,15 +1596,6 @@ namespace MWMechanics world->setActorCollisionMode(actor.getPtr(), false, false); continue; } - else if (!isPlayer) - { - actor.getPtr().getRefData().getBaseNode()->setNodeMask(MWRender::Mask_Actor); - if (!actor.getPositionAdjusted()) - { - actor.getPtr().getClass().adjustPosition(actor.getPtr(), false); - actor.setPositionAdjusted(true); - } - } const bool isDead = actor.getPtr().getClass().getCreatureStats(actor.getPtr()).isDead(); if (!isDead && (!godmode || !isPlayer) && actor.getPtr().getClass().getCreatureStats(actor.getPtr()).isParalyzed()) @@ -1612,13 +1603,21 @@ namespace MWMechanics // Handle player last, in case a cell transition occurs by casting a teleportation spell // (would invalidate the iterator) - if (actor.getPtr() == getPlayer()) + if (isPlayer) { playerCharacter = &ctrl; continue; } + actor.getPtr().getRefData().getBaseNode()->setNodeMask(MWRender::Mask_Actor); world->setActorCollisionMode(actor.getPtr(), true, !actor.getPtr().getClass().getCreatureStats(actor.getPtr()).isDeathAnimationFinished()); + + if (!actor.getPositionAdjusted()) + { + actor.getPtr().getClass().adjustPosition(actor.getPtr(), false); + actor.setPositionAdjusted(true); + } + ctrl.update(duration); updateVisibility(actor.getPtr(), ctrl);