Attempt to fix player position after using coc/coe

This commit is contained in:
scrawl 2014-06-28 14:59:33 +02:00
parent 8e361bb879
commit 3b2358888b
6 changed files with 24 additions and 6 deletions

View file

@ -274,6 +274,9 @@ namespace MWBase
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.
virtual void fixPosition (const MWWorld::Ptr& actor) = 0;
///< Attempt to fix position so that the Ptr is no longer inside collision geometry.
virtual void deleteObject (const MWWorld::Ptr& ptr) = 0; virtual void deleteObject (const MWWorld::Ptr& ptr) = 0;
virtual void moveObject (const MWWorld::Ptr& ptr, float x, float y, float z) = 0; virtual void moveObject (const MWWorld::Ptr& ptr, float x, float y, float z) = 0;

View file

@ -47,6 +47,7 @@ namespace MWScript
if (world->findExteriorPosition(cell, pos)) if (world->findExteriorPosition(cell, pos))
{ {
world->changeToExteriorCell(pos); world->changeToExteriorCell(pos);
world->fixPosition(world->getPlayerPtr());
} }
else else
{ {
@ -79,6 +80,7 @@ namespace MWScript
pos.rot[0] = pos.rot[1] = pos.rot[2] = 0; pos.rot[0] = pos.rot[1] = pos.rot[2] = 0;
world->changeToExteriorCell (pos); world->changeToExteriorCell (pos);
world->fixPosition(world->getPlayerPtr());
} }
}; };

View file

@ -215,7 +215,7 @@ namespace MWWorld
public: public:
static Ogre::Vector3 traceDown(const MWWorld::Ptr &ptr, OEngine::Physic::PhysicEngine *engine) static Ogre::Vector3 traceDown(const MWWorld::Ptr &ptr, OEngine::Physic::PhysicEngine *engine, float maxHeight)
{ {
const ESM::Position &refpos = ptr.getRefData().getPosition(); const ESM::Position &refpos = ptr.getRefData().getPosition();
Ogre::Vector3 position(refpos.pos); Ogre::Vector3 position(refpos.pos);
@ -224,7 +224,6 @@ namespace MWWorld
if (!physicActor) if (!physicActor)
return position; return position;
const int maxHeight = 200.f;
OEngine::Physic::ActorTracer tracer; OEngine::Physic::ActorTracer tracer;
tracer.findGround(physicActor, position, position-Ogre::Vector3(0,0,maxHeight), engine); tracer.findGround(physicActor, position, position-Ogre::Vector3(0,0,maxHeight), engine);
if(tracer.mFraction >= 1.0f) if(tracer.mFraction >= 1.0f)
@ -600,9 +599,9 @@ namespace MWWorld
return mEngine->getCollisions(ptr.getRefData().getBaseNode()->getName()); return mEngine->getCollisions(ptr.getRefData().getBaseNode()->getName());
} }
Ogre::Vector3 PhysicsSystem::traceDown(const MWWorld::Ptr &ptr) Ogre::Vector3 PhysicsSystem::traceDown(const MWWorld::Ptr &ptr, float maxHeight)
{ {
return MovementSolver::traceDown(ptr, mEngine); return MovementSolver::traceDown(ptr, mEngine, maxHeight);
} }
void PhysicsSystem::addHeightField (float* heights, void PhysicsSystem::addHeightField (float* heights,

View file

@ -56,7 +56,7 @@ namespace MWWorld
void stepSimulation(float dt); void stepSimulation(float dt);
std::vector<std::string> getCollisions(const MWWorld::Ptr &ptr); ///< get handles this object collides with std::vector<std::string> getCollisions(const MWWorld::Ptr &ptr); ///< get handles this object collides with
Ogre::Vector3 traceDown(const MWWorld::Ptr &ptr); Ogre::Vector3 traceDown(const MWWorld::Ptr &ptr, float maxHeight);
std::pair<float, std::string> getFacedHandle(float queryDistance); std::pair<float, std::string> getFacedHandle(float queryDistance);
std::pair<std::string,Ogre::Vector3> getHitContact(const std::string &name, std::pair<std::string,Ogre::Vector3> getHitContact(const std::string &name,

View file

@ -1166,7 +1166,7 @@ namespace MWWorld
if (!isFlying(ptr)) if (!isFlying(ptr))
{ {
Ogre::Vector3 traced = mPhysics->traceDown(ptr); Ogre::Vector3 traced = mPhysics->traceDown(ptr, 200);
if (traced.z < pos.pos[2]) if (traced.z < pos.pos[2])
pos.pos[2] = traced.z; pos.pos[2] = traced.z;
} }
@ -1174,6 +1174,17 @@ namespace MWWorld
moveObject(ptr, ptr.getCell(), pos.pos[0], pos.pos[1], pos.pos[2]); moveObject(ptr, ptr.getCell(), pos.pos[0], pos.pos[1], pos.pos[2]);
} }
void World::fixPosition(const Ptr &actor)
{
const float dist = 8000;
ESM::Position pos (actor.getRefData().getPosition());
pos.pos[2] += dist;
actor.getRefData().setPosition(pos);
Ogre::Vector3 traced = mPhysics->traceDown(actor, dist*1.1);
moveObject(actor, actor.getCell(), traced.x, traced.y, traced.z);
}
void World::rotateObject (const Ptr& ptr,float x,float y,float z, bool adjust) void World::rotateObject (const Ptr& ptr,float x,float y,float z, bool adjust)
{ {
rotateObjectImp(ptr, Ogre::Vector3(Ogre::Degree(x).valueRadians(), rotateObjectImp(ptr, Ogre::Vector3(Ogre::Degree(x).valueRadians(),

View file

@ -263,6 +263,9 @@ namespace MWWorld
virtual void adjustPosition (const Ptr& ptr); virtual void adjustPosition (const Ptr& ptr);
///< 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.
virtual void fixPosition (const Ptr& actor);
///< Attempt to fix position so that the Ptr is no longer inside collision geometry.
virtual void enable (const Ptr& ptr); virtual void enable (const Ptr& ptr);
virtual void disable (const Ptr& ptr); virtual void disable (const Ptr& ptr);