diff --git a/CHANGELOG.md b/CHANGELOG.md index 320e486937..ddf20fa7f3 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -155,6 +155,7 @@ Feature #4012: Editor: Write a log file if OpenCS crashes Feature #4222: 360° screenshots Feature #4256: Implement ToggleBorders (TB) console command + Feature #4285: Support soundgen calls for activators Feature #4324: Add CFBundleIdentifier in Info.plist to allow for macOS function key shortcuts Feature #4345: Add equivalents for the command line commands to Launcher Feature #4404: Editor: All EnumDelegate fields should have their items sorted alphabetically diff --git a/apps/openmw/mwclass/activator.cpp b/apps/openmw/mwclass/activator.cpp index 8df262f240..e0e2013912 100644 --- a/apps/openmw/mwclass/activator.cpp +++ b/apps/openmw/mwclass/activator.cpp @@ -1,6 +1,7 @@ #include "activator.hpp" #include +#include #include "../mwbase/environment.hpp" #include "../mwbase/windowmanager.hpp" @@ -134,4 +135,60 @@ namespace MWClass return MWWorld::Ptr(cell.insert(ref), &cell); } + + std::string Activator::getSoundIdFromSndGen(const MWWorld::Ptr &ptr, const std::string &name) const + { + std::string model = getModel(ptr); // Assume it's not empty, since we wouldn't have gotten the soundgen otherwise + const MWWorld::ESMStore &store = MWBase::Environment::get().getWorld()->getStore(); + std::string creatureId; + + for (const ESM::Creature &iter : store.get()) + { + if (!iter.mModel.empty() && Misc::StringUtils::ciEqual(model, "meshes\\" + iter.mModel)) + { + creatureId = !iter.mOriginal.empty() ? iter.mOriginal : iter.mId; + break; + } + } + + if (creatureId.empty()) + return std::string(); + + int type = getSndGenTypeFromName(name); + std::vector sounds; + + for (auto sound = store.get().begin(); sound != store.get().end(); ++sound) + if (type == sound->mType && !sound->mCreature.empty() && (Misc::StringUtils::ciEqual(creatureId, sound->mCreature))) + sounds.push_back(&*sound); + + if (!sounds.empty()) + return sounds[Misc::Rng::rollDice(sounds.size())]->mSound; + + if (type == ESM::SoundGenerator::Land) + return "Body Fall Large"; + + return std::string(); + } + + int Activator::getSndGenTypeFromName(const std::string &name) + { + if (name == "left") + return ESM::SoundGenerator::LeftFoot; + if (name == "right") + return ESM::SoundGenerator::RightFoot; + if (name == "swimleft") + return ESM::SoundGenerator::SwimLeft; + if (name == "swimright") + return ESM::SoundGenerator::SwimRight; + if (name == "moan") + return ESM::SoundGenerator::Moan; + if (name == "roar") + return ESM::SoundGenerator::Roar; + if (name == "scream") + return ESM::SoundGenerator::Scream; + if (name == "land") + return ESM::SoundGenerator::Land; + + throw std::runtime_error(std::string("Unexpected soundgen type: ")+name); + } } diff --git a/apps/openmw/mwclass/activator.hpp b/apps/openmw/mwclass/activator.hpp index 3f333f4cbe..b92dc75cbd 100644 --- a/apps/openmw/mwclass/activator.hpp +++ b/apps/openmw/mwclass/activator.hpp @@ -10,6 +10,8 @@ namespace MWClass virtual MWWorld::Ptr copyToCellImpl(const MWWorld::ConstPtr &ptr, MWWorld::CellStore &cell) const; + static int getSndGenTypeFromName(const std::string &name); + public: virtual void insertObjectRendering (const MWWorld::Ptr& ptr, const std::string& model, MWRender::RenderingInterface& renderingInterface) const; @@ -44,6 +46,8 @@ namespace MWClass ///< Whether or not to use animated variant of model (default false) virtual bool isActivator() const; + + virtual std::string getSoundIdFromSndGen(const MWWorld::Ptr &ptr, const std::string &name) const; }; } diff --git a/apps/openmw/mwclass/creature.cpp b/apps/openmw/mwclass/creature.cpp index 6d0b42bfeb..788e5cd689 100644 --- a/apps/openmw/mwclass/creature.cpp +++ b/apps/openmw/mwclass/creature.cpp @@ -688,9 +688,9 @@ namespace MWClass MWBase::World *world = MWBase::Environment::get().getWorld(); osg::Vec3f pos(ptr.getRefData().getPosition().asVec3()); if(world->isUnderwater(ptr.getCell(), pos) || world->isWalkingOnWater(ptr)) - return 2; + return ESM::SoundGenerator::SwimLeft; if(world->isOnGround(ptr)) - return 0; + return ESM::SoundGenerator::LeftFoot; return -1; } if(name == "right") @@ -698,23 +698,23 @@ namespace MWClass MWBase::World *world = MWBase::Environment::get().getWorld(); osg::Vec3f pos(ptr.getRefData().getPosition().asVec3()); if(world->isUnderwater(ptr.getCell(), pos) || world->isWalkingOnWater(ptr)) - return 3; + return ESM::SoundGenerator::SwimRight; if(world->isOnGround(ptr)) - return 1; + return ESM::SoundGenerator::RightFoot; return -1; } if(name == "swimleft") - return 2; + return ESM::SoundGenerator::SwimLeft; if(name == "swimright") - return 3; + return ESM::SoundGenerator::SwimRight; if(name == "moan") - return 4; + return ESM::SoundGenerator::Moan; if(name == "roar") - return 5; + return ESM::SoundGenerator::Roar; if(name == "scream") - return 6; + return ESM::SoundGenerator::Scream; if(name == "land") - return 7; + return ESM::SoundGenerator::Land; throw std::runtime_error(std::string("Unexpected soundgen type: ")+name); }