summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--src/cmake/ac_macros.cmake16
-rw-r--r--src/server/game/Achievements/AchievementMgr.cpp13
-rw-r--r--src/server/game/Battlegrounds/ArenaTeam.cpp111
-rw-r--r--src/server/game/Battlegrounds/ArenaTeam.h29
-rw-r--r--src/server/game/Battlegrounds/ArenaTeamMgr.cpp15
-rw-r--r--src/server/game/Battlegrounds/ArenaTeamMgr.h4
-rw-r--r--src/server/game/Battlegrounds/Battleground.cpp2
-rw-r--r--src/server/game/Battlegrounds/BattlegroundMgr.cpp74
-rw-r--r--src/server/game/Battlegrounds/BattlegroundMgr.h2
-rw-r--r--src/server/game/Battlegrounds/BattlegroundQueue.cpp42
-rw-r--r--src/server/game/Battlegrounds/BattlegroundQueue.h6
-rw-r--r--src/server/game/DungeonFinding/LFGMgr.cpp5
-rw-r--r--src/server/game/Entities/Creature/GossipDef.cpp6
-rw-r--r--src/server/game/Entities/Item/Item.cpp9
-rw-r--r--src/server/game/Entities/Object/Object.cpp4
-rw-r--r--src/server/game/Entities/Pet/Pet.cpp22
-rw-r--r--src/server/game/Entities/Player/Player.cpp277
-rw-r--r--src/server/game/Entities/Player/Player.h26
-rw-r--r--src/server/game/Entities/Unit/Unit.cpp30
-rw-r--r--src/server/game/Groups/Group.cpp8
-rw-r--r--src/server/game/Guilds/Guild.cpp3
-rw-r--r--src/server/game/Guilds/Guild.h3
-rw-r--r--src/server/game/Handlers/AuctionHouseHandler.cpp4
-rw-r--r--src/server/game/Handlers/BattleGroundHandler.cpp11
-rw-r--r--src/server/game/Handlers/GroupHandler.cpp7
-rw-r--r--src/server/game/Handlers/ItemHandler.cpp4
-rw-r--r--src/server/game/Handlers/MailHandler.cpp8
-rw-r--r--src/server/game/Handlers/NPCHandler.cpp2
-rw-r--r--src/server/game/Handlers/PetitionsHandler.cpp67
-rw-r--r--src/server/game/Handlers/SpellHandler.cpp11
-rw-r--r--src/server/game/Handlers/TradeHandler.cpp4
-rw-r--r--src/server/game/Instances/InstanceSaveMgr.cpp5
-rw-r--r--src/server/game/Loot/LootMgr.cpp2
-rw-r--r--src/server/game/Maps/MapManager.cpp4
-rw-r--r--src/server/game/Petitions/PetitionMgr.h11
-rw-r--r--src/server/game/Scripting/ScriptMgr.cpp912
-rw-r--r--src/server/game/Scripting/ScriptMgr.h449
-rw-r--r--src/server/game/Spells/Auras/SpellAuraEffects.cpp5
-rw-r--r--src/server/game/Spells/Spell.cpp41
-rw-r--r--src/server/game/Spells/Spell.h39
-rw-r--r--src/server/game/Spells/SpellInfo.cpp10
-rw-r--r--src/server/scripts/Commands/cs_misc.cpp2
-rw-r--r--src/server/scripts/Outland/BlackTemple/boss_mother_shahraz.cpp4
-rw-r--r--src/server/scripts/Outland/BlackTemple/illidari_council.cpp4
-rw-r--r--src/server/scripts/Pet/pet_generic.cpp4
-rw-r--r--src/server/scripts/Spells/spell_dk.cpp8
46 files changed, 2050 insertions, 275 deletions
diff --git a/src/cmake/ac_macros.cmake b/src/cmake/ac_macros.cmake
index 838210ed92..623fc30613 100644
--- a/src/cmake/ac_macros.cmake
+++ b/src/cmake/ac_macros.cmake
@@ -6,6 +6,22 @@ MACRO(AC_ADD_SCRIPT path)
ENDMACRO()
#
+# AC_ADD_SCRIPTS
+#
+# This macro can be used to automatically load scripts for the ScriptMgr
+# from a specified folder, instead of manually list them within the cmake
+# NOTE: you must still manually specify the script loader header
+#
+
+MACRO(AC_ADD_SCRIPTS path)
+CU_SUBDIRLIST(sub_DIRS ${path} TRUE TRUE)
+FOREACH(subdir ${sub_DIRS})
+ file(GLOB sources "${subdir}/*.cpp" "${subdir}/*.h")
+ CU_LIST_ADD_CACHE(scripts_STAT_SRCS "${sources}")
+ENDFOREACH()
+ENDMACRO()
+
+#
# AC_ADD_SCRIPT_LOADER
#
MACRO(AC_ADD_SCRIPT_LOADER script_dec include)
diff --git a/src/server/game/Achievements/AchievementMgr.cpp b/src/server/game/Achievements/AchievementMgr.cpp
index 07a3936f2d..d65587338c 100644
--- a/src/server/game/Achievements/AchievementMgr.cpp
+++ b/src/server/game/Achievements/AchievementMgr.cpp
@@ -828,6 +828,8 @@ void AchievementMgr::UpdateAchievementCriteria(AchievementCriteriaTypes type, ui
if (!achievementCriteriaList)
return;
+ sScriptMgr->OnBeforeCheckCriteria(this, achievementCriteriaList);
+
for (AchievementCriteriaEntryList::const_iterator i = achievementCriteriaList->begin(); i != achievementCriteriaList->end(); ++i)
{
AchievementCriteriaEntry const* achievementCriteria = (*i);
@@ -838,6 +840,9 @@ void AchievementMgr::UpdateAchievementCriteria(AchievementCriteriaTypes type, ui
if (!CanUpdateCriteria(achievementCriteria, achievement))
continue;
+ if (!sScriptMgr->CanCheckCriteria(this, achievementCriteria))
+ continue;
+
switch (type)
{
// std. case: increment at 1
@@ -1762,6 +1767,9 @@ bool AchievementMgr::IsCompletedCriteria(AchievementCriteriaEntry const* achieve
if (!progress)
return false;
+ if (!sScriptMgr->IsCompletedCriteria(this, achievementCriteria, achievement, progress))
+ return false;
+
switch (achievementCriteria->requiredType)
{
case ACHIEVEMENT_CRITERIA_TYPE_WIN_BG:
@@ -2394,6 +2402,9 @@ bool AchievementGlobalMgr::IsRealmCompleted(AchievementEntry const* achievement)
if (itr->second == std::chrono::system_clock::time_point::min())
return false;
+ if (!sScriptMgr->IsRealmCompleted(this, achievement, itr->second))
+ return false;
+
if (itr->second == std::chrono::system_clock::time_point::max())
return true;
@@ -2403,6 +2414,8 @@ bool AchievementGlobalMgr::IsRealmCompleted(AchievementEntry const* achievement)
if (achievement->flags & ACHIEVEMENT_FLAG_REALM_FIRST_KILL)
return (std::chrono::system_clock::now() - itr->second) > std::chrono::minutes(1);
+ sScriptMgr->SetRealmCompleted(achievement);
+
return true;
}
diff --git a/src/server/game/Battlegrounds/ArenaTeam.cpp b/src/server/game/Battlegrounds/ArenaTeam.cpp
index b0e2bbada8..09b83c3e7a 100644
--- a/src/server/game/Battlegrounds/ArenaTeam.cpp
+++ b/src/server/game/Battlegrounds/ArenaTeam.cpp
@@ -101,6 +101,9 @@ bool ArenaTeam::AddMember(uint64 playerGuid)
playerClass = playerData->playerClass;
}
+ if (!sScriptMgr->CanAddMember(this, playerGuid))
+ return false;
+
// Check if player is already in a similar arena team
if ((player && player->GetArenaTeamId(GetSlot())) || Player::GetArenaTeamIdFromStorage(GUID_LOPART(playerGuid), GetSlot()) != 0)
{
@@ -610,27 +613,24 @@ void ArenaTeam::MassInviteToEvent(WorldSession* session)
uint8 ArenaTeam::GetSlotByType(uint32 type)
{
uint8 slot = 0xFF;
- switch (type)
+
+ auto const& itr = ArenaSlotByType.find(type);
+ if (itr == ArenaSlotByType.end())
{
- case ARENA_TEAM_2v2:
- slot = 0;
- break;
- case ARENA_TEAM_3v3:
- slot = 1;
- break;
- case ARENA_TEAM_5v5:
- slot = 2;
- break;
- default:
- break;
+ sLog->outError("FATAL: Unknown arena team type %u for some arena team", type);
+ return slot;
}
- //Get the changed slot type
+
+ slot = ArenaSlotByType.at(type);
+
+ // Get the changed slot type
sScriptMgr->OnGetSlotByType(type, slot);
if (slot != 0xFF)
{
return slot;
}
+
sLog->outError("FATAL: Unknown arena team type %u for some arena team", type);
return 0xFF;
}
@@ -868,12 +868,14 @@ void ArenaTeam::MemberWon(Player* player, uint32 againstMatchmakerRating, int32
{
// update personal rating
int32 mod = GetRatingMod(itr->PersonalRating, againstMatchmakerRating, true);
+ sScriptMgr->OnBeforeUpdatingPersonalRating(mod, GetType());
itr->ModifyPersonalRating(player, mod, GetType());
// update matchmaker rating (pussywizard: but don't allow it to go over team rating)
if (itr->MatchMakerRating < Stats.Rating)
{
mod = std::min(MatchmakerRatingChange, Stats.Rating - itr->MatchMakerRating);
+ sScriptMgr->OnBeforeUpdatingPersonalRating(mod, GetType());
itr->ModifyMatchmakerRating(mod, GetSlot());
}
@@ -922,6 +924,9 @@ void ArenaTeam::UpdateArenaPointsHelper(std::map<uint32, uint32>& playerPoints)
void ArenaTeam::SaveToDB()
{
+ if (!sScriptMgr->CanSaveToDB(this))
+ return;
+
// Save team and member stats to db
// Called after a match has ended or when calculating arena_points
@@ -997,3 +1002,83 @@ ArenaTeamMember* ArenaTeam::GetMember(uint64 guid)
return nullptr;
}
+
+uint8 ArenaTeam::GetReqPlayersForType(uint32 type)
+{
+ auto const& itr = ArenaReqPlayersForType.find(type);
+ if (itr == ArenaReqPlayersForType.end())
+ {
+ sLog->outError("FATAL: Unknown arena type %u!", type);
+ return 0xFF;
+ }
+
+ return ArenaReqPlayersForType.at(type);
+}
+
+void ArenaTeam::CreateTempArenaTeam(std::vector<Player*> playerList, uint8 type, std::string const& teamName)
+{
+ auto playerCountInTeam = static_cast<uint32>(playerList.size());
+
+ ASSERT(playerCountInTeam == GetReqPlayersForType(type));
+
+ // Generate new arena team id
+ TeamId = sArenaTeamMgr->GenerateTempArenaTeamId();
+
+ // Assign member variables
+ CaptainGuid = playerList[0]->GetGUID();
+ Type = type;
+ TeamName = teamName;
+
+ BackgroundColor = 0;
+ EmblemStyle = 0;
+ EmblemColor = 0;
+ BorderStyle = 0;
+ BorderColor = 0;
+
+ Stats.WeekGames = 0;
+ Stats.SeasonGames = 0;
+ Stats.Rating = 0;
+ Stats.WeekWins = 0;
+ Stats.SeasonWins = 0;
+
+ for (auto const& _player : playerList)
+ {
+ ArenaTeam* team = sArenaTeamMgr->GetArenaTeamById(_player->GetArenaTeamId(GetSlotByType(type)));
+ if (!team)
+ continue;
+
+ ArenaTeamMember newMember;
+ for (auto const& itr : Members)
+ newMember = itr;
+
+ Stats.WeekGames += team->Stats.WeekGames;
+ Stats.SeasonGames += team->Stats.SeasonGames;
+ Stats.Rating += team->GetRating();
+ Stats.WeekWins += team->Stats.WeekWins;
+ Stats.SeasonWins += team->Stats.SeasonWins;
+
+ Members.push_back(newMember);
+ }
+
+ Stats.WeekGames /= playerCountInTeam;
+ Stats.SeasonGames /= playerCountInTeam;
+ Stats.Rating /= playerCountInTeam;
+ Stats.WeekWins /= playerCountInTeam;
+ Stats.SeasonWins /= playerCountInTeam;
+}
+
+// init/update unordered_map ArenaSlotByType
+std::unordered_map<uint32, uint8> ArenaTeam::ArenaSlotByType =
+{
+ { ARENA_TEAM_2v2, ARENA_SLOT_2v2},
+ { ARENA_TEAM_3v3, ARENA_SLOT_3v3},
+ { ARENA_TEAM_5v5, ARENA_SLOT_5v5}
+};
+
+// init/update unordered_map ArenaReqPlayersForType
+std::unordered_map<uint8, uint8> ArenaTeam::ArenaReqPlayersForType =
+{
+ { ARENA_TYPE_2v2, 4},
+ { ARENA_TYPE_3v3, 6},
+ { ARENA_TYPE_5v5, 10}
+};
diff --git a/src/server/game/Battlegrounds/ArenaTeam.h b/src/server/game/Battlegrounds/ArenaTeam.h
index 3bd6ec29c1..2fd3c9d5bd 100644
--- a/src/server/game/Battlegrounds/ArenaTeam.h
+++ b/src/server/game/Battlegrounds/ArenaTeam.h
@@ -58,6 +58,19 @@ enum ArenaTeamEvents
ERR_ARENA_TEAM_DISBANDED_S = 8 // captain name + arena team name
};
+// PLAYER_FIELD_ARENA_TEAM_INFO_1_1 offsets
+enum ArenaTeamInfoType
+{
+ ARENA_TEAM_ID = 0,
+ ARENA_TEAM_TYPE = 1, // new in 3.2 - team type?
+ ARENA_TEAM_MEMBER = 2, // 0 - captain, 1 - member
+ ARENA_TEAM_GAMES_WEEK = 3,
+ ARENA_TEAM_GAMES_SEASON = 4,
+ ARENA_TEAM_WINS_SEASON = 5,
+ ARENA_TEAM_PERSONAL_RATING = 6,
+ ARENA_TEAM_END = 7
+};
+
/*
need info how to send these ones:
ERR_ARENA_TEAM_YOU_JOIN_S - client show it automatically when accept invite
@@ -73,6 +86,13 @@ enum ArenaTeamTypes
ARENA_TEAM_5v5 = 5
};
+enum ArenaSlot
+{
+ ARENA_SLOT_2v2,
+ ARENA_SLOT_3v3,
+ ARENA_SLOT_5v5
+};
+
struct ArenaTeamMember
{
uint64 Guid;
@@ -118,9 +138,11 @@ public:
[[nodiscard]] uint32 GetType() const { return Type; }
[[nodiscard]] uint8 GetSlot() const { return GetSlotByType(GetType()); }
static uint8 GetSlotByType(uint32 type);
+ static uint8 GetReqPlayersForType(uint32 type);
[[nodiscard]] uint64 GetCaptain() const { return CaptainGuid; }
[[nodiscard]] std::string const& GetName() const { return TeamName; }
[[nodiscard]] const ArenaTeamStats& GetStats() const { return Stats; }
+ void SetArenaTeamStats(ArenaTeamStats& stats) { Stats = stats; }
[[nodiscard]] uint32 GetRating() const { return Stats.Rating; }
uint32 GetAverageMMR(Group* group) const;
@@ -137,6 +159,7 @@ public:
[[nodiscard]] bool Empty() const { return Members.empty(); }
MemberList::iterator m_membersBegin() { return Members.begin(); }
MemberList::iterator m_membersEnd() { return Members.end(); }
+ MemberList& GetMembers() { return Members; }
[[nodiscard]] bool IsMember(uint64 guid) const;
ArenaTeamMember* GetMember(uint64 guid);
@@ -174,6 +197,12 @@ public:
void FinishWeek();
void FinishGame(int32 mod, const Map* bgMap);
+ void CreateTempArenaTeam(std::vector<Player*> playerList, uint8 type, std::string const& teamName);
+
+ // Containers
+ static std::unordered_map<uint32, uint8> ArenaSlotByType; // Slot -> Type
+ static std::unordered_map<uint8, uint8> ArenaReqPlayersForType; // Type -> Players count
+
protected:
uint32 TeamId;
uint8 Type;
diff --git a/src/server/game/Battlegrounds/ArenaTeamMgr.cpp b/src/server/game/Battlegrounds/ArenaTeamMgr.cpp
index 8a0015f11f..770b8655e6 100644
--- a/src/server/game/Battlegrounds/ArenaTeamMgr.cpp
+++ b/src/server/game/Battlegrounds/ArenaTeamMgr.cpp
@@ -14,10 +14,14 @@
#include "ScriptMgr.h"
#include "World.h"
+constexpr uint32 MAX_ARENA_TEAM_ID = 0xFFF00000;
+constexpr uint32 MAX_TEMP_ARENA_TEAM_ID = 0xFFFFFFFE;
+
ArenaTeamMgr::ArenaTeamMgr()
{
NextArenaTeamId = 1;
LastArenaLogId = 0;
+ NextTempArenaTeamId = 0xFFF00000;
}
ArenaTeamMgr::~ArenaTeamMgr()
@@ -114,14 +118,23 @@ void ArenaTeamMgr::RemoveArenaTeam(uint32 arenaTeamId)
uint32 ArenaTeamMgr::GenerateArenaTeamId()
{
- if (NextArenaTeamId >= 0xFFFFFFFE)
+ if (NextArenaTeamId >= MAX_ARENA_TEAM_ID)
{
sLog->outError("Arena team ids overflow!! Can't continue, shutting down server. ");
World::StopNow(ERROR_EXIT_CODE);
}
+
return NextArenaTeamId++;
}
+uint32 ArenaTeamMgr::GenerateTempArenaTeamId()
+{
+ if (NextTempArenaTeamId >= MAX_TEMP_ARENA_TEAM_ID)
+ NextTempArenaTeamId = MAX_ARENA_TEAM_ID;
+
+ return NextTempArenaTeamId++;
+}
+
void ArenaTeamMgr::LoadArenaTeams()
{
uint32 oldMSTime = getMSTime();
diff --git a/src/server/game/Battlegrounds/ArenaTeamMgr.h b/src/server/game/Battlegrounds/ArenaTeamMgr.h
index 6195cf822c..b2363b9b81 100644
--- a/src/server/game/Battlegrounds/ArenaTeamMgr.h
+++ b/src/server/game/Battlegrounds/ArenaTeamMgr.h
@@ -31,6 +31,7 @@ public:
ArenaTeamContainer::iterator GetArenaTeamMapBegin() { return ArenaTeamStore.begin(); }
ArenaTeamContainer::iterator GetArenaTeamMapEnd() { return ArenaTeamStore.end(); }
+ ArenaTeamContainer& GetArenaTeams() { return ArenaTeamStore; }
void DistributeArenaPoints();
@@ -40,8 +41,11 @@ public:
uint32 GetNextArenaLogId() { return ++LastArenaLogId; }
void SetLastArenaLogId(uint32 id) { LastArenaLogId = id; }
+ uint32 GenerateTempArenaTeamId();
+
protected:
uint32 NextArenaTeamId;
+ uint32 NextTempArenaTeamId;
ArenaTeamContainer ArenaTeamStore;
uint32 LastArenaLogId;
};
diff --git a/src/server/game/Battlegrounds/Battleground.cpp b/src/server/game/Battlegrounds/Battleground.cpp
index 5fed74091f..16311747f4 100644
--- a/src/server/game/Battlegrounds/Battleground.cpp
+++ b/src/server/game/Battlegrounds/Battleground.cpp
@@ -1382,7 +1382,7 @@ void Battleground::ReadyMarkerClicked(Player* p)
return;
readyMarkerClickedSet.insert(p->GetGUIDLow());
uint32 count = readyMarkerClickedSet.size();
- uint32 req = GetArenaType() * 2;
+ uint32 req = ArenaTeam::GetReqPlayersForType(GetArenaType());
p->GetSession()->SendNotification("You are marked as ready %u/%u", count, req);
if (count == req)
{
diff --git a/src/server/game/Battlegrounds/BattlegroundMgr.cpp b/src/server/game/Battlegrounds/BattlegroundMgr.cpp
index 38afda5c8b..f8402de489 100644
--- a/src/server/game/Battlegrounds/BattlegroundMgr.cpp
+++ b/src/server/game/Battlegrounds/BattlegroundMgr.cpp
@@ -468,19 +468,7 @@ Battleground* BattlegroundMgr::CreateNewBattleground(BattlegroundTypeId original
// Set up correct min/max player counts for scoreboards
if (bg->isArena())
{
- uint32 maxPlayersPerTeam = 0;
- switch (arenaType)
- {
- case ARENA_TYPE_2v2:
- maxPlayersPerTeam = 2;
- break;
- case ARENA_TYPE_3v3:
- maxPlayersPerTeam = 3;
- break;
- case ARENA_TYPE_5v5:
- maxPlayersPerTeam = 5;
- break;
- }
+ uint32 maxPlayersPerTeam = ArenaTeam::GetReqPlayersForType(arenaType) / 2;
sScriptMgr->OnSetArenaMaxPlayersPerTeam(arenaType, maxPlayersPerTeam);
bg->SetMaxPlayersPerTeam(maxPlayersPerTeam);
}
@@ -748,31 +736,24 @@ bool BattlegroundMgr::IsArenaType(BattlegroundTypeId bgTypeId)
BattlegroundQueueTypeId BattlegroundMgr::BGQueueTypeId(BattlegroundTypeId bgTypeId, uint8 arenaType)
{
- if (arenaType) {
- uint32 queueTypeID = BATTLEGROUND_QUEUE_NONE;
- switch (arenaType) {
- case ARENA_TYPE_2v2:
- queueTypeID = BATTLEGROUND_QUEUE_2v2;
- break;
- case ARENA_TYPE_3v3:
- queueTypeID = BATTLEGROUND_QUEUE_3v3;
- break;
- case ARENA_TYPE_5v5:
- queueTypeID = BATTLEGROUND_QUEUE_5v5;
- break;
- default:
- break;
+ uint32 queueTypeID = BATTLEGROUND_QUEUE_NONE;
+
+ if (arenaType)
+ {
+ if (BattlegroundMgr::ArenaTypeToQueue.find(arenaType) != BattlegroundMgr::ArenaTypeToQueue.end())
+ {
+ queueTypeID = BattlegroundMgr::ArenaTypeToQueue.at(arenaType);
}
+
sScriptMgr->OnArenaTypeIDToQueueID(bgTypeId, arenaType, queueTypeID);
- return BattlegroundQueueTypeId(queueTypeID);
}
- if (BattlegroundMgr::bgToQueue.find(bgTypeId) == BattlegroundMgr::bgToQueue.end())
+ if (BattlegroundMgr::bgToQueue.find(bgTypeId) != BattlegroundMgr::bgToQueue.end())
{
- return BATTLEGROUND_QUEUE_NONE;
+ queueTypeID = BattlegroundMgr::bgToQueue.at(bgTypeId);
}
- return BattlegroundMgr::bgToQueue[bgTypeId];
+ return static_cast<BattlegroundQueueTypeId>(queueTypeID);
}
BattlegroundTypeId BattlegroundMgr::BGTemplateId(BattlegroundQueueTypeId bgQueueTypeId)
@@ -788,21 +769,14 @@ BattlegroundTypeId BattlegroundMgr::BGTemplateId(BattlegroundQueueTypeId bgQueue
uint8 BattlegroundMgr::BGArenaType(BattlegroundQueueTypeId bgQueueTypeId)
{
uint8 arenaType = 0;
- switch (bgQueueTypeId)
+
+ if (BattlegroundMgr::QueueToArenaType.find(bgQueueTypeId) != BattlegroundMgr::QueueToArenaType.end())
{
- case BATTLEGROUND_QUEUE_2v2:
- arenaType = ARENA_TYPE_2v2;
- break;
- case BATTLEGROUND_QUEUE_3v3:
- arenaType = ARENA_TYPE_3v3;
- break;
- case BATTLEGROUND_QUEUE_5v5:
- arenaType = ARENA_TYPE_5v5;
- break;
- default:
- break;
+ arenaType = BattlegroundMgr::QueueToArenaType.at(bgQueueTypeId);
}
+
sScriptMgr->OnArenaQueueIdToArenaType(bgQueueTypeId, arenaType);
+
return arenaType;
}
@@ -1166,3 +1140,17 @@ std::unordered_map<int, bgTypeRef> BattlegroundMgr::getBgFromTypeID =
}
}
};
+
+std::unordered_map<uint32, BattlegroundQueueTypeId> BattlegroundMgr::ArenaTypeToQueue =
+{
+ { ARENA_TYPE_2v2, BATTLEGROUND_QUEUE_2v2 },
+ { ARENA_TYPE_3v3, BATTLEGROUND_QUEUE_3v3 },
+ { ARENA_TYPE_5v5, BATTLEGROUND_QUEUE_5v5 }
+};
+
+std::unordered_map<uint32, ArenaType> BattlegroundMgr::QueueToArenaType =
+{
+ { BATTLEGROUND_QUEUE_2v2, ARENA_TYPE_2v2 },
+ { BATTLEGROUND_QUEUE_3v3, ARENA_TYPE_3v3 },
+ { BATTLEGROUND_QUEUE_5v5, ARENA_TYPE_5v5 }
+};
diff --git a/src/server/game/Battlegrounds/BattlegroundMgr.h b/src/server/game/Battlegrounds/BattlegroundMgr.h
index 350b26c130..7eb9d7ae65 100644
--- a/src/server/game/Battlegrounds/BattlegroundMgr.h
+++ b/src/server/game/Battlegrounds/BattlegroundMgr.h
@@ -127,6 +127,8 @@ public:
static std::unordered_map<int, bgRef> bgTypeToTemplate; // BattlegroundTypeId -> bgRef
static std::unordered_map<int, bgMapRef> getBgFromMap; // BattlegroundMapID -> bgMapRef
static std::unordered_map<int, bgTypeRef> getBgFromTypeID; // BattlegroundTypeID -> bgTypeRef
+ static std::unordered_map<uint32, BattlegroundQueueTypeId> ArenaTypeToQueue; // ArenaType -> BattlegroundQueueTypeId
+ static std::unordered_map<uint32, ArenaType> QueueToArenaType; // BattlegroundQueueTypeId -> ArenaType
private:
bool CreateBattleground(CreateBattlegroundData& data);
diff --git a/src/server/game/Battlegrounds/BattlegroundQueue.cpp b/src/server/game/Battlegrounds/BattlegroundQueue.cpp
index 3e870dc0d1..9dee21b767 100644
--- a/src/server/game/Battlegrounds/BattlegroundQueue.cpp
+++ b/src/server/game/Battlegrounds/BattlegroundQueue.cpp
@@ -152,9 +152,7 @@ GroupQueueInfo* BattlegroundQueue::AddGroup(Player* leader, Group* grp, PvPDiffi
ginfo->_groupType = index;
// announce world (this doesn't need mutex)
- if (isRated && sWorld->getBoolConfig(CONFIG_ARENA_QUEUE_ANNOUNCER_ENABLE))
- if (ArenaTeam* team = sArenaTeamMgr->GetArenaTeamById(arenateamid))
- sWorld->SendWorldText(LANG_ARENA_QUEUE_ANNOUNCE_WORLD_JOIN, team->GetName().c_str(), ginfo->ArenaType, ginfo->ArenaType, ginfo->ArenaTeamRating);
+ SendMessageArenaQueue(ginfo, true);
//add players from group to ginfo
if (grp)
@@ -185,7 +183,7 @@ GroupQueueInfo* BattlegroundQueue::AddGroup(Player* leader, Group* grp, PvPDiffi
return ginfo;
if (!isRated && !isPremade && sWorld->getBoolConfig(CONFIG_BATTLEGROUND_QUEUE_ANNOUNCER_ENABLE))
- SendMessageQueue(leader, bg, bracketEntry);
+ SendMessageBGQueue(leader, bg, bracketEntry);
return ginfo;
}
@@ -298,9 +296,7 @@ void BattlegroundQueue::RemovePlayer(uint64 guid, bool sentToBg, uint32 playerQu
m_QueuedPlayers.erase(itr);
// announce to world if arena team left queue for rated match, show only once
- if (groupInfo->ArenaType && groupInfo->IsRated && groupInfo->Players.empty() && sWorld->getBoolConfig(CONFIG_ARENA_QUEUE_ANNOUNCER_ENABLE))
- if (ArenaTeam* team = sArenaTeamMgr->GetArenaTeamById(groupInfo->ArenaTeamId))
- sWorld->SendWorldText(LANG_ARENA_QUEUE_ANNOUNCE_WORLD_EXIT, team->GetName().c_str(), groupInfo->ArenaType, groupInfo->ArenaType, groupInfo->ArenaTeamRating);
+ SendMessageArenaQueue(groupInfo, false);
// if player leaves queue and he is invited to a rated arena match, then count it as he lost
if (groupInfo->IsInvitedToBGInstanceGUID && groupInfo->IsRated && !sentToBg)
@@ -726,6 +722,8 @@ void BattlegroundQueue::BattlegroundQueueUpdate(BattlegroundBracketId bracket_id
MaxPlayersPerTeam = m_arenaType;
}
+ sScriptMgr->OnQueueUpdate(this, bracket_id, isRated, arenaRatedTeamId);
+
// check if can start new premade battleground
if (bg_template->isBattleground() && m_bgTypeId != BATTLEGROUND_RB)
if (CheckPremadeMatch(bracket_id, MinPlayersPerTeam, MaxPlayersPerTeam))
@@ -963,9 +961,9 @@ bool BattlegroundQueue::IsAllQueuesEmpty(BattlegroundBracketId bracket_id)
return queueEmptyCount == BG_QUEUE_MAX;
}
-void BattlegroundQueue::SendMessageQueue(Player* leader, Battleground* bg, PvPDifficultyEntry const* bracketEntry)
+void BattlegroundQueue::SendMessageBGQueue(Player* leader, Battleground* bg, PvPDifficultyEntry const* bracketEntry)
{
- if (!sScriptMgr->CanSendMessageQueue(this, leader, bg, bracketEntry))
+ if (!sScriptMgr->CanSendMessageBGQueue(this, leader, bg, bracketEntry))
return;
BattlegroundBracketId bracketId = bracketEntry->GetBracketId();
@@ -1004,6 +1002,32 @@ void BattlegroundQueue::SendMessageQueue(Player* leader, Battleground* bg, PvPDi
}
}
+void BattlegroundQueue::SendMessageArenaQueue(GroupQueueInfo* ginfo, bool IsJoin)
+{
+ if (!sWorld->getBoolConfig(CONFIG_ARENA_QUEUE_ANNOUNCER_ENABLE))
+ return;
+
+ if (!sScriptMgr->CanSendMessageArenaQueue(this, ginfo, IsJoin))
+ return;
+
+ ArenaTeam* team = sArenaTeamMgr->GetArenaTeamById(ginfo->ArenaTeamId);
+ if (!team)
+ return;
+
+ if (!ginfo->IsRated)
+ return;
+
+ uint8 ArenaType = ginfo->ArenaType;
+ uint32 ArenaTeamRating = ginfo->ArenaTeamRating;
+ std::string TeamName = team->GetName();
+
+ if (IsJoin)
+ sWorld->SendWorldText(LANG_ARENA_QUEUE_ANNOUNCE_WORLD_JOIN, TeamName.c_str(), ArenaType, ArenaType, ArenaTeamRating);
+
+ if (!IsJoin && ArenaType && ginfo->Players.empty())
+ sWorld->SendWorldText(LANG_ARENA_QUEUE_ANNOUNCE_WORLD_EXIT, TeamName.c_str(), ArenaType, ArenaType, ArenaTeamRating);
+}
+
/*********************************************************/
/*** BATTLEGROUND QUEUE EVENTS ***/
/*********************************************************/
diff --git a/src/server/game/Battlegrounds/BattlegroundQueue.h b/src/server/game/Battlegrounds/BattlegroundQueue.h
index d755426545..4e6ec9d5fb 100644
--- a/src/server/game/Battlegrounds/BattlegroundQueue.h
+++ b/src/server/game/Battlegrounds/BattlegroundQueue.h
@@ -71,7 +71,8 @@ public:
uint32 GetAverageQueueWaitTime(GroupQueueInfo* ginfo) const;
uint32 GetPlayersCountInGroupsQueue(BattlegroundBracketId bracketId, BattlegroundQueueGroupTypes bgqueue);
bool IsAllQueuesEmpty(BattlegroundBracketId bracket_id);
- void SendMessageQueue(Player* leader, Battleground* bg, PvPDifficultyEntry const* bracketEntry);
+ void SendMessageBGQueue(Player* leader, Battleground* bg, PvPDifficultyEntry const* bracketEntry);
+ void SendMessageArenaQueue(GroupQueueInfo* ginfo, bool IsJoin);
void SetBgTypeIdAndArenaType(BattlegroundTypeId b, uint8 a) { m_bgTypeId = b; m_arenaType = ArenaType(a); } // pussywizard
void AddEvent(BasicEvent* Event, uint64 e_time);
@@ -110,6 +111,9 @@ public:
//one selection pool for horde, other one for alliance
SelectionPool m_SelectionPools[BG_TEAMS_COUNT];
+
+ ArenaType GetArenaType() { return m_arenaType; }
+ BattlegroundTypeId GetBGTypeID() { return m_bgTypeId; }
private:
BattlegroundTypeId m_bgTypeId;
ArenaType m_arenaType;
diff --git a/src/server/game/DungeonFinding/LFGMgr.cpp b/src/server/game/DungeonFinding/LFGMgr.cpp
index 89a659e740..3bfd1b7823 100644
--- a/src/server/game/DungeonFinding/LFGMgr.cpp
+++ b/src/server/game/DungeonFinding/LFGMgr.cpp
@@ -456,7 +456,7 @@ namespace lfg
}
}
- sScriptMgr->OnInitializeLockedDungeons(player, level, lockData);
+ sScriptMgr->OnInitializeLockedDungeons(player, level, lockData, dungeon);
/* TODO VoA closed if WG is not under team control (LFG_LOCKSTATUS_RAID_LOCKED)
lockData = LFG_LOCKSTATUS_TOO_LOW_GEAR_SCORE;
@@ -500,6 +500,9 @@ namespace lfg
if (grp && (grp->isBGGroup() || grp->isBFGroup()))
return;
+ if (!sScriptMgr->CanJoinLfg(player, roles, dungeons, comment))
+ return;
+
// pussywizard: can't join LFG/LFR while using LFR
if (GetState(player->GetGUID()) == LFG_STATE_RAIDBROWSER)
{
diff --git a/src/server/game/Entities/Creature/GossipDef.cpp b/src/server/game/Entities/Creature/GossipDef.cpp
index cb49e7f47d..d9a498cb4b 100644
--- a/src/server/game/Entities/Creature/GossipDef.cpp
+++ b/src/server/game/Entities/Creature/GossipDef.cpp
@@ -11,6 +11,8 @@
#include "QuestDef.h"
#include "WorldPacket.h"
#include "WorldSession.h"
+#include "Formulas.h"
+#include "Player.h"
GossipMenu::GossipMenu()
{
@@ -420,7 +422,7 @@ void PlayerMenu::SendQuestGiverQuestDetails(Quest const* quest, uint64 npcGUID,
}
data << uint32(quest->GetRewOrReqMoney());
- data << uint32(quest->XPValue(_session->GetPlayer()) * sWorld->getRate(RATE_XP_QUEST));
+ data << uint32(quest->XPValue(_session->GetPlayer()) * _session->GetPlayer()->GetQuestRate());
}
// rewarded honor points. Multiply with 10 to satisfy client
@@ -650,7 +652,7 @@ void PlayerMenu::SendQuestGiverOfferReward(Quest const* quest, uint64 npcGUID, b
}
data << uint32(quest->GetRewOrReqMoney());
- data << uint32(quest->XPValue(_session->GetPlayer()) * sWorld->getRate(RATE_XP_QUEST));
+ data << uint32(quest->XPValue(_session->GetPlayer()) * _session->GetPlayer()->GetQuestRate());
// rewarded honor points. Multiply with 10 to satisfy client
data << uint32(10 * quest->CalculateHonorGain(_session->GetPlayer()->GetQuestLevel(quest)));
diff --git a/src/server/game/Entities/Item/Item.cpp b/src/server/game/Entities/Item/Item.cpp
index bd9185ba07..246c5353ba 100644
--- a/src/server/game/Entities/Item/Item.cpp
+++ b/src/server/game/Entities/Item/Item.cpp
@@ -91,7 +91,11 @@ void AddItemsSetItem(Player* player, Item* item)
}
// spell casted only if fit form requirement, in other case will casted at form change
- player->ApplyEquipSpell(spellInfo, nullptr, true);
+ if (sScriptMgr->CanItemApplyEquipSpell(player, item))
+ {
+ player->ApplyEquipSpell(spellInfo, nullptr, true);
+ }
+
eff->spells[y] = spellInfo;
break;
}
@@ -266,6 +270,7 @@ bool Item::Create(uint32 guidlow, uint32 itemid, Player const* owner)
SetUInt32Value(ITEM_FIELD_DURATION, itemProto->Duration);
SetUInt32Value(ITEM_FIELD_CREATE_PLAYED_TIME, 0);
+ sScriptMgr->OnItemCreate(this, itemProto, owner);
return true;
}
@@ -423,7 +428,7 @@ bool Item::LoadFromDB(uint32 guid, uint64 owner_guid, Field* fields, uint32 entr
SetUInt32Value(ITEM_FIELD_FLAGS, fields[5].GetUInt32());
// Remove bind flag for items vs NO_BIND set
- if (IsSoulBound() && proto->Bonding == NO_BIND)
+ if (IsSoulBound() && proto->Bonding == NO_BIND && sScriptMgr->CanApplySoulboundFlag(this, proto))
{
ApplyModFlag(ITEM_FIELD_FLAGS, ITEM_FIELD_FLAG_SOULBOUND, false);
need_save = true;
diff --git a/src/server/game/Entities/Object/Object.cpp b/src/server/game/Entities/Object/Object.cpp
index ba1677de7e..d535ac571f 100644
--- a/src/server/game/Entities/Object/Object.cpp
+++ b/src/server/game/Entities/Object/Object.cpp
@@ -87,6 +87,8 @@ Object::Object() : m_PackGUID(sizeof(uint64) + 1)
m_objectUpdated = false;
m_PackGUID.appendPackGUID(0);
+
+ sScriptMgr->OnConstructObject(this);
}
WorldObject::~WorldObject()
@@ -110,6 +112,8 @@ WorldObject::~WorldObject()
Object::~Object()
{
+ sScriptMgr->OnDestructObject(this);
+
if (IsInWorld())
{
sLog->outCrash("Object::~Object - guid=" UI64FMTD ", typeid=%d, entry=%u deleted but still in world!!", GetGUID(), GetTypeId(), GetEntry());
diff --git a/src/server/game/Entities/Pet/Pet.cpp b/src/server/game/Entities/Pet/Pet.cpp
index a968352744..ffbe5bf1f1 100644
--- a/src/server/game/Entities/Pet/Pet.cpp
+++ b/src/server/game/Entities/Pet/Pet.cpp
@@ -15,6 +15,7 @@
#include "Log.h"
#include "ObjectMgr.h"
#include "Pet.h"
+#include "ScriptMgr.h"
#include "SpellAuraEffects.h"
#include "SpellAuras.h"
#include "SpellMgr.h"
@@ -1073,6 +1074,8 @@ bool Guardian::InitStatsForLevel(uint8 petlevel)
}
}
+ sScriptMgr->OnInitStatsForLevel(this, petlevel);
+
UpdateAllStats();
SetFullHealth();
@@ -1585,7 +1588,7 @@ void Pet::InitLevelupSpellsForLevel()
for (PetLevelupSpellSet::const_reverse_iterator itr = levelupSpells->rbegin(); itr != levelupSpells->rend(); ++itr)
{
// will called first if level down
- if (itr->first > level)
+ if (itr->first > level && sScriptMgr->CanUnlearnSpellSet(this, itr->first, itr->second))
unlearnSpell(itr->second, true); // will learn prev rank if any
// will called if level up
else
@@ -1605,7 +1608,7 @@ void Pet::InitLevelupSpellsForLevel()
continue;
// will called first if level down
- if (spellEntry->SpellLevel > level)
+ if (spellEntry->SpellLevel > level && sScriptMgr->CanUnlearnSpellDefault(this, spellEntry))
unlearnSpell(spellEntry->Id, true);
// will called if level up
else
@@ -1710,6 +1713,9 @@ bool Pet::resetTalents()
if (!owner || owner->GetTypeId() != TYPEID_PLAYER)
return false;
+ if (!sScriptMgr->CanResetTalents(this))
+ return false;
+
// not need after this call
if (owner->ToPlayer()->HasAtLoginFlag(AT_LOGIN_RESET_PET_TALENTS))
owner->ToPlayer()->RemoveAtLoginFlag(AT_LOGIN_RESET_PET_TALENTS, true);
@@ -1863,16 +1869,17 @@ void Pet::InitTalentForLevel()
{
uint8 level = getLevel();
uint32 talentPointsForLevel = GetMaxTalentPointsForLevel(level);
+
+ Unit* owner = GetOwner();
+ if (!owner || owner->GetTypeId() != TYPEID_PLAYER)
+ return;
+
// Reset talents in case low level (on level down) or wrong points for level (hunter can unlearn TP increase talent)
if (talentPointsForLevel == 0 || m_usedTalentCount > talentPointsForLevel)
resetTalents(); // Remove all talent points
SetFreeTalentPoints(talentPointsForLevel - m_usedTalentCount);
- Unit* owner = GetOwner();
- if (!owner || owner->GetTypeId() != TYPEID_PLAYER)
- return;
-
if (!m_loading)
owner->ToPlayer()->SendTalentsInfoData(true);
}
@@ -1883,6 +1890,9 @@ uint8 Pet::GetMaxTalentPointsForLevel(uint8 level)
// Mod points from owner SPELL_AURA_MOD_PET_TALENT_POINTS
if (Unit* owner = GetOwner())
points += owner->GetTotalAuraModifier(SPELL_AURA_MOD_PET_TALENT_POINTS);
+
+ sScriptMgr->OnCalculateMaxTalentPointsForLevel(this, level, points);
+
return points;
}
diff --git a/src/server/game/Entities/Player/Player.cpp b/src/server/game/Entities/Player/Player.cpp
index c12fbdae1d..304246f28b 100644
--- a/src/server/game/Entities/Player/Player.cpp
+++ b/src/server/game/Entities/Player/Player.cpp
@@ -611,9 +611,9 @@ void KillRewarder::_RewardPlayer(Player* player, bool isDungeon)
// Give reputation and kill credit only in PvE.
if (!_isPvP || _isBattleGround)
{
- const float rate = _group ?
- _groupRate * float(player->getLevel()) / _sumLevel : // Group rate depends on summary level.
- 1.0f; // Personal rate is 100%.
+ float rate = _group ? _groupRate * float(player->getLevel()) / _sumLevel : /*Personal rate is 100%.*/ 1.0f; // Group rate depends on summary level.
+
+ sScriptMgr->OnRewardKillRewarder(player, isDungeon, rate); // Personal rate is 100%.
if (_xp)
// 4.2. Give XP.
_RewardXP(player, rate);
@@ -976,10 +976,14 @@ Player::Player(WorldSession* session): Unit(true), m_mover(this)
m_applyResilience = true;
m_isInstantFlightOn = true;
+
+ sScriptMgr->OnConstructPlayer(this);
}
Player::~Player()
{
+ sScriptMgr->OnDestructPlayer(this);
+
// it must be unloaded already in PlayerLogout and accessed only for loggined player
//m_social = nullptr;
@@ -3389,7 +3393,8 @@ void Player::GiveLevel(uint8 level)
if (Pet* pet = GetPet())
pet->SynchronizeLevelWithOwner();
- if (MailLevelReward const* mailReward = sObjectMgr->GetMailLevelReward(level, getRaceMask()))
+ MailLevelReward const* mailReward = sObjectMgr->GetMailLevelReward(level, getRaceMask());
+ if (mailReward && sScriptMgr->CanGiveMailRewardAtGiveLevel(this, level))
{
//- TODO: Poor design of mail system
SQLTransaction trans = CharacterDatabase.BeginTransaction();
@@ -5144,6 +5149,8 @@ void Player::DeleteFromDB(uint64 playerguid, uint32 accountId, bool updateRealmC
stmt->setUInt32(0, guid);
trans->Append(stmt);
+ sScriptMgr->OnDeleteFromDB(trans, guid);
+
CharacterDatabase.CommitTransaction(trans);
break;
}
@@ -5713,6 +5720,9 @@ void Player::RepopAtGraveyard()
AreaTableEntry const* zone = sAreaTableStore.LookupEntry(GetAreaId());
+ if (!sScriptMgr->CanRepopAtGraveyard(this))
+ return;
+
// Such zones are considered unreachable as a ghost and the player must be automatically revived
// Xinef: Get Transport Check is not needed
if ((!IsAlive() && zone && zone->flags & AREA_FLAG_NEED_FLY) /*|| GetTransport()*/ || GetPositionZ() < GetMap()->GetMinHeight(GetPositionX(), GetPositionY()))
@@ -6803,6 +6813,7 @@ uint16 Player::GetMaxSkillValue(uint32 skill) const
uint32 bonus = GetUInt32Value(PLAYER_SKILL_BONUS_INDEX(itr->second.pos));
int32 result = int32(SKILL_MAX(GetUInt32Value(PLAYER_SKILL_VALUE_INDEX(itr->second.pos))));
+ sScriptMgr->OnGetMaxSkillValue(const_cast<Player*>(this), skill, result, false);
result += SKILL_TEMP_BONUS(bonus);
result += SKILL_PERM_BONUS(bonus);
return result < 0 ? 0 : result;
@@ -6817,7 +6828,11 @@ uint16 Player::GetPureMaxSkillValue(uint32 skill) const
if (itr == mSkillStatus.end() || itr->second.uState == SKILL_DELETED)
return 0;
- return SKILL_MAX(GetUInt32Value(PLAYER_SKILL_VALUE_INDEX(itr->second.pos)));
+ int32 result = int32(SKILL_MAX(GetUInt32Value(PLAYER_SKILL_VALUE_INDEX(itr->second.pos))));
+
+ sScriptMgr->OnGetMaxSkillValue(const_cast<Player*>(this), skill, result, true);
+
+ return result < 0 ? 0 : result;
}
uint16 Player::GetBaseSkillValue(uint32 skill) const
@@ -7075,6 +7090,9 @@ void Player::CheckAreaExploreAndOutdoor()
if (sWorld->getBoolConfig(CONFIG_VMAP_INDOOR_CHECK) && !isOutdoor)
RemoveAurasWithAttribute(SPELL_ATTR0_OUTDOORS_ONLY);
+ if (!sScriptMgr->CanAreaExploreAndOutdoor(this))
+ return;
+
if (!areaId)
return;
@@ -7466,6 +7484,8 @@ bool Player::RewardHonor(Unit* uVictim, uint32 groupsize, int32 honor, bool awar
// [29..38] Other title and player name
// [39+] Nothing
uint32 victim_title = victim->GetUInt32Value(PLAYER_CHOSEN_TITLE);
+ uint32 killer_title = 0;
+ sScriptMgr->OnVictimRewardBefore(this, victim, killer_title, victim_title);
// Get Killer titles, CharTitlesEntry::bit_index
// Ranks:
// title[1..14] -> rank[5..18]
@@ -7492,6 +7512,7 @@ bool Player::RewardHonor(Unit* uVictim, uint32 groupsize, int32 honor, bool awar
UpdateAchievementCriteria(ACHIEVEMENT_CRITERIA_TYPE_HONORABLE_KILL_AT_AREA, GetAreaId());
UpdateAchievementCriteria(ACHIEVEMENT_CRITERIA_TYPE_HONORABLE_KILL, 1, 0, victim);
UpdateAchievementCriteria(ACHIEVEMENT_CRITERIA_TYPE_SPECIAL_PVP_KILL, 1, 0, victim);
+ sScriptMgr->OnVictimRewardAfter(this, victim, killer_title, victim_rank, honor_f);
}
else
{
@@ -7646,14 +7667,6 @@ uint32 Player::GetArenaTeamIdFromStorage(uint32 guid, uint8 slot)
return 0;
}
-void Player::SetArenaTeamInfoField(uint8 slot, ArenaTeamInfoType type, uint32 value)
-{
- if (slot < MAX_ARENA_SLOT)
- {
- SetUInt32Value(PLAYER_FIELD_ARENA_TEAM_INFO_1_1 + (slot * ARENA_TEAM_END) + type, value);
- }
-}
-
uint32 Player::GetArenaTeamIdFromDB(uint64 guid, uint8 type)
{
PreparedStatement* stmt = CharacterDatabase.GetPreparedStatement(CHAR_SEL_ARENA_TEAM_ID_BY_PLAYER_GUID);
@@ -8081,6 +8094,12 @@ void Player::_ApplyItemBonuses(ItemTemplate const* proto, uint8 slot, bool apply
// req. check at equip, but allow use for extended range if range limit max level, set proper level
uint32 ssd_level = getLevel();
+ uint32 CustomScalingStatValue = 0;
+
+ sScriptMgr->OnCustomScalingStatValueBefore(this, proto, slot, apply, CustomScalingStatValue);
+
+ uint32 ScalingStatValue = proto->ScalingStatValue > 0 ? proto->ScalingStatValue : CustomScalingStatValue;
+
if (ssd && ssd_level > ssd->MaxLevel)
ssd_level = ssd->MaxLevel;
@@ -8093,17 +8112,30 @@ void Player::_ApplyItemBonuses(ItemTemplate const* proto, uint8 slot, bool apply
uint32 statType = 0;
int32 val = 0;
// If set ScalingStatDistribution need get stats and values from it
- if (ssd && ssv)
+ if (ssv)
{
- if (ssd->StatMod[i] < 0)
- continue;
- statType = ssd->StatMod[i];
- val = (ssv->getssdMultiplier(proto->ScalingStatValue) * ssd->Modifier[i]) / 10000;
+ if (ssd)
+ {
+ if (ssd->StatMod[i] < 0)
+ continue;
+
+ statType = ssd->StatMod[i];
+ val = (ssv->getssdMultiplier(ScalingStatValue) * ssd->Modifier[i]) / 10000;
+ }
+ else
+ {
+ if (i >= proto->StatsCount)
+ continue;
+
+ // OnCustomScalingStatValue(Player* player, ItemTemplate const* proto, uint32& statType, int32& val, uint8 itemProtoStatNumber, uint32 ScalingStatValue, ScalingStatValuesEntry const* ssv)
+ sScriptMgr->OnCustomScalingStatValue(this, proto, statType, val, i, ScalingStatValue, ssv);
+ }
}
else
{
if (i >= proto->StatsCount)
continue;
+
statType = proto->ItemStat[i].ItemStatType;
val = proto->ItemStat[i].ItemStatValue;
}
@@ -8262,15 +8294,16 @@ void Player::_ApplyItemBonuses(ItemTemplate const* proto, uint8 slot, bool apply
// Apply Spell Power from ScalingStatValue if set
if (ssv)
- if (int32 spellbonus = ssv->getSpellBonus(proto->ScalingStatValue))
+ if (int32 spellbonus = ssv->getSpellBonus(ScalingStatValue))
ApplySpellPowerBonus(spellbonus, apply);
// If set ScalingStatValue armor get it or use item armor
uint32 armor = proto->Armor;
if (ssv)
{
- if (uint32 ssvarmor = ssv->getArmorMod(proto->ScalingStatValue))
- armor = ssvarmor;
+ if (uint32 ssvarmor = ssv->getArmorMod(ScalingStatValue))
+ if (proto->ScalingStatValue > 0 || ssvarmor < proto->Armor) //Check to avoid higher values than stat itself (heirloom OR items with correct armor value)
+ armor = ssvarmor;
}
else if (armor && proto->ArmorDamageModifier)
armor -= uint32(proto->ArmorDamageModifier);
@@ -8295,7 +8328,7 @@ void Player::_ApplyItemBonuses(ItemTemplate const* proto, uint8 slot, bool apply
}
// Add armor bonus from ArmorDamageModifier if > 0
- if (proto->ArmorDamageModifier > 0)
+ if (proto->ArmorDamageModifier > 0 && sScriptMgr->CanArmorDamageModifier(this))
HandleStatModifier(UNIT_MOD_ARMOR, TOTAL_VALUE, float(proto->ArmorDamageModifier), apply);
if (proto->Block)
@@ -8342,11 +8375,12 @@ void Player::_ApplyItemBonuses(ItemTemplate const* proto, uint8 slot, bool apply
int32 feral_bonus = 0;
if (ssv)
{
- dpsMod = ssv->getDPSMod(proto->ScalingStatValue);
- feral_bonus += ssv->getFeralBonus(proto->ScalingStatValue);
+ dpsMod = ssv->getDPSMod(ScalingStatValue);
+ feral_bonus += ssv->getFeralBonus(ScalingStatValue);
}
feral_bonus += proto->getFeralBonus(dpsMod);
+ sScriptMgr->OnGetFeralApBonus(this, feral_bonus, dpsMod, proto, ssv);
if (feral_bonus)
ApplyFeralAPBonus(feral_bonus, apply);
}
@@ -8354,6 +8388,27 @@ void Player::_ApplyItemBonuses(ItemTemplate const* proto, uint8 slot, bool apply
void Player::_ApplyWeaponDamage(uint8 slot, ItemTemplate const* proto, ScalingStatValuesEntry const* ssv, bool apply)
{
+ uint32 CustomScalingStatValue = 0;
+
+ sScriptMgr->OnCustomScalingStatValueBefore(this, proto, slot, apply, CustomScalingStatValue);
+
+ uint32 ScalingStatValue = proto->ScalingStatValue > 0 ? proto->ScalingStatValue : CustomScalingStatValue;
+
+ // following part fix disarm issue
+ // that doesn't apply the scaling after disarmed
+ if (!ssv)
+ {
+ ScalingStatDistributionEntry const* ssd = proto->ScalingStatDistribution ? sScalingStatDistributionStore.LookupEntry(proto->ScalingStatDistribution) : nullptr;
+
+ // req. check at equip, but allow use for extended range if range limit max level, set proper level
+ uint32 ssd_level = getLevel();
+
+ if (ssd && ssd_level > ssd->MaxLevel)
+ ssd_level = ssd->MaxLevel;
+
+ ssv = ScalingStatValue ? sScalingStatValuesStore.LookupEntry(ssd_level) : nullptr;
+ }
+
WeaponAttackType attType = BASE_ATTACK;
float damage = 0.0f;
@@ -8374,7 +8429,7 @@ void Player::_ApplyWeaponDamage(uint8 slot, ItemTemplate const* proto, ScalingSt
// If set dpsMod in ScalingStatValue use it for min (70% from average), max (130% from average) damage
if (ssv)
{
- int32 extraDPS = ssv->getDPSMod(proto->ScalingStatValue);
+ int32 extraDPS = ssv->getDPSMod(ScalingStatValue);
if (extraDPS)
{
float average = extraDPS * proto->Delay / 1000.0f;
@@ -8438,6 +8493,9 @@ void Player::_ApplyWeaponDependentAuraCritMod(Item* item, WeaponAttackType attac
if (aura->GetSpellInfo()->EquippedItemClass == -1)
return;
+ if (!sScriptMgr->CanApplyWeaponDependentAuraDamageMod(this, item, attackType, aura, apply))
+ return;
+
BaseModGroup mod = BASEMOD_END;
switch (attackType)
{
@@ -8548,6 +8606,9 @@ void Player::ApplyEquipSpell(SpellInfo const* spellInfo, Item* item, bool apply,
{
if (apply)
{
+ if (!sScriptMgr->CanApplyEquipSpell(this, spellInfo, item, apply, form_change))
+ return;
+
// Cannot be used in this stance/form
if (spellInfo->CheckShapeshift(GetShapeshiftForm()) != SPELL_CAST_OK)
return;
@@ -8619,6 +8680,8 @@ void Player::UpdateEquipSpellsAtFormChange()
continue;
ApplyEquipSpell(spellInfo, nullptr, false, true); // remove spells that not fit to form
+ if (!sScriptMgr->CanApplyEquipSpellsItemSet(this, eff))
+ break;
ApplyEquipSpell(spellInfo, nullptr, true, true); // add spells that fit form but not active
}
}
@@ -8671,6 +8734,9 @@ void Player::CastItemCombatSpell(Unit* target, WeaponAttackType attType, uint32
void Player::CastItemCombatSpell(Unit* target, WeaponAttackType attType, uint32 procVictim, uint32 procEx, Item* item, ItemTemplate const* proto)
{
+ if (!sScriptMgr->CanCastItemCombatSpell(this, target, attType, procVictim, procEx, item, proto))
+ return;
+
// Can do effect if any damage done to target
if (procVictim & PROC_FLAG_TAKEN_DAMAGE)
//if (damageInfo->procVictim & PROC_FLAG_TAKEN_ANY_DAMAGE)
@@ -8794,6 +8860,9 @@ void Player::CastItemCombatSpell(Unit* target, WeaponAttackType attType, uint32
void Player::CastItemUseSpell(Item* item, SpellCastTargets const& targets, uint8 cast_count, uint32 glyphIndex)
{
+ if (!sScriptMgr->CanCastItemUseSpell(this, item, targets, cast_count, glyphIndex))
+ return;
+
ItemTemplate const* proto = item->GetTemplate();
// special learning case
if (proto->Spells[0].SpellId == 483 || proto->Spells[0].SpellId == 55884)
@@ -9056,6 +9125,8 @@ void Player::_ApplyAmmoBonuses()
else
currentAmmoDPS = (ammo_proto->Damage[0].DamageMin + ammo_proto->Damage[0].DamageMax) / 2;
+ sScriptMgr->OnApplyAmmoBonuses(this, ammo_proto, currentAmmoDPS);
+
if (currentAmmoDPS == GetAmmoDPS())
return;
@@ -12047,6 +12118,9 @@ InventoryResult Player::CanEquipItem(uint8 slot, uint16& dest, Item* pItem, bool
ItemTemplate const* pProto = pItem->GetTemplate();
if (pProto)
{
+ if (!sScriptMgr->CanEquipItem(const_cast<Player*>(this), slot, dest, pItem, swap, not_loading))
+ return EQUIP_ERR_CANT_DO_RIGHT_NOW;
+
// item used
if (pItem->m_lootGenerated)
return EQUIP_ERR_ALREADY_LOOTED;
@@ -12208,6 +12282,9 @@ InventoryResult Player::CanEquipItem(uint8 slot, uint16& dest, Item* pItem, bool
InventoryResult Player::CanUnequipItem(uint16 pos, bool swap) const
{
+ if (!sScriptMgr->CanUnequipItem(const_cast<Player*>(this), pos, swap))
+ return EQUIP_ERR_CANT_DO_RIGHT_NOW;
+
// Applied only to equipped items and bank bags
if (!IsEquipmentPos(pos) && !IsBagPos(pos))
return EQUIP_ERR_OK;
@@ -12529,6 +12606,11 @@ InventoryResult Player::CanUseItem(ItemTemplate const* proto) const
if (proto->RequiredSpell != 0 && !HasSpell(proto->RequiredSpell))
return EQUIP_ERR_NO_REQUIRED_PROFICIENCY;
+ InventoryResult result = EQUIP_ERR_OK;
+
+ if (!sScriptMgr->CanUseItem(const_cast<Player*>(this), proto, result))
+ return result;
+
if (getLevel() < proto->RequiredLevel)
return EQUIP_ERR_CANT_EQUIP_LEVEL_I;
@@ -12872,7 +12954,11 @@ Item* Player::_StoreItem(uint16 pos, Item* pItem, uint32 count, bool clone, bool
Item* Player::EquipNewItem(uint16 pos, uint32 item, bool update)
{
- if (Item* pItem = Item::CreateItem(item, 1, this))
+ Item* _item = Item::CreateItem(item, 1, this);
+ if (!_item)
+ return nullptr;
+
+ if (!IsEquipmentPos(pos) || sScriptMgr->CanSaveEquipNewItem(this, _item, pos, update))
{
// pussywizard: obtaining blue or better items saves to db
if (ItemTemplate const* pProto = sObjectMgr->GetItemTemplate(item))
@@ -12881,10 +12967,9 @@ Item* Player::EquipNewItem(uint16 pos, uint32 item, bool update)
ItemAddedQuestCheck(item, 1);
UpdateAchievementCriteria(ACHIEVEMENT_CRITERIA_TYPE_RECEIVE_EPIC_ITEM, item, 1);
- return EquipItem(pos, pItem, update);
}
- return nullptr;
+ return EquipItem(pos, _item, update);
}
Item* Player::EquipItem(uint16 pos, Item* pItem, bool update)
@@ -14497,6 +14582,9 @@ void Player::ApplyEnchantment(Item* item, EnchantmentSlot slot, bool apply, bool
if (pEnchant->requiredSkill > 0 && pEnchant->requiredSkillValue > GetSkillValue(pEnchant->requiredSkill))
return;
+ if (!sScriptMgr->CanApplyEnchantment(this, item, slot, apply, apply_dur, ignore_condition))
+ return;
+
// If we're dealing with a gem inside a prismatic socket we need to check the prismatic socket requirements
// rather than the gem requirements itself. If the socket has no color it is a prismatic socket.
if ((slot == SOCK_ENCHANTMENT_SLOT || slot == SOCK_ENCHANTMENT_SLOT_2 || slot == SOCK_ENCHANTMENT_SLOT_3)
@@ -16096,7 +16184,7 @@ void Player::RewardQuest(Quest const* quest, uint32 reward, Object* questGiver,
bool rewarded = IsQuestRewarded(quest_id) && !quest->IsDFQuest();
// Not give XP in case already completed once repeatable quest
- uint32 XP = rewarded ? 0 : uint32(quest->XPValue(this) * sWorld->getRate(RATE_XP_QUEST));
+ uint32 XP = rewarded ? 0 : uint32(quest->XPValue(this) * GetQuestRate());
// handle SPELL_AURA_MOD_XP_QUEST_PCT auras
Unit::AuraEffectList const& ModXPPctAuras = GetAuraEffectsByType(SPELL_AURA_MOD_XP_QUEST_PCT);
@@ -17252,6 +17340,9 @@ void Player::KilledMonsterCredit(uint32 entry, uint64 guid)
if (q_status.Status == QUEST_STATUS_INCOMPLETE && (!GetGroup() || !GetGroup()->isRaidGroup() || qInfo->IsAllowedInRaid(GetMap()->GetDifficulty()) ||
(qInfo->IsPVPQuest() && (GetGroup()->isBFGroup() || GetGroup()->isBGGroup()))))
{
+ if (!sScriptMgr->PassedQuestKilledMonsterCredit(this, qInfo, entry, real_entry, guid))
+ continue;
+
if (qInfo->HasSpecialFlag(QUEST_SPECIAL_FLAGS_KILL) /*&& !qInfo->HasSpecialFlag(QUEST_SPECIAL_FLAGS_CAST)*/)
{
for (uint8 j = 0; j < QUEST_OBJECTIVES_COUNT; ++j)
@@ -17801,8 +17892,8 @@ void Player::_LoadArenaTeamInfo()
{
memset((void*)&m_uint32Values[PLAYER_FIELD_ARENA_TEAM_INFO_1_1], 0, sizeof(uint32) * MAX_ARENA_SLOT * ARENA_TEAM_END);
- for (uint8 slot = 0; slot < MAX_ARENA_SLOT; ++slot)
- if (uint32 arenaTeamId = Player::GetArenaTeamIdFromStorage(GetGUIDLow(), slot))
+ for (auto const& itr : ArenaTeam::ArenaSlotByType)
+ if (uint32 arenaTeamId = Player::GetArenaTeamIdFromStorage(GetGUIDLow(), itr.second))
{
ArenaTeam* arenaTeam = sArenaTeamMgr->GetArenaTeamById(arenaTeamId);
if (!arenaTeam) // some shit, should be assert, but just ignore
@@ -17811,6 +17902,8 @@ void Player::_LoadArenaTeamInfo()
if (!member) // some shit, should be assert, but just ignore
continue;
+ uint8 slot = itr.second;
+
SetArenaTeamInfoField(slot, ARENA_TEAM_ID, arenaTeamId);
SetArenaTeamInfoField(slot, ARENA_TEAM_TYPE, arenaTeam->GetType());
SetArenaTeamInfoField(slot, ARENA_TEAM_MEMBER, (arenaTeam->GetCaptain() == GetGUID()) ? 0 : 1);
@@ -18874,7 +18967,8 @@ void Player::_LoadInventory(PreparedQueryResult result, uint32 timeDiff)
else if (IsEquipmentPos(INVENTORY_SLOT_BAG_0, slot))
{
uint16 dest;
- err = CanEquipItem(slot, dest, item, false, false);
+ if (sScriptMgr->CheckItemInSlotAtLoadInventory(this, item, slot, err, dest))
+ err = CanEquipItem(slot, dest, item, false, false);
if (err == EQUIP_ERR_OK)
QuickEquipItem(dest, item);
}
@@ -19858,6 +19952,9 @@ bool Player::Satisfy(DungeonProgressionRequirements const* ar, uint32 target_map
|| missingPlayerItems.size() || missingPlayerQuests.size() || missingPlayerAchievements.size()
|| missingLeaderItems.size() || missingLeaderQuests.size() || missingLeaderAchievements.size())
{
+ if (!sScriptMgr->NotAvoidSatisfy(partyLeader, ar, target_map, report))
+ return true;
+
if (report)
{
uint8 requirementPrintMode = sWorld->getIntConfig(CONFIG_DUNGEON_ACCESS_REQUIREMENTS_PRINT_MODE);
@@ -22020,36 +22117,6 @@ void Player::LeaveAllArenaTeams(uint64 guid)
} while (result->NextRow());
}
-uint32 Player::GetArenaTeamId(uint8 slot) const
-{
- uint32 rtVal = 0;
- if (slot >= MAX_ARENA_SLOT)
- {
- sScriptMgr->GetCustomGetArenaTeamId(this, slot, rtVal);
- }
- else
- {
- rtVal = GetUInt32Value(PLAYER_FIELD_ARENA_TEAM_INFO_1_1 + (slot * ARENA_TEAM_END) + ARENA_TEAM_ID);
- }
-
- return rtVal;
-}
-
-uint32 Player::GetArenaPersonalRating(uint8 slot) const
-{
- uint32 rtVal = 0;
- if (slot >= MAX_ARENA_SLOT)
- {
- sScriptMgr->GetCustomGetArenaTeamId(this, slot, rtVal);
- }
- else
- {
- rtVal = GetUInt32Value(PLAYER_FIELD_ARENA_TEAM_INFO_1_1 + (slot * ARENA_TEAM_END) + ARENA_TEAM_PERSONAL_RATING);
- }
-
- return rtVal;
-}
-
void Player::SetRestBonus(float rest_bonus_new)
{
// Prevent resting on max level
@@ -22492,9 +22559,9 @@ inline bool Player::_StoreOrEquipNewItem(uint32 vendorslot, uint32 item, uint8 c
}
}
- Item* it = bStore ?
- StoreNewItem(vDest, item, true) :
- EquipNewItem(uiDest, item, true);
+ sScriptMgr->OnBeforeStoreOrEquipNewItem(this, vendorslot, item, count, bag, slot, pProto, pVendor, crItem, bStore);
+
+ Item* it = bStore ? StoreNewItem(vDest, item, true) : EquipNewItem(uiDest, item, true);
if (it)
{
uint32 new_count = pVendor->UpdateVendorItemCurrentCount(crItem, pProto->BuyCount * count);
@@ -22520,6 +22587,9 @@ inline bool Player::_StoreOrEquipNewItem(uint32 vendorslot, uint32 item, uint8 c
AddRefundReference(it->GetGUIDLow());
}
}
+
+ sScriptMgr->OnAfterStoreOrEquipNewItem(this, vendorslot, it, count, bag, slot, pProto, pVendor, crItem, bStore);
+
return true;
}
@@ -23371,6 +23441,9 @@ bool Player::IsVisibleGloballyFor(Player const* u) const
if (!AccountMgr::IsPlayerAccount(u->GetSession()->GetSecurity()))
return GetSession()->GetSecurity() <= u->GetSession()->GetSecurity();
+ if (!sScriptMgr->NotVisibleGloballyFor(const_cast<Player*>(this), u))
+ return true;
+
// non faction visibility non-breakable for non-GMs
return false;
}
@@ -28457,3 +28530,77 @@ void Player::RemoveRestFlag(RestFlag restFlag)
RemoveFlag(PLAYER_FLAGS, PLAYER_FLAGS_RESTING);
}
}
+
+void Player::SetArenaTeamInfoField(uint8 slot, ArenaTeamInfoType type, uint32 value)
+{
+ if (sScriptMgr->NotSetArenaTeamInfoField(this, slot, type, value))
+ SetUInt32Value(PLAYER_FIELD_ARENA_TEAM_INFO_1_1 + (slot * ARENA_TEAM_END) + type, value);
+}
+
+uint32 Player::GetArenaPersonalRating(uint8 slot) const
+{
+ uint32 result = GetUInt32Value(PLAYER_FIELD_ARENA_TEAM_INFO_1_1 + (slot * ARENA_TEAM_END) + ARENA_TEAM_PERSONAL_RATING);
+
+ sScriptMgr->OnGetArenaPersonalRating(const_cast<Player*>(this), slot, result);
+
+ return result;
+}
+
+uint32 Player::GetArenaTeamId(uint8 slot) const
+{
+ uint32 result = GetUInt32Value(PLAYER_FIELD_ARENA_TEAM_INFO_1_1 + (slot * ARENA_TEAM_END) + ARENA_TEAM_ID);
+
+ sScriptMgr->OnGetArenaTeamId(const_cast<Player*>(this), slot, result);
+
+ return result;
+}
+
+bool Player::IsFFAPvP()
+{
+ bool result = Unit::IsFFAPvP();
+
+ sScriptMgr->OnIsFFAPvP(this, result);
+
+ return result;
+}
+
+bool Player::IsPvP()
+{
+ bool result = Unit::IsPvP();
+
+ sScriptMgr->OnIsPvP(this, result);
+
+ return result;
+}
+
+uint16 Player::GetMaxSkillValueForLevel() const
+{
+ uint16 result = Unit::GetMaxSkillValueForLevel();
+
+ sScriptMgr->OnGetMaxSkillValueForLevel(const_cast<Player*>(this), result);
+
+ return result;
+}
+
+float Player::GetQuestRate()
+{
+ float result = sWorld->getRate(RATE_XP_QUEST);
+
+ sScriptMgr->OnGetQuestRate(this, result);
+
+ return result;
+}
+
+void Player::SetServerSideVisibility(ServerSideVisibilityType type, AccountTypes sec)
+{
+ sScriptMgr->OnSetServerSideVisibility(this, type, sec);
+
+ m_serverSideVisibility.SetValue(type, sec);
+}
+
+void Player::SetServerSideVisibilityDetect(ServerSideVisibilityType type, AccountTypes sec)
+{
+ sScriptMgr->OnSetServerSideVisibilityDetect(this, type, sec);
+
+ m_serverSideVisibilityDetect.SetValue(type, sec);
+}
diff --git a/src/server/game/Entities/Player/Player.h b/src/server/game/Entities/Player/Player.h
index 051a0c8760..802556dbe7 100644
--- a/src/server/game/Entities/Player/Player.h
+++ b/src/server/game/Entities/Player/Player.h
@@ -11,6 +11,7 @@
#include "DBCStores.h"
#include "GroupReference.h"
#include "InstanceSaveMgr.h"
+#include "ArenaTeam.h"
#include "Item.h"
#include "MapReference.h"
#include "ObjectMgr.h"
@@ -705,19 +706,6 @@ enum InstanceResetWarningType
RAID_INSTANCE_EXPIRED = 5
};
-// PLAYER_FIELD_ARENA_TEAM_INFO_1_1 offsets
-enum ArenaTeamInfoType
-{
- ARENA_TEAM_ID = 0,
- ARENA_TEAM_TYPE = 1, // new in 3.2 - team type?
- ARENA_TEAM_MEMBER = 2, // 0 - captain, 1 - member
- ARENA_TEAM_GAMES_WEEK = 3,
- ARENA_TEAM_GAMES_SEASON = 4,
- ARENA_TEAM_WINS_SEASON = 5,
- ARENA_TEAM_PERSONAL_RATING = 6,
- ARENA_TEAM_END = 7
-};
-
class InstanceSave;
enum RestFlag
@@ -1466,7 +1454,7 @@ public:
void RemoveRewardedQuest(uint32 questId, bool update = true);
void SendQuestUpdate(uint32 questId);
QuestGiverStatus GetQuestDialogStatus(Object* questGiver);
-
+ float GetQuestRate();
void SetDailyQuestStatus(uint32 quest_id);
bool IsDailyQuestDone(uint32 quest_id);
void SetWeeklyQuestStatus(uint32 quest_id);
@@ -1616,6 +1604,7 @@ public:
[[nodiscard]] RewardedQuestSet const& getRewardedQuests() const { return m_RewardedQuests; }
QuestStatusMap& getQuestStatusMap() { return m_QuestStatus; }
+ QuestStatusSaveMap& GetQuestStatusSaveMap() { return m_QuestStatusSave; }
[[nodiscard]] size_t GetRewardedQuestCount() const { return m_RewardedQuests.size(); }
[[nodiscard]] bool IsQuestRewarded(uint32 quest_id) const
@@ -1915,10 +1904,10 @@ public:
SetArenaTeamInfoField(slot, ARENA_TEAM_TYPE, type);
}
void SetArenaTeamInfoField(uint8 slot, ArenaTeamInfoType type, uint32 value);
+ uint32 GetArenaPersonalRating(uint8 slot) const;
static uint32 GetArenaTeamIdFromDB(uint64 guid, uint8 slot);
static void LeaveAllArenaTeams(uint64 guid);
[[nodiscard]] uint32 GetArenaTeamId(uint8 slot) const;
- [[nodiscard]] uint32 GetArenaPersonalRating(uint8 slot) const;
void SetArenaTeamIdInvited(uint32 ArenaTeamId) { m_ArenaTeamIdInvited = ArenaTeamId; }
uint32 GetArenaTeamIdInvited() { return m_ArenaTeamIdInvited; }
@@ -2443,6 +2432,10 @@ public:
void SendCinematicStart(uint32 CinematicSequenceId);
void SendMovieStart(uint32 MovieId);
+ uint16 GetMaxSkillValueForLevel() const;
+ bool IsFFAPvP();
+ bool IsPvP();
+
/*********************************************************/
/*** INSTANCE SYSTEM ***/
/*********************************************************/
@@ -2619,6 +2612,9 @@ public:
[[nodiscard]] uint32 GetNextSave() const { return m_nextSave; }
[[nodiscard]] SpellModList const& GetSpellModList(uint32 type) const { return m_spellMods[type]; }
+ void SetServerSideVisibility(ServerSideVisibilityType type, AccountTypes sec);
+ void SetServerSideVisibilityDetect(ServerSideVisibilityType type, AccountTypes sec);
+
static std::unordered_map<int, bgZoneRef> bgZoneIdToFillWorldStates; // zoneId -> FillInitialWorldStates
// Cinematic camera data and remote sight functions
diff --git a/src/server/game/Entities/Unit/Unit.cpp b/src/server/game/Entities/Unit/Unit.cpp
index b65b14e37b..c219cfc1f9 100644
--- a/src/server/game/Entities/Unit/Unit.cpp
+++ b/src/server/game/Entities/Unit/Unit.cpp
@@ -4363,6 +4363,8 @@ void Unit::RemoveAura(AuraApplicationMap::iterator& i, AuraRemoveMode mode)
// Remove aura - for Area and Target auras
if (aura->GetOwner() == this)
aura->Remove(mode);
+
+ sScriptMgr->OnAuraRemove(this, aurApp, mode);
}
void Unit::RemoveAura(uint32 spellId, uint64 caster, uint8 reqEffMask, AuraRemoveMode removeMode)
@@ -9687,6 +9689,11 @@ ReputationRank Unit::GetReactionTo(Unit const* target) const
}
}
}
+
+ ReputationRank repRank = REP_HATED;
+
+ if (!sScriptMgr->IfNormalReaction(this, target, repRank))
+ return ReputationRank(repRank);
// do checks dependant only on our faction
return GetFactionReactionTo(GetFactionTemplateEntry(), target);
}
@@ -10782,6 +10789,9 @@ float Unit::SpellPctDamageModsDone(Unit* victim, SpellInfo const* spellProto, Da
if (!spellProto->ValidateAttribute6SpellDamageMods(this, *i, damagetype == DOT))
continue;
+ if (!sScriptMgr->IsNeedModSpellDamagePercent(this, *i, DoneTotalMod, spellProto))
+ continue;
+
if ((*i)->GetMiscValue() & spellProto->GetSchoolMask())
{
if ((*i)->GetSpellInfo()->EquippedItemClass == -1)
@@ -11784,8 +11794,13 @@ float Unit::SpellPctHealingModsDone(Unit* victim, SpellInfo const* spellProto, D
// Healing done percent
AuraEffectList const& mHealingDonePct = GetAuraEffectsByType(SPELL_AURA_MOD_HEALING_DONE_PERCENT);
- for (AuraEffectList::const_iterator i = mHealingDonePct.begin(); i != mHealingDonePct.end(); ++i)
- AddPct(DoneTotalMod, (*i)->GetAmount());
+ for (auto const& auraEff : mHealingDonePct)
+ {
+ if (!sScriptMgr->IsNeedModHealPercent(this, auraEff, DoneTotalMod, spellProto))
+ continue;
+
+ AddPct(DoneTotalMod, auraEff->GetAmount());
+ }
// done scripted mod (take it from owner)
Unit* owner = GetOwner() ? GetOwner() : this;
@@ -12400,6 +12415,9 @@ uint32 Unit::MeleeDamageBonusDone(Unit* victim, uint32 pdamage, WeaponAttackType
if (!spellProto->ValidateAttribute6SpellDamageMods(this, *i, false))
continue;
+ if (!sScriptMgr->IsNeedModMeleeDamagePercent(this, *i, DoneTotalMod, spellProto))
+ continue;
+
if (((*i)->GetMiscValue() & spellProto->GetSchoolMask()) && !((*i)->GetMiscValue() & SPELL_SCHOOL_MASK_NORMAL))
{
if ((*i)->GetSpellInfo()->EquippedItemClass == -1)
@@ -18230,6 +18248,9 @@ void Unit::SetPhaseMask(uint32 newPhaseMask, bool update)
// pussywizard: goign to other phase (valithria, algalon) should not remove such auras
//RemoveNotOwnSingleTargetAuras(newPhaseMask, true); // we can lost access to caster or target
+ if (!sScriptMgr->CanSetPhaseMask(this, newPhaseMask, update))
+ return;
+
// modify hostile references for new phasemask, some special cases deal with hostile references themselves
if (GetTypeId() == TYPEID_UNIT || (!ToPlayer()->IsGameMaster() && !ToPlayer()->GetSession()->PlayerLogout()))
{
@@ -20077,7 +20098,10 @@ void Unit::BuildValuesUpdate(uint8 updateType, ByteBuffer* data, Player* target)
fieldBuffer << (uint32)target->getFaction();
}
else
- fieldBuffer << m_uint32Values[index];
+ if (!sScriptMgr->IsCustomBuildValuesUpdate(this, updateType, fieldBuffer, target, index))
+ {
+ fieldBuffer << m_uint32Values[index];
+ }
}
else
// send in current format (float as float, uint32 as uint32)
diff --git a/src/server/game/Groups/Group.cpp b/src/server/game/Groups/Group.cpp
index 72fd3cb72e..05db6332a0 100644
--- a/src/server/game/Groups/Group.cpp
+++ b/src/server/game/Groups/Group.cpp
@@ -59,10 +59,13 @@ Group::Group() : m_leaderGuid(0), m_leaderName(""), m_groupType(GROUPTYPE_NORMAL
{
for (uint8 i = 0; i < TARGETICONCOUNT; ++i)
m_targetIcons[i] = 0;
+ sScriptMgr->OnConstructGroup(this);
}
Group::~Group()
{
+ sScriptMgr->OnDestructGroup(this);
+
if (m_bgGroup)
{
#if defined(ENABLE_EXTRAS) && defined(ENABLE_EXTRA_LOGS)
@@ -142,6 +145,8 @@ bool Group::Create(Player* leader)
CharacterDatabase.Execute(stmt);
ASSERT(AddMember(leader)); // If the leader can't be added to a new group because it appears full, something is clearly wrong.
+
+ sScriptMgr->OnCreate(this, leader);
}
else if (!AddMember(leader))
return false;
@@ -1840,6 +1845,9 @@ GroupJoinBattlegroundResult Group::CanJoinBattlegroundQueue(Battleground const*
if (!member)
return ERR_BATTLEGROUND_JOIN_FAILED;
+ if (!sScriptMgr->CanGroupJoinBattlegroundQueue(this, member, bgTemplate, MinPlayerCount, isRated, arenaSlot))
+ return ERR_BATTLEGROUND_JOIN_FAILED;
+
// don't allow cross-faction groups to join queue
if (member->GetTeamId() != teamId)
return ERR_BATTLEGROUND_JOIN_TIMED_OUT;
diff --git a/src/server/game/Guilds/Guild.cpp b/src/server/game/Guilds/Guild.cpp
index 450b14b39f..b45c2fb12d 100644
--- a/src/server/game/Guilds/Guild.cpp
+++ b/src/server/game/Guilds/Guild.cpp
@@ -2875,6 +2875,9 @@ void Guild::_BroadcastEvent(GuildEvents guildEvent, uint64 guid, const char* par
void Guild::_SendBankList(WorldSession* session /* = nullptr*/, uint8 tabId /*= 0*/, bool sendAllSlots /*= false*/, SlotIds* slots /*= nullptr*/) const
{
+ if (!sScriptMgr->CanGuildSendBankList(this, session, tabId, sendAllSlots))
+ return;
+
WorldPacket data(SMSG_GUILD_BANK_LIST, 500);
data << uint64(m_bankMoney);
data << uint8(tabId);
diff --git a/src/server/game/Guilds/Guild.h b/src/server/game/Guilds/Guild.h
index e351546d30..4fb8426ce2 100644
--- a/src/server/game/Guilds/Guild.h
+++ b/src/server/game/Guilds/Guild.h
@@ -756,6 +756,9 @@ public:
void ResetTimes();
+ [[nodiscard]] bool ModifyBankMoney(SQLTransaction& trans, const uint64& amount, bool add) { return _ModifyBankMoney(trans, amount, add); }
+ [[nodiscard]] uint32 GetMemberSize() const { return m_members.size(); }
+
protected:
uint32 m_id;
std::string m_name;
diff --git a/src/server/game/Handlers/AuctionHouseHandler.cpp b/src/server/game/Handlers/AuctionHouseHandler.cpp
index d4d698553e..a3241a4a7e 100644
--- a/src/server/game/Handlers/AuctionHouseHandler.cpp
+++ b/src/server/game/Handlers/AuctionHouseHandler.cpp
@@ -12,6 +12,7 @@
#include "Log.h"
#include "ObjectMgr.h"
#include "Opcodes.h"
+#include "ScriptMgr.h"
#include "Player.h"
#include "UpdateMask.h"
#include "Util.h"
@@ -50,6 +51,9 @@ void WorldSession::SendAuctionHello(uint64 guid, Creature* unit)
return;
}
+ if (!sScriptMgr->CanSendAuctionHello(this, guid, unit))
+ return;
+
AuctionHouseEntry const* ahEntry = AuctionHouseMgr::GetAuctionHouseEntry(unit->getFaction());
if (!ahEntry)
return;
diff --git a/src/server/game/Handlers/BattleGroundHandler.cpp b/src/server/game/Handlers/BattleGroundHandler.cpp
index ccfd82efaa..1fde7b10ab 100644
--- a/src/server/game/Handlers/BattleGroundHandler.cpp
+++ b/src/server/game/Handlers/BattleGroundHandler.cpp
@@ -388,6 +388,9 @@ void WorldSession::HandleBattleFieldPortOpcode(WorldPacket& recvData)
BattlegroundQueueTypeId bgQueueTypeId = BattlegroundMgr::BGQueueTypeId(bgTypeId, arenaType);
BattlegroundQueue& bgQueue = sBattlegroundMgr->GetBattlegroundQueue(bgQueueTypeId);
+ if (!sScriptMgr->CanBattleFieldPort(_player, arenaType, bgTypeId, action))
+ return;
+
// get group info from queue
GroupQueueInfo ginfo;
if (!bgQueue.GetPlayerGroupInfoData(_player->GetGUID(), &ginfo))
@@ -658,6 +661,14 @@ void WorldSession::HandleBattlemasterJoinArena(WorldPacket& recvData)
// queue result (default ok)
GroupJoinBattlegroundResult err = GroupJoinBattlegroundResult(bgt->GetBgTypeID());
+ if (!sScriptMgr->CanJoinInArenaQueue(_player, guid, arenaslot, bgTypeId, asGroup, isRated, err) && err <= 0)
+ {
+ WorldPacket data;
+ sBattlegroundMgr->BuildGroupJoinedBattlegroundPacket(&data, err);
+ SendPacket(&data);
+ return;
+ }
+
// check if player can queue:
if (!asGroup)
{
diff --git a/src/server/game/Handlers/GroupHandler.cpp b/src/server/game/Handlers/GroupHandler.cpp
index e28dfac518..0920474e6d 100644
--- a/src/server/game/Handlers/GroupHandler.cpp
+++ b/src/server/game/Handlers/GroupHandler.cpp
@@ -14,6 +14,7 @@
#include "Opcodes.h"
#include "Pet.h"
#include "Player.h"
+#include "ScriptMgr.h"
#include "SocialMgr.h"
#include "SpellAuras.h"
#include "Util.h"
@@ -74,6 +75,9 @@ void WorldSession::HandleGroupInviteOpcode(WorldPacket& recvData)
return;
}
+ if (!sScriptMgr->CanGroupInvite(GetPlayer(), membername))
+ return;
+
if (GetPlayer()->IsSpectator() || player->IsSpectator())
{
SendPartyResult(PARTY_OP_INVITE, membername, ERR_INVITE_RESTRICTED);
@@ -224,6 +228,9 @@ void WorldSession::HandleGroupAcceptOpcode(WorldPacket& recvData)
return;
}
+ if (!sScriptMgr->CanGroupAccept(GetPlayer(), group))
+ return;
+
if (group->GetLeaderGUID() == GetPlayer()->GetGUID())
{
sLog->outError("HandleGroupAcceptOpcode: player %s(%d) tried to accept an invite to his own group", GetPlayer()->GetName().c_str(), GetPlayer()->GetGUIDLow());
diff --git a/src/server/game/Handlers/ItemHandler.cpp b/src/server/game/Handlers/ItemHandler.cpp
index b88c60acff..205c73ba4e 100644
--- a/src/server/game/Handlers/ItemHandler.cpp
+++ b/src/server/game/Handlers/ItemHandler.cpp
@@ -11,6 +11,7 @@
#include "ObjectMgr.h"
#include "Opcodes.h"
#include "Player.h"
+#include "ScriptMgr.h"
#include "SpellInfo.h"
#include "UpdateData.h"
#include "WorldPacket.h"
@@ -660,6 +661,9 @@ void WorldSession::HandleSellItemOpcode(WorldPacket& recvData)
Item* pItem = _player->GetItemByGuid(itemguid);
if (pItem)
{
+ if (!sScriptMgr->CanSellItem(_player, pItem, creature))
+ return;
+
// prevent sell not owner item
if (_player->GetGUID() != pItem->GetOwnerGUID())
{
diff --git a/src/server/game/Handlers/MailHandler.cpp b/src/server/game/Handlers/MailHandler.cpp
index 0b27534585..81e370eed7 100644
--- a/src/server/game/Handlers/MailHandler.cpp
+++ b/src/server/game/Handlers/MailHandler.cpp
@@ -14,6 +14,7 @@
#include "ObjectMgr.h"
#include "Opcodes.h"
#include "Player.h"
+#include "ScriptMgr.h"
#include "World.h"
#include "WorldPacket.h"
#include "WorldSession.h"
@@ -196,9 +197,7 @@ void WorldSession::HandleSendMail(WorldPacket& recvData)
}
}*/
- uint32 rc_account = receive
- ? receive->GetSession()->GetAccountId()
- : sObjectMgr->GetPlayerAccountIdByGUID(rc);
+ uint32 rc_account = receive ? receive->GetSession()->GetAccountId() : sObjectMgr->GetPlayerAccountIdByGUID(rc);
if (/*!accountBound*/ GetAccountId() != rc_account && !sWorld->getBoolConfig(CONFIG_ALLOW_TWO_SIDE_INTERACTION_MAIL) && player->GetTeamId() != rc_teamId && AccountMgr::IsPlayerAccount(GetSecurity()))
{
@@ -255,6 +254,9 @@ void WorldSession::HandleSendMail(WorldPacket& recvData)
return;
}
+ if (!sScriptMgr->CanSendMail(player, rc, mailbox, subject, body, money, COD, item))
+ return;
+
items[i] = item;
}
diff --git a/src/server/game/Handlers/NPCHandler.cpp b/src/server/game/Handlers/NPCHandler.cpp
index fce810b9c6..6f06b9b3d2 100644
--- a/src/server/game/Handlers/NPCHandler.cpp
+++ b/src/server/game/Handlers/NPCHandler.cpp
@@ -1019,6 +1019,8 @@ void WorldSession::HandleRepairItemOpcode(WorldPacket& recvData)
// reputation discount
float discountMod = _player->GetReputationPriceDiscount(unit);
+ sScriptMgr->OnBeforePlayerDurabilityRepair(_player, npcGUID, itemGUID, discountMod, guildBank);
+
if (itemGUID)
{
#if defined(ENABLE_EXTRAS) && defined(ENABLE_EXTRA_LOGS)
diff --git a/src/server/game/Handlers/PetitionsHandler.cpp b/src/server/game/Handlers/PetitionsHandler.cpp
index bfcfcb3f56..dda123537e 100644
--- a/src/server/game/Handlers/PetitionsHandler.cpp
+++ b/src/server/game/Handlers/PetitionsHandler.cpp
@@ -15,22 +15,12 @@
#include "ObjectMgr.h"
#include "Opcodes.h"
#include "PetitionMgr.h"
+#include "ScriptMgr.h"
#include "SocialMgr.h"
#include "World.h"
#include "WorldPacket.h"
#include "WorldSession.h"
-#define CHARTER_DISPLAY_ID 16161
-
-// Charters ID in item_template
-enum CharterItemIDs
-{
- GUILD_CHARTER = 5863,
- ARENA_TEAM_CHARTER_2v2 = 23560,
- ARENA_TEAM_CHARTER_3v3 = 23561,
- ARENA_TEAM_CHARTER_5v5 = 23562
-};
-
void WorldSession::HandlePetitionBuyOpcode(WorldPacket& recvData)
{
#if defined(ENABLE_EXTRAS) && defined(ENABLE_EXTRA_LOGS)
@@ -136,6 +126,8 @@ void WorldSession::HandlePetitionBuyOpcode(WorldPacket& recvData)
}
}
+ sScriptMgr->PetitionBuy(_player, creature, charterid, cost, type);
+
if (type == GUILD_CHARTER_TYPE)
{
if (sGuildMgr->GetGuildByName(name))
@@ -880,38 +872,65 @@ void WorldSession::SendPetitionShowList(uint64 guid)
WorldPacket data(SMSG_PETITION_SHOWLIST, 8 + 1 + 4 * 6);
data << guid; // npc guid
+ // For guild default
+ uint32 CharterEntry = GUILD_CHARTER;
+ uint32 CharterDispayID = CHARTER_DISPLAY_ID;
+ uint32 CharterCost = sWorld->getIntConfig(CONFIG_CHARTER_COST_GUILD);
+
if (creature->IsTabardDesigner())
{
+ sScriptMgr->PetitionShowList(_player, creature, CharterEntry, CharterDispayID, CharterCost);
+
data << uint8(1); // count
data << uint32(1); // index
- data << uint32(GUILD_CHARTER); // charter entry
- data << uint32(CHARTER_DISPLAY_ID); // charter display id
- data << uint32(sWorld->getIntConfig(CONFIG_CHARTER_COST_GUILD)); // charter cost
+ data << CharterEntry; // charter entry
+ data << CharterDispayID; // charter display id
+ data << CharterCost; // charter cost
data << uint32(0); // unknown
data << uint32(sWorld->getIntConfig(CONFIG_MIN_PETITION_SIGNS)); // required signs
}
else
{
- data << uint8(3); // count
+ // For 2v2 default
+ CharterEntry = ARENA_TEAM_CHARTER_2v2;
+ CharterDispayID = CHARTER_DISPLAY_ID;
+ CharterCost = sWorld->getIntConfig(CONFIG_CHARTER_COST_ARENA_2v2);
+
// 2v2
+ data << uint8(3); // count
+ sScriptMgr->PetitionShowList(_player, creature, CharterEntry, CharterDispayID, CharterCost);
data << uint32(1); // index
- data << uint32(ARENA_TEAM_CHARTER_2v2); // charter entry
- data << uint32(CHARTER_DISPLAY_ID); // charter display id
- data << uint32(sWorld->getIntConfig(CONFIG_CHARTER_COST_ARENA_2v2)); // charter cost
+ data << CharterEntry; // charter entry
+ data << CharterDispayID; // charter display id
+ data << CharterCost; // charter cost
data << uint32(2); // unknown
data << uint32(2); // required signs?
+
+ // For 3v3 default
+ CharterEntry = ARENA_TEAM_CHARTER_3v3;
+ CharterDispayID = CHARTER_DISPLAY_ID;
+ CharterCost = sWorld->getIntConfig(CONFIG_CHARTER_COST_ARENA_3v3);
+
// 3v3
+ sScriptMgr->PetitionShowList(_player, creature, CharterEntry, CharterDispayID, CharterCost);
data << uint32(2); // index
- data << uint32(ARENA_TEAM_CHARTER_3v3); // charter entry
- data << uint32(CHARTER_DISPLAY_ID); // charter display id
- data << uint32(sWorld->getIntConfig(CONFIG_CHARTER_COST_ARENA_3v3)); // charter cost
+ data << CharterEntry; // charter entry
+ data << CharterDispayID; // charter display id
+ data << CharterCost; // charter cost
data << uint32(3); // unknown
data << uint32(3); // required signs?
+
+ // For 3v3 default
+ CharterEntry = ARENA_TEAM_CHARTER_5v5;
+ CharterDispayID = CHARTER_DISPLAY_ID;
+ CharterCost = sWorld->getIntConfig(CONFIG_CHARTER_COST_ARENA_5v5);
+
// 5v5
+ sScriptMgr->PetitionShowList(_player, creature, CharterEntry, CharterDispayID, CharterCost);
data << uint32(3); // index
- data << uint32(ARENA_TEAM_CHARTER_5v5); // charter entry
- data << uint32(CHARTER_DISPLAY_ID); // charter display id
- data << uint32(sWorld->getIntConfig(CONFIG_CHARTER_COST_ARENA_5v5)); // charter cost
+ data << CharterEntry; // charter entry
+ data << CharterDispayID; // charter display id
+ data << CharterCost; // charter cost
data << uint32(5); // unknown
data << uint32(5); // required signs?
}
diff --git a/src/server/game/Handlers/SpellHandler.cpp b/src/server/game/Handlers/SpellHandler.cpp
index 1ffdf10081..4b5bc5285f 100644
--- a/src/server/game/Handlers/SpellHandler.cpp
+++ b/src/server/game/Handlers/SpellHandler.cpp
@@ -15,6 +15,7 @@
#include "ScriptMgr.h"
#include "Spell.h"
#include "SpellAuraEffects.h"
+#include "ScriptMgr.h"
#include "SpellAuras.h"
#include "SpellMgr.h"
#include "TemporarySummon.h"
@@ -343,6 +344,8 @@ void WorldSession::HandleCastSpellOpcode(WorldPacket& recvPacket)
uint8 castCount, castFlags;
recvPacket >> castCount >> spellId >> castFlags;
+ uint32 oldSpellId = spellId;
+
#if defined(ENABLE_EXTRAS) && defined(ENABLE_EXTRA_LOGS)
sLog->outDebug(LOG_FILTER_NETWORKIO, "WORLD: got cast spell packet, castCount: %u, spellId: %u, castFlags: %u, data length = %u", castCount, spellId, castFlags, (uint32)recvPacket.size());
#endif
@@ -404,6 +407,11 @@ void WorldSession::HandleCastSpellOpcode(WorldPacket& recvPacket)
}
}
+ sScriptMgr->ValidateSpellAtCastSpell(_player, oldSpellId, spellId, castCount, castFlags);
+
+ if (oldSpellId != spellId)
+ spellInfo = sSpellMgr->GetSpellInfo(spellId);
+
// Client is resending autoshot cast opcode when other spell is casted during shoot rotation
// Skip it to prevent "interrupt" message
if (spellInfo->IsAutoRepeatRangedSpell() && _player->GetCurrentSpell(CURRENT_AUTOREPEAT_SPELL)
@@ -443,6 +451,9 @@ void WorldSession::HandleCastSpellOpcode(WorldPacket& recvPacket)
}
Spell* spell = new Spell(mover, spellInfo, TRIGGERED_NONE, 0, false);
+
+ sScriptMgr->ValidateSpellAtCastSpellResult(_player, mover, spell, oldSpellId, spellId);
+
spell->m_cast_count = castCount; // set count of casts
spell->prepare(&targets);
}
diff --git a/src/server/game/Handlers/TradeHandler.cpp b/src/server/game/Handlers/TradeHandler.cpp
index 7734f5bbef..ea93790f33 100644
--- a/src/server/game/Handlers/TradeHandler.cpp
+++ b/src/server/game/Handlers/TradeHandler.cpp
@@ -12,6 +12,7 @@
#include "ObjectAccessor.h"
#include "Opcodes.h"
#include "Player.h"
+#include "ScriptMgr.h"
#include "SocialMgr.h"
#include "Spell.h"
#include "World.h"
@@ -640,6 +641,9 @@ void WorldSession::HandleInitiateTradeOpcode(WorldPacket& recvPacket)
return;
}
+ if (!sScriptMgr->CanInitTrade(_player, pOther))
+ return;
+
// OK start trade
_player->m_trade = new TradeData(_player, pOther);
pOther->m_trade = new TradeData(pOther, _player);
diff --git a/src/server/game/Instances/InstanceSaveMgr.cpp b/src/server/game/Instances/InstanceSaveMgr.cpp
index fbba193363..1d23fe4317 100644
--- a/src/server/game/Instances/InstanceSaveMgr.cpp
+++ b/src/server/game/Instances/InstanceSaveMgr.cpp
@@ -134,11 +134,14 @@ bool InstanceSaveManager::DeleteInstanceSaveIfNeeded(InstanceSave* save, bool sk
InstanceSave::InstanceSave(uint16 MapId, uint32 InstanceId, Difficulty difficulty, time_t resetTime, time_t extendedResetTime)
: m_resetTime(resetTime), m_extendedResetTime(extendedResetTime), m_instanceid(InstanceId), m_mapid(MapId), m_difficulty(IsSharedDifficultyMap(MapId) ? Difficulty(difficulty % 2) : difficulty), m_canReset(true), m_instanceData(""), m_completedEncounterMask(0)
{
+ sScriptMgr->OnConstructInstanceSave(this);
}
InstanceSave::~InstanceSave()
{
ASSERT(m_playerList.empty());
+
+ sScriptMgr->OnDestructInstanceSave(this);
}
void InstanceSave::InsertToDB()
@@ -169,6 +172,8 @@ void InstanceSave::InsertToDB()
stmt->setUInt32(4, completedEncounters);
stmt->setString(5, data);
CharacterDatabase.Execute(stmt);
+
+ sScriptMgr->OnInstanceSave(this);
}
time_t InstanceSave::GetResetTimeForDB()
diff --git a/src/server/game/Loot/LootMgr.cpp b/src/server/game/Loot/LootMgr.cpp
index 662419ef0d..c40916dab3 100644
--- a/src/server/game/Loot/LootMgr.cpp
+++ b/src/server/game/Loot/LootMgr.cpp
@@ -503,6 +503,8 @@ bool Loot::FillLoot(uint32 lootId, LootStore const& store, Player* lootOwner, bo
tab->Process(*this, store, lootMode, lootOwner); // Processing is done there, callback via Loot::AddItem()
+ sScriptMgr->OnAfterLootTemplateProcess(this, tab, store, lootOwner, personal, noEmptyError, lootMode);
+
// Setting access rights for group loot case
Group* group = lootOwner->GetGroup();
if (!personal && group)
diff --git a/src/server/game/Maps/MapManager.cpp b/src/server/game/Maps/MapManager.cpp
index 818d196967..d05378a422 100644
--- a/src/server/game/Maps/MapManager.cpp
+++ b/src/server/game/Maps/MapManager.cpp
@@ -22,6 +22,7 @@
#include "ObjectAccessor.h"
#include "ObjectMgr.h"
#include "Opcodes.h"
+#include "ScriptMgr.h"
#include "Player.h"
#include "Transport.h"
#include "World.h"
@@ -153,6 +154,9 @@ bool MapManager::CanPlayerEnter(uint32 mapid, Player* player, bool loginCheck)
char const* mapName = entry->name[player->GetSession()->GetSessionDbcLocale()];
+ if (!sScriptMgr->CanEnterMap(player, entry, instance, mapDiff, loginCheck))
+ return false;
+
Group* group = player->GetGroup();
if (entry->IsRaid())
{
diff --git a/src/server/game/Petitions/PetitionMgr.h b/src/server/game/Petitions/PetitionMgr.h
index 1401ea735b..175f1223d3 100644
--- a/src/server/game/Petitions/PetitionMgr.h
+++ b/src/server/game/Petitions/PetitionMgr.h
@@ -8,6 +8,17 @@ Xinef
#include "Common.h"
#include <map>
+#define CHARTER_DISPLAY_ID 16161
+
+// Charters ID in item_template
+enum CharterItemIDs
+{
+ GUILD_CHARTER = 5863,
+ ARENA_TEAM_CHARTER_2v2 = 23560,
+ ARENA_TEAM_CHARTER_3v3 = 23561,
+ ARENA_TEAM_CHARTER_5v5 = 23562
+};
+
typedef std::map<uint32, uint32> SignatureMap;
struct Petition
diff --git a/src/server/game/Scripting/ScriptMgr.cpp b/src/server/game/Scripting/ScriptMgr.cpp
index 2dda13f032..2a691b7ffd 100644
--- a/src/server/game/Scripting/ScriptMgr.cpp
+++ b/src/server/game/Scripting/ScriptMgr.cpp
@@ -64,6 +64,11 @@ template class ScriptRegistry<SpellSC>;
template class ScriptRegistry<AccountScript>;
template class ScriptRegistry<GameEventScript>;
template class ScriptRegistry<MailScript>;
+template class ScriptRegistry<AchievementScript>;
+template class ScriptRegistry<MiscScript>;
+template class ScriptRegistry<PetScript>;
+template class ScriptRegistry<ArenaScript>;
+template class ScriptRegistry<CommandSC>;
#include "ScriptMgrMacros.h"
@@ -124,10 +129,15 @@ void ScriptMgr::Unload()
SCR_CLEAR(GlobalScript);
SCR_CLEAR(ModuleScript);
SCR_CLEAR(BGScript);
+ SCR_CLEAR(AchievementScript);
SCR_CLEAR(ArenaTeamScript);
SCR_CLEAR(SpellSC);
SCR_CLEAR(GameEventScript);
SCR_CLEAR(MailScript);
+ SCR_CLEAR(MiscScript);
+ SCR_CLEAR(PetScript);
+ SCR_CLEAR(ArenaScript);
+ SCR_CLEAR(CommandSC);
#undef SCR_CLEAR
}
@@ -198,8 +208,13 @@ void ScriptMgr::CheckIfScriptsInDatabaseExist()
!ScriptRegistry<PlayerScript>::GetScriptById(sid) &&
!ScriptRegistry<GuildScript>::GetScriptById(sid) &&
!ScriptRegistry<BGScript>::GetScriptById(sid) &&
+ !ScriptRegistry<AchievementScript>::GetScriptById(sid) &&
!ScriptRegistry<ArenaTeamScript>::GetScriptById(sid) &&
!ScriptRegistry<SpellSC>::GetScriptById(sid) &&
+ !ScriptRegistry<MiscScript>::GetScriptById(sid) &&
+ !ScriptRegistry<PetScript>::GetScriptById(sid) &&
+ !ScriptRegistry<CommandSC>::GetScriptById(sid) &&
+ !ScriptRegistry<ArenaScript>::GetScriptById(sid) &&
!ScriptRegistry<GroupScript>::GetScriptById(sid))
sLog->outErrorDb("Script named '%s' is assigned in the database, but has no code!", (*itr).c_str());
}
@@ -347,6 +362,11 @@ void ScriptMgr::CreateSpellScriptLoaders(uint32 spellId, std::vector<std::pair<S
}
}
+void ScriptMgr::OnBeforePlayerDurabilityRepair(Player* player, uint64 npcGUID, uint64 itemGUID, float& discountMod, uint8 guildBank)
+{
+ FOREACH_SCRIPT(PlayerScript)->OnBeforeDurabilityRepair(player, npcGUID, itemGUID, discountMod, guildBank);
+}
+
void ScriptMgr::OnNetworkStart()
{
FOREACH_SCRIPT(ServerScript)->OnNetworkStart();
@@ -1961,9 +1981,9 @@ void ScriptMgr::OnItemRoll(Player const* player, LootStoreItem const* LootStoreI
FOREACH_SCRIPT(GlobalScript)->OnItemRoll(player, LootStoreItem, chance, loot, store);
}
-void ScriptMgr::OnInitializeLockedDungeons(Player* player, uint8& level, uint32& lockData)
+void ScriptMgr::OnInitializeLockedDungeons(Player* player, uint8& level, uint32& lockData, lfg::LFGDungeonData const* dungeon)
{
- FOREACH_SCRIPT(GlobalScript)->OnInitializeLockedDungeons(player, level, lockData);
+ FOREACH_SCRIPT(GlobalScript)->OnInitializeLockedDungeons(player, level, lockData, dungeon);
}
void ScriptMgr::OnAfterInitializeLockedDungeons(Player* player)
@@ -2037,7 +2057,7 @@ void ScriptMgr::OnBeforeBuyItemFromVendor(Player* player, uint64 vendorguid, uin
FOREACH_SCRIPT(PlayerScript)->OnBeforeBuyItemFromVendor(player, vendorguid, vendorslot, item, count, bag, slot);
}
-void ScriptMgr::OnAfterStoreOrEquipNewItem(Player* player, uint32 vendorslot, uint32& item, uint8 count, uint8 bag, uint8 slot, ItemTemplate const* pProto, Creature* pVendor, VendorItem const* crItem, bool bStore)
+void ScriptMgr::OnAfterStoreOrEquipNewItem(Player* player, uint32 vendorslot, Item* item, uint8 count, uint8 bag, uint8 slot, ItemTemplate const* pProto, Creature* pVendor, VendorItem const* crItem, bool bStore)
{
FOREACH_SCRIPT(PlayerScript)->OnAfterStoreOrEquipNewItem(player, vendorslot, item, count, bag, slot, pProto, pVendor, crItem, bStore);
}
@@ -2136,17 +2156,6 @@ void ScriptMgr::OnCheckNormalMatch(BattlegroundQueue* queue, uint32& Coef, Battl
FOREACH_SCRIPT(BGScript)->OnCheckNormalMatch(queue, Coef, bgTemplate, bracket_id, minPlayers, maxPlayers);
}
-bool ScriptMgr::CanSendMessageQueue(BattlegroundQueue* queue, Player* leader, Battleground* bg, PvPDifficultyEntry const* bracketEntry)
-{
- bool ret = true;
-
- FOR_SCRIPTS_RET(BGScript, itr, end, ret) // return true by default if not scripts
- if (!itr->second->CanSendMessageQueue(queue, leader, bg, bracketEntry))
- ret = false; // we change ret value only when scripts return false
-
- return ret;
-}
-
void ScriptMgr::OnGetSlotByType(const uint32 type, uint8& slot)
{
FOREACH_SCRIPT(ArenaTeamScript)->OnGetSlotByType(type, slot);
@@ -2200,6 +2209,851 @@ void ScriptMgr::OnBeforeMailDraftSendMailTo(MailDraft* mailDraft, MailReceiver c
FOREACH_SCRIPT(MailScript)->OnBeforeMailDraftSendMailTo(mailDraft, receiver, sender, checked, deliver_delay, custom_expiration, deleteMailItemsFromDB, sendMail);
}
+void ScriptMgr::OnBeforeUpdatingPersonalRating(int32& mod, uint32 type)
+{
+ FOREACH_SCRIPT(FormulaScript)->OnBeforeUpdatingPersonalRating(mod, type);
+}
+
+bool ScriptMgr::OnBeforePlayerQuestComplete(Player* player, uint32 quest_id)
+{
+ bool ret=true;
+ FOR_SCRIPTS_RET(PlayerScript, itr, end, ret) // return true by default if not scripts
+ if (!itr->second->OnBeforeQuestComplete(player, quest_id))
+ ret=false; // we change ret value only when scripts return false
+
+ return ret;
+}
+
+void ScriptMgr::OnBeforeStoreOrEquipNewItem(Player* player, uint32 vendorslot, uint32& item, uint8 count, uint8 bag, uint8 slot, ItemTemplate const* pProto, Creature* pVendor, VendorItem const* crItem, bool bStore)
+{
+ FOREACH_SCRIPT(PlayerScript)->OnBeforeStoreOrEquipNewItem(player, vendorslot, item, count, bag, slot, pProto, pVendor, crItem, bStore);
+}
+
+bool ScriptMgr::CanJoinInArenaQueue(Player* player, uint64 BattlemasterGuid, uint8 arenaslot, BattlegroundTypeId BGTypeID, uint8 joinAsGroup, uint8 IsRated, GroupJoinBattlegroundResult& err)
+{
+ bool ret = true;
+
+ FOR_SCRIPTS_RET(PlayerScript, itr, end, ret) // return true by default if not scripts
+ if (!itr->second->CanJoinInArenaQueue(player, BattlemasterGuid, arenaslot, BGTypeID, joinAsGroup, IsRated, err))
+ ret = false; // we change ret value only when scripts return false
+
+ return ret;
+}
+
+bool ScriptMgr::CanBattleFieldPort(Player* player, uint8 arenaType, BattlegroundTypeId BGTypeID, uint8 action)
+{
+ bool ret = true;
+
+ FOR_SCRIPTS_RET(PlayerScript, itr, end, ret) // return true by default if not scripts
+ if (!itr->second->CanBattleFieldPort(player, arenaType, BGTypeID, action))
+ ret = false; // we change ret value only when scripts return false
+
+ return ret;
+}
+
+bool ScriptMgr::CanGroupInvite(Player* player, std::string& membername)
+{
+ bool ret = true;
+
+ FOR_SCRIPTS_RET(PlayerScript, itr, end, ret) // return true by default if not scripts
+ if (!itr->second->CanGroupInvite(player, membername))
+ ret = false; // we change ret value only when scripts return false
+
+ return ret;
+}
+
+bool ScriptMgr::CanGroupAccept(Player* player, Group* group)
+{
+ bool ret = true;
+
+ FOR_SCRIPTS_RET(PlayerScript, itr, end, ret) // return true by default if not scripts
+ if (!itr->second->CanGroupAccept(player, group))
+ ret = false; // we change ret value only when scripts return false
+
+ return ret;
+}
+
+bool ScriptMgr::CanSellItem(Player* player, Item* item, Creature* creature)
+{
+ bool ret = true;
+
+ FOR_SCRIPTS_RET(PlayerScript, itr, end, ret) // return true by default if not scripts
+ if (!itr->second->CanSellItem(player, item, creature))
+ ret = false; // we change ret value only when scripts return false
+
+ return ret;
+}
+
+bool ScriptMgr::CanSendMail(Player* player, uint64 receiverGuid, uint64 mailbox, std::string& subject, std::string& body, uint32 money, uint32 COD, Item* item)
+{
+ bool ret = true;
+
+ FOR_SCRIPTS_RET(PlayerScript, itr, end, ret) // return true by default if not scripts
+ if (!itr->second->CanSendMail(player, receiverGuid, mailbox, subject, body, money, COD, item))
+ ret = false; // we change ret value only when scripts return false
+
+ return ret;
+}
+
+void ScriptMgr::PetitionBuy(Player* player, Creature* creature, uint32& charterid, uint32& cost, uint32& type)
+{
+ FOREACH_SCRIPT(PlayerScript)->PetitionBuy(player, creature, charterid, cost, type);
+}
+
+void ScriptMgr::PetitionShowList(Player* player, Creature* creature, uint32& CharterEntry, uint32& CharterDispayID, uint32& CharterCost)
+{
+ FOREACH_SCRIPT(PlayerScript)->PetitionShowList(player, creature, CharterEntry, CharterDispayID, CharterCost);
+}
+
+void ScriptMgr::OnRewardKillRewarder(Player* player, bool isDungeon, float& rate)
+{
+ FOREACH_SCRIPT(PlayerScript)->OnRewardKillRewarder(player, isDungeon, rate);
+}
+
+bool ScriptMgr::CanGiveMailRewardAtGiveLevel(Player* player, uint8 level)
+{
+ bool ret = true;
+
+ FOR_SCRIPTS_RET(PlayerScript, itr, end, ret) // return true by default if not scripts
+ if (!itr->second->CanGiveMailRewardAtGiveLevel(player, level))
+ ret = false; // we change ret value only when scripts return false
+
+ return ret;
+}
+
+void ScriptMgr::OnDeleteFromDB(SQLTransaction& trans, uint32 guid)
+{
+ FOREACH_SCRIPT(PlayerScript)->OnDeleteFromDB(trans, guid);
+}
+
+bool ScriptMgr::CanRepopAtGraveyard(Player* player)
+{
+ bool ret = true;
+
+ FOR_SCRIPTS_RET(PlayerScript, itr, end, ret) // return true by default if not scripts
+ if (!itr->second->CanRepopAtGraveyard(player))
+ ret = false; // we change ret value only when scripts return false
+
+ return ret;
+}
+
+void ScriptMgr::OnGetMaxSkillValue(Player* player, uint32 skill, int32& result, bool IsPure)
+{
+ FOREACH_SCRIPT(PlayerScript)->OnGetMaxSkillValue(player, skill, result, IsPure);
+}
+
+bool ScriptMgr::CanAreaExploreAndOutdoor(Player* player)
+{
+ bool ret = true;
+
+ FOR_SCRIPTS_RET(PlayerScript, itr, end, ret) // return true by default if not scripts
+ if (!itr->second->CanAreaExploreAndOutdoor(player))
+ ret = false; // we change ret value only when scripts return false
+
+ return ret;
+}
+
+void ScriptMgr::OnVictimRewardBefore(Player* player, Player* victim, uint32& killer_title, uint32& victim_title)
+{
+ FOREACH_SCRIPT(PlayerScript)->OnVictimRewardBefore(player, victim, killer_title, victim_title);
+}
+
+void ScriptMgr::OnVictimRewardAfter(Player* player, Player* victim, uint32& killer_title, uint32& victim_rank, float& honor_f)
+{
+ FOREACH_SCRIPT(PlayerScript)->OnVictimRewardAfter(player, victim, killer_title, victim_rank, honor_f);
+}
+
+void ScriptMgr::OnCustomScalingStatValueBefore(Player* player, ItemTemplate const* proto, uint8 slot, bool apply, uint32& CustomScalingStatValue)
+{
+ FOREACH_SCRIPT(PlayerScript)->OnCustomScalingStatValueBefore(player, proto, slot, apply, CustomScalingStatValue);
+}
+
+void ScriptMgr::OnCustomScalingStatValue(Player* player, ItemTemplate const* proto, uint32& statType, int32& val, uint8 itemProtoStatNumber, uint32 ScalingStatValue, ScalingStatValuesEntry const* ssv)
+{
+ FOREACH_SCRIPT(PlayerScript)->OnCustomScalingStatValue(player, proto, statType, val, itemProtoStatNumber, ScalingStatValue, ssv);
+}
+
+bool ScriptMgr::CanArmorDamageModifier(Player* player)
+{
+ bool ret = true;
+
+ FOR_SCRIPTS_RET(PlayerScript, itr, end, ret) // return true by default if not scripts
+ if (!itr->second->CanArmorDamageModifier(player))
+ ret = false; // we change ret value only when scripts return false
+
+ return ret;
+}
+
+void ScriptMgr::OnGetFeralApBonus(Player* player, int32& feral_bonus, int32 dpsMod, ItemTemplate const* proto, ScalingStatValuesEntry const* ssv)
+{
+ FOREACH_SCRIPT(PlayerScript)->OnGetFeralApBonus(player, feral_bonus, dpsMod, proto, ssv);
+}
+
+bool ScriptMgr::CanApplyWeaponDependentAuraDamageMod(Player* player, Item* item, WeaponAttackType attackType, AuraEffect const* aura, bool apply)
+{
+ bool ret = true;
+
+ FOR_SCRIPTS_RET(PlayerScript, itr, end, ret) // return true by default if not scripts
+ if (!itr->second->CanApplyWeaponDependentAuraDamageMod(player, item, attackType, aura, apply))
+ ret = false; // we change ret value only when scripts return false
+
+ return ret;
+}
+
+bool ScriptMgr::CanApplyEquipSpell(Player* player, SpellInfo const* spellInfo, Item* item, bool apply, bool form_change)
+{
+ bool ret = true;
+
+ FOR_SCRIPTS_RET(PlayerScript, itr, end, ret) // return true by default if not scripts
+ if (!itr->second->CanApplyEquipSpell(player, spellInfo, item, apply, form_change))
+ ret = false; // we change ret value only when scripts return false
+
+ return ret;
+}
+
+bool ScriptMgr::CanApplyEquipSpellsItemSet(Player* player, ItemSetEffect* eff)
+{
+ bool ret = true;
+
+ FOR_SCRIPTS_RET(PlayerScript, itr, end, ret) // return true by default if not scripts
+ if (!itr->second->CanApplyEquipSpellsItemSet(player, eff))
+ ret = false; // we change ret value only when scripts return false
+
+ return ret;
+}
+
+bool ScriptMgr::CanCastItemCombatSpell(Player* player, Unit* target, WeaponAttackType attType, uint32 procVictim, uint32 procEx, Item* item, ItemTemplate const* proto)
+{
+ bool ret = true;
+
+ FOR_SCRIPTS_RET(PlayerScript, itr, end, ret) // return true by default if not scripts
+ if (!itr->second->CanCastItemCombatSpell(player, target, attType, procVictim, procEx, item, proto))
+ ret = false; // we change ret value only when scripts return false
+
+ return ret;
+}
+
+bool ScriptMgr::CanCastItemUseSpell(Player* player, Item* item, SpellCastTargets const& targets, uint8 cast_count, uint32 glyphIndex)
+{
+ bool ret = true;
+
+ FOR_SCRIPTS_RET(PlayerScript, itr, end, ret) // return true by default if not scripts
+ if (!itr->second->CanCastItemUseSpell(player, item, targets, cast_count, glyphIndex))
+ ret = false; // we change ret value only when scripts return false
+
+ return ret;
+}
+
+void ScriptMgr::OnApplyAmmoBonuses(Player* player, ItemTemplate const* proto, float& currentAmmoDPS)
+{
+ FOREACH_SCRIPT(PlayerScript)->OnApplyAmmoBonuses(player, proto, currentAmmoDPS);
+}
+
+bool ScriptMgr::CanEquipItem(Player* player, uint8 slot, uint16& dest, Item* pItem, bool swap, bool not_loading)
+{
+ bool ret = true;
+
+ FOR_SCRIPTS_RET(PlayerScript, itr, end, ret) // return true by default if not scripts
+ if (!itr->second->CanEquipItem(player, slot, dest, pItem, swap, not_loading))
+ ret = false; // we change ret value only when scripts return false
+
+ return ret;
+}
+
+bool ScriptMgr::CanUnequipItem(Player* player, uint16 pos, bool swap)
+{
+ bool ret = true;
+
+ FOR_SCRIPTS_RET(PlayerScript, itr, end, ret) // return true by default if not scripts
+ if (!itr->second->CanUnequipItem(player, pos, swap))
+ ret = false; // we change ret value only when scripts return false
+
+ return ret;
+}
+
+bool ScriptMgr::CanUseItem(Player* player, ItemTemplate const* proto, InventoryResult& result)
+{
+ bool ret = true;
+
+ FOR_SCRIPTS_RET(PlayerScript, itr, end, ret) // return true by default if not scripts
+ if (!itr->second->CanUseItem(player, proto, result))
+ ret = false; // we change ret value only when scripts return false
+
+ return ret;
+}
+
+bool ScriptMgr::CanSaveEquipNewItem(Player* player, Item* item, uint16 pos, bool update)
+{
+ bool ret = true;
+
+ FOR_SCRIPTS_RET(PlayerScript, itr, end, ret) // return true by default if not scripts
+ if (!itr->second->CanSaveEquipNewItem(player, item, pos, update))
+ ret = false; // we change ret value only when scripts return false
+
+ return ret;
+}
+
+bool ScriptMgr::CanApplyEnchantment(Player* player, Item* item, EnchantmentSlot slot, bool apply, bool apply_dur, bool ignore_condition)
+{
+ bool ret = true;
+
+ FOR_SCRIPTS_RET(PlayerScript, itr, end, ret) // return true by default if not scripts
+ if (!itr->second->CanApplyEnchantment(player, item, slot, apply, apply_dur, ignore_condition))
+ ret = false; // we change ret value only when scripts return false
+
+ return ret;
+}
+
+void ScriptMgr::OnGetQuestRate(Player* player, float& result)
+{
+ FOREACH_SCRIPT(PlayerScript)->OnGetQuestRate(player, result);
+}
+
+bool ScriptMgr::PassedQuestKilledMonsterCredit(Player* player, Quest const* qinfo, uint32 entry, uint32 real_entry, uint64 guid)
+{
+ bool ret = true;
+
+ FOR_SCRIPTS_RET(PlayerScript, itr, end, ret) // return true by default if not scripts
+ if (!itr->second->PassedQuestKilledMonsterCredit(player, qinfo, entry, real_entry, guid))
+ ret = false; // we change ret value only when scripts return false
+
+ return ret;
+}
+
+bool ScriptMgr::CheckItemInSlotAtLoadInventory(Player* player, Item* item, uint8 slot, uint8& err, uint16& dest)
+{
+ bool ret = true;
+
+ FOR_SCRIPTS_RET(PlayerScript, itr, end, ret) // return true by default if not scripts
+ if (!itr->second->CheckItemInSlotAtLoadInventory(player, item, slot, err, dest))
+ ret = false; // we change ret value only when scripts return false
+
+ return ret;
+}
+
+bool ScriptMgr::NotAvoidSatisfy(Player* player, DungeonProgressionRequirements const* ar, uint32 target_map, bool report)
+{
+ bool ret = true;
+
+ FOR_SCRIPTS_RET(PlayerScript, itr, end, ret) // return true by default if not scripts
+ if (!itr->second->NotAvoidSatisfy(player, ar, target_map, report))
+ ret = false; // we change ret value only when scripts return false
+
+ return ret;
+}
+
+bool ScriptMgr::NotVisibleGloballyFor(Player* player, Player const* u)
+{
+ bool ret = true;
+
+ FOR_SCRIPTS_RET(PlayerScript, itr, end, ret) // return true by default if not scripts
+ if (!itr->second->NotVisibleGloballyFor(player, u))
+ ret = false; // we change ret value only when scripts return false
+
+ return ret;
+}
+
+void ScriptMgr::OnGetArenaPersonalRating(Player* player, uint8 slot, uint32& result)
+{
+ FOREACH_SCRIPT(PlayerScript)->OnGetArenaPersonalRating(player, slot, result);
+}
+
+void ScriptMgr::OnGetArenaTeamId(Player* player, uint8 slot, uint32& result)
+{
+ FOREACH_SCRIPT(PlayerScript)->OnGetArenaTeamId(player, slot, result);
+}
+
+void ScriptMgr::OnIsFFAPvP(Player* player, bool& result)
+{
+ FOREACH_SCRIPT(PlayerScript)->OnIsFFAPvP(player, result);
+}
+
+void ScriptMgr::OnIsPvP(Player* player, bool& result)
+{
+ FOREACH_SCRIPT(PlayerScript)->OnIsPvP(player, result);
+}
+
+void ScriptMgr::OnGetMaxSkillValueForLevel(Player* player, uint16& result)
+{
+ FOREACH_SCRIPT(PlayerScript)->OnGetMaxSkillValueForLevel(player, result);
+}
+
+bool ScriptMgr::NotSetArenaTeamInfoField(Player* player, uint8 slot, ArenaTeamInfoType type, uint32 value)
+{
+ bool ret = true;
+
+ FOR_SCRIPTS_RET(PlayerScript, itr, end, ret) // return true by default if not scripts
+ if (!itr->second->NotSetArenaTeamInfoField(player, slot, type, value))
+ ret = false; // we change ret value only when scripts return false
+
+ return ret;
+}
+
+bool ScriptMgr::CanJoinLfg(Player* player, uint8 roles, lfg::LfgDungeonSet& dungeons, const std::string& comment)
+{
+ bool ret = true;
+
+ FOR_SCRIPTS_RET(PlayerScript, itr, end, ret) // return true by default if not scripts
+ if (!itr->second->CanJoinLfg(player, roles, dungeons, comment))
+ ret = false; // we change ret value only when scripts return false
+
+ return ret;
+}
+
+bool ScriptMgr::CanEnterMap(Player* player, MapEntry const* entry, InstanceTemplate const* instance, MapDifficulty const* mapDiff, bool loginCheck)
+{
+ bool ret = true;
+
+ FOR_SCRIPTS_RET(PlayerScript, itr, end, ret) // return true by default if not scripts
+ if (!itr->second->CanEnterMap(player, entry, instance, mapDiff, loginCheck))
+ ret = false; // we change ret value only when scripts return false
+
+ return ret;
+}
+
+bool ScriptMgr::CanInitTrade(Player* player, Player* target)
+{
+ bool ret = true;
+
+ FOR_SCRIPTS_RET(PlayerScript, itr, end, ret) // return true by default if not scripts
+ if (!itr->second->CanInitTrade(player, target))
+ ret = false; // we change ret value only when scripts return false
+
+ return ret;
+}
+
+void ScriptMgr::OnSetServerSideVisibility(Player* player, ServerSideVisibilityType& type, AccountTypes& sec)
+{
+ FOREACH_SCRIPT(PlayerScript)->OnSetServerSideVisibility(player, type, sec);
+}
+
+void ScriptMgr::OnSetServerSideVisibilityDetect(Player* player, ServerSideVisibilityType& type, AccountTypes& sec)
+{
+ FOREACH_SCRIPT(PlayerScript)->OnSetServerSideVisibilityDetect(player, type, sec);
+}
+
+bool ScriptMgr::CanGuildSendBankList(Guild const* guild, WorldSession* session, uint8 tabId, bool sendAllSlots)
+{
+ bool ret = true;
+
+ FOR_SCRIPTS_RET(GuildScript, itr, end, ret) // return true by default if not scripts
+ if (!itr->second->CanGuildSendBankList(guild, session, tabId, sendAllSlots))
+ ret = false; // we change ret value only when scripts return true
+
+ return ret;
+}
+
+bool ScriptMgr::CanGroupJoinBattlegroundQueue(Group const* group, Player* member, Battleground const* bgTemplate, uint32 MinPlayerCount, bool isRated, uint32 arenaSlot)
+{
+ bool ret = true;
+
+ FOR_SCRIPTS_RET(GroupScript, itr, end, ret) // return true by default if not scripts
+ if (!itr->second->CanGroupJoinBattlegroundQueue(group, member, bgTemplate, MinPlayerCount, isRated, arenaSlot))
+ ret = false; // we change ret value only when scripts return true
+
+ return ret;
+}
+
+void ScriptMgr::OnCreate(Group* group, Player* leader)
+{
+ FOREACH_SCRIPT(GroupScript)->OnCreate(group, leader);
+}
+
+void ScriptMgr::OnAuraRemove(Unit* unit, AuraApplication* aurApp, AuraRemoveMode mode)
+{
+ FOREACH_SCRIPT(UnitScript)->OnAuraRemove(unit, aurApp, mode);
+}
+
+bool ScriptMgr::IfNormalReaction(Unit const* unit, Unit const* target, ReputationRank& repRank)
+{
+ bool ret = true;
+
+ FOR_SCRIPTS_RET(UnitScript, itr, end, ret) // return true by default if not scripts
+ if (!itr->second->IfNormalReaction(unit, target, repRank))
+ ret = false; // we change ret value only when scripts return false
+
+ return ret;
+}
+
+bool ScriptMgr::IsNeedModSpellDamagePercent(Unit const* unit, AuraEffect* auraEff, float& doneTotalMod, SpellInfo const* spellProto)
+{
+ bool ret = true;
+
+ FOR_SCRIPTS_RET(UnitScript, itr, end, ret) // return true by default if not scripts
+ if (!itr->second->IsNeedModSpellDamagePercent(unit, auraEff, doneTotalMod, spellProto))
+ ret = false; // we change ret value only when scripts return false
+
+ return ret;
+}
+
+bool ScriptMgr::IsNeedModMeleeDamagePercent(Unit const* unit, AuraEffect* auraEff, float& doneTotalMod, SpellInfo const* spellProto)
+{
+ bool ret = true;
+
+ FOR_SCRIPTS_RET(UnitScript, itr, end, ret) // return true by default if not scripts
+ if (!itr->second->IsNeedModMeleeDamagePercent(unit, auraEff, doneTotalMod, spellProto))
+ ret = false; // we change ret value only when scripts return false
+
+ return ret;
+}
+
+bool ScriptMgr::IsNeedModHealPercent(Unit const* unit, AuraEffect* auraEff, float& doneTotalMod, SpellInfo const* spellProto)
+{
+ bool ret = true;
+
+ FOR_SCRIPTS_RET(UnitScript, itr, end, ret) // return true by default if not scripts
+ if (!itr->second->IsNeedModHealPercent(unit, auraEff, doneTotalMod, spellProto))
+ ret = false; // we change ret value only when scripts return false
+
+ return ret;
+}
+
+bool ScriptMgr::CanSetPhaseMask(Unit const* unit, uint32 newPhaseMask, bool update)
+{
+ bool ret = true;
+
+ FOR_SCRIPTS_RET(UnitScript, itr, end, ret) // return true by default if not scripts
+ if (!itr->second->CanSetPhaseMask(unit, newPhaseMask, update))
+ ret = false; // we change ret value only when scripts return false
+
+ return ret;
+}
+
+bool ScriptMgr::IsCustomBuildValuesUpdate(Unit const* unit, uint8 updateType, ByteBuffer& fieldBuffer, Player const* target, uint16 index)
+{
+ bool ret = false;
+
+ FOR_SCRIPTS_RET(UnitScript, itr, end, ret) // return true by default if not scripts
+ if (itr->second->IsCustomBuildValuesUpdate(unit, updateType, fieldBuffer, target, index))
+ ret = true; // we change ret value only when scripts return true
+
+ return ret;
+}
+
+void ScriptMgr::OnQueueUpdate(BattlegroundQueue* queue, BattlegroundBracketId bracket_id, bool isRated, uint32 arenaRatedTeamId)
+{
+ FOREACH_SCRIPT(BGScript)->OnQueueUpdate(queue, bracket_id, isRated, arenaRatedTeamId);
+}
+
+bool ScriptMgr::CanSendMessageBGQueue(BattlegroundQueue* queue, Player* leader, Battleground* bg, PvPDifficultyEntry const* bracketEntry)
+{
+ bool ret = true;
+
+ FOR_SCRIPTS_RET(BGScript, itr, end, ret) // return true by default if not scripts
+ if (!itr->second->CanSendMessageBGQueue(queue, leader, bg, bracketEntry))
+ ret = false; // we change ret value only when scripts return false
+
+ return ret;
+}
+
+bool ScriptMgr::CanSendMessageArenaQueue(BattlegroundQueue* queue, GroupQueueInfo* ginfo, bool IsJoin)
+{
+ bool ret = true;
+
+ FOR_SCRIPTS_RET(BGScript, itr, end, ret) // return true by default if not scripts
+ if (!itr->second->CanSendMessageArenaQueue(queue, ginfo, IsJoin))
+ ret = false; // we change ret value only when scripts return false
+
+ return ret;
+}
+
+bool ScriptMgr::CanModAuraEffectDamageDone(AuraEffect const* auraEff, Unit* target, AuraApplication const* aurApp, uint8 mode, bool apply)
+{
+ bool ret = true;
+
+ FOR_SCRIPTS_RET(SpellSC, itr, end, ret) // return true by default if not scripts
+ if (!itr->second->CanModAuraEffectDamageDone(auraEff, target, aurApp, mode, apply))
+ ret = false; // we change ret value only when scripts return false
+
+ return ret;
+}
+
+bool ScriptMgr::CanModAuraEffectModDamagePercentDone(AuraEffect const* auraEff, Unit* target, AuraApplication const* aurApp, uint8 mode, bool apply)
+{
+ bool ret = true;
+
+ FOR_SCRIPTS_RET(SpellSC, itr, end, ret) // return true by default if not scripts
+ if (!itr->second->CanModAuraEffectModDamagePercentDone(auraEff, target, aurApp, mode, apply))
+ ret = false; // we change ret value only when scripts return false
+
+ return ret;
+}
+
+void ScriptMgr::OnSpellCheckCast(Spell* spell, bool strict, SpellCastResult& res)
+{
+ FOREACH_SCRIPT(SpellSC)->OnSpellCheckCast(spell, strict, res);
+}
+
+bool ScriptMgr::CanPrepare(Spell* spell, SpellCastTargets const* targets, AuraEffect const* triggeredByAura)
+{
+ bool ret = true;
+
+ FOR_SCRIPTS_RET(SpellSC, itr, end, ret) // return true by default if not scripts
+ if (!itr->second->CanPrepare(spell, targets, triggeredByAura))
+ ret = false; // we change ret value only when scripts return false
+
+ return ret;
+}
+
+bool ScriptMgr::CanScalingEverything(Spell* spell)
+{
+ bool ret = false;
+
+ FOR_SCRIPTS_RET(SpellSC, itr, end, ret) // return true by default if not scripts
+ if (itr->second->CanScalingEverything(spell))
+ ret = true; // we change ret value only when scripts return false
+
+ return ret;
+}
+
+bool ScriptMgr::CanSelectSpecTalent(Spell* spell)
+{
+ bool ret = true;
+
+ FOR_SCRIPTS_RET(SpellSC, itr, end, ret) // return true by default if not scripts
+ if (!itr->second->CanSelectSpecTalent(spell))
+ ret = false; // we change ret value only when scripts return false
+
+ return ret;
+}
+
+void ScriptMgr::OnScaleAuraUnitAdd(Spell* spell, Unit* target, uint32 effectMask, bool checkIfValid, bool implicit, uint8 auraScaleMask, TargetInfo& targetInfo)
+{
+ FOREACH_SCRIPT(SpellSC)->OnScaleAuraUnitAdd(spell, target, effectMask, checkIfValid, implicit, auraScaleMask, targetInfo);
+}
+
+void ScriptMgr::OnRemoveAuraScaleTargets(Spell* spell, TargetInfo& targetInfo, uint8 auraScaleMask, bool& needErase)
+{
+ FOREACH_SCRIPT(SpellSC)->OnRemoveAuraScaleTargets(spell, targetInfo, auraScaleMask, needErase);
+}
+
+void ScriptMgr::OnBeforeAuraRankForLevel(SpellInfo const* spellInfo, SpellInfo const* latestSpellInfo, uint8 level)
+{
+ FOREACH_SCRIPT(SpellSC)->OnBeforeAuraRankForLevel(spellInfo, latestSpellInfo, level);
+}
+
+void ScriptMgr::SetRealmCompleted(AchievementEntry const* achievement)
+{
+ FOREACH_SCRIPT(AchievementScript)->SetRealmCompleted(achievement);
+}
+
+bool ScriptMgr::IsCompletedCriteria(AchievementMgr* mgr, AchievementCriteriaEntry const* achievementCriteria, AchievementEntry const* achievement, CriteriaProgress const* progress)
+{
+ bool ret = true;
+
+ FOR_SCRIPTS_RET(AchievementScript, itr, end, ret) // return true by default if not scripts
+ if (!itr->second->IsCompletedCriteria(mgr, achievementCriteria, achievement, progress))
+ ret = false; // we change ret value only when scripts return false
+
+ return ret;
+}
+
+bool ScriptMgr::IsRealmCompleted(AchievementGlobalMgr const* globalmgr, AchievementEntry const* achievement, std::chrono::system_clock::time_point completionTime)
+{
+ bool ret = true;
+
+ FOR_SCRIPTS_RET(AchievementScript, itr, end, ret) // return true by default if not scripts
+ if (!itr->second->IsRealmCompleted(globalmgr, achievement, completionTime))
+ ret = false; // we change ret value only when scripts return false
+
+ return ret;
+}
+
+void ScriptMgr::OnBeforeCheckCriteria(AchievementMgr* mgr, AchievementCriteriaEntryList const* achievementCriteriaList)
+{
+ FOREACH_SCRIPT(AchievementScript)->OnBeforeCheckCriteria(mgr, achievementCriteriaList);
+}
+
+bool ScriptMgr::CanCheckCriteria(AchievementMgr* mgr, AchievementCriteriaEntry const* achievementCriteria)
+{
+ bool ret = true;
+
+ FOR_SCRIPTS_RET(AchievementScript, itr, end, ret) // return true by default if not scripts
+ if (!itr->second->CanCheckCriteria(mgr, achievementCriteria))
+ ret = false; // we change ret value only when scripts return false
+
+ return ret;
+}
+
+void ScriptMgr::OnInitStatsForLevel(Guardian* guardian, uint8 petlevel)
+{
+ FOREACH_SCRIPT(PetScript)->OnInitStatsForLevel(guardian, petlevel);
+}
+
+void ScriptMgr::OnCalculateMaxTalentPointsForLevel(Pet* pet, uint8 level, uint8& points)
+{
+ FOREACH_SCRIPT(PetScript)->OnCalculateMaxTalentPointsForLevel(pet, level, points);
+}
+
+bool ScriptMgr::CanUnlearnSpellSet(Pet* pet, uint32 level, uint32 spell)
+{
+ bool ret = true;
+
+ FOR_SCRIPTS_RET(PetScript, itr, end, ret) // return true by default if not scripts
+ if (!itr->second->CanUnlearnSpellSet(pet, level, spell))
+ ret = false; // we change ret value only when scripts return false
+
+ return ret;
+}
+
+bool ScriptMgr::CanUnlearnSpellDefault(Pet* pet, SpellInfo const* spellEntry)
+{
+ bool ret = true;
+
+ FOR_SCRIPTS_RET(PetScript, itr, end, ret) // return true by default if not scripts
+ if (!itr->second->CanUnlearnSpellDefault(pet, spellEntry))
+ ret = false; // we change ret value only when scripts return false
+
+ return ret;
+}
+
+bool ScriptMgr::CanResetTalents(Pet* pet)
+{
+ bool ret = true;
+
+ FOR_SCRIPTS_RET(PetScript, itr, end, ret) // return true by default if not scripts
+ if (!itr->second->CanResetTalents(pet))
+ ret = false; // we change ret value only when scripts return false
+
+ return ret;
+}
+
+bool ScriptMgr::CanAddMember(ArenaTeam* team, uint64 PlayerGuid)
+{
+ bool ret = true;
+
+ FOR_SCRIPTS_RET(ArenaScript, itr, end, ret) // return true by default if not scripts
+ if (!itr->second->CanAddMember(team, PlayerGuid))
+ ret = false; // we change ret value only when scripts return true
+
+ return ret;
+}
+
+void ScriptMgr::OnGetPoints(ArenaTeam* team, uint32 memberRating, float& points)
+{
+ FOREACH_SCRIPT(ArenaScript)->OnGetPoints(team, memberRating, points);
+}
+
+bool ScriptMgr::CanSaveToDB(ArenaTeam* team)
+{
+ bool ret = true;
+
+ FOR_SCRIPTS_RET(ArenaScript, itr, end, ret) // return true by default if not scripts
+ if (!itr->second->CanSaveToDB(team))
+ ret = false; // we change ret value only when scripts return true
+
+ return ret;
+}
+
+void ScriptMgr::OnItemCreate(Item* item, ItemTemplate const* itemProto, Player const* owner)
+{
+ FOREACH_SCRIPT(MiscScript)->OnItemCreate(item, itemProto, owner);
+}
+
+bool ScriptMgr::CanApplySoulboundFlag(Item* item, ItemTemplate const* proto)
+{
+ bool ret = true;
+
+ FOR_SCRIPTS_RET(MiscScript, itr, end, ret) // return true by default if not scripts
+ if (!itr->second->CanApplySoulboundFlag(item, proto))
+ ret = false; // we change ret value only when scripts return false
+
+ return ret;
+}
+
+void ScriptMgr::OnConstructObject(Object* origin)
+{
+ FOREACH_SCRIPT(MiscScript)->OnConstructObject(origin);
+}
+
+void ScriptMgr::OnDestructObject(Object* origin)
+{
+ FOREACH_SCRIPT(MiscScript)->OnDestructObject(origin);
+}
+
+void ScriptMgr::OnConstructPlayer(Player* origin)
+{
+ FOREACH_SCRIPT(MiscScript)->OnConstructPlayer(origin);
+}
+
+void ScriptMgr::OnDestructPlayer(Player* origin)
+{
+ FOREACH_SCRIPT(MiscScript)->OnDestructPlayer(origin);
+}
+
+void ScriptMgr::OnConstructGroup(Group* origin)
+{
+ FOREACH_SCRIPT(MiscScript)->OnConstructGroup(origin);
+}
+
+void ScriptMgr::OnDestructGroup(Group* origin)
+{
+ FOREACH_SCRIPT(MiscScript)->OnDestructGroup(origin);
+}
+
+void ScriptMgr::OnConstructInstanceSave(InstanceSave* origin)
+{
+ FOREACH_SCRIPT(MiscScript)->OnConstructInstanceSave(origin);
+}
+
+void ScriptMgr::OnDestructInstanceSave(InstanceSave* origin)
+{
+ FOREACH_SCRIPT(MiscScript)->OnDestructInstanceSave(origin);
+}
+
+bool ScriptMgr::CanItemApplyEquipSpell(Player* player, Item* item)
+{
+ bool ret = true;
+
+ FOR_SCRIPTS_RET(MiscScript, itr, end, ret) // return true by default if not scripts
+ if (!itr->second->CanItemApplyEquipSpell(player, item))
+ ret = false; // we change ret value only when scripts return false
+
+ return ret;
+}
+
+bool ScriptMgr::CanSendAuctionHello(WorldSession const* session, uint64 guid, Creature* creature)
+{
+ bool ret = true;
+
+ FOR_SCRIPTS_RET(MiscScript, itr, end, ret) // return true by default if not scripts
+ if (!itr->second->CanSendAuctionHello(session, guid, creature))
+ ret = false; // we change ret value only when scripts return false
+
+ return ret;
+}
+
+void ScriptMgr::ValidateSpellAtCastSpell(Player* player, uint32& oldSpellId, uint32& spellId, uint8& castCount, uint8& castFlags)
+{
+ FOREACH_SCRIPT(MiscScript)->ValidateSpellAtCastSpell(player, oldSpellId, spellId, castCount, castFlags);
+}
+
+void ScriptMgr::ValidateSpellAtCastSpellResult(Player* player, Unit* mover, Spell* spell, uint32 oldSpellId, uint32 spellId)
+{
+ FOREACH_SCRIPT(MiscScript)->ValidateSpellAtCastSpellResult(player, mover, spell, oldSpellId, spellId);
+}
+
+void ScriptMgr::OnAfterLootTemplateProcess(Loot* loot, LootTemplate const* tab, LootStore const& store, Player* lootOwner, bool personal, bool noEmptyError, uint16 lootMode)
+{
+ FOREACH_SCRIPT(MiscScript)->OnAfterLootTemplateProcess(loot, tab, store, lootOwner, personal, noEmptyError, lootMode);
+}
+
+void ScriptMgr::OnInstanceSave(InstanceSave* instanceSave)
+{
+ FOREACH_SCRIPT(MiscScript)->OnInstanceSave(instanceSave);
+}
+
+void ScriptMgr::OnPlayerSetPhase(const AuraEffect* auraEff, AuraApplication const* aurApp, uint8 mode, bool apply, uint32& newPhase)
+{
+ FOREACH_SCRIPT(MiscScript)->OnPlayerSetPhase(auraEff, aurApp, mode, apply, newPhase);
+}
+
+void ScriptMgr::OnHandleDevCommand(Player* player, std::string& argstr)
+{
+ FOREACH_SCRIPT(CommandSC)->OnHandleDevCommand(player, argstr);
+}
+
+///-
AllMapScript::AllMapScript(const char* name)
: ScriptObject(name)
{
@@ -2416,3 +3270,33 @@ MailScript::MailScript(const char* name)
{
ScriptRegistry<MailScript>::AddScript(this);
}
+
+AchievementScript::AchievementScript(const char* name)
+ : ScriptObject(name)
+{
+ ScriptRegistry<AchievementScript>::AddScript(this);
+}
+
+PetScript::PetScript(const char* name)
+ : ScriptObject(name)
+{
+ ScriptRegistry<PetScript>::AddScript(this);
+}
+
+ArenaScript::ArenaScript(const char* name)
+ : ScriptObject(name)
+{
+ ScriptRegistry<ArenaScript>::AddScript(this);
+}
+
+MiscScript::MiscScript(const char* name)
+ : ScriptObject(name)
+{
+ ScriptRegistry<MiscScript>::AddScript(this);
+}
+
+CommandSC::CommandSC(const char* name)
+ : ScriptObject(name)
+{
+ ScriptRegistry<CommandSC>::AddScript(this);
+}
diff --git a/src/server/game/Scripting/ScriptMgr.h b/src/server/game/Scripting/ScriptMgr.h
index 54703587e7..9359026a3f 100644
--- a/src/server/game/Scripting/ScriptMgr.h
+++ b/src/server/game/Scripting/ScriptMgr.h
@@ -15,6 +15,7 @@
#include "DBCStores.h"
#include "DynamicObject.h"
#include "GameEventMgr.h"
+#include "LFGMgr.h"
#include "ObjectMgr.h"
#include "PetDefines.h"
#include "QuestDef.h"
@@ -63,9 +64,11 @@ struct AchievementCriteriaData;
struct AuctionEntry;
struct ConditionSourceInfo;
struct Condition;
+struct DungeonProgressionRequirements;
struct ItemTemplate;
struct OutdoorPvPData;
struct GroupQueueInfo;
+struct TargetInfo;
#define VISIBLE_RANGE 166.0f //MAX visible range (size of grid)
@@ -287,6 +290,9 @@ public:
// Called after calculating arena rating changes
virtual void OnAfterArenaRatingCalculation(Battleground* const /*bg*/, int32& /*winnerMatchmakerChange*/, int32& /*loserMatchmakerChange*/, int32& /*winnerChange*/, int32& /*loserChange*/) { };
+
+ // Called before modifying a player's personal rating
+ virtual void OnBeforeUpdatingPersonalRating(int32& /*mod*/, uint32 /*type*/) { }
};
template<class TMap> class MapScript : public UpdatableScript<TMap>
@@ -397,19 +403,19 @@ public:
[[nodiscard]] bool IsDatabaseBound() const override { return true; }
// Called when a player accepts a quest from the item.
- virtual bool OnQuestAccept(Player* /*player*/, Item* /*item*/, Quest const* /*quest*/) { return false; }
+ [[nodiscard]] virtual bool OnQuestAccept(Player* /*player*/, Item* /*item*/, Quest const* /*quest*/) { return false; }
// Called when a player uses the item.
- virtual bool OnUse(Player* /*player*/, Item* /*item*/, SpellCastTargets const& /*targets*/) { return false; }
+ [[nodiscard]] virtual bool OnUse(Player* /*player*/, Item* /*item*/, SpellCastTargets const& /*targets*/) { return false; }
// Called when the item is destroyed.
- virtual bool OnRemove(Player* /*player*/, Item* /*item*/) { return false; }
+ [[nodiscard]] virtual bool OnRemove(Player* /*player*/, Item* /*item*/) { return false; }
// Called before casting a combat spell from this item (chance on hit spells of item template, can be used to prevent cast if returning false)
- virtual bool OnCastItemCombatSpell(Player* /*player*/, Unit* /*victim*/, SpellInfo const* /*spellInfo*/, Item* /*item*/) { return true; }
+ [[nodiscard]] virtual bool OnCastItemCombatSpell(Player* /*player*/, Unit* /*victim*/, SpellInfo const* /*spellInfo*/, Item* /*item*/) { return true; }
// Called when the item expires (is destroyed).
- virtual bool OnExpire(Player* /*player*/, ItemTemplate const* /*proto*/) { return false; }
+ [[nodiscard]] virtual bool OnExpire(Player* /*player*/, ItemTemplate const* /*proto*/) { return false; }
// Called when a player selects an option in an item gossip window
virtual void OnGossipSelect(Player* /*player*/, Item* /*item*/, uint32 /*sender*/, uint32 /*action*/) { }
@@ -447,6 +453,20 @@ public:
virtual uint32 DealDamage(Unit* /*AttackerUnit*/, Unit* /*pVictim*/, uint32 damage, DamageEffectType /*damagetype*/) { return damage; }
virtual void OnBeforeRollMeleeOutcomeAgainst(const Unit* /*attacker*/, const Unit* /*victim*/, WeaponAttackType /*attType*/, int32& /*attackerMaxSkillValueForLevel*/, int32& /*victimMaxSkillValueForLevel*/, int32& /*attackerWeaponSkill*/, int32& /*victimDefenseSkill*/, int32& /*crit_chance*/, int32& /*miss_chance*/, int32& /*dodge_chance*/, int32& /*parry_chance*/, int32& /*block_chance*/ ) { };
+
+ virtual void OnAuraRemove(Unit* /*unit*/, AuraApplication* /*aurApp*/, AuraRemoveMode /*mode*/) { }
+
+ [[nodiscard]] virtual bool IfNormalReaction(Unit const* /*unit*/, Unit const* /*target*/, ReputationRank& /*repRank*/) { return true; }
+
+ [[nodiscard]] virtual bool IsNeedModSpellDamagePercent(Unit const* /*unit*/, AuraEffect* /*auraEff*/, float& /*doneTotalMod*/, SpellInfo const* /*spellProto*/) { return true; }
+
+ [[nodiscard]] virtual bool IsNeedModMeleeDamagePercent(Unit const* /*unit*/, AuraEffect* /*auraEff*/, float& /*doneTotalMod*/, SpellInfo const* /*spellProto*/) { return true; }
+
+ [[nodiscard]] virtual bool IsNeedModHealPercent(Unit const* /*unit*/, AuraEffect* /*auraEff*/, float& /*doneTotalMod*/, SpellInfo const* /*spellProto*/) { return true; }
+
+ [[nodiscard]] virtual bool CanSetPhaseMask(Unit const* /*unit*/, uint32 /*newPhaseMask*/, bool /*update*/) { return true; }
+
+ [[nodiscard]] virtual bool IsCustomBuildValuesUpdate(Unit const* /*unit*/, uint8 /*updateType*/, ByteBuffer& /*fieldBuffer*/, Player const* /*target*/, uint16 /*index*/) { return false; }
};
class MovementHandlerScript : public ScriptObject
@@ -494,25 +514,25 @@ public:
[[nodiscard]] bool IsDatabaseBound() const override { return true; }
// Called when a player opens a gossip dialog with the creature.
- virtual bool OnGossipHello(Player* /*player*/, Creature* /*creature*/) { return false; }
+ [[nodiscard]] virtual bool OnGossipHello(Player* /*player*/, Creature* /*creature*/) { return false; }
// Called when a player selects a gossip item in the creature's gossip menu.
- virtual bool OnGossipSelect(Player* /*player*/, Creature* /*creature*/, uint32 /*sender*/, uint32 /*action*/) { return false; }
+ [[nodiscard]] virtual bool OnGossipSelect(Player* /*player*/, Creature* /*creature*/, uint32 /*sender*/, uint32 /*action*/) { return false; }
// Called when a player selects a gossip with a code in the creature's gossip menu.
- virtual bool OnGossipSelectCode(Player* /*player*/, Creature* /*creature*/, uint32 /*sender*/, uint32 /*action*/, const char* /*code*/) { return false; }
+ [[nodiscard]] virtual bool OnGossipSelectCode(Player* /*player*/, Creature* /*creature*/, uint32 /*sender*/, uint32 /*action*/, const char* /*code*/) { return false; }
// Called when a player accepts a quest from the creature.
- virtual bool OnQuestAccept(Player* /*player*/, Creature* /*creature*/, Quest const* /*quest*/) { return false; }
+ [[nodiscard]] virtual bool OnQuestAccept(Player* /*player*/, Creature* /*creature*/, Quest const* /*quest*/) { return false; }
// Called when a player selects a quest in the creature's quest menu.
- virtual bool OnQuestSelect(Player* /*player*/, Creature* /*creature*/, Quest const* /*quest*/) { return false; }
+ [[nodiscard]] virtual bool OnQuestSelect(Player* /*player*/, Creature* /*creature*/, Quest const* /*quest*/) { return false; }
// Called when a player completes a quest with the creature.
- virtual bool OnQuestComplete(Player* /*player*/, Creature* /*creature*/, Quest const* /*quest*/) { return false; }
+ [[nodiscard]] virtual bool OnQuestComplete(Player* /*player*/, Creature* /*creature*/, Quest const* /*quest*/) { return false; }
// Called when a player selects a quest reward.
- virtual bool OnQuestReward(Player* /*player*/, Creature* /*creature*/, Quest const* /*quest*/, uint32 /*opt*/) { return false; }
+ [[nodiscard]] virtual bool OnQuestReward(Player* /*player*/, Creature* /*creature*/, Quest const* /*quest*/, uint32 /*opt*/) { return false; }
// Called when the dialog status between a player and the creature is requested.
virtual uint32 GetDialogStatus(Player* /*player*/, Creature* /*creature*/) { return DIALOG_STATUS_SCRIPTED_NO_STATUS; }
@@ -530,19 +550,19 @@ public:
[[nodiscard]] bool IsDatabaseBound() const override { return true; }
// Called when a player opens a gossip dialog with the gameobject.
- virtual bool OnGossipHello(Player* /*player*/, GameObject* /*go*/) { return false; }
+ [[nodiscard]] virtual bool OnGossipHello(Player* /*player*/, GameObject* /*go*/) { return false; }
// Called when a player selects a gossip item in the gameobject's gossip menu.
- virtual bool OnGossipSelect(Player* /*player*/, GameObject* /*go*/, uint32 /*sender*/, uint32 /*action*/) { return false; }
+ [[nodiscard]] virtual bool OnGossipSelect(Player* /*player*/, GameObject* /*go*/, uint32 /*sender*/, uint32 /*action*/) { return false; }
// Called when a player selects a gossip with a code in the gameobject's gossip menu.
- virtual bool OnGossipSelectCode(Player* /*player*/, GameObject* /*go*/, uint32 /*sender*/, uint32 /*action*/, const char* /*code*/) { return false; }
+ [[nodiscard]] virtual bool OnGossipSelectCode(Player* /*player*/, GameObject* /*go*/, uint32 /*sender*/, uint32 /*action*/, const char* /*code*/) { return false; }
// Called when a player accepts a quest from the gameobject.
- virtual bool OnQuestAccept(Player* /*player*/, GameObject* /*go*/, Quest const* /*quest*/) { return false; }
+ [[nodiscard]] virtual bool OnQuestAccept(Player* /*player*/, GameObject* /*go*/, Quest const* /*quest*/) { return false; }
// Called when a player selects a quest reward.
- virtual bool OnQuestReward(Player* /*player*/, GameObject* /*go*/, Quest const* /*quest*/, uint32 /*opt*/) { return false; }
+ [[nodiscard]] virtual bool OnQuestReward(Player* /*player*/, GameObject* /*go*/, Quest const* /*quest*/, uint32 /*opt*/) { return false; }
// Called when the dialog status between a player and the gameobject is requested.
virtual uint32 GetDialogStatus(Player* /*player*/, GameObject* /*go*/) { return DIALOG_STATUS_SCRIPTED_NO_STATUS; }
@@ -572,7 +592,7 @@ public:
[[nodiscard]] bool IsDatabaseBound() const override { return true; }
// Called when the area trigger is activated by a player.
- virtual bool OnTrigger(Player* /*player*/, AreaTrigger const* /*trigger*/) { return false; }
+ [[nodiscard]] virtual bool OnTrigger(Player* /*player*/, AreaTrigger const* /*trigger*/) { return false; }
};
class BattlegroundScript : public ScriptObject
@@ -670,7 +690,7 @@ public:
[[nodiscard]] bool IsDatabaseBound() const override { return true; }
// Called when a single condition is checked for a player.
- virtual bool OnConditionCheck(Condition* /*condition*/, ConditionSourceInfo& /*sourceInfo*/) { return true; }
+ [[nodiscard]] virtual bool OnConditionCheck(Condition* /*condition*/, ConditionSourceInfo& /*sourceInfo*/) { return true; }
};
class VehicleScript : public ScriptObject
@@ -734,7 +754,7 @@ public:
[[nodiscard]] bool IsDatabaseBound() const override { return true; }
// deprecated/legacy
- virtual bool OnCheck(Player* /*source*/, Unit* /*target*/) { return true; };
+ [[nodiscard]] virtual bool OnCheck(Player* /*source*/, Unit* /*target*/) { return true; };
};
class PlayerScript : public ScriptObject
@@ -860,7 +880,7 @@ public:
virtual void OnMapChanged(Player* /*player*/) { }
// Called before a player is being teleported to new coords
- virtual bool OnBeforeTeleport(Player* /*player*/, uint32 /*mapid*/, float /*x*/, float /*y*/, float /*z*/, float /*orientation*/, uint32 /*options*/, Unit* /*target*/) { return true; }
+ [[nodiscard]] virtual bool OnBeforeTeleport(Player* /*player*/, uint32 /*mapid*/, float /*x*/, float /*y*/, float /*z*/, float /*orientation*/, uint32 /*options*/, Unit* /*target*/) { return true; }
// Called when team/faction is set on player
virtual void OnUpdateFaction(Player* /*player*/) { }
@@ -922,14 +942,23 @@ public:
//After creating item (eg profession item creation)
virtual void OnCreateItem(Player* /*player*/, Item* /*item*/, uint32 /*count*/) { }
- //After receiving item as a quest reward
+ // After receiving item as a quest reward
virtual void OnQuestRewardItem(Player* /*player*/, Item* /*item*/, uint32 /*count*/) { }
+ // After completed a quest
+ [[nodiscard]] virtual bool OnBeforeQuestComplete(Player* /*player*/, uint32 /*quest_id*/) { return true; }
+
+ // Before durability repair action, you can even modify the discount value
+ virtual void OnBeforeDurabilityRepair(Player* /*player*/, uint64 /*npcGUID*/, uint64 /*itemGUID*/, float&/*discountMod*/, uint8 /*guildBank*/) { }
+
//Before buying something from any vendor
virtual void OnBeforeBuyItemFromVendor(Player* /*player*/, uint64 /*vendorguid*/, uint32 /*vendorslot*/, uint32& /*item*/, uint8 /*count*/, uint8 /*bag*/, uint8 /*slot*/) { };
//Before buying something from any vendor
- virtual void OnAfterStoreOrEquipNewItem(Player* /*player*/, uint32 /*vendorslot*/, uint32& /*item*/, uint8 /*count*/, uint8 /*bag*/, uint8 /*slot*/, ItemTemplate const* /*pProto*/, Creature* /*pVendor*/, VendorItem const* /*crItem*/, bool /*bStore*/) { };
+ virtual void OnBeforeStoreOrEquipNewItem(Player* /*player*/, uint32 /*vendorslot*/, uint32& /*item*/, uint8 /*count*/, uint8 /*bag*/, uint8 /*slot*/, ItemTemplate const* /*pProto*/, Creature* /*pVendor*/, VendorItem const* /*crItem*/, bool /*bStore*/) { };
+
+ //After buying something from any vendor
+ virtual void OnAfterStoreOrEquipNewItem(Player* /*player*/, uint32 /*vendorslot*/, Item* /*item*/, uint8 /*count*/, uint8 /*bag*/, uint8 /*slot*/, ItemTemplate const* /*pProto*/, Creature* /*pVendor*/, VendorItem const* /*crItem*/, bool /*bStore*/) { };
virtual void OnAfterUpdateMaxPower(Player* /*player*/, Powers& /*power*/, float& /*value*/) { }
@@ -942,7 +971,7 @@ public:
virtual void OnFirstLogin(Player* /*player*/) { }
- virtual bool CanJoinInBattlegroundQueue(Player* /*player*/, uint64 /*BattlemasterGuid*/, BattlegroundTypeId /*BGTypeID*/, uint8 /*joinAsGroup*/, GroupJoinBattlegroundResult& /*err*/) { return true; }
+ [[nodiscard]] virtual bool CanJoinInBattlegroundQueue(Player* /*player*/, uint64 /*BattlemasterGuid*/, BattlegroundTypeId /*BGTypeID*/, uint8 /*joinAsGroup*/, GroupJoinBattlegroundResult& /*err*/) { return true; }
virtual bool ShouldBeRewardedWithMoneyInsteadOfExp(Player* /*player*/) { return false; }
// Called before the player's temporary summoned creature has initialized it's stats
@@ -956,6 +985,100 @@ public:
// Called before loading a player's pet from the DB
virtual void OnBeforeLoadPetFromDB(Player* /*player*/, uint32& /*petentry*/, uint32& /*petnumber*/, bool& /*current*/, bool& /*forceLoadFromDB*/) { }
+
+ [[nodiscard]] virtual bool CanJoinInArenaQueue(Player* /*player*/, uint64 /*BattlemasterGuid*/, uint8 /*arenaslot*/, BattlegroundTypeId /*BGTypeID*/, uint8 /*joinAsGroup*/, uint8 /*IsRated*/, GroupJoinBattlegroundResult& /*err*/) { return true; }
+
+ [[nodiscard]] virtual bool CanBattleFieldPort(Player* /*player*/, uint8 /*arenaType*/, BattlegroundTypeId /*BGTypeID*/, uint8 /*action*/) { return true; }
+
+ [[nodiscard]] virtual bool CanGroupInvite(Player* /*player*/, std::string& /*membername*/) { return true; }
+
+ [[nodiscard]] virtual bool CanGroupAccept(Player* /*player*/, Group* /*group*/) { return true; }
+
+ [[nodiscard]] virtual bool CanSellItem(Player* /*player*/, Item* /*item*/, Creature* /*creature*/) { return true; }
+
+ [[nodiscard]] virtual bool CanSendMail(Player* /*player*/, uint64 /*receiverGuid*/, uint64 /*mailbox*/, std::string& /*subject*/, std::string& /*body*/, uint32 /*money*/, uint32 /*COD*/, Item* /*item*/) { return true; }
+
+ virtual void PetitionBuy(Player* /*player*/, Creature* /*creature*/, uint32& /*charterid*/, uint32& /*cost*/, uint32& /*type*/) { }
+
+ virtual void PetitionShowList(Player* /*player*/, Creature* /*creature*/, uint32& /*CharterEntry*/, uint32& /*CharterDispayID*/, uint32& /*CharterCost*/) { }
+
+ virtual void OnRewardKillRewarder(Player* /*player*/, bool /*isDungeon*/, float& /*rate*/) { }
+
+ [[nodiscard]] virtual bool CanGiveMailRewardAtGiveLevel(Player* /*player*/, uint8 /*level*/) { return true; }
+
+ virtual void OnDeleteFromDB(SQLTransaction& /*trans*/, uint32 /*guid*/) { }
+
+ [[nodiscard]] virtual bool CanRepopAtGraveyard(Player* /*player*/) { return true; }
+
+ virtual void OnGetMaxSkillValue(Player* /*player*/, uint32 /*skill*/, int32& /*result*/, bool /*IsPure*/) { }
+
+ [[nodiscard]] virtual bool CanAreaExploreAndOutdoor(Player* /*player*/) { return true; }
+
+ virtual void OnVictimRewardBefore(Player* /*player*/, Player* /*victim*/, uint32& /*killer_title*/, uint32& /*victim_title*/) { }
+
+ virtual void OnVictimRewardAfter(Player* /*player*/, Player* /*victim*/, uint32& /*killer_title*/, uint32& /*victim_rank*/, float& /*honor_f*/) { }
+
+ virtual void OnCustomScalingStatValueBefore(Player* /*player*/, ItemTemplate const* /*proto*/, uint8 /*slot*/, bool /*apply*/, uint32& /*CustomScalingStatValue*/) { }
+
+ virtual void OnCustomScalingStatValue(Player* /*player*/, ItemTemplate const* /*proto*/, uint32& /*statType*/, int32& /*val*/, uint8 /*itemProtoStatNumber*/, uint32 /*ScalingStatValue*/, ScalingStatValuesEntry const* /*ssv*/) { }
+
+ [[nodiscard]] virtual bool CanArmorDamageModifier(Player* /*player*/) { return true; }
+
+ virtual void OnGetFeralApBonus(Player* /*player*/, int32& /*feral_bonus*/, int32 /*dpsMod*/, ItemTemplate const* /*proto*/, ScalingStatValuesEntry const* /*ssv*/) { }
+
+ [[nodiscard]] virtual bool CanApplyWeaponDependentAuraDamageMod(Player* /*player*/, Item* /*item*/, WeaponAttackType /*attackType*/, AuraEffect const* /*aura*/, bool /*apply*/) { return true; }
+
+ [[nodiscard]] virtual bool CanApplyEquipSpell(Player* /*player*/, SpellInfo const* /*spellInfo*/, Item* /*item*/, bool /*apply*/, bool /*form_change*/) { return true; }
+
+ [[nodiscard]] virtual bool CanApplyEquipSpellsItemSet(Player* /*player*/, ItemSetEffect* /*eff*/) { return true; }
+
+ [[nodiscard]] virtual bool CanCastItemCombatSpell(Player* /*player*/, Unit* /*target*/, WeaponAttackType /*attType*/, uint32 /*procVictim*/, uint32 /*procEx*/, Item* /*item*/, ItemTemplate const* /*proto*/) { return true; }
+
+ [[nodiscard]] virtual bool CanCastItemUseSpell(Player* /*player*/, Item* /*item*/, SpellCastTargets const& /*targets*/, uint8 /*cast_count*/, uint32 /*glyphIndex*/) { return true; }
+
+ virtual void OnApplyAmmoBonuses(Player* /*player*/, ItemTemplate const* /*proto*/, float& /*currentAmmoDPS*/) { }
+
+ [[nodiscard]] virtual bool CanEquipItem(Player* /*player*/, uint8 /*slot*/, uint16& /*dest*/, Item* /*pItem*/, bool /*swap*/, bool /*not_loading*/) { return true; }
+
+ [[nodiscard]] virtual bool CanUnequipItem(Player* /*player*/, uint16 /*pos*/, bool /*swap*/) { return true; }
+
+ [[nodiscard]] virtual bool CanUseItem(Player* /*player*/, ItemTemplate const* /*proto*/, InventoryResult& /*result*/) { return true; }
+
+ [[nodiscard]] virtual bool CanSaveEquipNewItem(Player* /*player*/, Item* /*item*/, uint16 /*pos*/, bool /*update*/) { return true; }
+
+ [[nodiscard]] virtual bool CanApplyEnchantment(Player* /*player*/, Item* /*item*/, EnchantmentSlot /*slot*/, bool /*apply*/, bool /*apply_dur*/, bool /*ignore_condition*/) { return true; }
+
+ virtual void OnGetQuestRate(Player* /*player*/, float& /*result*/) { }
+
+ [[nodiscard]] virtual bool PassedQuestKilledMonsterCredit(Player* /*player*/, Quest const* /*qinfo*/, uint32 /*entry*/, uint32 /*real_entry*/, uint64 /*guid*/) { return true; }
+
+ [[nodiscard]] virtual bool CheckItemInSlotAtLoadInventory(Player* /*player*/, Item* /*item*/, uint8 /*slot*/, uint8& /*err*/, uint16& /*dest*/) { return true; }
+
+ [[nodiscard]] virtual bool NotAvoidSatisfy(Player* /*player*/, DungeonProgressionRequirements const* /*ar*/, uint32 /*target_map*/, bool /*report*/) { return true; }
+
+ [[nodiscard]] virtual bool NotVisibleGloballyFor(Player* /*player*/, Player const* /*u*/) { return true; }
+
+ virtual void OnGetArenaPersonalRating(Player* /*player*/, uint8 /*slot*/, uint32& /*result*/) { }
+
+ virtual void OnGetArenaTeamId(Player* /*player*/, uint8 /*slot*/, uint32& /*result*/) { }
+
+ virtual void OnIsFFAPvP(Player* /*player*/, bool& /*result*/) { }
+
+ virtual void OnIsPvP(Player* /*player*/, bool& /*result*/) { }
+
+ virtual void OnGetMaxSkillValueForLevel(Player* /*player*/, uint16& /*result*/) { }
+
+ [[nodiscard]] virtual bool NotSetArenaTeamInfoField(Player* /*player*/, uint8 /*slot*/, ArenaTeamInfoType /*type*/, uint32 /*value*/) { return true; }
+
+ [[nodiscard]] virtual bool CanJoinLfg(Player* /*player*/, uint8 /*roles*/, lfg::LfgDungeonSet& /*dungeons*/, const std::string& /*comment*/) { return true; }
+
+ [[nodiscard]] virtual bool CanEnterMap(Player* /*player*/, MapEntry const* /*entry*/, InstanceTemplate const* /*instance*/, MapDifficulty const* /*mapDiff*/, bool /*loginCheck*/) { return true; }
+
+ [[nodiscard]] virtual bool CanInitTrade(Player* /*player*/, Player* /*target*/) { return true; }
+
+ virtual void OnSetServerSideVisibility(Player* /*player*/, ServerSideVisibilityType& /*type*/, AccountTypes& /*sec*/) { }
+
+ virtual void OnSetServerSideVisibilityDetect(Player* /*player*/, ServerSideVisibilityType& /*type*/, AccountTypes& /*sec*/) { }
};
class AccountScript : public ScriptObject
@@ -1025,6 +1148,8 @@ public:
virtual void OnEvent(Guild* /*guild*/, uint8 /*eventType*/, uint32 /*playerGuid1*/, uint32 /*playerGuid2*/, uint8 /*newRank*/) { }
virtual void OnBankEvent(Guild* /*guild*/, uint8 /*eventType*/, uint8 /*tabId*/, uint32 /*playerGuid*/, uint32 /*itemOrMoney*/, uint16 /*itemStackCount*/, uint8 /*destTabId*/) { }
+
+ [[nodiscard]] virtual bool CanGuildSendBankList(Guild const* /*guild*/, WorldSession* /*session*/, uint8 /*tabId*/, bool /*sendAllSlots*/) { return true; }
};
class GroupScript : public ScriptObject
@@ -1049,6 +1174,10 @@ public:
// Called when a group is disbanded.
virtual void OnDisband(Group* /*group*/) { }
+
+ [[nodiscard]] virtual bool CanGroupJoinBattlegroundQueue(Group const* /*group*/, Player* /*member*/, Battleground const* /*bgTemplate*/, uint32 /*MinPlayerCount*/, bool /*isRated*/, uint32 /*arenaSlot*/) { return true; }
+
+ virtual void OnCreate(Group* /*group*/, Player* /*leader*/) { }
};
// following hooks can be used anywhere and are not db bounded
@@ -1067,7 +1196,7 @@ public:
virtual void OnBeforeDropAddItem(Player const* /*player*/, Loot& /*loot*/, bool /*canRate*/, uint16 /*lootMode*/, LootStoreItem* /*LootStoreItem*/, LootStore const& /*store*/) { }
virtual void OnItemRoll(Player const* /*player*/, LootStoreItem const* /*LootStoreItem*/, float& /*chance*/, Loot& /*loot*/, LootStore const& /*store*/) { };
- virtual void OnInitializeLockedDungeons(Player* /*player*/, uint8& /*level*/, uint32& /*lockData*/) { }
+ virtual void OnInitializeLockedDungeons(Player* /*player*/, uint8& /*level*/, uint32& /*lockData*/, lfg::LFGDungeonData const* /*dungeon*/) { }
virtual void OnAfterInitializeLockedDungeons(Player* /*player*/) { }
// On Before arena points distribution
@@ -1106,16 +1235,20 @@ public:
// Remove player at leave BG
virtual void OnBattlegroundRemovePlayerAtLeave(Battleground* /*bg*/, Player* /*player*/) { }
+ virtual void OnQueueUpdate(BattlegroundQueue* /*queue*/, BattlegroundBracketId /*bracket_id*/, bool /*isRated*/, uint32 /*arenaRatedTeamId*/) { }
+
virtual void OnAddGroup(BattlegroundQueue* /*queue*/, GroupQueueInfo* /*ginfo*/, uint32& /*index*/, Player* /*leader*/, Group* /*grp*/, PvPDifficultyEntry const* /*bracketEntry*/, bool /*isPremade*/) { }
- virtual bool CanFillPlayersToBG(BattlegroundQueue* /*queue*/, Battleground* /*bg*/, const int32 /*aliFree*/, const int32 /*hordeFree*/, BattlegroundBracketId /*bracket_id*/) { return true; }
+ [[nodiscard]] virtual bool CanFillPlayersToBG(BattlegroundQueue* /*queue*/, Battleground* /*bg*/, const int32 /*aliFree*/, const int32 /*hordeFree*/, BattlegroundBracketId /*bracket_id*/) { return true; }
- virtual bool CanFillPlayersToBGWithSpecific(BattlegroundQueue* /*queue*/, Battleground* /*bg*/, const int32 /*aliFree*/, const int32 /*hordeFree*/,
+ [[nodiscard]] virtual bool CanFillPlayersToBGWithSpecific(BattlegroundQueue* /*queue*/, Battleground* /*bg*/, const int32 /*aliFree*/, const int32 /*hordeFree*/,
BattlegroundBracketId /*thisBracketId*/, BattlegroundQueue* /*specificQueue*/, BattlegroundBracketId /*specificBracketId*/) { return true; }
virtual void OnCheckNormalMatch(BattlegroundQueue* /*queue*/, uint32& /*Coef*/, Battleground* /*bgTemplate*/, BattlegroundBracketId /*bracket_id*/, uint32& /*minPlayers*/, uint32& /*maxPlayers*/) { }
- virtual bool CanSendMessageQueue(BattlegroundQueue* /*queue*/, Player* /*leader*/, Battleground* /*bg*/, PvPDifficultyEntry const* /*bracketEntry*/) { return true; }
+ [[nodiscard]] virtual bool CanSendMessageBGQueue(BattlegroundQueue* /*queue*/, Player* /*leader*/, Battleground* /*bg*/, PvPDifficultyEntry const* /*bracketEntry*/) { return true; }
+
+ [[nodiscard]] virtual bool CanSendMessageArenaQueue(BattlegroundQueue* /*queue*/, GroupQueueInfo* /*ginfo*/, bool /*IsJoin*/) { return true; }
};
class ArenaTeamScript : public ScriptObject
@@ -1143,6 +1276,24 @@ public:
// Calculate max duration in applying aura
virtual void OnCalcMaxDuration(Aura const* /*aura*/, int32& /*maxDuration*/) { }
+
+ [[nodiscard]] virtual bool CanModAuraEffectDamageDone(AuraEffect const* /*auraEff*/, Unit* /*target*/, AuraApplication const* /*aurApp*/, uint8 /*mode*/, bool /*apply*/) { return true; }
+
+ [[nodiscard]] virtual bool CanModAuraEffectModDamagePercentDone(AuraEffect const* /*auraEff*/, Unit* /*target*/, AuraApplication const* /*aurApp*/, uint8 /*mode*/, bool /*apply*/) { return true; }
+
+ virtual void OnSpellCheckCast(Spell* /*spell*/, bool /*strict*/, SpellCastResult& /*res*/) { }
+
+ [[nodiscard]] virtual bool CanPrepare(Spell* /*spell*/, SpellCastTargets const* /*targets*/, AuraEffect const* /*triggeredByAura*/) { return true; }
+
+ [[nodiscard]] virtual bool CanScalingEverything(Spell* /*spell*/) { return false; }
+
+ [[nodiscard]] virtual bool CanSelectSpecTalent(Spell* /*spell*/) { return true; }
+
+ virtual void OnScaleAuraUnitAdd(Spell* /*spell*/, Unit* /*target*/, uint32 /*effectMask*/, bool /*checkIfValid*/, bool /*implicit*/, uint8 /*auraScaleMask*/, TargetInfo& /*targetInfo*/) { }
+
+ virtual void OnRemoveAuraScaleTargets(Spell* /*spell*/, TargetInfo& /*targetInfo*/, uint8 /*auraScaleMask*/, bool& /*needErase*/) { }
+
+ virtual void OnBeforeAuraRankForLevel(SpellInfo const* /*spellInfo*/, SpellInfo const* /*latestSpellInfo*/, uint8 /*level*/) { }
};
// this class can be used to be extended by Modules
@@ -1176,6 +1327,124 @@ public:
virtual void OnBeforeMailDraftSendMailTo(MailDraft* /*mailDraft*/, MailReceiver const& /*receiver*/, MailSender const& /*sender*/, MailCheckMask& /*checked*/, uint32& /*deliver_delay*/, uint32& /*custom_expiration*/, bool& /*deleteMailItemsFromDB*/, bool& /*sendMail*/) { }
};
+class AchievementScript : public ScriptObject
+{
+protected:
+
+ AchievementScript(const char* name);
+
+public:
+
+ bool IsDatabaseBound() const { return false; }
+
+ // After complete global acvievement
+ virtual void SetRealmCompleted(AchievementEntry const* /*achievement*/) { }
+
+ [[nodiscard]] virtual bool IsCompletedCriteria(AchievementMgr* /*mgr*/, AchievementCriteriaEntry const* /*achievementCriteria*/, AchievementEntry const* /*achievement*/, CriteriaProgress const* /*progress*/) { return true; }
+
+ [[nodiscard]] virtual bool IsRealmCompleted(AchievementGlobalMgr const* /*globalmgr*/, AchievementEntry const* /*achievement*/, std::chrono::system_clock::time_point /*completionTime*/) { return true; }
+
+ virtual void OnBeforeCheckCriteria(AchievementMgr* /*mgr*/, AchievementCriteriaEntryList const* /*achievementCriteriaList*/) { }
+
+ [[nodiscard]] virtual bool CanCheckCriteria(AchievementMgr* /*mgr*/, AchievementCriteriaEntry const* /*achievementCriteria*/) { return true; }
+};
+
+class PetScript : public ScriptObject
+{
+protected:
+
+ PetScript(const char* name);
+
+public:
+
+ bool IsDatabaseBound() const { return false; }
+
+ virtual void OnInitStatsForLevel(Guardian* /*guardian*/, uint8 /*petlevel*/) { }
+
+ virtual void OnCalculateMaxTalentPointsForLevel(Pet* /*pet*/, uint8 /*level*/, uint8& /*points*/) { }
+
+ [[nodiscard]] virtual bool CanUnlearnSpellSet(Pet* /*pet*/, uint32 /*level*/, uint32 /*spell*/) { return true; }
+
+ [[nodiscard]] virtual bool CanUnlearnSpellDefault(Pet* /*pet*/, SpellInfo const* /*spellEntry*/) { return true; }
+
+ [[nodiscard]] virtual bool CanResetTalents(Pet* /*pet*/) { return true; }
+};
+
+class ArenaScript : public ScriptObject
+{
+protected:
+
+ ArenaScript(const char* name);
+
+public:
+
+ bool IsDatabaseBound() const { return false; }
+
+ [[nodiscard]] virtual bool CanAddMember(ArenaTeam* /*team*/, uint64 /*PlayerGuid*/) { return true; }
+
+ virtual void OnGetPoints(ArenaTeam* /*team*/, uint32 /*memberRating*/, float& /*points*/) { }
+
+ [[nodiscard]] virtual bool CanSaveToDB(ArenaTeam* /*team*/) { return true; }
+};
+
+class MiscScript : public ScriptObject
+{
+protected:
+
+ MiscScript(const char* name);
+
+public:
+
+ bool IsDatabaseBound() const { return false; }
+
+ virtual void OnConstructObject(Object* /*origin*/) { }
+
+ virtual void OnDestructObject(Object* /*origin*/) { }
+
+ virtual void OnConstructPlayer(Player* /*origin*/) { }
+
+ virtual void OnDestructPlayer(Player* /*origin*/) { }
+
+ virtual void OnConstructGroup(Group* /*origin*/) { }
+
+ virtual void OnDestructGroup(Group* /*origin*/) { }
+
+ virtual void OnConstructInstanceSave(InstanceSave* /*origin*/) { }
+
+ virtual void OnDestructInstanceSave(InstanceSave* /*origin*/) { }
+
+ virtual void OnItemCreate(Item* /*item*/, ItemTemplate const* /*itemProto*/, Player const* /*owner*/) { }
+
+ [[nodiscard]] virtual bool CanApplySoulboundFlag(Item* /*item*/, ItemTemplate const* /*proto*/) { return true; }
+
+ [[nodiscard]] virtual bool CanItemApplyEquipSpell(Player* /*player*/, Item* /*item*/) { return true; }
+
+ [[nodiscard]] virtual bool CanSendAuctionHello(WorldSession const* /*session*/, uint64 /*guid*/, Creature* /*creature*/) { return true; }
+
+ virtual void ValidateSpellAtCastSpell(Player* /*player*/, uint32& /*oldSpellId*/, uint32& /*spellId*/, uint8& /*castCount*/, uint8& /*castFlags*/) { }
+
+ virtual void ValidateSpellAtCastSpellResult(Player* /*player*/, Unit* /*mover*/, Spell* /*spell*/, uint32 /*oldSpellId*/, uint32 /*spellId*/) { }
+
+ virtual void OnAfterLootTemplateProcess(Loot* /*loot*/, LootTemplate const* /*tab*/, LootStore const& /*store*/, Player* /*lootOwner*/, bool /*personal*/, bool /*noEmptyError*/, uint16 /*lootMode*/) { }
+
+ virtual void OnPlayerSetPhase(const AuraEffect* /*auraEff*/, AuraApplication const* /*aurApp*/, uint8 /*mode*/, bool /*apply*/, uint32& /*newPhase*/) { }
+
+ virtual void OnInstanceSave(InstanceSave* /*instanceSave*/) { }
+};
+
+class CommandSC : public ScriptObject
+{
+protected:
+
+ CommandSC(const char* name);
+
+public:
+
+ bool IsDatabaseBound() const { return false; }
+
+ virtual void OnHandleDevCommand(Player* /*player*/, std::string& /*argstr*/) { }
+};
+
// Manages registration, loading, and execution of scripts.
class ScriptMgr
{
@@ -1234,6 +1503,7 @@ public: /* FormulaScript */
void OnGainCalculation(uint32& gain, Player* player, Unit* unit);
void OnGroupRateCalculation(float& rate, uint32 count, bool isRaid);
void OnAfterArenaRatingCalculation(Battleground* const bg, int32& winnerMatchmakerChange, int32& loserMatchmakerChange, int32& winnerChange, int32& loserChange);
+ void OnBeforeUpdatingPersonalRating(int32& mod, uint32 type);
public: /* MapScript */
void OnCreateMap(Map* map);
@@ -1396,8 +1666,11 @@ public: /* PlayerScript */
void OnLootItem(Player* player, Item* item, uint32 count, uint64 lootguid);
void OnCreateItem(Player* player, Item* item, uint32 count);
void OnQuestRewardItem(Player* player, Item* item, uint32 count);
+ bool OnBeforePlayerQuestComplete(Player* player, uint32 quest_id);
+ void OnBeforePlayerDurabilityRepair(Player* player, uint64 npcGUID, uint64 itemGUID, float& discountMod, uint8 guildBank);
void OnBeforeBuyItemFromVendor(Player* player, uint64 vendorguid, uint32 vendorslot, uint32& item, uint8 count, uint8 bag, uint8 slot);
- void OnAfterStoreOrEquipNewItem(Player* player, uint32 vendorslot, uint32& item, uint8 count, uint8 bag, uint8 slot, ItemTemplate const* pProto, Creature* pVendor, VendorItem const* crItem, bool bStore);
+ void OnBeforeStoreOrEquipNewItem(Player* player, uint32 vendorslot, uint32& item, uint8 count, uint8 bag, uint8 slot, ItemTemplate const* pProto, Creature* pVendor, VendorItem const* crItem, bool bStore);
+ void OnAfterStoreOrEquipNewItem(Player* player, uint32 vendorslot, Item* item, uint8 count, uint8 bag, uint8 slot, ItemTemplate const* pProto, Creature* pVendor, VendorItem const* crItem, bool bStore);
void OnAfterUpdateMaxPower(Player* player, Powers& power, float& value);
void OnAfterUpdateMaxHealth(Player* player, float& value);
void OnBeforeUpdateAttackPowerAndDamage(Player* player, float& level, float& val2, bool ranged);
@@ -1412,6 +1685,53 @@ public: /* PlayerScript */
void OnBeforeGuardianInitStatsForLevel(Player* player, Guardian* guardian, CreatureTemplate const* cinfo, PetType& petType);
void OnAfterGuardianInitStatsForLevel(Player* player, Guardian* guardian);
void OnBeforeLoadPetFromDB(Player* player, uint32& petentry, uint32& petnumber, bool& current, bool& forceLoadFromDB);
+ bool CanJoinInArenaQueue(Player* player, uint64 BattlemasterGuid, uint8 arenaslot, BattlegroundTypeId BGTypeID, uint8 joinAsGroup, uint8 IsRated, GroupJoinBattlegroundResult& err);
+ bool CanBattleFieldPort(Player* player, uint8 arenaType, BattlegroundTypeId BGTypeID, uint8 action);
+ bool CanGroupInvite(Player* player, std::string& membername);
+ bool CanGroupAccept(Player* player, Group* group);
+ bool CanSellItem(Player* player, Item* item, Creature* creature);
+ bool CanSendMail(Player* player, uint64 receiverGuid, uint64 mailbox, std::string& subject, std::string& body, uint32 money, uint32 COD, Item* item);
+ void PetitionBuy(Player* player, Creature* creature, uint32& charterid, uint32& cost, uint32& type);
+ void PetitionShowList(Player* player, Creature* creature, uint32& CharterEntry, uint32& CharterDispayID, uint32& CharterCost);
+ void OnRewardKillRewarder(Player* player, bool isDungeon, float& rate);
+ bool CanGiveMailRewardAtGiveLevel(Player* player, uint8 level);
+ void OnDeleteFromDB(SQLTransaction& trans, uint32 guid);
+ bool CanRepopAtGraveyard(Player* player);
+ void OnGetMaxSkillValue(Player* player, uint32 skill, int32& result, bool IsPure);
+ bool CanAreaExploreAndOutdoor(Player* player);
+ void OnVictimRewardBefore(Player* player, Player* victim, uint32& killer_title, uint32& victim_title);
+ void OnVictimRewardAfter(Player* player, Player* victim, uint32& killer_title, uint32& victim_rank, float& honor_f);
+ void OnCustomScalingStatValueBefore(Player* player, ItemTemplate const* proto, uint8 slot, bool apply, uint32& CustomScalingStatValue);
+ void OnCustomScalingStatValue(Player* player, ItemTemplate const* proto, uint32& statType, int32& val, uint8 itemProtoStatNumber, uint32 ScalingStatValue, ScalingStatValuesEntry const* ssv);
+ bool CanArmorDamageModifier(Player* player);
+ void OnGetFeralApBonus(Player* player, int32& feral_bonus, int32 dpsMod, ItemTemplate const* proto, ScalingStatValuesEntry const* ssv);
+ bool CanApplyWeaponDependentAuraDamageMod(Player* player, Item* item, WeaponAttackType attackType, AuraEffect const* aura, bool apply);
+ bool CanApplyEquipSpell(Player* player, SpellInfo const* spellInfo, Item* item, bool apply, bool form_change);
+ bool CanApplyEquipSpellsItemSet(Player* player, ItemSetEffect* eff);
+ bool CanCastItemCombatSpell(Player* player, Unit* target, WeaponAttackType attType, uint32 procVictim, uint32 procEx, Item* item, ItemTemplate const* proto);
+ bool CanCastItemUseSpell(Player* player, Item* item, SpellCastTargets const& targets, uint8 cast_count, uint32 glyphIndex);
+ void OnApplyAmmoBonuses(Player* player, ItemTemplate const* proto, float& currentAmmoDPS);
+ bool CanEquipItem(Player* player, uint8 slot, uint16& dest, Item* pItem, bool swap, bool not_loading);
+ bool CanUnequipItem(Player* player, uint16 pos, bool swap);
+ bool CanUseItem(Player* player, ItemTemplate const* proto, InventoryResult& result);
+ bool CanSaveEquipNewItem(Player* player, Item* item, uint16 pos, bool update);
+ bool CanApplyEnchantment(Player* player, Item* item, EnchantmentSlot slot, bool apply, bool apply_dur, bool ignore_condition);
+ void OnGetQuestRate(Player* player, float& result);
+ bool PassedQuestKilledMonsterCredit(Player* player, Quest const* qinfo, uint32 entry, uint32 real_entry, uint64 guid);
+ bool CheckItemInSlotAtLoadInventory(Player* player, Item* item, uint8 slot, uint8& err, uint16& dest);
+ bool NotAvoidSatisfy(Player* player, DungeonProgressionRequirements const* ar, uint32 target_map, bool report);
+ bool NotVisibleGloballyFor(Player* player, Player const* u);
+ void OnGetArenaPersonalRating(Player* player, uint8 slot, uint32& result);
+ void OnGetArenaTeamId(Player* player, uint8 slot, uint32& result);
+ void OnIsFFAPvP(Player* player, bool& result);
+ void OnIsPvP(Player* player, bool& result);
+ void OnGetMaxSkillValueForLevel(Player* player, uint16& result);
+ bool NotSetArenaTeamInfoField(Player* player, uint8 slot, ArenaTeamInfoType type, uint32 value);
+ bool CanJoinLfg(Player* player, uint8 roles, lfg::LfgDungeonSet& dungeons, const std::string& comment);
+ bool CanEnterMap(Player* player, MapEntry const* entry, InstanceTemplate const* instance, MapDifficulty const* mapDiff, bool loginCheck);
+ bool CanInitTrade(Player* player, Player* target);
+ void OnSetServerSideVisibility(Player* player, ServerSideVisibilityType& type, AccountTypes& sec);
+ void OnSetServerSideVisibilityDetect(Player* player, ServerSideVisibilityType& type, AccountTypes& sec);
public: /* AccountScript */
void OnAccountLogin(uint32 accountId);
@@ -1435,6 +1755,7 @@ public: /* GuildScript */
bool isDestBank, uint8 destContainer, uint8 destSlotId);
void OnGuildEvent(Guild* guild, uint8 eventType, uint32 playerGuid1, uint32 playerGuid2, uint8 newRank);
void OnGuildBankEvent(Guild* guild, uint8 eventType, uint8 tabId, uint32 playerGuid, uint32 itemOrMoney, uint16 itemStackCount, uint8 destTabId);
+ bool CanGuildSendBankList(Guild const* guild, WorldSession* session, uint8 tabId, bool sendAllSlots);
public: /* GroupScript */
void OnGroupAddMember(Group* group, uint64 guid);
@@ -1442,6 +1763,8 @@ public: /* GroupScript */
void OnGroupRemoveMember(Group* group, uint64 guid, RemoveMethod method, uint64 kicker, const char* reason);
void OnGroupChangeLeader(Group* group, uint64 newLeaderGuid, uint64 oldLeaderGuid);
void OnGroupDisband(Group* group);
+ bool CanGroupJoinBattlegroundQueue(Group const* group, Player* member, Battleground const* bgTemplate, uint32 MinPlayerCount, bool isRated, uint32 arenaSlot);
+ void OnCreate(Group* group, Player* leader);
public: /* GlobalScript */
void OnGlobalItemDelFromDB(SQLTransaction& trans, uint32 itemGuid);
@@ -1450,7 +1773,7 @@ public: /* GlobalScript */
void OnAfterRefCount(Player const* player, Loot& loot, bool canRate, uint16 lootMode, LootStoreItem* LootStoreItem, uint32& maxcount, LootStore const& store);
void OnBeforeDropAddItem(Player const* player, Loot& loot, bool canRate, uint16 lootMode, LootStoreItem* LootStoreItem, LootStore const& store);
void OnItemRoll(Player const* player, LootStoreItem const* LootStoreItem, float& chance, Loot& loot, LootStore const& store);
- void OnInitializeLockedDungeons(Player* player, uint8& level, uint32& lockData);
+ void OnInitializeLockedDungeons(Player* player, uint8& level, uint32& lockData, lfg::LFGDungeonData const* dungeon);
void OnAfterInitializeLockedDungeons(Player* player);
void OnAfterUpdateEncounterState(Map* map, EncounterCreditType type, uint32 creditEntry, Unit* source, Difficulty difficulty_fixed, DungeonEncounterList const* encounters, uint32 dungeonCompleted, bool updated);
void OnBeforeWorldObjectSetPhaseMask(WorldObject const* worldObject, uint32& oldPhaseMask, uint32& newPhaseMask, bool& useCombinedPhases, bool& update);
@@ -1470,6 +1793,13 @@ public: /* UnitScript */
void ModifyHealRecieved(Unit* target, Unit* attacker, uint32& addHealth);
uint32 DealDamage(Unit* AttackerUnit, Unit* pVictim, uint32 damage, DamageEffectType damagetype);
void OnBeforeRollMeleeOutcomeAgainst(const Unit* attacker, const Unit* victim, WeaponAttackType attType, int32& attackerMaxSkillValueForLevel, int32& victimMaxSkillValueForLevel, int32& attackerWeaponSkill, int32& victimDefenseSkill, int32& crit_chance, int32& miss_chance, int32& dodge_chance, int32& parry_chance, int32& block_chance);
+ void OnAuraRemove(Unit* unit, AuraApplication* aurApp, AuraRemoveMode mode);
+ bool IfNormalReaction(Unit const* unit, Unit const* target, ReputationRank& repRank);
+ bool IsNeedModSpellDamagePercent(Unit const* unit, AuraEffect* auraEff, float& doneTotalMod, SpellInfo const* spellProto);
+ bool IsNeedModMeleeDamagePercent(Unit const* unit, AuraEffect* auraEff, float& doneTotalMod, SpellInfo const* spellProto);
+ bool IsNeedModHealPercent(Unit const* unit, AuraEffect* auraEff, float& doneTotalMod, SpellInfo const* spellProto);
+ bool CanSetPhaseMask(Unit const* unit, uint32 newPhaseMask, bool update);
+ bool IsCustomBuildValuesUpdate(Unit const* unit, uint8 updateType, ByteBuffer& fieldBuffer, Player const* target, uint16 index);
public: /* MovementHandlerScript */
void OnPlayerMove(Player* player, MovementInfo movementInfo, uint32 opcode);
@@ -1491,12 +1821,14 @@ public: /* BGScript */
void OnBattlegroundAddPlayer(Battleground* bg, Player* player);
void OnBattlegroundBeforeAddPlayer(Battleground* bg, Player* player);
void OnBattlegroundRemovePlayerAtLeave(Battleground* bg, Player* player);
+ void OnQueueUpdate(BattlegroundQueue* queue, BattlegroundBracketId bracket_id, bool isRated, uint32 arenaRatedTeamId);
void OnAddGroup(BattlegroundQueue* queue, GroupQueueInfo* ginfo, uint32& index, Player* leader, Group* grp, PvPDifficultyEntry const* bracketEntry, bool isPremade);
bool CanFillPlayersToBG(BattlegroundQueue* queue, Battleground* bg, const int32 aliFree, const int32 hordeFree, BattlegroundBracketId bracket_id);
bool CanFillPlayersToBGWithSpecific(BattlegroundQueue* queue, Battleground* bg, const int32 aliFree, const int32 hordeFree,
BattlegroundBracketId thisBracketId, BattlegroundQueue* specificQueue, BattlegroundBracketId specificBracketId);
void OnCheckNormalMatch(BattlegroundQueue* queue, uint32& Coef, Battleground* bgTemplate, BattlegroundBracketId bracket_id, uint32& minPlayers, uint32& maxPlayers);
- bool CanSendMessageQueue(BattlegroundQueue* queue, Player* leader, Battleground* bg, PvPDifficultyEntry const* bracketEntry);
+ bool CanSendMessageBGQueue(BattlegroundQueue* queue, Player* leader, Battleground* bg, PvPDifficultyEntry const* bracketEntry);
+ bool CanSendMessageArenaQueue(BattlegroundQueue* queue, GroupQueueInfo* ginfo, bool IsJoin);
public: /* Arena Team Script */
void OnGetSlotByType(const uint32 type, uint8& slot);
@@ -1507,6 +1839,15 @@ public: /* Arena Team Script */
public: /* SpellSC */
void OnCalcMaxDuration(Aura const* aura, int32& maxDuration);
+ bool CanModAuraEffectDamageDone(AuraEffect const* auraEff, Unit* target, AuraApplication const* aurApp, uint8 mode, bool apply);
+ bool CanModAuraEffectModDamagePercentDone(AuraEffect const* auraEff, Unit* target, AuraApplication const* aurApp, uint8 mode, bool apply);
+ void OnSpellCheckCast(Spell* spell, bool strict, SpellCastResult& res);
+ bool CanPrepare(Spell* spell, SpellCastTargets const* targets, AuraEffect const* triggeredByAura);
+ bool CanScalingEverything(Spell* spell);
+ bool CanSelectSpecTalent(Spell* spell);
+ void OnScaleAuraUnitAdd(Spell* spell, Unit* target, uint32 effectMask, bool checkIfValid, bool implicit, uint8 auraScaleMask, TargetInfo& targetInfo);
+ void OnRemoveAuraScaleTargets(Spell* spell, TargetInfo& targetInfo, uint8 auraScaleMask, bool& needErase);
+ void OnBeforeAuraRankForLevel(SpellInfo const* spellInfo, SpellInfo const* latestSpellInfo, uint8 level);
public: /* GameEventScript */
void OnGameEventStart(uint16 EventID);
@@ -1515,6 +1856,52 @@ public: /* GameEventScript */
public: /* MailScript */
void OnBeforeMailDraftSendMailTo(MailDraft* mailDraft, MailReceiver const& receiver, MailSender const& sender, MailCheckMask& checked, uint32& deliver_delay, uint32& custom_expiration, bool& deleteMailItemsFromDB, bool& sendMail);
+public: /* AchievementScript */
+
+ void SetRealmCompleted(AchievementEntry const* achievement);
+ bool IsCompletedCriteria(AchievementMgr* mgr, AchievementCriteriaEntry const* achievementCriteria, AchievementEntry const* achievement, CriteriaProgress const* progress);
+ bool IsRealmCompleted(AchievementGlobalMgr const* globalmgr, AchievementEntry const* achievement, std::chrono::system_clock::time_point completionTime);
+ void OnBeforeCheckCriteria(AchievementMgr* mgr, AchievementCriteriaEntryList const* achievementCriteriaList);
+ bool CanCheckCriteria(AchievementMgr* mgr, AchievementCriteriaEntry const* achievementCriteria);
+
+ public: /* PetScript */
+
+ void OnInitStatsForLevel(Guardian* guardian, uint8 petlevel);
+ void OnCalculateMaxTalentPointsForLevel(Pet* pet, uint8 level, uint8& points);
+ bool CanUnlearnSpellSet(Pet* pet, uint32 level, uint32 spell);
+ bool CanUnlearnSpellDefault(Pet* pet, SpellInfo const* spellEntry);
+ bool CanResetTalents(Pet* pet);
+
+ public: /* ArenaScript */
+
+ bool CanAddMember(ArenaTeam* team, uint64 PlayerGuid);
+ void OnGetPoints(ArenaTeam* team, uint32 memberRating, float& points);
+ bool CanSaveToDB(ArenaTeam* team);
+
+ public: /* MiscScript */
+
+ void OnConstructObject(Object* origin);
+ void OnDestructObject(Object* origin);
+ void OnConstructPlayer(Player* origin);
+ void OnDestructPlayer(Player* origin);
+ void OnConstructGroup(Group* origin);
+ void OnDestructGroup(Group* origin);
+ void OnConstructInstanceSave(InstanceSave* origin);
+ void OnDestructInstanceSave(InstanceSave* origin);
+ void OnItemCreate(Item* item, ItemTemplate const* itemProto, Player const* owner);
+ bool CanApplySoulboundFlag(Item* item, ItemTemplate const* proto);
+ bool CanItemApplyEquipSpell(Player* player, Item* item);
+ bool CanSendAuctionHello(WorldSession const* session, uint64 guid, Creature* creature);
+ void ValidateSpellAtCastSpell(Player* player, uint32& oldSpellId, uint32& spellId, uint8& castCount, uint8& castFlags);
+ void OnPlayerSetPhase(const AuraEffect* auraEff, AuraApplication const* aurApp, uint8 mode, bool apply, uint32& newPhase);
+ void ValidateSpellAtCastSpellResult(Player* player, Unit* mover, Spell* spell, uint32 oldSpellId, uint32 spellId);
+ void OnAfterLootTemplateProcess(Loot* loot, LootTemplate const* tab, LootStore const& store, Player* lootOwner, bool personal, bool noEmptyError, uint16 lootMode);
+ void OnInstanceSave(InstanceSave* instanceSave);
+
+ public: /* CommandSC */
+
+ void OnHandleDevCommand(Player* player, std::string& argstr);
+
private:
uint32 _scriptCount;
diff --git a/src/server/game/Spells/Auras/SpellAuraEffects.cpp b/src/server/game/Spells/Auras/SpellAuraEffects.cpp
index 5ef3ab3620..b7b7ebc594 100644
--- a/src/server/game/Spells/Auras/SpellAuraEffects.cpp
+++ b/src/server/game/Spells/Auras/SpellAuraEffects.cpp
@@ -4726,7 +4726,7 @@ void AuraEffect::HandleModDamageDone(AuraApplication const* aurApp, uint8 mode,
// with spell->EquippedItemClass and EquippedItemSubClassMask and EquippedItemInventoryTypeMask
// GetMiscValue() comparison with item generated damage types
- if ((GetMiscValue() & SPELL_SCHOOL_MASK_NORMAL) != 0)
+ if ((GetMiscValue() & SPELL_SCHOOL_MASK_NORMAL) != 0 && sScriptMgr->CanModAuraEffectDamageDone(this, target, aurApp, mode, apply))
{
// apply generic physical damage bonuses including wand case
if (GetSpellInfo()->EquippedItemClass == -1 || target->GetTypeId() != TYPEID_PLAYER)
@@ -4796,6 +4796,9 @@ void AuraEffect::HandleModDamagePercentDone(AuraApplication const* aurApp, uint8
if (!target)
return;
+ if (!sScriptMgr->CanModAuraEffectModDamagePercentDone(this, target, aurApp, mode, apply))
+ return;
+
if (target->GetTypeId() == TYPEID_PLAYER)
{
for (int i = 0; i < MAX_ATTACK; ++i)
diff --git a/src/server/game/Spells/Spell.cpp b/src/server/game/Spells/Spell.cpp
index 92f9ceaf19..54141478d9 100644
--- a/src/server/game/Spells/Spell.cpp
+++ b/src/server/game/Spells/Spell.cpp
@@ -836,19 +836,21 @@ void Spell::SelectSpellTargets()
else if (m_auraScaleMask)
{
bool checkLvl = !m_UniqueTargetInfo.empty();
- for (std::list<TargetInfo>::iterator ihit = m_UniqueTargetInfo.begin(); ihit != m_UniqueTargetInfo.end();)
+ for (std::list<TargetInfo>::iterator itr = m_UniqueTargetInfo.begin(); itr != m_UniqueTargetInfo.end(); ++itr)
{
// remove targets which did not pass min level check
- if (m_auraScaleMask && ihit->effectMask == m_auraScaleMask)
+ if (m_auraScaleMask && itr->effectMask == m_auraScaleMask)
{
- // Do not check for selfcast
- if (!ihit->scaleAura && ihit->targetGUID != m_caster->GetGUID())
- {
- m_UniqueTargetInfo.erase(ihit++);
- continue;
- }
+ bool needErase = false;
+
+ if (!itr->scaleAura && itr->targetGUID != m_caster->GetGUID())
+ needErase = true;
+
+ sScriptMgr->OnRemoveAuraScaleTargets(this, *itr, m_auraScaleMask, needErase);
+
+ if (needErase)
+ m_UniqueTargetInfo.erase(itr);
}
- ++ihit;
}
if (checkLvl && m_UniqueTargetInfo.empty())
{
@@ -2154,6 +2156,8 @@ void Spell::AddUnitTarget(Unit* target, uint32 effectMask, bool checkIfValid /*=
if (uint32(target->getLevel() + 10) >= auraSpell->SpellLevel)
ihit->scaleAura = true;
}
+
+ sScriptMgr->OnScaleAuraUnitAdd(this, target, effectMask, checkIfValid, implicit, m_auraScaleMask, *ihit);
return;
}
}
@@ -2176,6 +2180,8 @@ void Spell::AddUnitTarget(Unit* target, uint32 effectMask, bool checkIfValid /*=
targetInfo.scaleAura = true;
}
+ sScriptMgr->OnScaleAuraUnitAdd(this, target, effectMask, checkIfValid, implicit, m_auraScaleMask, targetInfo);
+
// Calculate hit result
if (m_originalCaster)
{
@@ -3163,8 +3169,14 @@ SpellCastResult Spell::prepare(SpellCastTargets const* targets, AuraEffect const
InitExplicitTargets(*targets);
+ if (!sScriptMgr->CanPrepare(this, targets, triggeredByAura))
+ {
+ finish(false);
+ return SPELL_FAILED_UNKNOWN;
+ }
+
// Fill aura scaling information
- if (m_caster->IsTotem() || (m_caster->IsControlledByPlayer() && !m_spellInfo->IsPassive() && m_spellInfo->SpellLevel && !m_spellInfo->IsChanneled() && !(_triggeredCastFlags & TRIGGERED_IGNORE_AURA_SCALING)))
+ if (sScriptMgr->CanScalingEverything(this) || m_caster->IsTotem() || (m_caster->IsControlledByPlayer() && !m_spellInfo->IsPassive() && m_spellInfo->SpellLevel && !m_spellInfo->IsChanneled() && !(_triggeredCastFlags & TRIGGERED_IGNORE_AURA_SCALING)))
{
for (uint8 i = 0; i < MAX_SPELL_EFFECTS; ++i)
{
@@ -5140,6 +5152,13 @@ SpellCastResult Spell::CheckCast(bool strict)
if (((const Player*)m_caster)->IsSpectator() && m_spellInfo->Id != SPECTATOR_SPELL_BINDSIGHT)
return SPELL_FAILED_NOT_HERE;
+ SpellCastResult res = SPELL_CAST_OK;
+
+ sScriptMgr->OnSpellCheckCast(this, strict, res);
+
+ if (res != SPELL_CAST_OK)
+ return res;
+
// check cooldowns to prevent cheating
if (!m_spellInfo->HasAttribute(SPELL_ATTR0_PASSIVE))
{
@@ -5969,6 +5988,8 @@ SpellCastResult Spell::CheckCast(bool strict)
break;
}
case SPELL_EFFECT_TALENT_SPEC_SELECT:
+ if (!sScriptMgr->CanSelectSpecTalent(this))
+ return SPELL_FAILED_DONT_REPORT;
// can't change during already started arena/battleground
if (m_caster->GetTypeId() == TYPEID_PLAYER)
if (Battleground const* bg = m_caster->ToPlayer()->GetBattleground())
diff --git a/src/server/game/Spells/Spell.h b/src/server/game/Spells/Spell.h
index 68317b3937..ffe17b604f 100644
--- a/src/server/game/Spells/Spell.h
+++ b/src/server/game/Spells/Spell.h
@@ -234,6 +234,21 @@ struct ChannelTargetData
SpellDestination spellDst;
};
+ // Targets store structures and data
+struct TargetInfo
+{
+ uint64 targetGUID;
+ uint64 timeDelay;
+ SpellMissInfo missCondition:8;
+ SpellMissInfo reflectResult:8;
+ uint8 effectMask:8;
+ bool processed:1;
+ bool alive:1;
+ bool crit:1;
+ bool scaleAura:1;
+ int32 damage;
+};
+
static const uint32 SPELL_INTERRUPT_NONPLAYER = 32747;
class Spell
@@ -241,6 +256,9 @@ class Spell
friend void Unit::SetCurrentCastedSpell(Spell* pSpell);
friend class SpellScript;
public:
+ Spell(Unit* caster, SpellInfo const* info, TriggerCastFlags triggerFlags, uint64 originalCasterGUID = 0, bool skipCheck = false);
+ ~Spell();
+
void EffectNULL(SpellEffIndex effIndex);
void EffectUnused(SpellEffIndex effIndex);
void EffectDistract(SpellEffIndex effIndex);
@@ -369,9 +387,6 @@ public:
typedef std::set<Aura*> UsedSpellMods;
- Spell(Unit* caster, SpellInfo const* info, TriggerCastFlags triggerFlags, uint64 originalCasterGUID = 0, bool skipCheck = false);
- ~Spell();
-
void InitExplicitTargets(SpellCastTargets const& targets);
void SelectExplicitTargets();
@@ -473,7 +488,7 @@ public:
void HandleEffects(Unit* pUnitTarget, Item* pItemTarget, GameObject* pGOTarget, uint32 i, SpellEffectHandleMode mode);
void HandleThreatSpells();
- SpellInfo const* const m_spellInfo;
+ SpellInfo const* m_spellInfo;
Item* m_CastItem;
uint64 m_castItemGUID;
uint8 m_cast_count;
@@ -511,6 +526,7 @@ public:
Unit* GetCaster() const { return m_caster; }
Unit* GetOriginalCaster() const { return m_originalCaster; }
SpellInfo const* GetSpellInfo() const { return m_spellInfo; }
+ void SetSpellInfo(SpellInfo const* info) { m_spellInfo = info; }
int32 GetPowerCost() const { return m_powerCost; }
bool UpdatePointers(); // must be used at call Spell code after time delay (non triggered spell cast/update spell call/etc)
@@ -522,21 +538,6 @@ public:
// xinef: moved to public
void LoadScripts();
-
- // Targets store structures and data
- struct TargetInfo
- {
- uint64 targetGUID;
- uint64 timeDelay;
- SpellMissInfo missCondition: 8;
- SpellMissInfo reflectResult: 8;
- uint8 effectMask: 8;
- bool processed: 1;
- bool alive: 1;
- bool crit: 1;
- bool scaleAura: 1;
- int32 damage;
- };
std::list<TargetInfo>* GetUniqueTargetInfo() { return &m_UniqueTargetInfo; }
protected:
bool HasGlobalCooldown() const;
diff --git a/src/server/game/Spells/SpellInfo.cpp b/src/server/game/Spells/SpellInfo.cpp
index a109f86267..513f73c355 100644
--- a/src/server/game/Spells/SpellInfo.cpp
+++ b/src/server/game/Spells/SpellInfo.cpp
@@ -9,6 +9,7 @@
#include "ConditionMgr.h"
#include "DBCStores.h"
#include "Player.h"
+#include "ScriptMgr.h"
#include "Spell.h"
#include "SpellAuraDefines.h"
#include "SpellAuraEffects.h"
@@ -2487,7 +2488,14 @@ SpellInfo const* SpellInfo::GetAuraRankForLevel(uint8 level) const
if (!needRankSelection)
return this;
- for (SpellInfo const* nextSpellInfo = this; nextSpellInfo != nullptr; nextSpellInfo = nextSpellInfo->GetPrevRankSpell())
+ SpellInfo const* nextSpellInfo = nullptr;
+
+ sScriptMgr->OnBeforeAuraRankForLevel(this, nextSpellInfo, level);
+
+ if (nextSpellInfo != nullptr)
+ return nextSpellInfo;
+
+ for (nextSpellInfo = this; nextSpellInfo != nullptr; nextSpellInfo = nextSpellInfo->GetPrevRankSpell())
{
// if found appropriate level
if (uint32(level + 10) >= nextSpellInfo->SpellLevel)
diff --git a/src/server/scripts/Commands/cs_misc.cpp b/src/server/scripts/Commands/cs_misc.cpp
index 7839fa1728..944ba22c90 100644
--- a/src/server/scripts/Commands/cs_misc.cpp
+++ b/src/server/scripts/Commands/cs_misc.cpp
@@ -347,12 +347,14 @@ public:
{
player->SetDeveloper(true);
handler->GetSession()->SendNotification(LANG_DEV_ON);
+ sScriptMgr->OnHandleDevCommand(handler->GetSession()->GetPlayer(), enablestr);
return true;
}
else if (enablestr == "off")
{
player->SetDeveloper(false);
handler->GetSession()->SendNotification(LANG_DEV_OFF);
+ sScriptMgr->OnHandleDevCommand(handler->GetSession()->GetPlayer(), enablestr);
return true;
}
diff --git a/src/server/scripts/Outland/BlackTemple/boss_mother_shahraz.cpp b/src/server/scripts/Outland/BlackTemple/boss_mother_shahraz.cpp
index 7753f111b6..7b888c8255 100644
--- a/src/server/scripts/Outland/BlackTemple/boss_mother_shahraz.cpp
+++ b/src/server/scripts/Outland/BlackTemple/boss_mother_shahraz.cpp
@@ -265,8 +265,8 @@ public:
void SetDest(SpellDestination& dest)
{
- std::list<Spell::TargetInfo> const* targetsInfo = GetSpell()->GetUniqueTargetInfo();
- for (std::list<Spell::TargetInfo>::const_iterator ihit = targetsInfo->begin(); ihit != targetsInfo->end(); ++ihit)
+ std::list<TargetInfo> const* targetsInfo = GetSpell()->GetUniqueTargetInfo();
+ for (std::list<TargetInfo>::const_iterator ihit = targetsInfo->begin(); ihit != targetsInfo->end(); ++ihit)
if (Unit* target = ObjectAccessor::GetUnit(*GetCaster(), ihit->targetGUID))
{
dest.Relocate(*target);
diff --git a/src/server/scripts/Outland/BlackTemple/illidari_council.cpp b/src/server/scripts/Outland/BlackTemple/illidari_council.cpp
index 1de9f2f5f9..96f0f33a39 100644
--- a/src/server/scripts/Outland/BlackTemple/illidari_council.cpp
+++ b/src/server/scripts/Outland/BlackTemple/illidari_council.cpp
@@ -613,8 +613,8 @@ public:
}
float pct = (_sharedHealth / _sharedHealthMax) * 100.0f;
- std::list<Spell::TargetInfo> const* targetsInfo = GetSpell()->GetUniqueTargetInfo();
- for (std::list<Spell::TargetInfo>::const_iterator ihit = targetsInfo->begin(); ihit != targetsInfo->end(); ++ihit)
+ std::list<TargetInfo> const* targetsInfo = GetSpell()->GetUniqueTargetInfo();
+ for (std::list<TargetInfo>::const_iterator ihit = targetsInfo->begin(); ihit != targetsInfo->end(); ++ihit)
if (Creature* target = ObjectAccessor::GetCreature(*GetCaster(), ihit->targetGUID))
{
target->LowerPlayerDamageReq(target->GetMaxHealth());
diff --git a/src/server/scripts/Pet/pet_generic.cpp b/src/server/scripts/Pet/pet_generic.cpp
index 7372126909..b73967bb29 100644
--- a/src/server/scripts/Pet/pet_generic.cpp
+++ b/src/server/scripts/Pet/pet_generic.cpp
@@ -606,8 +606,8 @@ public:
{
if (GetHitUnit() != GetCaster())
{
- std::list<Spell::TargetInfo>* targetsInfo = GetSpell()->GetUniqueTargetInfo();
- for (std::list<Spell::TargetInfo>::iterator ihit = targetsInfo->begin(); ihit != targetsInfo->end(); ++ihit)
+ std::list<TargetInfo>* targetsInfo = GetSpell()->GetUniqueTargetInfo();
+ for (std::list<TargetInfo>::iterator ihit = targetsInfo->begin(); ihit != targetsInfo->end(); ++ihit)
if (ihit->targetGUID == GetCaster()->GetGUID())
ihit->damage = -int32(GetHitDamage() * 0.25f);
}
diff --git a/src/server/scripts/Spells/spell_dk.cpp b/src/server/scripts/Spells/spell_dk.cpp
index 1ddfd1757f..7678b6df0a 100644
--- a/src/server/scripts/Spells/spell_dk.cpp
+++ b/src/server/scripts/Spells/spell_dk.cpp
@@ -430,8 +430,8 @@ public:
{
if (Unit* target = GetExplTargetUnit())
{
- std::list<Spell::TargetInfo> const* targetsInfo = GetSpell()->GetUniqueTargetInfo();
- for (std::list<Spell::TargetInfo>::const_iterator ihit = targetsInfo->begin(); ihit != targetsInfo->end(); ++ihit)
+ std::list<TargetInfo> const* targetsInfo = GetSpell()->GetUniqueTargetInfo();
+ for (std::list<TargetInfo>::const_iterator ihit = targetsInfo->begin(); ihit != targetsInfo->end(); ++ihit)
if (ihit->missCondition == SPELL_MISS_NONE && ihit->targetGUID == target->GetGUID())
GetCaster()->CastSpell(target, 55095 /*SPELL_FROST_FEVER*/, true);
}
@@ -610,8 +610,8 @@ public:
void RecalculateDamage()
{
- std::list<Spell::TargetInfo>* targetsInfo = GetSpell()->GetUniqueTargetInfo();
- for (std::list<Spell::TargetInfo>::iterator ihit = targetsInfo->begin(); ihit != targetsInfo->end(); ++ihit)
+ std::list<TargetInfo>* targetsInfo = GetSpell()->GetUniqueTargetInfo();
+ for (std::list<TargetInfo>::iterator ihit = targetsInfo->begin(); ihit != targetsInfo->end(); ++ihit)
if (ihit->targetGUID == GetCaster()->GetGUID())
ihit->crit = roll_chance_f(GetCaster()->GetFloatValue(PLAYER_CRIT_PERCENTAGE));
}