From a72cd896caf7ef09c52ff2e9c9b338acc0ee2d7c Mon Sep 17 00:00:00 2001 From: Assumeru Date: Tue, 25 Oct 2016 19:26:17 +0200 Subject: [PATCH 1/5] 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 From 25d64989b3ea5c31360991730e035fa2840584d6 Mon Sep 17 00:00:00 2001 From: Assumeru Date: Wed, 26 Oct 2016 11:04:54 +0200 Subject: [PATCH 2/5] Check if the actor still exists /first/ --- apps/openmw/mwphysics/physicssystem.cpp | 44 +++++++++++-------------- 1 file changed, 19 insertions(+), 25 deletions(-) diff --git a/apps/openmw/mwphysics/physicssystem.cpp b/apps/openmw/mwphysics/physicssystem.cpp index cf75cbf10a..cd4484aa19 100644 --- a/apps/openmw/mwphysics/physicssystem.cpp +++ b/apps/openmw/mwphysics/physicssystem.cpp @@ -1309,12 +1309,16 @@ namespace MWPhysics PtrVelocityList::iterator iter = mMovementQueue.begin(); for(;iter != mMovementQueue.end();++iter) { + ActorMap::iterator foundActor = mActors.find(iter->first); + if (foundActor == mActors.end()) // actor was already removed from the scene + continue; + Actor* physicActor = foundActor->second; + float waterlevel = -std::numeric_limits::max(); const MWWorld::CellStore *cell = iter->first.getCell(); if(cell->getCell()->hasWater()) waterlevel = cell->getWaterLevel(); - const MWMechanics::MagicEffects& effects = iter->first.getClass().getCreatureStats(iter->first).getMagicEffects(); bool waterCollision = false; @@ -1322,35 +1326,25 @@ namespace MWPhysics { if (!world->isUnderwater(iter->first.getCell(), osg::Vec3f(iter->first.getRefData().getPosition().asVec3()))) waterCollision = true; - else + else if (physicActor->getCollisionMode()) { - Actor *actor = getActor(iter->first); - // Actor can collide - if (actor->getCollisionMode()) + const osg::Vec3f actorPosition = physicActor->getPosition(); + const osg::Vec3f destinationPosition(actorPosition.x(), actorPosition.y(), waterlevel); + ActorTracer tracer; + tracer.doTrace(physicActor->getCollisionObject(), actorPosition, destinationPosition, mCollisionWorld); + if (tracer.mFraction >= 1.0f) { - 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); - } + waterCollision = true; + physicActor->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 - continue; - Actor* physicActor = foundActor->second; physicActor->setCanWaterWalk(waterCollision); // Slow fall reduces fall speed by a factor of (effect magnitude / 200) From 99bc4f733fac5cda55c1832e17e12627f9a88cea Mon Sep 17 00:00:00 2001 From: Assumeru Date: Wed, 9 Nov 2016 18:03:10 +0100 Subject: [PATCH 3/5] Trace up to waterlevel + halfextent --- apps/openmw/mwphysics/physicssystem.cpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/apps/openmw/mwphysics/physicssystem.cpp b/apps/openmw/mwphysics/physicssystem.cpp index cd4484aa19..d854e0aca4 100644 --- a/apps/openmw/mwphysics/physicssystem.cpp +++ b/apps/openmw/mwphysics/physicssystem.cpp @@ -1329,13 +1329,13 @@ namespace MWPhysics else if (physicActor->getCollisionMode()) { const osg::Vec3f actorPosition = physicActor->getPosition(); - const osg::Vec3f destinationPosition(actorPosition.x(), actorPosition.y(), waterlevel); + const osg::Vec3f destinationPosition(actorPosition.x(), actorPosition.y(), waterlevel + physicActor->getHalfExtents().z()); ActorTracer tracer; tracer.doTrace(physicActor->getCollisionObject(), actorPosition, destinationPosition, mCollisionWorld); if (tracer.mFraction >= 1.0f) { waterCollision = true; - physicActor->setPosition(destinationPosition); + physicActor->setPosition(osg::Vec3f(actorPosition.x(), actorPosition.y(), waterlevel)); } else { From 02d859e2983a61fd9602a223ade21bc460faf3ac Mon Sep 17 00:00:00 2001 From: Bret Curtis Date: Thu, 10 Nov 2016 10:50:43 +0100 Subject: [PATCH 4/5] minor fix to remove Index:, it isn't necessary --- docs/source/openmw-mods/convert_bump_mapped_mods.rst | 2 -- 1 file changed, 2 deletions(-) diff --git a/docs/source/openmw-mods/convert_bump_mapped_mods.rst b/docs/source/openmw-mods/convert_bump_mapped_mods.rst index 520b4403ea..7d695d1d3d 100644 --- a/docs/source/openmw-mods/convert_bump_mapped_mods.rst +++ b/docs/source/openmw-mods/convert_bump_mapped_mods.rst @@ -1,8 +1,6 @@ ==================================== Normal maps from Morrowind to OpenMW ==================================== -Index: ------- - `General introduction to normal map conversion`_ - `Normal Mapping in OpenMW`_ From 05cc258ed3fcd598ee90c608239b8f753262317d Mon Sep 17 00:00:00 2001 From: Assumeru Date: Thu, 10 Nov 2016 15:38:14 +0100 Subject: [PATCH 5/5] Start trace from collision object origin --- apps/openmw/mwphysics/physicssystem.cpp | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/apps/openmw/mwphysics/physicssystem.cpp b/apps/openmw/mwphysics/physicssystem.cpp index d854e0aca4..21867591c0 100644 --- a/apps/openmw/mwphysics/physicssystem.cpp +++ b/apps/openmw/mwphysics/physicssystem.cpp @@ -1328,10 +1328,12 @@ namespace MWPhysics waterCollision = true; else if (physicActor->getCollisionMode()) { + const float halfZ = physicActor->getHalfExtents().z(); const osg::Vec3f actorPosition = physicActor->getPosition(); - const osg::Vec3f destinationPosition(actorPosition.x(), actorPosition.y(), waterlevel + physicActor->getHalfExtents().z()); + const osg::Vec3f startingPosition(actorPosition.x(), actorPosition.y(), actorPosition.z() + halfZ); + const osg::Vec3f destinationPosition(actorPosition.x(), actorPosition.y(), waterlevel + halfZ); ActorTracer tracer; - tracer.doTrace(physicActor->getCollisionObject(), actorPosition, destinationPosition, mCollisionWorld); + tracer.doTrace(physicActor->getCollisionObject(), startingPosition, destinationPosition, mCollisionWorld); if (tracer.mFraction >= 1.0f) { waterCollision = true;