forked from mirror/openmw-tes3mp
		
	Closes #1086: Implement blood effects
This commit is contained in:
		
							parent
							
								
									240d96a0f1
								
							
						
					
					
						commit
						805843d7ff
					
				
					 20 changed files with 263 additions and 23 deletions
				
			
		|  | @ -680,7 +680,7 @@ std::string creatureFlags(int flags) | |||
|     if (flags & ESM::Creature::Walks) properties += "Walks "; | ||||
|     if (flags & ESM::Creature::Swims) properties += "Swims "; | ||||
|     if (flags & ESM::Creature::Flies) properties += "Flies "; | ||||
|     if (flags & ESM::Creature::Biped) properties += "Biped ";    | ||||
|     if (flags & ESM::Creature::Bipedal) properties += "Bipedal "; | ||||
|     if (flags & ESM::Creature::Respawn) properties += "Respawn "; | ||||
|     if (flags & ESM::Creature::Weapon) properties += "Weapon "; | ||||
|     if (flags & ESM::Creature::Skeleton) properties += "Skeleton "; | ||||
|  | @ -691,7 +691,7 @@ std::string creatureFlags(int flags) | |||
|                    ESM::Creature::Walks| | ||||
|                    ESM::Creature::Swims| | ||||
|                    ESM::Creature::Flies| | ||||
|                    ESM::Creature::Biped| | ||||
|                    ESM::Creature::Bipedal| | ||||
|                    ESM::Creature::Respawn| | ||||
|                    ESM::Creature::Weapon| | ||||
|                    ESM::Creature::Skeleton| | ||||
|  |  | |||
|  | @ -181,7 +181,7 @@ CSMWorld::RefIdCollection::RefIdCollection() | |||
|         unsigned int mFlag; | ||||
|     } sCreatureFlagTable[] = | ||||
|     { | ||||
|         { Columns::ColumnId_Biped, ESM::Creature::Biped }, | ||||
|         { Columns::ColumnId_Biped, ESM::Creature::Bipedal }, | ||||
|         { Columns::ColumnId_HasWeapon, ESM::Creature::Weapon }, | ||||
|         { Columns::ColumnId_NoMovement, ESM::Creature::None }, | ||||
|         { Columns::ColumnId_Swims, ESM::Creature::Swims }, | ||||
|  |  | |||
|  | @ -20,7 +20,7 @@ add_openmw_dir (mwrender | |||
|     renderingmanager debugging sky camera animation npcanimation creatureanimation activatoranimation | ||||
|     actors objects renderinginterface localmap occlusionquery water shadows | ||||
|     characterpreview globalmap videoplayer ripplesimulation refraction | ||||
|     terrainstorage renderconst | ||||
|     terrainstorage renderconst effectmanager | ||||
|     ) | ||||
| 
 | ||||
| add_openmw_dir (mwinput | ||||
|  |  | |||
|  | @ -463,6 +463,9 @@ namespace MWBase | |||
| 
 | ||||
|             /// Spawn a random creature from a levelled list next to the player
 | ||||
|             virtual void spawnRandomCreature(const std::string& creatureList) = 0; | ||||
| 
 | ||||
|             /// Spawn a blood effect for \a ptr at \a worldPosition
 | ||||
|             virtual void spawnBloodEffect (const MWWorld::Ptr& ptr, const Ogre::Vector3& worldPosition) = 0; | ||||
|     }; | ||||
| } | ||||
| 
 | ||||
|  |  | |||
|  | @ -530,6 +530,17 @@ namespace MWClass | |||
|         } | ||||
|     } | ||||
| 
 | ||||
|     int Creature::getBloodTexture(const MWWorld::Ptr &ptr) const | ||||
|     { | ||||
|         MWWorld::LiveCellRef<ESM::Creature> *ref = ptr.get<ESM::Creature>(); | ||||
| 
 | ||||
|         if (ref->mBase->mFlags & ESM::Creature::Skeleton) | ||||
|             return 1; | ||||
|         if (ref->mBase->mFlags & ESM::Creature::Metal) | ||||
|             return 2; | ||||
|         return 0; | ||||
|     } | ||||
| 
 | ||||
|     const ESM::GameSetting* Creature::fMinWalkSpeedCreature; | ||||
|     const ESM::GameSetting* Creature::fMaxWalkSpeedCreature; | ||||
|     const ESM::GameSetting *Creature::fEncumberedMoveEffect; | ||||
|  |  | |||
|  | @ -111,6 +111,9 @@ namespace MWClass | |||
|             virtual bool isFlying (const MWWorld::Ptr &ptr) const; | ||||
| 
 | ||||
|             virtual int getSkill(const MWWorld::Ptr &ptr, int skill) const; | ||||
| 
 | ||||
|             /// Get a blood texture suitable for \a ptr (see Blood Texture 0-2 in Morrowind.ini)
 | ||||
|             virtual int getBloodTexture (const MWWorld::Ptr& ptr) const; | ||||
|     }; | ||||
| } | ||||
| 
 | ||||
|  |  | |||
|  | @ -455,7 +455,9 @@ namespace MWClass | |||
|                                weapon.get<ESM::Weapon>()->mBase->mData.mReach : | ||||
|                                gmst.find("fHandToHandReach")->getFloat()); | ||||
|         // TODO: Use second to work out the hit angle and where to spawn the blood effect
 | ||||
|         MWWorld::Ptr victim = world->getHitContact(ptr, dist).first; | ||||
|         std::pair<MWWorld::Ptr, Ogre::Vector3> result = world->getHitContact(ptr, dist); | ||||
|         MWWorld::Ptr victim = result.first; | ||||
|         Ogre::Vector3 hitPosition = result.second; | ||||
|         if(victim.isEmpty()) // Didn't hit anything
 | ||||
|             return; | ||||
| 
 | ||||
|  | @ -602,6 +604,8 @@ namespace MWClass | |||
|             } | ||||
|         } | ||||
| 
 | ||||
|         MWBase::Environment::get().getWorld()->spawnBloodEffect(victim, hitPosition); | ||||
| 
 | ||||
|         othercls.onHit(victim, damage, healthdmg, weapon, ptr, true); | ||||
|     } | ||||
| 
 | ||||
|  | @ -1216,6 +1220,17 @@ namespace MWClass | |||
|         return ptr.getClass().getNpcStats(ptr).getSkill(skill).getModified(); | ||||
|     } | ||||
| 
 | ||||
|     int Npc::getBloodTexture(const MWWorld::Ptr &ptr) const | ||||
|     { | ||||
|         MWWorld::LiveCellRef<ESM::NPC> *ref = ptr.get<ESM::NPC>(); | ||||
| 
 | ||||
|         if (ref->mBase->mFlags & ESM::NPC::Skeleton) | ||||
|             return 1; | ||||
|         if (ref->mBase->mFlags & ESM::NPC::Metal) | ||||
|             return 2; | ||||
|         return 0; | ||||
|     } | ||||
| 
 | ||||
|     const ESM::GameSetting *Npc::fMinWalkSpeed; | ||||
|     const ESM::GameSetting *Npc::fMaxWalkSpeed; | ||||
|     const ESM::GameSetting *Npc::fEncumberedMoveEffect; | ||||
|  |  | |||
|  | @ -142,6 +142,9 @@ namespace MWClass | |||
| 
 | ||||
|             virtual int getSkill(const MWWorld::Ptr& ptr, int skill) const; | ||||
| 
 | ||||
|             /// Get a blood texture suitable for \a ptr (see Blood Texture 0-2 in Morrowind.ini)
 | ||||
|             virtual int getBloodTexture (const MWWorld::Ptr& ptr) const; | ||||
| 
 | ||||
|             virtual bool isActor() const { | ||||
|                 return true; | ||||
|             } | ||||
|  |  | |||
|  | @ -1042,6 +1042,7 @@ void Animation::addEffect(const std::string &model, int effectId, bool loop, con | |||
|     else | ||||
|         params.mObjects = NifOgre::Loader::createObjects(mSkelBase, bonename, mInsert, model); | ||||
| 
 | ||||
|     // TODO: turn off shadow casting
 | ||||
|     setRenderProperties(params.mObjects, RV_Misc, | ||||
|                         RQG_Main, RQG_Alpha, 0.f, false, NULL); | ||||
| 
 | ||||
|  |  | |||
|  | @ -189,16 +189,18 @@ protected: | |||
|     /** Adds an additional light to the given object list using the specified ESM record. */ | ||||
|     void addExtraLight(Ogre::SceneManager *sceneMgr, NifOgre::ObjectScenePtr objlist, const ESM::Light *light); | ||||
| 
 | ||||
|     static void setRenderProperties(NifOgre::ObjectScenePtr objlist, Ogre::uint32 visflags, Ogre::uint8 solidqueue, | ||||
|                                     Ogre::uint8 transqueue, Ogre::Real dist=0.0f, | ||||
|                                     bool enchantedGlow=false, Ogre::Vector3* glowColor=NULL); | ||||
| 
 | ||||
|     void clearAnimSources(); | ||||
| 
 | ||||
|     // TODO: Should not be here
 | ||||
|     Ogre::Vector3 getEnchantmentColor(MWWorld::Ptr item); | ||||
| 
 | ||||
| public: | ||||
|     // FIXME: Move outside of this class
 | ||||
|     static void setRenderProperties(NifOgre::ObjectScenePtr objlist, Ogre::uint32 visflags, Ogre::uint8 solidqueue, | ||||
|                                     Ogre::uint8 transqueue, Ogre::Real dist=0.0f, | ||||
|                                     bool enchantedGlow=false, Ogre::Vector3* glowColor=NULL); | ||||
| 
 | ||||
| 
 | ||||
|     Animation(const MWWorld::Ptr &ptr, Ogre::SceneNode *node); | ||||
|     virtual ~Animation(); | ||||
| 
 | ||||
|  |  | |||
|  | @ -24,7 +24,7 @@ CreatureAnimation::CreatureAnimation(const MWWorld::Ptr &ptr) | |||
|         setObjectRoot(model, false); | ||||
|         setRenderProperties(mObjectRoot, RV_Actors, RQG_Main, RQG_Alpha); | ||||
| 
 | ||||
|         if((ref->mBase->mFlags&ESM::Creature::Biped)) | ||||
|         if((ref->mBase->mFlags&ESM::Creature::Bipedal)) | ||||
|             addAnimSource("meshes\\base_anim.nif"); | ||||
|         addAnimSource(model); | ||||
|     } | ||||
|  |  | |||
							
								
								
									
										117
									
								
								apps/openmw/mwrender/effectmanager.cpp
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										117
									
								
								apps/openmw/mwrender/effectmanager.cpp
									
									
									
									
									
										Normal file
									
								
							|  | @ -0,0 +1,117 @@ | |||
| #include "effectmanager.hpp" | ||||
| 
 | ||||
| #include <OgreSceneManager.h> | ||||
| #include <OgreParticleSystem.h> | ||||
| 
 | ||||
| #include "animation.hpp" | ||||
| #include "renderconst.hpp" | ||||
| 
 | ||||
| namespace MWRender | ||||
| { | ||||
| 
 | ||||
| class EffectAnimationTime : public Ogre::ControllerValue<Ogre::Real> | ||||
| { | ||||
| private: | ||||
|     float mTime; | ||||
| public: | ||||
|     EffectAnimationTime() : mTime(0) {  } | ||||
|     void addTime(float time) { mTime += time; } | ||||
| 
 | ||||
|     virtual Ogre::Real getValue() const { return mTime; } | ||||
|     virtual void setValue(Ogre::Real value) {} | ||||
| }; | ||||
| 
 | ||||
| EffectManager::EffectManager(Ogre::SceneManager *sceneMgr) | ||||
|     : mSceneMgr(sceneMgr) | ||||
| { | ||||
| } | ||||
| 
 | ||||
| void EffectManager::addEffect(const std::string &model, std::string textureOverride, const Ogre::Vector3 &worldPosition) | ||||
| { | ||||
|     Ogre::SceneNode* sceneNode = mSceneMgr->getRootSceneNode()->createChildSceneNode(worldPosition); | ||||
| 
 | ||||
|     // fix texture extension to .dds
 | ||||
|     if (textureOverride.size() > 4) | ||||
|     { | ||||
|         textureOverride[textureOverride.size()-3] = 'd'; | ||||
|         textureOverride[textureOverride.size()-2] = 'd'; | ||||
|         textureOverride[textureOverride.size()-1] = 's'; | ||||
|     } | ||||
| 
 | ||||
| 
 | ||||
|     NifOgre::ObjectScenePtr scene = NifOgre::Loader::createObjects(sceneNode, model); | ||||
| 
 | ||||
|     // TODO: turn off shadow casting
 | ||||
|     MWRender::Animation::setRenderProperties(scene, RV_Misc, | ||||
|                         RQG_Main, RQG_Alpha, 0.f, false, NULL); | ||||
| 
 | ||||
|     for(size_t i = 0;i < scene->mControllers.size();i++) | ||||
|     { | ||||
|         if(scene->mControllers[i].getSource().isNull()) | ||||
|             scene->mControllers[i].setSource(Ogre::SharedPtr<EffectAnimationTime> (new EffectAnimationTime())); | ||||
|     } | ||||
| 
 | ||||
|     if (!textureOverride.empty()) | ||||
|     { | ||||
|         for(size_t i = 0;i < scene->mParticles.size(); ++i) | ||||
|         { | ||||
|             Ogre::ParticleSystem* partSys = scene->mParticles[i]; | ||||
| 
 | ||||
|             Ogre::MaterialPtr mat = scene->mMaterialControllerMgr.getWritableMaterial(partSys); | ||||
| 
 | ||||
|             for (int t=0; t<mat->getNumTechniques(); ++t) | ||||
|             { | ||||
|                 Ogre::Technique* tech = mat->getTechnique(t); | ||||
|                 for (int p=0; p<tech->getNumPasses(); ++p) | ||||
|                 { | ||||
|                     Ogre::Pass* pass = tech->getPass(p); | ||||
|                     for (int tex=0; tex<pass->getNumTextureUnitStates(); ++tex) | ||||
|                     { | ||||
|                         Ogre::TextureUnitState* tus = pass->getTextureUnitState(tex); | ||||
|                         tus->setTextureName("textures\\" + textureOverride); | ||||
|                     } | ||||
|                 } | ||||
|             } | ||||
|         } | ||||
|     } | ||||
| 
 | ||||
|     mEffects.push_back(std::make_pair(sceneNode, scene)); | ||||
| } | ||||
| 
 | ||||
| void EffectManager::update(float dt) | ||||
| { | ||||
|     for (std::vector<std::pair<Ogre::SceneNode*, NifOgre::ObjectScenePtr> >::iterator it = mEffects.begin(); it != mEffects.end(); ) | ||||
|     { | ||||
|         NifOgre::ObjectScenePtr objects = it->second; | ||||
|         for(size_t i = 0; i < objects->mControllers.size() ;i++) | ||||
|         { | ||||
|             EffectAnimationTime* value = dynamic_cast<EffectAnimationTime*>(objects->mControllers[i].getSource().get()); | ||||
|             if (value) | ||||
|                 value->addTime(dt); | ||||
| 
 | ||||
|             objects->mControllers[i].update(); | ||||
|         } | ||||
| 
 | ||||
|         // Finished playing?
 | ||||
|         if (objects->mControllers[0].getSource()->getValue() >= objects->mMaxControllerLength) | ||||
|         { | ||||
|             Ogre::SceneNode* node = it->first; | ||||
|             it = mEffects.erase(it); | ||||
|             mSceneMgr->destroySceneNode(node); | ||||
|             continue; | ||||
|         } | ||||
|         ++it; | ||||
|     } | ||||
| } | ||||
| 
 | ||||
| void EffectManager::clear() | ||||
| { | ||||
|     for (std::vector<std::pair<Ogre::SceneNode*, NifOgre::ObjectScenePtr> >::iterator it = mEffects.begin(); it != mEffects.end(); ) | ||||
|     { | ||||
|         Ogre::SceneNode* node = it->first; | ||||
|         it = mEffects.erase(it); | ||||
|         mSceneMgr->destroySceneNode(node); | ||||
|     } | ||||
| } | ||||
| 
 | ||||
| } | ||||
							
								
								
									
										31
									
								
								apps/openmw/mwrender/effectmanager.hpp
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										31
									
								
								apps/openmw/mwrender/effectmanager.hpp
									
									
									
									
									
										Normal file
									
								
							|  | @ -0,0 +1,31 @@ | |||
| #ifndef OPENMW_MWRENDER_EFFECTMANAGER_H | ||||
| #define OPENMW_MWRENDER_EFFECTMANAGER_H | ||||
| 
 | ||||
| #include <components/nifogre/ogrenifloader.hpp> | ||||
| 
 | ||||
| namespace MWRender | ||||
| { | ||||
|     // Note: effects attached to another object should be managed by MWRender::Animation::addEffect.
 | ||||
|     // This class manages "free" effects, i.e. attached to a dedicated scene node in the world.
 | ||||
|     class EffectManager | ||||
|     { | ||||
|     public: | ||||
|         EffectManager(Ogre::SceneManager* sceneMgr); | ||||
|         ~EffectManager() { clear(); } | ||||
| 
 | ||||
|         /// Add an effect. When it's finished playing, it will be removed automatically.
 | ||||
|         void addEffect (const std::string& model, std::string textureOverride, const Ogre::Vector3& worldPosition); | ||||
| 
 | ||||
|         void update(float dt); | ||||
| 
 | ||||
|         /// Remove all effects
 | ||||
|         void clear(); | ||||
| 
 | ||||
|     private: | ||||
|         std::vector<std::pair<Ogre::SceneNode*, NifOgre::ObjectScenePtr> > mEffects; | ||||
|         Ogre::SceneManager* mSceneMgr; | ||||
|     }; | ||||
| 
 | ||||
| } | ||||
| 
 | ||||
| #endif | ||||
|  | @ -41,6 +41,7 @@ | |||
| #include "globalmap.hpp" | ||||
| #include "videoplayer.hpp" | ||||
| #include "terrainstorage.hpp" | ||||
| #include "effectmanager.hpp" | ||||
| 
 | ||||
| using namespace MWRender; | ||||
| using namespace Ogre; | ||||
|  | @ -57,9 +58,11 @@ RenderingManager::RenderingManager(OEngine::Render::OgreRenderer& _rend, const b | |||
|     , mSunEnabled(0) | ||||
|     , mPhysicsEngine(engine) | ||||
|     , mTerrain(NULL) | ||||
|     , mEffectManager(NULL) | ||||
| { | ||||
|     mActors = new MWRender::Actors(mRendering, this); | ||||
|     mObjects = new MWRender::Objects(mRendering); | ||||
|     mEffectManager = new EffectManager(mRendering.getScene()); | ||||
|     // select best shader mode
 | ||||
|     bool openGL = (Ogre::Root::getSingleton ().getRenderSystem ()->getName().find("OpenGL") != std::string::npos); | ||||
|     bool glES = (Ogre::Root::getSingleton ().getRenderSystem ()->getName().find("OpenGL ES") != std::string::npos); | ||||
|  | @ -193,6 +196,7 @@ RenderingManager::~RenderingManager () | |||
|     delete mVideoPlayer; | ||||
|     delete mActors; | ||||
|     delete mObjects; | ||||
|     delete mEffectManager; | ||||
|     delete mFactory; | ||||
| } | ||||
| 
 | ||||
|  | @ -374,6 +378,8 @@ void RenderingManager::update (float duration, bool paused) | |||
|     if(paused) | ||||
|         return; | ||||
| 
 | ||||
|     mEffectManager->update(duration); | ||||
| 
 | ||||
|     mActors->update (mRendering.getCamera()); | ||||
|     mPlayerAnimation->preRender(mRendering.getCamera()); | ||||
|     mObjects->update (duration, mRendering.getCamera()); | ||||
|  | @ -675,14 +681,14 @@ Shadows* RenderingManager::getShadows() | |||
| 
 | ||||
| void RenderingManager::switchToInterior() | ||||
| { | ||||
|     // causes light flicker in opengl when moving..
 | ||||
|     //mRendering.getScene()->setCameraRelativeRendering(false);
 | ||||
|     // TODO: also do this when switching worldspace
 | ||||
|     mEffectManager->clear(); | ||||
| } | ||||
| 
 | ||||
| void RenderingManager::switchToExterior() | ||||
| { | ||||
|     // causes light flicker in opengl when moving..
 | ||||
|     //mRendering.getScene()->setCameraRelativeRendering(true);
 | ||||
|     // TODO: also do this when switching worldspace
 | ||||
|     mEffectManager->clear(); | ||||
| } | ||||
| 
 | ||||
| Ogre::Vector4 RenderingManager::boundingBoxToScreen(Ogre::AxisAlignedBox bounds) | ||||
|  | @ -1020,4 +1026,9 @@ float RenderingManager::getCameraDistance() const | |||
|     return mCamera->getCameraDistance(); | ||||
| } | ||||
| 
 | ||||
| void RenderingManager::spawnEffect(const std::string &model, const std::string &texture, const Vector3 &worldPosition) | ||||
| { | ||||
|     mEffectManager->addEffect(model, texture, worldPosition); | ||||
| } | ||||
| 
 | ||||
| } // namespace
 | ||||
|  |  | |||
|  | @ -21,10 +21,7 @@ | |||
| 
 | ||||
| namespace Ogre | ||||
| { | ||||
|     class SceneManager; | ||||
|     class SceneNode; | ||||
|     class Quaternion; | ||||
|     class Vector3; | ||||
| } | ||||
| 
 | ||||
| namespace MWWorld | ||||
|  | @ -51,6 +48,7 @@ namespace MWRender | |||
|     class GlobalMap; | ||||
|     class VideoPlayer; | ||||
|     class Animation; | ||||
|     class EffectManager; | ||||
| 
 | ||||
| class RenderingManager: private RenderingInterface, public Ogre::RenderTargetListener, public OEngine::Render::WindowSizeListener | ||||
| { | ||||
|  | @ -209,6 +207,8 @@ public: | |||
|     void stopVideo(); | ||||
|     void frameStarted(float dt, bool paused); | ||||
| 
 | ||||
|     void spawnEffect (const std::string& model, const std::string& texture, const Ogre::Vector3& worldPosition); | ||||
| 
 | ||||
| protected: | ||||
|     virtual void windowResized(int x, int y); | ||||
| 
 | ||||
|  | @ -239,6 +239,8 @@ private: | |||
|     MWRender::Objects* mObjects; | ||||
|     MWRender::Actors* mActors; | ||||
| 
 | ||||
|     MWRender::EffectManager* mEffectManager; | ||||
| 
 | ||||
|     MWRender::NpcAnimation *mPlayerAnimation; | ||||
| 
 | ||||
|     // 0 normal, 1 more bright, 2 max
 | ||||
|  |  | |||
|  | @ -363,4 +363,8 @@ namespace MWWorld | |||
|         throw std::runtime_error("class does not support skills"); | ||||
|     } | ||||
| 
 | ||||
|     int Class::getBloodTexture (const MWWorld::Ptr& ptr) const | ||||
|     { | ||||
|         throw std::runtime_error("class does not support gore"); | ||||
|     } | ||||
| } | ||||
|  |  | |||
|  | @ -278,6 +278,9 @@ namespace MWWorld | |||
| 
 | ||||
|             virtual bool isKey (const MWWorld::Ptr& ptr) const { return false; } | ||||
| 
 | ||||
|             /// Get a blood texture suitable for \a ptr (see Blood Texture 0-2 in Morrowind.ini)
 | ||||
|             virtual int getBloodTexture (const MWWorld::Ptr& ptr) const; | ||||
| 
 | ||||
|             virtual Ptr | ||||
|             copyToCell(const Ptr &ptr, CellStore &cell) const; | ||||
| 
 | ||||
|  |  | |||
|  | @ -2610,4 +2610,31 @@ namespace MWWorld | |||
|             safePlaceObject(ref.getPtr(),*cell,ipos); | ||||
|         } | ||||
|     } | ||||
| 
 | ||||
|     void World::spawnBloodEffect(const Ptr &ptr, const Vector3 &worldPosition) | ||||
|     { | ||||
|         int type = ptr.getClass().getBloodTexture(ptr); | ||||
|         std::string texture; | ||||
|         switch (type) | ||||
|         { | ||||
|         case 2: | ||||
|             texture = getFallback()->getFallbackString("Blood_Texture_2"); | ||||
|             break; | ||||
|         case 1: | ||||
|             texture = getFallback()->getFallbackString("Blood_Texture_1"); | ||||
|             break; | ||||
|         case 0: | ||||
|         default: | ||||
|             texture = getFallback()->getFallbackString("Blood_Texture_0"); | ||||
|             break; | ||||
|         } | ||||
| 
 | ||||
|         std::stringstream modelName; | ||||
|         modelName << "Blood_Model_"; | ||||
|         int roll = std::rand()/ (static_cast<double> (RAND_MAX) + 1) * 3; // [0, 2]
 | ||||
|         modelName << roll; | ||||
|         std::string model = "meshes\\" + getFallback()->getFallbackString(modelName.str()); | ||||
| 
 | ||||
|         mRendering->spawnEffect(model, texture, worldPosition); | ||||
|     } | ||||
| } | ||||
|  |  | |||
|  | @ -549,6 +549,9 @@ namespace MWWorld | |||
| 
 | ||||
|             /// Spawn a random creature from a levelled list next to the player
 | ||||
|             virtual void spawnRandomCreature(const std::string& creatureList); | ||||
| 
 | ||||
|             /// Spawn a blood effect for \a ptr at \a worldPosition
 | ||||
|             virtual void spawnBloodEffect (const MWWorld::Ptr& ptr, const Ogre::Vector3& worldPosition); | ||||
|     }; | ||||
| } | ||||
| 
 | ||||
|  |  | |||
|  | @ -25,16 +25,20 @@ struct Creature | |||
|     // Default is 0x48?
 | ||||
|     enum Flags | ||||
|     { | ||||
|         Biped       = 0x001, | ||||
|         Respawn     = 0x002, | ||||
|         Weapon      = 0x004, // Has weapon and shield
 | ||||
|         None        = 0x008, // ??
 | ||||
|         // Movement types
 | ||||
|         Bipedal       = 0x001, | ||||
|         Swims       = 0x010, | ||||
|         Flies       = 0x020, // Don't know what happens if several
 | ||||
|         Walks       = 0x040, // of these are set
 | ||||
| 
 | ||||
|         Respawn     = 0x002, | ||||
|         Weapon      = 0x004, // Has weapon and shield
 | ||||
|         None        = 0x008, // ??
 | ||||
|         Essential   = 0x080, | ||||
|         Skeleton    = 0x400, // Does not have normal blood
 | ||||
|         Metal       = 0x800  // Has 'golden' blood
 | ||||
| 
 | ||||
|         // Blood types
 | ||||
|         Skeleton    = 0x400, | ||||
|         Metal       = 0x800 | ||||
|     }; | ||||
| 
 | ||||
|     enum Type | ||||
|  |  | |||
		Loading…
	
		Reference in a new issue