Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
22 changes: 15 additions & 7 deletions src/server/game/Entities/Player/KillRewarder.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -67,7 +67,7 @@
KillRewarder::KillRewarder(Player* killer, Unit* victim, bool isBattleGround) :
// 1. Initialize internal variables to default values.
_killer(killer), _victim(victim), _group(killer->GetGroup()),
_groupRate(1.0f), _maxNotGrayMember(nullptr), _count(0), _aliveSumLevel(0), _sumLevel(0), _xp(0),
_groupRate(1.0f), _maxNotGrayMember(nullptr), _maxNotGrayMemberLevel(0), _count(0), _aliveSumLevel(0), _sumLevel(0), _xp(0),
_isFullXP(false), _maxLevel(0), _isBattleGround(isBattleGround), _isPvP(false)
{
// mark the credit as pvp if victim is player
Expand All @@ -89,7 +89,7 @@ void KillRewarder::_InitGroupData()
if (Player* member = itr->GetSource())
if ((_killer == member || member->IsAtGroupRewardDistance(_victim)))
{
const uint8 lvl = member->GetLevel();
const uint8 lvl = _GetPlayerLevel(member);
if (member->IsAlive())
{
// 2.1. _count - number of alive group members within reward distance;
Expand All @@ -104,17 +104,18 @@ void KillRewarder::_InitGroupData()
// 2.4. _maxNotGrayMember - maximum level of alive group member within reward distance,
// for whom victim is not gray;
uint32 grayLevel = Acore::XP::GetGrayLevel(lvl);
if (_victim->GetLevel() > grayLevel && (!_maxNotGrayMember || _maxNotGrayMember->GetLevel() < lvl))
if (_victim->GetLevel() > grayLevel && (!_maxNotGrayMember || _maxNotGrayMemberLevel < lvl))
{
_maxNotGrayMember = member;
_maxNotGrayMemberLevel = lvl;
}
}
// 2.5. _sumLevel - sum of levels of group members within reward distance;
_sumLevel += lvl;
}
// 2.6. _isFullXP - flag identifying that for all group members victim is not gray,
// so 100% XP will be rewarded (50% otherwise).
_isFullXP = _maxNotGrayMember && (_maxLevel == _maxNotGrayMember->GetLevel());
_isFullXP = _maxNotGrayMember && (_maxLevel == _maxNotGrayMemberLevel);
}
else
_count = 1;
Expand Down Expand Up @@ -153,7 +154,7 @@ void KillRewarder::_RewardXP(Player* player, float rate)
// * set to 0 if player's level is more than maximum level of not gray member;
// * cut XP in half if _isFullXP is false.
if (_maxNotGrayMember && player->IsAlive() &&
_maxNotGrayMember->GetLevel() >= player->GetLevel())
_maxNotGrayMemberLevel >= _GetPlayerLevel(player))
xp = _isFullXP ?
uint32(xp * rate) : // Reward FULL XP if all group members are not gray.
uint32(xp * rate / 2) + 1; // Reward only HALF of XP if some of group members are gray.
Expand Down Expand Up @@ -208,8 +209,8 @@ void KillRewarder::_RewardPlayer(Player* player, bool isDungeon)
// Give reputation and kill credit only in PvE.
if (!_isPvP || _isBattleGround)
{
float xpRate = _group ? _groupRate * float(player->GetLevel()) / _aliveSumLevel : /*Personal rate is 100%.*/ 1.0f; // Group rate depends on the sum of levels.
sScriptMgr->OnPlayerRewardKillRewarder(player, this, isDungeon, xpRate); // Personal rate is 100%.
float xpRate = _group ? _groupRate * float(_GetPlayerLevel(player)) / _aliveSumLevel : /*Personal rate is 100%.*/ 1.0f; // Group rate depends on the sum of levels.
sScriptMgr->OnPlayerRewardKillRewarder(player, this, isDungeon, xpRate); // Personal rate is 100%.

if (_xp)
{
Expand Down Expand Up @@ -264,6 +265,13 @@ void KillRewarder::_RewardGroup()
}
}

uint8 KillRewarder::_GetPlayerLevel(Player const* player)
{
uint8 level = player->GetLevel();
sScriptMgr->OnPlayerBeforeGetLevelForXPGain(player, level);
return level;
}

void KillRewarder::Reward()
{
// 3. Reward killer (and group, if necessary).
Expand Down
2 changes: 2 additions & 0 deletions src/server/game/Entities/Player/KillRewarder.h
Original file line number Diff line number Diff line change
Expand Up @@ -43,12 +43,14 @@ class AC_GAME_API KillRewarder
void _RewardKillCredit(Player* player);
void _RewardPlayer(Player* player, bool isDungeon);
void _RewardGroup();
uint8 _GetPlayerLevel(Player const* player);

Player* _killer;
Unit* _victim;
Group* _group;
float _groupRate;
Player* _maxNotGrayMember;
uint8 _maxNotGrayMemberLevel;
uint32 _count;
uint32 _aliveSumLevel;
uint32 _sumLevel;
Expand Down
10 changes: 7 additions & 3 deletions src/server/game/Entities/Player/Player.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -2370,6 +2370,7 @@ void Player::GiveXP(uint32 xp, Unit* victim, float group_rate, bool isLFGReward)
}

uint8 level = GetLevel();
sScriptMgr->OnPlayerBeforeGetLevelForXPGain(this, level);

// Favored experience increase START
uint32 zone = GetZoneId();
Expand Down Expand Up @@ -5775,17 +5776,20 @@ void Player::CheckAreaExploreAndOutdoor()

if (areaEntry->area_level > 0)
{
if (GetLevel() >= sWorld->getIntConfig(CONFIG_MAX_PLAYER_LEVEL))
uint8 playerLevel = GetLevel();
sScriptMgr->OnPlayerBeforeGetLevelForXPGain(this, playerLevel);

if (playerLevel >= sWorld->getIntConfig(CONFIG_MAX_PLAYER_LEVEL))
{
SendExplorationExperience(areaId, 0);
}
else
{
int32 diff = int32(GetLevel()) - areaEntry->area_level;
int32 diff = int32(playerLevel) - areaEntry->area_level;
uint32 XP = 0;
if (diff < -5)
{
XP = uint32(sObjectMgr->GetBaseXP(GetLevel() + 5) * sWorld->getRate(RATE_XP_EXPLORE));
XP = uint32(sObjectMgr->GetBaseXP(playerLevel + 5) * sWorld->getRate(RATE_XP_EXPLORE));
}
else if (diff > 5)
{
Expand Down
5 changes: 4 additions & 1 deletion src/server/game/Entities/Player/PlayerQuest.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -1435,8 +1435,11 @@ bool Player::TakeQuestSourceItem(uint32 questId, bool msg)

uint32 Player::CalculateQuestRewardXP(Quest const* quest)
{
uint8 level = GetLevel();
sScriptMgr->OnPlayerBeforeGetLevelForXPGain(this, level);

// apply world quest rate
uint32 xp = uint32(quest->XPValue(GetLevel()) * GetQuestRate(quest->IsDFQuest()));
uint32 xp = uint32(quest->XPValue(level) * GetQuestRate(quest->IsDFQuest()));

// handle SPELL_AURA_MOD_XP_QUEST_PCT auras
xp *= GetTotalAuraMultiplier(SPELL_AURA_MOD_XP_QUEST_PCT);
Expand Down
12 changes: 9 additions & 3 deletions src/server/game/Handlers/LFGHandler.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,7 @@
#include "ObjectMgr.h"
#include "Opcodes.h"
#include "Player.h"
#include "ScriptMgr.h"
#include "WorldPacket.h"
#include "WorldSession.h"

Expand Down Expand Up @@ -188,10 +189,13 @@ void WorldSession::HandleLfgPlayerLockInfoRequestOpcode(WorldPacket& /*recvData*
if (quest)
{
uint8 playerLevel = GetPlayer() ? GetPlayer()->GetLevel() : 0;
uint8 playerLevelForXP = playerLevel;
sScriptMgr->OnPlayerBeforeGetLevelForXPGain(GetPlayer(), playerLevelForXP);

data << uint8(done);
data << uint32(quest->GetRewOrReqMoney(playerLevel));
if (!GetPlayer()->IsMaxLevel())
data << uint32(quest->XPValue(playerLevel));
if (playerLevelForXP < GetPlayer()->GetUInt32Value(PLAYER_FIELD_MAX_LEVEL))
data << uint32(quest->XPValue(playerLevelForXP));
else
data << uint32(0);
data << uint32(0);
Expand Down Expand Up @@ -479,14 +483,16 @@ void WorldSession::SendLfgPlayerReward(lfg::LfgPlayerRewardData const& rewardDat
uint8 itemNum = rewardData.quest->GetRewItemsCount();

uint8 playerLevel = GetPlayer() ? GetPlayer()->GetLevel() : 0;
uint8 playerLevelForXP = playerLevel;
sScriptMgr->OnPlayerBeforeGetLevelForXPGain(GetPlayer(), playerLevelForXP);

WorldPacket data(SMSG_LFG_PLAYER_REWARD, 4 + 4 + 1 + 4 + 4 + 4 + 4 + 4 + 1 + itemNum * (4 + 4 + 4));
data << uint32(rewardData.rdungeonEntry); // Random Dungeon Finished
data << uint32(rewardData.sdungeonEntry); // Dungeon Finished
data << uint8(rewardData.done);
data << uint32(1);
data << uint32(rewardData.quest->GetRewOrReqMoney(playerLevel));
data << uint32(rewardData.quest->XPValue(playerLevel));
data << uint32(rewardData.quest->XPValue(playerLevelForXP));
data << uint32(0);
data << uint32(0);
data << uint8(itemNum);
Expand Down
5 changes: 4 additions & 1 deletion src/server/game/Miscellaneous/Formulas.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,7 @@
#include "Creature.h"
#include "Log.h"
#include "Player.h"
#include "ScriptMgr.h"
#include "World.h"

uint32 Acore::XP::BaseGain(uint8 pl_level, uint8 mob_level, ContentLevels content)
Expand Down Expand Up @@ -79,7 +80,9 @@ uint32 Acore::XP::Gain(Player* player, Unit* unit, bool isBattleGround /*= false
{
float xpMod = 1.0f;

gain = BaseGain(player->GetLevel(), unit->GetLevel(), GetContentLevelsForMapAndZone(unit->GetMapId(), unit->GetZoneId()));
uint8 playerLevel = player->GetLevel();
sScriptMgr->OnPlayerBeforeGetLevelForXPGain(player, playerLevel);
gain = BaseGain(playerLevel, unit->GetLevel(), GetContentLevelsForMapAndZone(unit->GetMapId(), unit->GetZoneId()));

if (gain && creature)
{
Expand Down
9 changes: 9 additions & 0 deletions src/server/game/Scripting/ScriptDefines/PlayerScript.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,9 @@
#include "PlayerScript.h"
#include "ScriptMgr.h"
#include "ScriptMgrMacros.h"
#include "World.h"

#include <algorithm>

void ScriptMgr::OnPlayerBeforeDurabilityRepair(Player* player, ObjectGuid npcGUID, ObjectGuid itemGUID, float& discountMod, uint8 guildBank)
{
Expand Down Expand Up @@ -930,6 +933,12 @@ void ScriptMgr::OnPlayerLearnTaxiNode(Player const* player, uint32 nodeId)
CALL_ENABLED_HOOKS(PlayerScript, PLAYERHOOK_ON_LEARN_TAXI_NODE, script->OnPlayerLearnTaxiNode(player, nodeId));
}

void ScriptMgr::OnPlayerBeforeGetLevelForXPGain(Player const* player, uint8& level)
{
CALL_ENABLED_HOOKS(PlayerScript, PLAYERHOOK_ON_BEFORE_GET_LEVEL_FOR_XP_GAIN, script->OnPlayerBeforeGetLevelForXPGain(player, level));
level = std::clamp(level, uint8(1), uint8(sWorld->getIntConfig(CONFIG_MAX_PLAYER_LEVEL)));
}

PlayerScript::PlayerScript(const char* name, std::vector<uint16> enabledHooks)
: ScriptObject(name, PLAYERHOOK_END)
{
Expand Down
9 changes: 9 additions & 0 deletions src/server/game/Scripting/ScriptDefines/PlayerScript.h
Original file line number Diff line number Diff line change
Expand Up @@ -211,6 +211,7 @@ enum PlayerHook
PLAYERHOOK_ON_GIVE_REPUTATION,
PLAYERHOOK_ON_GET_REPUTATION_PRICE_DISCOUNT,
PLAYERHOOK_ON_LEARN_TAXI_NODE,
PLAYERHOOK_ON_BEFORE_GET_LEVEL_FOR_XP_GAIN,
PLAYERHOOK_END
};

Expand Down Expand Up @@ -829,6 +830,14 @@ class PlayerScript : public ScriptObject
* @param nodeId The id of the learned taxi node
*/
virtual void OnPlayerLearnTaxiNode(Player const* /*player*/, uint32 /*nodeId*/) {}

/**
* @brief This hook is called when XP is calculated for the player, and is used to modify the player level used in the XP formulas.
*
* @param player Contains information about the Player
* @param level The level that should be used for XP gain calculations
*/
virtual void OnPlayerBeforeGetLevelForXPGain(Player const* /*player*/, uint8& /*level*/) {}
};

#endif
1 change: 1 addition & 0 deletions src/server/game/Scripting/ScriptMgr.h
Original file line number Diff line number Diff line change
Expand Up @@ -467,6 +467,7 @@ class ScriptMgr
void OnPlayerGetReputationPriceDiscount(Player const* player, Creature const* creature, float& discount);
void OnPlayerGetReputationPriceDiscount(Player const* player, FactionTemplateEntry const* factionTemplate, float& discount);
void OnPlayerLearnTaxiNode(Player const* player, uint32 nodeId);
void OnPlayerBeforeGetLevelForXPGain(Player const* player, uint8& level);

// Anti cheat
void AnticheatSetCanFlybyServer(Player* player, bool apply);
Expand Down
Loading