forked from teamnwah/openmw-tes3coop
Add proper air movement mechanics (Fixes #2077)
This commit is contained in:
parent
261da8dd0a
commit
fafc14d5a0
2 changed files with 14 additions and 29 deletions
|
@ -1496,12 +1496,12 @@ void CharacterController::update(float duration)
|
||||||
forcestateupdate = (mJumpState != JumpState_InAir);
|
forcestateupdate = (mJumpState != JumpState_InAir);
|
||||||
mJumpState = JumpState_InAir;
|
mJumpState = JumpState_InAir;
|
||||||
|
|
||||||
// This is a guess. All that seems to be known is that "While the player is in the
|
|
||||||
// air, fJumpMoveBase and fJumpMoveMult governs air control". What does fJumpMoveMult do?
|
|
||||||
static const float fJumpMoveBase = gmst.find("fJumpMoveBase")->getFloat();
|
static const float fJumpMoveBase = gmst.find("fJumpMoveBase")->getFloat();
|
||||||
|
static const float fJumpMoveMult = gmst.find("fJumpMoveMult")->getFloat();
|
||||||
vec.x *= fJumpMoveBase;
|
float factor = fJumpMoveBase + fJumpMoveMult * mPtr.getClass().getSkill(mPtr, ESM::Skill::Acrobatics)/100.f;
|
||||||
vec.y *= fJumpMoveBase;
|
factor = std::min(1.f, factor);
|
||||||
|
vec.x *= factor;
|
||||||
|
vec.y *= factor;
|
||||||
vec.z = 0.0f;
|
vec.z = 0.0f;
|
||||||
}
|
}
|
||||||
else if(vec.z > 0.0f && mJumpState == JumpState_None)
|
else if(vec.z > 0.0f && mJumpState == JumpState_None)
|
||||||
|
|
|
@ -289,7 +289,7 @@ namespace MWWorld
|
||||||
|
|
||||||
// Reset per-frame data
|
// Reset per-frame data
|
||||||
physicActor->setWalkingOnWater(false);
|
physicActor->setWalkingOnWater(false);
|
||||||
/* Anything to collide with? */
|
// Anything to collide with?
|
||||||
if(!physicActor->getCollisionMode())
|
if(!physicActor->getCollisionMode())
|
||||||
{
|
{
|
||||||
return position + (Ogre::Quaternion(Ogre::Radian(refpos.rot[2]), Ogre::Vector3::NEGATIVE_UNIT_Z) *
|
return position + (Ogre::Quaternion(Ogre::Radian(refpos.rot[2]), Ogre::Vector3::NEGATIVE_UNIT_Z) *
|
||||||
|
@ -317,12 +317,11 @@ namespace MWWorld
|
||||||
*/
|
*/
|
||||||
|
|
||||||
OEngine::Physic::ActorTracer tracer;
|
OEngine::Physic::ActorTracer tracer;
|
||||||
Ogre::Vector3 inertia(0.0f);
|
Ogre::Vector3 inertia = physicActor->getInertialForce();
|
||||||
Ogre::Vector3 velocity;
|
Ogre::Vector3 velocity;
|
||||||
|
|
||||||
if(position.z < waterlevel || isFlying) // under water by 3/4 or can fly
|
if(position.z < waterlevel || isFlying)
|
||||||
{
|
{
|
||||||
// TODO: Shouldn't water have higher drag in calculating velocity?
|
|
||||||
velocity = (Ogre::Quaternion(Ogre::Radian(refpos.rot[2]), Ogre::Vector3::NEGATIVE_UNIT_Z)*
|
velocity = (Ogre::Quaternion(Ogre::Radian(refpos.rot[2]), Ogre::Vector3::NEGATIVE_UNIT_Z)*
|
||||||
Ogre::Quaternion(Ogre::Radian(refpos.rot[0]), Ogre::Vector3::NEGATIVE_UNIT_X)) * movement;
|
Ogre::Quaternion(Ogre::Radian(refpos.rot[0]), Ogre::Vector3::NEGATIVE_UNIT_X)) * movement;
|
||||||
}
|
}
|
||||||
|
@ -330,25 +329,12 @@ namespace MWWorld
|
||||||
{
|
{
|
||||||
velocity = Ogre::Quaternion(Ogre::Radian(refpos.rot[2]), Ogre::Vector3::NEGATIVE_UNIT_Z) * movement;
|
velocity = Ogre::Quaternion(Ogre::Radian(refpos.rot[2]), Ogre::Vector3::NEGATIVE_UNIT_Z) * movement;
|
||||||
|
|
||||||
// not in water nor can fly, so need to deal with gravity
|
if (velocity.z > 0.f)
|
||||||
if(!physicActor->getOnGround()) // if current OnGround status is false, must be falling or jumping
|
inertia = velocity;
|
||||||
|
if(!physicActor->getOnGround())
|
||||||
{
|
{
|
||||||
// If falling or jumping up, add part of the incoming velocity with the current inertia,
|
velocity = velocity + physicActor->getInertialForce();
|
||||||
// but don't allow increasing inertia beyond actor's speed (except on the initial jump impulse)
|
|
||||||
float actorSpeed = ptr.getClass().getSpeed(ptr);
|
|
||||||
float cap = std::max(actorSpeed, Ogre::Vector2(physicActor->getInertialForce().x, physicActor->getInertialForce().y).length());
|
|
||||||
Ogre::Vector3 newVelocity = velocity + physicActor->getInertialForce();
|
|
||||||
if (Ogre::Vector2(newVelocity.x, newVelocity.y).squaredLength() > cap*cap)
|
|
||||||
{
|
|
||||||
velocity = newVelocity;
|
|
||||||
float speedXY = Ogre::Vector2(velocity.x, velocity.y).length();
|
|
||||||
velocity.x *= cap / speedXY;
|
|
||||||
velocity.y *= cap / speedXY;
|
|
||||||
}
|
}
|
||||||
else
|
|
||||||
velocity = newVelocity;
|
|
||||||
}
|
|
||||||
inertia = velocity; // NOTE: velocity is for z axis only in this code block
|
|
||||||
}
|
}
|
||||||
ptr.getClass().getMovementSettings(ptr).mPosition[2] = 0;
|
ptr.getClass().getMovementSettings(ptr).mPosition[2] = 0;
|
||||||
|
|
||||||
|
@ -371,7 +357,6 @@ namespace MWWorld
|
||||||
float remainingTime = time;
|
float remainingTime = time;
|
||||||
for(int iterations = 0; iterations < sMaxIterations && remainingTime > 0.01f; ++iterations)
|
for(int iterations = 0; iterations < sMaxIterations && remainingTime > 0.01f; ++iterations)
|
||||||
{
|
{
|
||||||
// NOTE: velocity is either z axis only or x & z axis
|
|
||||||
Ogre::Vector3 nextpos = newPosition + velocity * remainingTime;
|
Ogre::Vector3 nextpos = newPosition + velocity * remainingTime;
|
||||||
|
|
||||||
// If not able to fly, don't allow to swim up into the air
|
// If not able to fly, don't allow to swim up into the air
|
||||||
|
@ -482,7 +467,7 @@ namespace MWWorld
|
||||||
// so that we do not stay suspended in air indefinitely.
|
// so that we do not stay suspended in air indefinitely.
|
||||||
if (tracer.mFraction < 1.0f && tracer.mHitObject->getBroadphaseHandle()->m_collisionFilterGroup == OEngine::Physic::CollisionType_Actor)
|
if (tracer.mFraction < 1.0f && tracer.mHitObject->getBroadphaseHandle()->m_collisionFilterGroup == OEngine::Physic::CollisionType_Actor)
|
||||||
{
|
{
|
||||||
if (Ogre::Vector3(inertia.x, inertia.y, 0).squaredLength() < 100.f*100.f)
|
if (Ogre::Vector3(velocity.x, velocity.y, 0).squaredLength() < 100.f*100.f)
|
||||||
{
|
{
|
||||||
btVector3 aabbMin, aabbMax;
|
btVector3 aabbMin, aabbMax;
|
||||||
tracer.mHitObject->getCollisionShape()->getAabb(tracer.mHitObject->getWorldTransform(), aabbMin, aabbMax);
|
tracer.mHitObject->getCollisionShape()->getAabb(tracer.mHitObject->getWorldTransform(), aabbMin, aabbMax);
|
||||||
|
@ -508,7 +493,7 @@ namespace MWWorld
|
||||||
}
|
}
|
||||||
physicActor->setOnGround(isOnGround);
|
physicActor->setOnGround(isOnGround);
|
||||||
|
|
||||||
newPosition.z -= halfExtents.z; // remove what was added at the beggining
|
newPosition.z -= halfExtents.z; // remove what was added at the beginning
|
||||||
return newPosition;
|
return newPosition;
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
Loading…
Reference in a new issue