mirror of
https://gitlab.com/OpenMW/openmw.git
synced 2025-02-12 18:40:22 +00:00
Consolidations and cleanup for multi-effect spells
This commit is contained in:
parent
dbd7c038b2
commit
f8270f6bd5
@ -486,9 +486,8 @@ namespace MWBase
|
|||||||
|
|
||||||
virtual void castSpell (const MWWorld::Ptr& actor) = 0;
|
virtual void castSpell (const MWWorld::Ptr& actor) = 0;
|
||||||
|
|
||||||
virtual void launchMagicBolt (const std::vector<std::string>& projectileIDs, const std::vector<std::string>& sounds, const std::string& spellId,
|
virtual void launchMagicBolt (const std::string& spellId, bool stack, const ESM::EffectList& effects,
|
||||||
float speed, bool stack, const ESM::EffectList& effects,
|
const MWWorld::Ptr& caster, const std::string& sourceName, const osg::Vec3f& fallbackDirection) = 0;
|
||||||
const MWWorld::Ptr& caster, const std::string& sourceName, const osg::Vec3f& fallbackDirection) = 0;
|
|
||||||
virtual void launchProjectile (MWWorld::Ptr actor, MWWorld::ConstPtr projectile,
|
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;
|
const osg::Vec3f& worldPos, const osg::Quat& orient, MWWorld::Ptr bow, float speed, float attackStrength) = 0;
|
||||||
|
|
||||||
|
@ -285,64 +285,10 @@ namespace MWMechanics
|
|||||||
|
|
||||||
/// Get projectile properties (model, sound and speed) for a spell with the given effects and launch.
|
/// 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.
|
/// If \a model is empty, the spell has no ranged effects and should not spawn a projectile.
|
||||||
void CastSpell::getProjectileInfoAndLaunch (const ESM::EffectList& effects)
|
void CastSpell::launchMagicBolt (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<ESM::ENAMstruct>::const_iterator iter (effects.mList.begin());
|
|
||||||
iter!=effects.mList.end(); ++iter)
|
|
||||||
{
|
|
||||||
const ESM::MagicEffect *magicEffect = MWBase::Environment::get().getWorld()->getStore().get<ESM::MagicEffect>().find (
|
|
||||||
iter->mEffectID);
|
|
||||||
speed += magicEffect->mData.mSpeed;
|
|
||||||
count++;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (count != 0)
|
|
||||||
speed /= count;
|
|
||||||
|
|
||||||
std::vector<std::string> projectileIDs;
|
|
||||||
std::vector<std::string> sounds;
|
|
||||||
ESM::EffectList projectileEffects;
|
|
||||||
|
|
||||||
osg::Vec3f fallbackDirection (0,1,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);
|
|
||||||
|
|
||||||
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<std::string>::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
|
// 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)
|
// (e.g. when cast by a non-actor)
|
||||||
if (!mTarget.isEmpty())
|
if (!mTarget.isEmpty())
|
||||||
@ -350,9 +296,8 @@ namespace MWMechanics
|
|||||||
osg::Vec3f(mTarget.getRefData().getPosition().asVec3())-
|
osg::Vec3f(mTarget.getRefData().getPosition().asVec3())-
|
||||||
osg::Vec3f(mCaster.getRefData().getPosition().asVec3());
|
osg::Vec3f(mCaster.getRefData().getPosition().asVec3());
|
||||||
|
|
||||||
if (!projectileEffects.mList.empty())
|
MWBase::Environment::get().getWorld()->launchMagicBolt(mId, false, effects,
|
||||||
MWBase::Environment::get().getWorld()->launchMagicBolt(projectileIDs, sounds, mId, speed,
|
mCaster, mSourceName, fallbackDirection);
|
||||||
false, projectileEffects, 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,
|
||||||
@ -823,7 +768,7 @@ namespace MWMechanics
|
|||||||
}
|
}
|
||||||
|
|
||||||
if (launchProjectile)
|
if (launchProjectile)
|
||||||
getProjectileInfoAndLaunch(enchantment->mEffects);
|
launchMagicBolt(enchantment->mEffects);
|
||||||
else if (!mTarget.isEmpty())
|
else if (!mTarget.isEmpty())
|
||||||
inflict(mTarget, mCaster, enchantment->mEffects, ESM::RT_Target);
|
inflict(mTarget, mCaster, enchantment->mEffects, ESM::RT_Target);
|
||||||
|
|
||||||
@ -906,7 +851,7 @@ namespace MWMechanics
|
|||||||
if (!mTarget.isEmpty())
|
if (!mTarget.isEmpty())
|
||||||
inflict(mTarget, mCaster, spell->mEffects, ESM::RT_Touch);
|
inflict(mTarget, mCaster, spell->mEffects, ESM::RT_Touch);
|
||||||
|
|
||||||
getProjectileInfoAndLaunch(spell->mEffects);
|
launchMagicBolt(spell->mEffects);
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
@ -94,9 +94,8 @@ namespace MWMechanics
|
|||||||
|
|
||||||
void playSpellCastingEffects(const std::string &spellid);
|
void playSpellCastingEffects(const std::string &spellid);
|
||||||
|
|
||||||
/// Get the models, sounds and speeds for all projectiles
|
/// Launch a bolt with the given effects.
|
||||||
/// in the given effects, and launch them.
|
void launchMagicBolt (const ESM::EffectList& effects);
|
||||||
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.
|
||||||
|
@ -35,6 +35,55 @@
|
|||||||
|
|
||||||
#include "../mwphysics/physicssystem.hpp"
|
#include "../mwphysics/physicssystem.hpp"
|
||||||
|
|
||||||
|
namespace
|
||||||
|
{
|
||||||
|
ESM::EffectList getMagicBoltData(std::vector<std::string>& projectileIDs, std::vector<std::string>& sounds, float& speed, const ESM::EffectList& effects)
|
||||||
|
{
|
||||||
|
int count = 0;
|
||||||
|
ESM::EffectList projectileEffects;
|
||||||
|
for (std::vector<ESM::ENAMstruct>::const_iterator iter (effects.mList.begin());
|
||||||
|
iter!=effects.mList.end(); ++iter)
|
||||||
|
{
|
||||||
|
const ESM::MagicEffect *magicEffect = MWBase::Environment::get().getWorld()->getStore().get<ESM::MagicEffect>().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<std::string>::iterator it;
|
||||||
|
it = projectileIDs.begin();
|
||||||
|
it = projectileIDs.insert(it, ID.str());
|
||||||
|
}
|
||||||
|
return projectileEffects;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
namespace MWWorld
|
namespace MWWorld
|
||||||
{
|
{
|
||||||
@ -126,10 +175,8 @@ namespace MWWorld
|
|||||||
state.mEffectAnimationTime->addTime(duration);
|
state.mEffectAnimationTime->addTime(duration);
|
||||||
}
|
}
|
||||||
|
|
||||||
void ProjectileManager::launchMagicBolt(const std::vector<std::string> &projectileIDs, const std::vector<std::string> &sounds,
|
void ProjectileManager::launchMagicBolt(const std::string &spellId, bool stack, const ESM::EffectList &effects, const Ptr &caster,
|
||||||
const std::string &spellId, float speed, bool stack,
|
const std::string &sourceName, const osg::Vec3f& fallbackDirection)
|
||||||
const ESM::EffectList &effects, const Ptr &caster, const std::string &sourceName,
|
|
||||||
const osg::Vec3f& fallbackDirection)
|
|
||||||
{
|
{
|
||||||
osg::Vec3f pos = caster.getRefData().getPosition().asVec3();
|
osg::Vec3f pos = caster.getRefData().getPosition().asVec3();
|
||||||
if (caster.getClass().isActor())
|
if (caster.getClass().isActor())
|
||||||
@ -157,23 +204,23 @@ namespace MWWorld
|
|||||||
state.mActorId = caster.getClass().getCreatureStats(caster).getActorId();
|
state.mActorId = caster.getClass().getCreatureStats(caster).getActorId();
|
||||||
else
|
else
|
||||||
state.mActorId = -1;
|
state.mActorId = -1;
|
||||||
state.mSpeed = speed;
|
|
||||||
state.mStack = stack;
|
state.mStack = stack;
|
||||||
state.mIdMagic = projectileIDs;
|
|
||||||
state.mSoundIds = sounds;
|
|
||||||
|
|
||||||
// Should have already had non-projectile effects removed
|
state.mEffects = getMagicBoltData(state.mIdMagic, state.mSoundIds, state.mSpeed, effects);
|
||||||
state.mEffects = 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();
|
MWWorld::Ptr ptr = ref.getPtr();
|
||||||
|
|
||||||
createModel(state, ptr.getClass().getModel(ptr), pos, orient, true);
|
createModel(state, ptr.getClass().getModel(ptr), pos, orient, true);
|
||||||
|
|
||||||
MWBase::SoundManager *sndMgr = MWBase::Environment::get().getSoundManager();
|
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);
|
mMagicBolts.push_back(state);
|
||||||
@ -437,40 +484,8 @@ namespace MWWorld
|
|||||||
state.mIdMagic.push_back(esm.mId);
|
state.mIdMagic.push_back(esm.mId);
|
||||||
state.mSpellId = esm.mSpellId;
|
state.mSpellId = esm.mSpellId;
|
||||||
state.mActorId = esm.mActorId;
|
state.mActorId = esm.mActorId;
|
||||||
state.mSpeed = esm.mSpeed;
|
|
||||||
state.mStack = esm.mStack;
|
state.mStack = esm.mStack;
|
||||||
state.mEffects = esm.mEffects;
|
state.mEffects = getMagicBoltData(state.mIdMagic, state.mSoundIds, state.mSpeed, esm.mEffects);
|
||||||
|
|
||||||
std::string projectileID;
|
|
||||||
std::vector<std::string> 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<ESM::ENAMstruct>::const_iterator iter (esm.mEffects.mList.begin());
|
|
||||||
iter != esm.mEffects.mList.end(); ++iter)
|
|
||||||
{
|
|
||||||
const ESM::MagicEffect *magicEffect = MWBase::Environment::get().getWorld()->getStore().get<ESM::MagicEffect>().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");
|
|
||||||
}
|
|
||||||
|
|
||||||
std::string model;
|
std::string model;
|
||||||
try
|
try
|
||||||
|
@ -49,9 +49,8 @@ namespace MWWorld
|
|||||||
MWRender::RenderingManager* rendering, MWPhysics::PhysicsSystem* physics);
|
MWRender::RenderingManager* rendering, MWPhysics::PhysicsSystem* physics);
|
||||||
|
|
||||||
/// If caster is an actor, the actor's facing orientation is used. Otherwise fallbackDirection is used.
|
/// If caster is an actor, the actor's facing orientation is used. Otherwise fallbackDirection is used.
|
||||||
void launchMagicBolt (const std::vector<std::string>& projectileIDs, const std::vector<std::string> &sounds, const std::string &spellId,
|
void launchMagicBolt (const std::string &spellId, bool stack, const ESM::EffectList& effects,
|
||||||
float speed, bool stack, const ESM::EffectList& effects,
|
const MWWorld::Ptr& caster, const std::string& sourceName, const osg::Vec3f& fallbackDirection);
|
||||||
const MWWorld::Ptr& caster, const std::string& sourceName, const osg::Vec3f& fallbackDirection);
|
|
||||||
|
|
||||||
void launchProjectile (MWWorld::Ptr actor, MWWorld::ConstPtr projectile,
|
void launchProjectile (MWWorld::Ptr actor, MWWorld::ConstPtr projectile,
|
||||||
const osg::Vec3f& pos, const osg::Quat& orient, MWWorld::Ptr bow, float speed, float attackStrength);
|
const osg::Vec3f& pos, const osg::Quat& orient, MWWorld::Ptr bow, float speed, float attackStrength);
|
||||||
|
@ -2705,11 +2705,10 @@ namespace MWWorld
|
|||||||
mProjectileManager->launchProjectile(actor, projectile, worldPos, orient, bow, speed, attackStrength);
|
mProjectileManager->launchProjectile(actor, projectile, worldPos, orient, bow, speed, attackStrength);
|
||||||
}
|
}
|
||||||
|
|
||||||
void World::launchMagicBolt (const std::vector<std::string> &projectileIDs, const std::vector<std::string> &sounds, const std::string &spellId,
|
void World::launchMagicBolt (const std::string &spellId, bool stack, const ESM::EffectList& effects,
|
||||||
float speed, bool stack, const ESM::EffectList& effects,
|
const MWWorld::Ptr& caster, const std::string& sourceName, const osg::Vec3f& fallbackDirection)
|
||||||
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<std::string>& World::getContentFiles() const
|
const std::vector<std::string>& World::getContentFiles() const
|
||||||
|
@ -594,9 +594,8 @@ namespace MWWorld
|
|||||||
*/
|
*/
|
||||||
virtual void castSpell (const MWWorld::Ptr& actor);
|
virtual void castSpell (const MWWorld::Ptr& actor);
|
||||||
|
|
||||||
virtual void launchMagicBolt (const std::vector<std::string>& projectileIDs, const std::vector<std::string>& sounds, const std::string& spellId,
|
virtual void launchMagicBolt (const std::string& spellId, bool stack, const ESM::EffectList& effects,
|
||||||
float speed, bool stack, const ESM::EffectList& effects,
|
const MWWorld::Ptr& caster, const std::string& sourceName, const osg::Vec3f& fallbackDirection);
|
||||||
const MWWorld::Ptr& caster, const std::string& sourceName, const osg::Vec3f& fallbackDirection);
|
|
||||||
virtual void launchProjectile (MWWorld::Ptr actor, MWWorld::ConstPtr projectile,
|
virtual void launchProjectile (MWWorld::Ptr actor, MWWorld::ConstPtr projectile,
|
||||||
const osg::Vec3f& worldPos, const osg::Quat& orient, MWWorld::Ptr bow, float speed, float attackStrength);
|
const osg::Vec3f& worldPos, const osg::Quat& orient, MWWorld::Ptr bow, float speed, float attackStrength);
|
||||||
|
|
||||||
|
Loading…
x
Reference in New Issue
Block a user