aboutsummaryrefslogtreecommitdiff
path: root/src/server/game/Handlers/LootHandler.cpp
diff options
context:
space:
mode:
authorShauren <shauren.trinity@gmail.com>2022-09-14 20:49:38 +0200
committerShauren <shauren.trinity@gmail.com>2022-09-14 20:49:38 +0200
commitf19f32f2a49cf0eb235f1aa12106322bf9db2a15 (patch)
tree1c01c7b4f087777b9e57d039bf40e3987957dc35 /src/server/game/Handlers/LootHandler.cpp
parentd0a5d04c4c8f17ecd0ba6efaa114da051d303155 (diff)
Core/Loot: Store references to Loot objects directly in players loot view map instead of guids of world objects holding that loot
Diffstat (limited to 'src/server/game/Handlers/LootHandler.cpp')
-rw-r--r--src/server/game/Handlers/LootHandler.cpp185
1 files changed, 30 insertions, 155 deletions
diff --git a/src/server/game/Handlers/LootHandler.cpp b/src/server/game/Handlers/LootHandler.cpp
index 389e2e373dc..a22d40ff2b1 100644
--- a/src/server/game/Handlers/LootHandler.cpp
+++ b/src/server/game/Handlers/LootHandler.cpp
@@ -70,8 +70,14 @@ void WorldSession::HandleAutostoreLootItemOpcode(WorldPackets::Loot::LootItem& p
/// @todo Implement looting by LootObject guid
for (WorldPackets::Loot::LootRequest const& req : packet.Loot)
{
- Loot* loot = nullptr;
- ObjectGuid lguid = player->GetLootWorldObjectGUID(req.Object);
+ Loot* loot = Trinity::Containers::MapGetValuePtr(player->GetAELootView(), req.Object);
+ if (!loot)
+ {
+ player->SendLootRelease(ObjectGuid::Empty);
+ continue;
+ }
+
+ ObjectGuid lguid = loot->GetOwnerGUID();
if (lguid.IsGameObject())
{
@@ -83,33 +89,8 @@ void WorldSession::HandleAutostoreLootItemOpcode(WorldPackets::Loot::LootItem& p
player->SendLootRelease(lguid);
continue;
}
-
- loot = go->GetLootForPlayer(player);
- }
- else if (lguid.IsItem())
- {
- Item* pItem = player->GetItemByGuid(lguid);
-
- if (!pItem)
- {
- player->SendLootRelease(lguid);
- continue;
- }
-
- loot = pItem->GetLootForPlayer(player);
- }
- else if (lguid.IsCorpse())
- {
- Corpse* bones = ObjectAccessor::GetCorpse(*player, lguid);
- if (!bones)
- {
- player->SendLootRelease(lguid);
- continue;
- }
-
- loot = bones->GetLootForPlayer(player);
}
- else
+ else if (lguid.IsCreatureOrVehicle())
{
Creature* creature = GetPlayer()->GetMap()->GetCreature(lguid);
if (!creature)
@@ -123,26 +104,13 @@ void WorldSession::HandleAutostoreLootItemOpcode(WorldPackets::Loot::LootItem& p
player->SendLootError(req.Object, lguid, LOOT_ERROR_TOO_FAR);
continue;
}
-
- loot = creature->GetLootForPlayer(player);
- if (creature->IsAlive() != (loot && loot->loot_type == LOOT_PICKPOCKETING))
- {
- player->SendLootError(req.Object, lguid, LOOT_ERROR_DIDNT_KILL);
- continue;
- }
- }
-
- if (!loot)
- {
- player->SendLootRelease(lguid);
- continue;
}
player->StoreLootItem(lguid, req.LootListID - 1, loot, aeResultPtr);
// If player is removing the last LootItem, delete the empty container.
if (loot->isLooted() && lguid.IsItem())
- player->GetSession()->DoLootRelease(lguid);
+ player->GetSession()->DoLootRelease(loot);
}
if (aeResultPtr)
@@ -162,78 +130,11 @@ void WorldSession::HandleAutostoreLootItemOpcode(WorldPackets::Loot::LootItem& p
void WorldSession::HandleLootMoneyOpcode(WorldPackets::Loot::LootMoney& /*packet*/)
{
Player* player = GetPlayer();
- for (std::pair<ObjectGuid const, ObjectGuid> const& lootView : player->GetAELootView())
+ for (std::pair<ObjectGuid const, Loot*> const& lootView : player->GetAELootView())
{
- ObjectGuid guid = lootView.second;
- Loot* loot = nullptr;
- bool shareMoney = true;
-
- switch (guid.GetHigh())
- {
- case HighGuid::GameObject:
- {
- GameObject* go = GetPlayer()->GetMap()->GetGameObject(guid);
-
- // do not check distance for GO if player is the owner of it (ex. fishing bobber)
- if (go && ((go->GetOwnerGUID() == player->GetGUID() || go->IsWithinDistInMap(player))))
- loot = go->GetLootForPlayer(player);
-
- break;
- }
- case HighGuid::Corpse: // remove insignia ONLY in BG
- {
- Corpse* bones = ObjectAccessor::GetCorpse(*player, guid);
-
- if (bones && bones->IsWithinDistInMap(player, INTERACTION_DISTANCE))
- {
- loot = bones->GetLootForPlayer(player);
- shareMoney = false;
- }
-
- break;
- }
- case HighGuid::Item:
- {
- if (Item* item = player->GetItemByGuid(guid))
- {
- loot = item->GetLootForPlayer(player);
- shareMoney = false;
- }
- break;
- }
- case HighGuid::Creature:
- case HighGuid::Vehicle:
- {
- Creature* creature = player->GetMap()->GetCreature(guid);
- if (!creature)
- {
- player->SendLootError(lootView.first, guid, LOOT_ERROR_NO_LOOT);
- continue;
- }
-
- if (!creature->IsWithinDistInMap(player, AELootCreatureCheck::LootDistance))
- {
- player->SendLootError(lootView.first, guid, LOOT_ERROR_TOO_FAR);
- continue;
- }
-
- loot = creature->GetLootForPlayer(player);
- if (creature->IsAlive() != (loot && loot->loot_type == LOOT_PICKPOCKETING))
- {
- player->SendLootError(lootView.first, guid, LOOT_ERROR_DIDNT_KILL);
- continue;
- }
-
- if (loot && loot->loot_type != LOOT_CORPSE)
- shareMoney = false;
- break;
- }
- default:
- continue; // unlootable type
- }
-
- if (!loot)
- continue;
+ Loot* loot = lootView.second;
+ ObjectGuid guid = loot->GetOwnerGUID();
+ bool shareMoney = loot->loot_type == LOOT_CORPSE;
loot->NotifyMoneyRemoved(player->GetMap());
if (shareMoney && player->GetGroup()) //item, pickpocket and players can be looted only single player
@@ -289,7 +190,7 @@ void WorldSession::HandleLootMoneyOpcode(WorldPackets::Loot::LootMoney& /*packet
// Delete container if empty
if (loot->isLooted() && guid.IsItem())
- player->GetSession()->DoLootRelease(guid);
+ player->GetSession()->DoLootRelease(loot);
}
}
@@ -332,20 +233,20 @@ void WorldSession::HandleLootReleaseOpcode(WorldPackets::Loot::LootRelease& pack
{
// cheaters can modify lguid to prevent correct apply loot release code and re-loot
// use internal stored guid
- if (GetPlayer()->HasLootWorldObjectGUID(packet.Unit))
- DoLootRelease(packet.Unit);
+ if (Loot* loot = GetPlayer()->GetLootByWorldObjectGUID(packet.Unit))
+ DoLootRelease(loot);
}
-void WorldSession::DoLootRelease(ObjectGuid lguid)
+void WorldSession::DoLootRelease(Loot* loot)
{
+ ObjectGuid lguid = loot->GetOwnerGUID();
Player *player = GetPlayer();
- Loot *loot;
if (player->GetLootGUID() == lguid)
player->SetLootGUID(ObjectGuid::Empty);
player->SendLootRelease(lguid);
- player->RemoveAELootedWorldObject(lguid);
+ player->m_AELootView.erase(loot->GetGUID());
if (player->GetAELootView().empty())
player->RemoveUnitFlag(UNIT_FLAG_LOOTING);
@@ -361,8 +262,6 @@ void WorldSession::DoLootRelease(ObjectGuid lguid)
if (!go || ((go->GetOwnerGUID() != player->GetGUID() && go->GetGoType() != GAMEOBJECT_TYPE_FISHINGHOLE) && !go->IsWithinDistInMap(player)))
return;
- loot = go->GetLootForPlayer(player);
-
if (go->GetGoType() == GAMEOBJECT_TYPE_DOOR)
{
// locked doors are opened with spelleffect openlock, prevent remove its as looted
@@ -399,11 +298,9 @@ void WorldSession::DoLootRelease(ObjectGuid lguid)
if (!corpse || !corpse->IsWithinDistInMap(player, INTERACTION_DISTANCE))
return;
- loot = corpse->GetLootForPlayer(player);
-
- if (loot && loot->isLooted())
+ if (loot->isLooted())
{
- loot->clear();
+ corpse->m_loot = nullptr;
corpse->RemoveCorpseDynamicFlag(CORPSE_DYNFLAG_LOOTABLE);
}
}
@@ -415,10 +312,8 @@ void WorldSession::DoLootRelease(ObjectGuid lguid)
ItemTemplate const* proto = pItem->GetTemplate();
- loot = pItem->GetLootForPlayer(player);
-
// destroy only 5 items from stack in case prospecting and milling
- if (loot && (loot->loot_type == LOOT_PROSPECTING || loot->loot_type == LOOT_MILLING))
+ if (loot->loot_type == LOOT_PROSPECTING || loot->loot_type == LOOT_MILLING)
{
pItem->m_lootGenerated = false;
pItem->m_loot.reset();
@@ -434,7 +329,7 @@ void WorldSession::DoLootRelease(ObjectGuid lguid)
else
{
// Only delete item if no loot or money (unlooted loot is saved to db) or if it isn't an openable item
- if ((loot && loot->isLooted()) || !proto->HasFlag(ITEM_FLAG_HAS_LOOT))
+ if (loot->isLooted() || !proto->HasFlag(ITEM_FLAG_HAS_LOOT))
player->DestroyItem(pItem->GetBagSlot(), pItem->GetSlot(), true);
}
return; // item can be looted only single player
@@ -448,11 +343,10 @@ void WorldSession::DoLootRelease(ObjectGuid lguid)
if (!creature->IsWithinDistInMap(player, AELootCreatureCheck::LootDistance))
return;
- loot = creature->GetLootForPlayer(player);
if (creature->IsAlive() != (loot && loot->loot_type == LOOT_PICKPOCKETING))
return;
- if (!loot || loot->isLooted())
+ if (loot->isLooted())
{
creature->RemoveDynamicFlag(UNIT_DYNFLAG_LOOTABLE);
@@ -476,15 +370,14 @@ void WorldSession::DoLootRelease(ObjectGuid lguid)
}
//Player is not looking at loot list, he doesn't need to see updates on the loot list
- if (loot)
- loot->RemoveLooter(player->GetGUID());
+ loot->RemoveLooter(player->GetGUID());
}
void WorldSession::DoLootReleaseAll()
{
- std::unordered_map<ObjectGuid, ObjectGuid> lootView = _player->GetAELootView();
- for (std::pair<ObjectGuid const, ObjectGuid> const& lootPair : lootView)
- DoLootRelease(lootPair.second);
+ std::unordered_map<ObjectGuid, Loot*> lootView = _player->GetAELootView();
+ for (auto const& [lootGuid, loot] : lootView)
+ DoLootRelease(loot);
}
void WorldSession::HandleLootMasterGiveOpcode(WorldPackets::Loot::MasterLootItem& masterLootItem)
@@ -509,8 +402,7 @@ void WorldSession::HandleLootMasterGiveOpcode(WorldPackets::Loot::MasterLootItem
for (WorldPackets::Loot::LootRequest const& req : masterLootItem.Loot)
{
- Loot* loot = nullptr;
- ObjectGuid lootguid = _player->GetLootWorldObjectGUID(req.Object);
+ Loot* loot = Trinity::Containers::MapGetValuePtr(_player->GetAELootView(), req.Object);
if (!_player->IsInRaidWith(target) || !_player->IsInMap(target))
{
@@ -519,23 +411,6 @@ void WorldSession::HandleLootMasterGiveOpcode(WorldPackets::Loot::MasterLootItem
return;
}
- if (GetPlayer()->GetLootGUID().IsCreatureOrVehicle())
- {
- Creature* creature = GetPlayer()->GetMap()->GetCreature(lootguid);
- if (!creature)
- return;
-
- loot = creature->GetLootForPlayer(_player);
- }
- else if (GetPlayer()->GetLootGUID().IsGameObject())
- {
- GameObject* go = GetPlayer()->GetMap()->GetGameObject(lootguid);
- if (!go)
- return;
-
- loot = go->GetLootForPlayer(_player);
- }
-
if (!loot)
return;