diff --git a/include/game/game_handler.hpp b/include/game/game_handler.hpp index 5df20457..61e7661d 100644 --- a/include/game/game_handler.hpp +++ b/include/game/game_handler.hpp @@ -819,6 +819,7 @@ public: void autoEquipItemInBag(int bagIndex, int slotIndex); void useItemBySlot(int backpackIndex); void useItemInBag(int bagIndex, int slotIndex); + void destroyItem(uint8_t bag, uint8_t slot, uint8_t count = 1); void swapContainerItems(uint8_t srcBag, uint8_t srcSlot, uint8_t dstBag, uint8_t dstSlot); void useItemById(uint32_t itemId); bool isVendorWindowOpen() const { return vendorWindowOpen; } diff --git a/src/game/game_handler.cpp b/src/game/game_handler.cpp index db92318c..04b56ab7 100644 --- a/src/game/game_handler.cpp +++ b/src/game/game_handler.cpp @@ -2763,6 +2763,7 @@ void GameHandler::selectCharacter(uint64_t characterGuid) { // Reset per-character state so previous character data doesn't bleed through inventory = Inventory(); onlineItems_.clear(); + itemInfoCache_.clear(); pendingItemQueries_.clear(); equipSlotGuids_ = {}; backpackSlotGuids_ = {}; @@ -9328,6 +9329,22 @@ void GameHandler::swapContainerItems(uint8_t srcBag, uint8_t srcSlot, uint8_t ds socket->send(packet); } +void GameHandler::destroyItem(uint8_t bag, uint8_t slot, uint8_t count) { + if (state != WorldState::IN_WORLD || !socket) return; + if (count == 0) count = 1; + + // AzerothCore WotLK expects CMSG_DESTROYITEM(bag:u8, slot:u8, count:u32). + // This opcode is currently not modeled as a logical opcode in our table. + constexpr uint16_t kCmsgDestroyItem = 0x111; + network::Packet packet(kCmsgDestroyItem); + packet.writeUInt8(bag); + packet.writeUInt8(slot); + packet.writeUInt32(static_cast(count)); + LOG_DEBUG("Destroy item request: bag=", (int)bag, " slot=", (int)slot, + " count=", (int)count, " wire=0x", std::hex, kCmsgDestroyItem, std::dec); + socket->send(packet); +} + void GameHandler::useItemBySlot(int backpackIndex) { if (backpackIndex < 0 || backpackIndex >= inventory.getBackpackSize()) return; const auto& slot = inventory.getBackpackSlot(backpackIndex); diff --git a/src/ui/inventory_screen.cpp b/src/ui/inventory_screen.cpp index 508b1e28..02d98d15 100644 --- a/src/ui/inventory_screen.cpp +++ b/src/ui/inventory_screen.cpp @@ -760,9 +760,35 @@ void InventoryScreen::render(game::Inventory& inventory, uint64_t moneyCopper) { ImGui::Text("Destroy \"%s\"?", dropItemName_.c_str()); ImGui::Spacing(); if (ImGui::Button("Yes", ImVec2(80, 0))) { + if (gameHandler_) { + uint8_t srcBag = 0xFF; + uint8_t srcSlot = 0; + bool haveSource = false; + if (heldSource == HeldSource::BACKPACK && heldBackpackIndex >= 0) { + srcSlot = static_cast(23 + heldBackpackIndex); + haveSource = true; + } else if (heldSource == HeldSource::BAG && heldBagIndex >= 0 && heldBagSlotIndex >= 0) { + srcBag = static_cast(19 + heldBagIndex); + srcSlot = static_cast(heldBagSlotIndex); + haveSource = true; + } else if (heldSource == HeldSource::EQUIPMENT && + heldEquipSlot != game::EquipSlot::NUM_SLOTS) { + srcSlot = static_cast(heldEquipSlot); + haveSource = true; + } + if (haveSource) { + uint8_t destroyCount = static_cast(std::clamp( + std::max(1u, heldItem.stackCount), 1u, 255u)); + gameHandler_->destroyItem(srcBag, srcSlot, destroyCount); + } + } holdingItem = false; heldItem = game::ItemDef{}; heldSource = HeldSource::NONE; + heldBackpackIndex = -1; + heldBagIndex = -1; + heldBagSlotIndex = -1; + heldEquipSlot = game::EquipSlot::NUM_SLOTS; inventoryDirty = true; dropItemName_.clear(); ImGui::CloseCurrentPopup(); @@ -1610,7 +1636,7 @@ void InventoryScreen::renderItemTooltip(const game::ItemDef& item, const game::I ImGui::TextColored(green, "%s", bonusLine.c_str()); } - if (!isWeapon && item.armor > 0) { + if (item.armor > 0) { ImGui::Text("%d Armor", item.armor); } if (item.sellPrice > 0) { @@ -1638,7 +1664,7 @@ void InventoryScreen::renderItemTooltip(const game::ItemDef& item, const game::I float dps = ((eq->item.damageMin + eq->item.damageMax) * 0.5f) / speed; ImGui::Text("%.1f DPS", dps); } - if (!isWeaponInventoryType(eq->item.inventoryType) && eq->item.armor > 0) { + if (eq->item.armor > 0) { ImGui::Text("%d Armor", eq->item.armor); } std::string eqBonusLine;