From 0b5f5351b5d4156f26f8a240b4db38f100c06a96 Mon Sep 17 00:00:00 2001 From: scrawl Date: Thu, 14 Nov 2013 13:30:48 +0100 Subject: [PATCH] Fix continuous FX getting removed instantly --- apps/openmw/mwmechanics/actors.cpp | 7 +++++ apps/openmw/mwmechanics/character.cpp | 2 -- apps/openmw/mwmechanics/character.hpp | 5 ++-- apps/openmw/mwmechanics/spells.cpp | 4 ++- apps/openmw/mwrender/animation.cpp | 3 ++- apps/openmw/mwrender/animation.hpp | 1 + apps/openmw/mwworld/inventorystore.cpp | 36 ++++++++++++++------------ 7 files changed, 36 insertions(+), 22 deletions(-) diff --git a/apps/openmw/mwmechanics/actors.cpp b/apps/openmw/mwmechanics/actors.cpp index 6cb0dc55a3..3d52ce8e69 100644 --- a/apps/openmw/mwmechanics/actors.cpp +++ b/apps/openmw/mwmechanics/actors.cpp @@ -374,6 +374,13 @@ namespace MWMechanics if(!paused) { + // Note: we need to do this before any of the animations are updated. + // Reaching the text keys may trigger Hit / Spellcast (and as such, particles), + // so updating VFX immediately after that would just remove the particle effects instantly. + // There needs to be a magic effect update in between. + for(PtrControllerMap::iterator iter(mActors.begin());iter != mActors.end();++iter) + iter->second->updateContinuousVfx(); + for(PtrControllerMap::iterator iter(mActors.begin());iter != mActors.end();++iter) iter->second->update(duration); } diff --git a/apps/openmw/mwmechanics/character.cpp b/apps/openmw/mwmechanics/character.cpp index 0a13f7c8f3..94aceba381 100644 --- a/apps/openmw/mwmechanics/character.cpp +++ b/apps/openmw/mwmechanics/character.cpp @@ -716,8 +716,6 @@ void CharacterController::update(float duration) const MWWorld::Class &cls = MWWorld::Class::get(mPtr); Ogre::Vector3 movement(0.0f); - updateContinuousVfx(); - if(!cls.isActor()) { if(mAnimQueue.size() > 1) diff --git a/apps/openmw/mwmechanics/character.hpp b/apps/openmw/mwmechanics/character.hpp index c82b29b479..0b55534a60 100644 --- a/apps/openmw/mwmechanics/character.hpp +++ b/apps/openmw/mwmechanics/character.hpp @@ -173,12 +173,13 @@ class CharacterController bool updateNpcState(bool onground, bool inwater, bool isrunning, bool sneak); - void updateContinuousVfx(); - public: CharacterController(const MWWorld::Ptr &ptr, MWRender::Animation *anim); virtual ~CharacterController(); + // Be careful when to call this, see comment in Actors + void updateContinuousVfx(); + void updatePtr(const MWWorld::Ptr &ptr); void update(float duration); diff --git a/apps/openmw/mwmechanics/spells.cpp b/apps/openmw/mwmechanics/spells.cpp index caf3c64818..df1f6a3182 100644 --- a/apps/openmw/mwmechanics/spells.cpp +++ b/apps/openmw/mwmechanics/spells.cpp @@ -32,7 +32,7 @@ namespace MWMechanics std::vector random; random.resize(spell->mEffects.mList.size()); - for (int i=0; i (std::rand()) / RAND_MAX; mSpells.insert (std::make_pair (spellId, random)); } @@ -51,6 +51,8 @@ namespace MWMechanics MagicEffects Spells::getMagicEffects() const { + // TODO: These are recalculated every frame, no need to do that + MagicEffects effects; for (TIterator iter = mSpells.begin(); iter!=mSpells.end(); ++iter) diff --git a/apps/openmw/mwrender/animation.cpp b/apps/openmw/mwrender/animation.cpp index d92912fa95..cc92e62489 100644 --- a/apps/openmw/mwrender/animation.cpp +++ b/apps/openmw/mwrender/animation.cpp @@ -998,7 +998,7 @@ void Animation::addEffect(const std::string &model, int effectId, bool loop, con { // Early out if we already have this effect for (std::vector::iterator it = mEffects.begin(); it != mEffects.end(); ++it) - if (it->mEffectId == effectId) + if (it->mLoop && loop && it->mEffectId == effectId && it->mBoneName == bonename) return; EffectParams params; @@ -1006,6 +1006,7 @@ void Animation::addEffect(const std::string &model, int effectId, bool loop, con params.mObjects = NifOgre::Loader::createObjects(mInsert, model); params.mLoop = loop; params.mEffectId = effectId; + params.mBoneName = bonename; for(size_t i = 0;i < params.mObjects.mControllers.size();i++) { diff --git a/apps/openmw/mwrender/animation.hpp b/apps/openmw/mwrender/animation.hpp index 11adf0c588..b1572b6a16 100644 --- a/apps/openmw/mwrender/animation.hpp +++ b/apps/openmw/mwrender/animation.hpp @@ -115,6 +115,7 @@ protected: NifOgre::ObjectList mObjects; int mEffectId; bool mLoop; + std::string mBoneName; }; std::vector mEffects; diff --git a/apps/openmw/mwworld/inventorystore.cpp b/apps/openmw/mwworld/inventorystore.cpp index 7a5e59f36d..d032b26139 100644 --- a/apps/openmw/mwworld/inventorystore.cpp +++ b/apps/openmw/mwworld/inventorystore.cpp @@ -308,25 +308,29 @@ void MWWorld::InventoryStore::updateMagicEffects(const Ptr& actor) // so it doesn't really matter if both items will get the same magnitude. *Extreme* edge case. mPermanentMagicEffectMagnitudes[(**iter).getCellRef().mRefID] = random; - // Only the sound of the first effect plays - if (effectIt == enchantment.mEffects.mList.begin()) + // TODO: What do we do if no animation yet? + if (MWBase::Environment::get().getWorld()->getAnimation(actor)) { - static const std::string schools[] = { - "alteration", "conjuration", "destruction", "illusion", "mysticism", "restoration" - }; + // Only the sound of the first effect plays + if (effectIt == enchantment.mEffects.mList.begin()) + { + static const std::string schools[] = { + "alteration", "conjuration", "destruction", "illusion", "mysticism", "restoration" + }; - MWBase::SoundManager *sndMgr = MWBase::Environment::get().getSoundManager(); - if(!magicEffect->mHitSound.empty()) - sndMgr->playSound3D(actor, magicEffect->mHitSound, 1.0f, 1.0f); - else - sndMgr->playSound3D(actor, schools[magicEffect->mData.mSchool]+" hit", 1.0f, 1.0f); - } + MWBase::SoundManager *sndMgr = MWBase::Environment::get().getSoundManager(); + if(!magicEffect->mHitSound.empty()) + sndMgr->playSound3D(actor, magicEffect->mHitSound, 1.0f, 1.0f); + else + sndMgr->playSound3D(actor, schools[magicEffect->mData.mSchool]+" hit", 1.0f, 1.0f); + } - if (!magicEffect->mHit.empty()) - { - const ESM::Static* castStatic = MWBase::Environment::get().getWorld()->getStore().get().find (magicEffect->mHit); - bool loop = magicEffect->mData.mFlags & ESM::MagicEffect::ContinuousVfx; - MWBase::Environment::get().getWorld()->getAnimation(actor)->addEffect("meshes\\" + castStatic->mModel, magicEffect->mIndex, loop, ""); + if (!magicEffect->mHit.empty()) + { + const ESM::Static* castStatic = MWBase::Environment::get().getWorld()->getStore().get().find (magicEffect->mHit); + bool loop = magicEffect->mData.mFlags & ESM::MagicEffect::ContinuousVfx; + MWBase::Environment::get().getWorld()->getAnimation(actor)->addEffect("meshes\\" + castStatic->mModel, magicEffect->mIndex, loop, ""); + } } }