mirror of
https://github.com/OpenMW/openmw.git
synced 2025-01-19 22:53:53 +00:00
Add particles for Cast + Hit. Not looking quite right yet.
This commit is contained in:
parent
6f3d737498
commit
ffdb91bb21
8 changed files with 113 additions and 19 deletions
|
@ -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;
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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())
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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)
|
||||
|
|
|
@ -64,8 +64,8 @@ struct MagicEffect
|
|||
MEDTstruct mData;
|
||||
|
||||
std::string mIcon, mParticle; // Textures
|
||||
std::string mCasting, mHit, mArea; // Statics
|
||||
std::string mBolt; // Weapon
|
||||
std::string mCasting, mHit, mArea; // ESM::Static
|
||||
std::string mBolt; // ESM::Weapon
|
||||
std::string mCastSound, mBoltSound, mHitSound, mAreaSound; // Sounds
|
||||
std::string mDescription;
|
||||
|
||||
|
|
|
@ -54,6 +54,7 @@ private:
|
|||
float mFrequency;
|
||||
float mPhase;
|
||||
float mStartTime;
|
||||
public:
|
||||
float mStopTime;
|
||||
|
||||
public:
|
||||
|
@ -468,7 +469,10 @@ class NIFObjectLoader
|
|||
Ogre::ControllerManager::getSingleton().getFrameTimeSource() :
|
||||
Ogre::ControllerValueRealPtr());
|
||||
Ogre::ControllerValueRealPtr dstval(OGRE_NEW UVController::Value(material, uv->data.getPtr()));
|
||||
Ogre::ControllerFunctionRealPtr func(OGRE_NEW UVController::Function(uv, (animflags&Nif::NiNode::AnimFlag_AutoPlay)));
|
||||
|
||||
UVController::Function* function = OGRE_NEW UVController::Function(uv, (animflags&Nif::NiNode::AnimFlag_AutoPlay));
|
||||
objectlist.mMaxControllerLength = std::max(function->mStopTime, objectlist.mMaxControllerLength);
|
||||
Ogre::ControllerFunctionRealPtr func(function);
|
||||
|
||||
objectlist.mControllers.push_back(Ogre::Controller<Ogre::Real>(srcval, dstval, func));
|
||||
}
|
||||
|
@ -481,7 +485,10 @@ class NIFObjectLoader
|
|||
Ogre::ControllerManager::getSingleton().getFrameTimeSource() :
|
||||
Ogre::ControllerValueRealPtr());
|
||||
Ogre::ControllerValueRealPtr dstval(OGRE_NEW GeomMorpherController::Value(subent, geom->data.getPtr()));
|
||||
Ogre::ControllerFunctionRealPtr func(OGRE_NEW GeomMorpherController::Function(geom, (animflags&Nif::NiNode::AnimFlag_AutoPlay)));
|
||||
|
||||
GeomMorpherController::Function* function = OGRE_NEW GeomMorpherController::Function(geom, (animflags&Nif::NiNode::AnimFlag_AutoPlay));
|
||||
objectlist.mMaxControllerLength = std::max(function->mStopTime, objectlist.mMaxControllerLength);
|
||||
Ogre::ControllerFunctionRealPtr func(function);
|
||||
|
||||
objectlist.mControllers.push_back(Ogre::Controller<Ogre::Real>(srcval, dstval, func));
|
||||
}
|
||||
|
@ -616,7 +623,11 @@ class NIFObjectLoader
|
|||
Ogre::ControllerManager::getSingleton().getFrameTimeSource() :
|
||||
Ogre::ControllerValueRealPtr());
|
||||
Ogre::ControllerValueRealPtr dstval(OGRE_NEW ParticleSystemController::Value(partsys, partctrl));
|
||||
Ogre::ControllerFunctionRealPtr func(OGRE_NEW ParticleSystemController::Function(partctrl, (partflags&Nif::NiNode::ParticleFlag_AutoPlay)));
|
||||
|
||||
ParticleSystemController::Function* function =
|
||||
OGRE_NEW ParticleSystemController::Function(partctrl, (partflags&Nif::NiNode::ParticleFlag_AutoPlay));
|
||||
objectlist.mMaxControllerLength = std::max(function->mStopTime, objectlist.mMaxControllerLength);
|
||||
Ogre::ControllerFunctionRealPtr func(function);
|
||||
|
||||
objectlist.mControllers.push_back(Ogre::Controller<Ogre::Real>(srcval, dstval, func));
|
||||
}
|
||||
|
@ -648,7 +659,10 @@ class NIFObjectLoader
|
|||
Ogre::ControllerManager::getSingleton().getFrameTimeSource() :
|
||||
Ogre::ControllerValueRealPtr());
|
||||
Ogre::ControllerValueRealPtr dstval(OGRE_NEW VisController::Value(trgtbone, vis->data.getPtr()));
|
||||
Ogre::ControllerFunctionRealPtr func(OGRE_NEW VisController::Function(vis, (animflags&Nif::NiNode::AnimFlag_AutoPlay)));
|
||||
|
||||
VisController::Function* function = OGRE_NEW VisController::Function(vis, (animflags&Nif::NiNode::AnimFlag_AutoPlay));
|
||||
objectlist.mMaxControllerLength = std::max(function->mStopTime, objectlist.mMaxControllerLength);
|
||||
Ogre::ControllerFunctionRealPtr func(function);
|
||||
|
||||
objectlist.mControllers.push_back(Ogre::Controller<Ogre::Real>(srcval, dstval, func));
|
||||
}
|
||||
|
@ -663,7 +677,9 @@ class NIFObjectLoader
|
|||
Ogre::ControllerManager::getSingleton().getFrameTimeSource() :
|
||||
Ogre::ControllerValueRealPtr());
|
||||
Ogre::ControllerValueRealPtr dstval(OGRE_NEW KeyframeController::Value(trgtbone, key->data.getPtr()));
|
||||
Ogre::ControllerFunctionRealPtr func(OGRE_NEW KeyframeController::Function(key, (animflags&Nif::NiNode::AnimFlag_AutoPlay)));
|
||||
KeyframeController::Function* function = OGRE_NEW KeyframeController::Function(key, (animflags&Nif::NiNode::AnimFlag_AutoPlay));
|
||||
objectlist.mMaxControllerLength = std::max(function->mStopTime, objectlist.mMaxControllerLength);
|
||||
Ogre::ControllerFunctionRealPtr func(function);
|
||||
|
||||
objectlist.mControllers.push_back(Ogre::Controller<Ogre::Real>(srcval, dstval, func));
|
||||
}
|
||||
|
|
|
@ -45,11 +45,14 @@ struct ObjectList {
|
|||
std::vector<Ogre::ParticleSystem*> mParticles;
|
||||
std::vector<Ogre::Light*> mLights;
|
||||
|
||||
// The maximum length on any of the controllers. For animations with controllers, but no text keys, consider this the animation length.
|
||||
float mMaxControllerLength;
|
||||
|
||||
std::map<int,TextKeyMap> mTextKeys;
|
||||
|
||||
std::vector<Ogre::Controller<Ogre::Real> > mControllers;
|
||||
|
||||
ObjectList() : mSkelBase(0)
|
||||
ObjectList() : mSkelBase(0), mMaxControllerLength(0)
|
||||
{ }
|
||||
};
|
||||
|
||||
|
|
Loading…
Reference in a new issue