aboutsummaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
authorOvahlord <dreadkiller@gmx.de>2024-08-22 16:28:26 +0200
committerOvahlord <dreadkiller@gmx.de>2024-08-22 16:28:26 +0200
commit926fda01d8e115cae70f015539b269d7ae4860f2 (patch)
treeefb5228f271db89921183e6a88c55aa0ff387448 /src
parentd6375047854b5dd6639d6208619f12ad4c09d6cc (diff)
Core/Quests: fixed max level quest money rewards and calculate them during runtime instead of using dumped DB values
* this fixes an exploit that was allowing players that have capped their level via npc to obtain higher max level money rewards if the quest info came from a sniff that was done with a max level character
Diffstat (limited to 'src')
-rw-r--r--src/server/game/Entities/Player/Player.cpp28
-rw-r--r--src/server/game/Quests/QuestDef.cpp19
-rw-r--r--src/server/game/Quests/QuestDef.h4
-rw-r--r--src/server/game/Spells/SpellEffects.cpp2
4 files changed, 23 insertions, 30 deletions
diff --git a/src/server/game/Entities/Player/Player.cpp b/src/server/game/Entities/Player/Player.cpp
index e05004e1f98..d3905dcc807 100644
--- a/src/server/game/Entities/Player/Player.cpp
+++ b/src/server/game/Entities/Player/Player.cpp
@@ -14104,7 +14104,11 @@ void Player::IncompleteQuest(uint32 quest_id)
uint32 Player::GetQuestMoneyReward(Quest const* quest) const
{
- return quest->GetMoneyReward(this) * sWorld->getRate(RATE_MONEY_QUEST);
+ uint32 moneyReward = quest->GetMoneyReward(this) * sWorld->getRate(RATE_MONEY_QUEST);
+ if (IsMaxLevel())
+ moneyReward += quest->GetRewMoneyMaxLevel(this) * sWorld->getRate(RATE_MONEY_MAX_LEVEL_QUEST);
+
+ return moneyReward;
}
uint32 Player::GetQuestXPReward(Quest const* quest)
@@ -14328,14 +14332,10 @@ void Player::RewardQuest(Quest const* quest, LootItemType rewardType, uint32 rew
uint32 XP = GetQuestXPReward(quest);
- int32 moneyRew = 0;
if (!IsMaxLevel())
GiveXP(XP, nullptr);
- else
- moneyRew = int32(quest->GetRewMoneyMaxLevel() * sWorld->getRate(RATE_DROP_MONEY));
-
- moneyRew += GetQuestMoneyReward(quest);
+ int32 moneyRew = GetQuestMoneyReward(quest);
if (moneyRew)
{
ModifyMoney(moneyRew);
@@ -16216,23 +16216,11 @@ void Player::SendQuestReward(Quest const* quest, Creature const* questGiver, uin
uint32 questId = quest->GetQuestId();
sGameEventMgr->HandleQuestComplete(questId);
- uint32 moneyReward;
-
- if (!IsMaxLevel())
- {
- moneyReward = GetQuestMoneyReward(quest);
- }
- else // At max level, increase gold reward
- {
- xp = 0;
- moneyReward = uint32(GetQuestMoneyReward(quest) + int32(quest->GetRewMoneyMaxLevel() * sWorld->getRate(RATE_DROP_MONEY)));
- }
-
WorldPackets::Quest::QuestGiverQuestComplete packet;
packet.QuestID = questId;
- packet.MoneyReward = moneyReward;
- packet.XPReward = xp;
+ packet.MoneyReward = GetQuestMoneyReward(quest);
+ packet.XPReward = IsMaxLevel() ? 0 : xp;
packet.SkillLineIDReward = quest->GetRewardSkillId();
packet.NumSkillUpsReward = quest->GetRewardSkillPoints();
diff --git a/src/server/game/Quests/QuestDef.cpp b/src/server/game/Quests/QuestDef.cpp
index 9de14cfd28f..55db20cb361 100644
--- a/src/server/game/Quests/QuestDef.cpp
+++ b/src/server/game/Quests/QuestDef.cpp
@@ -410,16 +410,16 @@ void Quest::LoadConditionalConditionalQuestCompletionLog(Field* fields)
uint32 Quest::XPValue(Player const* player) const
{
- return XPValue(player, GetQuestLevelForPlayer(player) , _level, _rewardXPDifficulty, _rewardXPMultiplier);
+ return XPValue(player ? player->GetLevel() : 0, GetQuestLevelForPlayer(player), _level, _rewardXPDifficulty, _rewardXPMultiplier);
}
-uint32 Quest::XPValue(Player const* player, uint32 questLevel, int32 unscaledQuestLevel, uint32 xpDifficulty, float xpMultiplier /*= 1.0f*/)
+uint32 Quest::XPValue(uint8 playerLevel, uint32 questLevel, int32 unscaledQuestLevel, uint32 xpDifficulty, float xpMultiplier /*= 1.0f*/)
{
QuestXPEntry const* questXp = sQuestXPStore.LookupEntry(questLevel);
if (!questXp || xpDifficulty >= 10)
return 0;
- int32 diffFactor = 2 * (questLevel - (unscaledQuestLevel == -1 ? 0 : -5) - (player ? player->GetLevel() : 0)) + 10;
+ int32 diffFactor = 2 * (questLevel - (unscaledQuestLevel == -1 ? 0 : -5) - playerLevel) + 10;
if (diffFactor < 1)
diffFactor = 1;
else if (diffFactor > 10)
@@ -541,14 +541,19 @@ void Quest::BuildQuestRewards(WorldPackets::Quest::QuestRewards& rewards, Player
}
}
-uint32 Quest::GetRewMoneyMaxLevel() const
+uint32 Quest::GetRewMoneyMaxLevel(Player const* player /*= nullptr*/) const
{
// If Quest has flag to not give money on max level, it's 0
if (HasFlag(QUEST_FLAGS_NO_MONEY_FOR_XP))
return 0;
- // Else, return the rewarded copper sum modified by the rate
- return uint32(_rewardBonusMoney * sWorld->getRate(RATE_MONEY_MAX_LEVEL_QUEST));
+ uint32 maxQuestLevel = _level == -1 ? _maxScalingLevel : _level;
+
+ // Query initialization during startup does not provide a valid player so we just go for the expansion's max level
+ uint8 playerLevel = player ? player->GetLevel() : GetMaxLevelForExpansion(CURRENT_EXPANSION);
+
+ // The conversion rate is XP * 6 copper
+ return XPValue(playerLevel, maxQuestLevel, _level, _rewardXPDifficulty, _rewardXPMultiplier) * 6;
}
bool Quest::IsAutoAccept() const
@@ -677,7 +682,7 @@ WorldPacket Quest::BuildQueryData(LocaleConstant loc, Player* player) const
response.Info.RewardMoneyDifficulty = GetRewMoneyDifficulty();
response.Info.RewardMoneyMultiplier = GetMoneyMultiplier();
- response.Info.RewardBonusMoney = GetRewMoneyMaxLevel();
+ response.Info.RewardBonusMoney = GetRewMoneyMaxLevel(player);
for (uint8 i = 0; i < QUEST_REWARD_DISPLAY_SPELL_COUNT; ++i)
response.Info.RewardDisplaySpell[i] = RewardDisplaySpell[i].SpellId;
diff --git a/src/server/game/Quests/QuestDef.h b/src/server/game/Quests/QuestDef.h
index edcde0fd66f..3b800a679bc 100644
--- a/src/server/game/Quests/QuestDef.h
+++ b/src/server/game/Quests/QuestDef.h
@@ -532,7 +532,7 @@ class TC_GAME_API Quest
void LoadConditionalConditionalQuestCompletionLog(Field* fields);
uint32 XPValue(Player const* player) const;
- static uint32 XPValue(Player const* player, uint32 questLevel, int32 unscaledQuestLevel, uint32 xpDifficulty, float xpMultiplier = 1.0f);
+ static uint32 XPValue(uint8 playerLevel, uint32 questLevel, int32 unscaledQuestLevel, uint32 xpDifficulty, float xpMultiplier = 1.0f);
uint32 GetMoneyReward(Player const* player) const;
Optional<QuestTagType> GetQuestTag() const;
bool IsImportant() const;
@@ -610,7 +610,7 @@ class TC_GAME_API Quest
uint32 GetArtifactXPDifficulty() const { return _rewardArtifactXPDifficulty; }
float GetArtifactXPMultiplier() const { return _rewardArtifactXPMultiplier; }
uint32 GetArtifactCategoryId() const { return _rewardArtifactCategoryID; }
- uint32 GetRewMoneyMaxLevel() const; // use in XP calculation at client
+ uint32 GetRewMoneyMaxLevel(Player const* player = nullptr) const;
uint32 GetRewSpell() const { return _rewardSpell; }
uint32 GetRewMailTemplateId() const { return _rewardMailTemplateId; }
uint32 GetRewMailDelaySecs() const { return _rewardMailDelay; }
diff --git a/src/server/game/Spells/SpellEffects.cpp b/src/server/game/Spells/SpellEffects.cpp
index b1623f71790..2502a2a66d3 100644
--- a/src/server/game/Spells/SpellEffects.cpp
+++ b/src/server/game/Spells/SpellEffects.cpp
@@ -5418,7 +5418,7 @@ void Spell::EffectGiveExperience()
if (!playerTarget)
return;
- uint32 xp = Quest::XPValue(playerTarget, 0, 0, effectInfo->MiscValueB);
+ uint32 xp = Quest::XPValue(playerTarget->GetLevel(), 0, 0, effectInfo->MiscValueB);
playerTarget->GiveXP(xp, nullptr);
}