1
0
Fork 1
mirror of https://github.com/TES3MP/openmw-tes3mp.git synced 2025-01-21 09:53:50 +00:00

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

View file

@ -512,6 +512,9 @@ bool CharacterController::updateNpcState(bool onground, bool inwater, bool isrun
const ESM::MagicEffect *effect; const ESM::MagicEffect *effect;
effect = store.get<ESM::MagicEffect>().find(effectentry.mEffectID); 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) switch(effectentry.mRange)
{ {
case 0: mAttackType = "self"; break; 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) void Animation::destroyObjectList(Ogre::SceneManager *sceneMgr, NifOgre::ObjectList &objects)
{ {
@ -916,6 +925,25 @@ Ogre::Vector3 Animation::runAnimation(float duration)
mSkelBase->getAllAnimationStates()->_notifyDirty(); 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; return movement;
} }
@ -980,6 +1008,17 @@ void Animation::detachObjectFromBone(Ogre::MovableObject *obj)
mSkelBase->detachObjectFromBone(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) ObjectAnimation::ObjectAnimation(const MWWorld::Ptr& ptr, const std::string &model)
: Animation(ptr, ptr.getRefData().getBaseNode()) : Animation(ptr, ptr.getRefData().getBaseNode())

View file

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

View file

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

View file

@ -64,8 +64,8 @@ struct MagicEffect
MEDTstruct mData; MEDTstruct mData;
std::string mIcon, mParticle; // Textures std::string mIcon, mParticle; // Textures
std::string mCasting, mHit, mArea; // Statics std::string mCasting, mHit, mArea; // ESM::Static
std::string mBolt; // Weapon std::string mBolt; // ESM::Weapon
std::string mCastSound, mBoltSound, mHitSound, mAreaSound; // Sounds std::string mCastSound, mBoltSound, mHitSound, mAreaSound; // Sounds
std::string mDescription; std::string mDescription;

View file

@ -54,6 +54,7 @@ private:
float mFrequency; float mFrequency;
float mPhase; float mPhase;
float mStartTime; float mStartTime;
public:
float mStopTime; float mStopTime;
public: public:
@ -468,7 +469,10 @@ class NIFObjectLoader
Ogre::ControllerManager::getSingleton().getFrameTimeSource() : Ogre::ControllerManager::getSingleton().getFrameTimeSource() :
Ogre::ControllerValueRealPtr()); Ogre::ControllerValueRealPtr());
Ogre::ControllerValueRealPtr dstval(OGRE_NEW UVController::Value(material, uv->data.getPtr())); 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)); objectlist.mControllers.push_back(Ogre::Controller<Ogre::Real>(srcval, dstval, func));
} }
@ -481,7 +485,10 @@ class NIFObjectLoader
Ogre::ControllerManager::getSingleton().getFrameTimeSource() : Ogre::ControllerManager::getSingleton().getFrameTimeSource() :
Ogre::ControllerValueRealPtr()); Ogre::ControllerValueRealPtr());
Ogre::ControllerValueRealPtr dstval(OGRE_NEW GeomMorpherController::Value(subent, geom->data.getPtr())); 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)); objectlist.mControllers.push_back(Ogre::Controller<Ogre::Real>(srcval, dstval, func));
} }
@ -616,7 +623,11 @@ class NIFObjectLoader
Ogre::ControllerManager::getSingleton().getFrameTimeSource() : Ogre::ControllerManager::getSingleton().getFrameTimeSource() :
Ogre::ControllerValueRealPtr()); Ogre::ControllerValueRealPtr());
Ogre::ControllerValueRealPtr dstval(OGRE_NEW ParticleSystemController::Value(partsys, partctrl)); 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)); objectlist.mControllers.push_back(Ogre::Controller<Ogre::Real>(srcval, dstval, func));
} }
@ -648,7 +659,10 @@ class NIFObjectLoader
Ogre::ControllerManager::getSingleton().getFrameTimeSource() : Ogre::ControllerManager::getSingleton().getFrameTimeSource() :
Ogre::ControllerValueRealPtr()); Ogre::ControllerValueRealPtr());
Ogre::ControllerValueRealPtr dstval(OGRE_NEW VisController::Value(trgtbone, vis->data.getPtr())); 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)); objectlist.mControllers.push_back(Ogre::Controller<Ogre::Real>(srcval, dstval, func));
} }
@ -663,7 +677,9 @@ class NIFObjectLoader
Ogre::ControllerManager::getSingleton().getFrameTimeSource() : Ogre::ControllerManager::getSingleton().getFrameTimeSource() :
Ogre::ControllerValueRealPtr()); Ogre::ControllerValueRealPtr());
Ogre::ControllerValueRealPtr dstval(OGRE_NEW KeyframeController::Value(trgtbone, key->data.getPtr())); 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)); objectlist.mControllers.push_back(Ogre::Controller<Ogre::Real>(srcval, dstval, func));
} }

View file

@ -45,11 +45,14 @@ struct ObjectList {
std::vector<Ogre::ParticleSystem*> mParticles; std::vector<Ogre::ParticleSystem*> mParticles;
std::vector<Ogre::Light*> mLights; 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::map<int,TextKeyMap> mTextKeys;
std::vector<Ogre::Controller<Ogre::Real> > mControllers; std::vector<Ogre::Controller<Ogre::Real> > mControllers;
ObjectList() : mSkelBase(0) ObjectList() : mSkelBase(0), mMaxControllerLength(0)
{ } { }
}; };