diff --git a/include/game/game_handler.hpp b/include/game/game_handler.hpp index f66e29d5..5e9c969c 100644 --- a/include/game/game_handler.hpp +++ b/include/game/game_handler.hpp @@ -660,6 +660,8 @@ public: void activateSpiritHealer(uint64_t npcGuid); bool isLootWindowOpen() const { return lootWindowOpen; } const LootResponseData& getCurrentLoot() const { return currentLoot; } + void setAutoLoot(bool enabled) { autoLoot_ = enabled; } + bool isAutoLoot() const { return autoLoot_; } // NPC Gossip void interactWithNpc(uint64_t guid); @@ -1354,6 +1356,7 @@ private: // ---- Phase 5: Loot ---- bool lootWindowOpen = false; + bool autoLoot_ = false; LootResponseData currentLoot; struct LocalLootState { LootResponseData data; diff --git a/include/ui/game_screen.hpp b/include/ui/game_screen.hpp index f0b48f34..8dfa0dd4 100644 --- a/include/ui/game_screen.hpp +++ b/include/ui/game_screen.hpp @@ -97,6 +97,7 @@ private: bool pendingMinimapRotate = false; bool pendingMinimapSquare = false; bool pendingSeparateBags = true; + bool pendingAutoLoot = false; bool pendingUseOriginalSoundtrack = true; // UI element transparency (0.0 = fully transparent, 1.0 = fully opaque) diff --git a/src/game/game_handler.cpp b/src/game/game_handler.cpp index 0040b368..d73bba0b 100644 --- a/src/game/game_handler.cpp +++ b/src/game/game_handler.cpp @@ -8190,6 +8190,14 @@ void GameHandler::handleLootResponse(network::Packet& packet) { currentLoot.gold = 0; } } + + // Auto-loot items when enabled + if (autoLoot_ && state == WorldState::IN_WORLD && socket) { + for (const auto& item : currentLoot.items) { + auto pkt = AutostoreLootItemPacket::build(item.slotIndex); + socket->send(pkt); + } + } } void GameHandler::handleLootReleaseResponse(network::Packet& packet) { diff --git a/src/ui/game_screen.cpp b/src/ui/game_screen.cpp index eb09d8de..ec4f89ed 100644 --- a/src/ui/game_screen.cpp +++ b/src/ui/game_screen.cpp @@ -216,6 +216,9 @@ void GameScreen::render(game::GameHandler& gameHandler) { } } + // Apply auto-loot setting to GameHandler every frame (cheap bool sync) + gameHandler.setAutoLoot(pendingAutoLoot); + // Sync chat auto-join settings to GameHandler gameHandler.chatAutoJoin.general = chatAutoJoinGeneral_; gameHandler.chatAutoJoin.trade = chatAutoJoinTrade_; @@ -5723,6 +5726,15 @@ void GameScreen::renderSettingsWindow() { } } + ImGui::Spacing(); + ImGui::Text("Loot"); + ImGui::Separator(); + if (ImGui::Checkbox("Auto Loot", &pendingAutoLoot)) { + saveSettings(); // per-frame sync applies pendingAutoLoot to gameHandler + } + if (ImGui::IsItemHovered()) + ImGui::SetTooltip("Automatically pick up all items when looting"); + ImGui::Spacing(); ImGui::Text("Bags"); ImGui::Separator(); @@ -6304,6 +6316,9 @@ void GameScreen::saveSettings() { out << "mount_volume=" << pendingMountVolume << "\n"; out << "activity_volume=" << pendingActivityVolume << "\n"; + // Gameplay + out << "auto_loot=" << (pendingAutoLoot ? 1 : 0) << "\n"; + // Controls out << "mouse_sensitivity=" << pendingMouseSensitivity << "\n"; out << "invert_mouse=" << (pendingInvertMouse ? 1 : 0) << "\n"; @@ -6373,6 +6388,8 @@ void GameScreen::loadSettings() { else if (key == "npc_voice_volume") pendingNpcVoiceVolume = std::clamp(std::stoi(val), 0, 100); else if (key == "mount_volume") pendingMountVolume = std::clamp(std::stoi(val), 0, 100); else if (key == "activity_volume") pendingActivityVolume = std::clamp(std::stoi(val), 0, 100); + // Gameplay + else if (key == "auto_loot") pendingAutoLoot = (std::stoi(val) != 0); // Controls else if (key == "mouse_sensitivity") pendingMouseSensitivity = std::clamp(std::stof(val), 0.05f, 1.0f); else if (key == "invert_mouse") pendingInvertMouse = (std::stoi(val) != 0);