mirror of
				https://github.com/OpenMW/openmw.git
				synced 2025-10-30 02:56:44 +00:00 
			
		
		
		
	Shoot projectiles of spells with multiple effects
This commit is contained in:
		
							parent
							
								
									446c0a4fa8
								
							
						
					
					
						commit
						f1a18027f2
					
				
					 2 changed files with 50 additions and 65 deletions
				
			
		|  | @ -27,41 +27,6 @@ | ||||||
| #include "npcstats.hpp" | #include "npcstats.hpp" | ||||||
| #include "actorutil.hpp" | #include "actorutil.hpp" | ||||||
| 
 | 
 | ||||||
| namespace |  | ||||||
| { |  | ||||||
| 
 |  | ||||||
|     /// Get projectile properties (model, sound and speed) for a spell with the given effects
 |  | ||||||
|     /// If \a model is empty, the spell has no ranged effects and should not spawn a projectile.
 |  | ||||||
|     void getProjectileInfo (const ESM::EffectList& effects, std::string& model, std::string& sound, float& speed) |  | ||||||
|     { |  | ||||||
|         for (std::vector<ESM::ENAMstruct>::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<ESM::MagicEffect>().find ( |  | ||||||
|                 iter->mEffectID); |  | ||||||
| 
 |  | ||||||
|             model = magicEffect->mBolt; |  | ||||||
|             if (model.empty()) |  | ||||||
|                 model = "VFX_DefaultBolt"; |  | ||||||
| 
 |  | ||||||
|             static const std::string schools[] = { |  | ||||||
|                 "alteration", "conjuration", "destruction", "illusion", "mysticism", "restoration" |  | ||||||
|             }; |  | ||||||
|             if (!magicEffect->mBoltSound.empty()) |  | ||||||
|                 sound = magicEffect->mBoltSound; |  | ||||||
|             else |  | ||||||
|                 sound = schools[magicEffect->mData.mSchool] + " bolt"; |  | ||||||
| 
 |  | ||||||
|             speed = magicEffect->mData.mSpeed; |  | ||||||
|             break; |  | ||||||
|         } |  | ||||||
|     } |  | ||||||
| 
 |  | ||||||
| } |  | ||||||
| 
 |  | ||||||
| namespace MWMechanics | namespace MWMechanics | ||||||
| { | { | ||||||
| 
 | 
 | ||||||
|  | @ -317,6 +282,50 @@ 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) | ||||||
|  |     { | ||||||
|  |         std::string model; | ||||||
|  |         std::string sound; | ||||||
|  |         float speed = 0; | ||||||
|  |         osg::Vec3f fallbackDirection (0,1,0); | ||||||
|  |         for (std::vector<ESM::ENAMstruct>::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<ESM::MagicEffect>().find ( | ||||||
|  |                 iter->mEffectID); | ||||||
|  | 
 | ||||||
|  |             model = magicEffect->mBolt; | ||||||
|  |             if (model.empty()) | ||||||
|  |                 model = "VFX_DefaultBolt"; | ||||||
|  | 
 | ||||||
|  |             static const std::string schools[] = { | ||||||
|  |                 "alteration", "conjuration", "destruction", "illusion", "mysticism", "restoration" | ||||||
|  |             }; | ||||||
|  |             if (!magicEffect->mBoltSound.empty()) | ||||||
|  |                 sound = magicEffect->mBoltSound; | ||||||
|  |             else | ||||||
|  |                 sound = schools[magicEffect->mData.mSchool] + " bolt"; | ||||||
|  | 
 | ||||||
|  |             speed = magicEffect->mData.mSpeed; | ||||||
|  | 
 | ||||||
|  |             // 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()) | ||||||
|  |                 fallbackDirection = | ||||||
|  |                    osg::Vec3f(mTarget.getRefData().getPosition().asVec3())- | ||||||
|  |                    osg::Vec3f(mCaster.getRefData().getPosition().asVec3()); | ||||||
|  |              | ||||||
|  |             if (!model.empty()) | ||||||
|  |                 MWBase::Environment::get().getWorld()->launchMagicBolt(model, sound, mId, speed, | ||||||
|  |                                                        false, effects, mCaster, mSourceName, fallbackDirection); | ||||||
|  |         } | ||||||
|  |     } | ||||||
|  | 
 | ||||||
|     void CastSpell::inflict(const MWWorld::Ptr &target, const MWWorld::Ptr &caster, |     void CastSpell::inflict(const MWWorld::Ptr &target, const MWWorld::Ptr &caster, | ||||||
|                             const ESM::EffectList &effects, ESM::RangeType range, bool reflected, bool exploded) |                             const ESM::EffectList &effects, ESM::RangeType range, bool reflected, bool exploded) | ||||||
|     { |     { | ||||||
|  | @ -785,17 +794,7 @@ namespace MWMechanics | ||||||
|         } |         } | ||||||
| 
 | 
 | ||||||
|         if (launchProjectile) |         if (launchProjectile) | ||||||
|         { |             getProjectileInfoAndLaunch(enchantment->mEffects); | ||||||
|             std::string projectileModel; |  | ||||||
|             std::string sound; |  | ||||||
|             float speed = 0; |  | ||||||
|             getProjectileInfo(enchantment->mEffects, projectileModel, sound, speed); |  | ||||||
|             if (!projectileModel.empty()) |  | ||||||
|                 MWBase::Environment::get().getWorld()->launchMagicBolt(projectileModel, sound, mId, speed, |  | ||||||
|                                                                    false, enchantment->mEffects, mCaster, mSourceName, |  | ||||||
|                                                                        // Not needed, enchantments can only be cast by actors
 |  | ||||||
|                                                                        osg::Vec3f(1,0,0)); |  | ||||||
|         } |  | ||||||
|         else if (!mTarget.isEmpty()) |         else if (!mTarget.isEmpty()) | ||||||
|             inflict(mTarget, mCaster, enchantment->mEffects, ESM::RT_Target); |             inflict(mTarget, mCaster, enchantment->mEffects, ESM::RT_Target); | ||||||
| 
 | 
 | ||||||
|  | @ -876,27 +875,9 @@ namespace MWMechanics | ||||||
|         inflict(mCaster, mCaster, spell->mEffects, ESM::RT_Self); |         inflict(mCaster, mCaster, spell->mEffects, ESM::RT_Self); | ||||||
| 
 | 
 | ||||||
|         if (!mTarget.isEmpty()) |         if (!mTarget.isEmpty()) | ||||||
|         { |  | ||||||
|             inflict(mTarget, mCaster, spell->mEffects, ESM::RT_Touch); |             inflict(mTarget, mCaster, spell->mEffects, ESM::RT_Touch); | ||||||
|         } |  | ||||||
| 
 | 
 | ||||||
|         std::string projectileModel; |         getProjectileInfoAndLaunch(spell->mEffects); | ||||||
|         std::string sound; |  | ||||||
|         float speed = 0; |  | ||||||
|         getProjectileInfo(spell->mEffects, projectileModel, sound, speed); |  | ||||||
|         if (!projectileModel.empty()) |  | ||||||
|         { |  | ||||||
|             osg::Vec3f fallbackDirection (0,1,0); |  | ||||||
|             // 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()) |  | ||||||
|                 fallbackDirection = |  | ||||||
|                    osg::Vec3f(mTarget.getRefData().getPosition().asVec3())- |  | ||||||
|                    osg::Vec3f(mCaster.getRefData().getPosition().asVec3()); |  | ||||||
| 
 |  | ||||||
|             MWBase::Environment::get().getWorld()->launchMagicBolt(projectileModel, sound, mId, speed, |  | ||||||
|                        false, spell->mEffects, mCaster, mSourceName, fallbackDirection); |  | ||||||
|         } |  | ||||||
| 
 | 
 | ||||||
|         return true; |         return true; | ||||||
|     } |     } | ||||||
|  |  | ||||||
|  | @ -94,6 +94,10 @@ namespace MWMechanics | ||||||
| 
 | 
 | ||||||
|         void playSpellCastingEffects(const std::string &spellid); |         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); | ||||||
|  | 
 | ||||||
|         /// @note \a target can be any type of object, not just actors.
 |         /// @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.
 |         /// @note \a caster can be any type of object, or even an empty object.
 | ||||||
|         void inflict (const MWWorld::Ptr& target, const MWWorld::Ptr& caster, |         void inflict (const MWWorld::Ptr& target, const MWWorld::Ptr& caster, | ||||||
|  |  | ||||||
		Loading…
	
		Reference in a new issue