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

OTClient Use all Stacked Items

Allan Silva

Member
Joined
May 30, 2018
Messages
43
Solutions
1
Reaction score
7
Hi community,

I am trying to implement an option in the game interface to use all stacked items at once when clicking the "use all ..." button, as shown in the image.

1734099074985.webp

Here is the part of the code in otcv8 gameinterface.lua:

after
LUA:
menu:addOption(tr('Use'), function() g_game.use(useThing) end, shortcut)

i added
LUA:
menu:addOption(tr('Use all ...'), function() g_game.use(useThing) end, shortcut)

Note: Since I just copied the "use" function, only one item is consumed instead of all.
Does anyone know what I can do to make the function use all the items when selecting "use all"?
 
You will have to create a new method on server side that is being called by a new packet which receives the item and its position and probably also the amount of the stack.
Alternative you could edit the existing use method by for example adding a boolean which then calls a different method on server side.
 
You will have to create a new method on server side that is being called by a new packet which receives the item and its position and probably also the amount of the stack.
Alternative you could edit the existing use method by for example adding a boolean which then calls a different method on server side.
Hi @Danger II, thanks for replying

I liked alternative solution you suggested, as I found this part of script at server base in game.cpp
C++:
void Game::playerUseItem(uint32_t playerId, const Position &pos, uint8_t stackPos, uint8_t index, uint16_t itemId) {
    metrics::method_latency measure(__METRICS_METHOD_NAME__);
    const auto &player = getPlayerByID(playerId);
    if (!player) {
        return;
    }

    bool isHotkey = (pos.x == 0xFFFF && pos.y == 0 && pos.z == 0);
    if (isHotkey && !g_configManager().getBoolean(AIMBOT_HOTKEY_ENABLED)) {
        return;
    }

    const auto &thing = internalGetThing(player, pos, stackPos, itemId, STACKPOS_FIND_THING);
    if (!thing) {
        player->sendCancelMessage(RETURNVALUE_NOTPOSSIBLE);
        return;
    }

    const auto &item = thing->getItem();
    if (!item || item->isMultiUse() || item->getID() != itemId) {
        player->sendCancelMessage(RETURNVALUE_CANNOTUSETHISOBJECT);
        return;
    }

    bool canUseHouseItem = !g_configManager().getBoolean(ONLY_INVITED_CAN_MOVE_HOUSE_ITEMS) || InternalGame::playerCanUseItemOnHouseTile(player, item);
    if (!canUseHouseItem && item->hasOwner() && !item->isOwner(player)) {
        player->sendCancelMessage(RETURNVALUE_ITEMISNOTYOURS);
        return;
    } else if (!canUseHouseItem) {
        player->sendCancelMessage(RETURNVALUE_CANNOTUSETHISOBJECT);
        return;
    }

    const ItemType &it = Item::items[item->getID()];
    if (it.isRune() || it.type == ITEM_TYPE_POTION) {
        if (player->walkExhausted()) {
            player->sendCancelMessage(RETURNVALUE_YOUAREEXHAUSTED);
            return;
        }
    }

    ReturnValue ret = g_actions().canUse(player, pos);
    if (ret != RETURNVALUE_NOERROR) {
        if (ret == RETURNVALUE_TOOFARAWAY) {
            std::vector<Direction> listDir;
            if (player->getPathTo(pos, listDir, 0, 1, true, true)) {
                g_dispatcher().addEvent([this, playerId = player->getID(), listDir] { playerAutoWalk(playerId, listDir); }, __FUNCTION__);
                const auto &task = createPlayerTask(
                    400,
                    [this, playerId, pos, stackPos, index, itemId] {
                        playerUseItem(playerId, pos, stackPos, index, itemId);
                    },
                    __FUNCTION__
                );
                if (it.isRune() || it.type == ITEM_TYPE_POTION) {
                    player->setNextPotionActionTask(task);
                } else {
                    player->setNextWalkActionTask(task);
                }
                return;
            }

            ret = RETURNVALUE_THEREISNOWAY;
        }

        player->sendCancelMessage(ret);
        return;
    }

    bool canDoAction = player->canDoAction();
    if (it.isRune() || it.type == ITEM_TYPE_POTION) {
        canDoAction = player->canDoPotionAction();
    }

    if (!canDoAction) {
        uint32_t delay = player->getNextActionTime();
        if (it.isRune() || it.type == ITEM_TYPE_POTION) {
            delay = player->getNextPotionActionTime();
        }
        const auto &task = createPlayerTask(
            delay,
            [this, playerId, pos, stackPos, index, itemId] {
                playerUseItem(playerId, pos, stackPos, index, itemId);
            },
            __FUNCTION__
        );
        if (it.isRune() || it.type == ITEM_TYPE_POTION) {
            player->setNextPotionActionTask(task);
        } else {
            player->setNextActionTask(task);
        }
        return;
    }

    player->resetIdleTime();
    player->setNextActionTask(nullptr);

    // Refresh depot search window if necessary
    bool refreshDepotSearch = false;
    if (player->isDepotSearchOpenOnItem(itemId) && item->isInsideDepot(true)) {
        refreshDepotSearch = true;
    }

    g_actions().useItem(player, pos, index, item, isHotkey);

    if (refreshDepotSearch) {
        player->requestDepotSearchItem(itemId, stackPos);
    }
}

I need to create a new condition here? If so, can you help me by giving me an idea of what this condition could be?
 
Back
Top