From c83f2b80727b29eff6347c0021b7571ad67e60da Mon Sep 17 00:00:00 2001 From: killerwife Date: Fri, 27 Dec 2024 13:15:42 +0100 Subject: [PATCH] Creature: Implement CreatureStaticFlags3::CAN_BE_MULTITAPPED --- src/game/Entities/Creature.cpp | 17 ++++++++++++----- src/game/Entities/Creature.h | 2 +- src/game/Entities/Unit.cpp | 9 +++++---- src/game/Loot/LootMgr.cpp | 13 ++++++++++--- 4 files changed, 28 insertions(+), 13 deletions(-) diff --git a/src/game/Entities/Creature.cpp b/src/game/Entities/Creature.cpp index 940a80a3e3..70432703cf 100644 --- a/src/game/Entities/Creature.cpp +++ b/src/game/Entities/Creature.cpp @@ -416,7 +416,7 @@ bool Creature::InitEntry(uint32 Entry, CreatureData const* data /*=nullptr*/, Ga if (GetSettings().HasFlag(CreatureStaticFlags::CAN_WIELD_LOOT)) // override from loot if any { - PrepareBodyLootState(); + PrepareBodyLootState(nullptr); if (m_loot != nullptr) { auto [mh, oh, ranged] = m_loot->GetQualifiedWeapons(); @@ -1095,7 +1095,7 @@ bool Creature::CanTrainAndResetTalentsOf(Player* pPlayer) const && pPlayer->getClass() == GetCreatureInfo()->TrainerClass; } -void Creature::PrepareBodyLootState() +void Creature::PrepareBodyLootState(Unit* killer) { // if can weild loot - already generated on spawn if (GetSettings().HasFlag(CreatureStaticFlags::CAN_WIELD_LOOT) && m_loot != nullptr && m_loot->GetLootType() == LOOT_CORPSE) @@ -1109,10 +1109,14 @@ void Creature::PrepareBodyLootState() SetLootStatus(CREATURE_LOOT_STATUS_LOOTED); else { - Player* killer = GetLootRecipient(); + Player* looter = nullptr; + if (GetSettings().HasFlag(CreatureStaticFlags3::CAN_BE_MULTITAPPED)) + looter = dynamic_cast(killer); + else + looter = GetLootRecipient(); - if (killer) - m_loot = new Loot(killer, this, LOOT_CORPSE); + if (looter || GetSettings().HasFlag(CreatureStaticFlags::CAN_WIELD_LOOT)) + m_loot = new Loot(looter, this, LOOT_CORPSE); } if (m_lootStatus == CREATURE_LOOT_STATUS_LOOTED && !HasFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_SKINNABLE)) @@ -1189,6 +1193,9 @@ void Creature::SetLootRecipient(Unit* unit) return; } + if (GetSettings().HasFlag(CreatureStaticFlags3::CAN_BE_MULTITAPPED)) + return; + Player* player = unit->GetBeneficiaryPlayer(); if (!player) // normal creature, no player involved return; diff --git a/src/game/Entities/Creature.h b/src/game/Entities/Creature.h index 3a09aa8b40..efaab76d50 100644 --- a/src/game/Entities/Creature.h +++ b/src/game/Entities/Creature.h @@ -723,7 +723,7 @@ class Creature : public Unit virtual void DeleteFromDB(); // overwrited in Pet static void DeleteFromDB(uint32 lowguid, CreatureData const* data); - void PrepareBodyLootState(); + void PrepareBodyLootState(Unit* killer); CreatureLootStatus GetLootStatus() const { return m_lootStatus; } virtual void InspectingLoot() override; void SetLootStatus(CreatureLootStatus status, bool forced = false); diff --git a/src/game/Entities/Unit.cpp b/src/game/Entities/Unit.cpp index b41f113948..8e3a703b42 100644 --- a/src/game/Entities/Unit.cpp +++ b/src/game/Entities/Unit.cpp @@ -1476,6 +1476,11 @@ void Unit::JustKilledCreature(Unit* killer, Creature* victim, Player* responsibl bool isPet = victim->IsPet(); + /* ******************************** Prepare loot if can ************************************ */ + // only lootable if it has loot or can drop gold, must be done before threat list is cleared + if (!isPet || !victim->GetSettings().HasFlag(CreatureStaticFlags::DESPAWN_INSTANTLY)) + victim->PrepareBodyLootState(killer); + /* ********************************* Set Death finally ************************************* */ DEBUG_FILTER_LOG(LOG_FILTER_DAMAGE, "SET JUST_DIED"); victim->SetDeathState(JUST_DIED); // if !spiritOfRedemtionTalentReady always true for unit @@ -1491,11 +1496,7 @@ void Unit::JustKilledCreature(Unit* killer, Creature* victim, Player* responsibl if (isPet) return; // Pets might have been unsummoned at this place, do not handle them further! - /* ******************************** Prepare loot if can ************************************ */ victim->DeleteThreatList(); - - // only lootable if it has loot or can drop gold - victim->PrepareBodyLootState(); } void Unit::PetOwnerKilledUnit(Unit* pVictim) diff --git a/src/game/Loot/LootMgr.cpp b/src/game/Loot/LootMgr.cpp index 9f2b073651..0f8147bd2f 100644 --- a/src/game/Loot/LootMgr.cpp +++ b/src/game/Loot/LootMgr.cpp @@ -1687,8 +1687,15 @@ Loot::Loot(Player* player, Creature* creature, LootType type) : { case LOOT_CORPSE: { - // setting loot right - SetGroupLootRight(player); + if (creature->GetSettings().HasFlag(CreatureStaticFlags3::CAN_BE_MULTITAPPED)) + { + for (auto& threatEntry : creature->getThreatManager().getThreatList()) + if (threatEntry->getTarget()->IsPlayer()) + m_ownerSet.insert(threatEntry->getTarget()->GetObjectGuid()); + } + else + // setting loot right + SetGroupLootRight(player); m_clientLootType = CLIENT_LOOT_CORPSE; if ((creatureInfo->LootId && FillLoot(creatureInfo->LootId, LootTemplates_Creature, player, false)) || creatureInfo->MaxLootGold > 0) @@ -2097,7 +2104,7 @@ InventoryResult Loot::SendItem(Player* target, LootItem* lootItem, bool sendErro std::tuple Loot::GetQualifiedWeapons() { - uint32 mh, oh, ranged; + uint32 mh = 0, oh = 0, ranged = 0; uint32 mhType = 0; for (auto const& itr : m_lootItems) {