1
0
mirror of https://gitlab.com/OpenMW/openmw.git synced 2025-02-21 09:39:56 +00:00

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
This commit is contained in:
fteppe 2022-10-12 19:51:42 +02:00 committed by florent.teppe
parent 62d8fe3fc2
commit b57dd6d083
11 changed files with 49 additions and 36 deletions

View File

@ -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<ESM::Sound>().searchRandom(ESM::RefId::stringRefId("WolfActivator"), prng);
const ESM::Sound* sound = store.get<ESM::Sound>().searchRandom("WolfActivator", prng);
std::unique_ptr<MWWorld::Action> action = std::make_unique<MWWorld::FailedAction>("#{sWerewolfRefusal}");
if (sound)

View File

@ -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

View File

@ -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<ESM::Sound>().searchRandom(ESM::RefId::stringRefId("WolfItem"), prng);
const ESM::Sound* sound = store.get<ESM::Sound>().searchRandom("WolfItem", prng);
std::unique_ptr<MWWorld::Action> action = std::make_unique<MWWorld::FailedAction>("#{sWerewolfRefusal}");
if (sound)

View File

@ -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<ESM::Sound>().searchRandom(ESM::RefId::stringRefId("WolfContainer"), prng);
const ESM::Sound* sound = store.get<ESM::Sound>().searchRandom("WolfContainer", prng);
std::unique_ptr<MWWorld::Action> action = std::make_unique<MWWorld::FailedAction>("#{sWerewolfRefusal}");
if (sound)

View File

@ -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<ESM::Sound>().searchRandom(ESM::RefId::stringRefId("WolfCreature"), prng);
const ESM::Sound* sound = store.get<ESM::Sound>().searchRandom("WolfCreature", prng);
std::unique_ptr<MWWorld::Action> action = std::make_unique<MWWorld::FailedAction>("#{sWerewolfRefusal}");
if (sound)

View File

@ -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<ESM::Sound>().searchRandom(ESM::RefId::stringRefId("WolfNPC"), prng);
const ESM::Sound* sound = store.get<ESM::Sound>().searchRandom("WolfNPC", prng);
std::unique_ptr<MWWorld::Action> action = std::make_unique<MWWorld::FailedAction>("#{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;
}
}

View File

@ -1420,7 +1420,7 @@ namespace MWMechanics
if (isWerewolf)
{
const MWWorld::ESMStore& store = world->getStore();
const ESM::Sound* sound = store.get<ESM::Sound>().searchRandom(ESM::RefId::stringRefId("WolfEquip"), prng);
const ESM::Sound* sound = store.get<ESM::Sound>().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<ESM::Sound>().searchRandom(ESM::RefId::stringRefId("WolfSwing"), world->getPrng());
const ESM::Sound* sound = store.get<ESM::Sound>().searchRandom("WolfSwing", world->getPrng());
if (sound)
soundId = &sound->mId;
}

View File

@ -493,7 +493,7 @@ namespace MWMechanics
if (isWerewolf)
{
auto& prng = MWBase::Environment::get().getWorld()->getPrng();
const ESM::Sound* sound = store.get<ESM::Sound>().searchRandom(ESM::RefId::stringRefId("WolfHit"), prng);
const ESM::Sound* sound = store.get<ESM::Sound>().searchRandom("WolfHit", prng);
if (sound)
sndMgr->playSound3D(victim, sound->mId, 1.0f, 1.0f);
}

View File

@ -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<ESM::Sound>().searchRandom(ESM::RefId::stringRefId("WolfItem"), prng);
const ESM::Sound* sound = store.get<ESM::Sound>().searchRandom("WolfItem", prng);
std::unique_ptr<MWWorld::Action> action = std::make_unique<MWWorld::FailedAction>("#{sWerewolfRefusal}");
if (sound)

View File

@ -145,11 +145,11 @@ namespace MWWorld
return (dit != mDynamic.end());
}
template <typename T>
const T* TypedDynamicStore<T>::searchRandom(const ESM::RefId& id, Misc::Rng::Generator& prng) const
const T* TypedDynamicStore<T>::searchRandom(const std::string_view prefix, Misc::Rng::Generator& prng) const
{
std::vector<const T*> 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;

View File

@ -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;