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), mSky (true), mCells (mStore, mEsm),
mActivationDistanceOverride (activationDistanceOverride), mActivationDistanceOverride (activationDistanceOverride),
mFallback(fallbackMap), mTeleportEnabled(true), mLevitationEnabled(true), mFallback(fallbackMap), mTeleportEnabled(true), mLevitationEnabled(true),
mFacedDistance(FLT_MAX), mGodMode(false), mContentFiles (contentFiles), mGodMode(false), mContentFiles (contentFiles),
mGoToJail(false), mGoToJail(false),
mStartCell (startCell), mStartupScript(startupScript) mStartCell (startCell), mStartupScript(startupScript)
{ {
@ -290,7 +290,6 @@ namespace MWWorld
mGodMode = false; mGodMode = false;
mSky = true; mSky = true;
mTeleportEnabled = true; mTeleportEnabled = true;
mFacedDistance = FLT_MAX;
mGlobalVariables.fill (mStore); mGlobalVariables.fill (mStore);
} }
@ -1462,30 +1461,22 @@ namespace MWWorld
updateFacedHandle (); updateFacedHandle ();
} }
void World::updateFacedHandle () void World::getFacedHandle(std::string& facedHandle, float maxDistance)
{ {
float telekinesisRangeBonus = maxDistance += mRendering->getCameraDistance();
mPlayer->getPlayer().getClass().getCreatureStats(mPlayer->getPlayer()).getMagicEffects()
.get(ESM::MagicEffect::Telekinesis).mMagnitude;
telekinesisRangeBonus = feetToGameUnits(telekinesisRangeBonus);
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; std::vector < std::pair < float, std::string > > results;
if (MWBase::Environment::get().getWindowManager()->isGuiMode()) if (MWBase::Environment::get().getWindowManager()->isGuiMode())
{ {
float x, y; float x, y;
MWBase::Environment::get().getWindowManager()->getMousePosition(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()) if (MWBase::Environment::get().getWindowManager()->isConsoleMode())
results = mPhysics->getFacedHandles(x, y, getMaxActivationDistance ()*50); results = mPhysics->getFacedHandles(x, y, getMaxActivationDistance ()*50);
} }
else else
{ {
results = mPhysics->getFacedHandles(activationDistance); results = mPhysics->getFacedHandles(maxDistance);
} }
// ignore the player and other things we're not interested in // ignore the player and other things we're not interested in
@ -1508,15 +1499,21 @@ namespace MWWorld
if (results.empty() if (results.empty()
|| results.front().second.find("HeightField") != std::string::npos) // Blocked by terrain || results.front().second.find("HeightField") != std::string::npos) // Blocked by terrain
{ facedHandle = "";
mFacedHandle = "";
mFacedDistance = FLT_MAX;
}
else else
{ facedHandle = results.front().second;
mFacedHandle = results.front().second; }
mFacedDistance = results.front().first;
} 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 bool World::isCellExterior() const
@ -2344,8 +2341,49 @@ namespace MWWorld
{ {
MWMechanics::CreatureStats& stats = actor.getClass().getCreatureStats(actor); MWMechanics::CreatureStats& stats = actor.getClass().getCreatureStats(actor);
// TODO: this only works for the player // Get the target to use for "on touch" effects
MWWorld::Ptr target = getFacedObject(); 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(); std::string selectedSpell = stats.getSpells().getSelectedSpell();

@ -92,7 +92,6 @@ namespace MWWorld
int mActivationDistanceOverride; int mActivationDistanceOverride;
std::string mFacedHandle; std::string mFacedHandle;
float mFacedDistance;
std::string mStartupScript; std::string mStartupScript;
@ -114,6 +113,7 @@ namespace MWWorld
void updateWindowManager (); void updateWindowManager ();
void performUpdateSceneQueries (); void performUpdateSceneQueries ();
void updateFacedHandle (); void updateFacedHandle ();
void getFacedHandle(std::string& facedHandle, float maxDistance);
float getMaxActivationDistance (); float getMaxActivationDistance ();
float getNpcActivationDistance (); 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 = ""; std::string name = "";
float d = -1; float d = -1;
@ -801,7 +801,7 @@ namespace Physic
return std::make_pair(false, 1); 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; MyRayResultCallback resultCallback1;
resultCallback1.m_collisionFilterGroup = 0xff; 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). * 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) * 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); bool ignoreHeightMap = false, Ogre::Vector3* normal = NULL);
/** /**
* Return all objects hit by a ray. * 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); std::pair<bool, float> sphereCast (float radius, btVector3& from, btVector3& to);
///< @return (hit, relative distance) ///< @return (hit, relative distance)

Loading…
Cancel
Save