• There is NO official Otland's Discord server and NO official Otland's server list. The Otland's Staff does not manage any Discord server or server list. Moderators or administrator of any Discord server or server lists have NO connection to the Otland's Staff. Do not get scammed!

Feature Perfect Autostacking Items 100,0% Stack All for 0.4 and 0.3.6pl1

You don't need to change doPlayerAddItem function. There is a bug inside __queryDestination function, so it will always omit first items for INDEX_WHEREVER.
Here is a fixed version of player.cpp:

C++:
Cylinder* Player::__queryDestination(int32_t& index, const Thing* thing, Item** destItem,
    uint32_t& flags)
{
    if (index == 0 /*drop to capacity window*/ || index == INDEX_WHEREEVER)
    {
        *destItem = NULL;

        const Item* item = thing->getItem();
        if (item == NULL)
        {
            return this;
        }

        //find an appropiate slot
        std::list<Container*> containerList;
        for (int i = SLOT_FIRST; i < SLOT_LAST; ++i)
        {
            Item* inventoryItem = inventory[i];
            if (inventoryItem)
            {
                if (inventoryItem == tradeItem)
                {
                    continue;
                }

                //try find an already existing item to stack with
                if (inventoryItem != item && item->isStackable() && inventoryItem->getID() == item->getID() && inventoryItem->getItemCount() < 100)
                {
                    *destItem = inventoryItem;
                    index = i;
                    return this;
                }
                //check sub-containers
                else if (Container* subContainer = inventoryItem->getContainer())
                {
                    Cylinder* tmpCylinder = NULL;
                    int32_t tmpIndex = INDEX_WHEREEVER;
                    Item* tmpDestItem = NULL;

                    tmpCylinder = subContainer->__queryDestination(tmpIndex, item, &tmpDestItem, flags);
                    if (tmpCylinder && tmpCylinder->__queryAdd(tmpIndex, item, item->getItemCount(), flags) == RET_NOERROR)
                    {
                        index = tmpIndex;
                        *destItem = tmpDestItem;
                        return tmpCylinder;
                    }

                    containerList.push_back(subContainer);
                }
            }
            //empty slot
            else if (__queryAdd(i, item, item->getItemCount(), flags) == RET_NOERROR)
            {
                index = i;
                *destItem = NULL;
                return this;
            }
        }

        //check deeper in the containers
        for (std::list<Container*>::iterator it = containerList.begin(); it != containerList.end(); ++it)
        {
            for (ContainerIterator iit = (*it)->begin(); iit != (*it)->end(); ++iit)
            {
                if (Container* subContainer = (*iit)->getContainer())
                {

                    if (subContainer == tradeItem)
                    {
                        continue;
                    }

                    Cylinder* tmpCylinder = NULL;
                    int32_t tmpIndex = INDEX_WHEREEVER;
                    Item* tmpDestItem = NULL;

                    tmpCylinder = subContainer->__queryDestination(tmpIndex, item, &tmpDestItem, flags);
                    if (tmpCylinder && tmpCylinder->__queryAdd(tmpIndex, item, item->getItemCount(), flags) == RET_NOERROR)
                    {
                        index = tmpIndex;
                        *destItem = tmpDestItem;
                        return tmpCylinder;
                    }
                }
            }
        }
        return this;
    }

    Thing* destThing = __getThing(index);
    if (destThing)
        *destItem = destThing->getItem();

    Cylinder* subCylinder = dynamic_cast<Cylinder*>(destThing);

    if (subCylinder)
    {
        index = INDEX_WHEREEVER;
        *destItem = NULL;
        return subCylinder;
    }
    else
        return this;
}
 
Tested on TFS 0.4 and 0.3.6pl1

Retired from:
Autostacking Items - XTibia - A sua comunidade de Tibia e OTserv

Credits: Exedion
Find the functions and modify !

container.cpp
Code:
Cylinder* Container::__queryDestination(int32_t& index, const Thing* thing, Item** destItem, uint32_t&)
{
        if(index == 254 /*move up*/)
        {
                index = INDEX_WHEREEVER;
                *destItem = NULL;
 
                Container* parentContainer = dynamic_cast<Container*>(getParent());
                if(parentContainer)
                        return parentContainer;
 
                return this;
        }
        else if(index == 255 /*add wherever*/){
                index = INDEX_WHEREEVER;
                *destItem = NULL;
        }
        else if(index >= (int32_t)capacity()){
                        /*
                        if you have a container, maximize it to show all 20 slots
                        then you open a bag that is inside the container you will have a bag with 8 slots
                        and a "grey" area where the other 12 slots where from the container
                        if you drop the item on that grey area
                        the client calculates the slot position as if the bag has 20 slots
                        */
                        index = INDEX_WHEREEVER;
                *destItem = NULL;
        }
 
        const Item* item = thing->getItem();
        if(item == NULL){
                return this;
        }
 
        if(item->isStackable()){
                if(item->getParent() != this){
                        //try find a suitable item to stack with
                        uint32_t n = 0;
                        for(ItemList::iterator cit = itemlist.begin(); cit != itemlist.end(); ++cit){
                                if((*cit) != item && (*cit)->getID() == item->getID() && (*cit)->getItemCount() < 100){
                                        *destItem = (*cit);
                                        index = n;
                                        return this;
                                }
 
                                ++n;
                        }
                }
        }
 
        if(index != INDEX_WHEREEVER){
                Thing* destThing = __getThing(index);
                if(destThing)
                        *destItem = destThing->getItem();
 
                Cylinder* subCylinder = dynamic_cast<Cylinder*>(*destItem);
 
                if(subCylinder){
                        index = INDEX_WHEREEVER;
                        *destItem = NULL;
                        return subCylinder;
                }
        }
 
        return this;
}

item.cpp
Code:
void Item::setDefaultSubtype()
{
        setItemCount(1);
        const ItemType& it = items[id];
        if(it.charges)
                setCharges(it.charges);
}

player.cpp
Code:
Cylinder* Player::__queryDestination(int32_t& index, const Thing* thing, Item** destItem,
        uint32_t& flags)
{
        if(index == 0 /*drop to capacity window*/ || index == INDEX_WHEREEVER){
                *destItem = NULL;
 
                const Item* item = thing->getItem();
                if(item == NULL){
                        return this;
                }
 
                //find an appropiate slot
                std::list<Container*> containerList;
                for(int i = SLOT_FIRST; i < SLOT_LAST; ++i){
                        Item* inventoryItem = inventory[i];
 
                        if(inventoryItem == tradeItem){
                                continue;
                        }
 
                        if(inventoryItem == tradeItem){
                                continue;
                        }
 
                                if(inventoryItem){
                                        //try find an already existing item to stack with
                                if(inventoryItem != item && item->isStackable() && inventoryItem->getID() == item->getID() && inventoryItem->getItemCount() < 100){
                                        *destItem = inventoryItem;
                                        index = i;
                                        return this;
                                }
                                //check sub-containers
                                else if(Container* subContainer = inventoryItem->getContainer()){
                                        Cylinder* tmpCylinder = NULL;
                                        int32_t tmpIndex = INDEX_WHEREEVER;
                                        Item* tmpDestItem = NULL;
 
                                        tmpCylinder = subContainer->__queryDestination(tmpIndex, item, &tmpDestItem, flags);
                                        if(tmpCylinder && tmpCylinder->__queryAdd(tmpIndex, item, item->getItemCount(), flags) == RET_NOERROR){
                                                index = tmpIndex;
                                                *destItem = tmpDestItem;
                                                return tmpCylinder;
                                        }
 
                                        containerList.push_back(subContainer);
                                }
                        }
                        //empty slot
                        else if(__queryAdd(i, item, item->getItemCount(), flags) == RET_NOERROR){
                                index = i;
                                *destItem = NULL;
                                return this;
                        }
                }
 
                //check deeper in the containers
                for(std::list<Container*>::iterator it = containerList.begin(); it != containerList.end(); ++it){
                        for(ContainerIterator iit = (*it)->begin(); iit != (*it)->end(); ++iit){
                                if(Container* subContainer = (*iit)->getContainer()){
 
                                        if(subContainer == tradeItem){
                                                continue;
                                        }
 
                                        Cylinder* tmpCylinder = NULL;
                                        int32_t tmpIndex = INDEX_WHEREEVER;
                                        Item* tmpDestItem = NULL;
 
                                        tmpCylinder = subContainer->__queryDestination(tmpIndex, item, &tmpDestItem, flags);
                                        if(tmpCylinder && tmpCylinder->__queryAdd(tmpIndex, item, item->getItemCount(), flags) == RET_NOERROR){
                                                index = tmpIndex;
                                                *destItem = tmpDestItem;
                                                return tmpCylinder;
                                        }
                                }
                        }
                }
                return this;
        }
 
        Thing* destThing = __getThing(index);
        if(destThing)
                *destItem = destThing->getItem();
 
        Cylinder* subCylinder = dynamic_cast<Cylinder*>(destThing);
 
        if(subCylinder){
                index = INDEX_WHEREEVER;
                *destItem = NULL;
                return subCylinder;
        }
        else
                return this;
}

Posted by Nubaza (Chavoz) in otland.net
Created by Exedion in xtibia.com/forum


Maybe this code ruins your firstitems, so i need the help of the forum to edit this code :S
Where can i find this container.cpp ,item.cpp and player.cpp in data
 
@froy
Can help me to find it what i do

You will have to insert text from thread starter's first post, probably replace something. Im not sure.
Then you will need to compile the source.Use the search function for finding a guide to compile your distro.
 
You don't need to change doPlayerAddItem function. There is a bug inside __queryDestination function, so it will always omit first items for INDEX_WHEREVER.
Here is a fixed version of player.cpp:

C++:
Cylinder* Player::__queryDestination(int32_t& index, const Thing* thing, Item** destItem,
    uint32_t& flags)
{
    if (index == 0 /*drop to capacity window*/ || index == INDEX_WHEREEVER)
    {
        *destItem = NULL;

        const Item* item = thing->getItem();
        if (item == NULL)
        {
            return this;
        }

        //find an appropiate slot
        std::list<Container*> containerList;
        for (int i = SLOT_FIRST; i < SLOT_LAST; ++i)
        {
            Item* inventoryItem = inventory[i];
            if (inventoryItem)
            {
                if (inventoryItem == tradeItem)
                {
                    continue;
                }

                //try find an already existing item to stack with
                if (inventoryItem != item && item->isStackable() && inventoryItem->getID() == item->getID() && inventoryItem->getItemCount() < 100)
                {
                    *destItem = inventoryItem;
                    index = i;
                    return this;
                }
                //check sub-containers
                else if (Container* subContainer = inventoryItem->getContainer())
                {
                    Cylinder* tmpCylinder = NULL;
                    int32_t tmpIndex = INDEX_WHEREEVER;
                    Item* tmpDestItem = NULL;

                    tmpCylinder = subContainer->__queryDestination(tmpIndex, item, &tmpDestItem, flags);
                    if (tmpCylinder && tmpCylinder->__queryAdd(tmpIndex, item, item->getItemCount(), flags) == RET_NOERROR)
                    {
                        index = tmpIndex;
                        *destItem = tmpDestItem;
                        return tmpCylinder;
                    }

                    containerList.push_back(subContainer);
                }
            }
            //empty slot
            else if (__queryAdd(i, item, item->getItemCount(), flags) == RET_NOERROR)
            {
                index = i;
                *destItem = NULL;
                return this;
            }
        }

        //check deeper in the containers
        for (std::list<Container*>::iterator it = containerList.begin(); it != containerList.end(); ++it)
        {
            for (ContainerIterator iit = (*it)->begin(); iit != (*it)->end(); ++iit)
            {
                if (Container* subContainer = (*iit)->getContainer())
                {

                    if (subContainer == tradeItem)
                    {
                        continue;
                    }

                    Cylinder* tmpCylinder = NULL;
                    int32_t tmpIndex = INDEX_WHEREEVER;
                    Item* tmpDestItem = NULL;

                    tmpCylinder = subContainer->__queryDestination(tmpIndex, item, &tmpDestItem, flags);
                    if (tmpCylinder && tmpCylinder->__queryAdd(tmpIndex, item, item->getItemCount(), flags) == RET_NOERROR)
                    {
                        index = tmpIndex;
                        *destItem = tmpDestItem;
                        return tmpCylinder;
                    }
                }
            }
        }
        return this;
    }

    Thing* destThing = __getThing(index);
    if (destThing)
        *destItem = destThing->getItem();

    Cylinder* subCylinder = dynamic_cast<Cylinder*>(destThing);

    if (subCylinder)
    {
        index = INDEX_WHEREEVER;
        *destItem = NULL;
        return subCylinder;
    }
    else
        return this;
}

Apologies for the necropost but just wanted to add this fixed the container stacking issue for me on latest OTHire (v0.0.3)
 
Back
Top