From 386604bc9dd859f4b11c3f2117b8cfd2888457e6 Mon Sep 17 00:00:00 2001 From: scrawl Date: Tue, 13 May 2014 01:43:52 +0200 Subject: [PATCH] Fixes #869: Added methods to control external and internal collision modes separately When an actor dies, we should only disable external collisions, i.e. prevent other actors from colliding with the dead body. The dead actor, however, should still have gravity and collision applied. Also moved disableCollision to when the death animation finishes, not as soon as the actor's health is 0. --- apps/openmw/mwmechanics/actors.cpp | 5 ++--- apps/openmw/mwworld/physicssystem.cpp | 4 ++-- apps/openmw/mwworld/worldimp.cpp | 2 +- libs/openengine/bullet/physic.cpp | 9 ++++++--- libs/openengine/bullet/physic.hpp | 10 +++++++++- 5 files changed, 20 insertions(+), 10 deletions(-) diff --git a/apps/openmw/mwmechanics/actors.cpp b/apps/openmw/mwmechanics/actors.cpp index 6375bdd1b..b935284d3 100644 --- a/apps/openmw/mwmechanics/actors.cpp +++ b/apps/openmw/mwmechanics/actors.cpp @@ -920,9 +920,6 @@ namespace MWMechanics spells.purge(iter->first.getRefData().getHandle()); } - // FIXME: see http://bugs.openmw.org/issues/869 - MWBase::Environment::get().getWorld()->enableActorCollision(iter->first, false); - if (iter->second->kill()) { ++mDeathCount[cls.getId(iter->first)]; @@ -939,6 +936,8 @@ namespace MWMechanics stats.setMagicEffects(MWMechanics::MagicEffects()); calculateCreatureStatModifiers(iter->first, 0); + MWBase::Environment::get().getWorld()->enableActorCollision(iter->first, false); + if (cls.isEssential(iter->first)) MWBase::Environment::get().getWindowManager()->messageBox("#{sKilledEssential}"); } diff --git a/apps/openmw/mwworld/physicssystem.cpp b/apps/openmw/mwworld/physicssystem.cpp index e30a2bbc1..cf2ff87c6 100644 --- a/apps/openmw/mwworld/physicssystem.cpp +++ b/apps/openmw/mwworld/physicssystem.cpp @@ -626,12 +626,12 @@ namespace MWWorld bool cmode = act->getCollisionMode(); if(cmode) { - act->enableCollisions(false); + act->enableCollisionMode(false); return false; } else { - act->enableCollisions(true); + act->enableCollisionMode(true); return true; } } diff --git a/apps/openmw/mwworld/worldimp.cpp b/apps/openmw/mwworld/worldimp.cpp index b9a8f8dda..538cd17df 100644 --- a/apps/openmw/mwworld/worldimp.cpp +++ b/apps/openmw/mwworld/worldimp.cpp @@ -1957,7 +1957,7 @@ namespace MWWorld { OEngine::Physic::PhysicActor *physicActor = mPhysEngine->getCharacter(actor.getRefData().getHandle()); - physicActor->enableCollisions(enable); + physicActor->enableCollisionBody(enable); } bool World::findInteriorPosition(const std::string &name, ESM::Position &pos) diff --git a/libs/openengine/bullet/physic.cpp b/libs/openengine/bullet/physic.cpp index 4484d9862..c10892e52 100644 --- a/libs/openengine/bullet/physic.cpp +++ b/libs/openengine/bullet/physic.cpp @@ -41,15 +41,18 @@ namespace Physic } } - void PhysicActor::enableCollisions(bool collision) + void PhysicActor::enableCollisionMode(bool collision) + { + mCollisionMode = collision; + } + + void PhysicActor::enableCollisionBody(bool collision) { assert(mBody); if(collision && !mCollisionMode) enableCollisionBody(); if(!collision && mCollisionMode) disableCollisionBody(); - mCollisionMode = collision; } - void PhysicActor::setPosition(const Ogre::Vector3 &pos) { assert(mBody); diff --git a/libs/openengine/bullet/physic.hpp b/libs/openengine/bullet/physic.hpp index 4ef611dc8..4e035446e 100644 --- a/libs/openengine/bullet/physic.hpp +++ b/libs/openengine/bullet/physic.hpp @@ -99,7 +99,15 @@ namespace Physic */ void setRotation(const Ogre::Quaternion &quat); - void enableCollisions(bool collision); + /** + * Sets the collisionMode for this actor. If disabled, the actor can fly and clip geometry. + */ + void enableCollisionMode(bool collision); + + /** + * Enables or disables the *external* collision body. If disabled, other actors will not collide with this actor. + */ + void enableCollisionBody(bool collision); bool getCollisionMode() const {