diff options
author | Shauren <shauren.trinity@gmail.com> | 2022-09-01 20:07:58 +0200 |
---|---|---|
committer | Shauren <shauren.trinity@gmail.com> | 2022-09-01 20:07:58 +0200 |
commit | 7957e2d380e08fa831765f610c0e29d2f3e11a04 (patch) | |
tree | 55632f7f94edb3096360c983abbdd448d8dc79d7 /src/server/game/Handlers/LootHandler.cpp | |
parent | 62e5b52d2b91832889f02edc7bbd83ad474923e3 (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.cpp | 106 |
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) |