From 9ea6b22a837a6ba144ef8cd0a7d37936df7ae991 Mon Sep 17 00:00:00 2001 From: Chris Robinson Date: Wed, 17 Jul 2013 23:58:21 -0700 Subject: [PATCH] Handle soundgen animation keys --- apps/openmw/mwclass/creature.cpp | 59 ++++++++++++++++++++++++++++++ apps/openmw/mwclass/creature.hpp | 4 ++ apps/openmw/mwclass/npc.cpp | 36 ++++++++++++++++++ apps/openmw/mwclass/npc.hpp | 2 + apps/openmw/mwrender/animation.cpp | 9 ++++- apps/openmw/mwworld/class.cpp | 4 ++ apps/openmw/mwworld/class.hpp | 3 ++ 7 files changed, 115 insertions(+), 2 deletions(-) diff --git a/apps/openmw/mwclass/creature.cpp b/apps/openmw/mwclass/creature.cpp index a263af464..f5bd434b1 100644 --- a/apps/openmw/mwclass/creature.cpp +++ b/apps/openmw/mwclass/creature.cpp @@ -291,6 +291,33 @@ namespace MWClass return ref->mBase->mPersistent; } + std::string Creature::getSoundIdFromSndGen(const MWWorld::Ptr &ptr, const std::string &name) const + { + const MWWorld::Store &store = MWBase::Environment::get().getWorld()->getStore().get(); + + int type = getSndGenTypeFromName(ptr, name); + if(type >= 0) + { + std::vector sounds; + sounds.reserve(8); + + std::string ptrid = Creature::getId(ptr); + MWWorld::Store::iterator sound = store.begin(); + while(sound != store.end()) + { + if(type == sound->mType && sound->mCreature.size() > 0 && + Misc::StringUtils::ciEqual(ptrid.substr(0, sound->mCreature.size()), + sound->mCreature)) + sounds.push_back(&*sound); + sound++; + } + if(sounds.size() > 0) + return sounds[(int)(rand()/(RAND_MAX+1.0)*sounds.size())]->mSound; + } + + return ""; + } + MWWorld::Ptr Creature::copyToCellImpl(const MWWorld::Ptr &ptr, MWWorld::CellStore &cell) const { @@ -300,6 +327,38 @@ namespace MWClass return MWWorld::Ptr(&cell.mCreatures.insert(*ref), &cell); } + int Creature::getSndGenTypeFromName(const MWWorld::Ptr &ptr, const std::string &name) + { + if(name == "left") + { + MWBase::World *world = MWBase::Environment::get().getWorld(); + Ogre::Vector3 pos(ptr.getRefData().getPosition().pos); + if(world->isUnderwater(ptr.getCell(), pos)) + return 2; + if(world->isOnGround(ptr)) + return 0; + return -1; + } + if(name == "right") + { + MWBase::World *world = MWBase::Environment::get().getWorld(); + Ogre::Vector3 pos(ptr.getRefData().getPosition().pos); + if(world->isUnderwater(ptr.getCell(), pos)) + return 3; + if(world->isOnGround(ptr)) + return 1; + return -1; + } + if(name == "moan") + return 4; + if(name == "roar") + return 5; + if(name == "scream") + return 6; + + throw std::runtime_error(std::string("Unexpected soundgen type: ")+name); + } + const ESM::GameSetting* Creature::fMinWalkSpeedCreature; const ESM::GameSetting* Creature::fMaxWalkSpeedCreature; } diff --git a/apps/openmw/mwclass/creature.hpp b/apps/openmw/mwclass/creature.hpp index 5c30004cd..356ecfb64 100644 --- a/apps/openmw/mwclass/creature.hpp +++ b/apps/openmw/mwclass/creature.hpp @@ -12,6 +12,8 @@ namespace MWClass virtual MWWorld::Ptr copyToCellImpl(const MWWorld::Ptr &ptr, MWWorld::CellStore &cell) const; + static int getSndGenTypeFromName(const MWWorld::Ptr &ptr, const std::string &name); + static const ESM::GameSetting *fMinWalkSpeedCreature; static const ESM::GameSetting *fMaxWalkSpeedCreature; @@ -69,6 +71,8 @@ namespace MWClass virtual bool isPersistent (const MWWorld::Ptr& ptr) const; + virtual std::string getSoundIdFromSndGen(const MWWorld::Ptr &ptr, const std::string &name) const; + virtual MWMechanics::Movement& getMovementSettings (const MWWorld::Ptr& ptr) const; ///< Return desired movement. diff --git a/apps/openmw/mwclass/npc.cpp b/apps/openmw/mwclass/npc.cpp index 4574792ae..eb100ff9a 100644 --- a/apps/openmw/mwclass/npc.cpp +++ b/apps/openmw/mwclass/npc.cpp @@ -663,6 +663,42 @@ namespace MWClass return 0; } + + std::string Npc::getSoundIdFromSndGen(const MWWorld::Ptr &ptr, const std::string &name) const + { + if(name == "left") + { + MWBase::World *world = MWBase::Environment::get().getWorld(); + Ogre::Vector3 pos(ptr.getRefData().getPosition().pos); + if(world->isUnderwater(ptr.getCell(), pos)) + return "FootWaterLeft"; + if(world->isOnGround(ptr)) + return "FootBareLeft"; + return ""; + } + if(name == "right") + { + MWBase::World *world = MWBase::Environment::get().getWorld(); + Ogre::Vector3 pos(ptr.getRefData().getPosition().pos); + if(world->isUnderwater(ptr.getCell(), pos)) + return "FootWaterRight"; + if(world->isOnGround(ptr)) + return "FootBareRight"; + return ""; + } + // TODO: I have no idea what these are supposed to do for NPCs since they use + // voiced dialog for various conditions like health loss and combat taunts. Maybe + // only for biped creatures? + if(name == "moan") + return ""; + if(name == "roar") + return ""; + if(name == "scream") + return ""; + + throw std::runtime_error(std::string("Unexpected soundgen type: ")+name); + } + MWWorld::Ptr Npc::copyToCellImpl(const MWWorld::Ptr &ptr, MWWorld::CellStore &cell) const { diff --git a/apps/openmw/mwclass/npc.hpp b/apps/openmw/mwclass/npc.hpp index 83bfbdcbf..2a73df593 100644 --- a/apps/openmw/mwclass/npc.hpp +++ b/apps/openmw/mwclass/npc.hpp @@ -132,6 +132,8 @@ namespace MWClass virtual bool isPersistent (const MWWorld::Ptr& ptr) const; + virtual std::string getSoundIdFromSndGen(const MWWorld::Ptr &ptr, const std::string &name) const; + static void registerSelf(); virtual std::string getModel(const MWWorld::Ptr &ptr) const; diff --git a/apps/openmw/mwrender/animation.cpp b/apps/openmw/mwrender/animation.cpp index 147e7c90e..330edf1e9 100644 --- a/apps/openmw/mwrender/animation.cpp +++ b/apps/openmw/mwrender/animation.cpp @@ -14,6 +14,7 @@ #include "../mwbase/world.hpp" #include "../mwmechanics/character.hpp" +#include "../mwworld/class.hpp" namespace MWRender { @@ -511,8 +512,12 @@ bool Animation::handleTextKey(AnimState &state, const std::string &groupname, co } if(evt.compare(0, 10, "soundgen: ") == 0) { - // FIXME: Lookup the SoundGen (SNDG) for the specified sound that corresponds - // to this actor type + std::string sound = MWWorld::Class::get(mPtr).getSoundIdFromSndGen(mPtr, evt.substr(10)); + if(!sound.empty()) + { + MWBase::SoundManager *sndMgr = MWBase::Environment::get().getSoundManager(); + sndMgr->playSound3D(mPtr, sound, 1.0f, 1.0f); + } return true; } diff --git a/apps/openmw/mwworld/class.cpp b/apps/openmw/mwworld/class.cpp index 5690531e7..6f420942b 100644 --- a/apps/openmw/mwworld/class.cpp +++ b/apps/openmw/mwworld/class.cpp @@ -240,6 +240,10 @@ namespace MWWorld throw std::runtime_error ("class does not have an down sound"); } + std::string Class::getSoundIdFromSndGen(const Ptr &ptr, const std::string &type) const + { + throw std::runtime_error("class does not support soundgen look up"); + } std::string Class::getInventoryIcon (const MWWorld::Ptr& ptr) const { diff --git a/apps/openmw/mwworld/class.hpp b/apps/openmw/mwworld/class.hpp index b4fd84a6b..eed100024 100644 --- a/apps/openmw/mwworld/class.hpp +++ b/apps/openmw/mwworld/class.hpp @@ -221,6 +221,9 @@ namespace MWWorld ///< Return the down sound ID of \a ptr or throw an exception, if class does not support ID retrieval /// (default implementation: throw an exception) + virtual std::string getSoundIdFromSndGen(const Ptr &ptr, const std::string &type) const; + ///< Returns the sound ID for \a ptr of the given soundgen \a type. + virtual float getArmorRating (const MWWorld::Ptr& ptr) const; ///< @return combined armor rating of this actor