1
0
Fork 1
mirror of https://github.com/TES3MP/openmw-tes3mp.git synced 2025-02-01 05:45:33 +00:00

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.
This commit is contained in:
Chris Robinson 2013-07-25 12:58:43 -07:00
parent b3a057d679
commit 6195062d72
6 changed files with 54 additions and 4 deletions

View file

@ -218,6 +218,10 @@ namespace MWBase
virtual MWWorld::Ptr getFacedObject() = 0; virtual MWWorld::Ptr getFacedObject() = 0;
///< Return pointer to the object the player is looking at, if it is within activation range ///< 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; virtual void adjustPosition (const MWWorld::Ptr& ptr) = 0;
///< Adjust position after load to be on ground. Must be called after model load. ///< Adjust position after load to be on ground. Must be called after model load.

View file

@ -305,14 +305,19 @@ namespace MWClass
void Npc::hit(const MWWorld::Ptr& ptr, int type) const 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()) // Get the weapon used (if hand-to-hand, weapon = inv.end())
MWWorld::InventoryStore &inv = getInventoryStore(ptr); MWWorld::InventoryStore &inv = getInventoryStore(ptr);
MWWorld::ContainerStoreIterator weapon = inv.getSlot(MWWorld::InventoryStore::Slot_CarriedRight); MWWorld::ContainerStoreIterator weapon = inv.getSlot(MWWorld::InventoryStore::Slot_CarriedRight);
if(weapon != inv.end() && weapon->getTypeName() != typeid(ESM::Weapon).name()) if(weapon != inv.end() && weapon->getTypeName() != typeid(ESM::Weapon).name())
weapon = inv.end(); weapon = inv.end();
// FIXME: Detect what was hit float dist = 100.0f * ((weapon != inv.end()) ?
MWWorld::Ptr victim; 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 if(victim.isEmpty()) // Didn't hit anything
return; return;
@ -362,8 +367,6 @@ namespace MWClass
//damage *= weapon_current_health / weapon_max_health; //damage *= weapon_current_health / weapon_max_health;
if(!othercls.hasDetected(victim, ptr)) 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(); damage *= gmst.find("fCombatCriticalStrikeMult")->getFloat();
MWBase::Environment::get().getWindowManager()->messageBox("#{sTargetCriticalStrike}"); MWBase::Environment::get().getWindowManager()->messageBox("#{sTargetCriticalStrike}");
} }

View file

@ -304,6 +304,19 @@ namespace MWWorld
return results; 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) void PhysicsSystem::setCurrentWater(bool hasWater, int waterHeight)
{ {
// TODO: store and use // TODO: store and use

View file

@ -55,6 +55,9 @@ namespace MWWorld
Ogre::Vector3 traceDown(const MWWorld::Ptr &ptr); Ogre::Vector3 traceDown(const MWWorld::Ptr &ptr);
std::pair<float, std::string> getFacedHandle (MWWorld::World& world, float queryDistance); 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 queryDistance);
std::vector < std::pair <float, std::string> > getFacedHandles (float mouseX, float mouseY, float queryDistance); std::vector < std::pair <float, std::string> > getFacedHandles (float mouseX, float mouseY, float queryDistance);

View file

@ -18,6 +18,7 @@
#include "../mwmechanics/movement.hpp" #include "../mwmechanics/movement.hpp"
#include "../mwrender/sky.hpp" #include "../mwrender/sky.hpp"
#include "../mwrender/animation.hpp"
#include "../mwclass/door.hpp" #include "../mwclass/door.hpp"
@ -776,6 +777,28 @@ namespace MWWorld
return object; 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) void World::deleteObject (const Ptr& ptr)
{ {
if (ptr.getRefData().getCount()>0) if (ptr.getRefData().getCount()>0)

View file

@ -252,6 +252,10 @@ namespace MWWorld
virtual MWWorld::Ptr getFacedObject(); virtual MWWorld::Ptr getFacedObject();
///< Return pointer to the object the player is looking at, if it is within activation range ///< 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 deleteObject (const Ptr& ptr);
virtual void moveObject (const Ptr& ptr, float x, float y, float z); virtual void moveObject (const Ptr& ptr, float x, float y, float z);