Merge branch 'master' into Playerbot

This commit is contained in:
Yunfan Li
2025-02-19 22:29:36 +08:00
parent d1032678ff
commit 7d431dc796
277 changed files with 7092 additions and 5050 deletions
+7 -5
View File
@@ -25,7 +25,8 @@
#include "ScriptMgr.h"
#include "World.h"
#include "WorldSession.h"
//#include "WorldStatePackets.h"
#include "WorldSessionMgr.h"
#include "WorldStatePackets.h"
void ArenaScore::AppendToPacket(WorldPacket& data)
{
@@ -146,10 +147,11 @@ void Arena::RemovePlayer(Player* /*player*/)
CheckWinConditions();
}
void Arena::FillInitialWorldStates(WorldPacket& data)
void Arena::FillInitialWorldStates(WorldPackets::WorldState::InitWorldStates& packet)
{
data << uint32(ARENA_WORLD_STATE_ALIVE_PLAYERS_GREEN) << uint32(GetAlivePlayersCountByTeam(TEAM_HORDE));
data << uint32(ARENA_WORLD_STATE_ALIVE_PLAYERS_GOLD) << uint32(GetAlivePlayersCountByTeam(TEAM_ALLIANCE));
packet.Worldstates.reserve(2);
packet.Worldstates.emplace_back(ARENA_WORLD_STATE_ALIVE_PLAYERS_GREEN, GetAlivePlayersCountByTeam(TEAM_HORDE));
packet.Worldstates.emplace_back(ARENA_WORLD_STATE_ALIVE_PLAYERS_GOLD, GetAlivePlayersCountByTeam(TEAM_ALLIANCE));
}
void Arena::UpdateArenaWorldState()
@@ -224,7 +226,7 @@ void Arena::EndBattleground(TeamId winnerTeamId)
{
// pussywizard: arena logs in database
uint32 fightId = sArenaTeamMgr->GetNextArenaLogId();
uint32 currOnline = sWorld->GetActiveSessionCount();
uint32 currOnline = sWorldSessionMgr->GetActiveSessionCount();
CharacterDatabaseTransaction trans = CharacterDatabase.BeginTransaction();
CharacterDatabasePreparedStatement* stmt2 = CharacterDatabase.GetPreparedStatement(CHAR_INS_ARENA_LOG_FIGHT);
+1 -1
View File
@@ -52,7 +52,7 @@ protected:
void AddPlayer(Player* player) override;
void RemovePlayer(Player* /*player*/) override;
void FillInitialWorldStates(WorldPacket& data) override;
void FillInitialWorldStates(WorldPackets::WorldState::InitWorldStates& packet) override;
void UpdateArenaWorldState();
void HandleKillPlayer(Player* player, Player* killer) override;
@@ -0,0 +1,224 @@
/*
* This file is part of the AzerothCore Project. See AUTHORS file for Copyright information
*
* This program is free software; you can redistribute it and/or modify it
* under the terms of the GNU Affero General Public License as published by the
* Free Software Foundation; either version 3 of the License, or (at your
* option) any later version.
*
* This program is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU Affero General Public License for
* more details.
*
* You should have received a copy of the GNU General Public License along
* with this program. If not, see <http://www.gnu.org/licenses/>.
*/
#include "ArenaSeasonMgr.h"
#include "ArenaTeamMgr.h"
#include "ArenaSeasonRewardsDistributor.h"
#include "BattlegroundMgr.h"
#include "GameEventMgr.h"
#include "MapMgr.h"
#include "Player.h"
ArenaSeasonMgr* ArenaSeasonMgr::instance()
{
static ArenaSeasonMgr instance;
return &instance;
}
void ArenaSeasonMgr::LoadRewards()
{
uint32 oldMSTime = getMSTime();
std::unordered_map<std::string, ArenaSeasonRewardGroupCriteriaType> stringToArenaSeasonRewardGroupCriteriaType = {
{"pct", ArenaSeasonRewardGroupCriteriaType::ARENA_SEASON_REWARD_CRITERIA_TYPE_PERCENT_VALUE},
{"abs", ArenaSeasonRewardGroupCriteriaType::ARENA_SEASON_REWARD_CRITERIA_TYPE_ABSOLUTE_VALUE}
};
QueryResult result = WorldDatabase.Query("SELECT id, arena_season, criteria_type, min_criteria, max_criteria, reward_mail_template_id, reward_mail_subject, reward_mail_body, gold_reward FROM arena_season_reward_group");
if (!result)
{
LOG_WARN("server.loading", ">> Loaded 0 arena season rewards. DB table `arena_season_reward_group` is empty.");
LOG_INFO("server.loading", " ");
return;
}
std::unordered_map<uint32, ArenaSeasonRewardGroup> groupsMap;
do
{
Field* fields = result->Fetch();
uint32 id = fields[0].Get<uint32>();
ArenaSeasonRewardGroup group;
group.season = fields[1].Get<uint8>();
group.criteriaType = stringToArenaSeasonRewardGroupCriteriaType[fields[2].Get<std::string>()];
group.minCriteria = fields[3].Get<float>();
group.maxCriteria = fields[4].Get<float>();
group.rewardMailTemplateID = fields[5].Get<uint32>();
group.rewardMailSubject = fields[6].Get<std::string>();
group.rewardMailBody = fields[7].Get<std::string>();
group.goldReward = fields[8].Get<uint32>();
groupsMap[id] = group;
} while (result->NextRow());
std::unordered_map<std::string, ArenaSeasonRewardType> stringToArenaSeasonRewardType = {
{"achievement", ArenaSeasonRewardType::ARENA_SEASON_REWARD_TYPE_ACHIEVEMENT},
{"item", ArenaSeasonRewardType::ARENA_SEASON_REWARD_TYPE_ITEM}
};
result = WorldDatabase.Query("SELECT group_id, type, entry FROM arena_season_reward");
if (!result)
{
LOG_WARN("server.loading", ">> Loaded 0 arena season rewards. DB table `arena_season_reward` is empty.");
LOG_INFO("server.loading", " ");
return;
}
do
{
Field* fields = result->Fetch();
uint32 groupId = fields[0].Get<uint32>();
ArenaSeasonReward reward;
reward.type = stringToArenaSeasonRewardType[fields[1].Get<std::string>()];
reward.entry = fields[2].Get<uint32>();
auto itr = groupsMap.find(groupId);
ASSERT(itr != groupsMap.end(), "Unknown arena_season_reward_group ({}) in arena_season_reward", groupId);
(reward.type == ARENA_SEASON_REWARD_TYPE_ITEM) ?
groupsMap[groupId].itemRewards.push_back(reward) :
groupsMap[groupId].achievementRewards.push_back(reward);
} while (result->NextRow());
for (auto const& itr : groupsMap)
_arenaSeasonRewardGroupsStore[itr.second.season].push_back(itr.second);
LOG_INFO("server.loading", ">> Loaded {} arena season rewards in {} ms", (uint32)groupsMap.size(), GetMSTimeDiffToNow(oldMSTime));
LOG_INFO("server.loading", " ");
}
void ArenaSeasonMgr::LoadActiveSeason()
{
QueryResult result = CharacterDatabase.Query("SELECT season_id, season_state FROM active_arena_season");
ASSERT(result, "active_arena_season can't be empty");
Field* fields = result->Fetch();
_currentSeason = fields[0].Get<uint8>();
_currentSeasonState = static_cast<ArenaSeasonState>(fields[1].Get<uint8>());
uint16 eventID = GameEventForArenaSeason(_currentSeason);
sGameEventMgr->StartEvent(eventID, true);
LOG_INFO("server.loading", "Arena Season {} loaded...", _currentSeason);
LOG_INFO("server.loading", " ");
}
void ArenaSeasonMgr::RewardTeamsForTheSeason(std::shared_ptr<ArenaTeamFilter> teamsFilter)
{
ArenaSeasonTeamRewarderImpl rewarder = ArenaSeasonTeamRewarderImpl();
ArenaSeasonRewardDistributor distributor = ArenaSeasonRewardDistributor(&rewarder);
std::vector<ArenaSeasonRewardGroup> rewards = _arenaSeasonRewardGroupsStore[GetCurrentSeason()];
ArenaTeamMgr::ArenaTeamContainer filteredTeams = teamsFilter->Filter(sArenaTeamMgr->GetArenaTeams());
distributor.DistributeRewards(filteredTeams, rewards);
}
bool ArenaSeasonMgr::CanDeleteArenaTeams()
{
std::vector<ArenaSeasonRewardGroup> rewards = _arenaSeasonRewardGroupsStore[GetCurrentSeason()];
if (rewards.empty())
return false;
for (auto const& bg : sBattlegroundMgr->GetActiveBattlegrounds())
if (bg->isRated())
return false;
return true;
}
void ArenaSeasonMgr::DeleteArenaTeams()
{
if (!CanDeleteArenaTeams())
return;
// Cleanup queue first.
std::vector<BattlegroundQueueTypeId> arenasQueueTypes = {BATTLEGROUND_QUEUE_2v2, BATTLEGROUND_QUEUE_3v3, BATTLEGROUND_QUEUE_5v5};
for (BattlegroundQueueTypeId queueType : arenasQueueTypes)
{
auto queue = sBattlegroundMgr->GetBattlegroundQueue(queueType);
for (auto const& [playerGUID, other] : queue.m_QueuedPlayers)
queue.RemovePlayer(playerGUID, true);
}
sArenaTeamMgr->DeleteAllArenaTeams();
}
void ArenaSeasonMgr::ChangeCurrentSeason(uint8 season)
{
if (_currentSeason == season)
return;
uint16 currentEventID = GameEventForArenaSeason(_currentSeason);
sGameEventMgr->StopEvent(currentEventID, true);
uint16 newEventID = GameEventForArenaSeason(season);
sGameEventMgr->StartEvent(newEventID, true);
_currentSeason = season;
_currentSeasonState = ARENA_SEASON_STATE_IN_PROGRESS;
CharacterDatabase.Execute("UPDATE active_arena_season SET season_id = {}, season_state = {}", _currentSeason, _currentSeasonState);
BroadcastUpdatedWorldState();
}
void ArenaSeasonMgr::SetSeasonState(ArenaSeasonState state)
{
if (_currentSeasonState == state)
return;
_currentSeasonState = state;
CharacterDatabase.Execute("UPDATE active_arena_season SET season_state = {}", _currentSeasonState);
BroadcastUpdatedWorldState();
}
uint16 ArenaSeasonMgr::GameEventForArenaSeason(uint8 season)
{
QueryResult result = WorldDatabase.Query("SELECT eventEntry FROM game_event_arena_seasons WHERE season = '{}'", season);
if (!result)
{
LOG_ERROR("arenaseasonmgr", "ArenaSeason ({}) must be an existant Arena Season", season);
return 0;
}
Field* fields = result->Fetch();
return fields[0].Get<uint16>();
}
void ArenaSeasonMgr::BroadcastUpdatedWorldState()
{
sMapMgr->DoForAllMaps([](Map* map)
{
// Ignore instanceable maps, players will get a fresh state once they change the map.
if (map->Instanceable())
return;
map->DoForAllPlayers([&](Player* player)
{
uint32 currZone, currArea;
player->GetZoneAndAreaId(currZone, currArea);
player->SendInitWorldStates(currZone, currArea);
});
});
}
@@ -0,0 +1,126 @@
/*
* This file is part of the AzerothCore Project. See AUTHORS file for Copyright information
*
* This program is free software; you can redistribute it and/or modify it
* under the terms of the GNU Affero General Public License as published by the
* Free Software Foundation; either version 3 of the License, or (at your
* option) any later version.
*
* This program is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU Affero General Public License for
* more details.
*
* You should have received a copy of the GNU General Public License along
* with this program. If not, see <http://www.gnu.org/licenses/>.
*/
#ifndef _ARENASEASONMGR_H
#define _ARENASEASONMGR_H
#include "Common.h"
#include "ArenaTeamFilter.h"
#include <vector>
#include <unordered_map>
enum ArenaSeasonState
{
ARENA_SEASON_STATE_DISABLED = 0,
ARENA_SEASON_STATE_IN_PROGRESS = 1
};
enum ArenaSeasonRewardType
{
ARENA_SEASON_REWARD_TYPE_ITEM,
ARENA_SEASON_REWARD_TYPE_ACHIEVEMENT
};
enum ArenaSeasonRewardGroupCriteriaType
{
ARENA_SEASON_REWARD_CRITERIA_TYPE_PERCENT_VALUE,
ARENA_SEASON_REWARD_CRITERIA_TYPE_ABSOLUTE_VALUE
};
// ArenaSeasonReward represents one reward, it can be an item or achievement.
struct ArenaSeasonReward
{
ArenaSeasonReward() = default;
// Item or acheivement entry.
uint32 entry{};
ArenaSeasonRewardType type{ARENA_SEASON_REWARD_TYPE_ITEM};
// Used in unit tests.
bool operator==(const ArenaSeasonReward& other) const
{
return entry == other.entry && type == other.type;
}
};
struct ArenaSeasonRewardGroup
{
ArenaSeasonRewardGroup() = default;
uint8 season{};
ArenaSeasonRewardGroupCriteriaType criteriaType;
float minCriteria{};
float maxCriteria{};
uint32 rewardMailTemplateID{};
std::string rewardMailSubject{};
std::string rewardMailBody{};
uint32 goldReward{};
std::vector<ArenaSeasonReward> itemRewards;
std::vector<ArenaSeasonReward> achievementRewards;
// Used in unit tests.
bool operator==(const ArenaSeasonRewardGroup& other) const
{
return minCriteria == other.minCriteria &&
maxCriteria == other.maxCriteria &&
criteriaType == other.criteriaType &&
itemRewards == other.itemRewards &&
achievementRewards == other.achievementRewards;
}
};
class ArenaSeasonMgr
{
public:
static ArenaSeasonMgr* instance();
using ArenaSeasonRewardGroupsBySeasonContainer = std::unordered_map<uint8, std::vector<ArenaSeasonRewardGroup>>;
// Loading functions
void LoadRewards();
void LoadActiveSeason();
// Season management functions
void ChangeCurrentSeason(uint8 season);
uint8 GetCurrentSeason() { return _currentSeason; }
void SetSeasonState(ArenaSeasonState state);
ArenaSeasonState GetSeasonState() { return _currentSeasonState; }
// Season completion functions
void RewardTeamsForTheSeason(std::shared_ptr<ArenaTeamFilter> teamsFilter);
bool CanDeleteArenaTeams();
void DeleteArenaTeams();
private:
uint16 GameEventForArenaSeason(uint8 season);
void BroadcastUpdatedWorldState();
ArenaSeasonRewardGroupsBySeasonContainer _arenaSeasonRewardGroupsStore;
uint8 _currentSeason{};
ArenaSeasonState _currentSeasonState{};
};
#define sArenaSeasonMgr ArenaSeasonMgr::instance()
#endif // _ARENASEASONMGR_H
@@ -0,0 +1,166 @@
/*
* This file is part of the AzerothCore Project. See AUTHORS file for Copyright information
*
* This program is free software; you can redistribute it and/or modify it
* under the terms of the GNU Affero General Public License as published by the
* Free Software Foundation; either version 3 of the License, or (at your
* option) any later version.
*
* This program is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU Affero General Public License for
* more details.
*
* You should have received a copy of the GNU General Public License along
* with this program. If not, see <http://www.gnu.org/licenses/>.
*/
#include "ArenaSeasonRewardsDistributor.h"
#include "AchievementMgr.h"
#include "CharacterDatabase.h"
#include "Mail.h"
#include "Player.h"
#include <algorithm>
constexpr float minPctTeamGamesForMemberToGetReward = 30;
void ArenaSeasonTeamRewarderImpl::RewardTeamWithRewardGroup(ArenaTeam *arenaTeam, const ArenaSeasonRewardGroup &rewardGroup)
{
RewardWithMail(arenaTeam, rewardGroup);
RewardWithAchievements(arenaTeam, rewardGroup);
}
void ArenaSeasonTeamRewarderImpl::RewardWithMail(ArenaTeam* arenaTeam, ArenaSeasonRewardGroup const & rewardGroup)
{
if (rewardGroup.itemRewards.empty() && rewardGroup.goldReward == 0)
return;
const uint32 npcKingDondSender = 18897;
CharacterDatabaseTransaction trans = CharacterDatabase.BeginTransaction();
for (auto const& member : arenaTeam->GetMembers())
{
uint32 teamSeasonGames = arenaTeam->GetStats().SeasonGames;
// Avoid division by zero.
if (teamSeasonGames == 0)
continue;
float memberParticipationPercentage = (static_cast<float>(member.SeasonGames) / teamSeasonGames) * 100;
if (memberParticipationPercentage < minPctTeamGamesForMemberToGetReward)
continue;
Player* player = ObjectAccessor::FindPlayer(member.Guid);
auto draft = rewardGroup.rewardMailTemplateID > 0 ?
MailDraft(rewardGroup.rewardMailTemplateID, false) :
MailDraft(rewardGroup.rewardMailSubject, rewardGroup.rewardMailBody);
if (rewardGroup.goldReward > 0)
draft.AddMoney(rewardGroup.goldReward);
for (auto const& reward : rewardGroup.itemRewards)
if (Item* item = Item::CreateItem(reward.entry, 1))
{
item->SaveToDB(trans);
draft.AddItem(item);
}
draft.SendMailTo(trans, MailReceiver(player, member.Guid.GetCounter()), MailSender(npcKingDondSender));
}
CharacterDatabase.CommitTransaction(trans);
}
void ArenaSeasonTeamRewarderImpl::RewardWithAchievements(ArenaTeam* arenaTeam, ArenaSeasonRewardGroup const & rewardGroup)
{
if (rewardGroup.achievementRewards.empty())
return;
for (auto const& member : arenaTeam->GetMembers())
{
uint32 teamSeasonGames = arenaTeam->GetStats().SeasonGames;
// Avoid division by zero.
if (teamSeasonGames == 0)
continue;
float memberParticipationPercentage = (static_cast<float>(member.SeasonGames) / teamSeasonGames) * 100;
if (memberParticipationPercentage < minPctTeamGamesForMemberToGetReward)
continue;
Player* player = ObjectAccessor::FindPlayer(member.Guid);
for (auto const& reward : rewardGroup.achievementRewards)
{
AchievementEntry const* achievement = sAchievementStore.LookupEntry(reward.entry);
if (!achievement)
continue;
if (player)
player->CompletedAchievement(achievement);
else
sAchievementMgr->CompletedAchievementForOfflinePlayer(member.Guid.GetCounter(), achievement);
}
}
}
ArenaSeasonRewardDistributor::ArenaSeasonRewardDistributor(ArenaSeasonTeamRewarder* rewarder)
: _rewarder(rewarder)
{
}
void ArenaSeasonRewardDistributor::DistributeRewards(ArenaTeamMgr::ArenaTeamContainer &arenaTeams, std::vector<ArenaSeasonRewardGroup> &rewardGroups)
{
std::vector<ArenaTeam*> sortedTeams;
sortedTeams.reserve(arenaTeams.size());
static constexpr uint16 minRequiredGames = 30;
for (auto const& [id, team] : arenaTeams)
if (team->GetStats().SeasonGames >= minRequiredGames)
sortedTeams.push_back(team);
std::sort(sortedTeams.begin(), sortedTeams.end(), [](ArenaTeam* a, ArenaTeam* b) {
return a->GetRating() > b->GetRating();
});
std::vector<ArenaSeasonRewardGroup> pctRewardGroup;
std::vector<ArenaSeasonRewardGroup> absRewardGroup;
for (auto const& reward : rewardGroups)
{
if (reward.criteriaType == ARENA_SEASON_REWARD_CRITERIA_TYPE_PERCENT_VALUE)
pctRewardGroup.push_back(reward);
else
absRewardGroup.push_back(reward);
}
size_t totalTeams = sortedTeams.size();
for (auto const& rewardGroup : pctRewardGroup)
{
size_t minIndex = static_cast<size_t>(rewardGroup.minCriteria * totalTeams / 100);
size_t maxIndex = static_cast<size_t>(rewardGroup.maxCriteria * totalTeams / 100);
minIndex = std::min(minIndex, totalTeams);
maxIndex = std::min(maxIndex, totalTeams);
for (size_t i = minIndex; i < maxIndex; ++i)
{
ArenaTeam* team = sortedTeams[i];
_rewarder->RewardTeamWithRewardGroup(team, rewardGroup);
}
}
for (auto const& rewardGroup : absRewardGroup)
{
size_t minIndex = rewardGroup.minCriteria-1; // Top 1 team is the team with index 0, so we need make -1.
size_t maxIndex = rewardGroup.maxCriteria;
minIndex = std::max(minIndex, size_t(0));
minIndex = std::min(minIndex, totalTeams);
maxIndex = std::min(maxIndex, totalTeams);
for (size_t i = minIndex; i < maxIndex; ++i)
{
ArenaTeam* team = sortedTeams[i];
_rewarder->RewardTeamWithRewardGroup(team, rewardGroup);
}
}
}
@@ -0,0 +1,54 @@
/*
* This file is part of the AzerothCore Project. See AUTHORS file for Copyright information
*
* This program is free software; you can redistribute it and/or modify it
* under the terms of the GNU Affero General Public License as published by the
* Free Software Foundation; either version 3 of the License, or (at your
* option) any later version.
*
* This program is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU Affero General Public License for
* more details.
*
* You should have received a copy of the GNU General Public License along
* with this program. If not, see <http://www.gnu.org/licenses/>.
*/
#ifndef _ARENASEASONREWARDDISTRIBUTOR_H
#define _ARENASEASONREWARDDISTRIBUTOR_H
#include "ArenaSeasonMgr.h"
#include "ArenaTeam.h"
#include "ArenaTeamMgr.h"
class ArenaSeasonTeamRewarder
{
public:
virtual ~ArenaSeasonTeamRewarder() = default;
virtual void RewardTeamWithRewardGroup(ArenaTeam* arenaTeam, ArenaSeasonRewardGroup const & rewardGroup) = 0;
};
class ArenaSeasonTeamRewarderImpl: public ArenaSeasonTeamRewarder
{
public:
void RewardTeamWithRewardGroup(ArenaTeam* arenaTeam, ArenaSeasonRewardGroup const & rewardGroup) override;
private:
void RewardWithMail(ArenaTeam* arenaTeam, ArenaSeasonRewardGroup const & rewardGroup);
void RewardWithAchievements(ArenaTeam* arenaTeam, ArenaSeasonRewardGroup const & rewardGroup);
};
class ArenaSeasonRewardDistributor
{
public:
ArenaSeasonRewardDistributor(ArenaSeasonTeamRewarder* rewarder);
void DistributeRewards(ArenaTeamMgr::ArenaTeamContainer& arenaTeams, std::vector<ArenaSeasonRewardGroup>& rewardGroups);
private:
ArenaSeasonTeamRewarder* _rewarder;
};
#endif // _ARENASEASONREWARDDISTRIBUTOR_H
@@ -0,0 +1,113 @@
/*
* This file is part of the AzerothCore Project. See AUTHORS file for Copyright information
*
* This program is free software; you can redistribute it and/or modify it
* under the terms of the GNU Affero General Public License as published by the
* Free Software Foundation; either version 3 of the License, or (at your
* option) any later version.
*
* This program is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU Affero General Public License for
* more details.
*
* You should have received a copy of the GNU General Public License along
* with this program. If not, see <http://www.gnu.org/licenses/>.
*/
#ifndef _ARENATEAMFILTER_H
#define _ARENATEAMFILTER_H
#include "Common.h"
#include "ArenaTeamMgr.h"
#include "ArenaTeam.h"
#include "Tokenize.h"
#include "StringConvert.h"
#include <sstream>
#include <string>
#include <memory>
#include <unordered_map>
#include <algorithm>
#include <cctype>
class ArenaTeamFilter
{
public:
virtual ~ArenaTeamFilter() = default;
virtual ArenaTeamMgr::ArenaTeamContainer Filter(ArenaTeamMgr::ArenaTeamContainer teams) = 0;
};
class ArenaTeamFilterByTypes : public ArenaTeamFilter
{
public:
ArenaTeamFilterByTypes(std::vector<uint8> validTypes) : _validTypes(validTypes) {}
ArenaTeamMgr::ArenaTeamContainer Filter(ArenaTeamMgr::ArenaTeamContainer teams) override
{
ArenaTeamMgr::ArenaTeamContainer result;
for (auto const& pair : teams)
{
ArenaTeam* team = pair.second;
for (uint8 arenaType : _validTypes)
{
if (team->GetType() == arenaType)
{
result[pair.first] = team;
break;
}
}
}
return result;
}
private:
std::vector<uint8> _validTypes;
};
class ArenaTeamFilterAllTeams : public ArenaTeamFilter
{
public:
ArenaTeamMgr::ArenaTeamContainer Filter(ArenaTeamMgr::ArenaTeamContainer teams) override
{
return teams;
}
};
class ArenaTeamFilterFactoryByUserInput
{
public:
std::unique_ptr<ArenaTeamFilter> CreateFilterByUserInput(std::string userInput)
{
std::transform(userInput.begin(), userInput.end(), userInput.begin(),
[](unsigned char c) { return std::tolower(c); });
if (userInput == "all")
return std::make_unique<ArenaTeamFilterAllTeams>();
// Parse the input string (e.g., "2,3") into valid types
std::vector<uint8> validTypes = ParseTypes(userInput);
if (!validTypes.empty())
return std::make_unique<ArenaTeamFilterByTypes>(validTypes);
return nullptr;
}
private:
std::vector<uint8> ParseTypes(std::string_view userInput)
{
std::vector<uint8> validTypes;
auto tokens = Acore::Tokenize(userInput, ',', false);
for (auto const& token : tokens)
if (auto typeOpt = Acore::StringTo<uint8>(token))
validTypes.push_back(*typeOpt);
return validTypes;
}
};
#endif // _ARENATEAMFILTER_H
+2 -1
View File
@@ -17,6 +17,7 @@
#include "ArenaTeam.h"
#include "ArenaTeamMgr.h"
#include "ArenaSeasonMgr.h"
#include "BattlegroundMgr.h"
#include "CharacterCache.h"
#include "Group.h"
@@ -658,7 +659,7 @@ uint32 ArenaTeam::GetPoints(uint32 memberRating)
if (rating <= 1500)
{
if (sWorld->getIntConfig(CONFIG_ARENA_SEASON_ID) < 6 && !sWorld->getIntConfig(CONFIG_LEGACY_ARENA_POINTS_CALC))
if (sArenaSeasonMgr->GetCurrentSeason() < 6 && !sWorld->getIntConfig(CONFIG_LEGACY_ARENA_POINTS_CALC))
points = (float)rating * 0.22f + 14.0f;
else
points = 344;
@@ -125,6 +125,27 @@ void ArenaTeamMgr::RemoveArenaTeam(uint32 arenaTeamId)
ArenaTeamStore.erase(arenaTeamId);
}
void ArenaTeamMgr::DeleteAllArenaTeams()
{
for (auto const& [id, team] : ArenaTeamStore)
{
while (team->GetMembersSize() > 0)
team->DelMember(team->GetMembers().front().Guid, false);
delete team;
}
ArenaTeamStore.clear();
CharacterDatabaseTransaction trans = CharacterDatabase.BeginTransaction();
trans->Append("DELETE FROM arena_team_member");
trans->Append("DELETE FROM arena_team");
trans->Append("DELETE FROM character_arena_stats");
CharacterDatabase.CommitTransaction(trans);
NextArenaTeamId = 1;
}
uint32 ArenaTeamMgr::GenerateArenaTeamId()
{
if (NextArenaTeamId >= MAX_ARENA_TEAM_ID)
@@ -43,6 +43,8 @@ public:
void AddArenaTeam(ArenaTeam* arenaTeam);
void RemoveArenaTeam(uint32 Id);
void DeleteAllArenaTeams();
ArenaTeamContainer::iterator GetArenaTeamMapBegin() { return ArenaTeamStore.begin(); }
ArenaTeamContainer::iterator GetArenaTeamMapEnd() { return ArenaTeamStore.end(); }
ArenaTeamContainer& GetArenaTeams() { return ArenaTeamStore; }
+2 -1
View File
@@ -24,6 +24,7 @@
#include "GameObject.h"
#include "SharedDefines.h"
#include "World.h"
#include "WorldStatePackets.h"
class Creature;
class GameObject;
@@ -458,7 +459,7 @@ public:
// Packet Transfer
// method that should fill worldpacket with actual world states (not yet implemented for all battlegrounds!)
virtual void FillInitialWorldStates(WorldPacket& /*data*/) { }
virtual void FillInitialWorldStates(WorldPackets::WorldState::InitWorldStates& /*packet*/) { }
void SendPacketToTeam(TeamId teamId, WorldPacket const* packet, Player* sender = nullptr, bool self = true);
void SendPacketToAll(WorldPacket const* packet);
void YellToAll(Creature* creature, const char* text, uint32 language);
@@ -334,6 +334,18 @@ Battleground* BattlegroundMgr::GetBattlegroundTemplate(BattlegroundTypeId bgType
return bgs.empty() ? nullptr : bgs.begin()->second;
}
std::vector<Battleground const*> BattlegroundMgr::GetActiveBattlegrounds()
{
std::vector<Battleground const*> result;
for (auto const& [bgType, bgData] : bgDataStore)
for (auto const& [id, bg] : bgData._Battlegrounds)
if (bg->GetStatus() == STATUS_WAIT_JOIN || bg->GetStatus() == STATUS_IN_PROGRESS)
result.push_back(static_cast<const Battleground*>(bg));
return result;
}
uint32 BattlegroundMgr::CreateClientVisibleInstanceId(BattlegroundTypeId bgTypeId, BattlegroundBracketId bracket_id)
{
if (IsArenaType(bgTypeId))
@@ -82,6 +82,7 @@ public:
Battleground* GetBattleground(uint32 instanceID, BattlegroundTypeId bgTypeId);
Battleground* GetBattlegroundTemplate(BattlegroundTypeId bgTypeId);
Battleground* CreateNewBattleground(BattlegroundTypeId bgTypeId, PvPDifficultyEntry const* bracketEntry, uint8 arenaType, bool isRated);
std::vector<Battleground const*> GetActiveBattlegrounds();
void AddBattleground(Battleground* bg);
void RemoveBattleground(BattlegroundTypeId bgTypeId, uint32 instanceId);
@@ -1355,11 +1355,11 @@ bool BGQueueRemoveEvent::Execute(uint64 /*e_time*/, uint32 /*p_time*/)
CharacterDatabase.Execute(stmt);
}
sScriptMgr->OnBattlegroundDesertion(player, BG_DESERTION_TYPE_NO_ENTER_BUTTON);
sScriptMgr->OnPlayerBattlegroundDesertion(player, BG_DESERTION_TYPE_NO_ENTER_BUTTON);
}
if (bg && bg->isArena() && (bg->GetStatus() == STATUS_IN_PROGRESS || bg->GetStatus() == STATUS_WAIT_JOIN))
sScriptMgr->OnBattlegroundDesertion(player, ARENA_DESERTION_TYPE_NO_ENTER_BUTTON);
sScriptMgr->OnPlayerBattlegroundDesertion(player, ARENA_DESERTION_TYPE_NO_ENTER_BUTTON);
LOG_DEBUG("bg.battleground", "Battleground: removing player {} from bg queue for instance {} because of not pressing enter battle in time.", player->GetGUID().ToString(), m_BgInstanceGUID);
@@ -23,6 +23,7 @@
#include "Util.h"
#include "WorldPacket.h"
#include "WorldSession.h"
#include "WorldStatePackets.h"
void BattlegroundABScore::BuildObjectivesBlock(WorldPacket& data)
{
@@ -234,24 +235,26 @@ void BattlegroundAB::DeleteBanner(uint8 node)
SpawnBGObject(node * BG_AB_OBJECTS_PER_NODE + BG_AB_OBJECT_AURA_ALLY + _capturePointInfo[node]._ownerTeamId, RESPAWN_ONE_DAY);
}
void BattlegroundAB::FillInitialWorldStates(WorldPacket& data)
void BattlegroundAB::FillInitialWorldStates(WorldPackets::WorldState::InitWorldStates& packet)
{
packet.Worldstates.reserve(BG_AB_DYNAMIC_NODES_COUNT+7);
for (auto& node : _capturePointInfo)
{
if (node._state == BG_AB_NODE_STATE_NEUTRAL)
data << uint32(node._iconNone) << uint32(1);
packet.Worldstates.emplace_back(node._iconNone, 1);
for (uint8 i = BG_AB_NODE_STATE_ALLY_OCCUPIED; i <= BG_AB_NODE_STATE_HORDE_CONTESTED; ++i)
data << uint32(node._iconCapture + i - 1) << uint32(node._state == i);
packet.Worldstates.emplace_back(node._iconCapture + i - 1, node._state == i ? 1 : 0);
}
data << uint32(BG_AB_OP_OCCUPIED_BASES_ALLY) << uint32(_controlledPoints[TEAM_ALLIANCE]);
data << uint32(BG_AB_OP_OCCUPIED_BASES_HORDE) << uint32(_controlledPoints[TEAM_HORDE]);
data << uint32(BG_AB_OP_RESOURCES_MAX) << uint32(BG_AB_MAX_TEAM_SCORE);
data << uint32(BG_AB_OP_RESOURCES_WARNING) << uint32(BG_AB_WARNING_NEAR_VICTORY_SCORE);
data << uint32(BG_AB_OP_RESOURCES_ALLY) << uint32(m_TeamScores[TEAM_ALLIANCE]);
data << uint32(BG_AB_OP_RESOURCES_HORDE) << uint32(m_TeamScores[TEAM_HORDE]);
data << uint32(0x745) << uint32(0x2); // 37 1861 unk
packet.Worldstates.emplace_back(BG_AB_OP_OCCUPIED_BASES_ALLY, _controlledPoints[TEAM_ALLIANCE]);
packet.Worldstates.emplace_back(BG_AB_OP_OCCUPIED_BASES_HORDE, _controlledPoints[TEAM_HORDE]);
packet.Worldstates.emplace_back(BG_AB_OP_RESOURCES_MAX, BG_AB_MAX_TEAM_SCORE);
packet.Worldstates.emplace_back(BG_AB_OP_RESOURCES_WARNING, BG_AB_WARNING_NEAR_VICTORY_SCORE);
packet.Worldstates.emplace_back(BG_AB_OP_RESOURCES_ALLY, m_TeamScores[TEAM_ALLIANCE]);
packet.Worldstates.emplace_back(BG_AB_OP_RESOURCES_HORDE, m_TeamScores[TEAM_HORDE]);
packet.Worldstates.emplace_back(0x745, 2);
}
void BattlegroundAB::SendNodeUpdate(uint8 node)
@@ -316,7 +316,7 @@ public:
GraveyardStruct const* GetClosestGraveyard(Player* player) override;
bool UpdatePlayerScore(Player* player, uint32 type, uint32 value, bool doAddHonor = true) override;
void FillInitialWorldStates(WorldPacket& data) override;
void FillInitialWorldStates(WorldPackets::WorldState::InitWorldStates& packet) override;
void EventPlayerClickedOnFlag(Player* source, GameObject* gameObject) override;
bool AllNodesConrolledByTeam(TeamId teamId) const override;
@@ -25,6 +25,7 @@
#include "Player.h"
#include "SpellAuras.h"
#include "WorldPacket.h"
#include "WorldStatePackets.h"
void BattlegroundAVScore::BuildObjectivesBlock(WorldPacket& data)
{
@@ -1084,9 +1085,10 @@ void BattlegroundAV::EventPlayerAssaultsPoint(Player* player, uint32 object)
player->KilledMonsterCredit((IsTower(node)) ? BG_AV_QUEST_CREDIT_TOWER : BG_AV_QUEST_CREDIT_GRAVEYARD);
}
void BattlegroundAV::FillInitialWorldStates(WorldPacket& data)
void BattlegroundAV::FillInitialWorldStates(WorldPackets::WorldState::InitWorldStates& packet)
{
bool stateok;
packet.Worldstates.reserve(7*2*2 + 8*2*2 + 5);
//graveyards
for (uint8 i = BG_AV_NODES_FIRSTAID_STATION; i <= BG_AV_NODES_FROSTWOLF_HUT; i++)
{
@@ -1094,8 +1096,8 @@ void BattlegroundAV::FillInitialWorldStates(WorldPacket& data)
{
//j=1=assaulted j=3=controled
stateok = (m_Nodes[i].State == j);
data << uint32(BG_AV_NodeWorldStates[i][GetWorldStateType(j, TEAM_ALLIANCE)]) << uint32((m_Nodes[i].OwnerId == TEAM_ALLIANCE && stateok) ? 1 : 0);
data << uint32(BG_AV_NodeWorldStates[i][GetWorldStateType(j, TEAM_HORDE)]) << uint32((m_Nodes[i].OwnerId == TEAM_HORDE && stateok) ? 1 : 0);
packet.Worldstates.emplace_back(BG_AV_NodeWorldStates[i][GetWorldStateType(j, TEAM_ALLIANCE)], (m_Nodes[i].OwnerId == TEAM_ALLIANCE && stateok) ? 1 : 0);
packet.Worldstates.emplace_back(BG_AV_NodeWorldStates[i][GetWorldStateType(j, TEAM_HORDE)], (m_Nodes[i].OwnerId == TEAM_HORDE && stateok) ? 1 : 0);
}
}
@@ -1105,23 +1107,19 @@ void BattlegroundAV::FillInitialWorldStates(WorldPacket& data)
{
//j=1=assaulted j=3=controled //i dont have j=2=destroyed cause destroyed is the same like enemy-team controll
stateok = (m_Nodes[i].State == j || (m_Nodes[i].State == POINT_DESTROYED && j == 3));
data << uint32(BG_AV_NodeWorldStates[i][GetWorldStateType(j, TEAM_ALLIANCE)]) << uint32((m_Nodes[i].OwnerId == TEAM_ALLIANCE && stateok) ? 1 : 0);
data << uint32(BG_AV_NodeWorldStates[i][GetWorldStateType(j, TEAM_HORDE)]) << uint32((m_Nodes[i].OwnerId == TEAM_HORDE && stateok) ? 1 : 0);
packet.Worldstates.emplace_back(BG_AV_NodeWorldStates[i][GetWorldStateType(j, TEAM_ALLIANCE)], (m_Nodes[i].OwnerId == TEAM_ALLIANCE && stateok) ? 1 : 0);
packet.Worldstates.emplace_back(BG_AV_NodeWorldStates[i][GetWorldStateType(j, TEAM_HORDE)], (m_Nodes[i].OwnerId == TEAM_HORDE && stateok) ? 1 : 0);
}
if (m_Nodes[BG_AV_NODES_SNOWFALL_GRAVE].OwnerId == TEAM_NEUTRAL) //cause neutral teams aren't handled generic
data << uint32(AV_SNOWFALL_N) << uint32(1);
data << uint32(AV_Alliance_Score) << uint32(m_Team_Scores[0]);
data << uint32(AV_Horde_Score) << uint32(m_Team_Scores[1]);
if (GetStatus() == STATUS_IN_PROGRESS) //only if game started the teamscores are displayed
{
data << uint32(AV_SHOW_A_SCORE) << uint32(1);
data << uint32(AV_SHOW_H_SCORE) << uint32(1);
}
else
{
data << uint32(AV_SHOW_A_SCORE) << uint32(0);
data << uint32(AV_SHOW_H_SCORE) << uint32(0);
packet.Worldstates.emplace_back(AV_SNOWFALL_N, 1);
}
packet.Worldstates.emplace_back(AV_Alliance_Score, m_Team_Scores[0]);
packet.Worldstates.emplace_back(AV_Horde_Score, m_Team_Scores[1]);
packet.Worldstates.emplace_back(AV_SHOW_A_SCORE, GetStatus() == STATUS_IN_PROGRESS ? 1 : 0);
packet.Worldstates.emplace_back(AV_SHOW_H_SCORE, GetStatus() == STATUS_IN_PROGRESS ? 1 : 0);
SendMineWorldStates(AV_NORTH_MINE);
SendMineWorldStates(AV_SOUTH_MINE);
}
@@ -1940,7 +1940,7 @@ private:
void ChangeMineOwner(uint8 mine, TeamId teamId, bool initial = false);
/*worldstates*/
void FillInitialWorldStates(WorldPacket& data) override;
void FillInitialWorldStates(WorldPackets::WorldState::InitWorldStates& packet) override;
uint8 GetWorldStateType(uint8 state, TeamId teamId);
void SendMineWorldStates(uint32 mine);
void UpdateNodeWorldState(BG_AV_Nodes node);
@@ -19,6 +19,7 @@
#include "Log.h"
#include "Player.h"
#include "WorldPacket.h"
#include "WorldStatePackets.h"
BattlegroundBE::BattlegroundBE()
{
@@ -87,10 +88,10 @@ void BattlegroundBE::HandleAreaTrigger(Player* player, uint32 trigger)
}
}
void BattlegroundBE::FillInitialWorldStates(WorldPacket& data)
void BattlegroundBE::FillInitialWorldStates(WorldPackets::WorldState::InitWorldStates& packet)
{
data << uint32(0x9f3) << uint32(1); // 9
Arena::FillInitialWorldStates(data);
packet.Worldstates.emplace_back(0x9f3, 1); // BATTLEGROUND_BLADES_EDGE_ARENA_SHOW
Arena::FillInitialWorldStates(packet);
}
bool BattlegroundBE::SetupBattleground()
@@ -54,7 +54,7 @@ public:
void HandleAreaTrigger(Player* player, uint32 trigger) override;
bool SetupBattleground() override;
void FillInitialWorldStates(WorldPacket& d) override;
void FillInitialWorldStates(WorldPackets::WorldState::InitWorldStates& packet) override;
bool HandlePlayerUnderMap(Player* player) override;
};
@@ -22,6 +22,7 @@
#include "ObjectAccessor.h"
#include "Player.h"
#include "WorldPacket.h"
#include "WorldStatePackets.h"
BattlegroundDS::BattlegroundDS()
{
@@ -173,10 +174,10 @@ bool BattlegroundDS::HandlePlayerUnderMap(Player* player)
return true;
}
void BattlegroundDS::FillInitialWorldStates(WorldPacket& data)
void BattlegroundDS::FillInitialWorldStates(WorldPackets::WorldState::InitWorldStates& packet)
{
data << uint32(3610) << uint32(1); // 9 show
Arena::FillInitialWorldStates(data);
packet.Worldstates.emplace_back(0xe1a, 1); // ARENA_WORLD_STATE_ALIVE_PLAYERS_SHOW
Arena::FillInitialWorldStates(packet);
}
bool BattlegroundDS::SetupBattleground()
@@ -101,7 +101,7 @@ public:
void HandleAreaTrigger(Player* player, uint32 trigger) override;
bool SetupBattleground() override;
void FillInitialWorldStates(WorldPacket& d) override;
void FillInitialWorldStates(WorldPackets::WorldState::InitWorldStates& packet) override;
bool HandlePlayerUnderMap(Player* player) override;
private:
@@ -26,6 +26,7 @@
#include "World.h"
#include "WorldPacket.h"
#include "WorldSession.h"
#include "WorldStatePackets.h"
void BattlegroundEYScore::BuildObjectivesBlock(WorldPacket& data)
{
@@ -506,7 +507,7 @@ void BattlegroundEY::EventTeamCapturedPoint(Player* player, TeamId teamId, uint3
_capturePointInfo[point]._ownerTeamId = teamId;
GraveyardStruct const* sg = sGraveyard->GetGraveyard(m_CapturingPointTypes[point].GraveYardId);
GraveyardStruct const* sg = sGraveyard->GetGraveyard(m_CapturingPointTypes[point].GraveyardId);
AddSpiritGuide(point, sg->x, sg->y, sg->z, 3.124139f, teamId);
UpdatePointsIcons(point);
@@ -568,30 +569,31 @@ bool BattlegroundEY::UpdatePlayerScore(Player* player, uint32 type, uint32 value
return true;
}
void BattlegroundEY::FillInitialWorldStates(WorldPacket& data)
void BattlegroundEY::FillInitialWorldStates(WorldPackets::WorldState::InitWorldStates& packet)
{
data << uint32(EY_HORDE_BASE) << uint32(_ownedPointsCount[TEAM_HORDE]);
data << uint32(EY_ALLIANCE_BASE) << uint32(_ownedPointsCount[TEAM_ALLIANCE]);
data << uint32(DRAENEI_RUINS_HORDE_CONTROL) << uint32(_capturePointInfo[POINT_DRAENEI_RUINS].IsUnderControl(TEAM_HORDE));
data << uint32(DRAENEI_RUINS_ALLIANCE_CONTROL) << uint32(_capturePointInfo[POINT_DRAENEI_RUINS].IsUnderControl(TEAM_ALLIANCE));
data << uint32(DRAENEI_RUINS_UNCONTROL) << uint32(_capturePointInfo[POINT_DRAENEI_RUINS].IsUncontrolled());
data << uint32(MAGE_TOWER_ALLIANCE_CONTROL) << uint32(_capturePointInfo[POINT_MAGE_TOWER].IsUnderControl(TEAM_HORDE));
data << uint32(MAGE_TOWER_HORDE_CONTROL) << uint32(_capturePointInfo[POINT_MAGE_TOWER].IsUnderControl(TEAM_ALLIANCE));
data << uint32(MAGE_TOWER_UNCONTROL) << uint32(_capturePointInfo[POINT_MAGE_TOWER].IsUncontrolled());
data << uint32(FEL_REAVER_HORDE_CONTROL) << uint32(_capturePointInfo[POINT_FEL_REAVER].IsUnderControl(TEAM_HORDE));
data << uint32(FEL_REAVER_ALLIANCE_CONTROL) << uint32(_capturePointInfo[POINT_FEL_REAVER].IsUnderControl(TEAM_ALLIANCE));
data << uint32(FEL_REAVER_UNCONTROL) << uint32(_capturePointInfo[POINT_FEL_REAVER].IsUncontrolled());
data << uint32(BLOOD_ELF_HORDE_CONTROL) << uint32(_capturePointInfo[POINT_BLOOD_ELF].IsUnderControl(TEAM_HORDE));
data << uint32(BLOOD_ELF_ALLIANCE_CONTROL) << uint32(_capturePointInfo[POINT_BLOOD_ELF].IsUnderControl(TEAM_ALLIANCE));
data << uint32(BLOOD_ELF_UNCONTROL) << uint32(_capturePointInfo[POINT_BLOOD_ELF].IsUncontrolled());
data << uint32(NETHERSTORM_FLAG) << uint32(_flagState == BG_EY_FLAG_STATE_ON_BASE);
data << uint32(NETHERSTORM_FLAG_STATE_HORDE) << uint32(1);
data << uint32(NETHERSTORM_FLAG_STATE_ALLIANCE) << uint32(1);
data << uint32(EY_HORDE_RESOURCES) << uint32(GetTeamScore(TEAM_HORDE));
data << uint32(EY_ALLIANCE_RESOURCES) << uint32(GetTeamScore(TEAM_ALLIANCE));
data << uint32(PROGRESS_BAR_SHOW) << uint32(0);
data << uint32(PROGRESS_BAR_PERCENT_GREY) << uint32(0);
data << uint32(PROGRESS_BAR_STATUS) << uint32(0);
packet.Worldstates.reserve(22);
packet.Worldstates.emplace_back(EY_HORDE_BASE, _ownedPointsCount[TEAM_HORDE]);
packet.Worldstates.emplace_back(EY_ALLIANCE_BASE, _ownedPointsCount[TEAM_ALLIANCE]);
packet.Worldstates.emplace_back(DRAENEI_RUINS_HORDE_CONTROL, _capturePointInfo[POINT_DRAENEI_RUINS].IsUnderControl(TEAM_HORDE));
packet.Worldstates.emplace_back(DRAENEI_RUINS_ALLIANCE_CONTROL, _capturePointInfo[POINT_DRAENEI_RUINS].IsUnderControl(TEAM_ALLIANCE));
packet.Worldstates.emplace_back(DRAENEI_RUINS_UNCONTROL, _capturePointInfo[POINT_DRAENEI_RUINS].IsUncontrolled());
packet.Worldstates.emplace_back(MAGE_TOWER_ALLIANCE_CONTROL, _capturePointInfo[POINT_MAGE_TOWER].IsUnderControl(TEAM_HORDE));
packet.Worldstates.emplace_back(MAGE_TOWER_HORDE_CONTROL, _capturePointInfo[POINT_MAGE_TOWER].IsUnderControl(TEAM_ALLIANCE));
packet.Worldstates.emplace_back(MAGE_TOWER_UNCONTROL, _capturePointInfo[POINT_MAGE_TOWER].IsUncontrolled());
packet.Worldstates.emplace_back(FEL_REAVER_HORDE_CONTROL, _capturePointInfo[POINT_FEL_REAVER].IsUnderControl(TEAM_HORDE));
packet.Worldstates.emplace_back(FEL_REAVER_ALLIANCE_CONTROL, _capturePointInfo[POINT_FEL_REAVER].IsUnderControl(TEAM_ALLIANCE));
packet.Worldstates.emplace_back(FEL_REAVER_UNCONTROL, _capturePointInfo[POINT_FEL_REAVER].IsUncontrolled());
packet.Worldstates.emplace_back(BLOOD_ELF_HORDE_CONTROL, _capturePointInfo[POINT_BLOOD_ELF].IsUnderControl(TEAM_HORDE));
packet.Worldstates.emplace_back(BLOOD_ELF_ALLIANCE_CONTROL, _capturePointInfo[POINT_BLOOD_ELF].IsUnderControl(TEAM_ALLIANCE));
packet.Worldstates.emplace_back(BLOOD_ELF_UNCONTROL, _capturePointInfo[POINT_BLOOD_ELF].IsUncontrolled());
packet.Worldstates.emplace_back(NETHERSTORM_FLAG, _flagState == BG_EY_FLAG_STATE_ON_BASE);
packet.Worldstates.emplace_back(NETHERSTORM_FLAG_STATE_HORDE, 1);
packet.Worldstates.emplace_back(NETHERSTORM_FLAG_STATE_ALLIANCE, 1);
packet.Worldstates.emplace_back(EY_HORDE_RESOURCES, GetTeamScore(TEAM_HORDE));
packet.Worldstates.emplace_back(EY_ALLIANCE_RESOURCES, GetTeamScore(TEAM_ALLIANCE));
packet.Worldstates.emplace_back(PROGRESS_BAR_SHOW, 0);
packet.Worldstates.emplace_back(PROGRESS_BAR_PERCENT_GREY, 0);
packet.Worldstates.emplace_back(PROGRESS_BAR_STATUS, 0);
}
GraveyardStruct const* BattlegroundEY::GetClosestGraveyard(Player* player)
@@ -608,7 +610,7 @@ GraveyardStruct const* BattlegroundEY::GetClosestGraveyard(Player* player)
for (uint8 i = 0; i < EY_POINTS_MAX; ++i)
if (_capturePointInfo[i].IsUnderControl(player->GetTeamId()))
{
entry = sGraveyard->GetGraveyard(m_CapturingPointTypes[i].GraveYardId);
entry = sGraveyard->GetGraveyard(m_CapturingPointTypes[i].GraveyardId);
dist = (entry->x - pX) * (entry->x - pX) + (entry->y - pY) * (entry->y - pY) + (entry->z - pZ) * (entry->z - pZ);
if (dist < minDist)
{
@@ -305,11 +305,11 @@ struct BattlegroundEYLosingPointStruct
struct BattlegroundEYCapturingPointStruct
{
BattlegroundEYCapturingPointStruct(uint32 _DespawnNeutralObjectType, uint32 _SpawnObjectTypeAlliance, uint32 _MessageIdAlliance, uint32 _SpawnObjectTypeHorde, uint32 _MessageIdHorde, uint32 _GraveYardId)
BattlegroundEYCapturingPointStruct(uint32 _DespawnNeutralObjectType, uint32 _SpawnObjectTypeAlliance, uint32 _MessageIdAlliance, uint32 _SpawnObjectTypeHorde, uint32 _MessageIdHorde, uint32 _GraveyardId)
: DespawnNeutralObjectType(_DespawnNeutralObjectType),
SpawnObjectTypeAlliance(_SpawnObjectTypeAlliance), MessageIdAlliance(_MessageIdAlliance),
SpawnObjectTypeHorde(_SpawnObjectTypeHorde), MessageIdHorde(_MessageIdHorde),
GraveYardId(_GraveYardId)
GraveyardId(_GraveyardId)
{}
uint32 DespawnNeutralObjectType;
@@ -317,7 +317,7 @@ struct BattlegroundEYCapturingPointStruct
uint32 MessageIdAlliance;
uint32 SpawnObjectTypeHorde;
uint32 MessageIdHorde;
uint32 GraveYardId;
uint32 GraveyardId;
};
const uint32 BG_EY_TickPoints[EY_POINTS_MAX] = {1, 2, 5, 10};
@@ -421,7 +421,7 @@ public:
void Init() override;
void EndBattleground(TeamId winnerTeamId) override;
bool UpdatePlayerScore(Player* player, uint32 type, uint32 value, bool doAddHonor = true) override;
void FillInitialWorldStates(WorldPacket& data) override;
void FillInitialWorldStates(WorldPackets::WorldState::InitWorldStates& packet) override;
void SetDroppedFlagGUID(ObjectGuid guid, TeamId /*teamId*/ = TEAM_NEUTRAL) override { _droppedFlagGUID = guid; }
ObjectGuid GetDroppedFlagGUID() const { return _droppedFlagGUID; }
@@ -26,6 +26,7 @@
#include "Transport.h"
#include "Vehicle.h"
#include "WorldPacket.h"
#include "WorldStatePackets.h"
void BattlegroundICScore::BuildObjectivesBlock(WorldPacket& data)
{
@@ -381,21 +382,24 @@ bool BattlegroundIC::UpdatePlayerScore(Player* player, uint32 type, uint32 value
return true;
}
void BattlegroundIC::FillInitialWorldStates(WorldPacket& data)
void BattlegroundIC::FillInitialWorldStates(WorldPackets::WorldState::InitWorldStates& packet)
{
data << uint32(BG_IC_ALLIANCE_RENFORT_SET) << uint32(1);
data << uint32(BG_IC_HORDE_RENFORT_SET) << uint32(1);
data << uint32(BG_IC_ALLIANCE_RENFORT) << uint32(factionReinforcements[TEAM_ALLIANCE]);
data << uint32(BG_IC_HORDE_RENFORT) << uint32(factionReinforcements[TEAM_HORDE]);
packet.Worldstates.reserve(4+MAX_FORTRESS_GATES_SPAWNS+MAX_NODE_TYPES+1);
packet.Worldstates.emplace_back(BG_IC_ALLIANCE_RENFORT_SET, 1);
packet.Worldstates.emplace_back(BG_IC_HORDE_RENFORT_SET, 1);
packet.Worldstates.emplace_back(BG_IC_ALLIANCE_RENFORT, factionReinforcements[TEAM_ALLIANCE]);
packet.Worldstates.emplace_back(BG_IC_HORDE_RENFORT, factionReinforcements[TEAM_HORDE]);
for (uint8 i = 0; i < MAX_FORTRESS_GATES_SPAWNS; ++i)
{
uint32 uws = GetWorldStateFromGateEntry(BG_IC_ObjSpawnlocs[i].entry, (GateStatus[GetGateIDFromEntry(BG_IC_ObjSpawnlocs[i].entry)] == BG_IC_GATE_DESTROYED));
data << uint32(uws) << uint32(1);
packet.Worldstates.emplace_back(uws, 1);
}
for (uint8 i = 0; i < MAX_NODE_TYPES; ++i)
data << uint32(nodePoint[i].worldStates[nodePoint[i].nodeState]) << uint32(1);
packet.Worldstates.emplace_back(nodePoint[i].worldStates[nodePoint[i].nodeState], 1);
packet.Worldstates.emplace_back(BG_IC_HORDE_RENFORT_SET, 1);
}
bool BattlegroundIC::SetupBattleground()
@@ -974,7 +974,7 @@ public:
/* Scorekeeping */
bool UpdatePlayerScore(Player* player, uint32 type, uint32 value, bool doAddHonor = true) override;
void FillInitialWorldStates(WorldPacket& data) override;
void FillInitialWorldStates(WorldPackets::WorldState::InitWorldStates& packet) override;
void HandlePlayerResurrect(Player* player) override;
@@ -64,10 +64,10 @@ void BattlegroundNA::HandleAreaTrigger(Player* player, uint32 trigger)
}
}
void BattlegroundNA::FillInitialWorldStates(WorldPacket& data)
void BattlegroundNA::FillInitialWorldStates(WorldPackets::WorldState::InitWorldStates& packet)
{
data << uint32(0xa11) << uint32(1); // 9
Arena::FillInitialWorldStates(data);
packet.Worldstates.emplace_back(0xa11, 1); // BATTLEGROUND_NAGRAND_ARENA_SHOW
Arena::FillInitialWorldStates(packet);
}
bool BattlegroundNA::SetupBattleground()
@@ -54,7 +54,8 @@ public:
void HandleAreaTrigger(Player* player, uint32 trigger) override;
bool SetupBattleground() override;
void FillInitialWorldStates(WorldPacket& d) override;
void FillInitialWorldStates(WorldPackets::WorldState::InitWorldStates& packet) override;
bool HandlePlayerUnderMap(Player* player) override;
};
@@ -91,10 +91,10 @@ void BattlegroundRL::HandleAreaTrigger(Player* player, uint32 trigger)
}
}
void BattlegroundRL::FillInitialWorldStates(WorldPacket& data)
void BattlegroundRL::FillInitialWorldStates(WorldPackets::WorldState::InitWorldStates& packet)
{
data << uint32(0xbba) << uint32(1); // 9
Arena::FillInitialWorldStates(data);
packet.Worldstates.emplace_back(0xbba, 1); // BATTELGROUND_RUINS_OF_LORDAERNON_SHOW
Arena::FillInitialWorldStates(packet);
}
bool BattlegroundRL::SetupBattleground()
@@ -45,7 +45,7 @@ public:
BattlegroundRL();
/* inherited from BattlegroundClass */
void FillInitialWorldStates(WorldPacket& d) override;
void FillInitialWorldStates(WorldPackets::WorldState::InitWorldStates& packet) override;
void StartingEventCloseDoors() override;
void StartingEventOpenDoors() override;
@@ -204,10 +204,10 @@ void BattlegroundRV::HandleAreaTrigger(Player* player, uint32 trigger)
}
}
void BattlegroundRV::FillInitialWorldStates(WorldPacket& data)
void BattlegroundRV::FillInitialWorldStates(WorldPackets::WorldState::InitWorldStates& packet)
{
data << uint32(BG_RV_WORLD_STATE) << uint32(1);
Arena::FillInitialWorldStates(data);
packet.Worldstates.emplace_back(BG_RV_WORLD_STATE, 1);
Arena::FillInitialWorldStates(packet);
}
void BattlegroundRV::Init()
@@ -90,7 +90,7 @@ public:
/* inherited from BattlegroundClass */
void StartingEventOpenDoors() override;
void Init() override;
void FillInitialWorldStates(WorldPacket& d) override;
void FillInitialWorldStates(WorldPackets::WorldState::InitWorldStates& packet) override;
void HandleAreaTrigger(Player* player, uint32 trigger) override;
bool SetupBattleground() override;
bool HandlePlayerUnderMap(Player* player) override;
@@ -467,44 +467,46 @@ void BattlegroundSA::StartingEventOpenDoors()
{
}
void BattlegroundSA::FillInitialWorldStates(WorldPacket& data)
void BattlegroundSA::FillInitialWorldStates(WorldPackets::WorldState::InitWorldStates& packet)
{
uint32 ally_attacks = uint32(Attackers == TEAM_ALLIANCE ? 1 : 0);
uint32 horde_attacks = uint32(Attackers == TEAM_HORDE ? 1 : 0);
bool const ally_attacks = Attackers == TEAM_ALLIANCE;
bool const horde_attacks = Attackers == TEAM_HORDE;
data << uint32(BG_SA_ANCIENT_GATEWS) << uint32(GateStatus[BG_SA_ANCIENT_GATE]);
data << uint32(BG_SA_YELLOW_GATEWS) << uint32(GateStatus[BG_SA_YELLOW_GATE]);
data << uint32(BG_SA_GREEN_GATEWS) << uint32(GateStatus[BG_SA_GREEN_GATE]);
data << uint32(BG_SA_BLUE_GATEWS) << uint32(GateStatus[BG_SA_BLUE_GATE]);
data << uint32(BG_SA_RED_GATEWS) << uint32(GateStatus[BG_SA_RED_GATE]);
data << uint32(BG_SA_PURPLE_GATEWS) << uint32(GateStatus[BG_SA_PURPLE_GATE]);
packet.Worldstates.reserve(25);
packet.Worldstates.emplace_back(BG_SA_ANCIENT_GATEWS, GateStatus[BG_SA_ANCIENT_GATE]);
packet.Worldstates.emplace_back(BG_SA_YELLOW_GATEWS, GateStatus[BG_SA_YELLOW_GATE]);
packet.Worldstates.emplace_back(BG_SA_GREEN_GATEWS, GateStatus[BG_SA_GREEN_GATE]);
packet.Worldstates.emplace_back(BG_SA_BLUE_GATEWS, GateStatus[BG_SA_BLUE_GATE]);
packet.Worldstates.emplace_back(BG_SA_RED_GATEWS, GateStatus[BG_SA_RED_GATE]);
packet.Worldstates.emplace_back(BG_SA_PURPLE_GATEWS, GateStatus[BG_SA_PURPLE_GATE]);
data << uint32(BG_SA_BONUS_TIMER) << uint32(0);
packet.Worldstates.emplace_back(BG_SA_BONUS_TIMER, 0);
data << uint32(BG_SA_HORDE_ATTACKS) << horde_attacks;
data << uint32(BG_SA_ALLY_ATTACKS) << ally_attacks;
packet.Worldstates.emplace_back(BG_SA_HORDE_ATTACKS, horde_attacks);
packet.Worldstates.emplace_back(BG_SA_ALLY_ATTACKS, ally_attacks);
//Time will be sent on first update...
data << uint32(BG_SA_ENABLE_TIMER) << ((TimerEnabled) ? uint32(1) : uint32(0));
data << uint32(BG_SA_TIMER_MINS) << uint32(0);
data << uint32(BG_SA_TIMER_SEC_TENS) << uint32(0);
data << uint32(BG_SA_TIMER_SEC_DECS) << uint32(0);
packet.Worldstates.emplace_back(BG_SA_ENABLE_TIMER, TimerEnabled ? 1 : 0);
data << uint32(BG_SA_RIGHT_GY_HORDE) << uint32(GraveyardStatus[BG_SA_RIGHT_CAPTURABLE_GY] == TEAM_HORDE ? 1 : 0);
data << uint32(BG_SA_LEFT_GY_HORDE) << uint32(GraveyardStatus[BG_SA_LEFT_CAPTURABLE_GY] == TEAM_HORDE ? 1 : 0);
data << uint32(BG_SA_CENTER_GY_HORDE) << uint32(GraveyardStatus[BG_SA_CENTRAL_CAPTURABLE_GY] == TEAM_HORDE ? 1 : 0);
packet.Worldstates.emplace_back(BG_SA_TIMER_MINS, 0);
packet.Worldstates.emplace_back(BG_SA_TIMER_SEC_TENS, 0);
packet.Worldstates.emplace_back(BG_SA_TIMER_SEC_DECS, 0);
data << uint32(BG_SA_RIGHT_GY_ALLIANCE) << uint32(GraveyardStatus[BG_SA_RIGHT_CAPTURABLE_GY] == TEAM_ALLIANCE ? 1 : 0);
data << uint32(BG_SA_LEFT_GY_ALLIANCE) << uint32(GraveyardStatus[BG_SA_LEFT_CAPTURABLE_GY] == TEAM_ALLIANCE ? 1 : 0);
data << uint32(BG_SA_CENTER_GY_ALLIANCE) << uint32(GraveyardStatus[BG_SA_CENTRAL_CAPTURABLE_GY] == TEAM_ALLIANCE ? 1 : 0);
packet.Worldstates.emplace_back(BG_SA_RIGHT_GY_HORDE, GraveyardStatus[BG_SA_RIGHT_CAPTURABLE_GY] == TEAM_HORDE ? 1 : 0);
packet.Worldstates.emplace_back(BG_SA_LEFT_GY_HORDE, GraveyardStatus[BG_SA_LEFT_CAPTURABLE_GY] == TEAM_HORDE ? 1 : 0);
packet.Worldstates.emplace_back(BG_SA_CENTER_GY_HORDE, GraveyardStatus[BG_SA_CENTRAL_CAPTURABLE_GY] == TEAM_HORDE ? 1 : 0);
data << uint32(BG_SA_HORDE_DEFENCE_TOKEN) << ally_attacks;
data << uint32(BG_SA_ALLIANCE_DEFENCE_TOKEN) << horde_attacks;
packet.Worldstates.emplace_back(BG_SA_RIGHT_GY_ALLIANCE, GraveyardStatus[BG_SA_RIGHT_CAPTURABLE_GY] == TEAM_ALLIANCE ? 1 : 0);
packet.Worldstates.emplace_back(BG_SA_LEFT_GY_ALLIANCE, GraveyardStatus[BG_SA_LEFT_CAPTURABLE_GY] == TEAM_ALLIANCE ? 1 : 0);
packet.Worldstates.emplace_back(BG_SA_CENTER_GY_ALLIANCE, GraveyardStatus[BG_SA_CENTRAL_CAPTURABLE_GY] == TEAM_ALLIANCE ? 1 : 0);
data << uint32(BG_SA_LEFT_ATT_TOKEN_HRD) << horde_attacks;
data << uint32(BG_SA_RIGHT_ATT_TOKEN_HRD) << horde_attacks;
data << uint32(BG_SA_RIGHT_ATT_TOKEN_ALL) << ally_attacks;
data << uint32(BG_SA_LEFT_ATT_TOKEN_ALL) << ally_attacks;
packet.Worldstates.emplace_back(BG_SA_HORDE_DEFENCE_TOKEN, ally_attacks);
packet.Worldstates.emplace_back(BG_SA_ALLIANCE_DEFENCE_TOKEN, horde_attacks);
packet.Worldstates.emplace_back(BG_SA_LEFT_ATT_TOKEN_HRD, horde_attacks);
packet.Worldstates.emplace_back(BG_SA_RIGHT_ATT_TOKEN_HRD, horde_attacks);
packet.Worldstates.emplace_back(BG_SA_RIGHT_ATT_TOKEN_ALL, ally_attacks);
packet.Worldstates.emplace_back(BG_SA_LEFT_ATT_TOKEN_ALL, ally_attacks);
}
void BattlegroundSA::AddPlayer(Player* player)
@@ -475,7 +475,7 @@ public:
bool SetupBattleground() override;
void Init() override;
/// Called for generate packet contain worldstate data
void FillInitialWorldStates(WorldPacket& data) override;
void FillInitialWorldStates(WorldPackets::WorldState::InitWorldStates& packet) override;
/// Called when a player deal damage to building (door)
void EventPlayerDamagedGO(Player* player, GameObject* go, uint32 eventType) override;
/// Called when a player kill a unit in bg
@@ -546,17 +546,18 @@ GraveyardStruct const* BattlegroundWS::GetClosestGraveyard(Player* player)
return sGraveyard->GetGraveyard(player->GetTeamId() == TEAM_ALLIANCE ? WS_GRAVEYARD_FLAGROOM_ALLIANCE : WS_GRAVEYARD_FLAGROOM_HORDE);
}
void BattlegroundWS::FillInitialWorldStates(WorldPacket& data)
void BattlegroundWS::FillInitialWorldStates(WorldPackets::WorldState::InitWorldStates& packet)
{
data << uint32(BG_WS_FLAG_CAPTURES_ALLIANCE) << uint32(GetTeamScore(TEAM_ALLIANCE));
data << uint32(BG_WS_FLAG_CAPTURES_HORDE) << uint32(GetTeamScore(TEAM_HORDE));
data << uint32(BG_WS_FLAG_CAPTURES_MAX) << uint32(BG_WS_MAX_TEAM_SCORE);
packet.Worldstates.reserve(7);
packet.Worldstates.emplace_back(BG_WS_FLAG_CAPTURES_ALLIANCE, GetTeamScore(TEAM_ALLIANCE));
packet.Worldstates.emplace_back(BG_WS_FLAG_CAPTURES_HORDE, GetTeamScore(TEAM_HORDE));
packet.Worldstates.emplace_back(BG_WS_FLAG_CAPTURES_MAX, BG_WS_MAX_TEAM_SCORE);
data << uint32(BG_WS_STATE_TIMER_ACTIVE) << uint32(GetStatus() == STATUS_IN_PROGRESS);
data << uint32(BG_WS_STATE_TIMER) << uint32(GetMatchTime());
packet.Worldstates.emplace_back(BG_WS_STATE_TIMER_ACTIVE, GetStatus() == STATUS_IN_PROGRESS ? 1 : 0);
packet.Worldstates.emplace_back(BG_WS_STATE_TIMER, GetMatchTime());
data << uint32(BG_WS_FLAG_STATE_HORDE) << uint32(GetFlagState(TEAM_HORDE));
data << uint32(BG_WS_FLAG_STATE_ALLIANCE) << uint32(GetFlagState(TEAM_ALLIANCE));
packet.Worldstates.emplace_back(BG_WS_FLAG_STATE_HORDE, GetFlagState(TEAM_HORDE));
packet.Worldstates.emplace_back(BG_WS_FLAG_STATE_ALLIANCE, GetFlagState(TEAM_ALLIANCE));
}
TeamId BattlegroundWS::GetPrematureWinner()
@@ -252,7 +252,7 @@ public:
bool UpdatePlayerScore(Player* player, uint32 type, uint32 value, bool doAddHonor = true) override;
void SetDroppedFlagGUID(ObjectGuid guid, TeamId teamId) override { _droppedFlagGUID[teamId] = guid; }
ObjectGuid GetDroppedFlagGUID(TeamId teamId) const { return _droppedFlagGUID[teamId];}
void FillInitialWorldStates(WorldPacket& data) override;
void FillInitialWorldStates(WorldPackets::WorldState::InitWorldStates& packet) override;
/* Scorekeeping */
void AddPoints(TeamId teamId, uint32 points) { m_TeamScores[teamId] += points; }