Skip to content

Commit

Permalink
Prevent Autocomplete Quest Packet-Editing Exploit (#844)
Browse files Browse the repository at this point in the history
  • Loading branch information
m-laniakea authored and StadenElysium committed May 24, 2017
1 parent 0858eaf commit 6c84ff7
Show file tree
Hide file tree
Showing 3 changed files with 23 additions and 8 deletions.
2 changes: 2 additions & 0 deletions src/game/Handlers/QuestHandler.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -279,7 +279,9 @@ void WorldSession::HandleQuestgiverChooseRewardOpcode(WorldPacket & recv_data)
_player->PlayerTalkClass->SendQuestGiverQuestDetails(nextquest, guid, true);
}
else
{
_player->PlayerTalkClass->SendQuestGiverOfferReward(pQuest, guid, true);
}
}
}

Expand Down
27 changes: 20 additions & 7 deletions src/game/Objects/Player.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -12072,12 +12072,12 @@ bool Player::CanSeeStartQuest(Quest const *pQuest) const
return false;
}

bool Player::CanTakeQuest(Quest const *pQuest, bool msg) const
bool Player::CanTakeQuest(Quest const *pQuest, bool msg, bool skipStatusCheck /*false*/) const
{
if (pQuest->GetType() == QUEST_TYPE_PVP && pQuest->GetQuestLevel() && pQuest->GetQuestLevel() < getLevel())
return false;

return SatisfyQuestStatus(pQuest, msg) && SatisfyQuestExclusiveGroup(pQuest, msg) &&
return (skipStatusCheck || SatisfyQuestStatus(pQuest, msg)) && SatisfyQuestExclusiveGroup(pQuest, msg) &&
SatisfyQuestClass(pQuest, msg) && SatisfyQuestRace(pQuest, msg) && SatisfyQuestLevel(pQuest, msg) &&
SatisfyQuestSkill(pQuest, msg) && SatisfyQuestReputation(pQuest, msg) &&
SatisfyQuestPreviousQuest(pQuest, msg) && SatisfyQuestTimed(pQuest, msg) &&
Expand Down Expand Up @@ -12196,11 +12196,21 @@ bool Player::CanCompleteRepeatableQuest(Quest const *pQuest) const

bool Player::CanRewardQuest(Quest const *pQuest, bool msg) const
{
// not auto complete quest and not completed quest (only cheating case, then ignore without message)
if (!pQuest->IsAutoComplete() && GetQuestStatus(pQuest->GetQuestId()) != QUEST_STATUS_COMPLETE)
return false;
// Prevent packet-editing exploits
// Players must meet prereqs for AutoComplete quests
if (pQuest->IsAutoComplete())
{
if (!CanTakeQuest(pQuest, false, true))
return false;
}
else
{
// Normal quests must be accepted and have a complete status
if (GetQuestStatus(pQuest->GetQuestId()) != QUEST_STATUS_COMPLETE)
return false;
}

// rewarded and not repeatable quest (only cheating case, then ignore without message)
// Prevent completing the same quest twice
if (GetQuestRewardStatus(pQuest->GetQuestId()))
return false;

Expand All @@ -12219,9 +12229,12 @@ bool Player::CanRewardQuest(Quest const *pQuest, bool msg) const
}
}

// prevent receive reward with low money and GetRewOrReqMoney() < 0
// Check if players have enough money to complete the quest
if (pQuest->GetRewOrReqMoney() < 0 && GetMoney() < uint32(-pQuest->GetRewOrReqMoney()))
{
SendCanTakeQuestResponse(INVALIDREASON_QUEST_FAILED_NOT_ENOUGH_MONEY);
return false;
}

return true;
}
Expand Down
2 changes: 1 addition & 1 deletion src/game/Objects/Player.h
Original file line number Diff line number Diff line change
Expand Up @@ -1201,7 +1201,7 @@ class MANGOS_DLL_SPEC Player final: public Unit
bool IsCurrentQuest(uint32 quest_id, uint8 completedOrNot = 0) const;
Quest const *GetNextQuest(ObjectGuid guid, Quest const *pQuest );
bool CanSeeStartQuest( Quest const *pQuest ) const;
bool CanTakeQuest( Quest const *pQuest, bool msg ) const;
bool CanTakeQuest( Quest const *pQuest, bool msg, bool skipStatusCheck = false ) const;
bool CanAddQuest( Quest const *pQuest, bool msg ) const;
bool CanCompleteQuest( uint32 quest_id ) const;
bool CanCompleteRepeatableQuest(Quest const *pQuest) const;
Expand Down

0 comments on commit 6c84ff7

Please sign in to comment.