From 6fd4cdb5fb94db503b5d3bf7ddc30160397862ec Mon Sep 17 00:00:00 2001 From: Chris Robinson Date: Sun, 11 Aug 2013 00:35:19 -0700 Subject: [PATCH] Play randomized werewolf sounds --- apps/openmw/mwclass/book.cpp | 7 +++-- apps/openmw/mwclass/container.cpp | 7 +++-- apps/openmw/mwclass/creature.cpp | 7 +++-- apps/openmw/mwclass/npc.cpp | 12 +++++--- apps/openmw/mwmechanics/character.cpp | 34 +++++++++++++++------- apps/openmw/mwworld/class.cpp | 8 ++++-- apps/openmw/mwworld/store.hpp | 41 +++++++++++++++++++++++++++ components/misc/stringops.hpp | 20 +++++++++++++ 8 files changed, 114 insertions(+), 22 deletions(-) diff --git a/apps/openmw/mwclass/book.cpp b/apps/openmw/mwclass/book.cpp index e85e742c8..a692b30d8 100644 --- a/apps/openmw/mwclass/book.cpp +++ b/apps/openmw/mwclass/book.cpp @@ -63,9 +63,12 @@ namespace MWClass { if(get(actor).isNpc() && get(actor).getNpcStats(actor).isWerewolf()) { + const MWWorld::ESMStore &store = MWBase::Environment::get().getWorld()->getStore(); + const ESM::Sound *sound = store.get().searchRandom("WolfItem"); + boost::shared_ptr action(new MWWorld::FailedAction("#{sWerewolfRefusal}")); - // FIXME: Randomize using all WolfItem* sound records - action->setSound("WolfItem1"); + if(sound) action->setSound(sound->mId); + return action; } diff --git a/apps/openmw/mwclass/container.cpp b/apps/openmw/mwclass/container.cpp index 32f061202..d057eea6a 100644 --- a/apps/openmw/mwclass/container.cpp +++ b/apps/openmw/mwclass/container.cpp @@ -95,9 +95,12 @@ namespace MWClass if(get(actor).isNpc() && get(actor).getNpcStats(actor).isWerewolf()) { + const MWWorld::ESMStore &store = MWBase::Environment::get().getWorld()->getStore(); + const ESM::Sound *sound = store.get().searchRandom("WolfContainer"); + boost::shared_ptr action(new MWWorld::FailedAction("#{sWerewolfRefusal}")); - // FIXME: Randomize using all WolfContainer* sound records - action->setSound("WolfContainer1"); + if(sound) action->setSound(sound->mId); + return action; } diff --git a/apps/openmw/mwclass/creature.cpp b/apps/openmw/mwclass/creature.cpp index 9d7aacd23..20f95ab0e 100644 --- a/apps/openmw/mwclass/creature.cpp +++ b/apps/openmw/mwclass/creature.cpp @@ -227,9 +227,12 @@ namespace MWClass { if(get(actor).isNpc() && get(actor).getNpcStats(actor).isWerewolf()) { + const MWWorld::ESMStore &store = MWBase::Environment::get().getWorld()->getStore(); + const ESM::Sound *sound = store.get().searchRandom("WolfCreature"); + boost::shared_ptr action(new MWWorld::FailedAction("#{sWerewolfRefusal}")); - // FIXME: Randomize using all WolfCreature* sound records - action->setSound("WolfCreature1"); + if(sound) action->setSound(sound->mId); + return action; } diff --git a/apps/openmw/mwclass/npc.cpp b/apps/openmw/mwclass/npc.cpp index 62c6d4744..620bfaaca 100644 --- a/apps/openmw/mwclass/npc.cpp +++ b/apps/openmw/mwclass/npc.cpp @@ -431,8 +431,9 @@ namespace MWClass MWBase::SoundManager *sndMgr = MWBase::Environment::get().getSoundManager(); if(stats.isWerewolf()) { - // Randomize from WolfHit* records - sndMgr->playSound3D(victim, "WolfHit1", 1.0f, 1.0f); + const ESM::Sound *sound = world->getStore().get().searchRandom("WolfHit"); + if(sound) + sndMgr->playSound3D(victim, sound->mId, 1.0f, 1.0f); } else sndMgr->playSound3D(victim, "Hand To Hand Hit", 1.0f, 1.0f); @@ -571,9 +572,12 @@ namespace MWClass { if(get(actor).isNpc() && get(actor).getNpcStats(actor).isWerewolf()) { + const MWWorld::ESMStore &store = MWBase::Environment::get().getWorld()->getStore(); + const ESM::Sound *sound = store.get().searchRandom("WolfNPC"); + boost::shared_ptr action(new MWWorld::FailedAction("#{sWerewolfRefusal}")); - // FIXME: Randomize using all WolfNPC* sound records - action->setSound("WolfNPC1"); + if(sound) action->setSound(sound->mId); + return action; } if(getCreatureStats(ptr).isDead()) diff --git a/apps/openmw/mwmechanics/character.cpp b/apps/openmw/mwmechanics/character.cpp index 5f59a9117..1b220e65f 100644 --- a/apps/openmw/mwmechanics/character.cpp +++ b/apps/openmw/mwmechanics/character.cpp @@ -405,9 +405,13 @@ bool CharacterController::updateNpcState(bool onground, bool inwater, bool isrun mUpperBodyState = UpperCharState_EquipingWeap; if(isWerewolf) { - MWBase::SoundManager *sndMgr = MWBase::Environment::get().getSoundManager(); - // TODO: Randomize from all WolfEquip* records - sndMgr->playSound3D(mPtr, "WolfEquip1", 1.0f, 1.0f); + const MWWorld::ESMStore &store = MWBase::Environment::get().getWorld()->getStore(); + const ESM::Sound *sound = store.get().searchRandom("WolfEquip"); + if(sound) + { + MWBase::SoundManager *sndMgr = MWBase::Environment::get().getSoundManager(); + sndMgr->playSound3D(mPtr, sound->mId, 1.0f, 1.0f); + } } } @@ -554,14 +558,24 @@ bool CharacterController::updateNpcState(bool onground, bool inwater, bool isrun if(mAttackType != "shoot") { MWBase::SoundManager *sndMgr = MWBase::Environment::get().getSoundManager(); - // TODO: Randomize from WolfSwing* records - std::string sound = (!isWerewolf ? "SwishM" : "WolfSwing"); - if(complete < 0.5f) - sndMgr->playSound3D(mPtr, sound, 1.0f, 0.8f); //Weak attack - else if(complete < 1.0f) - sndMgr->playSound3D(mPtr, sound, 1.0f, 1.0f); //Medium attack + + if(isWerewolf) + { + const MWWorld::ESMStore &store = MWBase::Environment::get().getWorld()->getStore(); + const ESM::Sound *sound = store.get().searchRandom("WolfSwing"); + if(sound) + sndMgr->playSound3D(mPtr, sound->mId, 1.0f, 1.0f); + } else - sndMgr->playSound3D(mPtr, sound, 1.0f, 1.2f); //Strong attack + { + std::string sound = "SwishM"; + if(complete < 0.5f) + sndMgr->playSound3D(mPtr, sound, 1.0f, 0.8f); //Weak attack + else if(complete < 1.0f) + sndMgr->playSound3D(mPtr, sound, 1.0f, 1.0f); //Medium attack + else + sndMgr->playSound3D(mPtr, sound, 1.0f, 1.2f); //Strong attack + } } stats.setAttackStrength(complete); diff --git a/apps/openmw/mwworld/class.cpp b/apps/openmw/mwworld/class.cpp index c6575f858..c7b8d341c 100644 --- a/apps/openmw/mwworld/class.cpp +++ b/apps/openmw/mwworld/class.cpp @@ -9,6 +9,7 @@ #include "../mwbase/environment.hpp" #include "../mwbase/windowmanager.hpp" +#include "../mwbase/world.hpp" #include "ptr.hpp" #include "refdata.hpp" @@ -318,9 +319,12 @@ namespace MWWorld if(get(actor).isNpc() && get(actor).getNpcStats(actor).isWerewolf()) { + const MWWorld::ESMStore &store = MWBase::Environment::get().getWorld()->getStore(); + const ESM::Sound *sound = store.get().searchRandom("WolfItem"); + boost::shared_ptr action(new MWWorld::FailedAction("#{sWerewolfRefusal}")); - // FIXME: Randomize using all WolfItem* sound records - action->setSound("WolfItem1"); + if(sound) action->setSound(sound->mId); + return action; } diff --git a/apps/openmw/mwworld/store.hpp b/apps/openmw/mwworld/store.hpp index 8ee71474f..2c10e3edc 100644 --- a/apps/openmw/mwworld/store.hpp +++ b/apps/openmw/mwworld/store.hpp @@ -95,6 +95,23 @@ namespace MWWorld typedef std::map Dynamic; typedef std::map Static; + class GetRecords { + const std::string mFind; + std::vector *mRecords; + + public: + GetRecords(const std::string &str, std::vector *records) + : mFind(Misc::StringUtils::lowerCase(str)), mRecords(records) + { } + + void operator()(const T *item) + { + if(Misc::StringUtils::ciCompareLen(mFind, item->mId, mFind.size()) == 0) + mRecords->push_back(item); + } + }; + + friend class ESMStore; public: @@ -132,6 +149,16 @@ namespace MWWorld return 0; } + /** Returns a random record that starts with the named ID, or NULL if not found. */ + const T *searchRandom(const std::string &id) const + { + std::vector results; + std::for_each(mShared.begin(), mShared.end(), GetRecords(id, &results)); + if(!results.empty()) + return results[int(std::rand()/((double)RAND_MAX+1)*results.size())]; + return NULL; + } + const T *find(const std::string &id) const { const T *ptr = search(id); if (ptr == 0) { @@ -142,6 +169,20 @@ namespace MWWorld return ptr; } + /** Returns a random record that starts with the named ID. An exception is thrown if none + * are found. */ + const T *findRandom(const std::string &id) const + { + const T *ptr = searchRandom(id); + if(ptr == 0) + { + std::ostringstream msg; + msg << "Object starting with '"< 0;++xit,++yit,--len) + { + int res = *xit - *yit; + if(res != 0 && std::tolower(*xit) != std::tolower(*yit)) + return (res > 0) ? 1 : -1; + } + if(len > 0) + { + if(xit != x.end()) + return 1; + if(yit != y.end()) + return -1; + } + return 0; + } + /// Transforms input string to lower case w/o copy static std::string &toLower(std::string &inout) { std::transform(