From 10eb6ec75f9eec6df9c6fee9b40f4b99732b1dd4 Mon Sep 17 00:00:00 2001 From: Andrei Kortunov Date: Mon, 31 Jul 2017 19:28:02 +0400 Subject: [PATCH] AI: Check angle between actor and door --- apps/openmw/mwbase/world.hpp | 4 --- apps/openmw/mwmechanics/obstacle.cpp | 45 ++++++++++++++++++---------- apps/openmw/mwworld/worldimp.cpp | 10 ++----- apps/openmw/mwworld/worldimp.hpp | 3 -- 4 files changed, 32 insertions(+), 30 deletions(-) diff --git a/apps/openmw/mwbase/world.hpp b/apps/openmw/mwbase/world.hpp index ce6cf38eb..86d26d3a7 100644 --- a/apps/openmw/mwbase/world.hpp +++ b/apps/openmw/mwbase/world.hpp @@ -10,7 +10,6 @@ #include "../mwworld/ptr.hpp" #include "../mwrender/rendermode.hpp" -#include "../mwphysics/physicssystem.hpp" namespace osg { @@ -300,9 +299,6 @@ namespace MWBase virtual bool castRay (float x1, float y1, float z1, float x2, float y2, float z2) = 0; ///< cast a Ray and return true if there is an object in the ray path. - virtual MWPhysics::PhysicsSystem::RayResult castRayTest (float x1, float y1, float z1, float x2, float y2, float z2) = 0; - ///< cast a rendering ray and return ray result. - virtual bool toggleCollisionMode() = 0; ///< Toggle collision mode for player. If disabled player object should ignore /// collisions and gravity. diff --git a/apps/openmw/mwmechanics/obstacle.cpp b/apps/openmw/mwmechanics/obstacle.cpp index 8e932f351..3c6f14bfd 100644 --- a/apps/openmw/mwmechanics/obstacle.cpp +++ b/apps/openmw/mwmechanics/obstacle.cpp @@ -1,11 +1,9 @@ #include "obstacle.hpp" -#include - #include +#include #include "../mwbase/world.hpp" -#include "../mwbase/environment.hpp" #include "../mwworld/class.hpp" #include "../mwworld/cellstore.hpp" @@ -36,24 +34,39 @@ namespace MWMechanics MWWorld::Ptr getNearbyDoor(const MWWorld::Ptr& actor, float minDist) { - osg::Vec3f origin = MWBase::Environment::get().getWorld()->getActorHeadTransform(actor).getTrans(); - - osg::Quat orient = osg::Quat(actor.getRefData().getPosition().rot[0], osg::Vec3f(-1,0,0)) - * osg::Quat(actor.getRefData().getPosition().rot[2], osg::Vec3f(0,0,-1)); - - osg::Vec3f direction = orient * osg::Vec3f(0,1,0); - osg::Vec3f dest = origin + direction * minDist; + MWWorld::CellStore *cell = actor.getCell(); + // Check all the doors in this cell + const MWWorld::CellRefList& doors = cell->getReadOnlyDoors(); + const MWWorld::CellRefList::List& refList = doors.mList; + MWWorld::CellRefList::List::const_iterator it = refList.begin(); osg::Vec3f pos(actor.getRefData().getPosition().asVec3()); - MWPhysics::PhysicsSystem::RayResult result = MWBase::Environment::get().getWorld()->castRayTest(pos.x(), pos.y(), pos.z(), dest.x(), dest.y(), dest.z()); + pos.z() = 0; - if (!result.mHit || result.mHitObject.isEmpty()) - return MWWorld::Ptr(); // none found + osg::Vec3f actorDir = (actor.getRefData().getBaseNode()->getAttitude() * osg::Vec3f(0,1,0)); - if (result.mHitObject.getClass().getTypeName() == typeid(ESM::Door).name() && !result.mHitObject.getCellRef().getTeleport()) - return result.mHitObject; + for (; it != refList.end(); ++it) + { + const MWWorld::LiveCellRef& ref = *it; - return MWWorld::Ptr(); + osg::Vec3f doorPos(ref.mData.getPosition().asVec3()); + doorPos.z() = 0; + + float angle = std::acos(actorDir * (doorPos - pos) / (actorDir.length() * (doorPos - pos).length())); + + // Allow 60 degrees angle between actor and door + if (angle < -osg::PI / 3 || angle > osg::PI / 3) + continue; + + // Door is not close enough + if ((pos - doorPos).length2() > minDist*minDist) + continue; + + // FIXME cast + return MWWorld::Ptr(&const_cast &>(ref), actor.getCell()); // found, stop searching + } + + return MWWorld::Ptr(); // none found } ObstacleCheck::ObstacleCheck(): diff --git a/apps/openmw/mwworld/worldimp.cpp b/apps/openmw/mwworld/worldimp.cpp index 86943a7e7..91a3c4a8f 100644 --- a/apps/openmw/mwworld/worldimp.cpp +++ b/apps/openmw/mwworld/worldimp.cpp @@ -1451,16 +1451,12 @@ namespace MWWorld } bool World::castRay (float x1, float y1, float z1, float x2, float y2, float z2) - { - MWPhysics::PhysicsSystem::RayResult result = castRayTest(x1, y1, z1, x2, y2, z2); - return result.mHit; - } - - MWPhysics::PhysicsSystem::RayResult World::castRayTest (float x1, float y1, float z1, float x2, float y2, float z2) { osg::Vec3f a(x1,y1,z1); osg::Vec3f b(x2,y2,z2); - return mPhysics->castRay(a, b, MWWorld::Ptr(), std::vector(), MWPhysics::CollisionType_World|MWPhysics::CollisionType_Door); + + MWPhysics::PhysicsSystem::RayResult result = mPhysics->castRay(a, b, MWWorld::Ptr(), std::vector(), MWPhysics::CollisionType_World|MWPhysics::CollisionType_Door); + return result.mHit; } void World::processDoors(float duration) diff --git a/apps/openmw/mwworld/worldimp.hpp b/apps/openmw/mwworld/worldimp.hpp index 951a837da..ce6e27672 100644 --- a/apps/openmw/mwworld/worldimp.hpp +++ b/apps/openmw/mwworld/worldimp.hpp @@ -407,9 +407,6 @@ namespace MWWorld virtual bool castRay (float x1, float y1, float z1, float x2, float y2, float z2); ///< cast a Ray and return true if there is an object in the ray path. - virtual MWPhysics::PhysicsSystem::RayResult castRayTest (float x1, float y1, float z1, float x2, float y2, float z2); - ///< cast a rendering ray and return ray result. - virtual bool toggleCollisionMode(); ///< Toggle collision mode for player. If disabled player object should ignore /// collisions and gravity.