diff --git a/src/server/game/Entities/Player/PlayerUpdates.cpp b/src/server/game/Entities/Player/PlayerUpdates.cpp index dcc77209d..fcf47d5c1 100644 --- a/src/server/game/Entities/Player/PlayerUpdates.cpp +++ b/src/server/game/Entities/Player/PlayerUpdates.cpp @@ -708,7 +708,7 @@ void Player::UpdateAllRatings() // skill+step, checking for max value bool Player::UpdateSkill(uint32 skill_id, uint32 step) { - if (!skill_id) + if (!skill_id || !sScriptMgr->CanPlayerUpdateSkill(this, skill_id)) return false; SkillStatusMap::iterator itr = mSkillStatus.find(skill_id); @@ -720,6 +720,8 @@ bool Player::UpdateSkill(uint32 skill_id, uint32 step) uint32 value = SKILL_VALUE(data); uint32 max = SKILL_MAX(data); + sScriptMgr->OnBeforePlayerUpdateSkill(this, skill_id, value, max, step); + if ((!max) || (!value) || (value >= max)) return false; @@ -736,6 +738,8 @@ bool Player::UpdateSkill(uint32 skill_id, uint32 step) UpdateSkillEnchantments(skill_id, value, new_value); UpdateAchievementCriteria(ACHIEVEMENT_CRITERIA_TYPE_REACH_SKILL_LEVEL, skill_id); + + sScriptMgr->OnPlayerUpdateSkill(this, skill_id, value, max, step, new_value); return true; } @@ -911,7 +915,7 @@ bool Player::UpdateSkillPro(uint16 SkillId, int32 Chance, uint32 step) LOG_DEBUG("entities.player.skills", "UpdateSkillPro(SkillId {}, Chance {:3.1f}%)", SkillId, Chance / 10.0f); - if (!SkillId) + if (!SkillId || !sScriptMgr->CanPlayerUpdateSkill(this, SkillId)) return false; if (Chance <= 0) // speedup in 0 chance case @@ -929,8 +933,10 @@ bool Player::UpdateSkillPro(uint16 SkillId, int32 Chance, uint32 step) uint32 valueIndex = PLAYER_SKILL_VALUE_INDEX(itr->second.pos); uint32 data = GetUInt32Value(valueIndex); - uint16 SkillValue = SKILL_VALUE(data); - uint16 MaxValue = SKILL_MAX(data); + uint32 SkillValue = SKILL_VALUE(data); + uint32 MaxValue = SKILL_MAX(data); + + sScriptMgr->OnBeforePlayerUpdateSkill(this, SkillId, SkillValue, MaxValue, step); if (!MaxValue || !SkillValue || SkillValue >= MaxValue) return false; @@ -962,6 +968,8 @@ bool Player::UpdateSkillPro(uint16 SkillId, int32 Chance, uint32 step) LOG_DEBUG("entities.player.skills", "Player::UpdateSkillPro Chance={:3.1f}% taken", Chance / 10.0f); + + sScriptMgr->OnPlayerUpdateSkill(this, SkillId, SkillValue, MaxValue, step, new_value); return true; } diff --git a/src/server/game/Scripting/ScriptDefines/PlayerScript.cpp b/src/server/game/Scripting/ScriptDefines/PlayerScript.cpp index 9d69dc3ba..78bea7872 100644 --- a/src/server/game/Scripting/ScriptDefines/PlayerScript.cpp +++ b/src/server/game/Scripting/ScriptDefines/PlayerScript.cpp @@ -895,6 +895,21 @@ bool ScriptMgr::AnticheatCheckMovementInfo(Player* player, MovementInfo const& m CALL_ENABLED_BOOLEAN_HOOKS(PlayerScript, PLAYERHOOK_ANTICHEAT_CHECK_MOVEMENT_INFO, !script->AnticheatCheckMovementInfo(player, movementInfo, mover, jump)); } +bool ScriptMgr::CanPlayerUpdateSkill(Player* player, uint32 skillId) +{ + CALL_ENABLED_BOOLEAN_HOOKS(PlayerScript, PLAYERHOOK_ON_CAN_UPDATE_SKILL, !script->CanPlayerUpdateSkill(player, skillId)); +} + +void ScriptMgr::OnBeforePlayerUpdateSkill(Player* player, uint32 skillId, uint32& value, uint32 max, uint32 step) +{ + CALL_ENABLED_HOOKS(PlayerScript, PLAYERHOOK_ON_BEFORE_UPDATE_SKILL, script->OnBeforePlayerUpdateSkill(player, skillId, value, max, step)); +} + +void ScriptMgr::OnPlayerUpdateSkill(Player* player, uint32 skillId, uint32 value, uint32 max, uint32 step, uint32 newValue) +{ + CALL_ENABLED_HOOKS(PlayerScript, PLAYERHOOK_ON_UPDATE_SKILL, script->OnPlayerUpdateSkill(player, skillId, value, max, step, newValue)); +} + bool ScriptMgr::CanPlayerResurrect(Player* player) { CALL_ENABLED_BOOLEAN_HOOKS(PlayerScript, PLAYERHOOK_CAN_RESURRECT, !script->CanPlayerResurrect(player)); diff --git a/src/server/game/Scripting/ScriptDefines/PlayerScript.h b/src/server/game/Scripting/ScriptDefines/PlayerScript.h index 3ffffadf9..1fee803df 100644 --- a/src/server/game/Scripting/ScriptDefines/PlayerScript.h +++ b/src/server/game/Scripting/ScriptDefines/PlayerScript.h @@ -204,6 +204,9 @@ enum PlayerHook PLAYERHOOK_CAN_SEND_ERROR_ALREADY_LOOTED, PLAYERHOOK_ON_AFTER_CREATURE_LOOT, PLAYERHOOK_ON_AFTER_CREATURE_LOOT_MONEY, + PLAYERHOOK_ON_CAN_UPDATE_SKILL, + PLAYERHOOK_ON_BEFORE_UPDATE_SKILL, + PLAYERHOOK_ON_UPDATE_SKILL, PLAYERHOOK_CAN_RESURRECT, PLAYERHOOK_END }; @@ -767,6 +770,10 @@ public: */ virtual void OnAfterCreatureLootMoney(Player* /*player*/) { } + virtual bool CanPlayerUpdateSkill(Player* /*player*/, uint32 /*skillId*/) { return true; } + virtual void OnBeforePlayerUpdateSkill(Player* /*player*/, uint32 /*skillId*/, uint32& /*value*/, uint32 /*max*/, uint32 /*step*/) { } + virtual void OnPlayerUpdateSkill(Player* /*player*/, uint32 /*skillId*/, uint32 /*value*/, uint32 /*max*/, uint32 /*step*/, uint32 /*newValue*/) { } + /** * @brief This hook is called, to avoid player resurrect * diff --git a/src/server/game/Scripting/ScriptMgr.h b/src/server/game/Scripting/ScriptMgr.h index 26159984b..b05d146f0 100644 --- a/src/server/game/Scripting/ScriptMgr.h +++ b/src/server/game/Scripting/ScriptMgr.h @@ -459,6 +459,9 @@ public: /* PlayerScript */ void OnAfterCreatureLoot(Player* player); void OnAfterCreatureLootMoney(Player* player); bool OnCanPlayerFlyInZone(Player* player, uint32 mapId, uint32 zoneId, SpellInfo const* bySpell); + bool CanPlayerUpdateSkill(Player* player, uint32 skillId); + void OnBeforePlayerUpdateSkill(Player* player, uint32 skill_id, uint32& value, uint32 max, uint32 step); + void OnPlayerUpdateSkill(Player* player, uint32 skillId, uint32 value, uint32 max, uint32 step, uint32 newValue); bool CanPlayerResurrect(Player* player); // Anti cheat