Shoot projectiles of spells with multiple effects

This commit is contained in:
Allofich 2016-08-31 19:03:28 +09:00
parent 446c0a4fa8
commit f1a18027f2
2 changed files with 50 additions and 65 deletions

View file

@ -27,41 +27,6 @@
#include "npcstats.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
{
@ -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,
const ESM::EffectList &effects, ESM::RangeType range, bool reflected, bool exploded)
{
@ -785,17 +794,7 @@ namespace MWMechanics
}
if (launchProjectile)
{
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));
}
getProjectileInfoAndLaunch(enchantment->mEffects);
else if (!mTarget.isEmpty())
inflict(mTarget, mCaster, enchantment->mEffects, ESM::RT_Target);
@ -876,27 +875,9 @@ namespace MWMechanics
inflict(mCaster, mCaster, spell->mEffects, ESM::RT_Self);
if (!mTarget.isEmpty())
{
inflict(mTarget, mCaster, spell->mEffects, ESM::RT_Touch);
}
std::string projectileModel;
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);
}
getProjectileInfoAndLaunch(spell->mEffects);
return true;
}

View file

@ -94,6 +94,10 @@ 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);
/// @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.
void inflict (const MWWorld::Ptr& target, const MWWorld::Ptr& caster,