aboutsummaryrefslogtreecommitdiff
path: root/src/server/game/Handlers/LootHandler.cpp
diff options
context:
space:
mode:
authorShauren <shauren.trinity@gmail.com>2022-09-01 20:07:58 +0200
committerShauren <shauren.trinity@gmail.com>2022-09-01 20:07:58 +0200
commit7957e2d380e08fa831765f610c0e29d2f3e11a04 (patch)
tree55632f7f94edb3096360c983abbdd448d8dc79d7 /src/server/game/Handlers/LootHandler.cpp
parent62e5b52d2b91832889f02edc7bbd83ad474923e3 (diff)
Core/Loot: Allocate Loot separately from objects
Diffstat (limited to 'src/server/game/Handlers/LootHandler.cpp')
-rw-r--r--src/server/game/Handlers/LootHandler.cpp106
1 files changed, 69 insertions, 37 deletions
diff --git a/src/server/game/Handlers/LootHandler.cpp b/src/server/game/Handlers/LootHandler.cpp
index 615f574d08e..2d161ab7694 100644
--- a/src/server/game/Handlers/LootHandler.cpp
+++ b/src/server/game/Handlers/LootHandler.cpp
@@ -78,13 +78,13 @@ void WorldSession::HandleAutostoreLootItemOpcode(WorldPackets::Loot::LootItem& p
GameObject* go = player->GetMap()->GetGameObject(lguid);
// not check distance for GO in case owned GO (fishing bobber case, for example) or Fishing hole GO
- if (!go || ((go->GetOwnerGUID() != _player->GetGUID() && go->GetGoType() != GAMEOBJECT_TYPE_FISHINGHOLE) && !go->IsWithinDistInMap(_player)))
+ if (!go || ((go->GetOwnerGUID() != player->GetGUID() && go->GetGoType() != GAMEOBJECT_TYPE_FISHINGHOLE) && !go->IsWithinDistInMap(player)))
{
player->SendLootRelease(lguid);
continue;
}
- loot = &go->loot;
+ loot = go->GetLootForPlayer(player);
}
else if (lguid.IsItem())
{
@@ -96,7 +96,7 @@ void WorldSession::HandleAutostoreLootItemOpcode(WorldPackets::Loot::LootItem& p
continue;
}
- loot = &pItem->loot;
+ loot = pItem->GetLootForPlayer(player);
}
else if (lguid.IsCorpse())
{
@@ -107,20 +107,35 @@ void WorldSession::HandleAutostoreLootItemOpcode(WorldPackets::Loot::LootItem& p
continue;
}
- loot = &bones->loot;
+ loot = bones->GetLootForPlayer(player);
}
else
{
Creature* creature = GetPlayer()->GetMap()->GetCreature(lguid);
+ if (!creature)
+ {
+ player->SendLootError(req.Object, lguid, LOOT_ERROR_NO_LOOT);
+ continue;
+ }
- bool lootAllowed = creature && creature->IsAlive() == (player->GetClass() == CLASS_ROGUE && creature->loot.loot_type == LOOT_PICKPOCKETING);
- if (!lootAllowed || !creature->IsWithinDistInMap(_player, AELootCreatureCheck::LootDistance))
+ if (!creature->IsWithinDistInMap(player, AELootCreatureCheck::LootDistance))
{
- player->SendLootError(req.Object, lguid, lootAllowed ? LOOT_ERROR_TOO_FAR : LOOT_ERROR_DIDNT_KILL);
+ player->SendLootError(req.Object, lguid, LOOT_ERROR_TOO_FAR);
continue;
}
- loot = &creature->loot;
+ 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);
@@ -161,7 +176,7 @@ void WorldSession::HandleLootMoneyOpcode(WorldPackets::Loot::LootMoney& /*packet
// 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->loot;
+ loot = go->GetLootForPlayer(player);
break;
}
@@ -171,7 +186,7 @@ void WorldSession::HandleLootMoneyOpcode(WorldPackets::Loot::LootMoney& /*packet
if (bones && bones->IsWithinDistInMap(player, INTERACTION_DISTANCE))
{
- loot = &bones->loot;
+ loot = bones->GetLootForPlayer(player);
shareMoney = false;
}
@@ -181,7 +196,7 @@ void WorldSession::HandleLootMoneyOpcode(WorldPackets::Loot::LootMoney& /*packet
{
if (Item* item = player->GetItemByGuid(guid))
{
- loot = &item->loot;
+ loot = item->GetLootForPlayer(player);
shareMoney = false;
}
break;
@@ -190,15 +205,27 @@ void WorldSession::HandleLootMoneyOpcode(WorldPackets::Loot::LootMoney& /*packet
case HighGuid::Vehicle:
{
Creature* creature = player->GetMap()->GetCreature(guid);
- bool lootAllowed = creature && creature->IsAlive() == (player->GetClass() == CLASS_ROGUE && creature->loot.loot_type == LOOT_PICKPOCKETING);
- if (lootAllowed && creature->IsWithinDistInMap(player, AELootCreatureCheck::LootDistance))
+ if (!creature)
{
- loot = &creature->loot;
- if (creature->IsAlive())
- shareMoney = false;
+ player->SendLootError(lootView.first, guid, LOOT_ERROR_NO_LOOT);
+ continue;
}
- else
- player->SendLootError(lootView.first, lootView.second, lootAllowed ? LOOT_ERROR_TOO_FAR : LOOT_ERROR_DIDNT_KILL);
+
+ 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:
@@ -330,10 +357,10 @@ void WorldSession::DoLootRelease(ObjectGuid lguid)
GameObject* go = GetPlayer()->GetMap()->GetGameObject(lguid);
// not check distance for GO in case owned GO (fishing bobber case, for example) or Fishing hole GO
- if (!go || ((go->GetOwnerGUID() != _player->GetGUID() && go->GetGoType() != GAMEOBJECT_TYPE_FISHINGHOLE) && !go->IsWithinDistInMap(_player)))
+ if (!go || ((go->GetOwnerGUID() != player->GetGUID() && go->GetGoType() != GAMEOBJECT_TYPE_FISHINGHOLE) && !go->IsWithinDistInMap(player)))
return;
- loot = &go->loot;
+ loot = go->GetLootForPlayer(player);
if (go->GetGoType() == GAMEOBJECT_TYPE_DOOR)
{
@@ -368,12 +395,12 @@ void WorldSession::DoLootRelease(ObjectGuid lguid)
else if (lguid.IsCorpse()) // ONLY remove insignia at BG
{
Corpse* corpse = ObjectAccessor::GetCorpse(*player, lguid);
- if (!corpse || !corpse->IsWithinDistInMap(_player, INTERACTION_DISTANCE))
+ if (!corpse || !corpse->IsWithinDistInMap(player, INTERACTION_DISTANCE))
return;
- loot = &corpse->loot;
+ loot = corpse->GetLootForPlayer(player);
- if (loot->isLooted())
+ if (loot && loot->isLooted())
{
loot->clear();
corpse->RemoveCorpseDynamicFlag(CORPSE_DYNFLAG_LOOTABLE);
@@ -387,11 +414,13 @@ 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 (pItem->loot.loot_type == LOOT_PROSPECTING || pItem->loot.loot_type == LOOT_MILLING)
+ if (loot && (loot->loot_type == LOOT_PROSPECTING || loot->loot_type == LOOT_MILLING))
{
pItem->m_lootGenerated = false;
- pItem->loot.clear();
+ pItem->m_loot.reset();
uint32 count = pItem->GetCount();
@@ -404,7 +433,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 (pItem->loot.isLooted() || !proto->HasFlag(ITEM_FLAG_HAS_LOOT))
+ if ((loot && loot->isLooted()) || !proto->HasFlag(ITEM_FLAG_HAS_LOOT))
player->DestroyItem(pItem->GetBagSlot(), pItem->GetSlot(), true);
}
return; // item can be looted only single player
@@ -412,21 +441,23 @@ void WorldSession::DoLootRelease(ObjectGuid lguid)
else
{
Creature* creature = GetPlayer()->GetMap()->GetCreature(lguid);
+ if (!creature)
+ return;
- bool lootAllowed = creature && creature->IsAlive() == (player->GetClass() == CLASS_ROGUE && creature->loot.loot_type == LOOT_PICKPOCKETING);
- if (!lootAllowed || !creature->IsWithinDistInMap(_player, AELootCreatureCheck::LootDistance))
+ if (!creature->IsWithinDistInMap(player, AELootCreatureCheck::LootDistance))
return;
- loot = &creature->loot;
- if (loot->isLooted())
+ loot = creature->GetLootForPlayer(player);
+ if (creature->IsAlive() != (loot && loot->loot_type == LOOT_PICKPOCKETING))
+ return;
+
+ if (!loot || loot->isLooted())
{
creature->RemoveDynamicFlag(UNIT_DYNFLAG_LOOTABLE);
// skip pickpocketing loot for speed, skinning timer reduction is no-op in fact
if (!creature->IsAlive())
creature->AllLootRemovedFromCorpse();
-
- loot->clear();
}
else
{
@@ -444,7 +475,8 @@ void WorldSession::DoLootRelease(ObjectGuid lguid)
}
//Player is not looking at loot list, he doesn't need to see updates on the loot list
- loot->RemoveLooter(player->GetGUID());
+ if (loot)
+ loot->RemoveLooter(player->GetGUID());
}
void WorldSession::DoLootReleaseAll()
@@ -492,15 +524,15 @@ void WorldSession::HandleLootMasterGiveOpcode(WorldPackets::Loot::MasterLootItem
if (!creature)
return;
- loot = &creature->loot;
+ loot = creature->GetLootForPlayer(_player);
}
else if (GetPlayer()->GetLootGUID().IsGameObject())
{
- GameObject* pGO = GetPlayer()->GetMap()->GetGameObject(lootguid);
- if (!pGO)
+ GameObject* go = GetPlayer()->GetMap()->GetGameObject(lootguid);
+ if (!go)
return;
- loot = &pGO->loot;
+ loot = go->GetLootForPlayer(_player);
}
if (!loot)