From a70537a6b42aba2830d737c8be81806254d83c01 Mon Sep 17 00:00:00 2001 From: killerwife Date: Thu, 26 Dec 2024 21:29:27 +0100 Subject: [PATCH] Creature: Implement CreatureStaticFlags::CAN_WIELD_LOOT --- src/game/Entities/Creature.cpp | 35 +++++++++++++++++++++++---- src/game/Loot/LootMgr.cpp | 44 +++++++++++++++++++++++++++++++++- src/game/Loot/LootMgr.h | 2 ++ 3 files changed, 76 insertions(+), 5 deletions(-) diff --git a/src/game/Entities/Creature.cpp b/src/game/Entities/Creature.cpp index 538212d66d5..306e0094cc9 100644 --- a/src/game/Entities/Creature.cpp +++ b/src/game/Entities/Creature.cpp @@ -409,10 +409,33 @@ bool Creature::InitEntry(uint32 Entry, CreatureData const* data /*=nullptr*/, Ga } else if (!data || (data->spawnTemplate->equipmentId == -1)) { - if (cinfo->EquipmentTemplateId == 0) - LoadEquipment(normalInfo->EquipmentTemplateId, true); // use default from normal template if diff does not have any - else - LoadEquipment(cinfo->EquipmentTemplateId); // else use from diff template + bool usingLoot = false; + if (GetSettings().HasFlag(CreatureStaticFlags::CAN_WIELD_LOOT)) + { + PrepareBodyLootState(); + if (m_loot != nullptr) + { + auto [mh, oh, ranged] = m_loot->GetQualifiedWeapons(); + if (mh != 0 || oh != 0 || ranged != 0) + usingLoot = true; + + if (mh != 0) + SetVirtualItem(VIRTUAL_ITEM_SLOT_0, mh); + + if (oh != 0) + SetVirtualItem(VIRTUAL_ITEM_SLOT_0, oh); + + if (ranged != 0) + SetVirtualItem(VIRTUAL_ITEM_SLOT_0, ranged); + } + } + if (!usingLoot) + { + if (cinfo->EquipmentTemplateId == 0) + LoadEquipment(normalInfo->EquipmentTemplateId, true); // use default from normal template if diff does not have any + else + LoadEquipment(cinfo->EquipmentTemplateId); // else use from diff template + } } else if (data) { @@ -1079,6 +1102,10 @@ bool Creature::CanTrainAndResetTalentsOf(Player* pPlayer) const void Creature::PrepareBodyLootState() { + // if can weild loot - already generated on spawn + if (GetSettings().HasFlag(CreatureStaticFlags::CAN_WIELD_LOOT) && m_loot != nullptr && m_loot->GetLootType() == LOOT_CORPSE) + return; + // loot may already exist (pickpocket case) delete m_loot; m_loot = nullptr; diff --git a/src/game/Loot/LootMgr.cpp b/src/game/Loot/LootMgr.cpp index ae9b452be46..9f2b0736511 100644 --- a/src/game/Loot/LootMgr.cpp +++ b/src/game/Loot/LootMgr.cpp @@ -1782,7 +1782,7 @@ Loot::Loot(Player* player, GameObject* gameObject, LootType type, bool lootSnaps m_guidTarget = gameObject->GetObjectGuid(); // not check distance for GO in case owned GO (fishing bobber case, for example) - // And permit out of range GO with no owner in case fishing hole + // And permit out of ranged GO with no owner in case fishing hole if (!lootSnapshot) // ignores distance { if ((type != LOOT_FISHINGHOLE && @@ -2095,6 +2095,48 @@ InventoryResult Loot::SendItem(Player* target, LootItem* lootItem, bool sendErro return msg; } +std::tuple Loot::GetQualifiedWeapons() +{ + uint32 mh, oh, ranged; + uint32 mhType = 0; + for (auto const& itr : m_lootItems) + { + if (ItemPrototype const* pItem = sObjectMgr.GetItemPrototype(itr->itemId)) + { + if (mh == 0) + { + if (pItem->InventoryType == INVTYPE_WEAPON || + pItem->InventoryType == INVTYPE_WEAPONMAINHAND || + pItem->InventoryType == INVTYPE_2HWEAPON && oh == 0) + { + mh = itr->itemId; + mhType = pItem->InventoryType; + continue; + } + } + + if (oh == 0 && mhType != INVTYPE_2HWEAPON) + { + if (pItem->InventoryType == INVTYPE_WEAPON || + pItem->InventoryType == INVTYPE_WEAPONOFFHAND || + pItem->InventoryType == INVTYPE_SHIELD || + pItem->InventoryType == INVTYPE_HOLDABLE) + { + oh = itr->itemId; + continue; + } + } + + if (ranged == 0 && pItem->IsRangedWeapon()) + { + ranged = itr->itemId; + continue; + } + } + } + return { mh, oh, ranged }; +} + bool Loot::AutoStore(Player* player, bool broadcast /*= false*/, uint32 bag /*= NULL_BAG*/, uint32 slot /*= NULL_SLOT*/) { bool result = true; diff --git a/src/game/Loot/LootMgr.h b/src/game/Loot/LootMgr.h index ffaded18ea1..aabe9ebed36 100644 --- a/src/game/Loot/LootMgr.h +++ b/src/game/Loot/LootMgr.h @@ -394,6 +394,8 @@ class Loot GuidSet const& GetOwnerSet() const { return m_ownerSet; } TimePoint const& GetCreateTime() const { return m_createTime; } + std::tuple GetQualifiedWeapons(); + private: Loot(): m_lootTarget(nullptr), m_itemTarget(nullptr), m_gold(0), m_maxSlot(0), m_lootType(), m_clientLootType(), m_lootMethod(), m_threshold(), m_maxEnchantSkill(0), m_haveItemOverThreshold(false),