mirror of
https://github.com/brighton-chi/mod-aoe-loot.git
synced 2026-01-13 00:58:34 +00:00
preserve configured loot method after server restart
This commit is contained in:
3
.vs/ProjectSettings.json
Normal file
3
.vs/ProjectSettings.json
Normal file
@@ -0,0 +1,3 @@
|
||||
{
|
||||
"CurrentProjectSetting": "No Configurations"
|
||||
}
|
||||
9
.vs/VSWorkspaceState.json
Normal file
9
.vs/VSWorkspaceState.json
Normal file
@@ -0,0 +1,9 @@
|
||||
{
|
||||
"ExpandedNodes": [
|
||||
"",
|
||||
"\\conf",
|
||||
"\\src"
|
||||
],
|
||||
"SelectedNode": "\\src\\aoe_loot.h",
|
||||
"PreviewInSolutionExplorer": false
|
||||
}
|
||||
BIN
.vs/mod-aoe-loot/CopilotIndices/17.14.995.13737/CodeChunks.db
Normal file
BIN
.vs/mod-aoe-loot/CopilotIndices/17.14.995.13737/CodeChunks.db
Normal file
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
BIN
.vs/mod-aoe-loot/v17/.wsuo
Normal file
BIN
.vs/mod-aoe-loot/v17/.wsuo
Normal file
Binary file not shown.
BIN
.vs/mod-aoe-loot/v17/Browse.VC.db
Normal file
BIN
.vs/mod-aoe-loot/v17/Browse.VC.db
Normal file
Binary file not shown.
71
.vs/mod-aoe-loot/v17/DocumentLayout.json
Normal file
71
.vs/mod-aoe-loot/v17/DocumentLayout.json
Normal file
@@ -0,0 +1,71 @@
|
||||
{
|
||||
"Version": 1,
|
||||
"WorkspaceRootPath": "C:\\Azerothcore (WotLK \u002B Playerbots)\\azerothcore-wotlk\\modules\\mod-aoe-loot\\",
|
||||
"Documents": [
|
||||
{
|
||||
"AbsoluteMoniker": "D:0:0:{A2FE74E1-B743-11D0-AE1A-00A0C90FFFC3}|\u003CMiscFiles\u003E|C:\\Azerothcore (WotLK \u002B Playerbots)\\azerothcore-wotlk\\modules\\mod-aoe-loot\\src\\aoe_loot.cpp||{D0E1A5C6-B359-4E41-9B60-3365922C2A22}",
|
||||
"RelativeMoniker": "D:0:0:{A2FE74E1-B743-11D0-AE1A-00A0C90FFFC3}|\u003CMiscFiles\u003E|solutionrelative:src\\aoe_loot.cpp||{D0E1A5C6-B359-4E41-9B60-3365922C2A22}"
|
||||
},
|
||||
{
|
||||
"AbsoluteMoniker": "D:0:0:{A2FE74E1-B743-11D0-AE1A-00A0C90FFFC3}|\u003CMiscFiles\u003E|C:\\Azerothcore (WotLK \u002B Playerbots)\\azerothcore-wotlk\\modules\\mod-aoe-loot\\conf\\mod_aoe_loot.conf.dist||{8B382828-6202-11D1-8870-0000F87579D2}",
|
||||
"RelativeMoniker": "D:0:0:{A2FE74E1-B743-11D0-AE1A-00A0C90FFFC3}|\u003CMiscFiles\u003E|solutionrelative:conf\\mod_aoe_loot.conf.dist||{8B382828-6202-11D1-8870-0000F87579D2}"
|
||||
},
|
||||
{
|
||||
"AbsoluteMoniker": "D:0:0:{A2FE74E1-B743-11D0-AE1A-00A0C90FFFC3}|\u003CMiscFiles\u003E|C:\\Azerothcore (WotLK \u002B Playerbots)\\azerothcore-wotlk\\modules\\mod-aoe-loot\\src\\aoe_loot.h||{D0E1A5C6-B359-4E41-9B60-3365922C2A22}",
|
||||
"RelativeMoniker": "D:0:0:{A2FE74E1-B743-11D0-AE1A-00A0C90FFFC3}|\u003CMiscFiles\u003E|solutionrelative:src\\aoe_loot.h||{D0E1A5C6-B359-4E41-9B60-3365922C2A22}"
|
||||
}
|
||||
],
|
||||
"DocumentGroupContainers": [
|
||||
{
|
||||
"Orientation": 0,
|
||||
"VerticalTabListWidth": 256,
|
||||
"DocumentGroups": [
|
||||
{
|
||||
"DockedWidth": 200,
|
||||
"SelectedChildIndex": 2,
|
||||
"Children": [
|
||||
{
|
||||
"$type": "Document",
|
||||
"DocumentIndex": 2,
|
||||
"Title": "aoe_loot.h",
|
||||
"DocumentMoniker": "C:\\Azerothcore (WotLK \u002B Playerbots)\\azerothcore-wotlk\\modules\\mod-aoe-loot\\src\\aoe_loot.h",
|
||||
"RelativeDocumentMoniker": "src\\aoe_loot.h",
|
||||
"ToolTip": "C:\\Azerothcore (WotLK \u002B Playerbots)\\azerothcore-wotlk\\modules\\mod-aoe-loot\\src\\aoe_loot.h",
|
||||
"RelativeToolTip": "src\\aoe_loot.h",
|
||||
"ViewState": "AgIAACcAAAAAAAAAAAAAAD4AAAAAAAAAAAAAAA==",
|
||||
"Icon": "ae27a6b0-e345-4288-96df-5eaf394ee369.000680|",
|
||||
"WhenOpened": "2025-08-16T01:59:55.31Z",
|
||||
"EditorCaption": ""
|
||||
},
|
||||
{
|
||||
"$type": "Document",
|
||||
"DocumentIndex": 1,
|
||||
"Title": "mod_aoe_loot.conf.dist",
|
||||
"DocumentMoniker": "C:\\Azerothcore (WotLK \u002B Playerbots)\\azerothcore-wotlk\\modules\\mod-aoe-loot\\conf\\mod_aoe_loot.conf.dist",
|
||||
"RelativeDocumentMoniker": "conf\\mod_aoe_loot.conf.dist",
|
||||
"ToolTip": "C:\\Azerothcore (WotLK \u002B Playerbots)\\azerothcore-wotlk\\modules\\mod-aoe-loot\\conf\\mod_aoe_loot.conf.dist",
|
||||
"RelativeToolTip": "conf\\mod_aoe_loot.conf.dist",
|
||||
"ViewState": "AgIAAAAAAAAAAAAAAAAAAAcAAAAgAAAAAAAAAA==",
|
||||
"Icon": "ae27a6b0-e345-4288-96df-5eaf394ee369.001001|",
|
||||
"WhenOpened": "2025-08-16T01:40:45.459Z",
|
||||
"EditorCaption": ""
|
||||
},
|
||||
{
|
||||
"$type": "Document",
|
||||
"DocumentIndex": 0,
|
||||
"Title": "aoe_loot.cpp",
|
||||
"DocumentMoniker": "C:\\Azerothcore (WotLK \u002B Playerbots)\\azerothcore-wotlk\\modules\\mod-aoe-loot\\src\\aoe_loot.cpp",
|
||||
"RelativeDocumentMoniker": "src\\aoe_loot.cpp",
|
||||
"ToolTip": "C:\\Azerothcore (WotLK \u002B Playerbots)\\azerothcore-wotlk\\modules\\mod-aoe-loot\\src\\aoe_loot.cpp",
|
||||
"RelativeToolTip": "src\\aoe_loot.cpp",
|
||||
"ViewState": "AgIAAAYAAAAAAAAAAAAAACYAAAADAAAAAAAAAA==",
|
||||
"Icon": "ae27a6b0-e345-4288-96df-5eaf394ee369.000677|",
|
||||
"WhenOpened": "2025-08-16T01:40:05.831Z",
|
||||
"EditorCaption": ""
|
||||
}
|
||||
]
|
||||
}
|
||||
]
|
||||
}
|
||||
]
|
||||
}
|
||||
BIN
.vs/mod-aoe-loot/v17/Solution.VC.db
Normal file
BIN
.vs/mod-aoe-loot/v17/Solution.VC.db
Normal file
Binary file not shown.
BIN
.vs/mod-aoe-loot/v17/ipch/AutoPCH/9b5505974df1ab6b/PLAYER.ipch
Normal file
BIN
.vs/mod-aoe-loot/v17/ipch/AutoPCH/9b5505974df1ab6b/PLAYER.ipch
Normal file
Binary file not shown.
Binary file not shown.
BIN
.vs/mod-aoe-loot/v17/ipch/AutoPCH/f16803946d677ffc/AOE_LOOT.ipch
Normal file
BIN
.vs/mod-aoe-loot/v17/ipch/AutoPCH/f16803946d677ffc/AOE_LOOT.ipch
Normal file
Binary file not shown.
BIN
.vs/slnx.sqlite
Normal file
BIN
.vs/slnx.sqlite
Normal file
Binary file not shown.
@@ -1,40 +1,48 @@
|
||||
########################################
|
||||
# AoeLoot module configuration
|
||||
# AoeLoot Module Configuration
|
||||
########################################
|
||||
#
|
||||
# AOELoot.Enable
|
||||
# Default: 2 - (Enabled for solo and group play)
|
||||
# 1 - (Enabled for solo play only)
|
||||
# 0 - (Disabled)
|
||||
# AoeLoot.EnableMod
|
||||
# Values: 0 = Disable module
|
||||
# 1 = Enable module
|
||||
# Default: 1 (Enabled)
|
||||
|
||||
AOELoot.Enable = 2
|
||||
AoeLoot.EnableMod = 1
|
||||
|
||||
# AOELoot.Message
|
||||
# Description: Enable module notification message on login
|
||||
# Default: 0 - (Disabled)
|
||||
# 1 - (Enabled)
|
||||
# AoeLoot.EnableAOELoot
|
||||
# Values: 0 = Disable AoE looting feature
|
||||
# 1 = Enable AoE looting feature (solo play only)
|
||||
# 2 = Enable AoE looting feature (solo and group play)
|
||||
# Default: 2 (Enabled for solo and group play)
|
||||
|
||||
AOELoot.Message = 0
|
||||
AoeLoot.EnableAOELoot = 2
|
||||
|
||||
# AOELoot.Range
|
||||
# AoeLoot.Message
|
||||
# Description: Enable module notification message on login
|
||||
# Values: 0 = Disable message
|
||||
# 1 = Enable message
|
||||
# Default: 1 (Enabled)
|
||||
|
||||
AoeLoot.Message = 1
|
||||
|
||||
# AoeLoot.Range
|
||||
# Description: Radius for AoE looting area
|
||||
# Default: 55.0
|
||||
|
||||
AOELoot.Range = 55.0
|
||||
AoeLoot.Range = 55.0
|
||||
|
||||
# AOELoot.DefaultLootMethod
|
||||
# AoeLoot.DefaultLootMethod
|
||||
# Description: Sets the default loot method for newly created groups
|
||||
# Values: 0 = Free For All (everyone can loot everything)
|
||||
# 1 = Round Robin (items are distributed in turn)
|
||||
# 2 = Master Loot (only master looter can distribute items)
|
||||
# 3 = Group Loot (group rolls on items above threshold)
|
||||
# 4 = Need Before Greed (players roll Need/Greed/Pass on items above threshold)
|
||||
# Default: 3 (Group Loot)
|
||||
# Values: 0 = Free For All (players can loot everything)
|
||||
# 1 = Round Robin (players take turns looting)
|
||||
# 2 = Group Loot (Blizzard default; players take turns looting, except items at or above the DefautlLootThreshold are rolled for by all players)
|
||||
# 3 = Need Before Greed (players take turns looting, except items at or above the DefaultLootThreshold are rolled for by players who can use them)
|
||||
# 4 = Master Loot (only master looter can distribute items)
|
||||
# Default: 2 (Group Loot)
|
||||
|
||||
AOELoot.DefaultLootMethod = 3
|
||||
AoeLoot.DefaultLootMethod = 2
|
||||
|
||||
#
|
||||
# AOELoot.DefaultLootThreshold
|
||||
# AoeLoot.DefaultLootThreshold
|
||||
# Description: Item quality threshold for group loot rolls (applies only to Group Loot and Need Before Greed)
|
||||
# Values: 0 = Poor (Gray)
|
||||
# 1 = Common (White)
|
||||
@@ -44,26 +52,18 @@ AOELoot.DefaultLootMethod = 3
|
||||
# 5 = Legendary (Orange)
|
||||
# Default: 2 (Uncommon)
|
||||
|
||||
AOELoot.DefaultLootThreshold = 2
|
||||
AoeLoot.DefaultLootThreshold = 2
|
||||
|
||||
# AOELoot.Debug
|
||||
# AoeLoot.Debug
|
||||
# Description: Enables debugging mode.
|
||||
# Values: 0 = Disabled
|
||||
# 1 = Enabled
|
||||
# Default: 0 (Disabled)
|
||||
|
||||
AOELoot.Debug = 0
|
||||
|
||||
# AOELoot.QuestItemsAsRegular
|
||||
# Description: Treat quest items as regular loot instead of processing them separately
|
||||
# Values: 0 = Process quest items separately (default behavior)
|
||||
# 1 = Treat quest items as regular loot
|
||||
# Default: 0 (Process separately)
|
||||
|
||||
AOELoot.QuestItemsAsRegular = 0
|
||||
AoeLoot.Debug = 0
|
||||
|
||||
# Chat Commands
|
||||
# .aoeloot off If module is enabled, disables AoE looting for player
|
||||
# .aoeloot on If module is enabled, reenables AoE looting for player
|
||||
# .aoeloot lootall Loot all enemies within AOELoot.Range
|
||||
# .AoeLoot off Disables AoE looting for player
|
||||
# .AoeLoot on Enables AoE looting for player (requires module to be enabled)
|
||||
# .AoeLoot lootall Loot all enemies within AoeLoot.Range
|
||||
#
|
||||
|
||||
374
src/aoe_loot.cpp
374
src/aoe_loot.cpp
@@ -26,11 +26,13 @@ using namespace WorldPackets;
|
||||
|
||||
// Thread-safe player AoE loot preference storage (renamed)
|
||||
std::map<uint64, bool> playerAoeLootPreferences;
|
||||
std::mutex aoeLootPreferencesMutex;
|
||||
std::mutex AoeLootPreferencesMutex;
|
||||
|
||||
// Track groups that have had default loot settings applied by us
|
||||
std::set<uint64> groupsWithAppliedDefaults;
|
||||
std::mutex groupLootMethodMutex;
|
||||
// Helper function to check if loot system module is enabled
|
||||
bool IsAoeLootModuleEnabled()
|
||||
{
|
||||
return sConfigMgr->GetOption<bool>("AoeLoot.EnableMod", true);
|
||||
}
|
||||
|
||||
// Helper function to get configured loot method from config value
|
||||
LootMethod GetLootMethodFromConfig(uint32 configValue)
|
||||
@@ -48,11 +50,33 @@ LootMethod GetLootMethodFromConfig(uint32 configValue)
|
||||
case 4:
|
||||
return NEED_BEFORE_GREED;
|
||||
default:
|
||||
LOG_WARN("module.aoe_loot", "Invalid AOELoot.DefaultLootMethod value: {}. Using Group Loot.", configValue);
|
||||
LOG_WARN("module.aoe_loot", "Invalid AoeLoot.DefaultLootMethod value: {}. Using Group Loot.", configValue);
|
||||
return GROUP_LOOT;
|
||||
}
|
||||
}
|
||||
|
||||
// Helper function to apply default loot settings to a group
|
||||
void ApplyDefaultLootSettings(Group* group, Player* leaderOrPlayer)
|
||||
{
|
||||
if (!group || !leaderOrPlayer)
|
||||
return;
|
||||
|
||||
uint32 defaultLootMethodConfig = sConfigMgr->GetOption<uint32>("AoeLoot.DefaultLootMethod", 3);
|
||||
LootMethod lootMethod = GetLootMethodFromConfig(defaultLootMethodConfig);
|
||||
group->SetLootMethod(lootMethod);
|
||||
|
||||
if (lootMethod == NEED_BEFORE_GREED || lootMethod == GROUP_LOOT)
|
||||
{
|
||||
uint32 defaultLootThreshold = sConfigMgr->GetOption<uint32>("AoeLoot.DefaultLootThreshold", 2);
|
||||
group->SetLootThreshold(ItemQualities(defaultLootThreshold));
|
||||
}
|
||||
|
||||
if (lootMethod == MASTER_LOOT)
|
||||
{
|
||||
group->SetMasterLooterGuid(leaderOrPlayer->GetGUID());
|
||||
}
|
||||
}
|
||||
|
||||
// Define the roll vote enum value - use the correct RollVote enum
|
||||
#ifndef NOT_EMITED_YET
|
||||
#define NOT_EMITED_YET RollVote(0)
|
||||
@@ -61,9 +85,9 @@ LootMethod GetLootMethodFromConfig(uint32 configValue)
|
||||
// Helper function to check if AOE loot is enabled for current context
|
||||
bool AoeLootCommandScript::IsAoeLootEnabledForPlayer(Player* player)
|
||||
{
|
||||
uint32 aoeLootMode = sConfigMgr->GetOption<uint32>("AOELoot.Enable", 2);
|
||||
|
||||
switch (aoeLootMode)
|
||||
uint32 AoeLootMode = sConfigMgr->GetOption<uint32>("AoeLoot.EnableAOELoot", 2);
|
||||
|
||||
switch (AoeLootMode)
|
||||
{
|
||||
case 0: // Disabled
|
||||
return false;
|
||||
@@ -75,13 +99,16 @@ bool AoeLootCommandScript::IsAoeLootEnabledForPlayer(Player* player)
|
||||
return true;
|
||||
|
||||
default: // Invalid value, default to solo + group
|
||||
LOG_WARN("module.aoe_loot", "Invalid AOELoot.Enable value: {}. Using default (2).", aoeLootMode);
|
||||
LOG_WARN("module.aoe_loot", "Invalid AoeLoot.EnableAOELoot value: {}. Using default (2).", AoeLootMode);
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
bool AoeLootServer::CanPacketReceive(WorldSession* session, WorldPacket& packet)
|
||||
{
|
||||
if (!IsAoeLootModuleEnabled())
|
||||
return true;
|
||||
|
||||
if (packet.GetOpcode() == CMSG_LOOT)
|
||||
{
|
||||
Player* player = session->GetPlayer();
|
||||
@@ -133,7 +160,7 @@ bool AoeLootServer::CanPacketReceive(WorldSession* session, WorldPacket& packet)
|
||||
|
||||
// Check if player has explicitly disabled AOE loot (thread-safe)
|
||||
{
|
||||
std::lock_guard<std::mutex> lock(aoeLootPreferencesMutex);
|
||||
std::lock_guard<std::mutex> lock(AoeLootPreferencesMutex);
|
||||
auto it = playerAoeLootPreferences.find(guid);
|
||||
if (it != playerAoeLootPreferences.end() && !it->second)
|
||||
{
|
||||
@@ -146,7 +173,7 @@ bool AoeLootServer::CanPacketReceive(WorldSession* session, WorldPacket& packet)
|
||||
if (player->GetLootGUID().IsEmpty())
|
||||
{
|
||||
ChatHandler handler(player->GetSession());
|
||||
handler.ParseCommands(".aoeloot lootall");
|
||||
handler.ParseCommands(".AoeLoot lootall");
|
||||
}
|
||||
}
|
||||
return true;
|
||||
@@ -154,23 +181,26 @@ bool AoeLootServer::CanPacketReceive(WorldSession* session, WorldPacket& packet)
|
||||
|
||||
ChatCommandTable AoeLootCommandScript::GetCommands() const
|
||||
{
|
||||
static ChatCommandTable aoeLootSubCommandTable =
|
||||
static ChatCommandTable AoeLootSubCommandTable =
|
||||
{
|
||||
{ "lootall", TriggerAoeLootCommand, SEC_PLAYER, Console::No },
|
||||
{ "on", EnableAoeLootCommand, SEC_PLAYER, Console::No },
|
||||
{ "off", DisableAoeLootCommand, SEC_PLAYER, Console::No }
|
||||
};
|
||||
|
||||
static ChatCommandTable aoeLootCommandTable =
|
||||
static ChatCommandTable AoeLootCommandTable =
|
||||
{
|
||||
{ "aoeloot", aoeLootSubCommandTable }
|
||||
{ "AoeLoot", AoeLootSubCommandTable }
|
||||
};
|
||||
|
||||
return aoeLootCommandTable;
|
||||
return AoeLootCommandTable;
|
||||
}
|
||||
|
||||
bool AoeLootCommandScript::EnableAoeLootCommand(ChatHandler* handler, Optional<std::string> /*args*/)
|
||||
bool AoeLootCommandScript::EnableAoeLootCommand(ChatHandler* handler, Optional<std::string>)
|
||||
{
|
||||
if (!IsAoeLootModuleEnabled())
|
||||
return true;
|
||||
|
||||
Player* player = handler->GetSession()->GetPlayer();
|
||||
if (!player)
|
||||
return true;
|
||||
@@ -180,8 +210,8 @@ bool AoeLootCommandScript::EnableAoeLootCommand(ChatHandler* handler, Optional<s
|
||||
// Check if AOE loot is enabled server-side
|
||||
if (!IsAoeLootEnabledForPlayer(player))
|
||||
{
|
||||
uint32 aoeLootMode = sConfigMgr->GetOption<uint32>("AOELoot.Enable", 2);
|
||||
switch (aoeLootMode)
|
||||
uint32 AoeLootMode = sConfigMgr->GetOption<uint32>("AoeLoot.EnableAOELoot", 2);
|
||||
switch (AoeLootMode)
|
||||
{
|
||||
case 0:
|
||||
handler->PSendSysMessage("AOE looting is completely disabled on this server.");
|
||||
@@ -198,16 +228,19 @@ bool AoeLootCommandScript::EnableAoeLootCommand(ChatHandler* handler, Optional<s
|
||||
|
||||
// Thread-safe update
|
||||
{
|
||||
std::lock_guard<std::mutex> lock(aoeLootPreferencesMutex);
|
||||
std::lock_guard<std::mutex> lock(AoeLootPreferencesMutex);
|
||||
playerAoeLootPreferences[guid] = true;
|
||||
}
|
||||
|
||||
handler->PSendSysMessage("AOE looting has been enabled for your character. Type: '.aoeloot off' to turn AoE Looting Off.");
|
||||
handler->PSendSysMessage("AOE looting has been enabled for your character. Type: '.AoeLoot off' to turn AoE Looting Off.");
|
||||
return true;
|
||||
}
|
||||
|
||||
bool AoeLootCommandScript::DisableAoeLootCommand(ChatHandler* handler, Optional<std::string> /*args*/)
|
||||
bool AoeLootCommandScript::DisableAoeLootCommand(ChatHandler* handler, Optional<std::string>)
|
||||
{
|
||||
if (!IsAoeLootModuleEnabled())
|
||||
return true;
|
||||
|
||||
Player* player = handler->GetSession()->GetPlayer();
|
||||
if (!player)
|
||||
return true;
|
||||
@@ -216,15 +249,14 @@ bool AoeLootCommandScript::DisableAoeLootCommand(ChatHandler* handler, Optional<
|
||||
|
||||
// Thread-safe update
|
||||
{
|
||||
std::lock_guard<std::mutex> lock(aoeLootPreferencesMutex);
|
||||
std::lock_guard<std::mutex> lock(AoeLootPreferencesMutex);
|
||||
playerAoeLootPreferences[guid] = false;
|
||||
}
|
||||
|
||||
handler->PSendSysMessage("AOE looting has been disabled for your character. Type: '.aoeloot on' to turn AoE Looting on.");
|
||||
handler->PSendSysMessage("AOE looting has been disabled for your character. Type: '.AoeLoot on' to turn AoE Looting on.");
|
||||
return true;
|
||||
}
|
||||
|
||||
// Rename ValidateLootDistance to ValidateLootingDistance
|
||||
bool AoeLootCommandScript::ValidateLootingDistance(Player* player, ObjectGuid lguid, float maxDistance)
|
||||
{
|
||||
if (!player)
|
||||
@@ -232,7 +264,7 @@ bool AoeLootCommandScript::ValidateLootingDistance(Player* player, ObjectGuid lg
|
||||
|
||||
// Use configured AOE distance if no specific distance provided
|
||||
if (maxDistance <= 0.0f)
|
||||
maxDistance = sConfigMgr->GetOption<float>("AOELoot.Range", 55.0f);
|
||||
maxDistance = sConfigMgr->GetOption<float>("AoeLoot.Range", 55.0f);
|
||||
|
||||
if (lguid.IsGameObject())
|
||||
{
|
||||
@@ -277,7 +309,6 @@ bool AoeLootCommandScript::ValidateLootingDistance(Player* player, ObjectGuid lg
|
||||
}
|
||||
}
|
||||
|
||||
// Rename ProcessLootMoney to ProcessCreatureGold
|
||||
bool AoeLootCommandScript::ProcessCreatureGold(Player* player, Creature* creature)
|
||||
{
|
||||
if (!player || !creature)
|
||||
@@ -341,8 +372,7 @@ bool AoeLootCommandScript::ProcessCreatureGold(Player* player, Creature* creatur
|
||||
return true;
|
||||
}
|
||||
|
||||
// Rename ProcessLootRelease to ReleaseAndCleanupLoot
|
||||
void AoeLootCommandScript::ReleaseAndCleanupLoot(ObjectGuid lguid, Player* player, Loot* /*originalLoot*/)
|
||||
void AoeLootCommandScript::ReleaseAndCleanupLoot(ObjectGuid lguid, Player* player, Loot*)
|
||||
{
|
||||
player->SetLootGUID(ObjectGuid::Empty);
|
||||
player->SendLootRelease(lguid);
|
||||
@@ -441,9 +471,11 @@ void AoeLootCommandScript::ReleaseAndCleanupLoot(ObjectGuid lguid, Player* playe
|
||||
}
|
||||
}
|
||||
|
||||
// Rename ProcessLootSlot to ProcessSingleLootSlot
|
||||
bool AoeLootCommandScript::ProcessSingleLootSlot(Player* player, ObjectGuid lguid, uint8 lootSlot)
|
||||
{
|
||||
if (!IsAoeLootModuleEnabled())
|
||||
return true;
|
||||
|
||||
if (!player)
|
||||
return false;
|
||||
|
||||
@@ -600,6 +632,9 @@ bool AoeLootCommandScript::ProcessSingleLootSlot(Player* player, ObjectGuid lgui
|
||||
|
||||
bool AoeLootCommandScript::TriggerAoeLootCommand(ChatHandler* handler, Optional<std::string> /*args*/)
|
||||
{
|
||||
if (!IsAoeLootModuleEnabled())
|
||||
return true;
|
||||
|
||||
Player* player = handler->GetSession()->GetPlayer();
|
||||
if (!player)
|
||||
return true;
|
||||
@@ -611,8 +646,8 @@ bool AoeLootCommandScript::TriggerAoeLootCommand(ChatHandler* handler, Optional<
|
||||
return true;
|
||||
}
|
||||
|
||||
float range = sConfigMgr->GetOption<float>("AOELoot.Range", 55.0);
|
||||
bool debugMode = sConfigMgr->GetOption<bool>("AOELoot.Debug", false);
|
||||
float range = sConfigMgr->GetOption<float>("AoeLoot.Range", 55.0);
|
||||
bool debugMode = sConfigMgr->GetOption<bool>("AoeLoot.Debug", false);
|
||||
|
||||
std::list<Creature*> nearbyCorpses;
|
||||
player->GetDeadCreatureListInGrid(nearbyCorpses, range);
|
||||
@@ -715,25 +750,8 @@ bool AoeLootCommandScript::TriggerAoeLootCommand(ChatHandler* handler, Optional<
|
||||
}
|
||||
}
|
||||
|
||||
// Handle quest items based on configuration
|
||||
if (ShouldProcessQuestItemsSeparately())
|
||||
{
|
||||
// Process quest items separately (default behavior)
|
||||
ProcessQuestItemsForPlayer(player, lguid, loot);
|
||||
}
|
||||
else
|
||||
{
|
||||
// Treat quest items as regular loot (like quest loot party mod)
|
||||
for (uint8 i = 0; i < loot->quest_items.size(); ++i)
|
||||
{
|
||||
uint8 questLootSlot = loot->items.size() + i;
|
||||
ProcessSingleLootSlot(player, lguid, questLootSlot);
|
||||
if (debugMode)
|
||||
{
|
||||
LOG_DEBUG("module.aoe_loot", "AOE Loot: looted quest item (as regular) in slot {}", questLootSlot);
|
||||
}
|
||||
}
|
||||
}
|
||||
// Always process quest items using Blizzard logic (only for players who need them)
|
||||
ProcessQuestItemsForPlayer(player, lguid, loot);
|
||||
|
||||
// Handle money
|
||||
if (loot->gold > 0)
|
||||
@@ -757,14 +775,22 @@ bool AoeLootCommandScript::TriggerAoeLootCommand(ChatHandler* handler, Optional<
|
||||
// Display login message to player
|
||||
void AoeLootPlayer::OnPlayerLogin(Player* player)
|
||||
{
|
||||
// Check if AOE loot is enabled at all (any mode > 0)
|
||||
uint32 aoeLootMode = sConfigMgr->GetOption<uint32>("AOELoot.Enable", 2);
|
||||
|
||||
if (aoeLootMode > 0 && sConfigMgr->GetOption<bool>("AOELoot.Message", true))
|
||||
if (!IsAoeLootModuleEnabled())
|
||||
return;
|
||||
|
||||
// If player is in a group, apply default loot settings
|
||||
if (Group* group = player->GetGroup())
|
||||
{
|
||||
ApplyDefaultLootSettings(group, player);
|
||||
}
|
||||
|
||||
uint32 AoeLootMode = sConfigMgr->GetOption<uint32>("AoeLoot.EnableAOELoot", 2);
|
||||
|
||||
if (AoeLootMode > 0 && sConfigMgr->GetOption<bool>("AoeLoot.Message", true))
|
||||
{
|
||||
std::string message = "AOE looting has been enabled for your character";
|
||||
|
||||
switch (aoeLootMode)
|
||||
switch (AoeLootMode)
|
||||
{
|
||||
case 1:
|
||||
message += " (solo play only)";
|
||||
@@ -774,246 +800,58 @@ void AoeLootPlayer::OnPlayerLogin(Player* player)
|
||||
break;
|
||||
}
|
||||
|
||||
message += ". Type: '.aoeloot off' to turn AoE Looting Off.";
|
||||
message += ". Type: '.AoeLoot off' to turn AoE Looting Off.";
|
||||
ChatHandler(player->GetSession()).PSendSysMessage(message.c_str());
|
||||
}
|
||||
}
|
||||
|
||||
// Group script implementation
|
||||
void AoeLootGroupScript::OnCreate(Group* group, Player* leader)
|
||||
{
|
||||
// Only apply default loot method to brand new groups, not reformed/rejoined groups
|
||||
if (!group || !leader)
|
||||
return;
|
||||
|
||||
// Only apply to truly new groups (single member = the leader)
|
||||
// When a player rejoins an existing group, the group already has its loot method preserved
|
||||
if (group->GetMembersCount() > 1)
|
||||
if (!IsAoeLootModuleEnabled())
|
||||
return;
|
||||
|
||||
// Check if this is a playerbot scenario - if the leader is a bot, delay loot method setting
|
||||
// to allow playerbot logic to handle leadership transfers when the player logs in
|
||||
// Note: Since IsBot() may not be available, we'll use a more conservative approach
|
||||
// and only apply defaults when we're certain it's a real player-led group
|
||||
if (!leader->GetSession() || !leader->GetSession()->GetPlayer())
|
||||
{
|
||||
// No valid session - likely a bot or disconnected player
|
||||
// Don't set loot method immediately
|
||||
if (!group || !leader)
|
||||
return;
|
||||
}
|
||||
|
||||
// Apply default loot settings for real player leaders
|
||||
|
||||
// Apply default loot settings to the group
|
||||
ApplyDefaultLootSettings(group, leader);
|
||||
}
|
||||
|
||||
// Handle leadership changes (important for playerbot scenarios)
|
||||
void AoeLootGroupScript::OnChangeLeader(Group* group, ObjectGuid newLeaderGuid, ObjectGuid /*oldLeaderGuid*/)
|
||||
{
|
||||
if (!group)
|
||||
return;
|
||||
|
||||
Player* newLeader = ObjectAccessor::FindPlayer(newLeaderGuid);
|
||||
if (!newLeader)
|
||||
return;
|
||||
|
||||
// Only apply default loot settings if:
|
||||
// 1. The new leader is a real player (has valid session)
|
||||
// 2. The loot method hasn't been manually changed from our defaults
|
||||
if (newLeader->GetSession() && newLeader->GetSession()->GetPlayer())
|
||||
{
|
||||
// Safety check for valid group GUID
|
||||
ObjectGuid groupGuid = group->GetGUID();
|
||||
if (!groupGuid.IsEmpty())
|
||||
{
|
||||
uint64 groupId = groupGuid.GetRawValue();
|
||||
if (groupId != 0) // Additional safety check
|
||||
{
|
||||
try
|
||||
{
|
||||
// Check if this group has had our defaults applied and if they've been changed
|
||||
std::lock_guard<std::mutex> lock(groupLootMethodMutex);
|
||||
if (groupsWithAppliedDefaults.find(groupId) == groupsWithAppliedDefaults.end())
|
||||
{
|
||||
// This group has never had our defaults applied
|
||||
// It's safe to apply our defaults
|
||||
ApplyDefaultLootSettings(group, newLeader);
|
||||
}
|
||||
else if (!IsLootMethodManuallySet(group))
|
||||
{
|
||||
// We've applied defaults before, but they haven't been manually changed
|
||||
// This handles bot-to-player leadership transfers where we want to reapply defaults
|
||||
ApplyDefaultLootSettings(group, newLeader);
|
||||
}
|
||||
// If the loot method has been manually changed, don't override it
|
||||
}
|
||||
catch (const std::exception& e)
|
||||
{
|
||||
LOG_ERROR("module.aoe_loot", "Failed to handle leadership change for group {}: {}", groupId, e.what());
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
LOG_WARN("module.aoe_loot", "Group has invalid GUID (0) in OnChangeLeader");
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
LOG_WARN("module.aoe_loot", "Group has empty GUID in OnChangeLeader");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Handle group dissolution - clean up tracking
|
||||
void AoeLootGroupScript::OnDisband(Group* group)
|
||||
{
|
||||
if (!group)
|
||||
return;
|
||||
|
||||
// Remove this group from our tracking when it's disbanded
|
||||
// Safety check for valid group GUID
|
||||
ObjectGuid groupGuid = group->GetGUID();
|
||||
if (!groupGuid.IsEmpty())
|
||||
{
|
||||
uint64 groupId = groupGuid.GetRawValue();
|
||||
if (groupId != 0) // Additional safety check
|
||||
{
|
||||
try
|
||||
{
|
||||
std::lock_guard<std::mutex> lock(groupLootMethodMutex);
|
||||
groupsWithAppliedDefaults.erase(groupId);
|
||||
}
|
||||
catch (const std::exception& e)
|
||||
{
|
||||
LOG_ERROR("module.aoe_loot", "Failed to clean up tracking for group {}: {}", groupId, e.what());
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Helper function to apply default loot settings
|
||||
void AoeLootGroupScript::ApplyDefaultLootSettings(Group* group, Player* leader)
|
||||
{
|
||||
if (!group || !leader)
|
||||
return;
|
||||
|
||||
// Get configured default loot method
|
||||
uint32 defaultLootMethodConfig = sConfigMgr->GetOption<uint32>("AOELoot.DefaultLootMethod", 3); // 3 = Group Loot (default)
|
||||
uint32 defaultLootThreshold = sConfigMgr->GetOption<uint32>("AOELoot.DefaultLootThreshold", 2); // Default: Uncommon
|
||||
|
||||
// Set the configured loot method for new groups
|
||||
LootMethod lootMethod = GetLootMethodFromConfig(defaultLootMethodConfig);
|
||||
group->SetLootMethod(lootMethod);
|
||||
|
||||
// If using Need Before Greed or Group Loot, also set the quality threshold
|
||||
if (lootMethod == NEED_BEFORE_GREED || lootMethod == GROUP_LOOT)
|
||||
{
|
||||
group->SetLootThreshold(ItemQualities(defaultLootThreshold));
|
||||
}
|
||||
|
||||
// If using Master Loot, set the leader as master looter
|
||||
if (lootMethod == MASTER_LOOT && leader)
|
||||
{
|
||||
group->SetMasterLooterGuid(leader->GetGUID());
|
||||
}
|
||||
|
||||
// Track that we've applied defaults to this group
|
||||
// Add safety check for valid group GUID
|
||||
ObjectGuid groupGuid = group->GetGUID();
|
||||
if (!groupGuid.IsEmpty())
|
||||
{
|
||||
uint64 groupId = groupGuid.GetRawValue();
|
||||
if (groupId != 0) // Additional safety check
|
||||
{
|
||||
try
|
||||
{
|
||||
std::lock_guard<std::mutex> lock(groupLootMethodMutex);
|
||||
groupsWithAppliedDefaults.insert(groupId);
|
||||
}
|
||||
catch (const std::exception& e)
|
||||
{
|
||||
LOG_ERROR("module.aoe_loot", "Failed to track group {} in ApplyDefaultLootSettings: {}", groupId, e.what());
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
LOG_WARN("module.aoe_loot", "Group has invalid GUID (0) in ApplyDefaultLootSettings");
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
LOG_WARN("module.aoe_loot", "Group has empty GUID in ApplyDefaultLootSettings");
|
||||
}
|
||||
}
|
||||
|
||||
// Helper function to check if loot method appears to be manually set
|
||||
bool AoeLootGroupScript::IsLootMethodManuallySet(Group* group)
|
||||
{
|
||||
if (!group)
|
||||
return false;
|
||||
|
||||
// Get our configured defaults
|
||||
uint32 defaultLootMethodConfig = sConfigMgr->GetOption<uint32>("AOELoot.DefaultLootMethod", 3);
|
||||
uint32 defaultLootThreshold = sConfigMgr->GetOption<uint32>("AOELoot.DefaultLootThreshold", 2);
|
||||
|
||||
LootMethod expectedDefaultMethod = GetLootMethodFromConfig(defaultLootMethodConfig);
|
||||
|
||||
// If the current loot method or threshold differs from our defaults,
|
||||
// it was likely changed manually by a player
|
||||
if (group->GetLootMethod() != expectedDefaultMethod)
|
||||
return true;
|
||||
|
||||
// For Group Loot and Need Before Greed, also check the threshold
|
||||
if ((expectedDefaultMethod == GROUP_LOOT || expectedDefaultMethod == NEED_BEFORE_GREED) &&
|
||||
group->GetLootThreshold() != defaultLootThreshold)
|
||||
return true;
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
// Helper function implementation for AoeLootGroupScript
|
||||
LootMethod AoeLootGroupScript::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: return GROUP_LOOT; // Safe default
|
||||
}
|
||||
}
|
||||
|
||||
// Quest item processing functions
|
||||
bool AoeLootCommandScript::ShouldProcessQuestItemsSeparately()
|
||||
{
|
||||
return !sConfigMgr->GetOption<bool>("AOELoot.QuestItemsAsRegular", false);
|
||||
}
|
||||
|
||||
bool AoeLootCommandScript::IsQuestItemForPlayer(Player* player, uint32 itemId)
|
||||
{
|
||||
if (!player)
|
||||
return false;
|
||||
|
||||
|
||||
const ItemTemplate* itemTemplate = sObjectMgr->GetItemTemplate(itemId);
|
||||
if (!itemTemplate)
|
||||
return false;
|
||||
|
||||
// Check if this item starts a quest or is a quest item
|
||||
|
||||
// Check if this item starts a quest
|
||||
if (itemTemplate->StartQuest != 0)
|
||||
return true;
|
||||
|
||||
{
|
||||
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
|
||||
{
|
||||
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)
|
||||
{
|
||||
@@ -1022,7 +860,7 @@ bool AoeLootCommandScript::IsQuestItemForPlayer(Player* player, uint32 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;
|
||||
@@ -1030,7 +868,7 @@ bool AoeLootCommandScript::IsQuestItemForPlayer(Player* player, uint32 itemId)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
@@ -1040,7 +878,7 @@ bool AoeLootCommandScript::ProcessQuestItemsForPlayer(Player* player, ObjectGuid
|
||||
return false;
|
||||
|
||||
bool processedAny = false;
|
||||
bool debugMode = sConfigMgr->GetOption<bool>("AOELoot.Debug", false);
|
||||
bool debugMode = sConfigMgr->GetOption<bool>("AoeLoot.Debug", false);
|
||||
|
||||
for (uint8 i = 0; i < loot->quest_items.size(); ++i)
|
||||
{
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
#ifndef MODULE_AOELOOT_H
|
||||
#define MODULE_AOELOOT_H
|
||||
#ifndef MODULE_AoeLoot_H
|
||||
#define MODULE_AoeLoot_H
|
||||
|
||||
#include "ScriptMgr.h"
|
||||
#include "Config.h"
|
||||
@@ -41,22 +41,20 @@ public:
|
||||
AoeLootCommandScript() : CommandScript("AoeLootCommandScript") {}
|
||||
ChatCommandTable GetCommands() const override;
|
||||
|
||||
// Renamed command handlers (removed "Handle" prefix)
|
||||
static bool EnableAoeLootCommand(ChatHandler* handler, Optional<std::string> args);
|
||||
static bool DisableAoeLootCommand(ChatHandler* handler, Optional<std::string> args);
|
||||
static bool TriggerAoeLootCommand(ChatHandler* handler, Optional<std::string> args);
|
||||
|
||||
// Renamed core processing functions
|
||||
// Core processing functions
|
||||
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 ShouldProcessQuestItemsSeparately();
|
||||
static bool ProcessQuestItemsForPlayer(Player* player, ObjectGuid lguid, Loot* loot);
|
||||
|
||||
// Renamed validation functions
|
||||
|
||||
// Validation functions
|
||||
static bool ValidateLootingDistance(Player* player, ObjectGuid lguid, float maxDistance = 0.0f);
|
||||
static bool IsAoeLootEnabledForPlayer(Player* player);
|
||||
};
|
||||
@@ -66,20 +64,12 @@ class AoeLootGroupScript : public GroupScript
|
||||
public:
|
||||
AoeLootGroupScript() : GroupScript("AoeLootGroupScript") {}
|
||||
void OnCreate(Group* group, Player* leader) override;
|
||||
void OnChangeLeader(Group* group, ObjectGuid newLeaderGuid, ObjectGuid oldLeaderGuid) override;
|
||||
void OnDisband(Group* group) override;
|
||||
|
||||
private:
|
||||
// Helper function to convert config value to LootMethod enum
|
||||
LootMethod GetLootMethodFromConfig(uint32 configValue);
|
||||
|
||||
// Helper function to apply default loot settings
|
||||
void ApplyDefaultLootSettings(Group* group, Player* leader);
|
||||
|
||||
// Helper function to check if loot method appears to be manually set
|
||||
bool IsLootMethodManuallySet(Group* group);
|
||||
};
|
||||
|
||||
void AddSC_AoeLoot();
|
||||
|
||||
#endif //MODULE_AOELOOT_H
|
||||
#endif
|
||||
|
||||
Reference in New Issue
Block a user