mirror of
https://github.com/TES3MP/openmw-tes3mp.git
synced 2025-01-16 19:19:56 +00:00
parent
4d94f38f4b
commit
c4b5a41ac3
5 changed files with 45 additions and 37 deletions
|
@ -541,6 +541,10 @@ namespace MWBase
|
|||
virtual void resetActors() = 0;
|
||||
|
||||
virtual bool isWalkingOnWater (const MWWorld::Ptr& actor) = 0;
|
||||
|
||||
/// 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;
|
||||
};
|
||||
}
|
||||
|
||||
|
|
|
@ -34,10 +34,9 @@ namespace
|
|||
return std::atan2(dir.x(), dir.y());
|
||||
}
|
||||
|
||||
float getXAngleToDir(const osg::Vec3f& dir, float dirLen = 0.0f)
|
||||
float getXAngleToDir(const osg::Vec3f& dir)
|
||||
{
|
||||
float len = (dirLen > 0.0f)? dirLen : dir.length();
|
||||
return -std::asin(dir.z() / len);
|
||||
return -std::asin(dir.z() / dir.length());
|
||||
}
|
||||
|
||||
const float REACTION_INTERVAL = 0.25f;
|
||||
|
@ -346,8 +345,9 @@ namespace MWMechanics
|
|||
ESM::Position pos = actor.getRefData().getPosition();
|
||||
osg::Vec3f vActorPos(pos.asVec3());
|
||||
osg::Vec3f vTargetPos(target.getRefData().getPosition().asVec3());
|
||||
osg::Vec3f vDirToTarget = vTargetPos - vActorPos;
|
||||
float distToTarget = vDirToTarget.length();
|
||||
|
||||
osg::Vec3f vAimDir = MWBase::Environment::get().getWorld()->aimToTarget(actor, target);
|
||||
float distToTarget = (vTargetPos - vActorPos).length();
|
||||
|
||||
osg::Vec3f& lastActorPos = storage.mLastActorPos;
|
||||
bool& followTarget = storage.mFollowTarget;
|
||||
|
@ -388,7 +388,7 @@ namespace MWMechanics
|
|||
if (distantCombat)
|
||||
{
|
||||
osg::Vec3f& lastTargetPos = storage.mLastTargetPos;
|
||||
osg::Vec3f vAimDir = AimDirToMovingTarget(actor, target, lastTargetPos, REACTION_INTERVAL, weaptype,
|
||||
vAimDir = AimDirToMovingTarget(actor, target, lastTargetPos, REACTION_INTERVAL, weaptype,
|
||||
storage.mStrength);
|
||||
lastTargetPos = vTargetPos;
|
||||
movement.mRotation[0] = getXAngleToDir(vAimDir);
|
||||
|
@ -396,8 +396,8 @@ namespace MWMechanics
|
|||
}
|
||||
else
|
||||
{
|
||||
movement.mRotation[0] = getXAngleToDir(vDirToTarget, distToTarget);
|
||||
movement.mRotation[2] = getZAngleToDir(vDirToTarget);
|
||||
movement.mRotation[0] = getXAngleToDir(vAimDir);
|
||||
movement.mRotation[2] = getZAngleToDir((vTargetPos-vActorPos)); // using vAimDir results in spastic movements since the head is animated
|
||||
}
|
||||
|
||||
// (not quite attack dist while following)
|
||||
|
@ -431,19 +431,19 @@ namespace MWMechanics
|
|||
if(speed == 0.0f) speed = actorClass.getSpeed(actor);
|
||||
// maximum dist before pit/obstacle for actor to avoid them depending on his speed
|
||||
float maxAvoidDist = REACTION_INTERVAL * speed + speed / MAX_VEL_ANGULAR_RADIANS * 2; // *2 - for reliability
|
||||
preferShortcut = checkWayIsClear(vActorPos, vTargetPos, osg::Vec3f(vDirToTarget.x(), vDirToTarget.y(), 0).length() > maxAvoidDist*1.5? maxAvoidDist : maxAvoidDist/2);
|
||||
preferShortcut = checkWayIsClear(vActorPos, vTargetPos, osg::Vec3f(vAimDir.x(), vAimDir.y(), 0).length() > maxAvoidDist*1.5? maxAvoidDist : maxAvoidDist/2);
|
||||
}
|
||||
|
||||
// don't use pathgrid when actor can move in 3 dimensions
|
||||
if (canMoveByZ)
|
||||
{
|
||||
preferShortcut = true;
|
||||
movement.mRotation[0] = getXAngleToDir(vDirToTarget, distToTarget);
|
||||
movement.mRotation[0] = getXAngleToDir(vAimDir);
|
||||
}
|
||||
|
||||
if(preferShortcut)
|
||||
{
|
||||
movement.mRotation[2] = getZAngleToDir(vDirToTarget);
|
||||
movement.mRotation[2] = getZAngleToDir((vTargetPos-vActorPos));
|
||||
forceNoShortcut = false;
|
||||
shortcutFailPos.pos[0] = shortcutFailPos.pos[1] = shortcutFailPos.pos[2] = 0;
|
||||
mPathFinder.clearPath();
|
||||
|
@ -478,7 +478,7 @@ namespace MWMechanics
|
|||
// if there is no new path, then go straight on target
|
||||
if (!mPathFinder.isPathConstructed())
|
||||
{
|
||||
movement.mRotation[2] = getZAngleToDir(vDirToTarget);
|
||||
movement.mRotation[2] = getZAngleToDir((vTargetPos-vActorPos));
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -779,9 +779,8 @@ osg::Vec3f AimDirToMovingTarget(const MWWorld::Ptr& actor, const MWWorld::Ptr& t
|
|||
|
||||
// idea: perpendicular to dir to target speed components of target move vector and projectile vector should be the same
|
||||
|
||||
osg::Vec3f vActorPos = actor.getRefData().getPosition().asVec3();
|
||||
osg::Vec3f vTargetPos = target.getRefData().getPosition().asVec3();
|
||||
osg::Vec3f vDirToTarget = vTargetPos - vActorPos;
|
||||
osg::Vec3f vDirToTarget = MWBase::Environment::get().getWorld()->aimToTarget(actor, target);
|
||||
float distToTarget = vDirToTarget.length();
|
||||
|
||||
osg::Vec3f vTargetMoveDir = vTargetPos - vLastTargetPos;
|
||||
|
@ -812,7 +811,7 @@ osg::Vec3f AimDirToMovingTarget(const MWWorld::Ptr& actor, const MWWorld::Ptr& t
|
|||
t_collision = projDistDiff / (std::sqrt(projVelDirSquared) - velDir);
|
||||
else t_collision = 0; // speed of projectile is not enough to reach moving target
|
||||
|
||||
return vTargetPos + vTargetMoveDir * t_collision - vActorPos;
|
||||
return vDirToTarget + vTargetMoveDir * t_collision;
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
@ -107,6 +107,7 @@ namespace MWPhysics
|
|||
|
||||
bool isOnGround (const MWWorld::Ptr& actor);
|
||||
|
||||
/// Get physical half extents (scaled) of the given actor.
|
||||
osg::Vec3f getHalfExtents(const MWWorld::Ptr& actor);
|
||||
|
||||
/// Queues velocity movement for a Ptr. If a Ptr is already queued, its velocity will
|
||||
|
|
|
@ -1018,14 +1018,11 @@ namespace MWWorld
|
|||
return facedObject;
|
||||
}
|
||||
|
||||
std::pair<MWWorld::Ptr,osg::Vec3f> World::getHitContact(const MWWorld::Ptr &ptr, float distance)
|
||||
osg::Vec3f getActorHeadPosition(const MWWorld::Ptr& actor, MWRender::RenderingManager* rendering)
|
||||
{
|
||||
const ESM::Position &posdata = ptr.getRefData().getPosition();
|
||||
osg::Vec3f origin(actor.getRefData().getPosition().asVec3());
|
||||
|
||||
osg::Quat rot = osg::Quat(posdata.rot[0], osg::Vec3f(-1,0,0)) * osg::Quat(posdata.rot[2], osg::Vec3f(0,0,-1));
|
||||
osg::Vec3f pos (posdata.asVec3());
|
||||
|
||||
MWRender::Animation* anim = mRendering->getAnimation(ptr);
|
||||
MWRender::Animation* anim = rendering->getAnimation(actor);
|
||||
if (anim != NULL)
|
||||
{
|
||||
const osg::Node* node = anim->getNode("Head");
|
||||
|
@ -1035,9 +1032,18 @@ namespace MWWorld
|
|||
{
|
||||
osg::MatrixList mats = node->getWorldMatrices();
|
||||
if (mats.size())
|
||||
pos = mats[0].getTrans();
|
||||
origin = mats[0].getTrans();
|
||||
}
|
||||
}
|
||||
return origin;
|
||||
}
|
||||
|
||||
std::pair<MWWorld::Ptr,osg::Vec3f> World::getHitContact(const MWWorld::Ptr &ptr, float distance)
|
||||
{
|
||||
const ESM::Position &posdata = ptr.getRefData().getPosition();
|
||||
|
||||
osg::Quat rot = osg::Quat(posdata.rot[0], osg::Vec3f(-1,0,0)) * osg::Quat(posdata.rot[2], osg::Vec3f(0,0,-1));
|
||||
osg::Vec3f pos = getActorHeadPosition(ptr, mRendering);
|
||||
|
||||
std::pair<MWWorld::Ptr,osg::Vec3f> result = mPhysics->getHitContact(ptr, pos, rot, distance);
|
||||
if(result.first.isEmpty())
|
||||
|
@ -2608,21 +2614,7 @@ namespace MWWorld
|
|||
MWWorld::Ptr target;
|
||||
float distance = 192.f; // ??
|
||||
osg::Vec3f hitPosition = actor.getRefData().getPosition().asVec3();
|
||||
osg::Vec3f origin(actor.getRefData().getPosition().asVec3());
|
||||
|
||||
MWRender::Animation* anim = mRendering->getAnimation(actor);
|
||||
if (anim != NULL)
|
||||
{
|
||||
const osg::Node* node = anim->getNode("Head");
|
||||
if (node == NULL)
|
||||
node = anim->getNode("Bip01 Head");
|
||||
if (node != NULL)
|
||||
{
|
||||
osg::MatrixList mats = node->getWorldMatrices();
|
||||
if (mats.size())
|
||||
origin = mats[0].getTrans();
|
||||
}
|
||||
}
|
||||
osg::Vec3f origin = getActorHeadPosition(actor, mRendering);
|
||||
|
||||
osg::Quat orient = osg::Quat(actor.getRefData().getPosition().rot[0], osg::Vec3f(-1,0,0))
|
||||
* osg::Quat(actor.getRefData().getPosition().rot[2], osg::Vec3f(0,0,-1));
|
||||
|
@ -3262,4 +3254,12 @@ namespace MWWorld
|
|||
return true;
|
||||
return false;
|
||||
}
|
||||
|
||||
osg::Vec3f World::aimToTarget(const Ptr &actor, const MWWorld::Ptr& target)
|
||||
{
|
||||
osg::Vec3f weaponPos = getActorHeadPosition(actor, mRendering);
|
||||
osg::Vec3f targetPos = target.getRefData().getPosition().asVec3();
|
||||
targetPos.z() += mPhysics->getHalfExtents(target).z();
|
||||
return (targetPos - weaponPos);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -630,6 +630,10 @@ namespace MWWorld
|
|||
virtual void resetActors();
|
||||
|
||||
virtual bool isWalkingOnWater (const MWWorld::Ptr& actor);
|
||||
|
||||
/// 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);
|
||||
};
|
||||
}
|
||||
|
||||
|
|
Loading…
Reference in a new issue