diff --git a/src/server/game/Entities/Player/Player.cpp b/src/server/game/Entities/Player/Player.cpp index 4d77527b7..bdb75066b 100644 --- a/src/server/game/Entities/Player/Player.cpp +++ b/src/server/game/Entities/Player/Player.cpp @@ -15747,15 +15747,23 @@ void Player::RewardQuest(Quest const* quest, uint32 reward, Object* questGiver, uint32 quest_id = quest->GetQuestId(); for (uint8 i = 0; i < QUEST_ITEM_OBJECTIVES_COUNT; ++i) - if (quest->RequiredItemId[i]) - DestroyItemCount(quest->RequiredItemId[i], quest->RequiredItemCount[i], true); - + { + if (ItemTemplate const* itemTemplate = sObjectMgr->GetItemTemplate(quest->RequiredItemId[i])) + { + if (quest->RequiredItemCount[i] > 0 && itemTemplate->Bonding == BIND_QUEST_ITEM && !quest->IsRepeatable() && !HasQuestForItem(quest->RequiredItemId[i], quest_id, true)) + DestroyItemCount(quest->RequiredItemId[i], 9999, true); + else + DestroyItemCount(quest->RequiredItemId[i], quest->RequiredItemCount[i], true); + } + } for (uint8 i = 0; i < QUEST_SOURCE_ITEM_IDS_COUNT; ++i) { - if (quest->ItemDrop[i]) + if (ItemTemplate const* itemTemplate = sObjectMgr->GetItemTemplate(quest->ItemDrop[i])) { - uint32 count = quest->ItemDropQuantity[i]; - DestroyItemCount(quest->ItemDrop[i], count ? count : 9999, true); + if (quest->ItemDropQuantity[i] > 0 && itemTemplate->Bonding == BIND_QUEST_ITEM && !quest->IsRepeatable() && !HasQuestForItem(quest->ItemDrop[i], quest_id)) + DestroyItemCount(quest->ItemDrop[i], 9999, true); + else + DestroyItemCount(quest->ItemDrop[i], quest->ItemDropQuantity[i], true); } } @@ -15986,14 +15994,32 @@ void Player::FailQuest(uint32 questId) SendQuestFailed(questId); // Destroy quest items on quest failure. - for (uint8 i = 0; i < QUEST_OBJECTIVES_COUNT; ++i) - if (quest->RequiredItemId[i] > 0 && quest->RequiredItemCount[i] > 0) - // Destroy items received on starting the quest. - DestroyItemCount(quest->RequiredItemId[i], quest->RequiredItemCount[i], true, true); + for (uint8 i = 0; i < QUEST_ITEM_OBJECTIVES_COUNT; ++i) + if (ItemTemplate const* itemTemplate = sObjectMgr->GetItemTemplate(quest->RequiredItemId[i])) + if (quest->RequiredItemCount[i] > 0 && itemTemplate->Bonding == BIND_QUEST_ITEM) + DestroyItemCount(quest->RequiredItemId[i], 9999, true); + for (uint8 i = 0; i < QUEST_SOURCE_ITEM_IDS_COUNT; ++i) - if (quest->ItemDrop[i] > 0 && quest->ItemDropQuantity[i] > 0) - // Destroy items received during the quest. - DestroyItemCount(quest->ItemDrop[i], quest->ItemDropQuantity[i], true, true); + if (ItemTemplate const* itemTemplate = sObjectMgr->GetItemTemplate(quest->ItemDrop[i])) + if (quest->ItemDropQuantity[i] > 0 && itemTemplate->Bonding == BIND_QUEST_ITEM) + DestroyItemCount(quest->ItemDrop[i], 9999, true); + } +} + +void Player::AbandonQuest(uint32 questId) +{ + if (Quest const* quest = sObjectMgr->GetQuestTemplate(questId)) + { + // It will Destroy quest items on quests abandons. + for (uint8 i = 0; i < QUEST_ITEM_OBJECTIVES_COUNT; ++i) + if (ItemTemplate const* itemTemplate = sObjectMgr->GetItemTemplate(quest->RequiredItemId[i])) + if (quest->RequiredItemCount[i] > 0 && itemTemplate->Bonding == BIND_QUEST_ITEM) + DestroyItemCount(quest->RequiredItemId[i], 9999, true); + + for (uint8 i = 0; i < QUEST_SOURCE_ITEM_IDS_COUNT; ++i) + if (ItemTemplate const* itemTemplate = sObjectMgr->GetItemTemplate(quest->ItemDrop[i])) + if (quest->ItemDropQuantity[i] > 0 && itemTemplate->Bonding == BIND_QUEST_ITEM) + DestroyItemCount(quest->ItemDrop[i], 9999, true); } } @@ -17221,12 +17247,12 @@ void Player::ReputationChanged2(FactionEntry const* factionEntry) } } -bool Player::HasQuestForItem(uint32 itemid) const +bool Player::HasQuestForItem(uint32 itemid, uint32 excludeQuestId /* 0 */, bool turnIn /* false */) const { for (uint8 i = 0; i < MAX_QUEST_LOG_SIZE; ++i) { uint32 questid = GetQuestSlotQuestId(i); - if (questid == 0) + if (questid == 0 || questid == excludeQuestId) continue; QuestStatusMap::const_iterator qs_itr = m_QuestStatus.find(questid); @@ -17235,7 +17261,7 @@ bool Player::HasQuestForItem(uint32 itemid) const QuestStatusData const& q_status = qs_itr->second; - if (q_status.Status == QUEST_STATUS_INCOMPLETE) + if ((q_status.Status == QUEST_STATUS_INCOMPLETE) || (turnIn && q_status.Status == QUEST_STATUS_COMPLETE)) { Quest const* qinfo = sObjectMgr->GetQuestTemplate(questid); if (!qinfo) @@ -17250,7 +17276,7 @@ bool Player::HasQuestForItem(uint32 itemid) const // This part for ReqItem drop for (uint8 j = 0; j < QUEST_ITEM_OBJECTIVES_COUNT; ++j) { - if (itemid == qinfo->RequiredItemId[j] && q_status.ItemCount[j] < qinfo->RequiredItemCount[j]) + if ((itemid == qinfo->RequiredItemId[j] && q_status.ItemCount[j] < qinfo->RequiredItemCount[j]) || (turnIn && q_status.ItemCount[j] >= qinfo->RequiredItemCount[j])) return true; } // This part - for ReqSource @@ -17260,17 +17286,18 @@ bool Player::HasQuestForItem(uint32 itemid) const if (qinfo->ItemDrop[j] == itemid) { ItemTemplate const* pProto = sObjectMgr->GetItemTemplate(itemid); - + uint32 ownedCount = GetItemCount(itemid, true); // 'unique' item - if (pProto->MaxCount && int32(GetItemCount(itemid, true)) < pProto->MaxCount) + if ((pProto->MaxCount && int32(ownedCount) < pProto->MaxCount) || (turnIn && int32(ownedCount) >= pProto->MaxCount)) return true; // allows custom amount drop when not 0 if (qinfo->ItemDropQuantity[j]) { - if (GetItemCount(itemid, true) < qinfo->ItemDropQuantity[j]) + if ((ownedCount < qinfo->ItemDropQuantity[j]) || (turnIn && ownedCount >= qinfo->ItemDropQuantity[j])) return true; - } else if (GetItemCount(itemid, true) < pProto->GetMaxStackSize()) + } + else if (ownedCount < pProto->GetMaxStackSize()) return true; } } diff --git a/src/server/game/Entities/Player/Player.h b/src/server/game/Entities/Player/Player.h index 73a57b509..3cc02b1f5 100644 --- a/src/server/game/Entities/Player/Player.h +++ b/src/server/game/Entities/Player/Player.h @@ -1399,6 +1399,7 @@ class Player : public Unit, public GridObject bool CanRewardQuest(Quest const* quest, uint32 reward, bool msg); void AddQuestAndCheckCompletion(Quest const* quest, Object* questGiver); void AddQuest(Quest const* quest, Object* questGiver); + void AbandonQuest(uint32 quest_id); void CompleteQuest(uint32 quest_id); void IncompleteQuest(uint32 quest_id); void RewardQuest(Quest const* quest, uint32 reward, Object* questGiver, bool announce = true); @@ -1486,7 +1487,7 @@ class Player : public Unit, public GridObject void MoneyChanged(uint32 value); void ReputationChanged(FactionEntry const* factionEntry); void ReputationChanged2(FactionEntry const* factionEntry); - bool HasQuestForItem(uint32 itemid) const; + bool HasQuestForItem(uint32 itemId, uint32 excludeQuestId = 0, bool turnIn = false) const; bool HasQuestForGO(int32 GOId) const; void UpdateForQuestWorldObjects(); bool CanShareQuest(uint32 quest_id) const; diff --git a/src/server/game/Handlers/QuestHandler.cpp b/src/server/game/Handlers/QuestHandler.cpp index 1be8665ed..862b636b2 100644 --- a/src/server/game/Handlers/QuestHandler.cpp +++ b/src/server/game/Handlers/QuestHandler.cpp @@ -418,6 +418,7 @@ void WorldSession::HandleQuestLogRemoveQuest(WorldPacket& recvData) } _player->TakeQuestSourceItem(questId, true); // remove quest src item from player + _player->AbandonQuest(questId); // remove all quest items player received before abandoning quest. _player->RemoveActiveQuest(questId); _player->RemoveTimedAchievement(ACHIEVEMENT_TIMED_TYPE_QUEST, questId); #ifdef ELUNA