Jameyboor
Retired Staff
Good day everyone,
I realized that I did not release anything recently, that's why I made this arena stats viewer.
The npc can show :
the arena stats of a specific player.
the arena stats of a specific team.
the top 10 arena stats per arena type.
there are even some booleans that you can set to your preferences :
INFO_VIA_GOSSIP:
if set to true, the info will be displayed in a gossip menu ( like in the screenshots ), if set to false, it will be displayed through the whispering of the npc.
USE_QUERIES:
if set to true, the script is allowed to use SQL queries to make the script more functional, if you have some kind of crappy VPS this could lead to a bit lag, that's why I made an option to turn it off ( set to false ), if set to false, some function will not work anymore, like checking the arena stats of a player that is offline, the npc will then just notify that the player is offline instead of showing the stats.
I've tested some options and they all seem to work, but as always, please report any bugs you might encounter when using this npc, here is the code:
some screens of it in action :
IM OUT /tableflip
I realized that I did not release anything recently, that's why I made this arena stats viewer.
The npc can show :
the arena stats of a specific player.
the arena stats of a specific team.
the top 10 arena stats per arena type.
there are even some booleans that you can set to your preferences :
Code:
const bool INFO_VIA_GOSSIP = true;
const bool USE_QUERIES = true;
if set to true, the info will be displayed in a gossip menu ( like in the screenshots ), if set to false, it will be displayed through the whispering of the npc.
USE_QUERIES:
if set to true, the script is allowed to use SQL queries to make the script more functional, if you have some kind of crappy VPS this could lead to a bit lag, that's why I made an option to turn it off ( set to false ), if set to false, some function will not work anymore, like checking the arena stats of a player that is offline, the npc will then just notify that the player is offline instead of showing the stats.
I've tested some options and they all seem to work, but as always, please report any bugs you might encounter when using this npc, here is the code:
Code:
/*
*╔═╦═╦═╦╦╦══╦═╦╗─╔╦══╗
*║╦╣║║║║║╠╗╗║╦╣╚╦╝║══╣
*║╩╣║║║║║╠╩╝║╩╬╗║╔╬══║
*╚═╩╩═╩╩═╩══╩═╝╚═╝╚══╝
* (http://emudevs.com)
*/
#include "ScriptPCH.h"
#include "ArenaTeamMgr.h"
#include "ArenaTeam.h"
#pragma warning(disable:4018)
const bool INFO_VIA_GOSSIP = true;
const bool USE_QUERIES = true;
typedef std::vector<ArenaTeam*> RankingContainer;
bool order(ArenaTeam* &a, ArenaTeam* &b)
{
return a->GetStats().Rating > b->GetStats().Rating;
}
std::string GetTypeAsString(uint32 type)
{
if(type == 2)
return "2v2";
else if(type == 3)
return "3v3";
return "5v5";
}
void SendTeamInfo(Player* player, Creature* creature, const char* code)
{
ArenaTeam* team = sArenaTeamMgr->GetArenaTeamByName(code);
if(!team)
{
player->GetSession()->SendNotification("That team does not exist");
player->PlayerTalkClass->SendCloseGossip();
return;
}
std::ostringstream info;
info << "Team " << team->GetName() << ", type : " << GetTypeAsString(team->GetType()) << ", arena info : \n";
INFO_VIA_GOSSIP ? player->ADD_GOSSIP_ITEM(GOSSIP_ICON_BATTLE, info.str().c_str(), GOSSIP_SENDER_MAIN, 0) : creature->MonsterWhisper(info.str().c_str(), player->GetGUID());
info.str("");
info.clear();
uint32 rank = team->GetStats().Rank;
uint32 rating = team->GetStats().Rating;
uint32 weekGames = team->GetStats().WeekGames;
uint32 weekWins = team->GetStats().WeekWins;
uint32 weekLosses = weekGames - weekWins;
uint32 seasonGames = team->GetStats().SeasonGames;
uint32 seasonWins = team->GetStats().SeasonWins;
uint32 seasonLosses = seasonGames - seasonWins;
Player* captain = ObjectAccessor::FindPlayer(team->GetCaptain());
std::string captainName;
bool captainValid;
if(!captain || !captain->GetSession())
{
if(USE_QUERIES)
{
QueryResult result = CharacterDatabase.PQuery("SELECT `name` FROM `characters` WHERE `guid` = %u", team->GetCaptain());
if(result)
{
Field* fields = result->Fetch();
captainName = fields[0].GetString();
captainValid = true;
}
}
else
captainValid = false;
}
else
{
captainName = captain->GetName();
captainValid = true;
}
info << "Rank : " << (uint16)rank;
if(captainValid) info << "\nCaptain Name : " << captainName;
info << "\nRating : " << (uint32)rating
<< "\nMembers : ";
for(ArenaTeam::MemberList::iterator itr = team->m_membersBegin(); itr != team->m_membersEnd(); ++itr)
{
info << itr->Name;
if(std::distance(team->m_membersBegin(), itr) < team->GetType() -1 )
info << ", ";
}
info << "\nWeek Games : "
<< (uint32)weekGames << ", Wins : " << (uint32)weekWins << ", Losses : " << (uint32)weekLosses
<< "\nSeason Games : "
<< (uint32)seasonGames << ", Wins : " << (uint32)seasonWins << ", Losses : " << (uint32)seasonLosses;
INFO_VIA_GOSSIP ? player->ADD_GOSSIP_ITEM(0, info.str().c_str(), GOSSIP_SENDER_MAIN, 0) : creature->MonsterWhisper(info.str().c_str(), player->GetGUID());
if(INFO_VIA_GOSSIP)
player->SEND_GOSSIP_MENU(907, creature->GetGUID());
}
void SendSoloInfo(Player* player, Creature* creature, uint32 teamId, uint64 target, uint32 type)
{
std::ostringstream info;
info << "Player : " << player->GetName() << ", type : " << GetTypeAsString(type) << ", arena info : \n";
INFO_VIA_GOSSIP ? player->ADD_GOSSIP_ITEM(GOSSIP_ICON_BATTLE, info.str().c_str(), GOSSIP_SENDER_MAIN, 0) : creature->MonsterWhisper(info.str().c_str(), player->GetGUID());
info.str("");
info.clear();
ArenaTeam* team = sArenaTeamMgr->GetArenaTeamById(teamId);
info << "Player stats : \n";
for(ArenaTeam::MemberList::iterator itr = team->m_membersBegin(); itr != team->m_membersEnd(); ++itr)
{
if(target == itr->Guid)
{
std::ostringstream ss;
std::string name = itr->Name;
std::string teamName = team->GetName();
uint32 MMR = itr->MatchMakerRating;
uint32 personalRating = itr->PersonalRating;
uint32 seasonGames = itr->SeasonGames;
uint32 seasonWins = itr->SeasonWins;
uint32 seasonLosses = seasonGames - seasonWins;
uint32 weekGames = itr->WeekGames;
uint32 weekWins = itr->WeekWins;
uint32 weekLosses = weekGames - weekWins;
ss << "Name : " << name << "\nTeam Name : " << teamName << "\nMatchMaker Rating : " << (uint32)MMR << "\nPersonal Rating : "
<< (uint32)personalRating << "\nSeason Games : " << (uint32)seasonGames
<< "\nSeason Wins : " << (uint32)seasonWins << "\nSeason Losses : " << (uint32)seasonLosses << "\nWeek Games : "
<< (uint32)weekGames << "\nWeek Wins : " << (uint32)weekWins
<< "\nWeek Losses : " << (uint32)weekLosses << "\n\n";
INFO_VIA_GOSSIP ? player->ADD_GOSSIP_ITEM(GOSSIP_ICON_BATTLE, ss.str().c_str(), GOSSIP_SENDER_MAIN, 0) : creature->MonsterWhisper(ss.str().c_str(), player->GetGUID());
}
}
if(INFO_VIA_GOSSIP)
player->SEND_GOSSIP_MENU(907, creature->GetGUID());
}
void SendTopInfo(Player* player, Creature* creature, RankingContainer RankingHolder, uint32 type)
{
std::ostringstream info;
info << "Top 10 " << GetTypeAsString(type) << " arena teams: \n\n";
INFO_VIA_GOSSIP ? player->ADD_GOSSIP_ITEM(0, info.str().c_str(), GOSSIP_SENDER_MAIN, 0) : creature->MonsterWhisper(info.str().c_str(), player->GetGUID());
uint16 rank = 1;
for(RankingContainer::iterator itr = RankingHolder.begin(); itr != RankingHolder.end(); ++itr)
{
if(rank > 10)
break;
std::ostringstream ss;
std::string teamName = (*itr)->GetName();
Player* captain = ObjectAccessor::FindPlayer((*itr)->GetCaptain());
std::string captainName;
bool captainValid;
if(!captain || !captain->GetSession())
{
if(USE_QUERIES)
{
QueryResult result = CharacterDatabase.PQuery("SELECT `name` FROM `characters` WHERE `guid` = %u", (*itr)->GetCaptain());
if(result)
{
Field* fields = result->Fetch();
captainName = fields[0].GetString();
captainValid = true;
}
}
else
captainValid = false;
}
else
{
captainName = captain->GetName();
captainValid = true;
}
uint32 rating = (*itr)->GetRating();
uint32 seasonGames = (*itr)->GetStats().SeasonGames;
uint32 seasonWins = (*itr)->GetStats().SeasonWins;
uint32 seasonLosses = seasonGames - seasonWins;
ss << "Rank : " << (uint16)rank << "\nTeam Name : " << teamName;
if(captainValid) ss << "\nCaptain Name : " << captainName;
ss << "\nRating : " << (uint32)rating
<< "\nMembers : ";
for(ArenaTeam::MemberList::iterator it = (*itr)->m_membersBegin(); it != (*itr)->m_membersEnd(); ++it)
{
ss << it->Name;
if(std::distance((*itr)->m_membersBegin(), it) < type -1 )
ss << ", ";
}
ss << "\nSeason Games : "
<< (uint32)seasonGames << ", Wins : " << (uint32)seasonWins << ", Losses : " << (uint32)seasonLosses;
INFO_VIA_GOSSIP ? player->ADD_GOSSIP_ITEM(0, ss.str().c_str(), GOSSIP_SENDER_MAIN, 0) : creature->MonsterWhisper(ss.str().c_str(), player->GetGUID());
++rank;
}
if(rank < 11)
{
--rank;
std::ostringstream ss;
ss << (uint16)rank << " team(s) displayed, no more available";
INFO_VIA_GOSSIP ? player->ADD_GOSSIP_ITEM(0, ss.str().c_str(), GOSSIP_SENDER_MAIN, 0) : creature->MonsterWhisper(ss.str().c_str(), player->GetGUID());
}
if(INFO_VIA_GOSSIP)
player->SEND_GOSSIP_MENU(907, creature->GetGUID());
}
void FillAndSortHolder(uint32 type, RankingContainer& RankingHolder)
{
for(ArenaTeamMgr::ArenaTeamContainer::iterator itr = sArenaTeamMgr->GetArenaTeamMapBegin(); itr != sArenaTeamMgr->GetArenaTeamMapEnd(); ++itr)
{
if(itr->second->GetType() != type)
continue;
RankingHolder.push_back(itr->second);
}
std::sort(RankingHolder.begin(), RankingHolder.end(), order);
}
uint32 GetTeamByDb(uint64 GUID, uint32 type)
{
QueryResult result = CharacterDatabase.PQuery("SELECT `arenaTeamId` FROM `arena_team_member` WHERE `guid` = %u", GUID);
if(!result)
return NULL;
std::vector<ArenaTeam*> teamIds;
do{
Field* fields = result->Fetch();
teamIds.push_back(sArenaTeamMgr->GetArenaTeamById(fields[0].GetUInt32()));
}while(result->NextRow());
for(RankingContainer::iterator itr = teamIds.begin(); itr != teamIds.end(); ++itr)
{
if((*itr)->GetType() == type)
return (*itr)->GetId();
}
return NULL;
}
uint32 GetGuidByDb(const char* name)
{
QueryResult check = CharacterDatabase.PQuery("SELECT `guid` FROM `characters` WHERE `name` = '%s'", name);
if(!check)
return NULL;
Field* fields = check->Fetch();
return fields[0].GetUInt64();
}
uint32 GetArenaTeamId(uint64 Guid, uint32 type)
{
Player* player = ObjectAccessor::FindPlayer(Guid);
if(!player || !player->GetSession())
{
if(USE_QUERIES)
return GetTeamByDb(Guid, type);
return NULL;
}
return player->GetArenaTeamId(ArenaTeam::GetSlotByType(type));
}
bool IsEmptyBracket(uint32 type)
{
for(ArenaTeamMgr::ArenaTeamContainer::iterator itr = sArenaTeamMgr->GetArenaTeamMapBegin(); itr != sArenaTeamMgr->GetArenaTeamMapEnd(); ++itr)
{
if(itr->second->GetType() == type)
return false;
}
return true;
}
void SendOptions(Player* player, Creature* creature, const char* code)
{
uint64 Guid;
Player* target = ObjectAccessor::FindPlayerByName(code);
if(!target || !target->GetSession())
{
if(USE_QUERIES)
Guid = GetGuidByDb(code);
else
{
player->GetSession()->SendNotification("Player does not exist or is offline");
player->PlayerTalkClass->SendCloseGossip();
return;
}
}
else
Guid = target->GetGUID();
if(!Guid)
{
player->GetSession()->SendNotification("Player does not exist");
player->PlayerTalkClass->SendCloseGossip();
return;
}
if(!GetArenaTeamId(Guid, 2) && !GetArenaTeamId(Guid, 3) && !GetArenaTeamId(Guid, 5))
{
player->GetSession()->SendNotification("Player is not in any arena team");
player->PlayerTalkClass->SendCloseGossip();
return;
}
for(int i = 2; i < 6; ++i)
{
if(i == 4)
continue;
uint16 action = (i != 5 ? i*2-(i == 3 ? 1 : 0) : i+1);
if(GetArenaTeamId(Guid, i))
player->ADD_GOSSIP_ITEM(GOSSIP_ICON_BATTLE, GetTypeAsString(i), Guid, action);
}
player->SEND_GOSSIP_MENU(907, creature->GetGUID());
}
class Top_Arena_View_NPC : public CreatureScript
{
public:
Top_Arena_View_NPC() : CreatureScript("Arena_NPC") {}
bool OnGossipHello(Player* player, Creature* creature)
{
player->ADD_GOSSIP_ITEM_EXTENDED(0, "Show arena stats of a specific player", GOSSIP_SENDER_MAIN, 1, "Enter the name of the player please", 0, true);
player->ADD_GOSSIP_ITEM(0, "Show the top 10 arena stats", GOSSIP_SENDER_MAIN, 2);
player->ADD_GOSSIP_ITEM_EXTENDED(0, "Show arena stats of a specific team", GOSSIP_SENDER_MAIN, 3, "Enter the name of the team please", 0, true);
player->SEND_GOSSIP_MENU(907, creature->GetGUID());
return true;
}
bool OnGossipSelectCode(Player* player, Creature* creature, uint32 sender, uint32 action, const char* code)
{
player->PlayerTalkClass->ClearMenus();
switch(action)
{
case 1:
SendOptions(player, creature, code);
return true;
break;
case 3:
SendTeamInfo(player, creature, code);
return true;
}
return true;
}
bool OnGossipSelect(Player* player, Creature* creature, uint32 sender, uint32 action)
{
player->PlayerTalkClass->ClearMenus();
switch(action)
{
case 2:
player->ADD_GOSSIP_ITEM(GOSSIP_ICON_BATTLE, "2v2", GOSSIP_SENDER_MAIN, 7);
player->ADD_GOSSIP_ITEM(GOSSIP_ICON_BATTLE, "3v3", GOSSIP_SENDER_MAIN, 8);
player->ADD_GOSSIP_ITEM(GOSSIP_ICON_BATTLE, "5v5", GOSSIP_SENDER_MAIN, 9);
player->SEND_GOSSIP_MENU(907, creature->GetGUID());
break;
//GetArenaTeamId can't return NULL, already checked in SendOptions, NULL returns will not be displayed in the gossip menu, just send the info.
case 4:
SendSoloInfo(player, creature, GetArenaTeamId(sender, 2), sender, 2);
break;
case 5:
SendSoloInfo(player, creature, GetArenaTeamId(sender, 3), sender, 3);
break;
case 6:
SendSoloInfo(player, creature, GetArenaTeamId(sender, 5), sender, 5);
break;
case 7:
{
if(IsEmptyBracket(2))
{
player->GetSession()->SendNotification("No teams available");
player->PlayerTalkClass->SendCloseGossip();
return false;
}
RankingContainer Rankingholder;
FillAndSortHolder(2, Rankingholder); //2v2
SendTopInfo(player, creature, Rankingholder, 2);
}break;
case 8:
{
if(IsEmptyBracket(3))
{
player->GetSession()->SendNotification("No teams available");
player->PlayerTalkClass->SendCloseGossip();
return false;
}
RankingContainer Rankingholder;
FillAndSortHolder(3, Rankingholder); //3v3
SendTopInfo(player, creature, Rankingholder, 3);
}break;
case 9:
{
if(IsEmptyBracket(5))
{
player->GetSession()->SendNotification("No teams available");
player->PlayerTalkClass->SendCloseGossip();
return false;
}
RankingContainer Rankingholder;
FillAndSortHolder(5, Rankingholder); //5v5
SendTopInfo(player, creature, Rankingholder, 5);
}break;
}
return true;
}
};
void AddSC_Arena_NPC()
{
new Top_Arena_View_NPC();
}
some screens of it in action :
IM OUT /tableflip
Last edited: