mirror of
https://github.com/TES3MP/openmw-tes3mp.git
synced 2025-01-21 12:53:51 +00:00
Move levelled list code out of ContainerStore
This commit is contained in:
parent
6aa56354c0
commit
90b92a8f41
4 changed files with 98 additions and 63 deletions
|
@ -74,7 +74,7 @@ add_openmw_dir (mwmechanics
|
||||||
mechanicsmanagerimp stat character creaturestats magiceffects movement actors objects
|
mechanicsmanagerimp stat character creaturestats magiceffects movement actors objects
|
||||||
drawstate spells activespells npcstats aipackage aisequence alchemy aiwander aitravel aifollow
|
drawstate spells activespells npcstats aipackage aisequence alchemy aiwander aitravel aifollow
|
||||||
aiescort aiactivate aicombat repair enchanting pathfinding security spellsuccess spellcasting
|
aiescort aiactivate aicombat repair enchanting pathfinding security spellsuccess spellcasting
|
||||||
disease pickpocket
|
disease pickpocket levelledlist
|
||||||
)
|
)
|
||||||
|
|
||||||
add_openmw_dir (mwbase
|
add_openmw_dir (mwbase
|
||||||
|
|
78
apps/openmw/mwmechanics/levelledlist.hpp
Normal file
78
apps/openmw/mwmechanics/levelledlist.hpp
Normal file
|
@ -0,0 +1,78 @@
|
||||||
|
#ifndef OPENMW_MECHANICS_LEVELLEDLIST_H
|
||||||
|
#define OPENMW_MECHANICS_LEVELLEDLIST_H
|
||||||
|
|
||||||
|
#include "../mwworld/ptr.hpp"
|
||||||
|
#include "../mwworld/manualref.hpp"
|
||||||
|
#include "../mwworld/class.hpp"
|
||||||
|
#include "../mwbase/world.hpp"
|
||||||
|
#include "../mwbase/environment.hpp"
|
||||||
|
|
||||||
|
namespace MWMechanics
|
||||||
|
{
|
||||||
|
|
||||||
|
/// @return ID of resulting item, or empty if none
|
||||||
|
std::string getLevelledItem (const ESM::LeveledListBase* levItem, unsigned char failChance=0)
|
||||||
|
{
|
||||||
|
const std::vector<ESM::LeveledListBase::LevelItem>& items = levItem->mList;
|
||||||
|
|
||||||
|
const MWWorld::Ptr& player = MWBase::Environment::get().getWorld()->getPlayerPtr();
|
||||||
|
int playerLevel = player.getClass().getCreatureStats(player).getLevel();
|
||||||
|
|
||||||
|
failChance += levItem->mChanceNone;
|
||||||
|
|
||||||
|
float random = static_cast<float> (std::rand()) / RAND_MAX;
|
||||||
|
if (random < failChance/100.f)
|
||||||
|
return std::string();
|
||||||
|
|
||||||
|
std::vector<std::string> candidates;
|
||||||
|
int highestLevel = 0;
|
||||||
|
for (std::vector<ESM::LeveledListBase::LevelItem>::const_iterator it = items.begin(); it != items.end(); ++it)
|
||||||
|
{
|
||||||
|
if (it->mLevel > highestLevel)
|
||||||
|
highestLevel = it->mLevel;
|
||||||
|
}
|
||||||
|
|
||||||
|
std::pair<int, std::string> highest = std::make_pair(-1, "");
|
||||||
|
for (std::vector<ESM::LeveledListBase::LevelItem>::const_iterator it = items.begin(); it != items.end(); ++it)
|
||||||
|
{
|
||||||
|
if (playerLevel >= it->mLevel
|
||||||
|
&& (levItem->mFlags & ESM::LeveledListBase::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()];
|
||||||
|
|
||||||
|
// Is this another levelled item or a real item?
|
||||||
|
try
|
||||||
|
{
|
||||||
|
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, failChance);
|
||||||
|
else
|
||||||
|
return getLevelledItem(ref.getPtr().get<ESM::CreatureLevList>()->mBase, failChance);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
catch (std::logic_error& e)
|
||||||
|
{
|
||||||
|
// Vanilla doesn't fail on nonexistent items in levelled lists
|
||||||
|
std::cerr << "Warning: ignoring nonexistent item '" << item << "'" << std::endl;
|
||||||
|
return std::string();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
#endif
|
|
@ -5,17 +5,11 @@
|
||||||
#include <typeinfo>
|
#include <typeinfo>
|
||||||
#include <stdexcept>
|
#include <stdexcept>
|
||||||
|
|
||||||
#include <boost/algorithm/string.hpp>
|
|
||||||
|
|
||||||
#include <components/esm/loadcont.hpp>
|
|
||||||
#include <components/compiler/locals.hpp>
|
|
||||||
#include <components/misc/stringops.hpp>
|
|
||||||
|
|
||||||
#include "../mwbase/environment.hpp"
|
#include "../mwbase/environment.hpp"
|
||||||
#include "../mwbase/world.hpp"
|
#include "../mwbase/world.hpp"
|
||||||
#include "../mwbase/scriptmanager.hpp"
|
|
||||||
|
|
||||||
#include "../mwmechanics/creaturestats.hpp"
|
#include "../mwmechanics/creaturestats.hpp"
|
||||||
|
#include "../mwmechanics/levelledlist.hpp"
|
||||||
|
|
||||||
#include "manualref.hpp"
|
#include "manualref.hpp"
|
||||||
#include "refdata.hpp"
|
#include "refdata.hpp"
|
||||||
|
@ -309,58 +303,28 @@ void MWWorld::ContainerStore::fill (const ESM::InventoryList& items, const std::
|
||||||
}
|
}
|
||||||
|
|
||||||
void MWWorld::ContainerStore::addInitialItem (const std::string& id, const std::string& owner, const std::string& faction,
|
void MWWorld::ContainerStore::addInitialItem (const std::string& id, const std::string& owner, const std::string& faction,
|
||||||
int count, unsigned char failChance, bool topLevel)
|
int count, bool topLevel)
|
||||||
{
|
{
|
||||||
count = std::abs(count); /// \todo implement item restocking (indicated by negative count)
|
count = std::abs(count); /// \todo implement item restocking (indicated by negative count)
|
||||||
|
|
||||||
try
|
|
||||||
{
|
|
||||||
ManualRef ref (MWBase::Environment::get().getWorld()->getStore(), id, count);
|
ManualRef ref (MWBase::Environment::get().getWorld()->getStore(), id, count);
|
||||||
|
|
||||||
if (ref.getPtr().getTypeName()==typeid (ESM::ItemLevList).name())
|
if (ref.getPtr().getTypeName()==typeid (ESM::ItemLevList).name())
|
||||||
{
|
{
|
||||||
const ESM::ItemLevList* levItem = ref.getPtr().get<ESM::ItemLevList>()->mBase;
|
const ESM::ItemLevList* levItem = ref.getPtr().get<ESM::ItemLevList>()->mBase;
|
||||||
const std::vector<ESM::LeveledListBase::LevelItem>& items = levItem->mList;
|
|
||||||
|
|
||||||
MWWorld::Ptr player = MWBase::Environment::get().getWorld()->getPlayerPtr();
|
|
||||||
int playerLevel = player.getClass().getCreatureStats(player).getLevel();
|
|
||||||
|
|
||||||
failChance += levItem->mChanceNone;
|
|
||||||
|
|
||||||
if (topLevel && count > 1 && levItem->mFlags & ESM::ItemLevList::Each)
|
if (topLevel && count > 1 && levItem->mFlags & ESM::ItemLevList::Each)
|
||||||
{
|
{
|
||||||
for (int i=0; i<count; ++i)
|
for (int i=0; i<count; ++i)
|
||||||
addInitialItem(id, owner, faction, 1, failChance, false);
|
addInitialItem(id, owner, faction, 1);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
else
|
||||||
float random = static_cast<float> (std::rand()) / RAND_MAX;
|
|
||||||
if (random >= failChance/100.f)
|
|
||||||
{
|
{
|
||||||
std::vector<std::string> candidates;
|
std::string id = MWMechanics::getLevelledItem(ref.getPtr().get<ESM::ItemLevList>()->mBase);
|
||||||
int highestLevel = 0;
|
if (id.empty())
|
||||||
for (std::vector<ESM::LeveledListBase::LevelItem>::const_iterator it = items.begin(); it != items.end(); ++it)
|
|
||||||
{
|
|
||||||
if (it->mLevel > highestLevel)
|
|
||||||
highestLevel = it->mLevel;
|
|
||||||
}
|
|
||||||
|
|
||||||
std::pair<int, std::string> highest = std::make_pair(-1, "");
|
|
||||||
for (std::vector<ESM::LeveledListBase::LevelItem>::const_iterator it = items.begin(); it != items.end(); ++it)
|
|
||||||
{
|
|
||||||
if (playerLevel >= it->mLevel
|
|
||||||
&& (levItem->mFlags & ESM::ItemLevList::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;
|
return;
|
||||||
std::string item = candidates[std::rand()%candidates.size()];
|
addInitialItem(id, owner, faction, count, false);
|
||||||
addInitialItem(item, owner, faction, count, failChance, false);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
|
@ -370,13 +334,6 @@ void MWWorld::ContainerStore::addInitialItem (const std::string& id, const std::
|
||||||
addImp (ref.getPtr(), count);
|
addImp (ref.getPtr(), count);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
catch (std::logic_error& e)
|
|
||||||
{
|
|
||||||
// Vanilla doesn't fail on nonexistent items in levelled lists
|
|
||||||
std::cerr << "Warning: ignoring nonexistent item '" << id << "'" << std::endl;
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
void MWWorld::ContainerStore::clear()
|
void MWWorld::ContainerStore::clear()
|
||||||
{
|
{
|
||||||
|
|
|
@ -54,7 +54,7 @@ namespace MWWorld
|
||||||
mutable float mCachedWeight;
|
mutable float mCachedWeight;
|
||||||
mutable bool mWeightUpToDate;
|
mutable bool mWeightUpToDate;
|
||||||
ContainerStoreIterator addImp (const Ptr& ptr, int count);
|
ContainerStoreIterator addImp (const Ptr& ptr, int count);
|
||||||
void addInitialItem (const std::string& id, const std::string& owner, const std::string& faction, int count, unsigned char failChance=0, bool topLevel=true);
|
void addInitialItem (const std::string& id, const std::string& owner, const std::string& faction, int count, bool topLevel=true);
|
||||||
|
|
||||||
public:
|
public:
|
||||||
|
|
||||||
|
|
Loading…
Reference in a new issue