mirror of
https://github.com/Kelsidavis/WoWee.git
synced 2026-05-03 08:03:50 +00:00
Fix bag bar drag/drop with container bags
Allow equipped bags to be moved through the shared inventory pickup/drop flow, including dragging from bag contents to bag bar and back from bag bar into bag/backpack slots. Changes: - Add InventoryScreen APIs to begin pickup from an equipment slot and drop held item into a target equipment slot. - Treat inventory type 18 (bags) as valid drops on BAG1-BAG4 during slot validation. - Route equipment placement in online mode through swapContainerItems with explicit src/dst addressing for deterministic bag slot moves. - Update bag bar hover-drop path to use InventoryScreen drop API instead of direct local slot mutation. - On bag bar drag start, hand off to inventory held-item drag when inventory/character UI is open so drops into bag/backpack slots work.
This commit is contained in:
parent
acb63d4f6e
commit
9a0415ad6b
3 changed files with 93 additions and 35 deletions
|
|
@ -166,8 +166,13 @@ public:
|
||||||
bool isHoldingItem() const { return holdingItem; }
|
bool isHoldingItem() const { return holdingItem; }
|
||||||
/// Returns the item being held (only valid when isHoldingItem() is true).
|
/// Returns the item being held (only valid when isHoldingItem() is true).
|
||||||
const game::ItemDef& getHeldItem() const { return heldItem; }
|
const game::ItemDef& getHeldItem() const { return heldItem; }
|
||||||
|
/// Begin pickup from an equipment slot (e.g., bag bar slot) into held cursor.
|
||||||
|
bool beginPickupFromEquipSlot(game::Inventory& inv, game::EquipSlot slot);
|
||||||
/// Cancel the pickup, returning the item to its original slot.
|
/// Cancel the pickup, returning the item to its original slot.
|
||||||
void returnHeldItem(game::Inventory& inv) { cancelPickup(inv); }
|
void returnHeldItem(game::Inventory& inv) { cancelPickup(inv); }
|
||||||
|
/// Drop the currently held item into a specific equipment slot.
|
||||||
|
/// Returns true if the drop was accepted and consumed.
|
||||||
|
bool dropHeldItemToEquipSlot(game::Inventory& inv, game::EquipSlot slot);
|
||||||
};
|
};
|
||||||
|
|
||||||
} // namespace ui
|
} // namespace ui
|
||||||
|
|
|
||||||
|
|
@ -3670,10 +3670,10 @@ void GameScreen::renderBagBar(game::GameHandler& gameHandler) {
|
||||||
// Accept dragged item from inventory
|
// Accept dragged item from inventory
|
||||||
if (hovered && inventoryScreen.isHoldingItem()) {
|
if (hovered && inventoryScreen.isHoldingItem()) {
|
||||||
const auto& heldItem = inventoryScreen.getHeldItem();
|
const auto& heldItem = inventoryScreen.getHeldItem();
|
||||||
if (heldItem.bagSlots > 0 && ImGui::IsMouseReleased(ImGuiMouseButton_Left)) {
|
if ((heldItem.inventoryType == 18 || heldItem.bagSlots > 0) &&
|
||||||
|
ImGui::IsMouseReleased(ImGuiMouseButton_Left)) {
|
||||||
auto& inventory = gameHandler.getInventory();
|
auto& inventory = gameHandler.getInventory();
|
||||||
inventory.setEquipSlot(bagSlot, heldItem);
|
inventoryScreen.dropHeldItemToEquipSlot(inventory, bagSlot);
|
||||||
inventoryScreen.returnHeldItem(inventory);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -3685,9 +3685,21 @@ void GameScreen::renderBagBar(game::GameHandler& gameHandler) {
|
||||||
// releasing completes swap or click
|
// releasing completes swap or click
|
||||||
if (bagBarDragSource_ >= 0) {
|
if (bagBarDragSource_ >= 0) {
|
||||||
if (ImGui::IsMouseDragging(ImGuiMouseButton_Left, 3.0f) && bagBarPickedSlot_ < 0) {
|
if (ImGui::IsMouseDragging(ImGuiMouseButton_Left, 3.0f) && bagBarPickedSlot_ < 0) {
|
||||||
|
// If an inventory window is open, hand off drag to inventory held-item
|
||||||
|
// so the bag can be dropped into backpack/bag slots.
|
||||||
|
if (inventoryScreen.isOpen() || inventoryScreen.isCharacterOpen()) {
|
||||||
|
auto equip = static_cast<game::EquipSlot>(
|
||||||
|
static_cast<int>(game::EquipSlot::BAG1) + bagBarDragSource_);
|
||||||
|
if (inventoryScreen.beginPickupFromEquipSlot(inv, equip)) {
|
||||||
|
bagBarDragSource_ = -1;
|
||||||
|
} else {
|
||||||
|
bagBarPickedSlot_ = bagBarDragSource_;
|
||||||
|
}
|
||||||
|
} else {
|
||||||
// Mouse moved enough — start visual drag
|
// Mouse moved enough — start visual drag
|
||||||
bagBarPickedSlot_ = bagBarDragSource_;
|
bagBarPickedSlot_ = bagBarDragSource_;
|
||||||
}
|
}
|
||||||
|
}
|
||||||
if (ImGui::IsMouseReleased(ImGuiMouseButton_Left)) {
|
if (ImGui::IsMouseReleased(ImGuiMouseButton_Left)) {
|
||||||
if (bagBarPickedSlot_ >= 0) {
|
if (bagBarPickedSlot_ >= 0) {
|
||||||
// Was dragging — check for drop target
|
// Was dragging — check for drop target
|
||||||
|
|
|
||||||
|
|
@ -395,6 +395,13 @@ game::EquipSlot InventoryScreen::getEquipSlotForType(uint8_t inventoryType, game
|
||||||
case 26: // Ranged
|
case 26: // Ranged
|
||||||
return game::EquipSlot::RANGED;
|
return game::EquipSlot::RANGED;
|
||||||
case 16: return game::EquipSlot::BACK;
|
case 16: return game::EquipSlot::BACK;
|
||||||
|
case 18: {
|
||||||
|
for (int i = 0; i < game::Inventory::NUM_BAG_SLOTS; ++i) {
|
||||||
|
auto slot = static_cast<game::EquipSlot>(static_cast<int>(game::EquipSlot::BAG1) + i);
|
||||||
|
if (inv.getEquipSlot(slot).empty()) return slot;
|
||||||
|
}
|
||||||
|
return game::EquipSlot::BAG1;
|
||||||
|
}
|
||||||
case 19: return game::EquipSlot::TABARD;
|
case 19: return game::EquipSlot::TABARD;
|
||||||
case 20: return game::EquipSlot::CHEST; // Robe
|
case 20: return game::EquipSlot::CHEST; // Robe
|
||||||
default: return game::EquipSlot::NUM_SLOTS;
|
default: return game::EquipSlot::NUM_SLOTS;
|
||||||
|
|
@ -518,40 +525,56 @@ void InventoryScreen::placeInBag(game::Inventory& inv, int bagIndex, int slotInd
|
||||||
|
|
||||||
void InventoryScreen::placeInEquipment(game::Inventory& inv, game::EquipSlot slot) {
|
void InventoryScreen::placeInEquipment(game::Inventory& inv, game::EquipSlot slot) {
|
||||||
if (!holdingItem) return;
|
if (!holdingItem) return;
|
||||||
if (gameHandler_) {
|
|
||||||
if (heldSource == HeldSource::BACKPACK && heldBackpackIndex >= 0) {
|
|
||||||
gameHandler_->autoEquipItemBySlot(heldBackpackIndex);
|
|
||||||
cancelPickup(inv);
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
if (heldSource == HeldSource::BAG) {
|
|
||||||
gameHandler_->autoEquipItemInBag(heldBagIndex, heldBagSlotIndex);
|
|
||||||
cancelPickup(inv);
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
if (heldSource == HeldSource::EQUIPMENT) {
|
|
||||||
cancelPickup(inv);
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// Validate: check if the held item can go in this slot
|
// Validate: check if the held item can go in this slot
|
||||||
if (heldItem.inventoryType > 0) {
|
if (heldItem.inventoryType > 0) {
|
||||||
|
bool valid = false;
|
||||||
|
if (heldItem.inventoryType == 18) {
|
||||||
|
valid = (slot >= game::EquipSlot::BAG1 && slot <= game::EquipSlot::BAG4);
|
||||||
|
} else {
|
||||||
game::EquipSlot validSlot = getEquipSlotForType(heldItem.inventoryType, inv);
|
game::EquipSlot validSlot = getEquipSlotForType(heldItem.inventoryType, inv);
|
||||||
if (validSlot == game::EquipSlot::NUM_SLOTS) return;
|
if (validSlot == game::EquipSlot::NUM_SLOTS) return;
|
||||||
|
|
||||||
bool valid = (slot == validSlot);
|
valid = (slot == validSlot);
|
||||||
if (!valid) {
|
if (!valid) {
|
||||||
if (heldItem.inventoryType == 11)
|
if (heldItem.inventoryType == 11)
|
||||||
valid = (slot == game::EquipSlot::RING1 || slot == game::EquipSlot::RING2);
|
valid = (slot == game::EquipSlot::RING1 || slot == game::EquipSlot::RING2);
|
||||||
else if (heldItem.inventoryType == 12)
|
else if (heldItem.inventoryType == 12)
|
||||||
valid = (slot == game::EquipSlot::TRINKET1 || slot == game::EquipSlot::TRINKET2);
|
valid = (slot == game::EquipSlot::TRINKET1 || slot == game::EquipSlot::TRINKET2);
|
||||||
}
|
}
|
||||||
|
}
|
||||||
if (!valid) return;
|
if (!valid) return;
|
||||||
} else {
|
} else {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (gameHandler_) {
|
||||||
|
uint8_t dstBag = 0xFF;
|
||||||
|
uint8_t dstSlot = static_cast<uint8_t>(slot);
|
||||||
|
uint8_t srcBag = 0xFF;
|
||||||
|
uint8_t srcSlot = 0;
|
||||||
|
if (heldSource == HeldSource::BACKPACK && heldBackpackIndex >= 0) {
|
||||||
|
srcSlot = static_cast<uint8_t>(23 + heldBackpackIndex);
|
||||||
|
} else if (heldSource == HeldSource::BAG && heldBagIndex >= 0 && heldBagSlotIndex >= 0) {
|
||||||
|
srcBag = static_cast<uint8_t>(19 + heldBagIndex);
|
||||||
|
srcSlot = static_cast<uint8_t>(heldBagSlotIndex);
|
||||||
|
} else if (heldSource == HeldSource::EQUIPMENT && heldEquipSlot != game::EquipSlot::NUM_SLOTS) {
|
||||||
|
srcSlot = static_cast<uint8_t>(heldEquipSlot);
|
||||||
|
} else {
|
||||||
|
cancelPickup(inv);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (srcBag == dstBag && srcSlot == dstSlot) {
|
||||||
|
cancelPickup(inv);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
gameHandler_->swapContainerItems(srcBag, srcSlot, dstBag, dstSlot);
|
||||||
|
cancelPickup(inv);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
const auto& target = inv.getEquipSlot(slot);
|
const auto& target = inv.getEquipSlot(slot);
|
||||||
if (target.empty()) {
|
if (target.empty()) {
|
||||||
inv.setEquipSlot(slot, heldItem);
|
inv.setEquipSlot(slot, heldItem);
|
||||||
|
|
@ -657,6 +680,20 @@ void InventoryScreen::renderHeldItem() {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
bool InventoryScreen::dropHeldItemToEquipSlot(game::Inventory& inv, game::EquipSlot slot) {
|
||||||
|
if (!holdingItem) return false;
|
||||||
|
placeInEquipment(inv, slot);
|
||||||
|
return !holdingItem;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool InventoryScreen::beginPickupFromEquipSlot(game::Inventory& inv, game::EquipSlot slot) {
|
||||||
|
if (holdingItem) return false;
|
||||||
|
const auto& eq = inv.getEquipSlot(slot);
|
||||||
|
if (eq.empty()) return false;
|
||||||
|
pickupFromEquipment(inv, slot);
|
||||||
|
return holdingItem;
|
||||||
|
}
|
||||||
|
|
||||||
// ============================================================
|
// ============================================================
|
||||||
// Bags window (B key) — bottom of screen, no equipment panel
|
// Bags window (B key) — bottom of screen, no equipment panel
|
||||||
// ============================================================
|
// ============================================================
|
||||||
|
|
@ -1392,6 +1429,9 @@ void InventoryScreen::renderItemSlot(game::Inventory& inventory, const game::Ite
|
||||||
if (kind == SlotKind::BACKPACK && (backpackIndex >= 0 || isBagSlot)) {
|
if (kind == SlotKind::BACKPACK && (backpackIndex >= 0 || isBagSlot)) {
|
||||||
validDrop = true;
|
validDrop = true;
|
||||||
} else if (kind == SlotKind::EQUIPMENT && heldItem.inventoryType > 0) {
|
} else if (kind == SlotKind::EQUIPMENT && heldItem.inventoryType > 0) {
|
||||||
|
if (heldItem.inventoryType == 18) {
|
||||||
|
validDrop = (equipSlot >= game::EquipSlot::BAG1 && equipSlot <= game::EquipSlot::BAG4);
|
||||||
|
} else {
|
||||||
game::EquipSlot validSlot = getEquipSlotForType(heldItem.inventoryType, inventory);
|
game::EquipSlot validSlot = getEquipSlotForType(heldItem.inventoryType, inventory);
|
||||||
validDrop = (equipSlot == validSlot);
|
validDrop = (equipSlot == validSlot);
|
||||||
if (!validDrop && heldItem.inventoryType == 11)
|
if (!validDrop && heldItem.inventoryType == 11)
|
||||||
|
|
@ -1400,6 +1440,7 @@ void InventoryScreen::renderItemSlot(game::Inventory& inventory, const game::Ite
|
||||||
validDrop = (equipSlot == game::EquipSlot::TRINKET1 || equipSlot == game::EquipSlot::TRINKET2);
|
validDrop = (equipSlot == game::EquipSlot::TRINKET1 || equipSlot == game::EquipSlot::TRINKET2);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
if (isEmpty) {
|
if (isEmpty) {
|
||||||
ImU32 bgCol = IM_COL32(30, 30, 30, 200);
|
ImU32 bgCol = IM_COL32(30, 30, 30, 200);
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue