mirror of
https://github.com/TrinityCore/TrinityCore.git
synced 2026-01-23 02:25:38 +01:00
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
This commit is contained in:
@@ -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();
|
||||
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -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; }
|
||||
|
||||
@@ -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);
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user