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

Arena spectator.cpp