Core/Quests: Abandon&Finish quest items

Destroy quest items on quest failure/abandon.

Failing/abandoning a quest should not unconditionally remove required items, non-quest specific items such as crafting reagents should remain in inventory.

Delete all quest bound items on quest reward, failure or abandoning.

Only delete all quest bound items from inventory on turn in if the quest is not repeatable
This commit is contained in:
poszer
2019-01-07 18:13:47 +01:00
parent b5d56462e2
commit d213a4ef93
3 changed files with 51 additions and 22 deletions

View File

@@ -15746,15 +15746,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);
}
}
@@ -15985,14 +15993,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);
}
}
@@ -17220,12 +17246,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);
@@ -17234,7 +17260,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)
@@ -17249,7 +17275,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
@@ -17259,17 +17285,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;
}
}