diff --git a/src/client/game.cpp b/src/client/game.cpp index 517135f13..d3bd1efab 100644 --- a/src/client/game.cpp +++ b/src/client/game.cpp @@ -885,6 +885,18 @@ void Game::useInventoryItemWith(const uint16_t itemId, const ThingPtr& toThing) if (!canPerformGameAction() || !toThing) return; + // pre-780 protocols resolve the source item by its real inventory slot and + // stackpos, so the synthetic Position(0xFFFF, 0, 0) below (source stackpos 0) + // addresses the wrong slot and the use silently fails (e.g. rope on 7.6). + // resolve the real item and go through useWith, the same gate the hotkey and + // keybind code already apply. see #1541 + if (getClientVersion() < 780) { + if (const auto& item = findPlayerItem(itemId, -1)) { + useWith(item, toThing); + return; + } + } + const auto& pos = Position(0xFFFF, 0, 0); // means that is a item in inventory if (toThing->isCreature()) m_protocolGame->sendUseOnCreature(pos, itemId, 0, toThing->getId()); @@ -894,6 +906,19 @@ void Game::useInventoryItemWith(const uint16_t itemId, const ThingPtr& toThing) g_lua.callGlobalField("g_game", "onUseWith", pos, itemId, toThing, 0); } +ItemPtr Game::findPlayerItem(const uint32_t itemId, const int subType) +{ + if (m_localPlayer) { + for (int slot = Otc::InventorySlotHead; slot < Otc::LastInventorySlot; ++slot) { + const auto& item = m_localPlayer->getInventoryItem(static_cast(slot)); + if (item && item->getId() == itemId && (subType == -1 || item->getSubType() == subType)) + return item; + } + } + + return findItemInContainers(itemId, subType, 0); +} + ItemPtr Game::findItemInContainers(const uint32_t itemId, const int subType, const uint8_t tier) { for (const auto& it : m_containers) { diff --git a/src/client/game.h b/src/client/game.h index f8fb1fa5d..acf6491f6 100644 --- a/src/client/game.h +++ b/src/client/game.h @@ -186,6 +186,7 @@ public: void useInventoryItem(uint16_t itemId); void useInventoryItemWith(uint16_t itemId, const ThingPtr& toThing); ItemPtr findItemInContainers(uint32_t itemId, int subType, uint8_t tier); + ItemPtr findPlayerItem(uint32_t itemId, int subType); // container related int open(const ItemPtr& item, const ContainerPtr& previousContainer);