diff options
| author | Shauren <shauren.trinity@gmail.com> | 2022-10-25 00:30:52 +0200 |
|---|---|---|
| committer | Shauren <shauren.trinity@gmail.com> | 2022-10-25 00:30:52 +0200 |
| commit | 010e6f7f49744b16e3ecececb7d9605f8b8db4d5 (patch) | |
| tree | 4e2101b0ffb51bbd3458f74b3dc75b3561833f5d /src/server/game/Entities | |
| parent | c672e27f27eda49230d87ec460539429251fefdc (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.cpp | 29 | ||||
| -rw-r--r-- | src/server/game/Entities/Item/ItemTemplate.h | 1 | ||||
| -rw-r--r-- | src/server/game/Entities/Player/Player.cpp | 53 | ||||
| -rw-r--r-- | src/server/game/Entities/Player/Player.h | 2 | ||||
| -rw-r--r-- | src/server/game/Entities/Unit/Unit.cpp | 56 |
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 { |
