forked from mirror/openmw-tes3mp
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