Do not allow resting on lava

openmw-38
scrawl 9 years ago
parent 2d302aef99
commit 43de13fa99

@ -515,6 +515,7 @@ namespace MWPhysics
public: public:
Object(const MWWorld::Ptr& ptr, osg::ref_ptr<Resource::BulletShapeInstance> shapeInstance) Object(const MWWorld::Ptr& ptr, osg::ref_ptr<Resource::BulletShapeInstance> shapeInstance)
: mShapeInstance(shapeInstance) : mShapeInstance(shapeInstance)
, mSolid(true)
{ {
mPtr = ptr; mPtr = ptr;
@ -549,6 +550,17 @@ namespace MWPhysics
return mCollisionObject.get(); return mCollisionObject.get();
} }
/// Return solid flag. Not used by the object itself, true by default.
bool isSolid() const
{
return mSolid;
}
void setSolid(bool solid)
{
mSolid = solid;
}
bool isAnimated() const bool isAnimated() const
{ {
return !mShapeInstance->mAnimatedShapes.empty(); return !mShapeInstance->mAnimatedShapes.empty();
@ -618,6 +630,7 @@ namespace MWPhysics
private: private:
std::auto_ptr<btCollisionObject> mCollisionObject; std::auto_ptr<btCollisionObject> mCollisionObject;
osg::ref_ptr<Resource::BulletShapeInstance> mShapeInstance; osg::ref_ptr<Resource::BulletShapeInstance> mShapeInstance;
bool mSolid;
}; };
// --------------------------------------------------------------- // ---------------------------------------------------------------
@ -684,6 +697,35 @@ namespace MWPhysics
return mDebugDrawEnabled; return mDebugDrawEnabled;
} }
void PhysicsSystem::markAsNonSolid(const MWWorld::Ptr &ptr)
{
ObjectMap::iterator found = mObjects.find(ptr);
if (found == mObjects.end())
return;
found->second->setSolid(false);
}
bool PhysicsSystem::isOnSolidGround (const MWWorld::Ptr& actor) const
{
const Actor* physactor = getActor(actor);
if (!physactor->getOnGround())
return false;
CollisionMap::const_iterator found = mStandingCollisions.find(actor);
if (found == mStandingCollisions.end())
return true; // assume standing on terrain (which is a non-object, so not collision tracked)
ObjectMap::const_iterator foundObj = mObjects.find(found->second);
if (foundObj == mObjects.end())
return false;
if (!foundObj->second->isSolid())
return false;
return true;
}
class DeepestNotMeContactTestResultCallback : public btCollisionWorld::ContactResultCallback class DeepestNotMeContactTestResultCallback : public btCollisionWorld::ContactResultCallback
{ {
const btCollisionObject* mMe; const btCollisionObject* mMe;

@ -153,6 +153,12 @@ namespace MWPhysics
bool toggleDebugRendering(); bool toggleDebugRendering();
/// Mark the given object as a 'non-solid' object. A non-solid object means that
/// \a isOnSolidGround will return false for actors standing on that object.
void markAsNonSolid (const MWWorld::Ptr& ptr);
bool isOnSolidGround (const MWWorld::Ptr& actor) const;
private: private:
void updateWater(); void updateWater();

@ -2059,11 +2059,10 @@ namespace MWWorld
if (!actor) if (!actor)
throw std::runtime_error("can't find player"); throw std::runtime_error("can't find player");
if((!actor->getOnGround()&&actor->getCollisionMode()) || isUnderwater(currentCell, playerPos) || isWalkingOnWater(player)) if ((actor->getCollisionMode() && !mPhysics->isOnSolidGround(player)) || isUnderwater(currentCell, playerPos))
return 2; return 2;
if((currentCell->getCell()->mData.mFlags&ESM::Cell::NoSleep) || if((currentCell->getCell()->mData.mFlags&ESM::Cell::NoSleep) || player.getClass().getNpcStats(player).isWerewolf())
player.getClass().getNpcStats(player).isWerewolf())
return 1; return 1;
return 0; return 0;
@ -2155,6 +2154,8 @@ namespace MWWorld
health.setCurrent(health.getCurrent()-healthPerSecond*MWBase::Environment::get().getFrameDuration()); health.setCurrent(health.getCurrent()-healthPerSecond*MWBase::Environment::get().getFrameDuration());
stats.setHealth(health); stats.setHealth(health);
mPhysics->markAsNonSolid (object);
if (healthPerSecond > 0.0f) if (healthPerSecond > 0.0f)
{ {
if (actor == getPlayerPtr()) if (actor == getPlayerPtr())
@ -2183,6 +2184,8 @@ namespace MWWorld
health.setCurrent(health.getCurrent()-healthPerSecond*MWBase::Environment::get().getFrameDuration()); health.setCurrent(health.getCurrent()-healthPerSecond*MWBase::Environment::get().getFrameDuration());
stats.setHealth(health); stats.setHealth(health);
mPhysics->markAsNonSolid (object);
if (healthPerSecond > 0.0f) if (healthPerSecond > 0.0f)
{ {
if (actor == getPlayerPtr()) if (actor == getPlayerPtr())

Loading…
Cancel
Save