Add particles for Cast + Hit. Not looking quite right yet.

This commit is contained in:
scrawl 2013-11-11 23:43:28 +01:00
parent 6f3d737498
commit ffdb91bb21
8 changed files with 113 additions and 19 deletions

View file

@ -17,6 +17,8 @@
#include "../mwbase/world.hpp"
#include "../mwbase/soundmanager.hpp"
#include "../mwrender/animation.hpp"
#include "../mwworld/class.hpp"
#include "creaturestats.hpp"
@ -217,7 +219,8 @@ namespace MWMechanics
else
iter->second = params;
// Play sounds
// Play sounds & particles
bool first=true;
for (std::vector<ESM::ENAMstruct>::const_iterator iter (effects.first.mList.begin());
iter!=effects.first.mList.end(); ++iter)
{
@ -228,17 +231,24 @@ namespace MWMechanics
MWBase::Environment::get().getWorld()->getStore().get<ESM::MagicEffect>().find (
iter->mEffectID);
static const std::string schools[] = {
"alteration", "conjuration", "destruction", "illusion", "mysticism", "restoration"
};
// Only the sound of the first effect plays
if (first)
{
static const std::string schools[] = {
"alteration", "conjuration", "destruction", "illusion", "mysticism", "restoration"
};
MWBase::SoundManager *sndMgr = MWBase::Environment::get().getSoundManager();
if(!magicEffect->mHitSound.empty())
sndMgr->playSound3D(actor, magicEffect->mHitSound, 1.0f, 1.0f);
else
sndMgr->playSound3D(actor, schools[magicEffect->mData.mSchool]+" hit", 1.0f, 1.0f);
MWBase::SoundManager *sndMgr = MWBase::Environment::get().getSoundManager();
if(!magicEffect->mHitSound.empty())
sndMgr->playSound3D(actor, magicEffect->mHitSound, 1.0f, 1.0f);
else
sndMgr->playSound3D(actor, schools[magicEffect->mData.mSchool]+" hit", 1.0f, 1.0f);
}
break;
const ESM::Static* castStatic = MWBase::Environment::get().getWorld()->getStore().get<ESM::Static>().find (magicEffect->mHit);
MWBase::Environment::get().getWorld()->getAnimation(actor)->addEffect("meshes\\" + castStatic->mModel, "");
first = false;
}
mSpellsChanged = true;

View file

@ -512,6 +512,9 @@ bool CharacterController::updateNpcState(bool onground, bool inwater, bool isrun
const ESM::MagicEffect *effect;
effect = store.get<ESM::MagicEffect>().find(effectentry.mEffectID);
const ESM::Static* castStatic = store.get<ESM::Static>().find (effect->mCasting);
mAnimation->addEffect("meshes\\" + castStatic->mModel, "");
switch(effectentry.mRange)
{
case 0: mAttackType = "self"; break;

View file

@ -39,6 +39,15 @@ void Animation::AnimationValue::setValue(Ogre::Real)
{
}
Ogre::Real Animation::EffectAnimationValue::getValue() const
{
return mTime;
}
void Animation::EffectAnimationValue::setValue(Ogre::Real)
{
}
void Animation::destroyObjectList(Ogre::SceneManager *sceneMgr, NifOgre::ObjectList &objects)
{
@ -916,6 +925,25 @@ Ogre::Vector3 Animation::runAnimation(float duration)
mSkelBase->getAllAnimationStates()->_notifyDirty();
}
for (std::vector<NifOgre::ObjectList>::iterator it = mEffects.begin(); it != mEffects.end(); )
{
for(size_t i = 0; i < it->mControllers.size() ;i++)
{
static_cast<EffectAnimationValue*> (it->mControllers[i].getSource().get())->addTime(duration);
it->mControllers[i].update();
}
if (it->mControllers[0].getSource()->getValue() >= it->mMaxControllerLength)
{
destroyObjectList(mInsert->getCreator(), *it);
it = mEffects.erase(it);
}
else
++it;
}
return movement;
}
@ -980,6 +1008,17 @@ void Animation::detachObjectFromBone(Ogre::MovableObject *obj)
mSkelBase->detachObjectFromBone(obj);
}
void Animation::addEffect(const std::string &model, const std::string &bonename)
{
NifOgre::ObjectList list = NifOgre::Loader::createObjects(mInsert, model);
for(size_t i = 0;i < list.mControllers.size();i++)
{
if(list.mControllers[i].getSource().isNull())
list.mControllers[i].setSource(Ogre::SharedPtr<EffectAnimationValue> (new EffectAnimationValue()));
}
mEffects.push_back(list);
}
ObjectAnimation::ObjectAnimation(const MWWorld::Ptr& ptr, const std::string &model)
: Animation(ptr, ptr.getRefData().getBaseNode())

View file

@ -3,6 +3,7 @@
#include <OgreController.h>
#include <OgreVector3.h>
#include <OgreTimer.h>
#include <components/nifogre/ogrenifloader.hpp>
@ -52,6 +53,19 @@ protected:
virtual void setValue(Ogre::Real value);
};
class EffectAnimationValue : public Ogre::ControllerValue<Ogre::Real>
{
private:
float mTime;
public:
EffectAnimationValue() : mTime(0) { }
void addTime(float time) { mTime += time; }
virtual Ogre::Real getValue() const;
virtual void setValue(Ogre::Real value);
};
class NullAnimationValue : public Ogre::ControllerValue<Ogre::Real>
{
@ -95,6 +109,8 @@ protected:
typedef std::map<Ogre::MovableObject*,std::string> ObjectAttachMap;
std::vector<NifOgre::ObjectList> mEffects;
MWWorld::Ptr mPtr;
Camera *mCamera;
@ -114,6 +130,7 @@ protected:
ObjectAttachMap mAttachedObjects;
/* Sets the appropriate animations on the bone groups based on priority.
*/
void resetActiveGroups();
@ -173,6 +190,8 @@ public:
Animation(const MWWorld::Ptr &ptr, Ogre::SceneNode *node);
virtual ~Animation();
void addEffect (const std::string& model, const std::string& bonename = "");
void updatePtr(const MWWorld::Ptr &ptr);
bool hasAnimation(const std::string &anim);

View file

@ -2029,6 +2029,8 @@ namespace MWWorld
MWMechanics::CreatureStats& stats = actor.getClass().getCreatureStats(actor);
stats.setAttackingOrSpell(false);
ESM::EffectList effects;
std::string selectedSpell = stats.getSpells().getSelectedSpell();
std::string sourceName;
if (!selectedSpell.empty())
@ -2094,6 +2096,7 @@ namespace MWWorld
actor.getClass().skillUsageSucceeded(actor, MWMechanics::spellSchoolToSkill(MWMechanics::getSpellSchool(selectedSpell, actor)), 0);
effects = spell->mEffects;
}
InventoryStore& inv = actor.getClass().getInventoryStore(actor);
if (selectedSpell.empty() && inv.getSelectedEnchantItem() != inv.end())
@ -2137,6 +2140,8 @@ namespace MWWorld
}
else
MWBase::Environment::get().getWindowManager()->setSelectedEnchantItem(item); // Set again to show the modified charge
effects = enchantment->mEffects;
}
// Now apply the spell!
@ -2158,7 +2163,6 @@ namespace MWWorld
}
}
// TODO: Launch projectile if there's a Target portion
}
void World::updateAnimParts(const Ptr& actor)