mirror of
https://github.com/OpenMW/openmw.git
synced 2025-01-21 09:23:53 +00:00
AiCombat distance check takes into account collision box (Fixes #1699)
This commit is contained in:
parent
0bdfd1b0d7
commit
3453353091
6 changed files with 52 additions and 1 deletions
|
@ -543,6 +543,9 @@ namespace MWBase
|
|||
/// Return a vector aiming the actor's weapon towards a target.
|
||||
/// @note The length of the vector is the distance between actor and target.
|
||||
virtual osg::Vec3f aimToTarget(const MWWorld::Ptr& actor, const MWWorld::Ptr& target) = 0;
|
||||
|
||||
/// Return the distance between actor's weapon and target's collision box.
|
||||
virtual float getHitDistance(const MWWorld::Ptr& actor, const MWWorld::Ptr& target) = 0;
|
||||
};
|
||||
}
|
||||
|
||||
|
|
|
@ -347,7 +347,7 @@ namespace MWMechanics
|
|||
osg::Vec3f vTargetPos(target.getRefData().getPosition().asVec3());
|
||||
|
||||
osg::Vec3f vAimDir = MWBase::Environment::get().getWorld()->aimToTarget(actor, target);
|
||||
float distToTarget = (vTargetPos - vActorPos).length();
|
||||
float distToTarget = MWBase::Environment::get().getWorld()->getHitDistance(actor, target);
|
||||
|
||||
osg::Vec3f& lastActorPos = storage.mLastActorPos;
|
||||
bool& followTarget = storage.mFollowTarget;
|
||||
|
|
|
@ -218,6 +218,7 @@ namespace MWPhysics
|
|||
resultCallback1.m_collisionFilterMask = CollisionType_World|CollisionType_HeightMap;
|
||||
|
||||
collisionWorld->rayTest(from, to, resultCallback1);
|
||||
|
||||
if (resultCallback1.hasHit() &&
|
||||
( (toOsg(resultCallback1.m_hitPointWorld) - tracer.mEndPos).length() > 30
|
||||
|| getSlope(tracer.mPlaneNormal) > sMaxSlope))
|
||||
|
@ -748,6 +749,36 @@ namespace MWPhysics
|
|||
return std::make_pair(MWWorld::Ptr(), osg::Vec3f());
|
||||
}
|
||||
|
||||
float PhysicsSystem::getHitDistance(const osg::Vec3f &point, const MWWorld::Ptr &target) const
|
||||
{
|
||||
btCollisionObject* targetCollisionObj = NULL;
|
||||
const Actor* actor = getActor(target);
|
||||
if (actor)
|
||||
targetCollisionObj = actor->getCollisionObject();
|
||||
if (!targetCollisionObj)
|
||||
return 0.f;
|
||||
|
||||
btTransform rayFrom;
|
||||
rayFrom.setIdentity();
|
||||
rayFrom.setOrigin(toBullet(point));
|
||||
|
||||
// target the collision object's world origin, this should be the center of the collision object
|
||||
btTransform rayTo;
|
||||
rayTo.setIdentity();
|
||||
rayTo.setOrigin(targetCollisionObj->getWorldTransform().getOrigin());
|
||||
|
||||
btCollisionWorld::ClosestRayResultCallback cb(rayFrom.getOrigin(), rayTo.getOrigin());
|
||||
|
||||
btCollisionWorld::rayTestSingle(rayFrom, rayTo, targetCollisionObj, targetCollisionObj->getCollisionShape(), targetCollisionObj->getWorldTransform(), cb);
|
||||
if (!cb.hasHit())
|
||||
{
|
||||
// didn't hit the target. this could happen if point is already inside the collision box
|
||||
return 0.f;
|
||||
}
|
||||
else
|
||||
return (point - toOsg(cb.m_hitPointWorld)).length();
|
||||
}
|
||||
|
||||
class ClosestNotMeRayResultCallback : public btCollisionWorld::ClosestRayResultCallback
|
||||
{
|
||||
public:
|
||||
|
|
|
@ -89,6 +89,13 @@ namespace MWPhysics
|
|||
const osg::Quat &orientation,
|
||||
float queryDistance);
|
||||
|
||||
|
||||
/// Get distance from \a point to the collision shape of \a target. Uses a raycast to find where the
|
||||
/// target vector hits the collision shape and then calculates distance from the intersection point.
|
||||
/// This can be used to find out how much nearer we need to move to the target for a "getHitContact" to be successful.
|
||||
/// \note Only Actor targets are supported at the moment.
|
||||
float getHitDistance(const osg::Vec3f& point, const MWWorld::Ptr& target) const;
|
||||
|
||||
struct RayResult
|
||||
{
|
||||
bool mHit;
|
||||
|
|
|
@ -3238,4 +3238,11 @@ namespace MWWorld
|
|||
osg::Vec3f targetPos = mPhysics->getPosition(target);
|
||||
return (targetPos - weaponPos);
|
||||
}
|
||||
|
||||
float World::getHitDistance(const Ptr &actor, const Ptr &target)
|
||||
{
|
||||
osg::Vec3f weaponPos = getActorHeadPosition(actor, mRendering);
|
||||
return mPhysics->getHitDistance(weaponPos, target);
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
@ -633,6 +633,9 @@ namespace MWWorld
|
|||
/// Return a vector aiming the actor's weapon towards a target.
|
||||
/// @note The length of the vector is the distance between actor and target.
|
||||
virtual osg::Vec3f aimToTarget(const MWWorld::Ptr& actor, const MWWorld::Ptr& target);
|
||||
|
||||
/// Return the distance between actor's weapon and target's collision box.
|
||||
virtual float getHitDistance(const MWWorld::Ptr& actor, const MWWorld::Ptr& target);
|
||||
};
|
||||
}
|
||||
|
||||
|
|
Loading…
Reference in a new issue