Improve getLOS (use eye level). Also, don't crash when used with non-actors.

This commit is contained in:
scrawl 2014-06-19 04:53:25 +02:00
parent 185ff279a3
commit 4648524df4
4 changed files with 22 additions and 11 deletions

View file

@ -407,7 +407,7 @@ namespace MWBase
virtual void getItemsOwnedBy (const MWWorld::Ptr& npc, std::vector<MWWorld::Ptr>& out) = 0;
///< get all items in active cells owned by this Npc
virtual bool getLOS(const MWWorld::Ptr& npc,const MWWorld::Ptr& targetNpc) = 0;
virtual bool getLOS(const MWWorld::Ptr& actor,const MWWorld::Ptr& targetActor) = 0;
///< get Line of Sight (morrowind stupid implementation)
virtual float getDistToNearestRayHit(const Ogre::Vector3& from, const Ogre::Vector3& dir, float maxDist) = 0;

View file

@ -371,6 +371,12 @@ namespace MWScript
MWWorld::Ptr actor = MWBase::Environment::get().getWorld()->getPtr(actorID, true);
if(!actor.getClass().isActor() || !observer.getClass().isActor())
{
runtime.push(0);
return;
}
Interpreter::Type_Integer value =
MWBase::Environment::get().getWorld()->getLOS(observer, actor) &&
MWBase::Environment::get().getMechanicsManager()->awarenessCheck(actor, observer);
@ -392,9 +398,10 @@ namespace MWScript
std::string actorID = runtime.getStringLiteral (runtime[0].mInteger);
runtime.pop();
MWWorld::Ptr dest = MWBase::Environment::get().getWorld()->getPtr(actorID,true);
bool value = false;
if(dest != MWWorld::Ptr() )
if(dest != MWWorld::Ptr() && source.getClass().isActor() && dest.getClass().isActor())
{
value = MWBase::Environment::get().getWorld()->getLOS(source,dest);
}

View file

@ -2031,20 +2031,24 @@ namespace MWWorld
}
}
bool World::getLOS(const MWWorld::Ptr& npc,const MWWorld::Ptr& targetNpc)
bool World::getLOS(const MWWorld::Ptr& actor,const MWWorld::Ptr& targetActor)
{
if (!targetNpc.getRefData().isEnabled() || !npc.getRefData().isEnabled())
if (!targetActor.getRefData().isEnabled() || !actor.getRefData().isEnabled())
return false; // cannot get LOS unless both NPC's are enabled
Ogre::Vector3 halfExt1 = mPhysEngine->getCharacter(npc.getRefData().getHandle())->getHalfExtents();
const float* pos1 = npc.getRefData().getPosition().pos;
Ogre::Vector3 halfExt2 = mPhysEngine->getCharacter(targetNpc.getRefData().getHandle())->getHalfExtents();
const float* pos2 = targetNpc.getRefData().getPosition().pos;
if (!targetActor.getRefData().getBaseNode() || !targetActor.getRefData().getBaseNode())
return false; // not in active cell
btVector3 from(pos1[0],pos1[1],pos1[2]+halfExt1.z);
btVector3 to(pos2[0],pos2[1],pos2[2]+halfExt2.z);
Ogre::Vector3 halfExt1 = mPhysEngine->getCharacter(actor.getRefData().getHandle())->getHalfExtents();
const float* pos1 = actor.getRefData().getPosition().pos;
Ogre::Vector3 halfExt2 = mPhysEngine->getCharacter(targetActor.getRefData().getHandle())->getHalfExtents();
const float* pos2 = targetActor.getRefData().getPosition().pos;
btVector3 from(pos1[0],pos1[1],pos1[2]+halfExt1.z*2*0.9); // eye level
btVector3 to(pos2[0],pos2[1],pos2[2]+halfExt2.z*2*0.9);
std::pair<std::string, float> result = mPhysEngine->rayTest(from, to,false);
if(result.first == "") return true;
return false;
}

View file

@ -482,7 +482,7 @@ namespace MWWorld
virtual void getItemsOwnedBy (const MWWorld::Ptr& npc, std::vector<MWWorld::Ptr>& out);
///< get all items in active cells owned by this Npc
virtual bool getLOS(const MWWorld::Ptr& npc,const MWWorld::Ptr& targetNpc);
virtual bool getLOS(const MWWorld::Ptr& actor,const MWWorld::Ptr& targetActor);
///< get Line of Sight (morrowind stupid implementation)
virtual float getDistToNearestRayHit(const Ogre::Vector3& from, const Ogre::Vector3& dir, float maxDist);