mirror of
https://gitlab.com/OpenMW/openmw.git
synced 2025-01-30 21:32:42 +00:00
42e45723b7
Fixes issue when fetching MyGui values that were stored as RefId but fetched as String Removed some uncessary copies, fixed issues with lowercase and uneeded changes
88 lines
3.2 KiB
C++
88 lines
3.2 KiB
C++
#ifndef OPENMW_MECHANICS_LEVELLEDLIST_H
|
|
#define OPENMW_MECHANICS_LEVELLEDLIST_H
|
|
|
|
#include <components/debug/debuglog.hpp>
|
|
#include <components/esm3/loadlevlist.hpp>
|
|
#include <components/misc/rng.hpp>
|
|
|
|
#include "../mwworld/class.hpp"
|
|
#include "../mwworld/esmstore.hpp"
|
|
#include "../mwworld/manualref.hpp"
|
|
#include "../mwworld/ptr.hpp"
|
|
|
|
#include "../mwbase/environment.hpp"
|
|
#include "../mwbase/world.hpp"
|
|
|
|
#include "actorutil.hpp"
|
|
#include "creaturestats.hpp"
|
|
|
|
namespace MWMechanics
|
|
{
|
|
|
|
/// @return ID of resulting item, or empty if none
|
|
inline const ESM::RefId& getLevelledItem(
|
|
const ESM::LevelledListBase* levItem, bool creature, Misc::Rng::Generator& prng)
|
|
{
|
|
const std::vector<ESM::LevelledListBase::LevelItem>& items = levItem->mList;
|
|
|
|
const MWWorld::Ptr& player = getPlayer();
|
|
int playerLevel = player.getClass().getCreatureStats(player).getLevel();
|
|
|
|
if (Misc::Rng::roll0to99(prng) < levItem->mChanceNone)
|
|
return ESM::RefId::sEmpty;
|
|
|
|
std::vector<const ESM::RefId*> candidates;
|
|
int highestLevel = 0;
|
|
for (const auto& levelledItem : items)
|
|
{
|
|
if (levelledItem.mLevel > highestLevel && levelledItem.mLevel <= playerLevel)
|
|
highestLevel = levelledItem.mLevel;
|
|
}
|
|
|
|
// For levelled creatures, the flags are swapped. This file format just makes so much sense.
|
|
bool allLevels = (levItem->mFlags & ESM::ItemLevList::AllLevels) != 0;
|
|
if (creature)
|
|
allLevels = levItem->mFlags & ESM::CreatureLevList::AllLevels;
|
|
|
|
std::pair<int, const ESM::RefId*> highest = { -1, nullptr };
|
|
for (const auto& levelledItem : items)
|
|
{
|
|
if (playerLevel >= levelledItem.mLevel && (allLevels || levelledItem.mLevel == highestLevel))
|
|
{
|
|
candidates.push_back(&levelledItem.mId);
|
|
if (levelledItem.mLevel >= highest.first)
|
|
highest = std::make_pair(levelledItem.mLevel, &levelledItem.mId);
|
|
}
|
|
}
|
|
if (candidates.empty())
|
|
return ESM::RefId::sEmpty;
|
|
const ESM::RefId& item = *candidates[Misc::Rng::rollDice(candidates.size(), prng)];
|
|
|
|
// Vanilla doesn't fail on nonexistent items in levelled lists
|
|
if (!MWBase::Environment::get().getWorld()->getStore().find(item))
|
|
{
|
|
Log(Debug::Warning) << "Warning: ignoring nonexistent item '" << item << "' in levelled list '"
|
|
<< levItem->mId << "'";
|
|
return ESM::RefId::sEmpty;
|
|
}
|
|
|
|
// Is this another levelled item or a real item?
|
|
MWWorld::ManualRef ref(MWBase::Environment::get().getWorld()->getStore(), item, 1);
|
|
if (ref.getPtr().getType() != ESM::ItemLevList::sRecordId
|
|
&& ref.getPtr().getType() != ESM::CreatureLevList::sRecordId)
|
|
{
|
|
return item;
|
|
}
|
|
else
|
|
{
|
|
if (ref.getPtr().getType() == ESM::ItemLevList::sRecordId)
|
|
return getLevelledItem(ref.getPtr().get<ESM::ItemLevList>()->mBase, false, prng);
|
|
else
|
|
return getLevelledItem(ref.getPtr().get<ESM::CreatureLevList>()->mBase, true, prng);
|
|
}
|
|
}
|
|
|
|
}
|
|
|
|
#endif
|