From b57dd6d083c851ea8dc614d1f99a997557db601d Mon Sep 17 00:00:00 2001 From: fteppe Date: Wed, 12 Oct 2022 19:51:42 +0200 Subject: [PATCH] Fixed search random, it is a prefix so not a refId Fixed situation where we return a const reference to a static variable that may change if the same function is called multiple times --- apps/openmw/mwclass/activator.cpp | 2 +- apps/openmw/mwclass/armor.cpp | 25 +++++++++--------- apps/openmw/mwclass/book.cpp | 2 +- apps/openmw/mwclass/container.cpp | 2 +- apps/openmw/mwclass/creature.cpp | 2 +- apps/openmw/mwclass/npc.cpp | 38 ++++++++++++++++++--------- apps/openmw/mwmechanics/character.cpp | 4 +-- apps/openmw/mwmechanics/combat.cpp | 2 +- apps/openmw/mwworld/class.cpp | 2 +- apps/openmw/mwworld/store.cpp | 4 +-- apps/openmw/mwworld/store.hpp | 2 +- 11 files changed, 49 insertions(+), 36 deletions(-) diff --git a/apps/openmw/mwclass/activator.cpp b/apps/openmw/mwclass/activator.cpp index 82e16bcfc8..a9fe07df53 100644 --- a/apps/openmw/mwclass/activator.cpp +++ b/apps/openmw/mwclass/activator.cpp @@ -122,7 +122,7 @@ namespace MWClass { const MWWorld::ESMStore& store = MWBase::Environment::get().getWorld()->getStore(); auto& prng = MWBase::Environment::get().getWorld()->getPrng(); - const ESM::Sound* sound = store.get().searchRandom(ESM::RefId::stringRefId("WolfActivator"), prng); + const ESM::Sound* sound = store.get().searchRandom("WolfActivator", prng); std::unique_ptr action = std::make_unique("#{sWerewolfRefusal}"); if (sound) diff --git a/apps/openmw/mwclass/armor.cpp b/apps/openmw/mwclass/armor.cpp index 94ea269e5f..2825b3e1d7 100644 --- a/apps/openmw/mwclass/armor.cpp +++ b/apps/openmw/mwclass/armor.cpp @@ -179,29 +179,30 @@ namespace MWClass const ESM::RefId& Armor::getUpSoundId(const MWWorld::ConstPtr& ptr) const { int es = getEquipmentSkill(ptr); - std::string soundName; + static const ESM::RefId lightUp = ESM::RefId::stringRefId("Item Armor Light Up"); + static const ESM::RefId mediumUp = ESM::RefId::stringRefId("Item Armor Medium Up"); + static const ESM::RefId heavyUp = ESM::RefId::stringRefId("Item Armor Heavy Up"); + if (es == ESM::Skill::LightArmor) - soundName = "Item Armor Light Up"; + return lightUp; else if (es == ESM::Skill::MediumArmor) - soundName = "Item Armor Medium Up"; + return mediumUp; else - soundName = "Item Armor Heavy Up"; - static const ESM::RefId id = ESM::RefId::stringRefId(soundName); - return id; + return heavyUp; } const ESM::RefId& Armor::getDownSoundId(const MWWorld::ConstPtr& ptr) const { int es = getEquipmentSkill(ptr); - std::string soundName; + static const ESM::RefId lightDown = ESM::RefId::stringRefId("Item Armor Light Down"); + static const ESM::RefId mediumDown = ESM::RefId::stringRefId("Item Armor Medium Down"); + static const ESM::RefId heavyDown = ESM::RefId::stringRefId("Item Armor Heavy Down"); if (es == ESM::Skill::LightArmor) - soundName = "Item Armor Light Down"; + return lightDown; else if (es == ESM::Skill::MediumArmor) - soundName = "Item Armor Medium Down"; + return mediumDown; else - soundName = "Item Armor Heavy Down"; - static const ESM::RefId id = ESM::RefId::stringRefId(soundName); - return id; + return heavyDown; } const std::string& Armor::getInventoryIcon(const MWWorld::ConstPtr& ptr) const diff --git a/apps/openmw/mwclass/book.cpp b/apps/openmw/mwclass/book.cpp index 55d5d29485..df00970f5f 100644 --- a/apps/openmw/mwclass/book.cpp +++ b/apps/openmw/mwclass/book.cpp @@ -60,7 +60,7 @@ namespace MWClass { const MWWorld::ESMStore& store = MWBase::Environment::get().getWorld()->getStore(); auto& prng = MWBase::Environment::get().getWorld()->getPrng(); - const ESM::Sound* sound = store.get().searchRandom(ESM::RefId::stringRefId("WolfItem"), prng); + const ESM::Sound* sound = store.get().searchRandom("WolfItem", prng); std::unique_ptr action = std::make_unique("#{sWerewolfRefusal}"); if (sound) diff --git a/apps/openmw/mwclass/container.cpp b/apps/openmw/mwclass/container.cpp index 825ca75213..5635a5d00a 100644 --- a/apps/openmw/mwclass/container.cpp +++ b/apps/openmw/mwclass/container.cpp @@ -143,7 +143,7 @@ namespace MWClass { const MWWorld::ESMStore& store = MWBase::Environment::get().getWorld()->getStore(); auto& prng = MWBase::Environment::get().getWorld()->getPrng(); - const ESM::Sound* sound = store.get().searchRandom(ESM::RefId::stringRefId("WolfContainer"), prng); + const ESM::Sound* sound = store.get().searchRandom("WolfContainer", prng); std::unique_ptr action = std::make_unique("#{sWerewolfRefusal}"); if (sound) diff --git a/apps/openmw/mwclass/creature.cpp b/apps/openmw/mwclass/creature.cpp index beecc2c8b2..38aef45d85 100644 --- a/apps/openmw/mwclass/creature.cpp +++ b/apps/openmw/mwclass/creature.cpp @@ -469,7 +469,7 @@ namespace MWClass { const MWWorld::ESMStore& store = MWBase::Environment::get().getWorld()->getStore(); auto& prng = MWBase::Environment::get().getWorld()->getPrng(); - const ESM::Sound* sound = store.get().searchRandom(ESM::RefId::stringRefId("WolfCreature"), prng); + const ESM::Sound* sound = store.get().searchRandom("WolfCreature", prng); std::unique_ptr action = std::make_unique("#{sWerewolfRefusal}"); if (sound) diff --git a/apps/openmw/mwclass/npc.cpp b/apps/openmw/mwclass/npc.cpp index b4457530e3..11a5db3529 100644 --- a/apps/openmw/mwclass/npc.cpp +++ b/apps/openmw/mwclass/npc.cpp @@ -933,7 +933,7 @@ namespace MWClass { const MWWorld::ESMStore& store = MWBase::Environment::get().getWorld()->getStore(); auto& prng = MWBase::Environment::get().getWorld()->getPrng(); - const ESM::Sound* sound = store.get().searchRandom(ESM::RefId::stringRefId("WolfNPC"), prng); + const ESM::Sound* sound = store.get().searchRandom("WolfNPC", prng); std::unique_ptr action = std::make_unique("#{sWerewolfRefusal}"); if (sound) @@ -1289,7 +1289,20 @@ namespace MWClass const ESM::RefId& Npc::getSoundIdFromSndGen(const MWWorld::Ptr& ptr, std::string_view name) const { - std::string sound; + static const ESM::RefId swimLeft = ESM::RefId::stringRefId("Swim Left"); + static const ESM::RefId swimRight = ESM::RefId::stringRefId("Swim Right"); + static const ESM::RefId footWaterLeft = ESM::RefId::stringRefId("FootWaterLeft"); + static const ESM::RefId footWaterRight = ESM::RefId::stringRefId("FootWaterRight"); + static const ESM::RefId footBareLeft = ESM::RefId::stringRefId("FootBareLeft"); + static const ESM::RefId footBareRight = ESM::RefId::stringRefId("FootBareRight"); + static const ESM::RefId footLightLeft = ESM::RefId::stringRefId("footLightLeft"); + static const ESM::RefId footLightRight = ESM::RefId::stringRefId("footLightRight"); + static const ESM::RefId footMediumRight = ESM::RefId::stringRefId("FootMedRight"); + static const ESM::RefId footMediumLeft = ESM::RefId::stringRefId("FootMedLeft"); + static const ESM::RefId footHeavyLeft = ESM::RefId::stringRefId("footHeavyLeft"); + static const ESM::RefId footHeavyRight = ESM::RefId::stringRefId("footHeavyRight"); + + const ESM::RefId* sound = nullptr; if (name == "left" || name == "right") { MWBase::World* world = MWBase::Environment::get().getWorld(); @@ -1297,9 +1310,9 @@ namespace MWClass return ESM::RefId::sEmpty; osg::Vec3f pos(ptr.getRefData().getPosition().asVec3()); if (world->isSwimming(ptr)) - sound = (name == "left") ? "Swim Left" : "Swim Right"; + sound = (name == "left") ? &swimLeft : &swimRight; if (world->isUnderwater(ptr.getCell(), pos) || world->isWalkingOnWater(ptr)) - sound = (name == "left") ? "FootWaterLeft" : "FootWaterRight"; + sound = (name == "left") ? &footWaterLeft : &footWaterRight; if (world->isOnGround(ptr)) { if (getNpcStats(ptr).isWerewolf() @@ -1314,16 +1327,16 @@ namespace MWClass const MWWorld::InventoryStore& inv = Npc::getInventoryStore(ptr); MWWorld::ConstContainerStoreIterator boots = inv.getSlot(MWWorld::InventoryStore::Slot_Boots); if (boots == inv.end() || boots->getType() != ESM::Armor::sRecordId) - sound = (name == "left") ? "FootBareLeft" : "FootBareRight"; + sound = (name == "left") ? &footBareLeft : &footBareRight; switch (boots->getClass().getEquipmentSkill(*boots)) { case ESM::Skill::LightArmor: - sound = (name == "left") ? "FootLightLeft" : "FootLightRight"; break; + sound = (name == "left") ? &footLightLeft : &footLightRight; break; case ESM::Skill::MediumArmor: - sound = (name == "left") ? "FootMedLeft" : "FootMedRight"; break; + sound = (name == "left") ? &footMediumLeft : &footMediumRight; break; case ESM::Skill::HeavyArmor: - sound = (name == "left") ? "FootHeavyLeft" : "FootHeavyRight"; break; + sound = (name == "left") ? &footHeavyLeft : &footHeavyRight; break; } } return ESM::RefId::sEmpty; @@ -1333,9 +1346,9 @@ namespace MWClass if (name == "land") return ESM::RefId::sEmpty; if (name == "swimleft") - sound = "Swim Left"; + sound = &swimLeft; if (name == "swimright") - sound = "Swim Right"; + sound = &swimRight; // 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? @@ -1347,12 +1360,11 @@ namespace MWClass if (name == "scream") return ESM::RefId::sEmpty; - if(sound.empty()) + if(sound == nullptr) throw std::runtime_error("Unexpected soundgen type: " + std::string(name)); else { - static auto soundId = ESM::RefId::stringRefId(sound); - return soundId; + return *sound; } } diff --git a/apps/openmw/mwmechanics/character.cpp b/apps/openmw/mwmechanics/character.cpp index 229c912a51..884de9b147 100644 --- a/apps/openmw/mwmechanics/character.cpp +++ b/apps/openmw/mwmechanics/character.cpp @@ -1420,7 +1420,7 @@ namespace MWMechanics if (isWerewolf) { const MWWorld::ESMStore& store = world->getStore(); - const ESM::Sound* sound = store.get().searchRandom(ESM::RefId::stringRefId("WolfEquip"), prng); + const ESM::Sound* sound = store.get().searchRandom("WolfEquip", prng); if (sound) { sndMgr->playSound3D(mPtr, sound->mId, 1.0f, 1.0f); @@ -2855,7 +2855,7 @@ namespace MWMechanics { MWBase::World* world = MWBase::Environment::get().getWorld(); const MWWorld::ESMStore& store = world->getStore(); - const ESM::Sound* sound = store.get().searchRandom(ESM::RefId::stringRefId("WolfSwing"), world->getPrng()); + const ESM::Sound* sound = store.get().searchRandom("WolfSwing", world->getPrng()); if (sound) soundId = &sound->mId; } diff --git a/apps/openmw/mwmechanics/combat.cpp b/apps/openmw/mwmechanics/combat.cpp index edb04bd6ab..755d3eb2b9 100644 --- a/apps/openmw/mwmechanics/combat.cpp +++ b/apps/openmw/mwmechanics/combat.cpp @@ -493,7 +493,7 @@ namespace MWMechanics if (isWerewolf) { auto& prng = MWBase::Environment::get().getWorld()->getPrng(); - const ESM::Sound* sound = store.get().searchRandom(ESM::RefId::stringRefId("WolfHit"), prng); + const ESM::Sound* sound = store.get().searchRandom("WolfHit", prng); if (sound) sndMgr->playSound3D(victim, sound->mId, 1.0f, 1.0f); } diff --git a/apps/openmw/mwworld/class.cpp b/apps/openmw/mwworld/class.cpp index 49bdc65168..5e0aa27a89 100644 --- a/apps/openmw/mwworld/class.cpp +++ b/apps/openmw/mwworld/class.cpp @@ -347,7 +347,7 @@ namespace MWWorld { const MWWorld::ESMStore& store = MWBase::Environment::get().getWorld()->getStore(); auto& prng = MWBase::Environment::get().getWorld()->getPrng(); - const ESM::Sound* sound = store.get().searchRandom(ESM::RefId::stringRefId("WolfItem"), prng); + const ESM::Sound* sound = store.get().searchRandom("WolfItem", prng); std::unique_ptr action = std::make_unique("#{sWerewolfRefusal}"); if (sound) diff --git a/apps/openmw/mwworld/store.cpp b/apps/openmw/mwworld/store.cpp index f17d3838db..8f776bd861 100644 --- a/apps/openmw/mwworld/store.cpp +++ b/apps/openmw/mwworld/store.cpp @@ -145,11 +145,11 @@ namespace MWWorld return (dit != mDynamic.end()); } template - const T* TypedDynamicStore::searchRandom(const ESM::RefId& id, Misc::Rng::Generator& prng) const + const T* TypedDynamicStore::searchRandom(const std::string_view prefix, Misc::Rng::Generator& prng) const { std::vector results; std::copy_if(mShared.begin(), mShared.end(), std::back_inserter(results), - [&id](const T* item) { return Misc::StringUtils::ciStartsWith(item->mId.getRefIdString(), id.getRefIdString()); }); + [prefix](const T* item) { return Misc::StringUtils::ciStartsWith(item->mId.getRefIdString(), prefix); }); if (!results.empty()) return results[Misc::Rng::rollDice(results.size(), prng)]; return nullptr; diff --git a/apps/openmw/mwworld/store.hpp b/apps/openmw/mwworld/store.hpp index d3a78f81e7..68f4dfdb58 100644 --- a/apps/openmw/mwworld/store.hpp +++ b/apps/openmw/mwworld/store.hpp @@ -200,7 +200,7 @@ namespace MWWorld bool isDynamic(const ESM::RefId& id) const; /** Returns a random record that starts with the named ID, or nullptr if not found. */ - const T* searchRandom(const ESM::RefId& id, Misc::Rng::Generator& prng) const; + const T* searchRandom(const std::string_view prefix, Misc::Rng::Generator& prng) const; // calls `search` and throws an exception if not found const T* find(const ESM::RefId& id) const;