mirror of
https://github.com/OpenMW/openmw.git
synced 2025-01-20 16:23:52 +00:00
Avoid swimming into the air from underwater
This commit is contained in:
parent
9f09bb6f6f
commit
602be9bbe7
2 changed files with 30 additions and 3 deletions
|
@ -107,7 +107,8 @@ namespace MWWorld
|
|||
}
|
||||
|
||||
static Ogre::Vector3 move(const MWWorld::Ptr &ptr, const Ogre::Vector3 &movement, float time,
|
||||
bool isSwimming, bool isFlying, OEngine::Physic::PhysicEngine *engine)
|
||||
bool isSwimming, bool isFlying, float waterlevel,
|
||||
OEngine::Physic::PhysicEngine *engine)
|
||||
{
|
||||
const ESM::Position &refpos = ptr.getRefData().getPosition();
|
||||
Ogre::Vector3 position(refpos.pos);
|
||||
|
@ -127,6 +128,8 @@ namespace MWWorld
|
|||
Ogre::Vector3 halfExtents = physicActor->getHalfExtents();
|
||||
position.z += halfExtents.z;
|
||||
|
||||
waterlevel -= halfExtents.z * 0.5;
|
||||
|
||||
OEngine::Physic::ActorTracer tracer;
|
||||
bool wasOnGround = false;
|
||||
bool isOnGround = false;
|
||||
|
@ -168,8 +171,21 @@ namespace MWWorld
|
|||
float remainingTime = time;
|
||||
for(int iterations = 0;iterations < sMaxIterations && remainingTime > 0.01f;++iterations)
|
||||
{
|
||||
Ogre::Vector3 nextpos = newPosition + velocity*remainingTime;
|
||||
|
||||
if(isSwimming && !isFlying &&
|
||||
nextpos.z > waterlevel && newPosition.z <= waterlevel)
|
||||
{
|
||||
const Ogre::Vector3 down(0,0,-1);
|
||||
Ogre::Real movelen = velocity.normalise();
|
||||
Ogre::Vector3 reflectdir = velocity.reflect(down);
|
||||
reflectdir.normalise();
|
||||
velocity = slide(reflectdir, down)*movelen;
|
||||
continue;
|
||||
}
|
||||
|
||||
// trace to where character would go if there were no obstructions
|
||||
tracer.doTrace(colobj, newPosition, newPosition+velocity*remainingTime, engine);
|
||||
tracer.doTrace(colobj, newPosition, nextpos, engine);
|
||||
|
||||
// check for obstructions
|
||||
if(tracer.mFraction >= 1.0f)
|
||||
|
@ -567,10 +583,16 @@ namespace MWWorld
|
|||
PtrVelocityList::iterator iter = mMovementQueue.begin();
|
||||
for(;iter != mMovementQueue.end();iter++)
|
||||
{
|
||||
float waterlevel = -std::numeric_limits<float>::max();
|
||||
const MWWorld::CellStore *cellstore = iter->first.getCell();
|
||||
if(cellstore->mCell->hasWater())
|
||||
waterlevel = cellstore->mCell->mWater;
|
||||
|
||||
Ogre::Vector3 newpos;
|
||||
newpos = MovementSolver::move(iter->first, iter->second, mTimeAccum,
|
||||
world->isSwimming(iter->first),
|
||||
world->isFlying(iter->first), mEngine);
|
||||
world->isFlying(iter->first),
|
||||
waterlevel, mEngine);
|
||||
mMovementResults.push_back(std::make_pair(iter->first, newpos));
|
||||
}
|
||||
|
||||
|
|
|
@ -119,6 +119,11 @@ struct Cell
|
|||
return mData.mY;
|
||||
}
|
||||
|
||||
bool hasWater() const
|
||||
{
|
||||
return (mData.mFlags&HasWater);
|
||||
}
|
||||
|
||||
// Restore the given reader to the stored position. Will try to open
|
||||
// the file matching the stored file name. If you want to read from
|
||||
// somewhere other than the file system, you need to pre-open the
|
||||
|
|
Loading…
Reference in a new issue