mirror of
https://github.com/TES3MP/openmw-tes3mp.git
synced 2025-01-19 23:53:52 +00:00
e197f5318b
conversion from 'const float' to 'int', possible loss of data conversion from 'double' to 'int', possible loss of data conversion from 'float' to 'int', possible loss of data
82 lines
3.3 KiB
C++
82 lines
3.3 KiB
C++
#ifndef OPENMW_MECHANICS_LEVELLEDLIST_H
|
|
#define OPENMW_MECHANICS_LEVELLEDLIST_H
|
|
|
|
#include "../mwworld/ptr.hpp"
|
|
#include "../mwworld/esmstore.hpp"
|
|
#include "../mwworld/manualref.hpp"
|
|
#include "../mwworld/class.hpp"
|
|
#include "../mwbase/world.hpp"
|
|
#include "../mwbase/environment.hpp"
|
|
#include "../mwmechanics/creaturestats.hpp"
|
|
|
|
namespace MWMechanics
|
|
{
|
|
|
|
/// @return ID of resulting item, or empty if none
|
|
inline std::string getLevelledItem (const ESM::LevelledListBase* levItem, bool creature, unsigned char failChance=0)
|
|
{
|
|
const std::vector<ESM::LevelledListBase::LevelItem>& items = levItem->mList;
|
|
|
|
const MWWorld::Ptr& player = MWBase::Environment::get().getWorld()->getPlayerPtr();
|
|
int playerLevel = player.getClass().getCreatureStats(player).getLevel();
|
|
|
|
failChance += levItem->mChanceNone;
|
|
|
|
int random = static_cast<int>(static_cast<int>(std::rand() / (static_cast<double> (RAND_MAX)+1) * 100)); // [0, 99]
|
|
if (random < failChance)
|
|
return std::string();
|
|
|
|
std::vector<std::string> candidates;
|
|
int highestLevel = 0;
|
|
for (std::vector<ESM::LevelledListBase::LevelItem>::const_iterator it = items.begin(); it != items.end(); ++it)
|
|
{
|
|
if (it->mLevel > highestLevel && it->mLevel <= playerLevel)
|
|
highestLevel = it->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, std::string> highest = std::make_pair(-1, "");
|
|
for (std::vector<ESM::LevelledListBase::LevelItem>::const_iterator it = items.begin(); it != items.end(); ++it)
|
|
{
|
|
if (playerLevel >= it->mLevel
|
|
&& (allLevels || it->mLevel == highestLevel))
|
|
{
|
|
candidates.push_back(it->mId);
|
|
if (it->mLevel >= highest.first)
|
|
highest = std::make_pair(it->mLevel, it->mId);
|
|
}
|
|
}
|
|
if (candidates.empty())
|
|
return std::string();
|
|
std::string item = candidates[std::rand()%candidates.size()];
|
|
|
|
// Vanilla doesn't fail on nonexistent items in levelled lists
|
|
if (!MWBase::Environment::get().getWorld()->getStore().find(Misc::StringUtils::lowerCase(item)))
|
|
{
|
|
std::cerr << "Warning: ignoring nonexistent item '" << item << "' in levelled list '" << levItem->mId << "'" << std::endl;
|
|
return std::string();
|
|
}
|
|
|
|
// Is this another levelled item or a real item?
|
|
MWWorld::ManualRef ref (MWBase::Environment::get().getWorld()->getStore(), item, 1);
|
|
if (ref.getPtr().getTypeName() != typeid(ESM::ItemLevList).name()
|
|
&& ref.getPtr().getTypeName() != typeid(ESM::CreatureLevList).name())
|
|
{
|
|
return item;
|
|
}
|
|
else
|
|
{
|
|
if (ref.getPtr().getTypeName() == typeid(ESM::ItemLevList).name())
|
|
return getLevelledItem(ref.getPtr().get<ESM::ItemLevList>()->mBase, false, failChance);
|
|
else
|
|
return getLevelledItem(ref.getPtr().get<ESM::CreatureLevList>()->mBase, true, failChance);
|
|
}
|
|
}
|
|
|
|
}
|
|
|
|
#endif
|