Commit 6195062d authored by Chris Robinson's avatar Chris Robinson

Try to figure out what gets hit

This isn't the greatest. The distance multiplier is a guess, and a sphere cast
may be better.
parent b3a057d6
......@@ -218,6 +218,10 @@ namespace MWBase
virtual MWWorld::Ptr getFacedObject() = 0;
///< Return pointer to the object the player is looking at, if it is within activation range
/// Returns a pointer to the object the provided object is facing (if within the
/// specified distance). This will attempt to use the "Bip01 Head" node as a basis.
virtual MWWorld::Ptr getFacedObject(const MWWorld::Ptr &ptr, float distance) = 0;
virtual void adjustPosition (const MWWorld::Ptr& ptr) = 0;
///< Adjust position after load to be on ground. Must be called after model load.
......
......@@ -305,14 +305,19 @@ namespace MWClass
void Npc::hit(const MWWorld::Ptr& ptr, int type) const
{
MWBase::World *world = MWBase::Environment::get().getWorld();
const MWWorld::Store<ESM::GameSetting> &gmst = world->getStore().get<ESM::GameSetting>();
// Get the weapon used (if hand-to-hand, weapon = inv.end())
MWWorld::InventoryStore &inv = getInventoryStore(ptr);
MWWorld::ContainerStoreIterator weapon = inv.getSlot(MWWorld::InventoryStore::Slot_CarriedRight);
if(weapon != inv.end() && weapon->getTypeName() != typeid(ESM::Weapon).name())
weapon = inv.end();
// FIXME: Detect what was hit
MWWorld::Ptr victim;
float dist = 100.0f * ((weapon != inv.end()) ?
weapon->get<ESM::Weapon>()->mBase->mData.mReach :
gmst.find("fHandToHandReach")->getFloat());
MWWorld::Ptr victim = world->getFacedObject(ptr, dist);
if(victim.isEmpty()) // Didn't hit anything
return;
......@@ -362,8 +367,6 @@ namespace MWClass
//damage *= weapon_current_health / weapon_max_health;
if(!othercls.hasDetected(victim, ptr))
{
const MWBase::World *world = MWBase::Environment::get().getWorld();
const MWWorld::Store<ESM::GameSetting> &gmst = world->getStore().get<ESM::GameSetting>();
damage *= gmst.find("fCombatCriticalStrikeMult")->getFloat();
MWBase::Environment::get().getWindowManager()->messageBox("#{sTargetCriticalStrike}");
}
......
......@@ -304,6 +304,19 @@ namespace MWWorld
return results;
}
std::pair<std::string,float> PhysicsSystem::getFacedHandle(const Ogre::Vector3 &origin_, const Ogre::Quaternion &orient_, float queryDistance)
{
Ogre::Vector3 dest_ = origin_ + orient_.yAxis()*queryDistance;
btVector3 origin(origin_.x, origin_.y, origin_.z);
btVector3 dest(dest_.x, dest_.y, dest_.z);
std::pair<std::string,float> result = mEngine->rayTest(origin, dest);
result.second *= queryDistance;
return result;
}
void PhysicsSystem::setCurrentWater(bool hasWater, int waterHeight)
{
// TODO: store and use
......
......@@ -55,6 +55,9 @@ namespace MWWorld
Ogre::Vector3 traceDown(const MWWorld::Ptr &ptr);
std::pair<float, std::string> getFacedHandle (MWWorld::World& world, float queryDistance);
std::pair<std::string,float> getFacedHandle(const Ogre::Vector3 &origin,
const Ogre::Quaternion &orientation,
float queryDistance);
std::vector < std::pair <float, std::string> > getFacedHandles (float queryDistance);
std::vector < std::pair <float, std::string> > getFacedHandles (float mouseX, float mouseY, float queryDistance);
......
......@@ -18,6 +18,7 @@
#include "../mwmechanics/movement.hpp"
#include "../mwrender/sky.hpp"
#include "../mwrender/animation.hpp"
#include "../mwclass/door.hpp"
......@@ -776,6 +777,28 @@ namespace MWWorld
return object;
}
MWWorld::Ptr World::getFacedObject(const MWWorld::Ptr &ptr, float distance)
{
const ESM::Position &posdata = ptr.getRefData().getPosition();
Ogre::Vector3 pos(posdata.pos);
Ogre::Quaternion rot = Ogre::Quaternion(Ogre::Radian(posdata.rot[2]), Ogre::Vector3::NEGATIVE_UNIT_Z) *
Ogre::Quaternion(Ogre::Radian(posdata.rot[0]), Ogre::Vector3::UNIT_X);
MWRender::Animation *anim = mRendering->getAnimation(ptr);
if(anim != NULL)
{
Ogre::Node *node = anim->getNode("Head");
if(node != NULL)
pos += node->_getDerivedPosition();
}
std::pair<std::string,float> result = mPhysics->getFacedHandle(pos, rot, distance);
if(result.first.empty())
return MWWorld::Ptr();
return searchPtrViaHandle(result.first);
}
void World::deleteObject (const Ptr& ptr)
{
if (ptr.getRefData().getCount()>0)
......
......@@ -252,6 +252,10 @@ namespace MWWorld
virtual MWWorld::Ptr getFacedObject();
///< Return pointer to the object the player is looking at, if it is within activation range
/// Returns a pointer to the object the provided object is facing (if within the
/// specified distance). This will attempt to use the "Bip01 Head" node as a basis.
virtual MWWorld::Ptr getFacedObject(const MWWorld::Ptr &ptr, float distance);
virtual void deleteObject (const Ptr& ptr);
virtual void moveObject (const Ptr& ptr, float x, float y, float z);
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment