mirror of
https://github.com/brighton-chi/mod-aoe-loot.git
synced 2026-01-13 00:58:34 +00:00
Update aoe_loot.cpp
This commit is contained in:
@@ -16,11 +16,18 @@
|
|||||||
#include "Map.h"
|
#include "Map.h"
|
||||||
#include <fmt/format.h>
|
#include <fmt/format.h>
|
||||||
#include "Corpse.h"
|
#include "Corpse.h"
|
||||||
|
#include "Group.h"
|
||||||
|
#include "ObjectMgr.h"
|
||||||
|
|
||||||
using namespace Acore::ChatCommands;
|
using namespace Acore::ChatCommands;
|
||||||
using namespace WorldPackets;
|
using namespace WorldPackets;
|
||||||
|
|
||||||
extern std::map<uint64, bool> playerAoeLootEnabled;
|
std::map<uint64, bool> playerAoeLootEnabled;
|
||||||
|
|
||||||
|
// Define the roll vote enum value - use the correct RollVote enum
|
||||||
|
#ifndef NOT_EMITED_YET
|
||||||
|
#define NOT_EMITED_YET RollVote(0)
|
||||||
|
#endif
|
||||||
|
|
||||||
bool AoeLootServer::CanPacketReceive(WorldSession* session, WorldPacket& packet)
|
bool AoeLootServer::CanPacketReceive(WorldSession* session, WorldPacket& packet)
|
||||||
{
|
{
|
||||||
@@ -46,6 +53,7 @@ bool AoeLootServer::CanPacketReceive(WorldSession* session, WorldPacket& packet)
|
|||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
ChatCommandTable AoeLootCommandScript::GetCommands() const
|
ChatCommandTable AoeLootCommandScript::GetCommands() const
|
||||||
{
|
{
|
||||||
static ChatCommandTable aoeLootSubCommandTable =
|
static ChatCommandTable aoeLootSubCommandTable =
|
||||||
@@ -57,7 +65,7 @@ ChatCommandTable AoeLootCommandScript::GetCommands() const
|
|||||||
|
|
||||||
static ChatCommandTable aoeLootCommandTable =
|
static ChatCommandTable aoeLootCommandTable =
|
||||||
{
|
{
|
||||||
{ "aoeloot", nullptr, SEC_PLAYER, Console::No, aoeLootSubCommandTable }
|
{ "aoeloot", aoeLootSubCommandTable }
|
||||||
};
|
};
|
||||||
|
|
||||||
return aoeLootCommandTable;
|
return aoeLootCommandTable;
|
||||||
@@ -246,13 +254,11 @@ bool AoeLootCommandScript::ProcessLootSlot(Player* player, ObjectGuid lguid, uin
|
|||||||
if (lguid.IsGameObject())
|
if (lguid.IsGameObject())
|
||||||
{
|
{
|
||||||
GameObject* go = player->GetMap()->GetGameObject(lguid);
|
GameObject* go = player->GetMap()->GetGameObject(lguid);
|
||||||
|
|
||||||
if (!go || ((go->GetOwnerGUID() != player->GetGUID() && go->GetGoType() != GAMEOBJECT_TYPE_FISHINGHOLE) && !go->IsWithinDistInMap(player, aoeDistance)))
|
if (!go || ((go->GetOwnerGUID() != player->GetGUID() && go->GetGoType() != GAMEOBJECT_TYPE_FISHINGHOLE) && !go->IsWithinDistInMap(player, aoeDistance)))
|
||||||
{
|
{
|
||||||
player->SendLootRelease(lguid);
|
player->SendLootRelease(lguid);
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
loot = &go->loot;
|
loot = &go->loot;
|
||||||
}
|
}
|
||||||
else if (lguid.IsItem())
|
else if (lguid.IsItem())
|
||||||
@@ -260,11 +266,9 @@ bool AoeLootCommandScript::ProcessLootSlot(Player* player, ObjectGuid lguid, uin
|
|||||||
Item* pItem = player->GetItemByGuid(lguid);
|
Item* pItem = player->GetItemByGuid(lguid);
|
||||||
if (!pItem)
|
if (!pItem)
|
||||||
{
|
{
|
||||||
|
|
||||||
player->SendLootRelease(lguid);
|
player->SendLootRelease(lguid);
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
loot = &pItem->loot;
|
loot = &pItem->loot;
|
||||||
}
|
}
|
||||||
else if (lguid.IsCorpse())
|
else if (lguid.IsCorpse())
|
||||||
@@ -280,34 +284,94 @@ bool AoeLootCommandScript::ProcessLootSlot(Player* player, ObjectGuid lguid, uin
|
|||||||
else
|
else
|
||||||
{
|
{
|
||||||
Creature* creature = player->GetMap()->GetCreature(lguid);
|
Creature* creature = player->GetMap()->GetCreature(lguid);
|
||||||
|
|
||||||
// Skip distance check for dead creatures (corpses)
|
// Skip distance check for dead creatures (corpses)
|
||||||
// Keep distance check for pickpocketing (live creatures)
|
// Keep distance check for pickpocketing (live creatures)
|
||||||
bool isPickpocketing = creature && creature->IsAlive() && player->IsClass(CLASS_ROGUE, CLASS_CONTEXT_ABILITY) && creature->loot.loot_type == LOOT_PICKPOCKETING;
|
bool isPickpocketing = creature && creature->IsAlive() && player->IsClass(CLASS_ROGUE, CLASS_CONTEXT_ABILITY) && creature->loot.loot_type == LOOT_PICKPOCKETING;
|
||||||
|
|
||||||
// Only check distance for pickpocketing, not for corpse looting
|
// Only check distance for pickpocketing, not for corpse looting
|
||||||
if (isPickpocketing && !creature->IsWithinDistInMap(player, INTERACTION_DISTANCE))
|
if (isPickpocketing && !creature->IsWithinDistInMap(player, INTERACTION_DISTANCE))
|
||||||
{
|
{
|
||||||
player->SendLootError(lguid, LOOT_ERROR_TOO_FAR);
|
player->SendLootError(lguid, LOOT_ERROR_TOO_FAR);
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
loot = &creature->loot;
|
loot = &creature->loot;
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
sScriptMgr->OnPlayerAfterCreatureLoot(player);
|
sScriptMgr->OnPlayerAfterCreatureLoot(player);
|
||||||
if (!loot)
|
if (!loot)
|
||||||
return false;
|
return false;
|
||||||
|
|
||||||
InventoryResult msg;
|
// --- Begin standard loot logic for solo/group ---
|
||||||
LootItem* lootItem = player->StoreLootItem(lootSlot, loot, msg);
|
Group* group = player->GetGroup();
|
||||||
|
LootItem* lootItem = nullptr;
|
||||||
|
InventoryResult msg = EQUIP_ERR_OK;
|
||||||
|
bool isGroupLoot = false;
|
||||||
|
bool isFFA = loot->items[lootSlot].freeforall;
|
||||||
|
bool isMasterLooter = false;
|
||||||
|
bool isRoundRobin = false;
|
||||||
|
bool isThreshold = false;
|
||||||
|
LootMethod lootMethod = GROUP_LOOT;
|
||||||
|
uint8 groupLootThreshold = 2; // Default: Uncommon
|
||||||
|
|
||||||
|
if (group)
|
||||||
|
{
|
||||||
|
lootMethod = group->GetLootMethod();
|
||||||
|
groupLootThreshold = group->GetLootThreshold();
|
||||||
|
isMasterLooter = (lootMethod == MASTER_LOOT);
|
||||||
|
isRoundRobin = (lootMethod == ROUND_ROBIN);
|
||||||
|
isGroupLoot = (lootMethod == GROUP_LOOT || lootMethod == NEED_BEFORE_GREED);
|
||||||
|
ItemTemplate const* itemTemplate = sObjectMgr->GetItemTemplate(loot->items[lootSlot].itemid);
|
||||||
|
isThreshold = (itemTemplate && itemTemplate->Quality >= groupLootThreshold);
|
||||||
|
}
|
||||||
|
|
||||||
|
// If in group and item meets group loot threshold, trigger group roll
|
||||||
|
if (group && isGroupLoot && isThreshold && !isFFA && !isMasterLooter)
|
||||||
|
{
|
||||||
|
// Use the existing game's SendLootStartRoll - it doesn't have distance checks
|
||||||
|
if (lootSlot < loot->items.size() && !loot->items[lootSlot].is_blocked)
|
||||||
|
{
|
||||||
|
// Create Roll object using the constructor: Roll(ObjectGuid _guid, LootItem const &li)
|
||||||
|
Roll roll(lguid, loot->items[lootSlot]);
|
||||||
|
roll.itemSlot = lootSlot;
|
||||||
|
roll.setLoot(loot);
|
||||||
|
|
||||||
|
// Initialize player votes for group members
|
||||||
|
for (GroupReference* itr = group->GetFirstMember(); itr != nullptr; itr = itr->next())
|
||||||
|
{
|
||||||
|
Player* member = itr->GetSource();
|
||||||
|
if (member && member->IsInWorld() && !member->isDead())
|
||||||
|
{
|
||||||
|
roll.playerVote[member->GetGUID()] = RollVote(0);
|
||||||
|
roll.totalPlayersRolling++;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Call SendLootStartRoll with 60 second countdown
|
||||||
|
group->SendLootStartRoll(60, player->GetMapId(), roll);
|
||||||
|
}
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
else if (group && isMasterLooter && !isFFA)
|
||||||
|
{
|
||||||
|
// Master looter: only master looter can loot
|
||||||
|
if (group->GetMasterLooterGuid() != player->GetGUID())
|
||||||
|
{
|
||||||
|
player->SendLootError(lguid, LOOT_ERROR_MASTER_OTHER);
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else if (group && isRoundRobin && loot->roundRobinPlayer && loot->roundRobinPlayer != player->GetGUID())
|
||||||
|
{
|
||||||
|
// Round robin: only designated player can loot
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
// If not blocked by group loot, proceed to loot the item
|
||||||
|
lootItem = player->StoreLootItem(lootSlot, loot, msg);
|
||||||
if (msg != EQUIP_ERR_OK && lguid.IsItem() && loot->loot_type != LOOT_CORPSE)
|
if (msg != EQUIP_ERR_OK && lguid.IsItem() && loot->loot_type != LOOT_CORPSE)
|
||||||
{
|
{
|
||||||
lootItem->is_looted = true;
|
lootItem->is_looted = true;
|
||||||
loot->NotifyItemRemoved(lootItem->itemIndex);
|
loot->NotifyItemRemoved(lootItem->itemIndex);
|
||||||
loot->unlootedCount--;
|
loot->unlootedCount--;
|
||||||
|
|
||||||
player->SendItemRetrievalMail(lootItem->itemid, lootItem->count);
|
player->SendItemRetrievalMail(lootItem->itemid, lootItem->count);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user