вывод из самбомудлей модов для азероткор

This commit is contained in:
2026-03-07 22:28:31 +04:00
parent 5877ea78cd
commit adcfe8e31d
1720 changed files with 1941740 additions and 40 deletions
+267
View File
@@ -0,0 +1,267 @@
/*
* This file is part of the AzerothCore Project. See AUTHORS file for Copyright information
*
* This program is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License as published by the
* Free Software Foundation; either version 2 of the License, or (at your
* option) any later version.
*
* This program is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
* more details.
*
* You should have received a copy of the GNU General Public License along
* with this program. If not, see <http://www.gnu.org/licenses/>.
*/
#include "aoe_loot.h"
#include <algorithm>
#include <limits>
std::map<uint64, bool> AoeLootCommandScript::playerAoeLootEnabled;
void AOELootPlayer::OnPlayerLogin(Player* player)
{
if (!player)
return;
if (sConfigMgr->GetOption<bool>("AOELoot.Enable", true) && sConfigMgr->GetOption<bool>("AOELoot.Message", true))
if (WorldSession* session = player->GetSession())
ChatHandler(session).PSendModuleSysMessage(MODULE_STRING, AOE_LOGIN_MESSAGE);
}
bool AOELootServer::CanPacketReceive(WorldSession* session, WorldPacket& packet)
{
// Only handle loot packets
if (packet.GetOpcode() != CMSG_LOOT)
return true;
// Basic validation checks
if (!session)
return true;
Player* player = session->GetPlayer();
if (!player)
return true;
// Check if module is enabled
if (!sConfigMgr->GetOption<bool>("AOELoot.Enable", true))
return true;
// Check if player has AOE loot disabled via command
uint64 playerGuid = player->GetGUID().GetRawValue();
if (AoeLootCommandScript::hasPlayerAoeLootEnabled(playerGuid) &&
!AoeLootCommandScript::getPlayerAoeLootEnabled(playerGuid))
return true;
// Check group settings
if (player->GetGroup() && !sConfigMgr->GetOption<bool>("AOELoot.Group", true))
return true;
// Get configured loot range
float range = sConfigMgr->GetOption<float>("AOELoot.Range", 30.0f);
// Limit range to reasonable values
if (range < 5.0f)
range = 5.0f;
if (range > 100.0f)
range = 100.0f;
// Read target GUID from packet
ObjectGuid targetGuid;
packet >> targetGuid;
if (!targetGuid)
return true;
// Get target creature
Creature* mainCreature = player->GetMap()->GetCreature(targetGuid);
if (!mainCreature)
return true;
// Check if main creature has loot
if (!mainCreature->HasDynamicFlag(UNIT_DYNFLAG_LOOTABLE))
return true;
// Get nearby corpses
std::list<Creature*> nearbyCorpses;
player->GetDeadCreatureListInGrid(nearbyCorpses, range);
// Remove invalid corpses and main target
nearbyCorpses.remove_if([&](Creature* c)
{
return !c ||
c->GetGUID() == targetGuid ||
!c->HasDynamicFlag(UNIT_DYNFLAG_LOOTABLE) ||
!player->isAllowedToLoot(c);
});
// If no other corpses, process normally
if (nearbyCorpses.empty())
{
player->SendLoot(targetGuid, LOOT_CORPSE);
return false;
}
// Get main loot
Loot* mainLoot = &mainCreature->loot;
// Limit number of corpses to process
size_t const maxCorpses = 10; // set to 10 to improve stability
size_t processedCorpses = 0;
// Track total gold to merge
uint32 totalGold = mainLoot->gold;
// Collect all items to merge (don't modify main loot directly)
std::vector<LootItem> itemsToAdd;
std::vector<LootItem> questItemsToAdd;
for (Creature* creature : nearbyCorpses)
{
if (processedCorpses >= maxCorpses)
break;
if (!creature)
continue;
Loot* loot = &creature->loot;
// Skip already looted corpses
if (loot->isLooted())
continue;
// Collect gold
if (loot->gold > 0)
{
// Prevent overflow
if (totalGold < (std::numeric_limits<uint32>::max() - loot->gold))
totalGold += loot->gold;
}
// Collect regular items
for (size_t i = 0; i < loot->items.size(); ++i)
{
// Check if there's still space
if ((mainLoot->items.size() + itemsToAdd.size() + mainLoot->quest_items.size() + questItemsToAdd.size()) >= 15)
break;
itemsToAdd.push_back(loot->items[i]);
}
// Collect quest items
for (size_t i = 0; i < loot->quest_items.size(); ++i)
{
// Check if there's still space
if ((mainLoot->items.size() + itemsToAdd.size() + mainLoot->quest_items.size() + questItemsToAdd.size()) >= 15)
break;
questItemsToAdd.push_back(loot->quest_items[i]);
}
// Clear source loot (but don't modify vector directly)
loot->clear();
creature->AllLootRemovedFromCorpse();
creature->RemoveDynamicFlag(UNIT_DYNFLAG_LOOTABLE);
processedCorpses++;
}
// Now safely add collected items to main loot
// Update gold
mainLoot->gold = totalGold;
// Add regular items
for (const auto& item : itemsToAdd)
{
if (mainLoot->items.size() < 15)
mainLoot->items.push_back(item);
}
// Add quest items to player inventory
for (const auto& item : questItemsToAdd)
{
player->AddItem(item.itemid, item.count);
}
// Send merged loot window
player->SendLoot(targetGuid, LOOT_CORPSE);
return false;
}
ChatCommandTable AoeLootCommandScript::GetCommands() const
{
static ChatCommandTable aoeLootSubCommandTable =
{
{ "on", HandleAoeLootOnCommand, SEC_PLAYER, Console::No },
{ "off", HandleAoeLootOffCommand, SEC_PLAYER, Console::No }
};
static ChatCommandTable aoeLootCommandTable =
{
{ "aoeloot", aoeLootSubCommandTable }
};
return aoeLootCommandTable;
}
bool AoeLootCommandScript::hasPlayerAoeLootEnabled(uint64 guid)
{
return playerAoeLootEnabled.count(guid) > 0;
}
bool AoeLootCommandScript::getPlayerAoeLootEnabled(uint64 guid)
{
auto it = playerAoeLootEnabled.find(guid);
if (it != playerAoeLootEnabled.end())
return it->second;
return false;
}
void AoeLootCommandScript::setPlayerAoeLootEnabled(uint64 guid, bool mode)
{
playerAoeLootEnabled[guid] = mode;
}
bool AoeLootCommandScript::HandleAoeLootOnCommand(ChatHandler* handler, Optional<std::string> /*args*/)
{
Player* player = handler->GetSession()->GetPlayer();
if (!player)
return true;
uint64 playerGuid = player->GetGUID().GetRawValue();
if (AoeLootCommandScript::hasPlayerAoeLootEnabled(playerGuid) &&
AoeLootCommandScript::getPlayerAoeLootEnabled(playerGuid))
{
handler->PSendModuleSysMessage(MODULE_STRING, AOE_LOOT_ALREADY_ENABLED);
return true;
}
AoeLootCommandScript::setPlayerAoeLootEnabled(playerGuid, true);
handler->PSendModuleSysMessage(MODULE_STRING, AOE_LOOT_ENABLED);
return true;
}
bool AoeLootCommandScript::HandleAoeLootOffCommand(ChatHandler* handler, Optional<std::string> /*args*/)
{
Player* player = handler->GetSession()->GetPlayer();
if (!player)
return true;
uint64 playerGuid = player->GetGUID().GetRawValue();
if (AoeLootCommandScript::hasPlayerAoeLootEnabled(playerGuid) &&
!AoeLootCommandScript::getPlayerAoeLootEnabled(playerGuid))
{
handler->PSendModuleSysMessage(MODULE_STRING, AOE_LOOT_ALREADY_DISABLED);
return true;
}
AoeLootCommandScript::setPlayerAoeLootEnabled(playerGuid, false);
handler->PSendModuleSysMessage(MODULE_STRING, AOE_LOOT_DISABLED);
return true;
}
+138
View File
@@ -0,0 +1,138 @@
/*
* This file is part of the AzerothCore Project. See AUTHORS file for Copyright information
*
* This program is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License as published by the
* Free Software Foundation; either version 2 of the License, or (at your
* option) any later version.
*
* This program is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
* more details.
*
* You should have received a copy of the GNU General Public License along
* with this program. If not, see <http://www.gnu.org/licenses/>.
*/
#ifndef MODULE_AOELOOT_H
#define MODULE_AOELOOT_H
#include "ScriptMgr.h"
#include "Config.h"
#include "Chat.h"
#include "Player.h"
#include "ScriptedGossip.h"
#include "Group.h"
#include "LootMgr.h"
#include "Creature.h"
#include "Log.h"
#include <vector>
#include <list>
#include <algorithm>
#include <string>
#define MODULE_STRING "mod-aoe-loot"
// Maximum loot items count
constexpr size_t MAX_LOOT_ITEMS = 16;
using namespace Acore::ChatCommands;
enum AoeLootString
{
AOE_LOGIN_MESSAGE = 1, // Login message
AOE_ITEM_IN_THE_MAIL = 2, // Mail notification
AOE_MODULE_ACTIVE = 3, // unused
AOE_QUEST_ITEM_SENT = 4, // unused
AOE_LOOT_ALREADY_ENABLED = 5, // Already enabled message
AOE_LOOT_ENABLED = 6, // Enabled confirmation
AOE_LOOT_ALREADY_DISABLED = 7, // Already disabled message
AOE_LOOT_DISABLED = 8 // Disabled confirmation
};
class AOELootPlayer : public PlayerScript
{
public:
AOELootPlayer() : PlayerScript("AOELootPlayer", { PLAYERHOOK_ON_LOGIN }) {}
void OnPlayerLogin(Player* player) override;
};
class AOELootServer : public ServerScript
{
public:
AOELootServer() : ServerScript("AOELootServer", { SERVERHOOK_CAN_PACKET_RECEIVE }) {}
bool CanPacketReceive(WorldSession* session, WorldPacket& packet) override;
private:
// Helper function - Check if loot is valid
bool IsLootValid(Loot* loot) const;
// Check if loot can be merged
bool CanMergeLoot(Player* player, Creature* creature) const;
// Safely get item count
size_t GetSafeItemCount(Loot* loot) const;
// Safely merge loot items
bool SafeMergeLootItems(Loot* mainLoot, Loot* sourceLoot, size_t& remainingSlots);
};
// Configuration options structure (optional, for better config management)
struct AOELootConfig
{
bool enabled = true;
bool messageOnLogin = true;
bool allowInGroup = true;
float range = 55.0f;
uint32 maxCorpses = 20;
static AOELootConfig* instance()
{
static AOELootConfig instance;
return &instance;
}
void Load()
{
enabled = sConfigMgr->GetOption<bool>("AOELoot.Enable", true);
messageOnLogin = sConfigMgr->GetOption<bool>("AOELoot.Message", true);
allowInGroup = sConfigMgr->GetOption<bool>("AOELoot.Group", true);
range = sConfigMgr->GetOption<float>("AOELoot.Range", 55.0f);
maxCorpses = sConfigMgr->GetOption<uint32>("AOELoot.MaxCorpses", 20);
// Validate configuration values
if (range < 5.0f) range = 5.0f;
if (range > 100.0f) range = 100.0f;
if (maxCorpses < 1) maxCorpses = 1;
if (maxCorpses > 50) maxCorpses = 50;
}
};
class AoeLootCommandScript : public CommandScript
{
public:
AoeLootCommandScript() : CommandScript("AoeLootCommandScript") {}
ChatCommandTable GetCommands() const override;
static bool HandleAoeLootOnCommand(ChatHandler* handler, Optional<std::string> args);
static bool HandleAoeLootOffCommand(ChatHandler* handler, Optional<std::string> args);
// Getters and setters for player AOE loot settings
static bool getPlayerAoeLootEnabled(uint64 guid);
static void setPlayerAoeLootEnabled(uint64 guid, bool mode);
static bool hasPlayerAoeLootEnabled(uint64 guid);
private:
static std::map<uint64, bool> playerAoeLootEnabled;
};
void AddSC_AoeLoot()
{
new AOELootPlayer();
new AOELootServer();
new AoeLootCommandScript();
}
#endif //MODULE_AOELOOT_H
@@ -0,0 +1,25 @@
/*
* This file is part of the AzerothCore Project. See AUTHORS file for Copyright information
*
* This program is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License as published by the
* Free Software Foundation; either version 2 of the License, or (at your
* option) any later version.
*
* This program is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
* more details.
*
* You should have received a copy of the GNU General Public License along
* with this program. If not, see <http://www.gnu.org/licenses/>.
*/
// From SC
void AddSC_AoeLoot();
// Add all
void Addmod_aoe_lootScripts()
{
AddSC_AoeLoot();
}