diff --git a/apps/openmw/mwrender/renderingmanager.cpp b/apps/openmw/mwrender/renderingmanager.cpp index ea3e7b7ee..c9be3bdcb 100644 --- a/apps/openmw/mwrender/renderingmanager.cpp +++ b/apps/openmw/mwrender/renderingmanager.cpp @@ -738,7 +738,9 @@ namespace MWRender mViewer->getCamera()->accept(*createIntersectionVisitor(intersector, ignorePlayer, ignoreActors)); - return getIntersectionResult(intersector); + RayResult result = getIntersectionResult(intersector); + result.mDistanceToFirstIntersection = maxDistance * intersector->getFirstIntersection().ratio; + return result; } void RenderingManager::updatePtr(const MWWorld::Ptr &old, const MWWorld::Ptr &updated) diff --git a/apps/openmw/mwrender/renderingmanager.hpp b/apps/openmw/mwrender/renderingmanager.hpp index ebe75d39b..3345d121f 100644 --- a/apps/openmw/mwrender/renderingmanager.hpp +++ b/apps/openmw/mwrender/renderingmanager.hpp @@ -120,6 +120,7 @@ namespace MWRender osg::Vec3f mHitNormalWorld; osg::Vec3f mHitPointWorld; MWWorld::Ptr mHitObject; + float mDistanceToFirstIntersection; }; RayResult castRay(const osg::Vec3f& origin, const osg::Vec3f& dest, bool ignorePlayer, bool ignoreActors=false); diff --git a/apps/openmw/mwworld/worldimp.cpp b/apps/openmw/mwworld/worldimp.cpp index 6915a389c..5b156cba0 100644 --- a/apps/openmw/mwworld/worldimp.cpp +++ b/apps/openmw/mwworld/worldimp.cpp @@ -1,4 +1,5 @@ #include "worldimp.hpp" +#include #include #include @@ -1023,15 +1024,16 @@ namespace MWWorld telekinesisRangeBonus = feetToGameUnits(telekinesisRangeBonus); float activationDistance = getMaxActivationDistance() + telekinesisRangeBonus; + float distanceToObject; - facedObject = getFacedObject(activationDistance); + facedObject = getFacedObject(activationDistance, distanceToObject, true); // Not allowing telekinesis on actors, on doors that teleport to other cells, or on activators // Original engine doesn't allow telekinesis on books or lights, either - if (!facedObject.isEmpty() && !facedObject.getClass().isActor() && !facedObject.getCellRef().getTeleport() && facedObject.getClass().getTypeName() != "struct ESM::Activator") - return facedObject; - else - facedObject = getFacedObject(getMaxActivationDistance()); + if (!facedObject.isEmpty() && (facedObject.getClass().isActor() + || facedObject.getCellRef().getTeleport() || facedObject.getClass().getTypeName() == "struct ESM::Activator") + && (distanceToObject > getMaxActivationDistance())) + return 0; } return facedObject; @@ -1731,6 +1733,31 @@ namespace MWWorld return mRendering->castCameraToViewportRay(0.5f, 0.5f, maxDistance, ignorePlayer).mHitObject; } } + + MWWorld::Ptr World::getFacedObject(float maxDistance, float& distance, bool ignorePlayer) + { + maxDistance += mRendering->getCameraDistance(); + MWWorld::Ptr facedObject; + + if (MWBase::Environment::get().getWindowManager()->isGuiMode()) + { + float x, y; + MWBase::Environment::get().getWindowManager()->getMousePosition(x, y); + MWRender::RenderingManager::RayResult rayToObject = mRendering->castCameraToViewportRay(x, y, maxDistance, ignorePlayer); + facedObject = rayToObject.mHitObject; + if (!facedObject.isEmpty()) + distance = rayToObject.mDistanceToFirstIntersection; + return facedObject; + } + else + { + MWRender::RenderingManager::RayResult rayToObject = mRendering->castCameraToViewportRay(0.5f, 0.5f, maxDistance, ignorePlayer); + facedObject = rayToObject.mHitObject; + if (!facedObject.isEmpty()) + distance = rayToObject.mDistanceToFirstIntersection; + return facedObject; + } + } bool World::isCellExterior() const { diff --git a/apps/openmw/mwworld/worldimp.hpp b/apps/openmw/mwworld/worldimp.hpp index 7af632d23..d5c3c7815 100644 --- a/apps/openmw/mwworld/worldimp.hpp +++ b/apps/openmw/mwworld/worldimp.hpp @@ -127,7 +127,13 @@ namespace MWWorld void updateSoundListener(); void updateWindowManager (); void updatePlayer(bool paused); + + /// Return faced object MWWorld::Ptr getFacedObject(float maxDistance, bool ignorePlayer=true); + + /// Return faced object and distance from player to it + MWWorld::Ptr getFacedObject(float maxDistance, float& distanceToObject, bool ignorePlayer=true); + public: // FIXME void removeContainerScripts(const Ptr& reference); private: