From 133334a902b705dae6f7e92bb1009b84cf1c51d2 Mon Sep 17 00:00:00 2001 From: Shauren Date: Mon, 17 Oct 2022 23:11:46 +0200 Subject: Core/Loot: Implemented personal loot and tag sharing for non-boss loot --- src/server/game/Entities/GameObject/GameObject.cpp | 95 +++++----------------- src/server/game/Entities/GameObject/GameObject.h | 11 +-- 2 files changed, 26 insertions(+), 80 deletions(-) (limited to 'src/server/game/Entities/GameObject') diff --git a/src/server/game/Entities/GameObject/GameObject.cpp b/src/server/game/Entities/GameObject/GameObject.cpp index ed2dc526fba..4dffcf2652e 100644 --- a/src/server/game/Entities/GameObject/GameObject.cpp +++ b/src/server/game/Entities/GameObject/GameObject.cpp @@ -34,7 +34,6 @@ #include "GossipDef.h" #include "GridNotifiersImpl.h" #include "Group.h" -#include "GroupMgr.h" #include "Item.h" #include "Log.h" #include "Loot.h" @@ -1419,45 +1418,45 @@ void GameObject::SendGameObjectDespawn() Loot* GameObject::GetFishLoot(Player* lootOwner) { - uint32 zone, subzone; uint32 defaultzone = 1; - GetZoneAndAreaId(zone, subzone); Loot* fishLoot = new Loot(GetMap(), GetGUID(), LOOT_FISHING, nullptr); - // if subzone loot exist use it - fishLoot->FillLoot(subzone, LootTemplates_Fishing, lootOwner, true, true); - if (fishLoot->empty()) //use this becase if zone or subzone has set LOOT_MODE_JUNK_FISH,Even if no normal drop, fishloot->FillLoot return true. it wrong. + uint32 areaId = GetAreaId(); + while (AreaTableEntry const* areaEntry = sAreaTableStore.LookupEntry(areaId)) { - //subzone no result,use zone loot - fishLoot->FillLoot(zone, LootTemplates_Fishing, lootOwner, true, true); - //use zone 1 as default, somewhere fishing got nothing,becase subzone and zone not set, like Off the coast of Storm Peaks. - if (fishLoot->empty()) - fishLoot->FillLoot(defaultzone, LootTemplates_Fishing, lootOwner, true, true); + fishLoot->FillLoot(areaId, LootTemplates_Fishing, lootOwner, true, true); + if (!fishLoot->isLooted()) + break; + + areaId = areaEntry->ParentAreaID; } + if (fishLoot->isLooted()) + fishLoot->FillLoot(defaultzone, LootTemplates_Fishing, lootOwner, true, true); + return fishLoot; } Loot* GameObject::GetFishLootJunk(Player* lootOwner) { - uint32 zone, subzone; uint32 defaultzone = 1; - GetZoneAndAreaId(zone, subzone); Loot* fishLoot = new Loot(GetMap(), GetGUID(), LOOT_FISHING_JUNK, nullptr); - // if subzone loot exist use it - fishLoot->FillLoot(subzone, LootTemplates_Fishing, lootOwner, true, true, LOOT_MODE_JUNK_FISH); - if (fishLoot->empty()) //use this becase if zone or subzone has normal mask drop, then fishloot->FillLoot return true. + uint32 areaId = GetAreaId(); + while (AreaTableEntry const* areaEntry = sAreaTableStore.LookupEntry(areaId)) { - //use zone loot - fishLoot->FillLoot(zone, LootTemplates_Fishing, lootOwner, true, true, LOOT_MODE_JUNK_FISH); - if (fishLoot->empty()) - //use zone 1 as default - fishLoot->FillLoot(defaultzone, LootTemplates_Fishing, lootOwner, true, true, LOOT_MODE_JUNK_FISH); + fishLoot->FillLoot(areaId, LootTemplates_Fishing, lootOwner, true, true, LOOT_MODE_JUNK_FISH); + if (!fishLoot->isLooted()) + break; + + areaId = areaEntry->ParentAreaID; } + if (fishLoot->isLooted()) + fishLoot->FillLoot(defaultzone, LootTemplates_Fishing, lootOwner, true, true, LOOT_MODE_JUNK_FISH); + return fishLoot; } @@ -3279,49 +3278,6 @@ void GameObject::UpdateModel() GetMap()->InsertGameObjectModel(*m_model); } -Player* GameObject::GetLootRecipient() const -{ - if (!m_lootRecipient) - return nullptr; - return ObjectAccessor::FindConnectedPlayer(m_lootRecipient); -} - -Group* GameObject::GetLootRecipientGroup() const -{ - if (!m_lootRecipientGroup) - return nullptr; - return sGroupMgr->GetGroupByGUID(m_lootRecipientGroup); -} - -void GameObject::SetLootRecipient(Unit* unit, Group* group) -{ - // set the player whose group should receive the right - // to loot the creature after it dies - // should be set to nullptr after the loot disappears - - if (!unit) - { - m_lootRecipient.Clear(); - m_lootRecipientGroup = group ? group->GetGUID() : ObjectGuid::Empty; - return; - } - - if (unit->GetTypeId() != TYPEID_PLAYER && !unit->IsVehicle()) - return; - - Player* player = unit->GetCharmerOrOwnerPlayerOrPlayerItself(); - if (!player) // normal creature, no player involved - return; - - m_lootRecipient = player->GetGUID(); - - // either get the group from the passed parameter or from unit's one - if (group) - m_lootRecipientGroup = group->GetGUID(); - else if (Group* unitGroup = player->GetGroup()) - m_lootRecipientGroup = unitGroup->GetGUID(); -} - bool GameObject::IsLootAllowedFor(Player const* player) const { if (Loot const* loot = GetLootForPlayer(player)) // check only if loot was already generated @@ -3332,15 +3288,8 @@ bool GameObject::IsLootAllowedFor(Player const* player) const return false; } - if (!m_lootRecipient && !m_lootRecipientGroup) - return true; - - if (player->GetGUID() == m_lootRecipient) - return true; - - Group const* playerGroup = player->GetGroup(); - if (!playerGroup || playerGroup != GetLootRecipientGroup()) // if we dont have a group we arent the recipient - return false; // if go doesnt have group bound it means it was solo killed by someone else + if (HasLootRecipient()) + return m_tapList.find(player->GetGUID()) != m_tapList.end(); return true; } diff --git a/src/server/game/Entities/GameObject/GameObject.h b/src/server/game/Entities/GameObject/GameObject.h index 55d86f1e5f8..7d7d0563532 100644 --- a/src/server/game/Entities/GameObject/GameObject.h +++ b/src/server/game/Entities/GameObject/GameObject.h @@ -27,7 +27,6 @@ class GameObject; class GameObjectAI; class GameObjectModel; -class Group; class OPvPCapturePoint; class Transport; class TransportBase; @@ -281,11 +280,10 @@ class TC_GAME_API GameObject : public WorldObject, public GridObject std::unique_ptr m_loot; std::unordered_map> m_personalLoot; - Player* GetLootRecipient() const; - Group* GetLootRecipientGroup() const; - void SetLootRecipient(Unit* unit, Group* group = nullptr); + GuidUnorderedSet const& GetTapList() const { return m_tapList; } + void SetTapList(GuidUnorderedSet tapList) { m_tapList = std::move(tapList); } bool IsLootAllowedFor(Player const* player) const; - bool HasLootRecipient() const { return !m_lootRecipient.IsEmpty() || !m_lootRecipientGroup.IsEmpty(); } + bool HasLootRecipient() const { return !m_tapList.empty(); } Loot* GetLootForPlayer(Player const* /*player*/) const override; GameObject* GetLinkedTrap(); @@ -427,8 +425,7 @@ class TC_GAME_API GameObject : public WorldObject, public GridObject QuaternionData m_localRotation; Position m_stationaryPosition; - ObjectGuid m_lootRecipient; - ObjectGuid m_lootRecipientGroup; + GuidUnorderedSet m_tapList; uint16 m_LootMode; // bitmask, default LOOT_MODE_DEFAULT, determines what loot will be lootable ObjectGuid m_linkedTrap; -- cgit v1.2.3