diff --git a/src/server/game/Battlegrounds/ArenaTeam.cpp b/src/server/game/Battlegrounds/ArenaTeam.cpp index 412191b8f..b3195ce21 100644 --- a/src/server/game/Battlegrounds/ArenaTeam.cpp +++ b/src/server/game/Battlegrounds/ArenaTeam.cpp @@ -13,7 +13,7 @@ #include "Player.h" #include "WorldSession.h" #include "Opcodes.h" -#include +#include "ScriptMgr.h" ArenaTeam::ArenaTeam() : TeamId(0), Type(0), TeamName(), CaptainGuid(0), BackgroundColor(0), EmblemStyle(0), EmblemColor(0), @@ -473,7 +473,7 @@ void ArenaTeam::NotifyStatsChanged() void ArenaTeam::Inspect(WorldSession* session, uint64 guid) { ArenaTeamMember* member = GetMember(guid); - if (!member) + if (!member || GetSlot() >= MAX_ARENA_SLOT) return; WorldPacket data(MSG_INSPECT_ARENA_TEAMS, 8 + 1 + 4 * 6); @@ -495,7 +495,7 @@ void ArenaTeamMember::ModifyPersonalRating(Player* player, int32 mod, uint32 typ else PersonalRating += mod; - if (player) + if (player && ArenaTeam::GetSlotByType(type) < 3) { player->SetArenaTeamInfoField(ArenaTeam::GetSlotByType(type), ARENA_TEAM_PERSONAL_RATING, PersonalRating); player->UpdateAchievementCriteria(ACHIEVEMENT_CRITERIA_TYPE_HIGHEST_PERSONAL_RATING, PersonalRating, type); @@ -579,17 +579,28 @@ void ArenaTeam::MassInviteToEvent(WorldSession* session) uint8 ArenaTeam::GetSlotByType(uint32 type) { + uint8 slot = 0xFF; switch (type) { case ARENA_TEAM_2v2: - return 0; + slot = 0; + break; case ARENA_TEAM_3v3: - return 1; + slot = 1; + break; case ARENA_TEAM_5v5: - return 2; + slot = 2; + break; default: break; } + //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; } @@ -626,6 +637,8 @@ uint32 ArenaTeam::GetPoints(uint32 memberRating) else if (Type == ARENA_TEAM_3v3) points *= 0.88f; + sScriptMgr->OnGetArenaPoints(this, points); + points *= sWorld->getRate(RATE_ARENA_POINTS); return (uint32) points; diff --git a/src/server/game/Battlegrounds/ArenaTeamMgr.cpp b/src/server/game/Battlegrounds/ArenaTeamMgr.cpp index 60af82552..3a8eda017 100644 --- a/src/server/game/Battlegrounds/ArenaTeamMgr.cpp +++ b/src/server/game/Battlegrounds/ArenaTeamMgr.cpp @@ -51,7 +51,30 @@ ArenaTeam* ArenaTeamMgr::GetArenaTeamByName(const std::string& arenaTeamName) co std::string teamName = itr->second->GetName(); std::transform(teamName.begin(), teamName.end(), teamName.begin(), ::toupper); if (search == teamName) + { return itr->second; + } + } + return nullptr; +} + + +ArenaTeam* ArenaTeamMgr::GetArenaTeamByName(std::string const& arenaTeamName, const uint32 type) const +{ + std::string search = arenaTeamName; + std::transform(search.begin(), search.end(), search.begin(), ::toupper); + for (auto itr = ArenaTeamStore.begin(); itr != ArenaTeamStore.end(); ++itr) + { + if (itr->second->GetType() != type) + { + continue; + } + std::string teamName = itr->second->GetName(); + std::transform(teamName.begin(), teamName.end(), teamName.begin(), ::toupper); + if (search == teamName) + { + return itr->second; + } } return nullptr; } @@ -59,9 +82,25 @@ ArenaTeam* ArenaTeamMgr::GetArenaTeamByName(const std::string& arenaTeamName) co ArenaTeam* ArenaTeamMgr::GetArenaTeamByCaptain(uint64 guid) const { for (ArenaTeamContainer::const_iterator itr = ArenaTeamStore.begin(); itr != ArenaTeamStore.end(); ++itr) + { if (itr->second->GetCaptain() == guid) + { return itr->second; + } + } + return nullptr; +} + +ArenaTeam* ArenaTeamMgr::GetArenaTeamByCaptain(uint64 guid, const uint32 type) const +{ + for (ArenaTeamContainer::const_iterator itr = ArenaTeamStore.begin(); itr != ArenaTeamStore.end(); ++itr) + { + if (itr->second->GetCaptain() == guid && itr->second->GetType() == type) + { + return itr->second; + } + } return nullptr; } diff --git a/src/server/game/Battlegrounds/ArenaTeamMgr.h b/src/server/game/Battlegrounds/ArenaTeamMgr.h index c94478236..881a29dfd 100644 --- a/src/server/game/Battlegrounds/ArenaTeamMgr.h +++ b/src/server/game/Battlegrounds/ArenaTeamMgr.h @@ -22,6 +22,8 @@ public: ArenaTeam* GetArenaTeamById(uint32 arenaTeamId) const; ArenaTeam* GetArenaTeamByName(std::string const& arenaTeamName) const; ArenaTeam* GetArenaTeamByCaptain(uint64 guid) const; + ArenaTeam* GetArenaTeamByName(std::string const& arenaTeamName, const uint32 type) const; + ArenaTeam* GetArenaTeamByCaptain(uint64 guid, const uint32 type) const; void LoadArenaTeams(); void AddArenaTeam(ArenaTeam* arenaTeam); diff --git a/src/server/game/Battlegrounds/BattlegroundMgr.cpp b/src/server/game/Battlegrounds/BattlegroundMgr.cpp index 7a89ee9a6..24247164e 100644 --- a/src/server/game/Battlegrounds/BattlegroundMgr.cpp +++ b/src/server/game/Battlegrounds/BattlegroundMgr.cpp @@ -482,7 +482,7 @@ Battleground* BattlegroundMgr::CreateNewBattleground(BattlegroundTypeId original maxPlayersPerTeam = 5; break; } - + sScriptMgr->OnSetArenaMaxPlayersPerTeam(arenaType, maxPlayersPerTeam); bg->SetMaxPlayersPerTeam(maxPlayersPerTeam); } @@ -748,19 +748,23 @@ bool BattlegroundMgr::IsArenaType(BattlegroundTypeId bgTypeId) BattlegroundQueueTypeId BattlegroundMgr::BGQueueTypeId(BattlegroundTypeId bgTypeId, uint8 arenaType) { - if (arenaType) - { - switch (arenaType) - { + if (arenaType) { + uint32 queueTypeID = BATTLEGROUND_QUEUE_NONE; + switch (arenaType) { case ARENA_TYPE_2v2: - return BATTLEGROUND_QUEUE_2v2; + queueTypeID = BATTLEGROUND_QUEUE_2v2; + break; case ARENA_TYPE_3v3: - return BATTLEGROUND_QUEUE_3v3; + queueTypeID = BATTLEGROUND_QUEUE_3v3; + break; case ARENA_TYPE_5v5: - return BATTLEGROUND_QUEUE_5v5; + queueTypeID = BATTLEGROUND_QUEUE_5v5; + break; default: - return BATTLEGROUND_QUEUE_NONE; + break; } + sScriptMgr->OnArenaTypeIDToQueueID(bgTypeId, arenaType, queueTypeID); + return BattlegroundQueueTypeId(queueTypeID); } if (BattlegroundMgr::bgToQueue.find(bgTypeId) == BattlegroundMgr::bgToQueue.end()) @@ -783,17 +787,23 @@ BattlegroundTypeId BattlegroundMgr::BGTemplateId(BattlegroundQueueTypeId bgQueue uint8 BattlegroundMgr::BGArenaType(BattlegroundQueueTypeId bgQueueTypeId) { + uint8 arenaType = 0; switch (bgQueueTypeId) { case BATTLEGROUND_QUEUE_2v2: - return ARENA_TYPE_2v2; + arenaType = ARENA_TYPE_2v2; + break; case BATTLEGROUND_QUEUE_3v3: - return ARENA_TYPE_3v3; + arenaType = ARENA_TYPE_3v3; + break; case BATTLEGROUND_QUEUE_5v5: - return ARENA_TYPE_5v5; + arenaType = ARENA_TYPE_5v5; + break; default: - return 0; + break; } + sScriptMgr->OnArenaQueueIdToArenaType(bgQueueTypeId, arenaType); + return arenaType; } void BattlegroundMgr::ToggleTesting() diff --git a/src/server/game/Entities/Player/Player.cpp b/src/server/game/Entities/Player/Player.cpp index 90ba01d29..4faa12840 100644 --- a/src/server/game/Entities/Player/Player.cpp +++ b/src/server/game/Entities/Player/Player.cpp @@ -7546,10 +7546,25 @@ uint32 Player::GetGroupIdFromStorage(uint32 guid) uint32 Player::GetArenaTeamIdFromStorage(uint32 guid, uint8 slot) { if (GlobalPlayerData const* playerData = sWorld->GetGlobalPlayerData(guid)) - return playerData->arenaTeamId[slot]; + { + auto itr = playerData->arenaTeamId.find(slot); + if (itr != playerData->arenaTeamId.end()) + { + return itr->second; + } + } 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); @@ -17710,7 +17725,7 @@ 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 <= 2; ++slot) + for (uint8 slot = 0; slot < MAX_ARENA_SLOT; ++slot) if (uint32 arenaTeamId = Player::GetArenaTeamIdFromStorage(GetGUIDLow(), slot)) { ArenaTeam* arenaTeam = sArenaTeamMgr->GetArenaTeamById(arenaTeamId); @@ -21627,6 +21642,38 @@ 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 @@ -22287,6 +22334,9 @@ uint32 Player::GetMaxPersonalArenaRatingRequirement(uint32 minarenaslot) const max_personal_rating = p_rating; } } + + sScriptMgr->OnGetMaxPersonalArenaRatingRequirement(this, minarenaslot, max_personal_rating); + return max_personal_rating; } diff --git a/src/server/game/Entities/Player/Player.h b/src/server/game/Entities/Player/Player.h index c4b07e70d..98ed866bf 100644 --- a/src/server/game/Entities/Player/Player.h +++ b/src/server/game/Entities/Player/Player.h @@ -1939,14 +1939,11 @@ public: SetArenaTeamInfoField(slot, ARENA_TEAM_ID, ArenaTeamId); SetArenaTeamInfoField(slot, ARENA_TEAM_TYPE, type); } - void SetArenaTeamInfoField(uint8 slot, ArenaTeamInfoType type, uint32 value) - { - SetUInt32Value(PLAYER_FIELD_ARENA_TEAM_INFO_1_1 + (slot * ARENA_TEAM_END) + type, value); - } + void SetArenaTeamInfoField(uint8 slot, ArenaTeamInfoType type, uint32 value); static uint32 GetArenaTeamIdFromDB(uint64 guid, uint8 slot); static void LeaveAllArenaTeams(uint64 guid); - uint32 GetArenaTeamId(uint8 slot) const { return GetUInt32Value(PLAYER_FIELD_ARENA_TEAM_INFO_1_1 + (slot * ARENA_TEAM_END) + ARENA_TEAM_ID); } - uint32 GetArenaPersonalRating(uint8 slot) const { return GetUInt32Value(PLAYER_FIELD_ARENA_TEAM_INFO_1_1 + (slot * ARENA_TEAM_END) + ARENA_TEAM_PERSONAL_RATING); } + uint32 GetArenaTeamId(uint8 slot) const; + uint32 GetArenaPersonalRating(uint8 slot) const; void SetArenaTeamIdInvited(uint32 ArenaTeamId) { m_ArenaTeamIdInvited = ArenaTeamId; } uint32 GetArenaTeamIdInvited() { return m_ArenaTeamIdInvited; } diff --git a/src/server/game/Scripting/ScriptMgr.cpp b/src/server/game/Scripting/ScriptMgr.cpp index 13d09d324..fbbade441 100644 --- a/src/server/game/Scripting/ScriptMgr.cpp +++ b/src/server/game/Scripting/ScriptMgr.cpp @@ -59,6 +59,7 @@ template class ScriptRegistry; template class ScriptRegistry; template class ScriptRegistry; template class ScriptRegistry; +template class ScriptRegistry; template class ScriptRegistry; template class ScriptRegistry; template class ScriptRegistry; @@ -124,6 +125,7 @@ void ScriptMgr::Unload() SCR_CLEAR(GlobalScript); SCR_CLEAR(ModuleScript); SCR_CLEAR(BGScript); + SCR_CLEAR(ArenaTeamScript); SCR_CLEAR(SpellSC); SCR_CLEAR(GameEventScript); SCR_CLEAR(MailScript); @@ -197,6 +199,7 @@ void ScriptMgr::CheckIfScriptsInDatabaseExist() !ScriptRegistry::GetScriptById(sid) && !ScriptRegistry::GetScriptById(sid) && !ScriptRegistry::GetScriptById(sid) && + !ScriptRegistry::GetScriptById(sid) && !ScriptRegistry::GetScriptById(sid) && !ScriptRegistry::GetScriptById(sid)) sLog->outErrorDb("Script named '%s' is assigned in the database, but has no code!", (*itr).c_str()); @@ -1667,6 +1670,21 @@ void ScriptMgr::OnPlayerJoinArena(Player* player) FOREACH_SCRIPT(PlayerScript)->OnPlayerJoinArena(player); } +void ScriptMgr::GetCustomGetArenaTeamId(const Player* player, uint8 slot, uint32& teamID) const +{ + FOREACH_SCRIPT(PlayerScript)->GetCustomGetArenaTeamId(player, slot, teamID); +} + +void ScriptMgr::GetCustomArenaPersonalRating(const Player* player, uint8 slot, uint32& rating) const +{ + FOREACH_SCRIPT(PlayerScript)->GetCustomArenaPersonalRating(player, slot, rating); +} + +void ScriptMgr::OnGetMaxPersonalArenaRatingRequirement(const Player* player, uint32 minSlot, uint32& maxArenaRating) const +{ + FOREACH_SCRIPT(PlayerScript)->OnGetMaxPersonalArenaRatingRequirement(player, minSlot, maxArenaRating); +} + void ScriptMgr::OnLootItem(Player* player, Item* item, uint32 count, uint64 lootguid) { FOREACH_SCRIPT(PlayerScript)->OnLootItem(player, item, count, lootguid); @@ -2108,6 +2126,31 @@ bool ScriptMgr::CanSendMessageQueue(BattlegroundQueue* queue, Player* leader, Ba return ret; } +void ScriptMgr::OnGetSlotByType(const uint32 type, uint8& slot) +{ + FOREACH_SCRIPT(ArenaTeamScript)->OnGetSlotByType(type, slot); +} + +void ScriptMgr::OnGetArenaPoints(ArenaTeam* at, float& points) +{ + FOREACH_SCRIPT(ArenaTeamScript)->OnGetArenaPoints(at, points); +} + +void ScriptMgr::OnArenaTypeIDToQueueID(const BattlegroundTypeId bgTypeId, const uint8 arenaType, uint32& queueTypeID) +{ + FOREACH_SCRIPT(ArenaTeamScript)->OnTypeIDToQueueID(bgTypeId, arenaType, queueTypeID); +} + +void ScriptMgr::OnArenaQueueIdToArenaType(const BattlegroundQueueTypeId bgQueueTypeId, uint8& ArenaType) +{ + FOREACH_SCRIPT(ArenaTeamScript)->OnQueueIdToArenaType(bgQueueTypeId, ArenaType); +} + +void ScriptMgr::OnSetArenaMaxPlayersPerTeam(const uint8 arenaType, uint32& maxPlayerPerTeam) +{ + FOREACH_SCRIPT(ArenaTeamScript)->OnSetArenaMaxPlayersPerTeam(arenaType, maxPlayerPerTeam); +} + // SpellSC void ScriptMgr::OnCalcMaxDuration(Aura const* aura, int32& maxDuration) { @@ -2323,6 +2366,12 @@ BGScript::BGScript(char const* name) ScriptRegistry::AddScript(this); } +ArenaTeamScript::ArenaTeamScript(const char* name) + : ScriptObject(name) +{ + ScriptRegistry::AddScript(this); +} + SpellSC::SpellSC(char const* name) : ScriptObject(name) { diff --git a/src/server/game/Scripting/ScriptMgr.h b/src/server/game/Scripting/ScriptMgr.h index 4b557dfe5..690bcea21 100644 --- a/src/server/game/Scripting/ScriptMgr.h +++ b/src/server/game/Scripting/ScriptMgr.h @@ -960,6 +960,15 @@ public: // After player enters queue for Arena virtual void OnPlayerJoinArena(Player* /*player*/) { } + //Called when trying to get a team ID of a slot > 2 (This is for custom teams created by modules) + virtual void GetCustomGetArenaTeamId(const Player* /*player*/, uint8 /*slot*/, uint32& /*teamID*/) const { } + + //Called when trying to get players personal rating of an arena slot > 2 (This is for custom teams created by modules) + virtual void GetCustomArenaPersonalRating(const Player* /*player*/, uint8 /*slot*/, uint32& /*rating*/) const { } + + //Called after the normal slots (0..2) for arena have been evaluated so that custom arena teams could modify it if nececasry + virtual void OnGetMaxPersonalArenaRatingRequirement(const Player* /*player*/, uint32 /*minSlot*/, uint32& /*maxArenaRating*/) const {} + //After looting item virtual void OnLootItem(Player* /*player*/, Item* /*item*/, uint32 /*count*/, uint64 /*lootguid*/) { } @@ -1173,6 +1182,21 @@ public: virtual bool CanSendMessageQueue(BattlegroundQueue* /*queue*/, Player* /*leader*/, Battleground* /*bg*/, PvPDifficultyEntry const* /*bracketEntry*/) { return true; } }; +class ArenaTeamScript : public ScriptObject +{ +protected: + ArenaTeamScript(const char* name); + +public: + bool IsDatabaseBound() const { return false; }; + + virtual void OnGetSlotByType(const uint32 /*type*/, uint8& /*slot*/) {} + virtual void OnGetArenaPoints(ArenaTeam* /*team*/, float& /*points*/) {} + virtual void OnTypeIDToQueueID(const BattlegroundTypeId /*bgTypeId*/, const uint8 /*arenaType*/, uint32& /*queueTypeID*/) {} + virtual void OnQueueIdToArenaType(const BattlegroundQueueTypeId /*bgQueueTypeId*/, uint8& /*ArenaType*/) {} + virtual void OnSetArenaMaxPlayersPerTeam(const uint8 /*arenaType*/, uint32& /*maxPlayerPerTeam*/) {} +}; + class SpellSC : public ScriptObject { protected: @@ -1460,6 +1484,9 @@ public: /* PlayerScript */ void OnEquip(Player* player, Item* it, uint8 bag, uint8 slot, bool update); void OnPlayerJoinBG(Player* player); void OnPlayerJoinArena(Player* player); + void GetCustomGetArenaTeamId(const Player* player, uint8 slot, uint32& teamID) const; + void GetCustomArenaPersonalRating(const Player* player, uint8 slot, uint32& rating) const; + void OnGetMaxPersonalArenaRatingRequirement(const Player* player, uint32 minSlot, uint32& maxArenaRating) const; 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); @@ -1572,6 +1599,14 @@ public: /* BGScript */ 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); +public: /* Arena Team Script */ + + void OnGetSlotByType(const uint32 type, uint8& slot); + void OnGetArenaPoints(ArenaTeam* at, float& points); + void OnArenaTypeIDToQueueID(const BattlegroundTypeId bgTypeId, const uint8 arenaType, uint32& queueTypeID); + void OnArenaQueueIdToArenaType(const BattlegroundQueueTypeId bgQueueTypeId, uint8& ArenaType); + void OnSetArenaMaxPlayersPerTeam(const uint8 arenaType, uint32& maxPlayerPerTeam); + public: /* SpellSC */ void OnCalcMaxDuration(Aura const* aura, int32& maxDuration); @@ -1643,9 +1678,10 @@ public: if (script->IsDatabaseBound()) { - if (!_checkMemory(script)) + { return; + } // Get an ID for the script. An ID only exists if it's a script that is assigned in the database // through a script name (or similar). diff --git a/src/server/game/World/World.h b/src/server/game/World/World.h index 2b7973112..ecab18d16 100644 --- a/src/server/game/World/World.h +++ b/src/server/game/World/World.h @@ -585,7 +585,7 @@ struct GlobalPlayerData uint16 mailCount; uint32 guildId; uint32 groupId; - uint32 arenaTeamId[3]; + std::map arenaTeamId; }; enum GlobalPlayerUpdateMask