Determine target for On Touch effects for non-player actors

pull/191/head
scrawl 11 years ago
parent fdc6dd6985
commit 8c81e22f3e

@ -148,7 +148,7 @@ namespace MWWorld
mSky (true), mCells (mStore, mEsm),
mActivationDistanceOverride (activationDistanceOverride),
mFallback(fallbackMap), mTeleportEnabled(true), mLevitationEnabled(true),
mFacedDistance(FLT_MAX), mGodMode(false), mContentFiles (contentFiles),
mGodMode(false), mContentFiles (contentFiles),
mGoToJail(false),
mStartCell (startCell), mStartupScript(startupScript)
{
@ -290,7 +290,6 @@ namespace MWWorld
mGodMode = false;
mSky = true;
mTeleportEnabled = true;
mFacedDistance = FLT_MAX;
mGlobalVariables.fill (mStore);
}
@ -1462,30 +1461,22 @@ namespace MWWorld
updateFacedHandle ();
}
void World::updateFacedHandle ()
void World::getFacedHandle(std::string& facedHandle, float maxDistance)
{
float telekinesisRangeBonus =
mPlayer->getPlayer().getClass().getCreatureStats(mPlayer->getPlayer()).getMagicEffects()
.get(ESM::MagicEffect::Telekinesis).mMagnitude;
telekinesisRangeBonus = feetToGameUnits(telekinesisRangeBonus);
maxDistance += mRendering->getCameraDistance();
float activationDistance = getMaxActivationDistance() + telekinesisRangeBonus;
activationDistance += mRendering->getCameraDistance();
// send new query
// figure out which object we want to test against
std::vector < std::pair < float, std::string > > results;
if (MWBase::Environment::get().getWindowManager()->isGuiMode())
{
float x, y;
MWBase::Environment::get().getWindowManager()->getMousePosition(x, y);
results = mPhysics->getFacedHandles(x, y, activationDistance);
results = mPhysics->getFacedHandles(x, y, maxDistance);
if (MWBase::Environment::get().getWindowManager()->isConsoleMode())
results = mPhysics->getFacedHandles(x, y, getMaxActivationDistance ()*50);
}
else
{
results = mPhysics->getFacedHandles(activationDistance);
results = mPhysics->getFacedHandles(maxDistance);
}
// ignore the player and other things we're not interested in
@ -1508,15 +1499,21 @@ namespace MWWorld
if (results.empty()
|| results.front().second.find("HeightField") != std::string::npos) // Blocked by terrain
{
mFacedHandle = "";
mFacedDistance = FLT_MAX;
}
facedHandle = "";
else
{
mFacedHandle = results.front().second;
mFacedDistance = results.front().first;
}
facedHandle = results.front().second;
}
void World::updateFacedHandle ()
{
float telekinesisRangeBonus =
mPlayer->getPlayer().getClass().getCreatureStats(mPlayer->getPlayer()).getMagicEffects()
.get(ESM::MagicEffect::Telekinesis).mMagnitude;
telekinesisRangeBonus = feetToGameUnits(telekinesisRangeBonus);
float activationDistance = getMaxActivationDistance() + telekinesisRangeBonus;
getFacedHandle(mFacedHandle, activationDistance);
}
bool World::isCellExterior() const
@ -2344,8 +2341,49 @@ namespace MWWorld
{
MWMechanics::CreatureStats& stats = actor.getClass().getCreatureStats(actor);
// TODO: this only works for the player
MWWorld::Ptr target = getFacedObject();
// Get the target to use for "on touch" effects
MWWorld::Ptr target;
float distance = 192.f; // ??
if (actor == getPlayerPtr())
{
// For the player, use camera to aim
std::string facedHandle;
getFacedHandle(facedHandle, distance);
if (!facedHandle.empty())
target = getPtrViaHandle(facedHandle);
}
else
{
// For NPCs use facing direction from Head node
Ogre::Vector3 origin(actor.getRefData().getPosition().pos);
MWRender::Animation *anim = mRendering->getAnimation(actor);
if(anim != NULL)
{
Ogre::Node *node = anim->getNode("Head");
if (node == NULL)
node = anim->getNode("Bip01 Head");
if(node != NULL)
origin += node->_getDerivedPosition();
}
Ogre::Quaternion orient;
orient = Ogre::Quaternion(Ogre::Radian(actor.getRefData().getPosition().rot[2]), Ogre::Vector3::NEGATIVE_UNIT_Z) *
Ogre::Quaternion(Ogre::Radian(actor.getRefData().getPosition().rot[0]), Ogre::Vector3::NEGATIVE_UNIT_X);
Ogre::Vector3 direction = orient.yAxis();
Ogre::Vector3 dest = origin + direction * distance;
std::vector<std::pair<float, std::string> > collisions = mPhysEngine->rayTest2(btVector3(origin.x, origin.y, origin.z), btVector3(dest.x, dest.y, dest.z));
for (std::vector<std::pair<float, std::string> >::iterator cIt = collisions.begin(); cIt != collisions.end(); ++cIt)
{
MWWorld::Ptr collided = getPtrViaHandle(cIt->second);
if (collided != actor)
{
target = collided;
break;
}
}
}
std::string selectedSpell = stats.getSpells().getSelectedSpell();

@ -92,7 +92,6 @@ namespace MWWorld
int mActivationDistanceOverride;
std::string mFacedHandle;
float mFacedDistance;
std::string mStartupScript;
@ -114,6 +113,7 @@ namespace MWWorld
void updateWindowManager ();
void performUpdateSceneQueries ();
void updateFacedHandle ();
void getFacedHandle(std::string& facedHandle, float maxDistance);
float getMaxActivationDistance ();
float getNpcActivationDistance ();

@ -737,7 +737,7 @@ namespace Physic
{
}
std::pair<std::string,float> PhysicEngine::rayTest(btVector3& from,btVector3& to,bool raycastingObjectOnly,bool ignoreHeightMap, Ogre::Vector3* normal)
std::pair<std::string,float> PhysicEngine::rayTest(const btVector3 &from, const btVector3 &to, bool raycastingObjectOnly, bool ignoreHeightMap, Ogre::Vector3* normal)
{
std::string name = "";
float d = -1;
@ -801,7 +801,7 @@ namespace Physic
return std::make_pair(false, 1);
}
std::vector< std::pair<float, std::string> > PhysicEngine::rayTest2(btVector3& from, btVector3& to)
std::vector< std::pair<float, std::string> > PhysicEngine::rayTest2(const btVector3& from, const btVector3& to)
{
MyRayResultCallback resultCallback1;
resultCallback1.m_collisionFilterGroup = 0xff;

@ -302,13 +302,13 @@ namespace Physic
* Return the closest object hit by a ray. If there are no objects, it will return ("",-1).
* If \a normal is non-NULL, the hit normal will be written there (if there is a hit)
*/
std::pair<std::string,float> rayTest(btVector3& from,btVector3& to,bool raycastingObjectOnly = true,
std::pair<std::string,float> rayTest(const btVector3& from,const btVector3& to,bool raycastingObjectOnly = true,
bool ignoreHeightMap = false, Ogre::Vector3* normal = NULL);
/**
* Return all objects hit by a ray.
*/
std::vector< std::pair<float, std::string> > rayTest2(btVector3& from, btVector3& to);
std::vector< std::pair<float, std::string> > rayTest2(const btVector3 &from, const btVector3 &to);
std::pair<bool, float> sphereCast (float radius, btVector3& from, btVector3& to);
///< @return (hit, relative distance)

Loading…
Cancel
Save