From 43757efdc4af643aeedc99c43e170b324c062830 Mon Sep 17 00:00:00 2001 From: cc9cii Date: Sun, 16 Mar 2014 08:09:14 +1100 Subject: [PATCH] Feature #1030 - partial fix to stop creatures unable to walk/fly to come out of water. Does not necessarily handle situations where they are already out of water, however. --- apps/openmw/mwclass/creature.cpp | 28 +++++++- apps/openmw/mwclass/creature.hpp | 5 +- apps/openmw/mwworld/class.cpp | 17 ++++- apps/openmw/mwworld/class.hpp | 5 +- apps/openmw/mwworld/physicssystem.cpp | 97 ++++++++++++++++++++------- apps/openmw/mwworld/worldimp.cpp | 2 +- 6 files changed, 122 insertions(+), 32 deletions(-) diff --git a/apps/openmw/mwclass/creature.cpp b/apps/openmw/mwclass/creature.cpp index 33c4390a0..c66bda09f 100644 --- a/apps/openmw/mwclass/creature.cpp +++ b/apps/openmw/mwclass/creature.cpp @@ -525,7 +525,7 @@ namespace MWClass float moveSpeed; if(normalizedEncumbrance >= 1.0f) moveSpeed = 0.0f; - else if(isFlying(ptr) || (mageffects.get(ESM::MagicEffect::Levitate).mMagnitude > 0 && + else if(canFly(ptr) || (mageffects.get(ESM::MagicEffect::Levitate).mMagnitude > 0 && world->isLevitationEnabled())) { float flySpeed = 0.01f*(stats.getAttribute(ESM::Attribute::Speed).getModified() + @@ -678,7 +678,15 @@ namespace MWClass return MWWorld::Ptr(&cell.get().insert(*ref), &cell); } - bool Creature::isFlying(const MWWorld::Ptr &ptr) const + bool Creature::isBipedal(const MWWorld::Ptr &ptr) const + { + MWWorld::LiveCellRef *ref = + ptr.get(); + + return ref->mBase->mFlags & ESM::Creature::Bipedal; + } + + bool Creature::canFly(const MWWorld::Ptr &ptr) const { MWWorld::LiveCellRef *ref = ptr.get(); @@ -686,6 +694,22 @@ namespace MWClass return ref->mBase->mFlags & ESM::Creature::Flies; } + bool Creature::canSwim(const MWWorld::Ptr &ptr) const + { + MWWorld::LiveCellRef *ref = + ptr.get(); + + return ref->mBase->mFlags & ESM::Creature::Swims; + } + + bool Creature::canWalk(const MWWorld::Ptr &ptr) const + { + MWWorld::LiveCellRef *ref = + ptr.get(); + + return ref->mBase->mFlags & ESM::Creature::Walks; + } + int Creature::getSndGenTypeFromName(const MWWorld::Ptr &ptr, const std::string &name) { if(name == "left") diff --git a/apps/openmw/mwclass/creature.hpp b/apps/openmw/mwclass/creature.hpp index 6df6db297..c1bcb8739 100644 --- a/apps/openmw/mwclass/creature.hpp +++ b/apps/openmw/mwclass/creature.hpp @@ -124,7 +124,10 @@ namespace MWClass return true; } - virtual bool isFlying (const MWWorld::Ptr &ptr) const; + virtual bool isBipedal (const MWWorld::Ptr &ptr) const; + virtual bool canFly (const MWWorld::Ptr &ptr) const; + virtual bool canSwim (const MWWorld::Ptr &ptr) const; + virtual bool canWalk (const MWWorld::Ptr &ptr) const; virtual int getSkill(const MWWorld::Ptr &ptr, int skill) const; diff --git a/apps/openmw/mwworld/class.cpp b/apps/openmw/mwworld/class.cpp index 2110086d3..39d48f95b 100644 --- a/apps/openmw/mwworld/class.cpp +++ b/apps/openmw/mwworld/class.cpp @@ -363,7 +363,22 @@ namespace MWWorld return newPtr; } - bool Class::isFlying(const Ptr &ptr) const + bool Class::isBipedal(const Ptr &ptr) const + { + return false; + } + + bool Class::canFly(const Ptr &ptr) const + { + return false; + } + + bool Class::canSwim(const Ptr &ptr) const + { + return false; + } + + bool Class::canWalk(const Ptr &ptr) const { return false; } diff --git a/apps/openmw/mwworld/class.hpp b/apps/openmw/mwworld/class.hpp index ad2cc3af4..739fd5942 100644 --- a/apps/openmw/mwworld/class.hpp +++ b/apps/openmw/mwworld/class.hpp @@ -307,7 +307,10 @@ namespace MWWorld return false; } - virtual bool isFlying(const MWWorld::Ptr& ptr) const; + virtual bool isBipedal(const MWWorld::Ptr& ptr) const; + virtual bool canFly(const MWWorld::Ptr& ptr) const; + virtual bool canSwim(const MWWorld::Ptr& ptr) const; + virtual bool canWalk(const MWWorld::Ptr& ptr) const; virtual int getSkill(const MWWorld::Ptr& ptr, int skill) const; diff --git a/apps/openmw/mwworld/physicssystem.cpp b/apps/openmw/mwworld/physicssystem.cpp index 1657cf267..1c6838939 100644 --- a/apps/openmw/mwworld/physicssystem.cpp +++ b/apps/openmw/mwworld/physicssystem.cpp @@ -116,8 +116,9 @@ namespace MWWorld const ESM::Position &refpos = ptr.getRefData().getPosition(); Ogre::Vector3 position(refpos.pos); - /* Anything to collide with? */ OEngine::Physic::PhysicActor *physicActor = engine->getCharacter(ptr.getRefData().getHandle()); + + // If no need to check for collision simply return the new position. if(!physicActor || !physicActor->getCollisionMode()) { return position + (Ogre::Quaternion(Ogre::Radian(refpos.rot[2]), Ogre::Vector3::NEGATIVE_UNIT_Z) * @@ -125,36 +126,67 @@ namespace MWWorld * movement * time; } + /* Anything to collide with? */ btCollisionObject *colobj = physicActor->getCollisionBody(); Ogre::Vector3 halfExtents = physicActor->getHalfExtents(); - position.z += halfExtents.z; - - waterlevel -= halfExtents.z * 0.5; + Ogre::Vector3 newPosition = position; // FIXME: not sure if a copy is needed + newPosition.z += halfExtents.z; // NOTE: remember to restore before returning + float actorWaterlevel = waterlevel - halfExtents.z * 0.5; + + /* + * A 3/4 submerged example + * + * +---+ + * | | + * | | <- waterlevel + * | | + * | | <- newPosition <- actorWaterlevel + * | | + * | | + * | | + * +---+ <- position + */ OEngine::Physic::ActorTracer tracer; bool wasOnGround = false; bool isOnGround = false; Ogre::Vector3 inertia(0.0f); Ogre::Vector3 velocity; - if(position.z < waterlevel || isFlying) + + bool canWalk = ptr.getClass().canWalk(ptr); + bool isBipedal = ptr.getClass().isBipedal(ptr); + bool isNpc = ptr.getClass().isNpc(); + + //if(!canWalk && !isBipedal && !isNpc && (position.z >= waterlevel)) + //{ + //std::cout << "Swim Creature \""<