Beispiel #1
0
MWWorld::ContainerStoreIterator MWWorld::ContainerStore::add (const Ptr& itemPtr, const Ptr& actorPtr)
{
    MWWorld::ContainerStoreIterator it = addImp(itemPtr);
    MWWorld::Ptr item = *it;

    std::string script = MWWorld::Class::get(item).getScript(item);
    if(script != "")
    {
        CellStore *cell;

        Ptr player = MWBase::Environment::get().getWorld ()->getPlayer().getPlayer();

        if(&(MWWorld::Class::get (player).getContainerStore (player)) == this)
        {
            cell = 0; // Items in player's inventory have cell set to 0, so their scripts will never be removed

            // Set OnPCAdd special variable, if it is declared
            item.getRefData().getLocals().setVarByInt(script, "onpcadd", 1);
        }
        else
            cell = player.getCell();

        item.mCell = cell;
        item.mContainerStore = 0;
        MWBase::Environment::get().getWorld()->getLocalScripts().add(script, item);
    }

    return it;
}
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;
    }

}
Beispiel #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;
    }
}
MWWorld::ContainerStoreIterator MWWorld::ContainerStore::add (const Ptr& itemPtr, int count, const Ptr& actorPtr, bool setOwner)
{
    Ptr player = MWBase::Environment::get().getWorld ()->getPlayerPtr();

    MWWorld::ContainerStoreIterator it = end();

    // HACK: Set owner on the original item, then reset it after we have copied it
    // If we set the owner on the copied item, it would not stack correctly...
    std::string oldOwner = itemPtr.getCellRef().getOwner();
    if (!setOwner || actorPtr == MWMechanics::getPlayer()) // No point in setting owner to the player - NPCs will not respect this anyway
    {
        itemPtr.getCellRef().setOwner("");
    }
    else
    {
        itemPtr.getCellRef().setOwner(actorPtr.getCellRef().getRefId());
    }

    it = addImp(itemPtr, count);

    itemPtr.getCellRef().setOwner(oldOwner);

    // The copy of the original item we just made
    MWWorld::Ptr item = *it;

    // we may have copied an item from the world, so reset a few things first
    item.getRefData().setBaseNode(NULL); // Especially important, otherwise scripts on the item could think that it's actually in a cell
    ESM::Position pos;
    pos.rot[0] = 0;
    pos.rot[1] = 0;
    pos.rot[2] = 0;
    pos.pos[0] = 0;
    pos.pos[1] = 0;
    pos.pos[2] = 0;
    item.getCellRef().setPosition(pos);

    // reset ownership stuff, owner was already handled above
    item.getCellRef().resetGlobalVariable();
    item.getCellRef().setFaction("");
    item.getCellRef().setFactionRank(-1);

    // must reset the RefNum on the copied item, so that the RefNum on the original item stays unique
    // maybe we should do this in the copy constructor instead?
    item.getCellRef().unsetRefNum(); // destroy link to content file

    std::string script = item.getClass().getScript(item);
    if(script != "")
    {
        if (actorPtr == player)
        {
            // Items in player's inventory have cell set to 0, so their scripts will never be removed
            item.mCell = 0;
        }
        else
        {
            // Set mCell to the cell of the container/actor, so that the scripts are removed properly when
            // the cell of the container/actor goes inactive
            item.mCell = actorPtr.getCell();
        }

        item.mContainerStore = this;

        MWBase::Environment::get().getWorld()->getLocalScripts().add(script, item);

        // Set OnPCAdd special variable, if it is declared
        // Make sure to do this *after* we have added the script to LocalScripts
        if (actorPtr == player)
            item.getRefData().getLocals().setVarByInt(script, "onpcadd", 1);
    }

    if (mListener)
        mListener->itemAdded(item, count);

    return it;
}
Beispiel #5
0
void ConstraintStorage::addImp(std::vector<ReifiedLinearConstraint>&& vl)
{
    for (auto& l : vl)
        addImp(std::move(l));
}