• 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!

Compiling Moveitem exhaust

Shackal

Alien Project
Joined
Feb 7, 2009
Messages
211
Reaction score
17
Location
Brazil
Hello Guys,

Why potions, runes and spells cause exhaust to drag itens?
I'm using TFS 0.4 3777

Ty u in advance!!
 
Last edited:
Never heard about this problem and there were many popular servers hosted on rev. 3777. Are you sure that is not client-related thing?
 
Also found it strange, something similar happens when you use potion and spear attacks, there is an exhaust. But on my server is experiencing this problem when trying to drag any item, use potions, runes cause exhaust when I try to drag anything.
 
something wrong here:

Code:
bool Game::playerMoveItem(uint32_t playerId, const Position& fromPos, //DRAG ITEM VER AQUI
    uint16_t spriteId, int16_t fromStackpos, const Position& toPos, uint8_t count)
{
    Player* player = getPlayerByID(playerId);
    if(!player || player->isRemoved() || player->hasFlag(PlayerFlag_CannotMoveItems))
        return false;

    if(!player->canDoAction())
    {
        uint32_t delay = player->getNextActionTime();
        SchedulerTask* task = createSchedulerTask(delay, boost::bind(&Game::playerMoveItem, this,
            playerId, fromPos, spriteId, fromStackpos, toPos, count));

        player->setNextActionTask(task);
        return false;
    }

    player->setNextActionTask(NULL);
    Cylinder* fromCylinder = internalGetCylinder(player, fromPos);

    uint8_t fromIndex = 0;
    if(fromPos.x == 0xFFFF)
    {
        if(fromPos.y & 0x40)
            fromIndex = static_cast<uint8_t>(fromPos.z);
        else
            fromIndex = static_cast<uint8_t>(fromPos.y);
    }
    else
        fromIndex = fromStackpos;

    Thing* thing = internalGetThing(player, fromPos, fromIndex, spriteId, STACKPOS_MOVE);
    if(!thing || !thing->getItem())
    {
        player->sendCancelMessage(RET_NOTPOSSIBLE);
        return false;
    }

    Item* item = thing->getItem();
    Cylinder* toCylinder = internalGetCylinder(player, toPos);

    uint8_t toIndex = 0;
    if(toPos.x == 0xFFFF)
    {
        if(toPos.y & 0x40)
            toIndex = static_cast<uint8_t>(toPos.z);
        else
            toIndex = static_cast<uint8_t>(toPos.y);
    }

    if(!fromCylinder || !toCylinder || !item || item->getClientID() != spriteId)
    {
        player->sendCancelMessage(RET_NOTPOSSIBLE);
        return false;
    }

    if(!player->hasCustomFlag(PlayerCustomFlag_CanPushAllItems) && (!item->isPushable() || (item->isLoadedFromMap() &&
        (item->getUniqueId() != 0 || (item->getActionId() != 0 && item->getContainer())))))
    {
        player->sendCancelMessage(RET_NOTMOVEABLE);
        return false;
    }

    const Position &mapToPos = toCylinder->getTile()->getPosition(), &playerPos = player->getPosition(),
        &mapFromPos = fromCylinder->getTile()->getPosition();
    if(playerPos.z > mapFromPos.z && !player->hasCustomFlag(PlayerCustomFlag_CanThrowAnywhere))
    {
        player->sendCancelMessage(RET_FIRSTGOUPSTAIRS);
        return false;
    }

    if(playerPos.z < mapFromPos.z && !player->hasCustomFlag(PlayerCustomFlag_CanThrowAnywhere))
    {
        player->sendCancelMessage(RET_FIRSTGODOWNSTAIRS);
        return false;
    }

    if(!Position::areInRange<1,1,0>(playerPos, mapFromPos) && !player->hasCustomFlag(PlayerCustomFlag_CanMoveFromFar))
    {
        //need to walk to the item first before using it
        std::list<Direction> listDir;
        if(getPathToEx(player, item->getPosition(), listDir, 0, 1, true, true))
        {
            Dispatcher::getInstance().addTask(createTask(boost::bind(&Game::playerAutoWalk,
                this, player->getID(), listDir)));
            SchedulerTask* task = createSchedulerTask(std::max((int32_t)SCHEDULER_MINTICKS, player->getStepDuration()),
                boost::bind(&Game::playerMoveItem, this, playerId, fromPos, spriteId, fromStackpos, toPos, count));

            player->setNextWalkActionTask(task);
            return true;
        }

        player->sendCancelMessage(RET_THEREISNOWAY);
        return false;
    }

    //hangable item specific code
    if(item->isHangable() && toCylinder->getTile()->hasProperty(SUPPORTHANGABLE))
    {
        //destination supports hangable objects so need to move there first
        if(toCylinder->getTile()->hasProperty(ISVERTICAL))
        {
            if(player->getPosition().x + 1 == mapToPos.x)
            {
                player->sendCancelMessage(RET_NOTPOSSIBLE);
                return false;
            }
        }
        else if(toCylinder->getTile()->hasProperty(ISHORIZONTAL))
        {
            if(player->getPosition().y + 1 == mapToPos.y)
            {
                player->sendCancelMessage(RET_NOTPOSSIBLE);
                return false;
            }
        }

        if(!Position::areInRange<1,1,0>(playerPos, mapToPos) && !player->hasCustomFlag(PlayerCustomFlag_CanMoveFromFar))
        {
            Position walkPos = mapToPos;
            if(toCylinder->getTile()->hasProperty(ISVERTICAL))
                walkPos.x -= -1;

            if(toCylinder->getTile()->hasProperty(ISHORIZONTAL))
                walkPos.y -= -1;

            Position itemPos = fromPos;
            int16_t itemStackpos = fromStackpos;
            if(fromPos.x != 0xFFFF && Position::areInRange<1,1,0>(mapFromPos, player->getPosition())
                && !Position::areInRange<1,1,0>(mapFromPos, walkPos))
            {
                //need to pickup the item first
                Item* moveItem = NULL;
                ReturnValue ret = internalMoveItem(player, fromCylinder, player, INDEX_WHEREEVER, item, count, &moveItem);
                if(ret != RET_NOERROR)
                {
                    player->sendCancelMessage(ret);
                    return false;
                }

                //changing the position since its now in the inventory of the player
                internalGetPosition(moveItem, itemPos, itemStackpos);
            }

            std::list<Direction> listDir;
            if(map->getPathTo(player, walkPos, listDir))
            {
                Dispatcher::getInstance().addTask(createTask(boost::bind(&Game::playerAutoWalk,
                    this, player->getID(), listDir)));
                SchedulerTask* task = createSchedulerTask(std::max((int32_t)SCHEDULER_MINTICKS, player->getStepDuration()),
                    boost::bind(&Game::playerMoveItem, this, playerId, itemPos, spriteId, itemStackpos, toPos, count));

                player->setNextWalkActionTask(task);
                return true;
            }

            player->sendCancelMessage(RET_THEREISNOWAY);
            return false;
        }
    }

    if(!player->hasCustomFlag(PlayerCustomFlag_CanThrowAnywhere))
    {
        if((std::abs(playerPos.x - mapToPos.x) > item->getThrowRange()) ||
            (std::abs(playerPos.y - mapToPos.y) > item->getThrowRange()) ||
            (std::abs(mapFromPos.z - mapToPos.z) * 4 > item->getThrowRange()))
        {
            player->sendCancelMessage(RET_DESTINATIONOUTOFREACH);
            return false;
        }
    }

    if(!canThrowObjectTo(mapFromPos, mapToPos) && !player->hasCustomFlag(PlayerCustomFlag_CanThrowAnywhere))
    {
        player->sendCancelMessage(RET_CANNOTTHROW);
        return false;
    }
   
    bool success = true;
        CreatureEventList moveitemEvents = player->getCreatureEvents(CREATURE_EVENT_MOVEITEM);
        for(CreatureEventList::iterator it = moveitemEvents.begin(); it != moveitemEvents.end(); ++it)
        {
            Item* toContainer = toCylinder->getItem();
            Item* fromContainer = fromCylinder->getItem();
            if(!(*it)->executeMoveItem(player, item, count, fromPos, toPos, (toContainer ? toContainer : 0), (fromContainer ? fromContainer : 0), fromStackpos) && success)
                success = false;
        }

    if(!success){ return false; }
   
    /* Corrigido ElfBot Anti-Push (Anti-Crash) */
    uint16_t items[] = {2148, 2152, 2160, 3976, 2599, 7636, 7635, 7634};
    uint16_t n = 0;
    for (n = 0; n < sizeof(items) / sizeof(uint16_t); n++){
        if(item->getID() == items[n] && player->hasCondition(CONDITION_EXHAUST, 1)){
            player->sendTextMessage(MSG_STATUS_SMALL, "Please wait a few seconds to move this item.");
        return false;
        }
    }

    if(Condition* condition = Condition::createCondition(CONDITIONID_DEFAULT, CONDITION_EXHAUST, 500, 0, false, 1))
    player->addCondition(condition);
    /* end */

    ReturnValue ret = internalMoveItem(player, fromCylinder, toCylinder, toIndex, item, count, NULL);
    if(ret == RET_NOERROR)
        return true;

    player->setNextAction(OTSYS_TIME() + g_config.getNumber(ConfigManager::ACTIONS_DELAY_INTERVAL) - 2000);
    player->sendCancelMessage(ret);
    return false;
}
 
I figured that but it seems like the server has hard-coded that you get exhausted in "timeBetweenExActions" whenever you use "onUse"

I solved it myself doing the following:
In game.cpp, in functions "playerUseItemEx" and "playerUseItem", create an if-statement around:
Code:
if (!player->canDoAction())
{
SchedulerTask* task = createSchedulerTask(player->getNextActionTime(),
boost::bind(&Game::playerUseItem, this, playerId, pos, stackpos, index, spriteId, isHotkey));
player->setNextActionTask(task);
returnfalse;
}
Use this statement:
Code:
if (!item->isContainer())
{
--PREVIOUS CODE GOES HERE (it's a bit different from function to function)
}

also, comment out or remove the same lines in function "playerMoveItem" (the lines including the if-statement "if (!player->canDoAction())").

Also, in actions.cpp, in functions "useItemEx" and "useItem" use the same if-statement around:
Code:
if (!player->canDoAction())
returnfalse;

so that it looks like this:
Code:
if (!item->isContainer())
{
if (!player->canDoAction())
returnfalse;
}

This fix only does so that you can open containers and move items during exhaust. You will still not be able to use rope or any other action until exhaust has expired.

Pardon my horrible english :D

Edit:
I use TFS for 10.10. Not quite sure which version. I just know it's not 1.0

This works, but the overlap of the SD exhaust
 
Back
Top