From a72cd896caf7ef09c52ff2e9c9b338acc0ee2d7c Mon Sep 17 00:00:00 2001 From: Assumeru Date: Tue, 25 Oct 2016 19:26:17 +0200 Subject: [PATCH] Move actors out of the water if there's room for them. Fixes #1138 --- apps/openmw/mwphysics/physicssystem.cpp | 33 +++++++++++++++++++++---- 1 file changed, 28 insertions(+), 5 deletions(-) diff --git a/apps/openmw/mwphysics/physicssystem.cpp b/apps/openmw/mwphysics/physicssystem.cpp index e442fbda1e..cf75cbf10a 100644 --- a/apps/openmw/mwphysics/physicssystem.cpp +++ b/apps/openmw/mwphysics/physicssystem.cpp @@ -1318,11 +1318,34 @@ namespace MWPhysics const MWMechanics::MagicEffects& effects = iter->first.getClass().getCreatureStats(iter->first).getMagicEffects(); bool waterCollision = false; - if (effects.get(ESM::MagicEffect::WaterWalking).getMagnitude() - && cell->getCell()->hasWater() - && !world->isUnderwater(iter->first.getCell(), - osg::Vec3f(iter->first.getRefData().getPosition().asVec3()))) - waterCollision = true; + if (cell->getCell()->hasWater() && effects.get(ESM::MagicEffect::WaterWalking).getMagnitude()) + { + if (!world->isUnderwater(iter->first.getCell(), osg::Vec3f(iter->first.getRefData().getPosition().asVec3()))) + waterCollision = true; + else + { + Actor *actor = getActor(iter->first); + // Actor can collide + if (actor->getCollisionMode()) + { + const osg::Vec3f actorPosition = actor->getPosition(); + const osg::Vec3f destinationPosition(actorPosition.x(), actorPosition.y(), waterlevel); + ActorTracer tracer; + tracer.doTrace(actor->getCollisionObject(), actorPosition, destinationPosition, mCollisionWorld); + if (tracer.mFraction >= 1.0f) + { + waterCollision = true; + actor->setPosition(destinationPosition); + } + else + { + //Remove the effect to remove the performance hit of casting in a weird spot + //probably makes that Tribunal quest where the water rises a bit safer + iter->first.getClass().getCreatureStats(iter->first).getActiveSpells().purgeEffect(ESM::MagicEffect::WaterWalking); + } + } + } + } ActorMap::iterator foundActor = mActors.find(iter->first); if (foundActor == mActors.end()) // actor was already removed from the scene