fix: useInventoryItemWith source stackpos on pre-780 protocols (7.6 usewith) (#1755)

Bug Fixes:
- Improved compatibility when using inventory items on older client versions, reducing silent failures.
- The game now correctly identifies the matching inventory item and uses accurate slot/stack information for the action.
- If the item isn’t found in the player’s inventory, the game will check nearby containers and proceed when available.
This commit is contained in:
Kizuno18 2026-07-18 16:43:24 -03:00 committed by GitHub
parent fec1cca042
commit a7d1b3961e
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
2 changed files with 26 additions and 0 deletions

View file

@ -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<Otc::InventorySlot>(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) {

View file

@ -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);