1. /*
  2. * Copyright (C) 2008-2012 TrinityCore <http://www.trinitycore.org/>
  3. * Copyright (C) 2006-2009 ScriptDev2 <https://scriptdev2.svn.sourceforge.net/>
  4. *
  5. * This program is free software; you can redistribute it and/or modify it
  6. * under the terms of the GNU General Public License as published by the
  7. * Free Software Foundation; either version 2 of the License, or (at your
  8. * option) any later version.
  9. *
  10. * This program is distributed in the hope that it will be useful, but WITHOUT
  11. * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
  12. * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
  13. * more details.
  14. *
  15. * You should have received a copy of the GNU General Public License along
  16. * with this program. If not, see <http://www.gnu.org/licenses/>.
  17. */
  18. /* ScriptData
  19. Name: Arena Spectator
  20. %Complete: 100
  21. Comment: Script allow spectate arena games
  22. Category: Custom Script
  23. EndScriptData */
  24. #include "Chat.h"
  25. #include "ArenaTeamMgr.h"
  26. #include "BattlegroundMgr.h"
  27. #include "WorldSession.h"
  28. #include "Player.h"
  29. #include "ArenaTeam.h"
  30. #include "Battleground.h"
  31. #include "BattlegroundMgr.h"
  32. #include "CreatureTextMgr.h"
  33. #include "Config.h"
  34. #define sArenaTeamMgr ArenaTeamMgr::instance()
  35. int8 UsingGossip;
  36. class arena_spectator_commands : public CommandScript
  37. {
  38. public:
  39. arena_spectator_commands() : CommandScript("arena_spectator_commands") { }
  40. static bool HandleSpectateCommand(ChatHandler* handler, char const* args)
  41. {
  42. Player* target;
  43. ObjectGuid target_guid;
  44. std::string target_name;
  45. if (!handler->extractPlayerTarget((char*)args, &target, &target_guid, &target_name))
  46. return false;
  47. Player* player = handler->GetSession()->GetPlayer();
  48. if (target == player || target_guid == player->GetGUID())
  49. {
  50. handler->PSendSysMessage("You can't spectate yourself.");
  51. handler->SetSentErrorMessage(true);
  52. return false;
  53. }
  54. if (player->IsInCombat())
  55. {
  56. handler->PSendSysMessage("You are in combat.");
  57. handler->SetSentErrorMessage(true);
  58. return false;
  59. }
  60. if (!target)
  61. {
  62. handler->PSendSysMessage("Target is not online or does not exist.");
  63. handler->SetSentErrorMessage(true);
  64. return false;
  65. }
  66. if (player->GetPet())
  67. {
  68. handler->PSendSysMessage("You must hide your pet.");
  69. handler->SetSentErrorMessage(true);
  70. return false;
  71. }
  72. if (player->GetMap()->IsBattlegroundOrArena() && !player->IsSpectator())
  73. {
  74. handler->PSendSysMessage("You are already in a battleground or arena.");
  75. handler->SetSentErrorMessage(true);
  76. return false;
  77. }
  78. Map* cMap = target->GetMap();
  79. if (!cMap->IsBattleArena())
  80. {
  81. handler->PSendSysMessage("Player is not in an Arena match.");
  82. handler->SetSentErrorMessage(true);
  83. return false;
  84. }
  85. if (player->GetMap()->IsBattleground())
  86. {
  87. handler->PSendSysMessage("You can't do that while in a battleground.");
  88. handler->SetSentErrorMessage(true);
  89. return false;
  90. }
  91. if (target->HasAura(32728) || target->HasAura(32727))
  92. {
  93. handler->PSendSysMessage("You can't do that. The Arena match didn't start yet.");
  94. handler->SetSentErrorMessage(true);
  95. return false;
  96. }
  97. if (target->IsSpectator())
  98. {
  99. handler->PSendSysMessage("You can't do that. Your target is a spectator.");
  100. handler->SetSentErrorMessage(true);
  101. return false;
  102. }
  103. if (player->IsMounted())
  104. {
  105. handler->PSendSysMessage("Cannot Spectate while mounted.");
  106. handler->SetSentErrorMessage(true);
  107. return false;
  108. }
  109. // all's well, set bg id
  110. // when porting out from the bg, it will be reset to 0
  111. player->SetBattlegroundId(target->GetBattlegroundId(), target->GetBattlegroundTypeId());
  112. // remember current position as entry point for return at bg end teleportation
  113. if (!player->GetMap()->IsBattlegroundOrArena())
  114. player->SetBattlegroundEntryPoint();
  115. // stop flight if need
  116. if (player->IsInFlight())
  117. {
  118. player->GetMotionMaster()->MovementExpired();
  119. player->CleanupAfterTaxiFlight();
  120. }
  121. // save only in non-flight case
  122. else
  123. player->SaveRecallPosition();
  124. // search for two teams
  125. Battleground *bGround = target->GetBattleground();
  126. if (bGround->isRated())
  127. {
  128. uint32 slot = bGround->GetArenaType() - 2;
  129. if (bGround->GetArenaType() > 3)
  130. slot = 2;
  131. uint32 firstTeamID = target->GetArenaTeamId(slot);
  132. uint32 secondTeamID = 0;
  133. Player *firstTeamMember = target;
  134. Player *secondTeamMember = NULL;
  135. for (Battleground::BattlegroundPlayerMap::const_iterator itr = bGround->GetPlayers().begin(); itr != bGround->GetPlayers().end(); ++itr)
  136. if (Player* tmpPlayer = ObjectAccessor::FindPlayer(itr->first))
  137. {
  138. if (tmpPlayer->IsSpectator())
  139. continue;
  140. uint32 tmpID = tmpPlayer->GetArenaTeamId(slot);
  141. if (tmpID != firstTeamID && tmpID > 0)
  142. {
  143. secondTeamID = tmpID;
  144. secondTeamMember = tmpPlayer;
  145. break;
  146. }
  147. }
  148. if (firstTeamID > 0 && secondTeamID > 0 && secondTeamMember)
  149. {
  150. ArenaTeam *firstTeam = sArenaTeamMgr->GetArenaTeamById(firstTeamID);
  151. ArenaTeam *secondTeam = sArenaTeamMgr->GetArenaTeamById(secondTeamID);
  152. if (firstTeam && secondTeam)
  153. {
  154. handler->PSendSysMessage("You entered a Rated Arena.");
  155. handler->PSendSysMessage("Teams:");
  156. handler->PSendSysMessage("|cFFffffff%s|r vs |cFFffffff%s|r", firstTeam->GetName().c_str(), secondTeam->GetName().c_str());
  157. handler->PSendSysMessage("|cFFffffff%u(%u)|r -- |cFFffffff%u(%u)|r", firstTeam->GetRating(), firstTeam->GetAverageMMR(firstTeamMember->GetGroup()),
  158. secondTeam->GetRating(), secondTeam->GetAverageMMR(secondTeamMember->GetGroup()));
  159. }
  160. }
  161. }
  162. // to point to see at target with same orientation
  163. float x, y, z;
  164. target->GetContactPoint(player, x, y, z);
  165. player->TeleportTo(target->GetMapId(), x, y, z, player->GetAngle(target), TELE_TO_GM_MODE);
  166. player->SetPhaseMask(target->GetPhaseMask(), true);
  167. player->SetSpectate(true);
  168. target->GetBattleground()->AddSpectator(player->GetGUID());
  169. return true;
  170. }
  171. static bool HandleSpectateCancelCommand(ChatHandler* handler, const char* /*args*/)
  172. {
  173. Player* player = handler->GetSession()->GetPlayer();
  174. if (!player->IsSpectator())
  175. {
  176. handler->PSendSysMessage("You are not a spectator.");
  177. handler->SetSentErrorMessage(true);
  178. return false;
  179. }
  180. player->GetBattleground()->RemoveSpectator(player->GetGUID());
  181. player->CancelSpectate();
  182. player->TeleportToBGEntryPoint();
  183. return true;
  184. }
  185. static bool HandleSpectateFromCommand(ChatHandler* handler, const char *args)
  186. {
  187. Player* target;
  188. ObjectGuid target_guid;
  189. std::string target_name;
  190. if (!handler->extractPlayerTarget((char*)args, &target, &target_guid, &target_name))
  191. return false;
  192. Player* player = handler->GetSession()->GetPlayer();
  193. if (target->HasAuraType(SPELL_AURA_MOD_STEALTH))
  194. {
  195. handler->PSendSysMessage("You can't target stealthed players.");
  196. handler->SetSentErrorMessage(true);
  197. return false;
  198. }
  199. if (!target)
  200. {
  201. handler->PSendSysMessage("Player is not online or does not exist.");
  202. handler->SetSentErrorMessage(true);
  203. return false;
  204. }
  205. if (!player->IsSpectator())
  206. {
  207. handler->PSendSysMessage("You are not a spectator, spectate someone first.");
  208. handler->SetSentErrorMessage(true);
  209. return false;
  210. }
  211. if (target->IsSpectator() && target != player)
  212. {
  213. handler->PSendSysMessage("You can't do that. Your target is a spectator.");
  214. handler->SetSentErrorMessage(true);
  215. return false;
  216. }
  217. if (player->GetMap() != target->GetMap())
  218. {
  219. handler->PSendSysMessage("You can't do that. Your target might be in a different arena match.");
  220. handler->SetSentErrorMessage(true);
  221. return false;
  222. }
  223. // check for arena preperation
  224. // if exists than battle didn`t begin
  225. if (target->HasAura(32728) || target->HasAura(32727))
  226. {
  227. handler->PSendSysMessage("You can't do that. The Arena match didn't start yet.");
  228. handler->SetSentErrorMessage(true);
  229. return false;
  230. }
  231. (target == player && player->getSpectateFrom()) ? player->SetViewpoint(player->getSpectateFrom(), false) :
  232. player->SetViewpoint(target, true);
  233. return true;
  234. }
  235. static bool HandleSpectateResetCommand(ChatHandler* handler, const char *args)
  236. {
  237. Player* player = handler->GetSession()->GetPlayer();
  238. if (!player)
  239. {
  240. handler->PSendSysMessage("Cant find player.");
  241. handler->SetSentErrorMessage(true);
  242. return false;
  243. }
  244. if (!player->IsSpectator())
  245. {
  246. handler->PSendSysMessage("You are not a spectator!");
  247. handler->SetSentErrorMessage(true);
  248. return false;
  249. }
  250. Battleground *bGround = player->GetBattleground();
  251. if (!bGround)
  252. return false;
  253. if (bGround->GetStatus() != STATUS_IN_PROGRESS)
  254. return true;
  255. for (Battleground::BattlegroundPlayerMap::const_iterator itr = bGround->GetPlayers().begin(); itr != bGround->GetPlayers().end(); ++itr)
  256. if (Player* tmpPlayer = ObjectAccessor::FindPlayer(itr->first))
  257. {
  258. if (tmpPlayer->IsSpectator())
  259. continue;
  260. uint32 tmpID = bGround->GetPlayerTeam(tmpPlayer->GetGUID());
  261. // generate addon massage
  262. std::string pName = tmpPlayer->GetName();
  263. std::string tName = "";
  264. if (Player *target = tmpPlayer->GetSelectedPlayer())
  265. tName = target->GetName();
  266. SpectatorAddonMsg msg; // Travis
  267. msg.SetPlayer(pName);
  268. if (tName != "")
  269. msg.SetTarget(tName);
  270. msg.SetStatus(tmpPlayer->IsAlive());
  271. msg.SetClass(tmpPlayer->getClass());
  272. msg.SetCurrentHP(tmpPlayer->GetHealth());
  273. msg.SetMaxHP(tmpPlayer->GetMaxHealth());
  274. Powers powerType = tmpPlayer->getPowerType();
  275. msg.SetMaxPower(tmpPlayer->GetMaxPower(powerType));
  276. msg.SetCurrentPower(tmpPlayer->GetPower(powerType));
  277. msg.SetPowerType(powerType);
  278. msg.SetTeam(tmpID);
  279. msg.SendPacket(player->GetGUID());
  280. }
  281. return true;
  282. }
  283. ChatCommand* GetCommands() const
  284. {
  285. static ChatCommand spectateCommandTable[] =
  286. {
  287. { "player", rbac::RBAC_PERM_COMMAND_SPECTATE_PLAYER, true, &HandleSpectateCommand, "", NULL },
  288. { "view", rbac::RBAC_PERM_COMMAND_SPECTATE_VIEW, true, &HandleSpectateFromCommand, "", NULL },
  289. { "reset", rbac::RBAC_PERM_COMMAND_SPECTATE_RESET, true, &HandleSpectateResetCommand, "", NULL },
  290. { "leave", rbac::RBAC_PERM_COMMAND_SPECTATE_LEAVE, true, &HandleSpectateCancelCommand, "", NULL },
  291. { NULL, 0, false, NULL, "", NULL }
  292. };
  293. static ChatCommand commandTable[] =
  294. {
  295. { "spectate", rbac::RBAC_PERM_COMMAND_SPECTATE, false, NULL, "", spectateCommandTable },
  296. { NULL, 0, false, NULL, "", NULL }
  297. };
  298. return commandTable;
  299. }
  300. };
  301. enum NpcSpectatorAtions {
  302. // will be used for scrolling
  303. NPC_SPECTATOR_ACTION_2V2_GAMES = 2000, //NPC_SPECTATOR_ACTION_LIST_GAMES = 1000,
  304. NPC_SPECTATOR_ACTION_3V3_GAMES = 3000, // NPC_SPECTATOR_ACTION_LIST_TOP_GAMES = 2000,
  305. NPC_SPECTATOR_ACTION_5V5_GAMES = 1000,
  306. NPC_SPECTATOR_ACTION_SPECIFIC = 500,
  307. // NPC_SPECTATOR_ACTION_SELECTED_PLAYER + player.Guid()
  308. NPC_SPECTATOR_ACTION_SELECTED_PLAYER = 4000
  309. };
  310. const uint8 GamesOnPage = 15;
  311. class npc_arena_spectator : public CreatureScript
  312. {
  313. public:
  314. npc_arena_spectator() : CreatureScript("npc_arena_spectator") { }
  315. bool OnGossipHello(Player* pPlayer, Creature* pCreature)
  316. {
  317. pPlayer->ADD_GOSSIP_ITEM(GOSSIP_ICON_CHAT, "|TInterface\\icons\\Achievement_Arena_2v2_7:35:35:-30:0|tGames: 2v2", GOSSIP_SENDER_MAIN, NPC_SPECTATOR_ACTION_2V2_GAMES);
  318. pPlayer->ADD_GOSSIP_ITEM(GOSSIP_ICON_CHAT, "|TInterface\\icons\\Achievement_Arena_3v3_7:35:35:-30:0|tGames: 3v3", GOSSIP_SENDER_MAIN, NPC_SPECTATOR_ACTION_3V3_GAMES);
  319. pPlayer->ADD_GOSSIP_ITEM(GOSSIP_ICON_CHAT, "|TInterface\\icons\\Achievement_Arena_5v5_7:35:35:-30:0|tGames: 1v1/soloqueue", GOSSIP_SENDER_MAIN, NPC_SPECTATOR_ACTION_5V5_GAMES);
  320. pPlayer->ADD_GOSSIP_ITEM_EXTENDED(GOSSIP_ICON_CHAT, "|TInterface\\icons\\Spell_Holy_DevineAegis:35:35:-30:0|tSpectate Specific Player.", GOSSIP_SENDER_MAIN, NPC_SPECTATOR_ACTION_SPECIFIC, "", 0, true);
  321. pPlayer->SEND_GOSSIP_MENU(DEFAULT_GOSSIP_MESSAGE, pCreature->GetGUID());
  322. return true;
  323. }
  324. bool OnGossipSelect(Player* player, Creature* creature, uint32 /*sender*/, uint32 action)
  325. {
  326. player->PlayerTalkClass->ClearMenus();
  327. if (action == NPC_SPECTATOR_ACTION_SPECIFIC)
  328. {
  329. }
  330. if (action >= NPC_SPECTATOR_ACTION_2V2_GAMES && action < NPC_SPECTATOR_ACTION_3V3_GAMES)
  331. {
  332. player->ADD_GOSSIP_ITEM(GOSSIP_ICON_DOT, " Refresh", GOSSIP_SENDER_MAIN, NPC_SPECTATOR_ACTION_2V2_GAMES);
  333. ShowPage(player, action - NPC_SPECTATOR_ACTION_2V2_GAMES, ARENA_TYPE_2v2);
  334. player->SEND_GOSSIP_MENU(DEFAULT_GOSSIP_MESSAGE, creature->GetGUID());
  335. }
  336. else if (action >= NPC_SPECTATOR_ACTION_3V3_GAMES && action < NPC_SPECTATOR_ACTION_5V5_GAMES)
  337. {
  338. player->ADD_GOSSIP_ITEM(GOSSIP_ICON_DOT, "Refresh", GOSSIP_SENDER_MAIN, NPC_SPECTATOR_ACTION_3V3_GAMES);
  339. ShowPage(player, action - NPC_SPECTATOR_ACTION_3V3_GAMES, ARENA_TYPE_3v3);
  340. player->SEND_GOSSIP_MENU(DEFAULT_GOSSIP_MESSAGE, creature->GetGUID());
  341. }
  342. else if (action >= NPC_SPECTATOR_ACTION_5V5_GAMES && action < NPC_SPECTATOR_ACTION_SELECTED_PLAYER)
  343. {
  344. player->ADD_GOSSIP_ITEM(GOSSIP_ICON_DOT, "Refresh", GOSSIP_SENDER_MAIN, NPC_SPECTATOR_ACTION_5V5_GAMES);
  345. ShowPage(player, action - NPC_SPECTATOR_ACTION_5V5_GAMES, ARENA_TYPE_5v5);
  346. player->SEND_GOSSIP_MENU(DEFAULT_GOSSIP_MESSAGE, creature->GetGUID());
  347. }
  348. else
  349. {
  350. ObjectGuid guid = ObjectGuid(HIGHGUID_PLAYER, action - NPC_SPECTATOR_ACTION_SELECTED_PLAYER);
  351. if (Player* target = ObjectAccessor::FindPlayer(guid))
  352. {
  353. ChatHandler handler(player->GetSession());
  354. char const* pTarget = target->GetName().c_str();
  355. arena_spectator_commands::HandleSpectateCommand(&handler, pTarget);
  356. }
  357. }
  358. return true;
  359. }
  360. std::string GetClassNameById(uint8 id)
  361. {
  362. std::string sClass = "";
  363. switch (id)
  364. {
  365. case CLASS_WARRIOR: sClass = "Warrior "; break;
  366. case CLASS_PALADIN: sClass = "Paladin "; break;
  367. case CLASS_HUNTER: sClass = "Hunter "; break;
  368. case CLASS_ROGUE: sClass = "Rogue "; break;
  369. case CLASS_PRIEST: sClass = "Priest "; break;
  370. case CLASS_DEATH_KNIGHT: sClass = "DKnight "; break;
  371. case CLASS_SHAMAN: sClass = "Shaman "; break;
  372. case CLASS_MAGE: sClass = "Mage "; break;
  373. case CLASS_WARLOCK: sClass = "Warlock "; break;
  374. case CLASS_DRUID: sClass = "Druid "; break;
  375. }
  376. return sClass;
  377. }
  378. std::string GetGamesStringData(Battleground* team, uint16 mmr, uint16 mmrTwo)
  379. {
  380. std::string teamsMember[BG_TEAMS_COUNT];
  381. uint32 firstTeamId = 0;
  382. for (Battleground::BattlegroundPlayerMap::const_iterator itr = team->GetPlayers().begin(); itr != team->GetPlayers().end(); ++itr)
  383. if (Player* player = ObjectAccessor::FindPlayer(itr->first))
  384. {
  385. if (player->IsSpectator())
  386. continue;
  387. if (player->IsGameMaster())
  388. continue;
  389. uint32 team = itr->second.Team;
  390. if (!firstTeamId)
  391. firstTeamId = team;
  392. teamsMember[firstTeamId == team] += GetClassNameById(player->getClass());
  393. }
  394. std::string data = teamsMember[0] + "(";
  395. std::stringstream ss;
  396. std::stringstream sstwo;
  397. ss << mmr;
  398. sstwo << mmrTwo;
  399. data += ss.str();
  400. data += ") - ";
  401. data += teamsMember[1] + "(" + sstwo.str();
  402. data += ")";
  403. return data;
  404. }
  405. ObjectGuid GetFirstPlayerGuid(Battleground* team)
  406. {
  407. for (Battleground::BattlegroundPlayerMap::const_iterator itr = team->GetPlayers().begin(); itr != team->GetPlayers().end(); ++itr)
  408. if (Player* player = ObjectAccessor::FindPlayer(itr->first))
  409. return itr->first;
  410. return ObjectGuid::Empty;
  411. }
  412. void ShowPage(Player* player, uint16 page, uint32 IsTop)
  413. {
  414. uint32 firstTeamId = 0;
  415. uint16 TypeOne = 0;
  416. uint16 TypeTwo = 0;
  417. uint16 TypeThree = 0;
  418. uint16 mmr = 0;
  419. uint16 mmrTwo = 0;
  420. bool haveNextPage = false;
  421. for (uint8 i = 0; i <= MAX_BATTLEGROUND_TYPE_ID; ++i)
  422. {
  423. if (!sBattlegroundMgr->IsArenaType(BattlegroundTypeId(i)))
  424. continue;
  425. //BattlegroundContainer arenas = sBattlegroundMgr->GetBattlegroundsByType((BattlegroundTypeId)i);
  426. BattlegroundData* arenas = sBattlegroundMgr->GetAllBattlegroundsWithTypeId(BattlegroundTypeId(i));
  427. if (!arenas || arenas->m_Battlegrounds.empty())
  428. continue;
  429. for (BattlegroundContainer::const_iterator itr = arenas->m_Battlegrounds.begin(); itr != arenas->m_Battlegrounds.end(); ++itr)
  430. {
  431. Battleground* arena = itr->second;
  432. Player* target = ObjectAccessor::FindPlayer(GetFirstPlayerGuid(arena));
  433. if (target && (target->HasAura(32728) || target->HasAura(32727)))
  434. continue;
  435. if (!arena->GetPlayersSize())
  436. continue;
  437. if (arena->GetArenaType() == ARENA_TYPE_2v2)
  438. {
  439. mmr = arena->GetArenaMatchmakerRating(0);
  440. firstTeamId = target->GetArenaTeamId(0);
  441. Battleground::BattlegroundPlayerMap::const_iterator citr = arena->GetPlayers().begin();
  442. for (; citr != arena->GetPlayers().end(); ++citr)
  443. if (Player* plrs = sObjectAccessor->FindPlayer(citr->first))
  444. if (plrs->GetArenaTeamId(0) != firstTeamId)
  445. mmrTwo = arena->GetArenaMatchmakerRating(citr->second.Team);
  446. }
  447. else if (arena->GetArenaType() == ARENA_TYPE_3v3)
  448. {
  449. mmr = arena->GetArenaMatchmakerRating(1);
  450. firstTeamId = target->GetArenaTeamId(1);
  451. Battleground::BattlegroundPlayerMap::const_iterator citr = arena->GetPlayers().begin();
  452. for (; citr != arena->GetPlayers().end(); ++citr)
  453. if (Player* plrs = sObjectAccessor->FindPlayer(citr->first))
  454. if (plrs->GetArenaTeamId(1) != firstTeamId)
  455. mmrTwo = arena->GetArenaMatchmakerRating(citr->second.Team);
  456. }
  457. else if (arena->GetArenaType() == ARENA_TYPE_5v5 && arena->GetArenaType() == ARENA_TYPE_3v3_SOLO)
  458. {
  459. mmr = arena->GetArenaMatchmakerRating(2);
  460. firstTeamId = target->GetArenaTeamId(2);
  461. Battleground::BattlegroundPlayerMap::const_iterator citr = arena->GetPlayers().begin();
  462. for (; citr != arena->GetPlayers().end(); ++citr)
  463. if (Player* plrs = sObjectAccessor->FindPlayer(citr->first))
  464. if (plrs->GetArenaTeamId(2) != firstTeamId)
  465. mmrTwo = arena->GetArenaMatchmakerRating(citr->second.Team);
  466. }
  467. if (IsTop == 1 && arena->GetArenaType() == ARENA_TYPE_2v2)
  468. {
  469. TypeOne++;
  470. if (TypeOne > (page + 1) * GamesOnPage)
  471. {
  472. haveNextPage = true;
  473. break;
  474. }
  475. if (TypeOne >= page * GamesOnPage)
  476. player->ADD_GOSSIP_ITEM(GOSSIP_ICON_BATTLE, GetGamesStringData(arena, mmr, mmrTwo), GOSSIP_SENDER_MAIN, NPC_SPECTATOR_ACTION_SELECTED_PLAYER + GetFirstPlayerGuid(arena));
  477. }
  478. else if (IsTop == 2 && arena->GetArenaType() == ARENA_TYPE_3v3)
  479. {
  480. TypeTwo++;
  481. if (TypeTwo > (page + 1) * GamesOnPage)
  482. {
  483. haveNextPage = true;
  484. break;
  485. }
  486. if (TypeTwo >= page * GamesOnPage)
  487. player->ADD_GOSSIP_ITEM(GOSSIP_ICON_BATTLE, GetGamesStringData(arena, mmr, mmrTwo), GOSSIP_SENDER_MAIN, NPC_SPECTATOR_ACTION_SELECTED_PLAYER + GetFirstPlayerGuid(arena));
  488. }
  489. else if (IsTop == 3 && arena->GetArenaType() == ARENA_TYPE_5v5 && arena->GetArenaType() == ARENA_TYPE_3v3_SOLO)
  490. {
  491. TypeThree++;
  492. if (TypeThree > (page + 1) * GamesOnPage)
  493. {
  494. haveNextPage = true;
  495. break;
  496. }
  497. if (TypeThree >= page * GamesOnPage)
  498. player->ADD_GOSSIP_ITEM(GOSSIP_ICON_BATTLE, GetGamesStringData(arena, mmr, mmrTwo), GOSSIP_SENDER_MAIN, NPC_SPECTATOR_ACTION_SELECTED_PLAYER + GetFirstPlayerGuid(arena));
  499. }
  500. }
  501. }
  502. if (page > 0)
  503. {
  504. player->ADD_GOSSIP_ITEM(GOSSIP_ICON_DOT, "Prev..", GOSSIP_SENDER_MAIN, NPC_SPECTATOR_ACTION_2V2_GAMES + page - 1);
  505. player->ADD_GOSSIP_ITEM(GOSSIP_ICON_DOT, "Prev..", GOSSIP_SENDER_MAIN, NPC_SPECTATOR_ACTION_3V3_GAMES + page - 1);
  506. player->ADD_GOSSIP_ITEM(GOSSIP_ICON_DOT, "Prev..", GOSSIP_SENDER_MAIN, NPC_SPECTATOR_ACTION_5V5_GAMES + page - 1);
  507. }
  508. if (haveNextPage)
  509. {
  510. player->ADD_GOSSIP_ITEM(GOSSIP_ICON_DOT, "Next..", GOSSIP_SENDER_MAIN, NPC_SPECTATOR_ACTION_2V2_GAMES + page + 1);
  511. player->ADD_GOSSIP_ITEM(GOSSIP_ICON_DOT, "Next..", GOSSIP_SENDER_MAIN, NPC_SPECTATOR_ACTION_3V3_GAMES + page + 1);
  512. player->ADD_GOSSIP_ITEM(GOSSIP_ICON_DOT, "Next..", GOSSIP_SENDER_MAIN, NPC_SPECTATOR_ACTION_5V5_GAMES + page + 1);
  513. }
  514. }
  515. bool OnGossipSelectCode(Player* player, Creature* creature, uint32 sender, uint32 action, const char* code)
  516. {
  517. if (!player)
  518. return true;
  519. player->PlayerTalkClass->ClearMenus();
  520. player->CLOSE_GOSSIP_MENU();
  521. if (sender == GOSSIP_SENDER_MAIN)
  522. {
  523. switch (action)
  524. {
  525. case NPC_SPECTATOR_ACTION_SPECIFIC: // choosing a player
  526. const char* plrName = code;
  527. char playerName[50];
  528. strcpy(playerName, plrName);
  529. for (int i = 0; i < 13; i++)
  530. {
  531. if (playerName[i] == NULL)
  532. break;
  533. if (i == 0 && playerName[i] > 96)
  534. playerName[0] -= 32;
  535. else if (playerName[i] < 97)
  536. playerName[i] += 32;
  537. }
  538. if (Player* target = sObjectAccessor->FindPlayerByName(playerName))
  539. {
  540. ChatHandler handler(player->GetSession());
  541. char const* pTarget = target->GetName().c_str();
  542. arena_spectator_commands::HandleSpectateCommand(&handler, pTarget);
  543. }
  544. ChatHandler(player->GetSession()).PSendSysMessage("Player is not online or does not exist.");
  545. return true;
  546. }
  547. }
  548. return false;
  549. }
  550. };
  551. void AddSC_arena_spectator_script()
  552. {
  553. new arena_spectator_commands();
  554. new npc_arena_spectator();
  555. }

Arena Spectator Outdated!