• 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!
  • 2026 staff recruitment is open! Check it out and consider applying!

TFS 0.X [C++] Few stackable items remaining in house

potinho

Advanced OT User
Joined
Oct 11, 2009
Messages
1,493
Solutions
17
Reaction score
187
Location
Brazil
Hello guys, i realize few days ago when a player looses his house, some stackable items remains at house, even with "Nobody" as owner...if a new player buy this house, stackable itens keep in house, causing a seriours problem.
Its not happens everytime, but its getting more common, i tried to reproduce leaving house (using /leave command) and not happens, just if player loose house by inactive time or without money to pay rent. Anyone can help me to fix? Thank you all, some follow related functions bellow:


C++:
bool House::transferToDepot()
{
    if(!townId)
        return false;

    Player* player = NULL;
    if(owner)
    {
        uint32_t tmp = owner;
        if(isGuild() && !IOGuild::getInstance()->swapGuildIdToOwner(tmp))
            tmp = 0;

        if(tmp)
            player = g_game.getPlayerByGuidEx(tmp);
    }

    Container* tmpContainer = NULL;
    TileItemVector* items = NULL;

    ItemList moveList;
    for(HouseTileList::iterator it = houseTiles.begin(); it != houseTiles.end(); ++it)
    {
        if(!(items = (*it)->getItemList()))
            continue;

        for(ItemVector::iterator iit = items->begin(); iit != items->end(); ++iit)
        {
            if((*iit)->isPickupable())
                moveList.push_back(*iit);
            else if((tmpContainer = (*iit)->getContainer()))
            {
                for(ItemList::const_iterator cit = tmpContainer->getItems(); cit != tmpContainer->getEnd(); ++cit)
                    moveList.push_back(*cit);
            }
        }
    }

    if(player)
    {
        Depot* depot = player->getDepot(townId, true);
        for(ItemList::iterator it = moveList.begin(); it != moveList.end(); ++it)
            g_game.internalMoveItem(NULL, (*it)->getParent(), depot, INDEX_WHEREEVER, (*it), (*it)->getItemCount(), NULL, FLAG_NOLIMIT);

        if(player->isVirtual())
        {
            IOLoginData::getInstance()->savePlayer(player);
            delete player;
        }
    }
    else
    {
        for(ItemList::iterator it = moveList.begin(); it != moveList.end(); ++it)
            g_game.internalRemoveItem(NULL, (*it), (*it)->getItemCount(), false, FLAG_NOLIMIT);
    }

    return true;
}

C++:
ReturnValue Container::__queryAdd(int32_t index, const Thing* thing, uint32_t count,
    uint32_t flags, Creature* actor/* = NULL*/) const
{
    bool childIsOwner = hasBitSet(FLAG_CHILDISOWNER, flags);
    if(childIsOwner)
    {
        //a child container is querying, since we are the top container (not carried by a player)
        //just return with no error.
        return RET_NOERROR;
    }

    const Item* item = thing->getItem();
    if(!item)
        return RET_NOTPOSSIBLE;

    if(!item->isPickupable())
        return RET_CANNOTPICKUP;

    if(item == this)
        return RET_THISISIMPOSSIBLE;

    const Cylinder* cylinder = getParent();
    const Cylinder* const topParent = getTopParent();

    if(isQuiver() && item->getWeaponType() != WEAPON_AMMO)
        return RET_NOTPOSSIBLE;

    if (actor && getLootContainer() && (flags & FLAG_NOLIMIT) != FLAG_NOLIMIT)
    {
        if (!item->getContainer())
            return RET_NOTMOVABLETOCONTAINER;

        if (item->getContainer()->getItemHoldingCount() > 0)
            return RET_CONTAINERMUSTBEEMPTY;
    }

    const Container* container = item->getContainer();
    for (const Cylinder* cylinder = getParent(); cylinder; cylinder = cylinder->getParent())
    {
        if (cylinder == container)
            return RET_THISISIMPOSSIBLE;

        if (actor && (flags & FLAG_NOLIMIT) != FLAG_NOLIMIT && dynamic_cast<const LootContainer*>(cylinder))
        {
            if (!item->getContainer())
                return RET_NOTMOVABLETOCONTAINER;

            if (item->getContainer()->getItemHoldingCount() > 0)
                return RET_CONTAINERMUSTBEEMPTY;
        }
    }

    if((flags & FLAG_NOLIMIT) != FLAG_NOLIMIT && (index == INDEX_WHEREEVER && full()))
        return RET_CONTAINERNOTENOUGHROOM;

    if(topParent != this)
        return topParent->__queryAdd(INDEX_WHEREEVER, item, count, flags | FLAG_CHILDISOWNER, actor);

    return RET_NOERROR;
}

C++:
ReturnValue Depot::__queryAdd(int32_t index, const Thing* thing, uint32_t count,
    uint32_t flags, Creature* actor/* = NULL*/) const
{
    const Item* item = thing->getItem();
    if(!item)
        return RET_NOTPOSSIBLE;

    if((flags & FLAG_NOLIMIT) == FLAG_NOLIMIT)
        return Container::__queryAdd(index, thing, count, flags, actor);

    int32_t addCount = 0;
    if((item->isStackable() && item->getItemCount() != count))
        addCount = 1;

    if(item->getTopParent() != this)
    {
        if(const Container* container = item->getContainer())
            addCount = container->getItemHoldingCount() + 1;
        else
            addCount = 1;
    }

    if(getItemHoldingCount() + addCount > depotLimit)
        return RET_DEPOTISFULL;

    return Container::__queryAdd(index, thing, count, flags, actor);
}
 
I guess i've solved, changing:


C++:
ReturnValue Game::internalMoveItem(Creature* actor, Cylinder* fromCylinder, Cylinder* toCylinder,
    int32_t index, Item* item, uint32_t count, Item** _moveItem, uint32_t flags /*= 0*/)
{
    if(!toCylinder)
        return RET_NOTPOSSIBLE;

    if(!item->getParent())
    {
        assert(fromCylinder == item->getParent());
        return internalAddItem(actor, toCylinder, item, INDEX_WHEREEVER, FLAG_NOLIMIT);
    }

    Item* toItem = NULL;
    Cylinder* subCylinder = NULL;

    int32_t floor = 0;
    while((subCylinder = toCylinder->__queryDestination(index, item, &toItem, flags)) != toCylinder)
    {
        flags = 0;
        toCylinder = subCylinder;
        //to prevent infinite loop
        if(++floor >= MAP_MAX_LAYERS)
            break;
    }

    //destination is the same as the source?
    if(item == toItem)
        return RET_NOERROR; //silently ignore move


to

C++:
ReturnValue Game::internalMoveItem(Creature* actor, Cylinder* fromCylinder, Cylinder* toCylinder,
    int32_t index, Item* item, uint32_t count, Item** _moveItem, uint32_t flags /*= 0*/)
{
    if(!toCylinder)
        return RET_NOTPOSSIBLE;

    if(!item->getParent())
    {
        assert(fromCylinder == item->getParent());
        return internalAddItem(actor, toCylinder, item, INDEX_WHEREEVER, FLAG_NOLIMIT);
    }

    Item* toItem = NULL;
    Cylinder* subCylinder = NULL;

    int32_t floor = 0;
    while((subCylinder = toCylinder->__queryDestination(index, item, &toItem, flags)) != toCylinder)
    {
        flags &= FLAG_NOLIMIT;
        toCylinder = subCylinder;
        //to prevent infinite loop
        if(++floor >= MAP_MAX_LAYERS)
            break;
    }

    //destination is the same as the source?
    if(item == toItem)
        return RET_NOERROR; //silently ignore move

I will keep looking for this
 

Similar threads

Back
Top