From 289f140ab1853920d6411e45c6d1281d6603fcab Mon Sep 17 00:00:00 2001 From: UltraNix <80540499+UltraNix@users.noreply.github.com> Date: Fri, 18 Jun 2021 17:07:24 +0200 Subject: [PATCH] fix(Core/Loot): Fixed loading conditioned item loot. (#6337) - Fixes #6326 --- .../rev_1623572783362357500.sql | 6 +++++ .../Implementation/CharacterDatabase.cpp | 4 ++-- src/server/game/Loot/LootItemStorage.cpp | 18 +++++++++++---- src/server/game/Loot/LootItemStorage.h | 6 +++-- src/server/game/Loot/LootMgr.cpp | 23 +++++++++++++++---- src/server/game/Loot/LootMgr.h | 2 +- 6 files changed, 45 insertions(+), 14 deletions(-) create mode 100644 data/sql/updates/pending_db_characters/rev_1623572783362357500.sql diff --git a/data/sql/updates/pending_db_characters/rev_1623572783362357500.sql b/data/sql/updates/pending_db_characters/rev_1623572783362357500.sql new file mode 100644 index 000000000..657892b33 --- /dev/null +++ b/data/sql/updates/pending_db_characters/rev_1623572783362357500.sql @@ -0,0 +1,6 @@ +INSERT INTO `version_db_characters` (`sql_rev`) VALUES ('1623572783362357500'); + +ALTER TABLE `item_loot_storage` +ADD COLUMN `conditionLootId` INT NOT NULL AFTER `needs_quest`; + + diff --git a/src/server/database/Database/Implementation/CharacterDatabase.cpp b/src/server/database/Database/Implementation/CharacterDatabase.cpp index e456e9e3d..854a6c3f0 100644 --- a/src/server/database/Database/Implementation/CharacterDatabase.cpp +++ b/src/server/database/Database/Implementation/CharacterDatabase.cpp @@ -509,9 +509,9 @@ void CharacterDatabaseConnection::DoPrepareStatements() PrepareStatement(CHAR_DEL_CHAR_ACTION_EXCEPT_SPEC, "DELETE FROM character_action WHERE spec<>? AND guid = ?", CONNECTION_ASYNC); // Items that hold loot or money - PrepareStatement(CHAR_SEL_ITEMCONTAINER_ITEMS, "SELECT containerGUID, itemid, count, randomPropertyId, randomSuffix, follow_loot_rules, freeforall, is_blocked, is_counted, is_underthreshold, needs_quest FROM item_loot_storage", CONNECTION_SYNCH); + PrepareStatement(CHAR_SEL_ITEMCONTAINER_ITEMS, "SELECT containerGUID, itemid, count, randomPropertyId, randomSuffix, follow_loot_rules, freeforall, is_blocked, is_counted, is_underthreshold, needs_quest, conditionLootId FROM item_loot_storage", CONNECTION_SYNCH); PrepareStatement(CHAR_DEL_ITEMCONTAINER_SINGLE_ITEM, "DELETE FROM item_loot_storage WHERE containerGUID = ? AND itemid = ? AND count = ? LIMIT 1", CONNECTION_ASYNC); - PrepareStatement(CHAR_INS_ITEMCONTAINER_SINGLE_ITEM, "INSERT INTO item_loot_storage (containerGUID, itemid, count, randomPropertyId, randomSuffix, follow_loot_rules, freeforall, is_blocked, is_counted, is_underthreshold, needs_quest) VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)", CONNECTION_ASYNC); + PrepareStatement(CHAR_INS_ITEMCONTAINER_SINGLE_ITEM, "INSERT INTO item_loot_storage (containerGUID, itemid, count, randomPropertyId, randomSuffix, follow_loot_rules, freeforall, is_blocked, is_counted, is_underthreshold, needs_quest, conditionLootId) VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)", CONNECTION_ASYNC); PrepareStatement(CHAR_DEL_ITEMCONTAINER_CONTAINER, "DELETE FROM item_loot_storage WHERE containerGUID = ?", CONNECTION_ASYNC); // Calendar diff --git a/src/server/game/Loot/LootItemStorage.cpp b/src/server/game/Loot/LootItemStorage.cpp index 06c3b3bf6..b211a0147 100644 --- a/src/server/game/Loot/LootItemStorage.cpp +++ b/src/server/game/Loot/LootItemStorage.cpp @@ -41,7 +41,7 @@ void LootItemStorage::LoadStorageFromDB() StoredLootItemList& itemList = lootItemStore[ObjectGuid::Create(fields[0].GetUInt32())]; itemList.push_back(StoredLootItem(fields[1].GetUInt32(), fields[2].GetUInt32(), fields[3].GetInt32(), fields[4].GetUInt32(), fields[5].GetBool(), - fields[6].GetBool(), fields[7].GetBool(), fields[8].GetBool(), fields[9].GetBool(), fields[10].GetBool())); + fields[6].GetBool(), fields[7].GetBool(), fields[8].GetBool(), fields[9].GetBool(), fields[10].GetBool(), fields[11].GetUInt32())); ++count; } while (result->NextRow()); @@ -79,7 +79,7 @@ void LootItemStorage::AddNewStoredLoot(Loot* loot, Player* /*player*/) // Gold at first if (loot->gold) { - itemList.push_back(StoredLootItem(0, loot->gold, 0, 0, false, false, false, false, false, false)); + itemList.push_back(StoredLootItem(0, loot->gold, 0, 0, false, false, false, false, false, false, 0)); uint8 index = 0; stmt = CharacterDatabase.GetPreparedStatement(CHAR_INS_ITEMCONTAINER_SINGLE_ITEM); @@ -107,12 +107,18 @@ void LootItemStorage::AddNewStoredLoot(Loot* loot, Player* /*player*/) //if (!li->AllowedForPlayer(player)) // continue; - const ItemTemplate* itemTemplate = sObjectMgr->GetItemTemplate(li->itemid); + ItemTemplate const* itemTemplate = sObjectMgr->GetItemTemplate(li->itemid); if (!itemTemplate || itemTemplate->IsCurrencyToken()) continue; + uint32 conditionLootId = 0; + if (!li->conditions.empty()) + { + conditionLootId = li->conditions.front()->SourceGroup; + } + itemList.push_back(StoredLootItem(li->itemid, li->count, li->randomPropertyId, li->randomSuffix, li->follow_loot_rules, li->freeforall, li->is_blocked, li->is_counted, - li->is_underthreshold, li->needs_quest)); + li->is_underthreshold, li->needs_quest, conditionLootId)); uint8 index = 0; stmt = CharacterDatabase.GetPreparedStatement(CHAR_INS_ITEMCONTAINER_SINGLE_ITEM); @@ -127,6 +133,8 @@ void LootItemStorage::AddNewStoredLoot(Loot* loot, Player* /*player*/) stmt->setBool(index++, li->is_counted); stmt->setBool(index++, li->is_underthreshold); stmt->setBool(index++, li->needs_quest); + stmt->setUInt32(index++, conditionLootId); + trans->Append(stmt); } @@ -172,7 +180,7 @@ bool LootItemStorage::LoadStoredLoot(Item* item, Player* player) li.rollWinnerGUID = ObjectGuid::Empty; // Copy the extra loot conditions from the item in the loot template - lt->CopyConditions(&li); + lt->CopyConditions(&li, it2->conditionLootId); if (li.needs_quest) { diff --git a/src/server/game/Loot/LootItemStorage.h b/src/server/game/Loot/LootItemStorage.h index 16f3cf574..0e982822f 100644 --- a/src/server/game/Loot/LootItemStorage.h +++ b/src/server/game/Loot/LootItemStorage.h @@ -13,9 +13,10 @@ Xinef struct StoredLootItem { - StoredLootItem(uint32 i, uint32 c, int32 ri, uint32 rs, bool follow_loot_rules, bool freeforall, bool is_blocked, bool is_counted, bool is_underthreshold, bool needs_quest) : + StoredLootItem(uint32 i, uint32 c, int32 ri, uint32 rs, bool follow_loot_rules, bool freeforall, + bool is_blocked, bool is_counted, bool is_underthreshold, bool needs_quest, uint32 conditionLootId) : itemid(i), count(c), randomPropertyId(ri), randomSuffix(rs), follow_loot_rules(follow_loot_rules), freeforall(freeforall), is_blocked(is_blocked), - is_counted(is_counted), is_underthreshold(is_underthreshold), needs_quest(needs_quest) { } + is_counted(is_counted), is_underthreshold(is_underthreshold), needs_quest(needs_quest), conditionLootId(conditionLootId) { } // If itemid == 0 - money amount is stored in count value uint32 itemid; @@ -28,6 +29,7 @@ struct StoredLootItem bool is_counted; bool is_underthreshold; bool needs_quest; + uint32 conditionLootId; }; typedef std::list StoredLootItemList; diff --git a/src/server/game/Loot/LootMgr.cpp b/src/server/game/Loot/LootMgr.cpp index 1a3da7a4c..dd07705e9 100644 --- a/src/server/game/Loot/LootMgr.cpp +++ b/src/server/game/Loot/LootMgr.cpp @@ -1380,7 +1380,7 @@ void LootTemplate::CopyConditions(ConditionList conditions) group->CopyConditions(conditions); } -bool LootTemplate::CopyConditions(LootItem* li) const +bool LootTemplate::CopyConditions(LootItem* li, uint32 conditionLootId) const { for (LootStoreItemList::const_iterator _iter = Entries.begin(); _iter != Entries.end(); ++_iter) { @@ -1389,7 +1389,7 @@ bool LootTemplate::CopyConditions(LootItem* li) const { if (LootTemplate const* Referenced = LootTemplates_Reference.GetLootFor(item->reference)) { - if (Referenced->CopyConditions(li)) + if (Referenced->CopyConditions(li, conditionLootId)) { return true; } @@ -1402,6 +1402,11 @@ bool LootTemplate::CopyConditions(LootItem* li) const continue; } + if (!item->conditions.empty() && conditionLootId && conditionLootId != item->conditions.front()->SourceGroup) + { + continue; + } + li->conditions = item->conditions; return true; } @@ -1421,7 +1426,7 @@ bool LootTemplate::CopyConditions(LootItem* li) const { if (LootTemplate const* Referenced = LootTemplates_Reference.GetLootFor(item->reference)) { - if (Referenced->CopyConditions(li)) + if (Referenced->CopyConditions(li, conditionLootId)) { return true; } @@ -1434,6 +1439,11 @@ bool LootTemplate::CopyConditions(LootItem* li) const continue; } + if (!item->conditions.empty() && conditionLootId && conditionLootId != item->conditions.front()->SourceGroup) + { + continue; + } + li->conditions = item->conditions; return true; } @@ -1447,7 +1457,7 @@ bool LootTemplate::CopyConditions(LootItem* li) const { if (LootTemplate const* Referenced = LootTemplates_Reference.GetLootFor(item->reference)) { - if (Referenced->CopyConditions(li)) + if (Referenced->CopyConditions(li, conditionLootId)) { return true; } @@ -1460,6 +1470,11 @@ bool LootTemplate::CopyConditions(LootItem* li) const continue; } + if (!item->conditions.empty() && conditionLootId && conditionLootId != item->conditions.front()->SourceGroup) + { + continue; + } + li->conditions = item->conditions; return true; } diff --git a/src/server/game/Loot/LootMgr.h b/src/server/game/Loot/LootMgr.h index bcd7ae9a5..3ed2873c9 100644 --- a/src/server/game/Loot/LootMgr.h +++ b/src/server/game/Loot/LootMgr.h @@ -243,7 +243,7 @@ public: // Rolls for every item in the template and adds the rolled items the the loot void Process(Loot& loot, LootStore const& store, uint16 lootMode, Player const* player, uint8 groupId = 0) const; void CopyConditions(ConditionList conditions); - bool CopyConditions(LootItem* li) const; + bool CopyConditions(LootItem* li, uint32 conditionLootId = 0) const; // True if template includes at least 1 quest drop entry [[nodiscard]] bool HasQuestDrop(LootTemplateMap const& store, uint8 groupId = 0) const;