Merge pull request #1241 from poszer/QuestAbandonFinishFix

Core/Quests: Abandon&Finish quest items
This commit is contained in:
Poszer
2019-01-09 19:58:57 +01:00
committed by GitHub
3 changed files with 51 additions and 22 deletions

View File

@@ -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;
}
}

View File

@@ -1399,6 +1399,7 @@ class Player : public Unit, public GridObject<Player>
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<Player>
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;

View File

@@ -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