예제 #1
0
void MWWorld::ContainerStore::fill (const ESM::InventoryList& items, const ESMS::ESMStore& store)
{
    for (std::vector<ESM::ContItem>::const_iterator iter (items.mList.begin()); iter!=items.mList.end();
        ++iter)
    {
        ManualRef ref (store, iter->mItem.toString());

        if (ref.getPtr().getTypeName()==typeid (ESM::ItemLevList).name())
        {
            /// \todo implement leveled item lists
            continue;
        }

        ref.getPtr().getRefData().setCount (std::abs(iter->mCount)); /// \todo implement item restocking (indicated by negative count)
        add (ref.getPtr());
    }

    flagAsModified();
}
예제 #2
0
void MWWorld::ContainerStore::addInitialItem (const std::string& id, const std::string& owner,
                                              int count, bool topLevel, const std::string& levItem)
{
    if (count == 0) return; //Don't restock with nothing.
    try {
        ManualRef ref (MWBase::Environment::get().getWorld()->getStore(), id, count);

        if (ref.getPtr().getTypeName()==typeid (ESM::ItemLevList).name())
        {
            const ESM::ItemLevList* levItemList = ref.getPtr().get<ESM::ItemLevList>()->mBase;

            if (topLevel && std::abs(count) > 1 && levItemList->mFlags & ESM::ItemLevList::Each)
            {
                for (int i=0; i<std::abs(count); ++i)
                    addInitialItem(id, owner, count > 0 ? 1 : -1, true, levItemList->mId);
                return;
            }
            else
            {
                std::string itemId = MWMechanics::getLevelledItem(ref.getPtr().get<ESM::ItemLevList>()->mBase, false);
                if (itemId.empty())
                    return;
                addInitialItem(itemId, owner, count, false, levItemList->mId);
            }
        }
        else
        {
            // A negative count indicates restocking items
            // For a restocking levelled item, remember what we spawned so we can delete it later when the merchant restocks
            if (!levItem.empty() && count < 0)
            {
                //If there is no item in map, insert it
                std::map<std::pair<std::string, std::string>, int>::iterator itemInMap =
                    mLevelledItemMap.insert(std::make_pair(std::make_pair(id, levItem), 0)).first;
                //Update spawned count
                itemInMap->second += std::abs(count);
            }
            count = std::abs(count);

            ref.getPtr().getCellRef().setOwner(owner);
            addImp (ref.getPtr(), count);
        }
    }
    catch (const std::exception& e)
    {
        std::cerr << "Warning: MWWorld::ContainerStore::addInitialItem: " << e.what() << std::endl;
    }

}
예제 #3
0
void MWWorld::ContainerStore::addInitialItem (const std::string& id, const std::string& owner, int count, unsigned char failChance, bool topLevel)
{
    count = std::abs(count); /// \todo implement item restocking (indicated by negative count)

    try
    {
        ManualRef ref (MWBase::Environment::get().getWorld()->getStore(), id);

        if (ref.getPtr().getTypeName()==typeid (ESM::ItemLevList).name())
        {
            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()->getPlayer().getPlayer();
            int playerLevel = MWWorld::Class::get(player).getCreatureStats(player).getLevel();

            failChance += levItem->mChanceNone;

            if (topLevel && count > 1 && levItem->mFlags & ESM::ItemLevList::Each)
            {
                for (int i=0; i<count; ++i)
                    addInitialItem(id, owner, 1, failChance, false);
                return;
            }

            float random = static_cast<float> (std::rand()) / RAND_MAX;
            if (random >= failChance/100.f)
            {
                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::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;
                std::string item = candidates[std::rand()%candidates.size()];
                addInitialItem(item, owner, count, failChance, false);
            }
        }
        else
        {
            ref.getPtr().getRefData().setCount (count);
            ref.getPtr().getCellRef().mOwner = owner;
            addImp (ref.getPtr());
        }
    }
    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;
    }
}