aboutsummaryrefslogtreecommitdiff
path: root/src/server/game/Entities
diff options
context:
space:
mode:
authorShauren <shauren.trinity@gmail.com>2022-10-25 00:30:52 +0200
committerShauren <shauren.trinity@gmail.com>2022-10-25 00:30:52 +0200
commit010e6f7f49744b16e3ecececb7d9605f8b8db4d5 (patch)
tree4e2101b0ffb51bbd3458f74b3dc75b3561833f5d /src/server/game/Entities
parentc672e27f27eda49230d87ec460539429251fefdc (diff)
Core/Loot: Implemented dungeon encounter personal loot
Closes #20066
Diffstat (limited to 'src/server/game/Entities')
-rw-r--r--src/server/game/Entities/GameObject/GameObject.cpp29
-rw-r--r--src/server/game/Entities/Item/ItemTemplate.h1
-rw-r--r--src/server/game/Entities/Player/Player.cpp53
-rw-r--r--src/server/game/Entities/Player/Player.h2
-rw-r--r--src/server/game/Entities/Unit/Unit.cpp56
5 files changed, 71 insertions, 70 deletions
diff --git a/src/server/game/Entities/GameObject/GameObject.cpp b/src/server/game/Entities/GameObject/GameObject.cpp
index caa65afa59e..70e088a23ea 100644
--- a/src/server/game/Entities/GameObject/GameObject.cpp
+++ b/src/server/game/Entities/GameObject/GameObject.cpp
@@ -2268,15 +2268,32 @@ void GameObject::Use(Unit* user)
{
if (info->chest.chestPersonalLoot)
{
- Loot* loot = new Loot(GetMap(), GetGUID(), LOOT_CHEST, nullptr);
- m_personalLoot[player->GetGUID()].reset(loot);
+ GameObjectTemplateAddon const* addon = GetTemplateAddon();
+ if (info->chest.DungeonEncounter)
+ {
+ std::vector<Player*> tappers;
+ for (ObjectGuid tapperGuid : GetTapList())
+ if (Player* tapper = ObjectAccessor::GetPlayer(*this, tapperGuid))
+ tappers.push_back(tapper);
- loot->SetDungeonEncounterId(info->chest.DungeonEncounter);
- loot->FillLoot(info->chest.chestPersonalLoot, LootTemplates_Gameobject, player, true, false, GetLootMode(), GetMap()->GetDifficultyLootItemContext());
+ if (tappers.empty())
+ tappers.push_back(player);
- if (GetLootMode() > 0)
- if (GameObjectTemplateAddon const* addon = GetTemplateAddon())
+ m_personalLoot = GenerateDungeonEncounterPersonalLoot(info->chest.DungeonEncounter, info->chest.chestPersonalLoot,
+ LootTemplates_Gameobject, LOOT_CHEST, this, addon ? addon->Mingold : 0, addon ? addon->Maxgold : 0,
+ GetLootMode(), GetMap()->GetDifficultyLootItemContext(), tappers);
+ }
+ else
+ {
+ Loot* loot = new Loot(GetMap(), GetGUID(), LOOT_CHEST, nullptr);
+ m_personalLoot[player->GetGUID()].reset(loot);
+
+ loot->SetDungeonEncounterId(info->chest.DungeonEncounter);
+ loot->FillLoot(info->chest.chestPersonalLoot, LootTemplates_Gameobject, player, true, false, GetLootMode(), GetMap()->GetDifficultyLootItemContext());
+
+ if (GetLootMode() > 0 && addon)
loot->generateMoneyLoot(addon->Mingold, addon->Maxgold);
+ }
}
}
diff --git a/src/server/game/Entities/Item/ItemTemplate.h b/src/server/game/Entities/Item/ItemTemplate.h
index 992c736569f..d2fa2029fa8 100644
--- a/src/server/game/Entities/Item/ItemTemplate.h
+++ b/src/server/game/Entities/Item/ItemTemplate.h
@@ -821,6 +821,7 @@ struct TC_GAME_API ItemTemplate
bool HasSignature() const;
bool IsWeapon() const { return GetClass() == ITEM_CLASS_WEAPON; }
+ bool IsArmor() const { return GetClass() == ITEM_CLASS_ARMOR; }
bool IsRangedWeapon() const
{
diff --git a/src/server/game/Entities/Player/Player.cpp b/src/server/game/Entities/Player/Player.cpp
index 7ece702802f..3b46774769e 100644
--- a/src/server/game/Entities/Player/Player.cpp
+++ b/src/server/game/Entities/Player/Player.cpp
@@ -11080,14 +11080,17 @@ InventoryResult Player::CanUseItem(ItemTemplate const* proto, bool skipRequiredL
return EQUIP_ERR_OK;
}
-InventoryResult Player::CanRollForItemInLFG(ItemTemplate const* proto, Map const* map) const
+InventoryResult Player::CanRollNeedForItem(ItemTemplate const* proto, Map const* map, bool restrictOnlyLfg) const
{
- if (!GetGroup() || !GetGroup()->isLFGGroup())
- return EQUIP_ERR_OK; // not in LFG group
+ if (restrictOnlyLfg)
+ {
+ if (!GetGroup() || !GetGroup()->isLFGGroup())
+ return EQUIP_ERR_OK; // not in LFG group
- // check if looted object is inside the lfg dungeon
- if (!sLFGMgr->inLfgDungeonMap(GetGroup()->GetGUID(), map->GetId(), map->GetDifficultyID()))
- return EQUIP_ERR_OK;
+ // check if looted object is inside the lfg dungeon
+ if (!sLFGMgr->inLfgDungeonMap(GetGroup()->GetGUID(), map->GetId(), map->GetDifficultyID()))
+ return EQUIP_ERR_OK;
+ }
if (!proto)
return EQUIP_ERR_ITEM_NOT_FOUND;
@@ -11107,41 +11110,14 @@ InventoryResult Player::CanRollForItemInLFG(ItemTemplate const* proto, Map const
return EQUIP_ERR_CANT_EQUIP_SKILL;
}
- uint8 _class = GetClass();
-
if (proto->GetClass() == ITEM_CLASS_WEAPON && GetSkillValue(proto->GetSkill()) == 0)
return EQUIP_ERR_PROFICIENCY_NEEDED;
- if (proto->GetClass() == ITEM_CLASS_ARMOR && proto->GetSubClass() > ITEM_SUBCLASS_ARMOR_MISCELLANEOUS && proto->GetSubClass() < ITEM_SUBCLASS_ARMOR_COSMETIC && proto->GetInventoryType() != INVTYPE_CLOAK)
+ if (proto->GetClass() == ITEM_CLASS_ARMOR && proto->GetInventoryType() != INVTYPE_CLOAK)
{
- if (_class == CLASS_WARRIOR || _class == CLASS_PALADIN || _class == CLASS_DEATH_KNIGHT)
- {
- if (GetLevel() < 40)
- {
- if (proto->GetSubClass() != ITEM_SUBCLASS_ARMOR_MAIL)
- return EQUIP_ERR_CLIENT_LOCKED_OUT;
- }
- else if (proto->GetSubClass() != ITEM_SUBCLASS_ARMOR_PLATE)
- return EQUIP_ERR_CLIENT_LOCKED_OUT;
- }
- else if (_class == CLASS_HUNTER || _class == CLASS_SHAMAN)
- {
- if (GetLevel() < 40)
- {
- if (proto->GetSubClass() != ITEM_SUBCLASS_ARMOR_LEATHER)
- return EQUIP_ERR_CLIENT_LOCKED_OUT;
- }
- else if (proto->GetSubClass() != ITEM_SUBCLASS_ARMOR_MAIL)
- return EQUIP_ERR_CLIENT_LOCKED_OUT;
- }
-
- if (_class == CLASS_ROGUE || _class == CLASS_DRUID)
- if (proto->GetSubClass() != ITEM_SUBCLASS_ARMOR_LEATHER)
- return EQUIP_ERR_CLIENT_LOCKED_OUT;
-
- if (_class == CLASS_MAGE || _class == CLASS_PRIEST || _class == CLASS_WARLOCK)
- if (proto->GetSubClass() != ITEM_SUBCLASS_ARMOR_CLOTH)
- return EQUIP_ERR_CLIENT_LOCKED_OUT;
+ ChrClassesEntry const* classesEntry = sChrClassesStore.AssertEntry(GetClass());
+ if (!(classesEntry->ArmorTypeMask & 1 << proto->GetSubClass()))
+ return EQUIP_ERR_CLIENT_LOCKED_OUT;
}
return EQUIP_ERR_OK;
@@ -17880,8 +17856,7 @@ bool Player::isAllowedToLoot(const Creature* creature) const
switch (loot->GetLootMethod())
{
- case PERSONAL_LOOT: /// @todo implement personal loot (http://wow.gamepedia.com/Loot#Personal_Loot)
- return false;
+ case PERSONAL_LOOT:
case FREE_FOR_ALL:
return true;
case ROUND_ROBIN:
diff --git a/src/server/game/Entities/Player/Player.h b/src/server/game/Entities/Player/Player.h
index 7cf62d43c6e..c155ccd6d01 100644
--- a/src/server/game/Entities/Player/Player.h
+++ b/src/server/game/Entities/Player/Player.h
@@ -1355,7 +1355,7 @@ class TC_GAME_API Player : public Unit, public GridObject<Player>
InventoryResult CanUseItem(Item* pItem, bool not_loading = true) const;
bool HasItemTotemCategory(uint32 TotemCategory) const;
InventoryResult CanUseItem(ItemTemplate const* pItem, bool skipRequiredLevelCheck = false) const;
- InventoryResult CanRollForItemInLFG(ItemTemplate const* item, Map const* map) const;
+ InventoryResult CanRollNeedForItem(ItemTemplate const* item, Map const* map, bool restrictOnlyLfg) const;
Item* StoreNewItem(ItemPosCountVec const& pos, uint32 itemId, bool update, ItemRandomBonusListId randomBonusListId = 0, GuidSet const& allowedLooters = GuidSet(), ItemContext context = ItemContext::NONE, std::vector<int32> const& bonusListIDs = std::vector<int32>(), bool addToCollection = true);
Item* StoreItem(ItemPosCountVec const& pos, Item* pItem, bool update);
Item* EquipNewItem(uint16 pos, uint32 item, ItemContext context, bool update);
diff --git a/src/server/game/Entities/Unit/Unit.cpp b/src/server/game/Entities/Unit/Unit.cpp
index db3caadc21c..a5a605fc19e 100644
--- a/src/server/game/Entities/Unit/Unit.cpp
+++ b/src/server/game/Entities/Unit/Unit.cpp
@@ -10583,9 +10583,9 @@ void Unit::SetMeleeAnimKitId(uint16 animKitId)
Creature* creature = victim->ToCreature();
- bool isRewardAllowed = true;
+ bool isRewardAllowed = attacker != victim;
if (creature)
- isRewardAllowed = !creature->GetTapList().empty();
+ isRewardAllowed = isRewardAllowed && !creature->GetTapList().empty();
std::vector<Player*> tappers;
if (isRewardAllowed && creature)
@@ -10601,11 +10601,6 @@ void Unit::SetMeleeAnimKitId(uint16 animKitId)
// call kill spell proc event (before real die and combat stop to triggering auras removed at death/combat stop)
if (isRewardAllowed)
{
- WorldPackets::Party::PartyKillLog partyKillLog;
- partyKillLog.Player = player->GetGUID();
- partyKillLog.Victim = victim->GetGUID();
- partyKillLog.Write();
-
std::unordered_set<Group*> groups;
for (Player* tapper : tappers)
{
@@ -10613,6 +10608,11 @@ void Unit::SetMeleeAnimKitId(uint16 animKitId)
{
if (groups.insert(tapperGroup).second)
{
+ WorldPackets::Party::PartyKillLog partyKillLog;
+ partyKillLog.Player = player && tapperGroup->IsMember(player->GetGUID()) ? player->GetGUID() : tapper->GetGUID();
+ partyKillLog.Victim = victim->GetGUID();
+ partyKillLog.Write();
+
tapperGroup->BroadcastPacket(partyKillLog.GetRawPacket(), tapperGroup->GetMemberGroup(tapper->GetGUID()) != 0);
if (creature)
@@ -10620,7 +10620,12 @@ void Unit::SetMeleeAnimKitId(uint16 animKitId)
}
}
else
- tapper->SendDirectMessage(partyKillLog.GetRawPacket());
+ {
+ WorldPackets::Party::PartyKillLog partyKillLog;
+ partyKillLog.Player = tapper->GetGUID();
+ partyKillLog.Victim = victim->GetGUID();
+ tapper->SendDirectMessage(partyKillLog.Write());
+ }
}
// Generate loot before updating looter
@@ -10635,29 +10640,32 @@ void Unit::SetMeleeAnimKitId(uint16 animKitId)
Group* group = !groups.empty() ? *groups.begin() : nullptr;
Player* looter = group ? ASSERT_NOTNULL(ObjectAccessor::GetPlayer(*creature, group->GetLooterGuid())) : tappers[0];
- Loot* loot = new Loot(creature->GetMap(), creature->GetGUID(), LOOT_CORPSE, dungeonEncounter ? group : nullptr);
-
if (dungeonEncounter)
- loot->SetDungeonEncounterId(dungeonEncounter->ID);
+ {
+ creature->m_personalLoot = GenerateDungeonEncounterPersonalLoot(dungeonEncounter->ID, creature->GetCreatureTemplate()->lootid,
+ LootTemplates_Creature, LOOT_CORPSE, creature, creature->GetCreatureTemplate()->mingold, creature->GetCreatureTemplate()->maxgold,
+ creature->GetLootMode(), creature->GetMap()->GetDifficultyLootItemContext(), tappers);
+ }
+ else
+ {
+ Loot* loot = new Loot(creature->GetMap(), creature->GetGUID(), LOOT_CORPSE, dungeonEncounter ? group : nullptr);
- if (uint32 lootid = creature->GetCreatureTemplate()->lootid)
- loot->FillLoot(lootid, LootTemplates_Creature, looter, dungeonEncounter != nullptr, false, creature->GetLootMode(), creature->GetMap()->GetDifficultyLootItemContext());
+ if (uint32 lootid = creature->GetCreatureTemplate()->lootid)
+ loot->FillLoot(lootid, LootTemplates_Creature, looter, dungeonEncounter != nullptr, false, creature->GetLootMode(), creature->GetMap()->GetDifficultyLootItemContext());
- if (creature->GetLootMode() > 0)
- loot->generateMoneyLoot(creature->GetCreatureTemplate()->mingold, creature->GetCreatureTemplate()->maxgold);
+ if (creature->GetLootMode() > 0)
+ loot->generateMoneyLoot(creature->GetCreatureTemplate()->mingold, creature->GetCreatureTemplate()->maxgold);
- if (group)
- loot->NotifyLootList(creature->GetMap());
+ if (group)
+ loot->NotifyLootList(creature->GetMap());
- if (dungeonEncounter || groups.empty())
- creature->m_loot.reset(loot); // TODO: personal boss loot
- else
creature->m_personalLoot[looter->GetGUID()].reset(loot); // trash mob loot is personal, generated with round robin rules
- // Update round robin looter only if the creature had loot
- if (!loot->isLooted())
- for (Group* tapperGroup : groups)
- tapperGroup->UpdateLooterGuid(creature);
+ // Update round robin looter only if the creature had loot
+ if (!loot->isLooted())
+ for (Group* tapperGroup : groups)
+ tapperGroup->UpdateLooterGuid(creature);
+ }
}
else
{