diff --git a/CHANGELOG.md b/CHANGELOG.md index cfe21ab8d..febf869c1 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -127,6 +127,7 @@ Bug #5112: Insufficient magicka for current spell not reflected on HUD icon Bug #5123: Script won't run on respawn Bug #5124: Arrow remains attached to actor if pulling animation was cancelled + Bug #5134: Doors rotation by "Lock" console command is inconsistent Bug #5137: Textures with Clamp Mode set to Clamp instead of Wrap are too dark outside the boundaries Feature #1774: Handle AvoidNode Feature #2229: Improve pathfinding AI diff --git a/apps/openmw/mwscript/miscextensions.cpp b/apps/openmw/mwscript/miscextensions.cpp index ccdc6becf..47873a3b6 100644 --- a/apps/openmw/mwscript/miscextensions.cpp +++ b/apps/openmw/mwscript/miscextensions.cpp @@ -189,12 +189,6 @@ namespace MWScript if (ptr.getTypeName() == typeid(ESM::Door).name() && !ptr.getCellRef().getTeleport()) { MWBase::Environment::get().getWorld()->activateDoor(ptr, 0); - - float xr = ptr.getCellRef().getPosition().rot[0]; - float yr = ptr.getCellRef().getPosition().rot[1]; - float zr = ptr.getCellRef().getPosition().rot[2]; - - MWBase::Environment::get().getWorld()->rotateObject(ptr, xr, yr, zr); } } }; diff --git a/apps/openmw/mwworld/worldimp.cpp b/apps/openmw/mwworld/worldimp.cpp index dbcf1cd14..ef65ec162 100644 --- a/apps/openmw/mwworld/worldimp.cpp +++ b/apps/openmw/mwworld/worldimp.cpp @@ -1617,6 +1617,45 @@ namespace MWWorld return result.mHit; } + bool World::rotateDoor(const Ptr door, int state, float duration) + { + const ESM::Position& objPos = door.getRefData().getPosition(); + float oldRot = objPos.rot[2]; + + float minRot = door.getCellRef().getPosition().rot[2]; + float maxRot = minRot + osg::DegreesToRadians(90.f); + + float diff = duration * osg::DegreesToRadians(90.f); + float targetRot = std::min(std::max(minRot, oldRot + diff * (state == 1 ? 1 : -1)), maxRot); + rotateObject(door, objPos.rot[0], objPos.rot[1], targetRot); + + bool reached = (targetRot == maxRot && state) || targetRot == minRot; + + /// \todo should use convexSweepTest here + std::vector collisions = mPhysics->getCollisions(door, MWPhysics::CollisionType_Door, MWPhysics::CollisionType_Actor); + for (MWWorld::Ptr& ptr : collisions) + { + if (ptr.getClass().isActor()) + { + // Collided with actor, ask actor to try to avoid door + if(ptr != getPlayerPtr() ) + { + MWMechanics::AiSequence& seq = ptr.getClass().getCreatureStats(ptr).getAiSequence(); + if(seq.getTypeId() != MWMechanics::AiPackage::TypeIdAvoidDoor) //Only add it once + seq.stack(MWMechanics::AiAvoidDoor(door),ptr); + } + + // we need to undo the rotation + rotateObject(door, objPos.rot[0], objPos.rot[1], oldRot); + reached = false; + } + } + + // the rotation order we want to use + mWorldScene->updateObjectRotation(door, false); + return reached; + } + void World::processDoors(float duration) { std::map::iterator it = mDoorStates.begin(); @@ -1631,40 +1670,7 @@ namespace MWWorld } else { - const ESM::Position& objPos = it->first.getRefData().getPosition(); - float oldRot = objPos.rot[2]; - - float minRot = it->first.getCellRef().getPosition().rot[2]; - float maxRot = minRot + osg::DegreesToRadians(90.f); - - float diff = duration * osg::DegreesToRadians(90.f); - float targetRot = std::min(std::max(minRot, oldRot + diff * (it->second == 1 ? 1 : -1)), maxRot); - rotateObject(it->first, objPos.rot[0], objPos.rot[1], targetRot); - - bool reached = (targetRot == maxRot && it->second) || targetRot == minRot; - - /// \todo should use convexSweepTest here - std::vector collisions = mPhysics->getCollisions(it->first, MWPhysics::CollisionType_Door, MWPhysics::CollisionType_Actor); - for (MWWorld::Ptr& ptr : collisions) - { - if (ptr.getClass().isActor()) - { - // Collided with actor, ask actor to try to avoid door - if(ptr != getPlayerPtr() ) - { - MWMechanics::AiSequence& seq = ptr.getClass().getCreatureStats(ptr).getAiSequence(); - if(seq.getTypeId() != MWMechanics::AiPackage::TypeIdAvoidDoor) //Only add it once - seq.stack(MWMechanics::AiAvoidDoor(it->first),ptr); - } - - // we need to undo the rotation - rotateObject(it->first, objPos.rot[0], objPos.rot[1], oldRot); - reached = false; - } - } - - // the rotation order we want to use - mWorldScene->updateObjectRotation(it->first, false); + bool reached = rotateDoor(it->first, it->second, duration); if (reached) { @@ -2535,7 +2541,10 @@ namespace MWWorld door.getClass().setDoorState(door, state); mDoorStates[door] = state; if (state == 0) + { mDoorStates.erase(door); + rotateDoor(door, state, 1); + } } bool World::getPlayerStandingOn (const MWWorld::ConstPtr& object) diff --git a/apps/openmw/mwworld/worldimp.hpp b/apps/openmw/mwworld/worldimp.hpp index dd915c8bd..0284d8fee 100644 --- a/apps/openmw/mwworld/worldimp.hpp +++ b/apps/openmw/mwworld/worldimp.hpp @@ -146,6 +146,8 @@ namespace MWWorld private: void PCDropped (const Ptr& item); + bool rotateDoor(const Ptr door, int state, float duration); + void processDoors(float duration); ///< Run physics simulation and modify \a world accordingly.