mirror of
https://github.com/TES3MP/openmw-tes3mp.git
synced 2025-03-03 13:19:40 +00:00
Determine target for On Touch effects for non-player actors
This commit is contained in:
parent
fdc6dd6985
commit
8c81e22f3e
4 changed files with 67 additions and 29 deletions
|
@ -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…
Reference in a new issue