diff --git a/conf/mod_aoe_loot.conf.dist b/conf/mod_aoe_loot.conf.dist index 3d38a5d..056ab2d 100644 --- a/conf/mod_aoe_loot.conf.dist +++ b/conf/mod_aoe_loot.conf.dist @@ -54,14 +54,6 @@ AoeLoot.DefaultLootMethod = 2 AoeLoot.DefaultLootThreshold = 2 -# AoeLoot.Debug -# Description: Enables debugging mode. -# Values: 0 = Disabled -# 1 = Enabled -# Default: 0 (Disabled) - -AoeLoot.Debug = 0 - # Chat Commands # .AoeLoot off Disables AoE looting for player # .AoeLoot on Enables AoE looting for player (requires module to be enabled) diff --git a/src/aoe_loot.cpp b/src/aoe_loot.cpp index 6a40724..9a8c8a6 100644 --- a/src/aoe_loot.cpp +++ b/src/aoe_loot.cpp @@ -1,6 +1,5 @@ #include "aoe_loot.h" #include "ScriptMgr.h" -#include "World.h" #include "LootMgr.h" #include "ServerScript.h" #include "WorldSession.h" @@ -9,12 +8,10 @@ #include "Chat.h" #include "ChatCommand.h" #include "ChatCommandArgs.h" -#include "WorldObjectScript.h" #include "Creature.h" #include "Config.h" #include "Log.h" #include "Map.h" -#include #include "Corpse.h" #include "Group.h" #include "ObjectMgr.h" @@ -39,19 +36,12 @@ LootMethod GetLootMethodFromConfig(uint32 configValue) { switch (configValue) { - case 0: - return FREE_FOR_ALL; - case 1: - return ROUND_ROBIN; - case 2: - return MASTER_LOOT; - case 3: - return GROUP_LOOT; - case 4: - return NEED_BEFORE_GREED; - default: - LOG_WARN("module.aoe_loot", "Invalid AoeLoot.DefaultLootMethod value: {}. Using Group Loot.", configValue); - return GROUP_LOOT; + case 0: return FREE_FOR_ALL; + case 1: return ROUND_ROBIN; + case 2: return MASTER_LOOT; + case 3: return GROUP_LOOT; + case 4: return NEED_BEFORE_GREED; + default: return GROUP_LOOT; } } @@ -97,9 +87,8 @@ bool AoeLootCommandScript::IsAoeLootEnabledForPlayer(Player* player) case 2: // Enabled for both solo and group play return true; - - default: // Invalid value, default to solo + group - LOG_WARN("module.aoe_loot", "Invalid AoeLoot.EnableAOELoot value: {}. Using default (2).", AoeLootMode); + + default: // Enabled for both solo and group play return true; } } @@ -199,40 +188,17 @@ ChatCommandTable AoeLootCommandScript::GetCommands() const bool AoeLootCommandScript::EnableAoeLootCommand(ChatHandler* handler, Optional) { if (!IsAoeLootModuleEnabled()) - return true; + return true; Player* player = handler->GetSession()->GetPlayer(); - if (!player) + if (!player || !IsAoeLootEnabledForPlayer(player)) return true; uint64 guid = player->GetGUID().GetRawValue(); - - // Check if AOE loot is enabled server-side - if (!IsAoeLootEnabledForPlayer(player)) - { - uint32 AoeLootMode = sConfigMgr->GetOption("AoeLoot.EnableAOELoot", 2); - switch (AoeLootMode) - { - case 0: - handler->PSendSysMessage("AOE looting is completely disabled on this server."); - break; - case 1: - handler->PSendSysMessage("AOE looting is only available for solo play (you are currently in a group)."); - break; - default: - handler->PSendSysMessage("AOE looting is not available in your current context."); - break; - } - return true; - } - - // Thread-safe update { std::lock_guard lock(AoeLootPreferencesMutex); playerAoeLootPreferences[guid] = true; } - - handler->PSendSysMessage("AOE looting has been enabled for your character. Type: '.AoeLoot off' to turn AoE Looting Off."); return true; } @@ -253,7 +219,6 @@ bool AoeLootCommandScript::DisableAoeLootCommand(ChatHandler* handler, Optional< playerAoeLootPreferences[guid] = false; } - handler->PSendSysMessage("AOE looting has been disabled for your character. Type: '.AoeLoot on' to turn AoE Looting on."); return true; } @@ -642,37 +607,31 @@ bool AoeLootCommandScript::TriggerAoeLootCommand(ChatHandler* handler, Optional< // Check if AOE loot is enabled for this player's context if (!IsAoeLootEnabledForPlayer(player)) { - handler->PSendSysMessage("AOE looting is not available in your current context."); return true; } float range = sConfigMgr->GetOption("AoeLoot.Range", 55.0); - bool debugMode = sConfigMgr->GetOption("AoeLoot.Debug", false); std::list nearbyCorpses; player->GetDeadCreatureListInGrid(nearbyCorpses, range); - if (debugMode) - { - LOG_DEBUG("module.aoe_loot", "AOE Loot: Found {} nearby corpses within range {}.", nearbyCorpses.size(), range); - } - // Filter valid corpses std::list validCorpses; for (auto* creature : nearbyCorpses) { if (!player || !creature) continue; - - // Check if creature is valid for looting by this player + if (!player->isAllowedToLoot(creature)) - { - if (debugMode) - LOG_DEBUG("module.aoe_loot", "AOE Loot: Skipping creature {} - not your loot", creature->GetGUID().ToString()); continue; - } - if (!creature->hasLootRecipient() || !creature->isTappedBy(player)) + if (!creature->HasDynamicFlag(UNIT_DYNFLAG_LOOTABLE)) + continue; + + if (!creature->hasLootRecipient()) + continue; + + if (!creature->isTappedBy(player)) continue; // Get player's group and check loot permissions based on group loot method @@ -686,9 +645,6 @@ bool AoeLootCommandScript::TriggerAoeLootCommand(ChatHandler* handler, Optional< { if (loot->roundRobinPlayer && loot->roundRobinPlayer != player->GetGUID()) { - if (debugMode) - LOG_DEBUG("module.aoe_loot", "AOE Loot: Skipping creature {} - not your turn (Round Robin)", creature->GetGUID().ToString()); - continue; } } @@ -697,30 +653,14 @@ bool AoeLootCommandScript::TriggerAoeLootCommand(ChatHandler* handler, Optional< { if (group->GetMasterLooterGuid() != player->GetGUID()) { - if (debugMode) - LOG_DEBUG("module.aoe_loot", "AOE Loot: Skipping creature {} - not master looter", creature->GetGUID().ToString()); - continue; } } } - - // Skip if corpse is not lootable - if (!creature->HasDynamicFlag(UNIT_DYNFLAG_LOOTABLE)) - { - if (debugMode) - LOG_DEBUG("module.aoe_loot", "AOE Loot: Skipping creature {} - not lootable", creature->GetGUID().ToString()); - continue; - } validCorpses.push_back(creature); } - if (debugMode) - { - LOG_DEBUG("module.aoe_loot", "AOE Loot: Found {} valid nearby corpses within range {}.", validCorpses.size(), range); - } - // Process all valid corpses for (auto* creature : validCorpses) { @@ -733,35 +673,22 @@ bool AoeLootCommandScript::TriggerAoeLootCommand(ChatHandler* handler, Optional< // Double-check distance validation for security if (!ValidateLootingDistance(player, lguid)) { - if (debugMode) - LOG_DEBUG("module.aoe_loot", "AOE Loot: Skipping creature {} - too far away", lguid.ToString()); continue; } player->SetLootGUID(lguid); - // Process all regular items (includes quest items and FFA items automatically) + // Process all loot items for (uint8 lootSlot = 0; lootSlot < loot->items.size(); ++lootSlot) { ProcessSingleLootSlot(player, lguid, lootSlot); - if (debugMode) - { - LOG_DEBUG("module.aoe_loot", "AOE Loot: looted item from slot {} (ID: {}) from {}", lootSlot, loot->items[lootSlot].itemid, lguid.ToString()); - } } - // Always process quest items using Blizzard logic (only for players who need them) - ProcessQuestItemsForPlayer(player, lguid, loot); - // Handle money if (loot->gold > 0) { uint32 goldAmount = loot->gold; ProcessCreatureGold(player, creature); - if (debugMode) - { - LOG_DEBUG("module.aoe_loot", "AOE Loot: Looted {} copper from {}", goldAmount, lguid.ToString()); - } } if (loot->isLooted()) @@ -772,7 +699,6 @@ bool AoeLootCommandScript::TriggerAoeLootCommand(ChatHandler* handler, Optional< return true; } -// Display login message to player void AoeLootPlayer::OnPlayerLogin(Player* player) { if (!IsAoeLootModuleEnabled()) @@ -801,7 +727,6 @@ void AoeLootPlayer::OnPlayerLogin(Player* player) } message += ". Type: '.AoeLoot off' to turn AoE Looting Off."; - ChatHandler(player->GetSession()).PSendSysMessage(message.c_str()); } } @@ -817,96 +742,30 @@ void AoeLootGroupScript::OnCreate(Group* group, Player* leader) ApplyDefaultLootSettings(group, leader); } -// Quest item processing functions -bool AoeLootCommandScript::IsQuestItemForPlayer(Player* player, uint32 itemId) +class AoeLootQuestParty : public PlayerScript { - if (!player) - return false; +public: + AoeLootQuestParty() : PlayerScript("AoeLootQuestParty") { } - const ItemTemplate* itemTemplate = sObjectMgr->GetItemTemplate(itemId); - if (!itemTemplate) - return false; - - // Check if this item starts a quest - if (itemTemplate->StartQuest != 0) + void OnPlayerBeforeFillQuestLootItem(Player* /*player*/, LootItem& item) override { - uint32 questId = itemTemplate->StartQuest; - // Player must NOT have the quest, must NOT have completed it, and must NOT already have the item - if (!player->HasQuest(questId) && - player->GetQuestStatus(questId) != QUEST_STATUS_COMPLETE && - player->GetItemCount(itemId, true) == 0) // true = include bank + ItemTemplate const* itemTemplate = sObjectMgr->GetItemTemplate(item.itemid); + if (itemTemplate && + itemTemplate->Quality == ITEM_QUALITY_NORMAL && + itemTemplate->Class == ITEM_CLASS_QUEST && + itemTemplate->SubClass == ITEM_SUBCLASS_QUEST && + itemTemplate->Bonding == BIND_QUEST_ITEM) { - return true; - } - return false; - } - - // Check if player has quests requiring this item - for (uint8 slot = 0; slot < MAX_QUEST_LOG_SIZE; ++slot) - { - uint32 questId = player->GetQuestSlotQuestId(slot); - if (questId == 0) - continue; - - Quest const* quest = sObjectMgr->GetQuestTemplate(questId); - if (!quest) - continue; - - // Check quest objectives for this item - for (uint8 i = 0; i < QUEST_OBJECTIVES_COUNT; ++i) - { - if (quest->RequiredItemId[i] == itemId) - { - // Check if player still needs this item for the quest - uint32 currentCount = player->GetItemCount(itemId, true); - uint32 requiredCount = quest->RequiredItemCount[i]; - - if (currentCount < requiredCount) - { - return true; - } - } + item.freeforall = true; } } +}; - return false; -} - -bool AoeLootCommandScript::ProcessQuestItemsForPlayer(Player* player, ObjectGuid lguid, Loot* loot) -{ - if (!player || !loot) - return false; - - bool processedAny = false; - bool debugMode = sConfigMgr->GetOption("AoeLoot.Debug", false); - - for (uint8 i = 0; i < loot->quest_items.size(); ++i) - { - LootItem& questItem = loot->quest_items[i]; - - // Check if this quest item is for the current player - if (IsQuestItemForPlayer(player, questItem.itemid)) - { - uint8 questLootSlot = loot->items.size() + i; - ProcessSingleLootSlot(player, lguid, questLootSlot); - processedAny = true; - - if (debugMode) - { - LOG_DEBUG("module.aoe_loot", "AOE Loot: looted quest item {} from slot {} for player {}", - questItem.itemid, questLootSlot, player->GetName()); - } - } - } - - return processedAny; -} - -// Add script registrations void AddSC_AoeLoot() { new AoeLootPlayer(); new AoeLootServer(); new AoeLootCommandScript(); new AoeLootGroupScript(); + new AoeLootQuestParty(); } diff --git a/src/aoe_loot.h b/src/aoe_loot.h index a8d8a18..ba0959e 100644 --- a/src/aoe_loot.h +++ b/src/aoe_loot.h @@ -2,22 +2,14 @@ #define MODULE_AoeLoot_H #include "ScriptMgr.h" -#include "Config.h" #include "ServerScript.h" -#include "Chat.h" -#include "Player.h" -#include "Item.h" -#include "ScriptedGossip.h" #include "ChatCommand.h" -#include "ChatCommandArgs.h" -#include "AccountMgr.h" -#include "ObjectMgr.h" -#include "QuestDef.h" -#include -#include -#include -#include -#include + +class Player; +class Group; +class Loot; +class Creature; +class ObjectGuid; using namespace Acore::ChatCommands; @@ -49,10 +41,6 @@ public: static bool ProcessSingleLootSlot(Player* player, ObjectGuid lguid, uint8 lootSlot); static bool ProcessCreatureGold(Player* player, Creature* creature); static void ReleaseAndCleanupLoot(ObjectGuid lguid, Player* player, Loot* loot); - - // Quest item processing functions - static bool IsQuestItemForPlayer(Player* player, uint32 itemId); - static bool ProcessQuestItemsForPlayer(Player* player, ObjectGuid lguid, Loot* loot); // Validation functions static bool ValidateLootingDistance(Player* player, ObjectGuid lguid, float maxDistance = 0.0f); @@ -64,10 +52,6 @@ class AoeLootGroupScript : public GroupScript public: AoeLootGroupScript() : GroupScript("AoeLootGroupScript") {} void OnCreate(Group* group, Player* leader) override; - -private: - // Helper function to convert config value to LootMethod enum - LootMethod GetLootMethodFromConfig(uint32 configValue); }; void AddSC_AoeLoot();