diff --git a/apps/openmw/mwmechanics/character.cpp b/apps/openmw/mwmechanics/character.cpp index cb13305356..f7c50c5b6b 100644 --- a/apps/openmw/mwmechanics/character.cpp +++ b/apps/openmw/mwmechanics/character.cpp @@ -2405,9 +2405,6 @@ void CharacterController::update(float duration) if (!mMovementAnimationControlled) world->queueMovement(mPtr, vec); } - else - // We must always queue movement, even if there is none, to apply gravity. - world->queueMovement(mPtr, osg::Vec3f(0.f, 0.f, 0.f)); movement = vec; movementSettings.mPosition[0] = movementSettings.mPosition[1] = 0; @@ -2429,8 +2426,6 @@ void CharacterController::update(float duration) if (cls.isPersistent(mPtr) || cls.getCreatureStats(mPtr).isDeathAnimationFinished()) playDeath(1.f, mDeathState); } - // We must always queue movement, even if there is none, to apply gravity. - world->queueMovement(mPtr, osg::Vec3f(0.f, 0.f, 0.f)); } bool isPersist = isPersistentAnimPlaying(); diff --git a/apps/openmw/mwphysics/actor.cpp b/apps/openmw/mwphysics/actor.cpp index 4b97ecffb9..9793906098 100644 --- a/apps/openmw/mwphysics/actor.cpp +++ b/apps/openmw/mwphysics/actor.cpp @@ -22,7 +22,7 @@ namespace MWPhysics Actor::Actor(const MWWorld::Ptr& ptr, const Resource::BulletShape* shape, PhysicsTaskScheduler* scheduler) : mStandingOnPtr(nullptr), mCanWaterWalk(false), mWalkingOnWater(false) , mCollisionObject(nullptr), mMeshTranslation(shape->mCollisionBox.center), mHalfExtents(shape->mCollisionBox.extents) - , mStuckFrames(0), mLastStuckPosition{0, 0, 0} + , mVelocity(0,0,0), mStuckFrames(0), mLastStuckPosition{0, 0, 0} , mForce(0.f, 0.f, 0.f), mOnGround(true), mOnSlope(false) , mInternalCollisionMode(true) , mExternalCollisionMode(true) @@ -303,4 +303,14 @@ bool Actor::skipCollisions() return std::exchange(mSkipCollisions, false); } +void Actor::setVelocity(osg::Vec3f velocity) +{ + mVelocity = velocity; +} + +osg::Vec3f Actor::velocity() +{ + return std::exchange(mVelocity, osg::Vec3f()); +} + } diff --git a/apps/openmw/mwphysics/actor.hpp b/apps/openmw/mwphysics/actor.hpp index 45e2039ba5..acbf33ca75 100644 --- a/apps/openmw/mwphysics/actor.hpp +++ b/apps/openmw/mwphysics/actor.hpp @@ -178,6 +178,9 @@ namespace MWPhysics bool skipCollisions(); + void setVelocity(osg::Vec3f velocity); + osg::Vec3f velocity(); + private: MWWorld::Ptr mStandingOnPtr; /// Removes then re-adds the collision object to the dynamics world @@ -206,6 +209,7 @@ namespace MWPhysics osg::Vec3f mPosition; osg::Vec3f mPreviousPosition; osg::Vec3f mPositionOffset; + osg::Vec3f mVelocity; bool mWorldPositionChanged; bool mSkipCollisions; btTransform mLocalTransform; diff --git a/apps/openmw/mwphysics/object.cpp b/apps/openmw/mwphysics/object.cpp index e3615989dd..6363065323 100644 --- a/apps/openmw/mwphysics/object.cpp +++ b/apps/openmw/mwphysics/object.cpp @@ -119,11 +119,8 @@ namespace MWPhysics assert (mShapeInstance->getCollisionShape()->isCompound()); btCompoundShape* compound = static_cast(mShapeInstance->getCollisionShape()); - for (const auto& shape : mShapeInstance->mAnimatedShapes) + for (const auto& [recIndex, shapeIndex] : mShapeInstance->mAnimatedShapes) { - int recIndex = shape.first; - int shapeIndex = shape.second; - auto nodePathFound = mRecIndexToNodePath.find(recIndex); if (nodePathFound == mRecIndexToNodePath.end()) { diff --git a/apps/openmw/mwphysics/physicssystem.cpp b/apps/openmw/mwphysics/physicssystem.cpp index 382c951209..a5d6018f46 100644 --- a/apps/openmw/mwphysics/physicssystem.cpp +++ b/apps/openmw/mwphysics/physicssystem.cpp @@ -725,21 +725,15 @@ namespace MWPhysics void PhysicsSystem::queueObjectMovement(const MWWorld::Ptr &ptr, const osg::Vec3f &velocity) { - for(auto& movementItem : mMovementQueue) - { - if (movementItem.first == ptr) - { - movementItem.second = velocity; - return; - } - } - - mMovementQueue.emplace_back(ptr, velocity); + ActorMap::iterator found = mActors.find(ptr); + if (found != mActors.end()) + found->second->setVelocity(velocity); } void PhysicsSystem::clearQueuedMovement() { - mMovementQueue.clear(); + for (const auto& [_, actor] : mActors) + actor->setVelocity(osg::Vec3f()); } const std::vector& PhysicsSystem::applyQueuedMovement(float dt, bool skipSimulation, osg::Timer_t frameStart, unsigned int frameNumber, osg::Stats& stats) @@ -756,27 +750,21 @@ namespace MWPhysics std::vector PhysicsSystem::prepareFrameData(bool willSimulate) { std::vector actorsFrameData; - actorsFrameData.reserve(mMovementQueue.size()); + actorsFrameData.reserve(mActors.size()); const MWBase::World *world = MWBase::Environment::get().getWorld(); - for (const auto& [character, movement] : mMovementQueue) + for (const auto& [ptr, physicActor] : mActors) { - const auto foundActor = mActors.find(character); - if (foundActor == mActors.end()) // actor was already removed from the scene - continue; - - auto physicActor = foundActor->second; - float waterlevel = -std::numeric_limits::max(); - const MWWorld::CellStore *cell = character.getCell(); + const MWWorld::CellStore *cell = ptr.getCell(); if(cell->getCell()->hasWater()) waterlevel = cell->getWaterLevel(); - const MWMechanics::MagicEffects& effects = character.getClass().getCreatureStats(character).getMagicEffects(); + const MWMechanics::MagicEffects& effects = ptr.getClass().getCreatureStats(physicActor->getPtr()).getMagicEffects(); bool waterCollision = false; if (cell->getCell()->hasWater() && effects.get(ESM::MagicEffect::WaterWalking).getMagnitude()) { - if (physicActor->getCollisionMode() || !world->isUnderwater(character.getCell(), osg::Vec3f(character.getRefData().getPosition().asVec3()))) + if (physicActor->getCollisionMode() || !world->isUnderwater(ptr.getCell(), osg::Vec3f(ptr.getRefData().getPosition().asVec3()))) waterCollision = true; } @@ -790,9 +778,8 @@ namespace MWPhysics if (!willSimulate) standingOn = physicActor->getStandingOnPtr(); - actorsFrameData.emplace_back(std::move(physicActor), standingOn, waterCollision, movement, slowFall, waterlevel); + actorsFrameData.emplace_back(physicActor, standingOn, waterCollision, slowFall, waterlevel); } - mMovementQueue.clear(); return actorsFrameData; } @@ -933,10 +920,10 @@ namespace MWPhysics } ActorFrameData::ActorFrameData(const std::shared_ptr& actor, const MWWorld::Ptr standingOn, - bool waterCollision, osg::Vec3f movement, float slowFall, float waterlevel) + bool waterCollision, float slowFall, float waterlevel) : mActor(actor), mActorRaw(actor.get()), mStandingOn(standingOn), mDidJump(false), mNeedLand(false), mWaterCollision(waterCollision), mSkipCollisionDetection(actor->skipCollisions()), - mWaterlevel(waterlevel), mSlowFall(slowFall), mOldHeight(0), mFallHeight(0), mMovement(movement), mPosition(), mRefpos() + mWaterlevel(waterlevel), mSlowFall(slowFall), mOldHeight(0), mFallHeight(0), mMovement(actor->velocity()), mPosition(), mRefpos() { const MWBase::World *world = MWBase::Environment::get().getWorld(); const auto ptr = actor->getPtr(); diff --git a/apps/openmw/mwphysics/physicssystem.hpp b/apps/openmw/mwphysics/physicssystem.hpp index 23b2786750..3d2a3c580d 100644 --- a/apps/openmw/mwphysics/physicssystem.hpp +++ b/apps/openmw/mwphysics/physicssystem.hpp @@ -78,7 +78,7 @@ namespace MWPhysics struct ActorFrameData { - ActorFrameData(const std::shared_ptr& actor, const MWWorld::Ptr standingOn, bool moveToWaterSurface, osg::Vec3f movement, float slowFall, float waterlevel); + ActorFrameData(const std::shared_ptr& actor, const MWWorld::Ptr standingOn, bool moveToWaterSurface, float slowFall, float waterlevel); void updatePosition(btCollisionWorld* world); std::weak_ptr mActor; Actor* mActorRaw; @@ -281,9 +281,6 @@ namespace MWPhysics bool mDebugDrawEnabled; - using PtrVelocityList = std::vector>; - PtrVelocityList mMovementQueue; - float mTimeAccum; unsigned int mProjectileId; diff --git a/apps/openmw/mwrender/objectpaging.cpp b/apps/openmw/mwrender/objectpaging.cpp index 472b555618..d8f0215c0d 100644 --- a/apps/openmw/mwrender/objectpaging.cpp +++ b/apps/openmw/mwrender/objectpaging.cpp @@ -440,10 +440,8 @@ namespace MWRender continue; } } - for (ESM::CellRefTracker::const_iterator it = cell->mLeasedRefs.begin(); it != cell->mLeasedRefs.end(); ++it) + for (auto [ref, deleted] : cell->mLeasedRefs) { - ESM::CellRef ref = it->first; - bool deleted = it->second; if (deleted) { refs.erase(ref.mRefNum); continue; } Misc::StringUtils::lowerCaseInPlace(ref.mRefID); int type = store.findStatic(ref.mRefID); diff --git a/apps/openmw/mwworld/cellstore.cpp b/apps/openmw/mwworld/cellstore.cpp index 02ffe733fa..2e2735e11a 100644 --- a/apps/openmw/mwworld/cellstore.cpp +++ b/apps/openmw/mwworld/cellstore.cpp @@ -345,8 +345,8 @@ namespace MWWorld void merge() { - for (std::map::const_iterator it = mMovedHere.begin(); it != mMovedHere.end(); ++it) - mMergeTo.push_back(it->first); + for (const auto & [base, _] : mMovedHere) + mMergeTo.push_back(base); } private: @@ -453,9 +453,9 @@ namespace MWWorld if (Ptr ptr = ::searchViaActorId (mCreatures, id, this, mMovedToAnotherCell)) return ptr; - for (MovedRefTracker::const_iterator it = mMovedHere.begin(); it != mMovedHere.end(); ++it) + for (const auto& [base, _] : mMovedHere) { - MWWorld::Ptr actor (it->first, this); + MWWorld::Ptr actor (base, this); if (!actor.getClass().isActor()) continue; if (actor.getClass().getCreatureStats (actor).matchesActorId (id) && actor.getRefData().getCount() > 0) @@ -577,11 +577,8 @@ namespace MWWorld } // List moved references, from separately tracked list. - for (ESM::CellRefTracker::const_iterator it = mCell->mLeasedRefs.begin(); it != mCell->mLeasedRefs.end(); ++it) + for (const auto& [ref, deleted]: mCell->mLeasedRefs) { - const ESM::CellRef &ref = it->first; - bool deleted = it->second; - if (!deleted) mIds.push_back(Misc::StringUtils::lowerCase(ref.mRefID)); } @@ -633,10 +630,10 @@ namespace MWWorld } // Load moved references, from separately tracked list. - for (ESM::CellRefTracker::const_iterator it = mCell->mLeasedRefs.begin(); it != mCell->mLeasedRefs.end(); ++it) + for (const auto& leasedRef : mCell->mLeasedRefs) { - ESM::CellRef &ref = const_cast(it->first); - bool deleted = it->second; + ESM::CellRef &ref = const_cast(leasedRef.first); + bool deleted = leasedRef.second; loadRef (ref, deleted, refNumToID); } @@ -807,11 +804,10 @@ namespace MWWorld writeReferenceCollection (writer, mWeapons); writeReferenceCollection (writer, mBodyParts); - for (MovedRefTracker::const_iterator it = mMovedToAnotherCell.begin(); it != mMovedToAnotherCell.end(); ++it) + for (const auto& [base, store] : mMovedToAnotherCell) { - LiveCellRefBase* base = it->first; ESM::RefNum refNum = base->mRef.getRefNum(); - ESM::CellId movedTo = it->second->getCell()->getCellId(); + ESM::CellId movedTo = store->getCell()->getCellId(); refNum.save(writer, true, "MVRF"); movedTo.save(writer); @@ -1138,9 +1134,9 @@ namespace MWWorld updateRechargingItems(); mRechargingItemsUpToDate = true; } - for (TRechargingItems::iterator it = mRechargingItems.begin(); it != mRechargingItems.end(); ++it) + for (const auto& [item, charge] : mRechargingItems) { - MWMechanics::rechargeItem(it->first, it->second, duration); + MWMechanics::rechargeItem(item, charge, duration); } } @@ -1148,38 +1144,22 @@ namespace MWWorld { mRechargingItems.clear(); - for (CellRefList::List::iterator it (mWeapons.mList.begin()); it!=mWeapons.mList.end(); ++it) + const auto update = [this](auto& list) { - Ptr ptr = getCurrentPtr(&*it); - if (!ptr.isEmpty() && ptr.getRefData().getCount() > 0) + for (auto & item : list) { - checkItem(ptr); + Ptr ptr = getCurrentPtr(&item); + if (!ptr.isEmpty() && ptr.getRefData().getCount() > 0) + { + checkItem(ptr); + } } - } - for (CellRefList::List::iterator it (mArmors.mList.begin()); it!=mArmors.mList.end(); ++it) - { - Ptr ptr = getCurrentPtr(&*it); - if (!ptr.isEmpty() && ptr.getRefData().getCount() > 0) - { - checkItem(ptr); - } - } - for (CellRefList::List::iterator it (mClothes.mList.begin()); it!=mClothes.mList.end(); ++it) - { - Ptr ptr = getCurrentPtr(&*it); - if (!ptr.isEmpty() && ptr.getRefData().getCount() > 0) - { - checkItem(ptr); - } - } - for (CellRefList::List::iterator it (mBooks.mList.begin()); it!=mBooks.mList.end(); ++it) - { - Ptr ptr = getCurrentPtr(&*it); - if (!ptr.isEmpty() && ptr.getRefData().getCount() > 0) - { - checkItem(ptr); - } - } + }; + + update(mWeapons.mList); + update(mArmors.mList); + update(mClothes.mList); + update(mBooks.mList); } void MWWorld::CellStore::checkItem(Ptr ptr) diff --git a/apps/openmw/mwworld/store.cpp b/apps/openmw/mwworld/store.cpp index e9895eb083..8753a7173b 100644 --- a/apps/openmw/mwworld/store.cpp +++ b/apps/openmw/mwworld/store.cpp @@ -621,20 +621,15 @@ namespace MWWorld void Store::setUp() { - typedef DynamicExt::iterator ExtIterator; - typedef std::map::iterator IntIterator; - mSharedInt.clear(); mSharedInt.reserve(mInt.size()); - for (IntIterator it = mInt.begin(); it != mInt.end(); ++it) { - mSharedInt.push_back(&(it->second)); - } + for (auto & [_, cell] : mInt) + mSharedInt.push_back(&cell); mSharedExt.clear(); mSharedExt.reserve(mExt.size()); - for (ExtIterator it = mExt.begin(); it != mExt.end(); ++it) { - mSharedExt.push_back(&(it->second)); - } + for (auto & [_, cell] : mExt) + mSharedExt.push_back(&cell); } RecordId Store::load(ESM::ESMReader &esm) { @@ -1050,18 +1045,13 @@ namespace MWWorld { // DialInfos marked as deleted are kept during the loading phase, so that the linked list // structure is kept intact for inserting further INFOs. Delete them now that loading is done. - for (Static::iterator it = mStatic.begin(); it != mStatic.end(); ++it) - { - ESM::Dialogue& dial = it->second; + for (auto & [_, dial] : mStatic) dial.clearDeletedInfos(); - } mShared.clear(); mShared.reserve(mStatic.size()); - std::map::iterator it = mStatic.begin(); - for (; it != mStatic.end(); ++it) { - mShared.push_back(&(it->second)); - } + for (auto & [_, dial] : mStatic) + mShared.push_back(&dial); } template <>