feat(Core/Scripting): Add OnPlayerBeforeGetLevelForXPGain hook (#25295)
This commit is contained in:
parent
0f2841ddcf
commit
cd3cccc961
9 changed files with 60 additions and 15 deletions
|
|
@ -67,7 +67,7 @@
|
||||||
KillRewarder::KillRewarder(Player* killer, Unit* victim, bool isBattleGround) :
|
KillRewarder::KillRewarder(Player* killer, Unit* victim, bool isBattleGround) :
|
||||||
// 1. Initialize internal variables to default values.
|
// 1. Initialize internal variables to default values.
|
||||||
_killer(killer), _victim(victim), _group(killer->GetGroup()),
|
_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)
|
_isFullXP(false), _maxLevel(0), _isBattleGround(isBattleGround), _isPvP(false)
|
||||||
{
|
{
|
||||||
// mark the credit as pvp if victim is player
|
// mark the credit as pvp if victim is player
|
||||||
|
|
@ -89,7 +89,7 @@ void KillRewarder::_InitGroupData()
|
||||||
if (Player* member = itr->GetSource())
|
if (Player* member = itr->GetSource())
|
||||||
if ((_killer == member || member->IsAtGroupRewardDistance(_victim)))
|
if ((_killer == member || member->IsAtGroupRewardDistance(_victim)))
|
||||||
{
|
{
|
||||||
const uint8 lvl = member->GetLevel();
|
const uint8 lvl = _GetPlayerLevel(member);
|
||||||
if (member->IsAlive())
|
if (member->IsAlive())
|
||||||
{
|
{
|
||||||
// 2.1. _count - number of alive group members within reward distance;
|
// 2.1. _count - number of alive group members within reward distance;
|
||||||
|
|
@ -104,9 +104,10 @@ void KillRewarder::_InitGroupData()
|
||||||
// 2.4. _maxNotGrayMember - maximum level of alive group member within reward distance,
|
// 2.4. _maxNotGrayMember - maximum level of alive group member within reward distance,
|
||||||
// for whom victim is not gray;
|
// for whom victim is not gray;
|
||||||
uint32 grayLevel = Acore::XP::GetGrayLevel(lvl);
|
uint32 grayLevel = Acore::XP::GetGrayLevel(lvl);
|
||||||
if (_victim->GetLevel() > grayLevel && (!_maxNotGrayMember || _maxNotGrayMember->GetLevel() < lvl))
|
if (_victim->GetLevel() > grayLevel && (!_maxNotGrayMember || _maxNotGrayMemberLevel < lvl))
|
||||||
{
|
{
|
||||||
_maxNotGrayMember = member;
|
_maxNotGrayMember = member;
|
||||||
|
_maxNotGrayMemberLevel = lvl;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
// 2.5. _sumLevel - sum of levels of group members within reward distance;
|
// 2.5. _sumLevel - sum of levels of group members within reward distance;
|
||||||
|
|
@ -114,7 +115,7 @@ void KillRewarder::_InitGroupData()
|
||||||
}
|
}
|
||||||
// 2.6. _isFullXP - flag identifying that for all group members victim is not gray,
|
// 2.6. _isFullXP - flag identifying that for all group members victim is not gray,
|
||||||
// so 100% XP will be rewarded (50% otherwise).
|
// so 100% XP will be rewarded (50% otherwise).
|
||||||
_isFullXP = _maxNotGrayMember && (_maxLevel == _maxNotGrayMember->GetLevel());
|
_isFullXP = _maxNotGrayMember && (_maxLevel == _maxNotGrayMemberLevel);
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
_count = 1;
|
_count = 1;
|
||||||
|
|
@ -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;
|
// * set to 0 if player's level is more than maximum level of not gray member;
|
||||||
// * cut XP in half if _isFullXP is false.
|
// * cut XP in half if _isFullXP is false.
|
||||||
if (_maxNotGrayMember && player->IsAlive() &&
|
if (_maxNotGrayMember && player->IsAlive() &&
|
||||||
_maxNotGrayMember->GetLevel() >= player->GetLevel())
|
_maxNotGrayMemberLevel >= _GetPlayerLevel(player))
|
||||||
xp = _isFullXP ?
|
xp = _isFullXP ?
|
||||||
uint32(xp * rate) : // Reward FULL XP if all group members are not gray.
|
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.
|
uint32(xp * rate / 2) + 1; // Reward only HALF of XP if some of group members are gray.
|
||||||
|
|
@ -208,8 +209,8 @@ void KillRewarder::_RewardPlayer(Player* player, bool isDungeon)
|
||||||
// Give reputation and kill credit only in PvE.
|
// Give reputation and kill credit only in PvE.
|
||||||
if (!_isPvP || _isBattleGround)
|
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.
|
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%.
|
sScriptMgr->OnPlayerRewardKillRewarder(player, this, isDungeon, xpRate); // Personal rate is 100%.
|
||||||
|
|
||||||
if (_xp)
|
if (_xp)
|
||||||
{
|
{
|
||||||
|
|
@ -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()
|
void KillRewarder::Reward()
|
||||||
{
|
{
|
||||||
// 3. Reward killer (and group, if necessary).
|
// 3. Reward killer (and group, if necessary).
|
||||||
|
|
|
||||||
|
|
@ -43,12 +43,14 @@ private:
|
||||||
void _RewardKillCredit(Player* player);
|
void _RewardKillCredit(Player* player);
|
||||||
void _RewardPlayer(Player* player, bool isDungeon);
|
void _RewardPlayer(Player* player, bool isDungeon);
|
||||||
void _RewardGroup();
|
void _RewardGroup();
|
||||||
|
uint8 _GetPlayerLevel(Player const* player);
|
||||||
|
|
||||||
Player* _killer;
|
Player* _killer;
|
||||||
Unit* _victim;
|
Unit* _victim;
|
||||||
Group* _group;
|
Group* _group;
|
||||||
float _groupRate;
|
float _groupRate;
|
||||||
Player* _maxNotGrayMember;
|
Player* _maxNotGrayMember;
|
||||||
|
uint8 _maxNotGrayMemberLevel;
|
||||||
uint32 _count;
|
uint32 _count;
|
||||||
uint32 _aliveSumLevel;
|
uint32 _aliveSumLevel;
|
||||||
uint32 _sumLevel;
|
uint32 _sumLevel;
|
||||||
|
|
|
||||||
|
|
@ -2370,6 +2370,7 @@ void Player::GiveXP(uint32 xp, Unit* victim, float group_rate, bool isLFGReward)
|
||||||
}
|
}
|
||||||
|
|
||||||
uint8 level = GetLevel();
|
uint8 level = GetLevel();
|
||||||
|
sScriptMgr->OnPlayerBeforeGetLevelForXPGain(this, level);
|
||||||
|
|
||||||
// Favored experience increase START
|
// Favored experience increase START
|
||||||
uint32 zone = GetZoneId();
|
uint32 zone = GetZoneId();
|
||||||
|
|
@ -5775,17 +5776,20 @@ void Player::CheckAreaExploreAndOutdoor()
|
||||||
|
|
||||||
if (areaEntry->area_level > 0)
|
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);
|
SendExplorationExperience(areaId, 0);
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
int32 diff = int32(GetLevel()) - areaEntry->area_level;
|
int32 diff = int32(playerLevel) - areaEntry->area_level;
|
||||||
uint32 XP = 0;
|
uint32 XP = 0;
|
||||||
if (diff < -5)
|
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)
|
else if (diff > 5)
|
||||||
{
|
{
|
||||||
|
|
|
||||||
|
|
@ -1435,8 +1435,11 @@ bool Player::TakeQuestSourceItem(uint32 questId, bool msg)
|
||||||
|
|
||||||
uint32 Player::CalculateQuestRewardXP(Quest const* quest)
|
uint32 Player::CalculateQuestRewardXP(Quest const* quest)
|
||||||
{
|
{
|
||||||
|
uint8 level = GetLevel();
|
||||||
|
sScriptMgr->OnPlayerBeforeGetLevelForXPGain(this, level);
|
||||||
|
|
||||||
// apply world quest rate
|
// 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
|
// handle SPELL_AURA_MOD_XP_QUEST_PCT auras
|
||||||
xp *= GetTotalAuraMultiplier(SPELL_AURA_MOD_XP_QUEST_PCT);
|
xp *= GetTotalAuraMultiplier(SPELL_AURA_MOD_XP_QUEST_PCT);
|
||||||
|
|
|
||||||
|
|
@ -23,6 +23,7 @@
|
||||||
#include "ObjectMgr.h"
|
#include "ObjectMgr.h"
|
||||||
#include "Opcodes.h"
|
#include "Opcodes.h"
|
||||||
#include "Player.h"
|
#include "Player.h"
|
||||||
|
#include "ScriptMgr.h"
|
||||||
#include "WorldPacket.h"
|
#include "WorldPacket.h"
|
||||||
#include "WorldSession.h"
|
#include "WorldSession.h"
|
||||||
|
|
||||||
|
|
@ -188,10 +189,13 @@ void WorldSession::HandleLfgPlayerLockInfoRequestOpcode(WorldPacket& /*recvData*
|
||||||
if (quest)
|
if (quest)
|
||||||
{
|
{
|
||||||
uint8 playerLevel = GetPlayer() ? GetPlayer()->GetLevel() : 0;
|
uint8 playerLevel = GetPlayer() ? GetPlayer()->GetLevel() : 0;
|
||||||
|
uint8 playerLevelForXP = playerLevel;
|
||||||
|
sScriptMgr->OnPlayerBeforeGetLevelForXPGain(GetPlayer(), playerLevelForXP);
|
||||||
|
|
||||||
data << uint8(done);
|
data << uint8(done);
|
||||||
data << uint32(quest->GetRewOrReqMoney(playerLevel));
|
data << uint32(quest->GetRewOrReqMoney(playerLevel));
|
||||||
if (!GetPlayer()->IsMaxLevel())
|
if (playerLevelForXP < GetPlayer()->GetUInt32Value(PLAYER_FIELD_MAX_LEVEL))
|
||||||
data << uint32(quest->XPValue(playerLevel));
|
data << uint32(quest->XPValue(playerLevelForXP));
|
||||||
else
|
else
|
||||||
data << uint32(0);
|
data << uint32(0);
|
||||||
data << uint32(0);
|
data << uint32(0);
|
||||||
|
|
@ -479,6 +483,8 @@ void WorldSession::SendLfgPlayerReward(lfg::LfgPlayerRewardData const& rewardDat
|
||||||
uint8 itemNum = rewardData.quest->GetRewItemsCount();
|
uint8 itemNum = rewardData.quest->GetRewItemsCount();
|
||||||
|
|
||||||
uint8 playerLevel = GetPlayer() ? GetPlayer()->GetLevel() : 0;
|
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));
|
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.rdungeonEntry); // Random Dungeon Finished
|
||||||
|
|
@ -486,7 +492,7 @@ void WorldSession::SendLfgPlayerReward(lfg::LfgPlayerRewardData const& rewardDat
|
||||||
data << uint8(rewardData.done);
|
data << uint8(rewardData.done);
|
||||||
data << uint32(1);
|
data << uint32(1);
|
||||||
data << uint32(rewardData.quest->GetRewOrReqMoney(playerLevel));
|
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 << uint32(0);
|
data << uint32(0);
|
||||||
data << uint8(itemNum);
|
data << uint8(itemNum);
|
||||||
|
|
|
||||||
|
|
@ -21,6 +21,7 @@
|
||||||
#include "Creature.h"
|
#include "Creature.h"
|
||||||
#include "Log.h"
|
#include "Log.h"
|
||||||
#include "Player.h"
|
#include "Player.h"
|
||||||
|
#include "ScriptMgr.h"
|
||||||
#include "World.h"
|
#include "World.h"
|
||||||
|
|
||||||
uint32 Acore::XP::BaseGain(uint8 pl_level, uint8 mob_level, ContentLevels content)
|
uint32 Acore::XP::BaseGain(uint8 pl_level, uint8 mob_level, ContentLevels content)
|
||||||
|
|
@ -79,7 +80,9 @@ uint32 Acore::XP::Gain(Player* player, Unit* unit, bool isBattleGround /*= false
|
||||||
{
|
{
|
||||||
float xpMod = 1.0f;
|
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)
|
if (gain && creature)
|
||||||
{
|
{
|
||||||
|
|
|
||||||
|
|
@ -18,6 +18,9 @@
|
||||||
#include "PlayerScript.h"
|
#include "PlayerScript.h"
|
||||||
#include "ScriptMgr.h"
|
#include "ScriptMgr.h"
|
||||||
#include "ScriptMgrMacros.h"
|
#include "ScriptMgrMacros.h"
|
||||||
|
#include "World.h"
|
||||||
|
|
||||||
|
#include <algorithm>
|
||||||
|
|
||||||
void ScriptMgr::OnPlayerBeforeDurabilityRepair(Player* player, ObjectGuid npcGUID, ObjectGuid itemGUID, float& discountMod, uint8 guildBank)
|
void ScriptMgr::OnPlayerBeforeDurabilityRepair(Player* player, ObjectGuid npcGUID, ObjectGuid itemGUID, float& discountMod, uint8 guildBank)
|
||||||
{
|
{
|
||||||
|
|
@ -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));
|
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)
|
PlayerScript::PlayerScript(const char* name, std::vector<uint16> enabledHooks)
|
||||||
: ScriptObject(name, PLAYERHOOK_END)
|
: ScriptObject(name, PLAYERHOOK_END)
|
||||||
{
|
{
|
||||||
|
|
|
||||||
|
|
@ -211,6 +211,7 @@ enum PlayerHook
|
||||||
PLAYERHOOK_ON_GIVE_REPUTATION,
|
PLAYERHOOK_ON_GIVE_REPUTATION,
|
||||||
PLAYERHOOK_ON_GET_REPUTATION_PRICE_DISCOUNT,
|
PLAYERHOOK_ON_GET_REPUTATION_PRICE_DISCOUNT,
|
||||||
PLAYERHOOK_ON_LEARN_TAXI_NODE,
|
PLAYERHOOK_ON_LEARN_TAXI_NODE,
|
||||||
|
PLAYERHOOK_ON_BEFORE_GET_LEVEL_FOR_XP_GAIN,
|
||||||
PLAYERHOOK_END
|
PLAYERHOOK_END
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
@ -829,6 +830,14 @@ public:
|
||||||
* @param nodeId The id of the learned taxi node
|
* @param nodeId The id of the learned taxi node
|
||||||
*/
|
*/
|
||||||
virtual void OnPlayerLearnTaxiNode(Player const* /*player*/, uint32 /*nodeId*/) {}
|
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
|
#endif
|
||||||
|
|
|
||||||
|
|
@ -467,6 +467,7 @@ public: /* PlayerScript */
|
||||||
void OnPlayerGetReputationPriceDiscount(Player const* player, Creature const* creature, float& discount);
|
void OnPlayerGetReputationPriceDiscount(Player const* player, Creature const* creature, float& discount);
|
||||||
void OnPlayerGetReputationPriceDiscount(Player const* player, FactionTemplateEntry const* factionTemplate, float& discount);
|
void OnPlayerGetReputationPriceDiscount(Player const* player, FactionTemplateEntry const* factionTemplate, float& discount);
|
||||||
void OnPlayerLearnTaxiNode(Player const* player, uint32 nodeId);
|
void OnPlayerLearnTaxiNode(Player const* player, uint32 nodeId);
|
||||||
|
void OnPlayerBeforeGetLevelForXPGain(Player const* player, uint8& level);
|
||||||
|
|
||||||
// Anti cheat
|
// Anti cheat
|
||||||
void AnticheatSetCanFlybyServer(Player* player, bool apply);
|
void AnticheatSetCanFlybyServer(Player* player, bool apply);
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue