Use a contactTest for collision script functions

The previous method didn't work for stationary actors. This change fixes the grinder in "Sotha Sil, Dome of Kasia" not registering collisions if the player stands still. (Fixes #1934)
openmw-38
scrawl 9 years ago
parent 9fce428929
commit a49058721e

@ -234,9 +234,8 @@ namespace MWPhysics
}
static osg::Vec3f move(const MWWorld::Ptr &ptr, Actor* physicActor, const osg::Vec3f &movement, float time,
bool isFlying, float waterlevel, float slowFall, btCollisionWorld* collisionWorld
, std::map<MWWorld::Ptr, MWWorld::Ptr>& collisionTracker
, std::map<MWWorld::Ptr, MWWorld::Ptr>& standingCollisionTracker)
bool isFlying, float waterlevel, float slowFall, btCollisionWorld* collisionWorld,
std::map<MWWorld::Ptr, MWWorld::Ptr>& standingCollisionTracker)
{
const ESM::Position& refpos = ptr.getRefData().getPosition();
osg::Vec3f position(refpos.asVec3());
@ -345,13 +344,6 @@ namespace MWPhysics
newPosition = tracer.mEndPos; // ok to move, so set newPosition
break;
}
else
{
const btCollisionObject* standingOn = tracer.mHitObject;
const PtrHolder* ptrHolder = static_cast<const PtrHolder*>(standingOn->getUserPointer());
if (ptrHolder)
collisionTracker[ptr] = ptrHolder->getPtr();
}
}
else
{
@ -968,11 +960,11 @@ namespace MWPhysics
}
};
std::vector<MWWorld::Ptr> PhysicsSystem::getCollisions(const MWWorld::Ptr &ptr, int collisionGroup, int collisionMask)
std::vector<MWWorld::Ptr> PhysicsSystem::getCollisions(const MWWorld::Ptr &ptr, int collisionGroup, int collisionMask) const
{
btCollisionObject* me = NULL;
ObjectMap::iterator found = mObjects.find(ptr);
ObjectMap::const_iterator found = mObjects.find(ptr);
if (found != mObjects.end())
me = found->second->getCollisionObject();
else
@ -1081,7 +1073,6 @@ namespace MWPhysics
mActors.insert(std::make_pair(updated, actor));
}
updateCollisionMapPtr(mCollisions, old, updated);
updateCollisionMapPtr(mStandingCollisions, old, updated);
}
@ -1197,7 +1188,6 @@ namespace MWPhysics
void PhysicsSystem::clearQueuedMovement()
{
mMovementQueue.clear();
mCollisions.clear();
mStandingCollisions.clear();
}
@ -1209,7 +1199,6 @@ namespace MWPhysics
if(mTimeAccum >= 1.0f/60.0f)
{
// Collision events should be available on every frame
mCollisions.clear();
mStandingCollisions.clear();
const MWBase::World *world = MWBase::Environment::get().getWorld();
@ -1243,7 +1232,7 @@ namespace MWPhysics
osg::Vec3f newpos = MovementSolver::move(iter->first, physicActor, iter->second, mTimeAccum,
world->isFlying(iter->first),
waterlevel, slowFall, mCollisionWorld, mCollisions, mStandingCollisions);
waterlevel, slowFall, mCollisionWorld, mStandingCollisions);
float heightDiff = newpos.z() - oldHeight;
@ -1296,21 +1285,14 @@ namespace MWPhysics
bool PhysicsSystem::isActorCollidingWith(const MWWorld::Ptr &actor, const MWWorld::Ptr &object) const
{
for (CollisionMap::const_iterator it = mCollisions.begin(); it != mCollisions.end(); ++it)
{
if (it->first == actor && it->second == object)
return true;
}
return false;
std::vector<MWWorld::Ptr> collisions = getCollisions(object, CollisionType_World, CollisionType_Actor);
return (std::find(collisions.begin(), collisions.end(), actor) != collisions.end());
}
void PhysicsSystem::getActorsCollidingWith(const MWWorld::Ptr &object, std::vector<MWWorld::Ptr> &out) const
{
for (CollisionMap::const_iterator it = mCollisions.begin(); it != mCollisions.end(); ++it)
{
if (it->second == object)
out.push_back(it->first);
}
std::vector<MWWorld::Ptr> collisions = getCollisions(object, CollisionType_World, CollisionType_Actor);
out.insert(out.end(), collisions.begin(), collisions.end());
}
void PhysicsSystem::disableWater()

@ -81,7 +81,7 @@ namespace MWPhysics
void stepSimulation(float dt);
void debugDraw();
std::vector<MWWorld::Ptr> getCollisions(const MWWorld::Ptr &ptr, int collisionGroup, int collisionMask); ///< get handles this object collides with
std::vector<MWWorld::Ptr> getCollisions(const MWWorld::Ptr &ptr, int collisionGroup, int collisionMask) const; ///< get handles this object collides with
osg::Vec3f traceDown(const MWWorld::Ptr &ptr, float maxHeight);
std::pair<MWWorld::Ptr, osg::Vec3f> getHitContact(const MWWorld::Ptr& actor,
@ -174,11 +174,9 @@ namespace MWPhysics
bool mDebugDrawEnabled;
// Tracks all movement collisions happening during a single frame. <actor handle, collided handle>
// This will detect e.g. running against a vertical wall. It will not detect climbing up stairs,
// stepping up small objects, etc.
// Tracks standing collisions happening during a single frame. <actor handle, collided handle>
// This will detect standing on an object, but won't detect running e.g. against a wall.
typedef std::map<MWWorld::Ptr, MWWorld::Ptr> CollisionMap;
CollisionMap mCollisions;
CollisionMap mStandingCollisions;
// replaces all occurences of 'old' in the map by 'updated', no matter if its a key or value

Loading…
Cancel
Save