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<ESM::Sound>().searchRandom("WolfItem");
+
             boost::shared_ptr<MWWorld::Action> 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<ESM::Sound>().searchRandom("WolfContainer");
+
             boost::shared_ptr<MWWorld::Action> 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<ESM::Sound>().searchRandom("WolfCreature");
+
             boost::shared_ptr<MWWorld::Action> 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<ESM::Sound>().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<ESM::Sound>().searchRandom("WolfNPC");
+
             boost::shared_ptr<MWWorld::Action> 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<ESM::Sound>().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<ESM::Sound>().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<ESM::Sound>().searchRandom("WolfItem");
+
             boost::shared_ptr<MWWorld::Action> 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<std::string, T> Dynamic;
         typedef std::map<std::string, T> Static;
 
+        class GetRecords {
+            const std::string mFind;
+            std::vector<const T*> *mRecords;
+
+        public:
+            GetRecords(const std::string &str, std::vector<const T*> *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<const T*> 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 '"<<id<<"' not found (const)";
+                throw std::runtime_error(msg.str());
+            }
+            return ptr;
+        }
+
         void load(ESM::ESMReader &esm, const std::string &id) {
             std::string idLower = Misc::StringUtils::lowerCase(id);
             mStatic[idLower] = T();
diff --git a/components/misc/stringops.hpp b/components/misc/stringops.hpp
index 029b617e1..d41463cfc 100644
--- a/components/misc/stringops.hpp
+++ b/components/misc/stringops.hpp
@@ -35,6 +35,26 @@ public:
         return true;
     }
 
+    static int ciCompareLen(const std::string &x, const std::string &y, size_t len)
+    {
+        std::string::const_iterator xit = x.begin();
+        std::string::const_iterator yit = y.begin();
+        for(;xit != x.end() && yit != y.end() && len > 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(