diff --git a/apps/openmw/mwbase/world.hpp b/apps/openmw/mwbase/world.hpp index 4737a0e222..c78bd20537 100644 --- a/apps/openmw/mwbase/world.hpp +++ b/apps/openmw/mwbase/world.hpp @@ -486,9 +486,8 @@ namespace MWBase virtual void castSpell (const MWWorld::Ptr& actor) = 0; - virtual void launchMagicBolt (const std::vector& projectileIDs, const std::vector& sounds, const std::string& spellId, - float speed, bool stack, const ESM::EffectList& effects, - const MWWorld::Ptr& caster, const std::string& sourceName, const osg::Vec3f& fallbackDirection) = 0; + virtual void launchMagicBolt (const std::string& spellId, bool stack, const ESM::EffectList& effects, + const MWWorld::Ptr& caster, const std::string& sourceName, const osg::Vec3f& fallbackDirection) = 0; virtual void launchProjectile (MWWorld::Ptr actor, MWWorld::ConstPtr projectile, const osg::Vec3f& worldPos, const osg::Quat& orient, MWWorld::Ptr bow, float speed, float attackStrength) = 0; diff --git a/apps/openmw/mwmechanics/spellcasting.cpp b/apps/openmw/mwmechanics/spellcasting.cpp index 8736379f22..f1c9204210 100644 --- a/apps/openmw/mwmechanics/spellcasting.cpp +++ b/apps/openmw/mwmechanics/spellcasting.cpp @@ -285,64 +285,10 @@ namespace MWMechanics /// Get projectile properties (model, sound and speed) for a spell with the given effects and launch. /// If \a model is empty, the spell has no ranged effects and should not spawn a projectile. - void CastSpell::getProjectileInfoAndLaunch (const ESM::EffectList& effects) - { - // All projectiles should use the same speed. From observations in the - // original engine, this seems to be the average of the constituent effects. - // First we get this average speed. - float speed = 0; - int count = 0; - for (std::vector::const_iterator iter (effects.mList.begin()); - iter!=effects.mList.end(); ++iter) - { - const ESM::MagicEffect *magicEffect = MWBase::Environment::get().getWorld()->getStore().get().find ( - iter->mEffectID); - speed += magicEffect->mData.mSpeed; - count++; - } - - if (count != 0) - speed /= count; - - std::vector projectileIDs; - std::vector sounds; - ESM::EffectList projectileEffects; - + void CastSpell::launchMagicBolt (const ESM::EffectList& effects) + { osg::Vec3f fallbackDirection (0,1,0); - for (std::vector::const_iterator iter (effects.mList.begin()); - iter!=effects.mList.end(); ++iter) - { - if (iter->mRange != ESM::RT_Target) - continue; - - const ESM::MagicEffect *magicEffect = MWBase::Environment::get().getWorld()->getStore().get().find ( - iter->mEffectID); - - if (magicEffect->mBolt.empty()) - projectileIDs.push_back("VFX_DefaultBolt"); - else - projectileIDs.push_back(magicEffect->mBolt); - - static const std::string schools[] = { - "alteration", "conjuration", "destruction", "illusion", "mysticism", "restoration" - }; - if (!magicEffect->mBoltSound.empty()) - sounds.push_back(magicEffect->mBoltSound); - else - sounds.push_back(schools[magicEffect->mData.mSchool] + " bolt"); - projectileEffects.mList.push_back(*iter); - } - - if (projectileEffects.mList.size() > 1) // insert a VFX_Multiple projectile if there are multiple projectile effects - { - std::ostringstream ID; - ID << "VFX_Multiple" << projectileEffects.mList.size(); - std::vector::iterator it; - it = projectileIDs.begin(); - it = projectileIDs.insert(it, ID.str()); - } - // Fall back to a "caster to target" direction if we have no other means of determining it // (e.g. when cast by a non-actor) if (!mTarget.isEmpty()) @@ -350,9 +296,8 @@ namespace MWMechanics osg::Vec3f(mTarget.getRefData().getPosition().asVec3())- osg::Vec3f(mCaster.getRefData().getPosition().asVec3()); - if (!projectileEffects.mList.empty()) - MWBase::Environment::get().getWorld()->launchMagicBolt(projectileIDs, sounds, mId, speed, - false, projectileEffects, mCaster, mSourceName, fallbackDirection); + MWBase::Environment::get().getWorld()->launchMagicBolt(mId, false, effects, + mCaster, mSourceName, fallbackDirection); } void CastSpell::inflict(const MWWorld::Ptr &target, const MWWorld::Ptr &caster, @@ -823,7 +768,7 @@ namespace MWMechanics } if (launchProjectile) - getProjectileInfoAndLaunch(enchantment->mEffects); + launchMagicBolt(enchantment->mEffects); else if (!mTarget.isEmpty()) inflict(mTarget, mCaster, enchantment->mEffects, ESM::RT_Target); @@ -906,7 +851,7 @@ namespace MWMechanics if (!mTarget.isEmpty()) inflict(mTarget, mCaster, spell->mEffects, ESM::RT_Touch); - getProjectileInfoAndLaunch(spell->mEffects); + launchMagicBolt(spell->mEffects); return true; } diff --git a/apps/openmw/mwmechanics/spellcasting.hpp b/apps/openmw/mwmechanics/spellcasting.hpp index e300b18189..85277401f9 100644 --- a/apps/openmw/mwmechanics/spellcasting.hpp +++ b/apps/openmw/mwmechanics/spellcasting.hpp @@ -94,9 +94,8 @@ namespace MWMechanics void playSpellCastingEffects(const std::string &spellid); - /// Get the models, sounds and speeds for all projectiles - /// in the given effects, and launch them. - void getProjectileInfoAndLaunch (const ESM::EffectList& effects); + /// Launch a bolt with the given effects. + void launchMagicBolt (const ESM::EffectList& effects); /// @note \a target can be any type of object, not just actors. /// @note \a caster can be any type of object, or even an empty object. diff --git a/apps/openmw/mwworld/projectilemanager.cpp b/apps/openmw/mwworld/projectilemanager.cpp index ffb2063c20..509cee80c5 100644 --- a/apps/openmw/mwworld/projectilemanager.cpp +++ b/apps/openmw/mwworld/projectilemanager.cpp @@ -35,6 +35,55 @@ #include "../mwphysics/physicssystem.hpp" +namespace +{ + ESM::EffectList getMagicBoltData(std::vector& projectileIDs, std::vector& sounds, float& speed, const ESM::EffectList& effects) + { + int count = 0; + ESM::EffectList projectileEffects; + for (std::vector::const_iterator iter (effects.mList.begin()); + iter!=effects.mList.end(); ++iter) + { + const ESM::MagicEffect *magicEffect = MWBase::Environment::get().getWorld()->getStore().get().find ( + iter->mEffectID); + + // All the projectiles should use the same speed. From observations in the + // original engine, this seems to be the average of the constituent effects. + speed += magicEffect->mData.mSpeed; + count++; + + if (iter->mRange != ESM::RT_Target) + continue; + + if (magicEffect->mBolt.empty()) + projectileIDs.push_back("VFX_DefaultBolt"); + else + projectileIDs.push_back(magicEffect->mBolt); + + static const std::string schools[] = { + "alteration", "conjuration", "destruction", "illusion", "mysticism", "restoration" + }; + if (!magicEffect->mBoltSound.empty()) + sounds.push_back(magicEffect->mBoltSound); + else + sounds.push_back(schools[magicEffect->mData.mSchool] + " bolt"); + projectileEffects.mList.push_back(*iter); + } + + if (count != 0) + speed /= count; + + if (projectileEffects.mList.size() > 1) // insert a VFX_Multiple projectile if there are multiple projectile effects + { + std::ostringstream ID; + ID << "VFX_Multiple" << effects.mList.size(); + std::vector::iterator it; + it = projectileIDs.begin(); + it = projectileIDs.insert(it, ID.str()); + } + return projectileEffects; + } +} namespace MWWorld { @@ -126,10 +175,8 @@ namespace MWWorld state.mEffectAnimationTime->addTime(duration); } - void ProjectileManager::launchMagicBolt(const std::vector &projectileIDs, const std::vector &sounds, - const std::string &spellId, float speed, bool stack, - const ESM::EffectList &effects, const Ptr &caster, const std::string &sourceName, - const osg::Vec3f& fallbackDirection) + void ProjectileManager::launchMagicBolt(const std::string &spellId, bool stack, const ESM::EffectList &effects, const Ptr &caster, + const std::string &sourceName, const osg::Vec3f& fallbackDirection) { osg::Vec3f pos = caster.getRefData().getPosition().asVec3(); if (caster.getClass().isActor()) @@ -157,23 +204,23 @@ namespace MWWorld state.mActorId = caster.getClass().getCreatureStats(caster).getActorId(); else state.mActorId = -1; - state.mSpeed = speed; state.mStack = stack; - state.mIdMagic = projectileIDs; - state.mSoundIds = sounds; - // Should have already had non-projectile effects removed - state.mEffects = effects; + state.mEffects = getMagicBoltData(state.mIdMagic, state.mSoundIds, state.mSpeed, effects); - MWWorld::ManualRef ref(MWBase::Environment::get().getWorld()->getStore(), projectileIDs.at(0)); + // Non-projectile should have been removed by getMagicBoltData + if (state.mEffects.mList.size() == 0) + return; + + MWWorld::ManualRef ref(MWBase::Environment::get().getWorld()->getStore(), state.mIdMagic.at(0)); MWWorld::Ptr ptr = ref.getPtr(); createModel(state, ptr.getClass().getModel(ptr), pos, orient, true); MWBase::SoundManager *sndMgr = MWBase::Environment::get().getSoundManager(); - for (size_t it = 0; it != sounds.size(); it++) + for (size_t it = 0; it != state.mSoundIds.size(); it++) { - state.mSounds.push_back(sndMgr->playSound3D(pos, sounds.at(it), 1.0f, 1.0f, MWBase::SoundManager::Play_TypeSfx, MWBase::SoundManager::Play_Loop)); + state.mSounds.push_back(sndMgr->playSound3D(pos, state.mSoundIds.at(it), 1.0f, 1.0f, MWBase::SoundManager::Play_TypeSfx, MWBase::SoundManager::Play_Loop)); } mMagicBolts.push_back(state); @@ -437,40 +484,8 @@ namespace MWWorld state.mIdMagic.push_back(esm.mId); state.mSpellId = esm.mSpellId; state.mActorId = esm.mActorId; - state.mSpeed = esm.mSpeed; state.mStack = esm.mStack; - state.mEffects = esm.mEffects; - - std::string projectileID; - std::vector projectileIDs; - - if (esm.mEffects.mList.size() > 1) - { - std::ostringstream ID; - ID << "VFX_Multiple" << esm.mEffects.mList.size(); - state.mIdMagic.push_back(ID.str()); - } - - for (std::vector::const_iterator iter (esm.mEffects.mList.begin()); - iter != esm.mEffects.mList.end(); ++iter) - { - const ESM::MagicEffect *magicEffect = MWBase::Environment::get().getWorld()->getStore().get().find ( - iter->mEffectID); - - projectileID = magicEffect->mBolt; - if (projectileID.empty()) - projectileID = "VFX_DefaultBolt"; - state.mIdMagic.push_back(projectileID); - - static const std::string schools[] = { - "alteration", "conjuration", "destruction", "illusion", "mysticism", "restoration" - }; - - if (!magicEffect->mBoltSound.empty()) - state.mSoundIds.push_back(magicEffect->mBoltSound); - else - state.mSoundIds.push_back(schools[magicEffect->mData.mSchool] + " bolt"); - } + state.mEffects = getMagicBoltData(state.mIdMagic, state.mSoundIds, state.mSpeed, esm.mEffects); std::string model; try diff --git a/apps/openmw/mwworld/projectilemanager.hpp b/apps/openmw/mwworld/projectilemanager.hpp index 46a6b10de1..55ce0cd12b 100644 --- a/apps/openmw/mwworld/projectilemanager.hpp +++ b/apps/openmw/mwworld/projectilemanager.hpp @@ -49,9 +49,8 @@ namespace MWWorld MWRender::RenderingManager* rendering, MWPhysics::PhysicsSystem* physics); /// If caster is an actor, the actor's facing orientation is used. Otherwise fallbackDirection is used. - void launchMagicBolt (const std::vector& projectileIDs, const std::vector &sounds, const std::string &spellId, - float speed, bool stack, const ESM::EffectList& effects, - const MWWorld::Ptr& caster, const std::string& sourceName, const osg::Vec3f& fallbackDirection); + void launchMagicBolt (const std::string &spellId, bool stack, const ESM::EffectList& effects, + const MWWorld::Ptr& caster, const std::string& sourceName, const osg::Vec3f& fallbackDirection); void launchProjectile (MWWorld::Ptr actor, MWWorld::ConstPtr projectile, const osg::Vec3f& pos, const osg::Quat& orient, MWWorld::Ptr bow, float speed, float attackStrength); diff --git a/apps/openmw/mwworld/worldimp.cpp b/apps/openmw/mwworld/worldimp.cpp index cf5845adf5..4cb75b8c67 100644 --- a/apps/openmw/mwworld/worldimp.cpp +++ b/apps/openmw/mwworld/worldimp.cpp @@ -2705,11 +2705,10 @@ namespace MWWorld mProjectileManager->launchProjectile(actor, projectile, worldPos, orient, bow, speed, attackStrength); } - void World::launchMagicBolt (const std::vector &projectileIDs, const std::vector &sounds, const std::string &spellId, - float speed, bool stack, const ESM::EffectList& effects, - const MWWorld::Ptr& caster, const std::string& sourceName, const osg::Vec3f& fallbackDirection) + void World::launchMagicBolt (const std::string &spellId, bool stack, const ESM::EffectList& effects, + const MWWorld::Ptr& caster, const std::string& sourceName, const osg::Vec3f& fallbackDirection) { - mProjectileManager->launchMagicBolt(projectileIDs, sounds, spellId, speed, stack, effects, caster, sourceName, fallbackDirection); + mProjectileManager->launchMagicBolt(spellId, stack, effects, caster, sourceName, fallbackDirection); } const std::vector& World::getContentFiles() const diff --git a/apps/openmw/mwworld/worldimp.hpp b/apps/openmw/mwworld/worldimp.hpp index f26e2b9c04..8774e549fd 100644 --- a/apps/openmw/mwworld/worldimp.hpp +++ b/apps/openmw/mwworld/worldimp.hpp @@ -594,9 +594,8 @@ namespace MWWorld */ virtual void castSpell (const MWWorld::Ptr& actor); - virtual void launchMagicBolt (const std::vector& projectileIDs, const std::vector& sounds, const std::string& spellId, - float speed, bool stack, const ESM::EffectList& effects, - const MWWorld::Ptr& caster, const std::string& sourceName, const osg::Vec3f& fallbackDirection); + virtual void launchMagicBolt (const std::string& spellId, bool stack, const ESM::EffectList& effects, + const MWWorld::Ptr& caster, const std::string& sourceName, const osg::Vec3f& fallbackDirection); virtual void launchProjectile (MWWorld::Ptr actor, MWWorld::ConstPtr projectile, const osg::Vec3f& worldPos, const osg::Quat& orient, MWWorld::Ptr bow, float speed, float attackStrength);