kusanagy

Arena_Spectator

Dec 2nd, 2017
519
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
Diff 56.22 KB | None | 0 0
  1. From ee3a882311fe302b66502c8f56c1c8949dc914be Mon Sep 17 00:00:00 2001
  2.  
  3. Date: Sat, 23 Jan 2016 10:56:53 -0600
  4. Subject: [PATCH] 2016_01_23-Arena_Spectator
  5.  
  6. ---
  7. .../Arena_Spectator/auth.Arena_Spectator.sql       |  15 +
  8.  .../Arena_Spectator/world.Arena_Spectator.sql      |  10 +
  9.  src/server/game/Accounts/RBAC.h                    |   8 +-
  10.  src/server/game/Battlegrounds/Battleground.cpp     |  24 +-
  11.  src/server/game/Battlegrounds/Battleground.h       |  11 +
  12.  src/server/game/Battlegrounds/BattlegroundMgr.h    |  12 +-
  13.  src/server/game/Battlegrounds/SpectatorAddon.cpp   | 224 +++++++
  14.  src/server/game/Battlegrounds/SpectatorAddon.h     |  96 +++
  15.  src/server/game/Entities/GameObject/GameObject.cpp |   9 +
  16.  src/server/game/Entities/Player/Player.cpp         | 114 +++-
  17.  src/server/game/Entities/Player/Player.h           |  15 +-
  18.  src/server/game/Entities/Unit/Unit.cpp             |  13 +
  19.  src/server/game/Handlers/ChatHandler.cpp           |   6 +
  20.  src/server/game/Maps/Map.cpp                       |   7 +
  21.  src/server/game/Miscellaneous/Language.h           |   3 +
  22.  src/server/game/Spells/Spell.cpp                   |   4 +
  23.  src/server/scripts/Commands/cs_gm.cpp              |   3 +
  24.  src/server/scripts/Custom/ArenaSpectator/README.md |  33 ++
  25.  .../Custom/ArenaSpectator/arena_spectator.cpp      | 643 +++++++++++++++++++++
  26.  19 files changed, 1239 insertions(+), 11 deletions(-)
  27.  create mode 100644 sql/TrinityCore-Patches/Arena_Spectator/auth.Arena_Spectator.sql
  28.  create mode 100644 sql/TrinityCore-Patches/Arena_Spectator/world.Arena_Spectator.sql
  29.  create mode 100644 src/server/game/Battlegrounds/SpectatorAddon.cpp
  30.  create mode 100644 src/server/game/Battlegrounds/SpectatorAddon.h
  31.  create mode 100644 src/server/scripts/Custom/ArenaSpectator/README.md
  32.  create mode 100644 src/server/scripts/Custom/ArenaSpectator/arena_spectator.cpp
  33.  
  34. diff --git a/sql/TrinityCore-Patches/Arena_Spectator/auth.Arena_Spectator.sql b/sql/TrinityCore-Patches/Arena_Spectator/auth.Arena_Spectator.sql
  35. new file mode 100644
  36. index 0000000..862cda6
  37. --- /dev/null
  38. +++ b/sql/TrinityCore-Patches/Arena_Spectator/auth.Arena_Spectator.sql
  39. @@ -0,0 +1,15 @@
  40. +DELETE FROM `rbac_linked_permissions` where `linkedId` IN ("1003","1004","1005","1006","1007");
  41. +INSERT INTO `rbac_linked_permissions` (`id`, `linkedId`) values
  42. +('195','1003'),
  43. +('195','1004'),
  44. +('195','1005'),
  45. +('195','1006'),
  46. +('195','1007');
  47. +
  48. +DELETE FROM `rbac_permissions` WHERE `id` IN ("1003","1004","1005","1006","1007");
  49. +insert into `rbac_permissions` (`id`, `name`) values
  50. +('1003', 'spectate'),
  51. +('1004', 'spectate player'),
  52. +('1005', 'spectate view'),
  53. +('1006', 'spectate reset'),
  54. +('1007', 'spectate leave');
  55. \ No newline at end of file
  56. diff --git a/sql/TrinityCore-Patches/Arena_Spectator/world.Arena_Spectator.sql b/sql/TrinityCore-Patches/Arena_Spectator/world.Arena_Spectator.sql
  57. new file mode 100644
  58. index 0000000..2f4aed5
  59. --- /dev/null
  60. +++ b/sql/TrinityCore-Patches/Arena_Spectator/world.Arena_Spectator.sql
  61. @@ -0,0 +1,10 @@
  62. +SET
  63. +@Entry = 190000,
  64. +@Name = "Arena Spectator",
  65. +@Subname = "Spectate Master",
  66. +@IconName = "Speak";
  67. +
  68. +DELETE FROM `creature_template` WHERE `entry`=@Entry;
  69. +INSERT INTO `creature_template` (`entry`, `modelid1`, `modelid2`, `name`, `subname`, `IconName`, `gossip_menu_id`, `minlevel`, `maxlevel`, `exp`, `faction`, `npcflag`, `scale`, `rank`, `dmgschool`, `baseattacktime`, `rangeattacktime`, `unit_class`, `unit_flags`, `type`, `type_flags`, `lootid`, `pickpocketloot`, `skinloot`, `AIName`, `MovementType`, `InhabitType`, `HoverHeight`, `RacialLeader`, `movementId`, `RegenHealth`, `mechanic_immune_mask`, `flags_extra`, `ScriptName`) VALUES
  70. +(@Entry, 29348, 0, @Name, @Subname, @IconName, 0, 80, 80, 2, 35, 3, 1, 0, 0, 2000, 0, 1, 0, 7, 138936390, 0, 0, 0, '', 0, 3, 1, 0, 0, 1, 0, 0, 'npc_arena_spectator');
  71. +
  72. diff --git a/src/server/game/Accounts/RBAC.h b/src/server/game/Accounts/RBAC.h
  73. index 3c3e838..5cc3daf 100644
  74. --- a/src/server/game/Accounts/RBAC.h
  75. +++ b/src/server/game/Accounts/RBAC.h
  76. @@ -697,7 +697,13 @@ enum RBACPermissions
  77.      // 799 - 834 6.x only
  78.      RBAC_PERM_COMMAND_DEBUG_LOADCELLS                        = 835,
  79.      RBAC_PERM_COMMAND_DEBUG_BOUNDARY                         = 836,
  80. -
  81. +  
  82. +   //Arena Spectator
  83. +    RBAC_PERM_COMMAND_SPECTATE                               = 1003,
  84. +    RBAC_PERM_COMMAND_SPECTATE_PLAYER                        = 1004,
  85. +    RBAC_PERM_COMMAND_SPECTATE_VIEW                          = 1005,
  86. +    RBAC_PERM_COMMAND_SPECTATE_RESET                         = 1006,
  87. +    RBAC_PERM_COMMAND_SPECTATE_LEAVE                         = 1007,
  88.      // custom permissions 1000+
  89.      // Prepatch by LordPsyan
  90.      // 01
  91. diff --git a/src/server/game/Battlegrounds/Battleground.cpp b/src/server/game/Battlegrounds/Battleground.cpp
  92. index 100e2e6..e79a643 100644
  93. --- a/src/server/game/Battlegrounds/Battleground.cpp
  94. +++ b/src/server/game/Battlegrounds/Battleground.cpp
  95. @@ -1141,13 +1141,23 @@ void Battleground::EventPlayerLoggedOut(Player* player)
  96.      m_Players[guid].OfflineRemoveTime = sWorld->GetGameTime() + MAX_OFFLINE_TIME;
  97.      if (GetStatus() == STATUS_IN_PROGRESS)
  98.      {
  99. -        // drop flag and handle other cleanups
  100. -        RemovePlayer(player, guid, GetPlayerTeam(guid));
  101. -
  102. -        // 1 player is logging out, if it is the last, then end arena!
  103. -        if (isArena())
  104. -            if (GetAlivePlayersCountByTeam(player->GetBGTeam()) <= 1 && GetPlayersCountByTeam(GetOtherTeam(player->GetBGTeam())))
  105. -                EndBattleground(GetOtherTeam(player->GetBGTeam()));
  106. +        if (!player->IsSpectator())
  107. +        {
  108. +            // drop flag and handle other cleanups
  109. +            RemovePlayer(player, guid, GetPlayerTeam(guid));
  110. +            // 1 player is logging out, if it is the last, then end arena!
  111. +            if (isArena())
  112. +                if (GetAlivePlayersCountByTeam(player->GetTeam()) <= 1 && GetPlayersCountByTeam(GetOtherTeam(player->GetTeam())))
  113. +                    EndBattleground(GetOtherTeam(player->GetTeam()));
  114. +        }
  115. +    }
  116. +      
  117. +   if (!player->IsSpectator())
  118. +        player->LeaveBattleground();
  119. +    else
  120. +    {
  121. +        player->TeleportToBGEntryPoint();
  122. +        RemoveSpectator(player->GetGUID());
  123.      }
  124.  }
  125.  
  126. diff --git a/src/server/game/Battlegrounds/Battleground.h b/src/server/game/Battlegrounds/Battleground.h
  127. index 03f138a..190528e 100644
  128. --- a/src/server/game/Battlegrounds/Battleground.h
  129. +++ b/src/server/game/Battlegrounds/Battleground.h
  130. @@ -27,6 +27,7 @@
  131.  #include "Object.h"
  132.  #include "GameObject.h"
  133.  #include "EventMap.h"
  134. +#include "SpectatorAddon.h"
  135.  
  136.  class Creature;
  137.  class GameObject;
  138. @@ -309,6 +310,13 @@ class Battleground
  139.          uint32 GetInvitedCount(uint32 team) const   { return (team == ALLIANCE) ? m_InvitedAlliance : m_InvitedHorde; }
  140.          bool HasFreeSlots() const;
  141.          uint32 GetFreeSlotsForTeam(uint32 Team) const;
  142. +      
  143. +       /* Arena Spectator */
  144. +       typedef std::set<uint32> SpectatorList;
  145. +       void AddSpectator(uint32 playerId) { m_Spectators.insert(playerId); }
  146. +       void RemoveSpectator(uint32 playerId) { m_Spectators.erase(playerId); }
  147. +       bool HaveSpectators() { return (m_Spectators.size() > 0); }
  148. +       /* Arena Spectator */
  149.  
  150.          bool isArena() const        { return m_IsArena; }
  151.          bool isBattleground() const { return !m_IsArena; }
  152. @@ -589,6 +597,9 @@ class Battleground
  153.  
  154.          // Players count by team
  155.          uint32 m_PlayersCount[BG_TEAMS_COUNT];
  156. +      
  157. +        // Arena Spectator
  158. +        SpectatorList m_Spectators;
  159.  
  160.          // Arena team ids by team
  161.          uint32 m_ArenaTeamIds[BG_TEAMS_COUNT];
  162. diff --git a/src/server/game/Battlegrounds/BattlegroundMgr.h b/src/server/game/Battlegrounds/BattlegroundMgr.h
  163. index 595745e..e088c5b 100644
  164. --- a/src/server/game/Battlegrounds/BattlegroundMgr.h
  165. +++ b/src/server/game/Battlegrounds/BattlegroundMgr.h
  166. @@ -109,6 +109,7 @@ class BattlegroundMgr
  167.  
  168.          bool isArenaTesting() const { return m_ArenaTesting; }
  169.          bool isTesting() const { return m_Testing; }
  170. +       bool IsArenaType(BattlegroundTypeId bgTypeId);
  171.  
  172.          static BattlegroundQueueTypeId BGQueueTypeId(BattlegroundTypeId bgTypeId, uint8 arenaType);
  173.          static BattlegroundTypeId BGTemplateId(BattlegroundQueueTypeId bgQueueTypeId);
  174. @@ -118,6 +119,15 @@ class BattlegroundMgr
  175.          static BattlegroundTypeId WeekendHolidayIdToBGType(HolidayIds holiday);
  176.          static bool IsBGWeekend(BattlegroundTypeId bgTypeId);
  177.  
  178. +       BattlegroundData* GetAllBattlegroundsWithTypeId(BattlegroundTypeId bgTypeId)
  179. +        {
  180. +            BattlegroundDataContainer::iterator it = bgDataStore.find(bgTypeId);
  181. +            if (it == bgDataStore.end())
  182. +                return NULL;
  183. +
  184. +            return &it->second;
  185. +        }
  186. +
  187.          uint32 GetMaxRatingDifference() const;
  188.          uint32 GetRatingDiscardTimer()  const;
  189.          void InitAutomaticArenaPointDistribution();
  190. @@ -134,7 +144,7 @@ class BattlegroundMgr
  191.      private:
  192.          bool CreateBattleground(BattlegroundTemplate const* bgTemplate);
  193.          uint32 CreateClientVisibleInstanceId(BattlegroundTypeId bgTypeId, BattlegroundBracketId bracket_id);
  194. -        static bool IsArenaType(BattlegroundTypeId bgTypeId);
  195. +        //static bool IsArenaType(BattlegroundTypeId bgTypeId);
  196.          BattlegroundTypeId GetRandomBG(BattlegroundTypeId id);
  197.  
  198.          typedef std::map<BattlegroundTypeId, BattlegroundData> BattlegroundDataContainer;
  199. diff --git a/src/server/game/Battlegrounds/SpectatorAddon.cpp b/src/server/game/Battlegrounds/SpectatorAddon.cpp
  200. new file mode 100644
  201. index 0000000..ce265b6
  202. --- /dev/null
  203. +++ b/src/server/game/Battlegrounds/SpectatorAddon.cpp
  204. @@ -0,0 +1,224 @@
  205. +/*
  206. + * Copyright (C) 2008-2012 TrinityCore <http://www.trinitycore.org/>
  207. + *
  208. + * This program is free software; you can redistribute it and/or modify it
  209. + * under the terms of the GNU General Public License as published by the
  210. + * Free Software Foundation; either version 2 of the License, or (at your
  211. + * option) any later version.
  212. + *
  213. + * This program is distributed in the hope that it will be useful, but WITHOUT
  214. + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
  215. + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
  216. + * more details.
  217. + *
  218. + * You should have received a copy of the GNU General Public License along
  219. + * with this program. If not, see <http://www.gnu.org/licenses/>.
  220. + */
  221. +
  222. +#include "Player.h"
  223. +#include "Item.h"
  224. +#include "SpellInfo.h"
  225. +#include "SpectatorAddon.h"
  226. +#include "ObjectAccessor.h"
  227. +#include "Opcodes.h"
  228. +#include "WorldPacket.h"
  229. +#include "WorldSession.h"
  230. +
  231. +SpectatorAddonMsg::SpectatorAddonMsg()
  232. +{
  233. +    for (uint8 i = 0; i < SPECTATOR_PREFIX_COUNT; ++i)
  234. +        prefixFlags[i] = false;
  235. +
  236. +    player    = "";
  237. +    target    = "";
  238. +    isAlive   = false;
  239. +    pClass    = CLASS_WARRIOR;
  240. +    maxHP     = 0;
  241. +    maxPower  = 0;
  242. +    currHP    = 0;
  243. +    currPower = 0;
  244. +    powerType = POWER_MANA;
  245. +    spellId   = 0;
  246. +    castTime  = 0;
  247. +    team      = ALLIANCE;
  248. +}
  249. +
  250. +bool SpectatorAddonMsg::CanSandAura(uint32 auraID)
  251. +{
  252. +    const SpellInfo *spell = sSpellMgr->GetSpellInfo(auraID);
  253. +    if (!spell)
  254. +        return false;
  255. +
  256. +    if (spell->SpellIconID == 1)
  257. +        return false;
  258. +
  259. +    return true;
  260. +}
  261. +
  262. +void SpectatorAddonMsg::CreateAura(uint32 _caster, uint32 _spellId, bool _isDebuff, uint8 _type, int32 _duration, int32 _expire, uint16 _stack, bool _isRemove)
  263. +{
  264. +    if (!CanSandAura(_spellId))
  265. +        return;
  266. +
  267. +    aCaster     = _caster;
  268. +    aSpellId    = _spellId;
  269. +    aIsDebuff   = _isDebuff;
  270. +    aType       = _type;
  271. +    aDuration   = _duration;
  272. +    aExpire     = _expire;
  273. +    aStack      = _stack;
  274. +    aRemove     = _isRemove;
  275. +    EnableFlag(SPECTATOR_PREFIX_AURA);
  276. +}
  277. +
  278. +std::string SpectatorAddonMsg::GetMsgData()
  279. +{
  280. +    std::string addonData = "";
  281. +
  282. +    if (!isFilledIn(SPECTATOR_PREFIX_PLAYER))
  283. +    {
  284. +        TC_LOG_INFO("battleground", "SPECTATOR ADDON: player is not filled in.");
  285. +        return addonData;
  286. +    }
  287. +
  288. +    std::string msg = "";
  289. +    for (uint8 i = 0; i < SPECTATOR_PREFIX_COUNT; ++i)
  290. +        if (isFilledIn(i))
  291. +        {
  292. +            switch (i)
  293. +            {
  294. +                case SPECTATOR_PREFIX_PLAYER:
  295. +                    msg += player + ";";
  296. +                    break;
  297. +                case SPECTATOR_PREFIX_TARGET:
  298. +                    msg += "TRG=" + target + ";";
  299. +                    break;
  300. +                case SPECTATOR_PREFIX_TEAM:
  301. +                {
  302. +                    char buffer[20];
  303. +                    sprintf(buffer, "TEM=%i;", (uint16)team);
  304. +                    msg += buffer;
  305. +                    break;
  306. +                }
  307. +                case SPECTATOR_PREFIX_STATUS:
  308. +                {
  309. +                    char buffer[20];
  310. +                    sprintf(buffer, "STA=%d;", isAlive);
  311. +                    msg += buffer;
  312. +                    break;
  313. +                }
  314. +                case SPECTATOR_PREFIX_CLASS:
  315. +                {
  316. +                    char buffer[20];
  317. +                    sprintf(buffer, "CLA=%i;", (int)pClass);
  318. +                    msg += buffer;
  319. +                    break;
  320. +                }
  321. +                case SPECTATOR_PREFIX_MAXHP:
  322. +                {
  323. +                    char buffer[30];
  324. +                    sprintf(buffer, "MHP=%i;", maxHP);
  325. +                    msg += buffer;
  326. +                    break;
  327. +                }
  328. +                case SPECTATOR_PREFIX_CURHP:
  329. +                {
  330. +                    char buffer[30];
  331. +                    sprintf(buffer, "CHP=%i;", currHP);
  332. +                    msg += buffer;
  333. +                    break;
  334. +                }
  335. +                case SPECTATOR_PREFIX_MAXPOWER:
  336. +                {
  337. +                    char buffer[30];
  338. +                    sprintf(buffer, "MPW=%i;", maxPower);
  339. +                    msg += buffer;
  340. +                    break;
  341. +                }
  342. +                case SPECTATOR_PREFIX_CURPOWER:
  343. +                {
  344. +                    char buffer[30];
  345. +                    sprintf(buffer, "CPW=%i;", currPower);
  346. +                    msg += buffer;
  347. +                    break;
  348. +                }
  349. +                case SPECTATOR_PREFIX_POWERTYPE:
  350. +                {
  351. +                    char buffer[20];
  352. +                    sprintf(buffer, "PWT=%i;", (uint8)powerType);
  353. +                    msg += buffer;
  354. +                    break;
  355. +                }
  356. +                case SPECTATOR_PREFIX_SPELL:
  357. +                {
  358. +                    char buffer[80];
  359. +                    sprintf(buffer, "SPE=%i,%i;", spellId, castTime);
  360. +                    msg += buffer;
  361. +                    break;
  362. +                }
  363. +                case SPECTATOR_PREFIX_AURA:
  364. +                {
  365. +                    char buffer[300];
  366. +                    sprintf(buffer, "AUR=%i,%i,%i,%i,%i,%i,%i,0x%X;", aRemove,   aStack,
  367. +                                                                    aExpire,   aDuration,
  368. +                                                                    aSpellId,  aType,
  369. +                                                                    aIsDebuff, aCaster);
  370. +                    msg += buffer;
  371. +                    break;
  372. +                }
  373. +            }
  374. +        }
  375. +
  376. +    if (msg != "")
  377. +        addonData = "ARENASPEC " + msg;
  378. +
  379. +    return addonData;
  380. +}
  381. +
  382. +bool SpectatorAddonMsg::SendPacket(ObjectGuid receiver)
  383. +{
  384. +   std::string addonData = GetMsgData();
  385. +   if (addonData == "")
  386. +       return false;
  387. +
  388. +   Player* rPlayer = ObjectAccessor::FindPlayer(receiver);
  389. +   if (!rPlayer)
  390. +       return false;
  391. +
  392. +   WorldPacket data(SMSG_MESSAGECHAT, 200);
  393. +   data << uint8(CHAT_MSG_WHISPER);
  394. +   data << uint32(LANG_ADDON);
  395. +   data << uint64(0);
  396. +   data << uint32(LANG_ADDON);                               //language 2.1.0 ?
  397. +   data << uint64(0);
  398. +   data << uint32(addonData.length() + 1);
  399. +   data << addonData;
  400. +   data << uint8(CHAT_TAG_NONE);
  401. +   rPlayer->GetSession()->SendPacket(&data);
  402. +
  403. +   return true;
  404. +}
  405. +
  406. +bool SpectatorAddonMsg::SendPacket(SpectatorAddonMsg msg, ObjectGuid receiver)
  407. +{
  408. +   std::string addonData = msg.GetMsgData();
  409. +   if (addonData == "")
  410. +       return false;
  411. +
  412. +   Player* rPlayer = ObjectAccessor::FindPlayer(receiver);
  413. +   if (!rPlayer)
  414. +       return false;
  415. +
  416. +   WorldPacket data(SMSG_MESSAGECHAT, 200);
  417. +   data << uint8(CHAT_MSG_WHISPER);
  418. +   data << uint32(LANG_ADDON);
  419. +   data << uint64(0);
  420. +   data << uint32(LANG_ADDON);                               //language 2.1.0 ?
  421. +   data << uint64(0);
  422. +   data << uint32(addonData.length() + 1);
  423. +   data << addonData;
  424. +   data << uint8(CHAT_TAG_NONE);
  425. +   rPlayer->GetSession()->SendPacket(&data);
  426. +
  427. +   return true;
  428. +}
  429. \ No newline at end of file
  430. diff --git a/src/server/game/Battlegrounds/SpectatorAddon.h b/src/server/game/Battlegrounds/SpectatorAddon.h
  431. new file mode 100644
  432. index 0000000..21f44c4
  433. --- /dev/null
  434. +++ b/src/server/game/Battlegrounds/SpectatorAddon.h
  435. @@ -0,0 +1,96 @@
  436. +/*
  437. + * Copyright (C) 2008-2012 TrinityCore <http://www.trinitycore.org/>
  438. + * Copyright (C) 2005-2009 MaNGOS <http://getmangos.com/>
  439. + *
  440. + * This program is free software; you can redistribute it and/or modify it
  441. + * under the terms of the GNU General Public License as published by the
  442. + * Free Software Foundation; either version 2 of the License, or (at your
  443. + * option) any later version.
  444. + *
  445. + * This program is distributed in the hope that it will be useful, but WITHOUT
  446. + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
  447. + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
  448. + * more details.
  449. + *
  450. + * You should have received a copy of the GNU General Public License along
  451. + * with this program. If not, see <http://www.gnu.org/licenses/>.
  452. + */
  453. +
  454. +#define SPECTATOR_ADDON_SPELL_INTERUPTED 99999 // specific addons
  455. +#define SPECTATOR_ADDON_SPELL_CANCELED 99998   // numbers =\
  456. +
  457. +
  458. +enum SpectatorPrefix {
  459. +   SPECTATOR_PREFIX_PLAYER,
  460. +   SPECTATOR_PREFIX_STATUS,
  461. +   SPECTATOR_PREFIX_MAXHP,
  462. +   SPECTATOR_PREFIX_CURHP,
  463. +   SPECTATOR_PREFIX_MAXPOWER,
  464. +   SPECTATOR_PREFIX_CURPOWER,
  465. +   SPECTATOR_PREFIX_POWERTYPE,
  466. +   SPECTATOR_PREFIX_TARGET,
  467. +   SPECTATOR_PREFIX_CLASS,
  468. +   SPECTATOR_PREFIX_TEAM,
  469. +   SPECTATOR_PREFIX_SPELL,
  470. +   SPECTATOR_PREFIX_AURA,
  471. +   SPECTATOR_PREFIX_COUNT      // must be at the end of list
  472. +};
  473. +
  474. +class SpectatorAddonMsg {
  475. +    public:
  476. +        SpectatorAddonMsg();
  477. +
  478. +        void SetPlayer(std::string _player)     { player    = _player;  EnableFlag(SPECTATOR_PREFIX_PLAYER); }
  479. +        void SetStatus(bool _isAlive)           { isAlive   = _isAlive; EnableFlag(SPECTATOR_PREFIX_STATUS); }
  480. +        void SetClass(uint8 _class)             { pClass    = _class;   EnableFlag(SPECTATOR_PREFIX_CLASS); }
  481. +        void SetTarget(std::string _target)     { target    = _target;  EnableFlag(SPECTATOR_PREFIX_TARGET); }
  482. +        void SetTeam(uint32 _team)              { team      = _team;    EnableFlag(SPECTATOR_PREFIX_TEAM); }
  483. +
  484. +        void SetMaxHP(uint16 hp)                { maxHP     = hp; EnableFlag(SPECTATOR_PREFIX_MAXHP); }
  485. +        void SetCurrentHP(uint16 hp)            { currHP    = hp; EnableFlag(SPECTATOR_PREFIX_CURHP);  }
  486. +        void SetMaxPower(uint16 power)          { maxPower  = power; EnableFlag(SPECTATOR_PREFIX_MAXPOWER); }
  487. +        void SetCurrentPower(uint16 power)      { currPower = power; EnableFlag(SPECTATOR_PREFIX_CURPOWER); }
  488. +        void SetPowerType(Powers power)         { powerType = power; EnableFlag(SPECTATOR_PREFIX_POWERTYPE); }
  489. +
  490. +        void CastSpell(uint32 _spellId, uint32 _castTime) { spellId = _spellId; castTime = _castTime; EnableFlag(SPECTATOR_PREFIX_SPELL); }
  491. +        void CreateAura(uint32 _caster,  uint32 _spellId, bool _isDebuff, uint8 _type, int32 _duration, int32 _expire, uint16 _stack, bool _isRemove);
  492. +
  493. +        static bool SendPacket(SpectatorAddonMsg msg, ObjectGuid receiver);
  494. +        bool SendPacket(ObjectGuid receiver);
  495. +
  496. +        std::string GetMsgData();
  497. +
  498. +        bool isFilledIn(uint8 prefix) { return prefixFlags[prefix]; }
  499. +
  500. +        static bool CanSandAura(uint32 auraID);
  501. +    private:
  502. +
  503. +        void EnableFlag(uint8 prefix) { prefixFlags[prefix] = true; }
  504. +        std::string player;
  505. +        bool isAlive;
  506. +        std::string target;
  507. +        uint8 pClass;
  508. +
  509. +        uint16 maxHP;
  510. +        uint16 maxPower;
  511. +        uint16 currHP;
  512. +        uint16 currPower;
  513. +        Powers powerType;
  514. +
  515. +        uint32 spellId;
  516. +        uint32 castTime;
  517. +
  518. +        uint32 team;
  519. +
  520. +        // aura data
  521. +        uint32 aCaster;
  522. +        uint32 aSpellId;
  523. +        bool aIsDebuff;
  524. +        uint8 aType;
  525. +        int32 aDuration;
  526. +        int32 aExpire;
  527. +        uint16 aStack;
  528. +        bool aRemove;
  529. +
  530. +        bool prefixFlags[SPECTATOR_PREFIX_COUNT];
  531. +};
  532. diff --git a/src/server/game/Entities/GameObject/GameObject.cpp b/src/server/game/Entities/GameObject/GameObject.cpp
  533. index 6f0b9f8..aff8918 100644
  534. --- a/src/server/game/Entities/GameObject/GameObject.cpp
  535. +++ b/src/server/game/Entities/GameObject/GameObject.cpp
  536. @@ -571,6 +571,10 @@ void GameObject::Update(uint32 diff)
  537.                      }
  538.                      else if (Unit* target = ObjectAccessor::GetUnit(*this, m_lootStateUnitGUID))
  539.                      {
  540. +                        // If player is spectator do not activate.
  541. +                       if (Player *tmpPlayer = target->ToPlayer())
  542. +                            if (tmpPlayer->IsSpectator())
  543. +                                return;
  544.                          // Some traps do not have a spell but should be triggered
  545.                          if (goInfo->trap.spellId)
  546.                              CastSpell(target, goInfo->trap.spellId);
  547. @@ -1774,6 +1778,11 @@ void GameObject::Use(Unit* user)
  548.  
  549.  void GameObject::CastSpell(Unit* target, uint32 spellId, bool triggered /*= true*/)
  550.  {
  551. +   if (target)
  552. +        if (Player *tmpPlayer = target->ToPlayer())
  553. +            if (tmpPlayer->IsSpectator())
  554. +                return;
  555. +          
  556.      SpellInfo const* spellInfo = sSpellMgr->GetSpellInfo(spellId);
  557.      if (!spellInfo)
  558.          return;
  559. diff --git a/src/server/game/Entities/Player/Player.cpp b/src/server/game/Entities/Player/Player.cpp
  560. index 15c2c47..9d15b81 100644
  561. --- a/src/server/game/Entities/Player/Player.cpp
  562. +++ b/src/server/game/Entities/Player/Player.cpp
  563. @@ -555,6 +555,11 @@ Player::Player(WorldSession* session): Unit(true)
  564.      m_MonthlyQuestChanged = false;
  565.  
  566.      m_SeasonalQuestChanged = false;
  567. +  
  568. +    // Arena Spectator
  569. +   spectatorFlag = false;
  570. +   spectateCanceled = false;
  571. +   spectateFrom = NULL;
  572.  
  573.      SetPendingBind(0, 0);
  574.  
  575. @@ -2084,7 +2089,17 @@ bool Player::TeleportToBGEntryPoint()
  576.      ScheduleDelayedOperation(DELAYED_BG_MOUNT_RESTORE);
  577.      ScheduleDelayedOperation(DELAYED_BG_TAXI_RESTORE);
  578.      ScheduleDelayedOperation(DELAYED_BG_GROUP_RESTORE);
  579. -    return TeleportTo(m_bgData.joinPos);
  580. +    //return TeleportTo(m_bgData.joinPos);
  581. +    Battleground *oldBg = GetBattleground();
  582. +    bool result = TeleportTo(m_bgData.joinPos);
  583. +
  584. +    if (IsSpectator() && result)
  585. +    {
  586. +        SetSpectate(false);
  587. +        if (oldBg)
  588. +            oldBg->RemoveSpectator(GetGUID());
  589. +    }
  590. +    return result;
  591.  }
  592.  
  593.  void Player::ProcessDelayedOperations()
  594. @@ -23978,6 +23993,15 @@ void Player::SetViewpoint(WorldObject* target, bool apply)
  595.  {
  596.      if (apply)
  597.      {
  598. +       if (target->ToPlayer() == this)
  599. +            return;
  600. +
  601. +        //remove Viewpoint if already have
  602. +        if (IsSpectator() && spectateFrom)
  603. +        {
  604. +            SetViewpoint(spectateFrom, false);
  605. +            spectateFrom = NULL;
  606. +        }
  607.          TC_LOG_DEBUG("maps", "Player::CreateViewpoint: Player %s create seer %u (TypeId: %u).", GetName().c_str(), target->GetEntry(), target->GetTypeId());
  608.  
  609.          if (!AddGuidValue(PLAYER_FARSIGHT, target->GetGUID()))
  610. @@ -24007,6 +24031,9 @@ void Player::SetViewpoint(WorldObject* target, bool apply)
  611.  
  612.          //must immediately set seer back otherwise may crash
  613.          m_seer = this;
  614. +      
  615. +       if (IsSpectator())
  616. +            spectateFrom = NULL;
  617.  
  618.          //WorldPacket data(SMSG_CLEAR_FAR_SIGHT_IMMEDIATE, 0);
  619.          //GetSession()->SendPacket(&data);
  620. @@ -26485,3 +26512,88 @@ void Player::RemoveRestFlag(RestFlag restFlag)
  621.          RemoveFlag(PLAYER_FLAGS, PLAYER_FLAGS_RESTING);
  622.      }
  623.  }
  624. +
  625. +void Player::SetSelection(ObjectGuid guid)
  626. +{
  627. +    uint32 m_curSelection = guid;
  628. +    SetUInt64Value(UNIT_FIELD_TARGET, guid);
  629. +}
  630. +
  631. +void Player::SetSpectate(bool on)
  632. +{
  633. +    if (on)
  634. +    {
  635. +        SetSpeed(MOVE_RUN, 5.0);
  636. +        spectatorFlag = true;
  637. +
  638. +        m_ExtraFlags |= PLAYER_EXTRA_GM_ON;
  639. +        setFaction(35);
  640. +
  641. +        if (Pet* pet = GetPet())
  642. +        {
  643. +            RemovePet(pet, PET_SAVE_AS_CURRENT);
  644. +        }
  645. +        UnsummonPetTemporaryIfAny();
  646. +
  647. +        RemoveByteFlag(UNIT_FIELD_BYTES_2, 1, UNIT_BYTE2_FLAG_FFA_PVP);
  648. +        ResetContestedPvP();
  649. +
  650. +        getHostileRefManager().setOnlineOfflineState(false);
  651. +        CombatStopWithPets();
  652. +
  653. +        m_serverSideVisibility.SetValue(SERVERSIDE_VISIBILITY_GM, SEC_ADMINISTRATOR);
  654. +    }
  655. +    else
  656. +    {
  657. +        uint32 newPhase = 0;
  658. +        AuraEffectList const& phases = GetAuraEffectsByType(SPELL_AURA_PHASE);
  659. +        if (!phases.empty())
  660. +            for (AuraEffectList::const_iterator itr = phases.begin(); itr != phases.end(); ++itr)
  661. +                newPhase |= (*itr)->GetMiscValue();
  662. +
  663. +        if (!newPhase)
  664. +            newPhase = PHASEMASK_NORMAL;
  665. +
  666. +        SetPhaseMask(newPhase, false);
  667. +
  668. +        m_ExtraFlags &= ~ PLAYER_EXTRA_GM_ON;
  669. +        setFactionForRace(getRace());
  670. +        RemoveFlag(PLAYER_FLAGS, PLAYER_FLAGS_GM);
  671. +        RemoveFlag(UNIT_FIELD_FLAGS_2, UNIT_FLAG2_ALLOW_CHEAT_SPELLS);
  672. +
  673. +        if (spectateFrom)
  674. +            SetViewpoint(spectateFrom, false);
  675. +
  676. +        // restore FFA PvP Server state
  677. +        if (sWorld->IsFFAPvPRealm())
  678. +            SetByteFlag(UNIT_FIELD_BYTES_2, 1, UNIT_BYTE2_FLAG_FFA_PVP);
  679. +
  680. +        // restore FFA PvP area state, remove not allowed for GM mounts
  681. +        UpdateArea(m_areaUpdateId);
  682. +
  683. +        getHostileRefManager().setOnlineOfflineState(true);
  684. +        m_serverSideVisibility.SetValue(SERVERSIDE_VISIBILITY_GM, SEC_PLAYER);
  685. +        spectateCanceled = false;
  686. +        spectatorFlag = false;
  687. +        RestoreDisplayId();
  688. +        UpdateSpeed(MOVE_RUN, true);
  689. +    }
  690. +    UpdateObjectVisibility();
  691. +}
  692. +
  693. +bool Player::HaveSpectators()
  694. +{
  695. +    if (IsSpectator())
  696. +        return false;
  697. +
  698. +    if (Battleground *bg = GetBattleground())
  699. +        if (bg->isArena())
  700. +        {
  701. +            if (bg->GetStatus() != STATUS_IN_PROGRESS)
  702. +                return false;
  703. +
  704. +            return bg->HaveSpectators();
  705. +        }
  706. +
  707. +        return false;
  708. +}
  709. diff --git a/src/server/game/Entities/Player/Player.h b/src/server/game/Entities/Player/Player.h
  710. index b7d7d81..f1f5cbb 100644
  711. --- a/src/server/game/Entities/Player/Player.h
  712. +++ b/src/server/game/Entities/Player/Player.h
  713. @@ -1085,6 +1085,14 @@ class Player : public Unit, public GridObject<Player>
  714.          bool Has310Flyer(bool checkAllSpells, uint32 excludeSpellId = 0);
  715.          void SetHas310Flyer(bool on) { if (on) m_ExtraFlags |= PLAYER_EXTRA_HAS_310_FLYER; else m_ExtraFlags &= ~PLAYER_EXTRA_HAS_310_FLYER; }
  716.          void SetPvPDeath(bool on) { if (on) m_ExtraFlags |= PLAYER_EXTRA_PVP_DEATH; else m_ExtraFlags &= ~PLAYER_EXTRA_PVP_DEATH; }
  717. +      
  718. +       // Arena Spectator
  719. +       bool HaveSpectators();
  720. +        bool isSpectateCanceled() { return spectateCanceled; }
  721. +        void CancelSpectate() { spectateCanceled = true; }
  722. +        Unit* getSpectateFrom() { return spectateFrom; }
  723. +        bool IsSpectator() const { return spectatorFlag; }
  724. +        void SetSpectate(bool on);
  725.  
  726.          void GiveXP(uint32 xp, Unit* victim, float group_rate=1.0f);
  727.          void GiveLevel(uint8 level);
  728. @@ -1453,7 +1461,8 @@ class Player : public Unit, public GridObject<Player>
  729.          Player* GetSelectedPlayer() const;
  730.  
  731.          void SetTarget(ObjectGuid /*guid*/) override { } /// Used for serverside target changes, does not apply to players
  732. -        void SetSelection(ObjectGuid guid) { SetGuidValue(UNIT_FIELD_TARGET, guid); }
  733. +        //void SetSelection(ObjectGuid guid) { SetGuidValue(UNIT_FIELD_TARGET, guid); }
  734. +       void SetSelection(ObjectGuid guid);
  735.  
  736.          uint8 GetComboPoints() const { return m_comboPoints; }
  737.          ObjectGuid GetComboTarget() const { return m_comboTarget; }
  738. @@ -2583,6 +2592,10 @@ class Player : public Unit, public GridObject<Player>
  739.          InstanceTimeMap _instanceResetTimes;
  740.          uint32 _pendingBindId;
  741.          uint32 _pendingBindTimer;
  742. +      
  743. +       bool spectatorFlag;
  744. +        bool spectateCanceled;
  745. +        Unit *spectateFrom;
  746.  
  747.          uint32 _activeCheats;
  748.  
  749. diff --git a/src/server/game/Entities/Unit/Unit.cpp b/src/server/game/Entities/Unit/Unit.cpp
  750. index a826f84..fae8c5b 100644
  751. --- a/src/server/game/Entities/Unit/Unit.cpp
  752. +++ b/src/server/game/Entities/Unit/Unit.cpp
  753. @@ -291,6 +291,19 @@ Unit::~Unit()
  754.              m_currentSpells[i]->SetReferencedFromCurrent(false);
  755.              m_currentSpells[i] = NULL;
  756.          }
  757. +      
  758. +   // remove view point for spectator
  759. +    if (!m_sharedVision.empty())
  760. +    {
  761. +        for (SharedVisionList::iterator itr = m_sharedVision.begin(); itr != m_sharedVision.end(); ++itr)
  762. +            if ((*itr)->IsSpectator() && (*itr)->getSpectateFrom())
  763. +            {
  764. +                (*itr)->SetViewpoint((*itr)->getSpectateFrom(), false);
  765. +                if (m_sharedVision.empty())
  766. +                    break;
  767. +                --itr;
  768. +            }
  769. +    }
  770.  
  771.      _DeleteRemovedAuras();
  772.  
  773. diff --git a/src/server/game/Handlers/ChatHandler.cpp b/src/server/game/Handlers/ChatHandler.cpp
  774. index f7fd9c8..0fdba1e 100644
  775. --- a/src/server/game/Handlers/ChatHandler.cpp
  776. +++ b/src/server/game/Handlers/ChatHandler.cpp
  777. @@ -574,6 +574,12 @@ void WorldSession::HandleTextEmoteOpcode(WorldPacket& recvData)
  778.      recvData >> text_emote;
  779.      recvData >> emoteNum;
  780.      recvData >> guid;
  781. +  
  782. +   if (GetPlayer()->IsSpectator())
  783. +    {
  784. +        SendNotification(LANG_SPEC_CAN_NOT_CHAT);
  785. +        return;
  786. +    }
  787.  
  788.      sScriptMgr->OnPlayerTextEmote(GetPlayer(), text_emote, emoteNum, guid);
  789.  
  790. diff --git a/src/server/game/Maps/Map.cpp b/src/server/game/Maps/Map.cpp
  791. index a2cb843..7c8cc9e 100644
  792. --- a/src/server/game/Maps/Map.cpp
  793. +++ b/src/server/game/Maps/Map.cpp
  794. @@ -3347,6 +3347,13 @@ bool BattlegroundMap::AddPlayerToMap(Player* player)
  795.  
  796.  void BattlegroundMap::RemovePlayerFromMap(Player* player, bool remove)
  797.  {
  798. +   if (player && player->IsSpectator() && !player->isSpectateCanceled())
  799. +    {
  800. +        if (GetBG())
  801. +            GetBG()->RemoveSpectator(player->GetGUID());
  802. +        player->SetSpectate(false);
  803. +    }
  804. +  
  805.      TC_LOG_DEBUG("maps", "MAP: Removing player '%s' from bg '%u' of map '%s' before relocating to another map", player->GetName().c_str(), GetInstanceId(), GetMapName());
  806.      Map::RemovePlayerFromMap(player, remove);
  807.  }
  808. diff --git a/src/server/game/Miscellaneous/Language.h b/src/server/game/Miscellaneous/Language.h
  809. index 73a9905..cc579b4 100644
  810. --- a/src/server/game/Miscellaneous/Language.h
  811. +++ b/src/server/game/Miscellaneous/Language.h
  812. @@ -854,6 +854,9 @@ enum TrinityStrings
  813.      LANG_ACCOUNT_SEC_TYPE               = 880,
  814.      LANG_RBAC_EMAIL_REQUIRED            = 881,
  815.      // Room for in-game strings           882-999 not used
  816. +  
  817. +   // Arena Spectator
  818. +    LANG_SPEC_CAN_NOT_CHAT = 900,
  819.  
  820.      // Level 4 (CLI only commands)
  821.      LANG_COMMAND_EXIT                   = 1000,
  822. diff --git a/src/server/game/Spells/Spell.cpp b/src/server/game/Spells/Spell.cpp
  823. index 84bff4a..059d6ff 100644
  824. --- a/src/server/game/Spells/Spell.cpp
  825. +++ b/src/server/game/Spells/Spell.cpp
  826. @@ -4736,6 +4736,10 @@ SpellCastResult Spell::CheckCast(bool strict)
  827.                  m_caster->GetMap()->IsOutdoors(m_caster->GetPositionX(), m_caster->GetPositionY(), m_caster->GetPositionZ()))
  828.              return SPELL_FAILED_ONLY_INDOORS;
  829.      }
  830. +  
  831. +   if (Player *tmpPlayer = m_caster->ToPlayer())
  832. +        if (tmpPlayer->IsSpectator())
  833. +            return SPELL_FAILED_SPELL_UNAVAILABLE;
  834.  
  835.      // only check at first call, Stealth auras are already removed at second call
  836.      // for now, ignore triggered spells
  837. diff --git a/src/server/scripts/Commands/cs_gm.cpp b/src/server/scripts/Commands/cs_gm.cpp
  838. index e03942b..fc48f27 100644
  839. --- a/src/server/scripts/Commands/cs_gm.cpp
  840. +++ b/src/server/scripts/Commands/cs_gm.cpp
  841. @@ -131,6 +131,9 @@ public:
  842.                   itrSec <= AccountTypes(sWorld->getIntConfig(CONFIG_GM_LEVEL_IN_GM_LIST)))) &&
  843.                  (!handler->GetSession() || itr->second->IsVisibleGloballyFor(handler->GetSession()->GetPlayer())))
  844.              {
  845. +               if (itr->second->IsSpectator())
  846. +                   continue; // don't show spectators, they're not really gms
  847. +              
  848.                  if (first)
  849.                  {
  850.                      first = false;
  851. diff --git a/src/server/scripts/Custom/ArenaSpectator/README.md b/src/server/scripts/Custom/ArenaSpectator/README.md
  852. new file mode 100644
  853. index 0000000..abbb7a5
  854. --- /dev/null
  855. +++ b/src/server/scripts/Custom/ArenaSpectator/README.md
  856. @@ -0,0 +1,33 @@
  857. +#Arena Spectator
  858. +
  859. +####About
  860. +Arena Spectator gives you the
  861. +oportunity to spectate players when
  862. +they are in arena.You can spectate a
  863. +2vs2 / 3vs3 / 5vs5 / Specific Player arena.
  864. +
  865. +
  866. +####Installation
  867. +
  868. +Available as:
  869. +- Direct merge: https://github.com/Flameshot/TrinityCore/tree/Arena-Spectator
  870. +- Diff/Patch: http://flameshot.tk/ipbdownload/Arena-Spectator.diff
  871. +
  872. +Using direct merge:
  873. +- open git bash to source location
  874. +- do `git remote add flameshot https://github.com/Flameshot/TrinityCore.git`
  875. +- do `git pull flameshot arena-spectator`
  876. +- use cmake and compile
  877. +
  878. +Using diff:
  879. +- download the diff by __right clicking__ the link and select __Save link as__
  880. +- place the downloaded `arena-spectator.diff` to the source root folder
  881. +- open git bash to source location
  882. +- do `git apply arena-spectator.diff`
  883. +- use cmake and compile
  884. +
  885. +After compiling:
  886. +- Navigate to `\src\server\scripts\Custom\ArenaSpectator\sql\`
  887. +- Run `Arena Spectator NPC.sql` to your world database
  888. +- Run `rbac_permissions.sql` to your auth database
  889. +- Run `rbac_linked_permissions.sql` to your auth database
  890. \ No newline at end of file
  891. diff --git a/src/server/scripts/Custom/ArenaSpectator/arena_spectator.cpp b/src/server/scripts/Custom/ArenaSpectator/arena_spectator.cpp
  892. new file mode 100644
  893. index 0000000..7eeed69
  894. --- /dev/null
  895. +++ b/src/server/scripts/Custom/ArenaSpectator/arena_spectator.cpp
  896. @@ -0,0 +1,643 @@
  897. +/*
  898. +* Copyright (C) 2008-2012 TrinityCore <http://www.trinitycore.org/>
  899. +* Copyright (C) 2006-2009 ScriptDev2 <https://scriptdev2.svn.sourceforge.net/>
  900. +*
  901. +* This program is free software; you can redistribute it and/or modify it
  902. +* under the terms of the GNU General Public License as published by the
  903. +* Free Software Foundation; either version 2 of the License, or (at your
  904. +* option) any later version.
  905. +*
  906. +* This program is distributed in the hope that it will be useful, but WITHOUT
  907. +* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
  908. +* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
  909. +* more details.
  910. +*
  911. +* You should have received a copy of the GNU General Public License along
  912. +* with this program. If not, see <http://www.gnu.org/licenses/>.
  913. +*/
  914. +
  915. +/* ScriptData
  916. +Name: Arena Spectator
  917. +%Complete: 100
  918. +Comment: Script allow spectate arena games
  919. +Category: Custom Script
  920. +Copyright: Flameshot
  921. +EndScriptData */
  922. +
  923. +#include "Chat.h"
  924. +#include "ArenaTeamMgr.h"
  925. +#include "BattlegroundMgr.h"
  926. +#include "WorldSession.h"
  927. +#include "Player.h"
  928. +#include "ArenaTeam.h"
  929. +#include "Battleground.h"
  930. +#include "BattlegroundMgr.h"
  931. +#include "CreatureTextMgr.h"
  932. +#include "Config.h"
  933. +#include "ScriptedGossip.h"
  934. +#include "ScriptMgr.h"
  935. +
  936. +int8 UsingGossip;
  937. +
  938. +class arena_spectator_commands : public CommandScript
  939. +{
  940. +public:
  941. +   arena_spectator_commands() : CommandScript("arena_spectator_commands") { }
  942. +
  943. +   static bool HandleSpectateCommand(ChatHandler* handler, char const* args)
  944. +   {
  945. +       Player* target;
  946. +       ObjectGuid target_guid;
  947. +       std::string target_name;
  948. +       if (!handler->extractPlayerTarget((char*)args, &target, &target_guid, &target_name))
  949. +           return false;
  950. +
  951. +       Player* player = handler->GetSession()->GetPlayer();
  952. +       if (target == player || target_guid == player->GetGUID())
  953. +       {
  954. +           handler->PSendSysMessage("You can't spectate yourself.");
  955. +           handler->SetSentErrorMessage(true);
  956. +           return false;
  957. +       }
  958. +
  959. +       if (player->IsInCombat())
  960. +       {
  961. +           handler->PSendSysMessage("You are in combat.");
  962. +           handler->SetSentErrorMessage(true);
  963. +           return false;
  964. +       }
  965. +
  966. +       if (!target)
  967. +       {
  968. +           handler->PSendSysMessage("Target is not online or does not exist.");
  969. +           handler->SetSentErrorMessage(true);
  970. +           return false;
  971. +       }
  972. +
  973. +       if (player->GetPet())
  974. +       {
  975. +           handler->PSendSysMessage("You must hide your pet.");
  976. +           handler->SetSentErrorMessage(true);
  977. +           return false;
  978. +       }
  979. +
  980. +       if (player->GetMap()->IsBattlegroundOrArena() && !player->IsSpectator())
  981. +       {
  982. +           handler->PSendSysMessage("You are already in a battleground or arena.");
  983. +           handler->SetSentErrorMessage(true);
  984. +           return false;
  985. +       }
  986. +
  987. +       Map* cMap = target->GetMap();
  988. +       if (!cMap->IsBattleArena())
  989. +       {
  990. +           handler->PSendSysMessage("Player is not in an Arena match.");
  991. +           handler->SetSentErrorMessage(true);
  992. +           return false;
  993. +       }
  994. +
  995. +       if (player->GetMap()->IsBattleground())
  996. +       {
  997. +           handler->PSendSysMessage("You can't do that while in a battleground.");
  998. +           handler->SetSentErrorMessage(true);
  999. +           return false;
  1000. +       }
  1001. +
  1002. +       if (target->HasAura(32728) || target->HasAura(32727))
  1003. +       {
  1004. +           handler->PSendSysMessage("You can't do that. The Arena match didn't start yet.");
  1005. +           handler->SetSentErrorMessage(true);
  1006. +           return false;
  1007. +       }
  1008. +
  1009. +       if (target->IsSpectator())
  1010. +       {
  1011. +           handler->PSendSysMessage("You can't do that. Your target is a spectator.");
  1012. +           handler->SetSentErrorMessage(true);
  1013. +           return false;
  1014. +       }
  1015. +
  1016. +       if (player->IsMounted())
  1017. +       {
  1018. +           handler->PSendSysMessage("Cannot Spectate while mounted.");
  1019. +           handler->SetSentErrorMessage(true);
  1020. +           return false;
  1021. +       }
  1022. +
  1023. +       // all's well, set bg id
  1024. +       // when porting out from the bg, it will be reset to 0
  1025. +       player->SetBattlegroundId(target->GetBattlegroundId(), target->GetBattlegroundTypeId());
  1026. +       // remember current position as entry point for return at bg end teleportation
  1027. +       if (!player->GetMap()->IsBattlegroundOrArena())
  1028. +           player->SetBattlegroundEntryPoint();
  1029. +
  1030. +       // stop flight if need
  1031. +       if (player->IsInFlight())
  1032. +       {
  1033. +           player->GetMotionMaster()->MovementExpired();
  1034. +           player->CleanupAfterTaxiFlight();
  1035. +       }
  1036. +       // save only in non-flight case
  1037. +       else
  1038. +           player->SaveRecallPosition();
  1039. +
  1040. +       // search for two teams
  1041. +       Battleground *bGround = target->GetBattleground();
  1042. +       if (bGround->isRated())
  1043. +       {
  1044. +           uint32 slot = bGround->GetArenaType() - 2;
  1045. +           if (bGround->GetArenaType() > 3)
  1046. +               slot = 2;
  1047. +           uint32 firstTeamID = target->GetArenaTeamId(slot);
  1048. +           uint32 secondTeamID = 0;
  1049. +           Player *firstTeamMember = target;
  1050. +           Player *secondTeamMember = NULL;
  1051. +           for (Battleground::BattlegroundPlayerMap::const_iterator itr = bGround->GetPlayers().begin(); itr != bGround->GetPlayers().end(); ++itr)
  1052. +               if (Player* tmpPlayer = ObjectAccessor::FindPlayer(itr->first))
  1053. +               {
  1054. +                   if (tmpPlayer->IsSpectator())
  1055. +                       continue;
  1056. +
  1057. +                   uint32 tmpID = tmpPlayer->GetArenaTeamId(slot);
  1058. +                   if (tmpID != firstTeamID && tmpID > 0)
  1059. +                   {
  1060. +                       secondTeamID = tmpID;
  1061. +                       secondTeamMember = tmpPlayer;
  1062. +                       break;
  1063. +                   }
  1064. +               }
  1065. +
  1066. +           if (firstTeamID > 0 && secondTeamID > 0 && secondTeamMember)
  1067. +           {
  1068. +               ArenaTeam *firstTeam = sArenaTeamMgr->GetArenaTeamById(firstTeamID);
  1069. +               ArenaTeam *secondTeam = sArenaTeamMgr->GetArenaTeamById(secondTeamID);
  1070. +               if (firstTeam && secondTeam)
  1071. +               {
  1072. +                   handler->PSendSysMessage("You entered a Rated Arena.");
  1073. +                   handler->PSendSysMessage("Teams:");
  1074. +                   handler->PSendSysMessage("|cFFffffff%s|r vs |cFFffffff%s|r", firstTeam->GetName().c_str(), secondTeam->GetName().c_str());
  1075. +                   handler->PSendSysMessage("|cFFffffff%u(%u)|r -- |cFFffffff%u(%u)|r", firstTeam->GetRating(), firstTeam->GetAverageMMR(firstTeamMember->GetGroup()),
  1076. +                       secondTeam->GetRating(), secondTeam->GetAverageMMR(secondTeamMember->GetGroup()));
  1077. +               }
  1078. +           }
  1079. +       }
  1080. +
  1081. +       // to point to see at target with same orientation
  1082. +       float x, y, z;
  1083. +       target->GetContactPoint(player, x, y, z);
  1084. +
  1085. +       player->TeleportTo(target->GetMapId(), x, y, z, player->GetAngle(target), TELE_TO_GM_MODE);
  1086. +       player->SetPhaseMask(target->GetPhaseMask(), true);
  1087. +       player->SetSpectate(true);
  1088. +       target->GetBattleground()->AddSpectator(player->GetGUID());
  1089. +
  1090. +       return true;
  1091. +   }
  1092. +
  1093. +   static bool HandleSpectateCancelCommand(ChatHandler* handler, const char* /*args*/)
  1094. +   {
  1095. +       Player* player = handler->GetSession()->GetPlayer();
  1096. +
  1097. +       if (!player->IsSpectator())
  1098. +       {
  1099. +           handler->PSendSysMessage("You are not a spectator.");
  1100. +           handler->SetSentErrorMessage(true);
  1101. +           return false;
  1102. +       }
  1103. +
  1104. +       player->GetBattleground()->RemoveSpectator(player->GetGUID());
  1105. +       player->CancelSpectate();
  1106. +       player->TeleportToBGEntryPoint();
  1107. +
  1108. +       return true;
  1109. +   }
  1110. +
  1111. +   static bool HandleSpectateFromCommand(ChatHandler* handler, const char *args)
  1112. +   {
  1113. +       Player* target;
  1114. +       ObjectGuid target_guid;
  1115. +       std::string target_name;
  1116. +       if (!handler->extractPlayerTarget((char*)args, &target, &target_guid, &target_name))
  1117. +           return false;
  1118. +
  1119. +       Player* player = handler->GetSession()->GetPlayer();
  1120. +
  1121. +       if (target->HasAuraType(SPELL_AURA_MOD_STEALTH))
  1122. +       {
  1123. +           handler->PSendSysMessage("You can't target stealthed players.");
  1124. +           handler->SetSentErrorMessage(true);
  1125. +           return false;
  1126. +       }
  1127. +
  1128. +       if (!target)
  1129. +       {
  1130. +           handler->PSendSysMessage("Player is not online or does not exist.");
  1131. +           handler->SetSentErrorMessage(true);
  1132. +           return false;
  1133. +       }
  1134. +
  1135. +       if (!player->IsSpectator())
  1136. +       {
  1137. +           handler->PSendSysMessage("You are not a spectator, spectate someone first.");
  1138. +           handler->SetSentErrorMessage(true);
  1139. +           return false;
  1140. +       }
  1141. +
  1142. +       if (target->IsSpectator() && target != player)
  1143. +       {
  1144. +           handler->PSendSysMessage("You can't do that. Your target is a spectator.");
  1145. +           handler->SetSentErrorMessage(true);
  1146. +           return false;
  1147. +       }
  1148. +
  1149. +       if (player->GetMap() != target->GetMap())
  1150. +       {
  1151. +           handler->PSendSysMessage("You can't do that. Your target might be in a different arena match.");
  1152. +           handler->SetSentErrorMessage(true);
  1153. +           return false;
  1154. +       }
  1155. +
  1156. +       // check for arena preperation
  1157. +       // if exists than battle didn`t begin
  1158. +       if (target->HasAura(32728) || target->HasAura(32727))
  1159. +       {
  1160. +           handler->PSendSysMessage("You can't do that. The Arena match didn't start yet.");
  1161. +           handler->SetSentErrorMessage(true);
  1162. +           return false;
  1163. +       }
  1164. +
  1165. +       (target == player && player->getSpectateFrom()) ? player->SetViewpoint(player->getSpectateFrom(), false) :
  1166. +           player->SetViewpoint(target, true);
  1167. +       return true;
  1168. +   }
  1169. +
  1170. +   static bool HandleSpectateResetCommand(ChatHandler* handler, const char *args)
  1171. +   {
  1172. +       Player* player = handler->GetSession()->GetPlayer();
  1173. +
  1174. +       if (!player)
  1175. +       {
  1176. +           handler->PSendSysMessage("Cant find player.");
  1177. +           handler->SetSentErrorMessage(true);
  1178. +           return false;
  1179. +       }
  1180. +
  1181. +       if (!player->IsSpectator())
  1182. +       {
  1183. +           handler->PSendSysMessage("You are not a spectator!");
  1184. +           handler->SetSentErrorMessage(true);
  1185. +           return false;
  1186. +       }
  1187. +
  1188. +       Battleground *bGround = player->GetBattleground();
  1189. +       if (!bGround)
  1190. +           return false;
  1191. +
  1192. +       if (bGround->GetStatus() != STATUS_IN_PROGRESS)
  1193. +           return true;
  1194. +
  1195. +       for (Battleground::BattlegroundPlayerMap::const_iterator itr = bGround->GetPlayers().begin(); itr != bGround->GetPlayers().end(); ++itr)
  1196. +           if (Player* tmpPlayer = ObjectAccessor::FindPlayer(itr->first))
  1197. +           {
  1198. +               if (tmpPlayer->IsSpectator())
  1199. +                   continue;
  1200. +
  1201. +               uint32 tmpID = bGround->GetPlayerTeam(tmpPlayer->GetGUID());
  1202. +
  1203. +               // generate addon massage
  1204. +               std::string pName = tmpPlayer->GetName();
  1205. +               std::string tName = "";
  1206. +
  1207. +               if (Player *target = tmpPlayer->GetSelectedPlayer())
  1208. +                   tName = target->GetName();
  1209. +
  1210. +               SpectatorAddonMsg msg; // Travis
  1211. +               msg.SetPlayer(pName);
  1212. +               if (tName != "")
  1213. +                   msg.SetTarget(tName);
  1214. +               msg.SetStatus(tmpPlayer->IsAlive());
  1215. +               msg.SetClass(tmpPlayer->getClass());
  1216. +               msg.SetCurrentHP(tmpPlayer->GetHealth());
  1217. +               msg.SetMaxHP(tmpPlayer->GetMaxHealth());
  1218. +               Powers powerType = tmpPlayer->getPowerType();
  1219. +               msg.SetMaxPower(tmpPlayer->GetMaxPower(powerType));
  1220. +               msg.SetCurrentPower(tmpPlayer->GetPower(powerType));
  1221. +               msg.SetPowerType(powerType);
  1222. +               msg.SetTeam(tmpID);
  1223. +               msg.SendPacket(player->GetGUID());
  1224. +           }
  1225. +
  1226. +       return true;
  1227. +   }
  1228. +
  1229. +   std::vector<ChatCommand> GetCommands() const override
  1230. +   {
  1231. +       static std::vector<ChatCommand> spectateCommandTable =
  1232. +       {
  1233. +           { "player", rbac::RBAC_PERM_COMMAND_SPECTATE_PLAYER, true,     &HandleSpectateCommand, "" },
  1234. +           { "view", rbac::RBAC_PERM_COMMAND_SPECTATE_VIEW, true,     &HandleSpectateFromCommand, "" },
  1235. +           { "reset", rbac::RBAC_PERM_COMMAND_SPECTATE_RESET, true,  &HandleSpectateResetCommand, "" },
  1236. +           { "leave", rbac::RBAC_PERM_COMMAND_SPECTATE_LEAVE, true, &HandleSpectateCancelCommand, "" },
  1237. +       };
  1238. +
  1239. +       static std::vector<ChatCommand> commandTable =
  1240. +       {
  1241. +           { "spectate", rbac::RBAC_PERM_COMMAND_SPECTATE, false, NULL, "",     spectateCommandTable },
  1242. +       };
  1243. +       return commandTable;
  1244. +   }
  1245. +};
  1246. +
  1247. +
  1248. +enum NpcSpectatorAtions {
  1249. +   // will be used for scrolling
  1250. +   NPC_SPECTATOR_ACTION_2V2_GAMES = 2000,  //NPC_SPECTATOR_ACTION_LIST_GAMES = 1000,
  1251. +   NPC_SPECTATOR_ACTION_3V3_GAMES = 3000, // NPC_SPECTATOR_ACTION_LIST_TOP_GAMES = 2000,
  1252. +   NPC_SPECTATOR_ACTION_5V5_GAMES = 1000,
  1253. +   NPC_SPECTATOR_ACTION_SPECIFIC = 500,
  1254. +
  1255. +   // NPC_SPECTATOR_ACTION_SELECTED_PLAYER + player.Guid()
  1256. +   NPC_SPECTATOR_ACTION_SELECTED_PLAYER = 4000
  1257. +};
  1258. +
  1259. +const uint8  GamesOnPage = 15;
  1260. +
  1261. +class npc_arena_spectator : public CreatureScript
  1262. +{
  1263. +public:
  1264. +   npc_arena_spectator() : CreatureScript("npc_arena_spectator") { }
  1265. +
  1266. +   bool OnGossipHello(Player* pPlayer, Creature* pCreature)
  1267. +   {
  1268. +       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);
  1269. +       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);
  1270. +       pPlayer->ADD_GOSSIP_ITEM(GOSSIP_ICON_CHAT, "|TInterface\\icons\\Achievement_Arena_5v5_7:35:35:-30:0|tGames: 5v5", GOSSIP_SENDER_MAIN, NPC_SPECTATOR_ACTION_5V5_GAMES);
  1271. +       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);
  1272. +       pPlayer->SEND_GOSSIP_MENU(DEFAULT_GOSSIP_MESSAGE, pCreature->GetGUID());
  1273. +       return true;
  1274. +   }
  1275. +
  1276. +   bool OnGossipSelect(Player* player, Creature* creature, uint32 /*sender*/, uint32 action)
  1277. +   {
  1278. +       player->PlayerTalkClass->ClearMenus();
  1279. +
  1280. +       if (action == NPC_SPECTATOR_ACTION_SPECIFIC)
  1281. +       {
  1282. +
  1283. +       }
  1284. +
  1285. +       if (action >= NPC_SPECTATOR_ACTION_2V2_GAMES && action < NPC_SPECTATOR_ACTION_3V3_GAMES)
  1286. +       {
  1287. +           player->ADD_GOSSIP_ITEM(GOSSIP_ICON_DOT, " Refresh", GOSSIP_SENDER_MAIN, NPC_SPECTATOR_ACTION_2V2_GAMES);
  1288. +           ShowPage(player, action - NPC_SPECTATOR_ACTION_2V2_GAMES, ARENA_TYPE_2v2);
  1289. +           player->SEND_GOSSIP_MENU(DEFAULT_GOSSIP_MESSAGE, creature->GetGUID());
  1290. +       }
  1291. +       else if (action >= NPC_SPECTATOR_ACTION_3V3_GAMES && action < NPC_SPECTATOR_ACTION_5V5_GAMES)
  1292. +       {
  1293. +           player->ADD_GOSSIP_ITEM(GOSSIP_ICON_DOT, "Refresh", GOSSIP_SENDER_MAIN, NPC_SPECTATOR_ACTION_3V3_GAMES);
  1294. +           ShowPage(player, action - NPC_SPECTATOR_ACTION_3V3_GAMES, ARENA_TYPE_3v3);
  1295. +           player->SEND_GOSSIP_MENU(DEFAULT_GOSSIP_MESSAGE, creature->GetGUID());
  1296. +       }
  1297. +       else if (action >= NPC_SPECTATOR_ACTION_5V5_GAMES && action < NPC_SPECTATOR_ACTION_SELECTED_PLAYER)
  1298. +       {
  1299. +           player->ADD_GOSSIP_ITEM(GOSSIP_ICON_DOT, "Refresh", GOSSIP_SENDER_MAIN, NPC_SPECTATOR_ACTION_5V5_GAMES);
  1300. +           ShowPage(player, action - NPC_SPECTATOR_ACTION_5V5_GAMES, ARENA_TYPE_5v5);
  1301. +           player->SEND_GOSSIP_MENU(DEFAULT_GOSSIP_MESSAGE, creature->GetGUID());
  1302. +       }
  1303. +       else
  1304. +       {
  1305. +
  1306. +           ObjectGuid guid = ObjectGuid(HighGuid::Player, action - NPC_SPECTATOR_ACTION_SELECTED_PLAYER);
  1307. +           if (Player* target = ObjectAccessor::FindPlayer(guid))
  1308. +           {
  1309. +               ChatHandler handler(player->GetSession());
  1310. +               char const* pTarget = target->GetName().c_str();
  1311. +               arena_spectator_commands::HandleSpectateCommand(&handler, pTarget);
  1312. +           }
  1313. +       }
  1314. +       return true;
  1315. +   }
  1316. +
  1317. +   std::string GetClassNameById(uint8 id)
  1318. +   {
  1319. +       std::string sClass = "";
  1320. +       switch (id)
  1321. +       {
  1322. +       case CLASS_WARRIOR:         sClass = "Warrior ";        break;
  1323. +       case CLASS_PALADIN:         sClass = "Paladin ";        break;
  1324. +       case CLASS_HUNTER:          sClass = "Hunter ";         break;
  1325. +       case CLASS_ROGUE:           sClass = "Rogue ";          break;
  1326. +       case CLASS_PRIEST:          sClass = "Priest ";         break;
  1327. +       case CLASS_DEATH_KNIGHT:    sClass = "DKnight ";        break;
  1328. +       case CLASS_SHAMAN:          sClass = "Shaman ";         break;
  1329. +       case CLASS_MAGE:            sClass = "Mage ";           break;
  1330. +       case CLASS_WARLOCK:         sClass = "Warlock ";        break;
  1331. +       case CLASS_DRUID:           sClass = "Druid ";          break;
  1332. +       }
  1333. +       return sClass;
  1334. +   }
  1335. +
  1336. +   std::string GetGamesStringData(Battleground* team, uint16 mmr, uint16 mmrTwo)
  1337. +   {
  1338. +       std::string teamsMember[BG_TEAMS_COUNT];
  1339. +       uint32 firstTeamId = 0;
  1340. +       for (Battleground::BattlegroundPlayerMap::const_iterator itr = team->GetPlayers().begin(); itr != team->GetPlayers().end(); ++itr)
  1341. +           if (Player* player = ObjectAccessor::FindPlayer(itr->first))
  1342. +           {
  1343. +               if (player->IsSpectator())
  1344. +                   continue;
  1345. +
  1346. +               if (player->IsGameMaster())
  1347. +                   continue;
  1348. +
  1349. +               uint32 team = itr->second.Team;
  1350. +               if (!firstTeamId)
  1351. +                   firstTeamId = team;
  1352. +
  1353. +               teamsMember[firstTeamId == team] += GetClassNameById(player->getClass());
  1354. +           }
  1355. +
  1356. +       std::string data = teamsMember[0] + "(";
  1357. +       std::stringstream ss;
  1358. +       std::stringstream sstwo;
  1359. +       ss << mmr;
  1360. +       sstwo << mmrTwo;
  1361. +       data += ss.str();
  1362. +       data += ") - ";
  1363. +       data += teamsMember[1] + "(" + sstwo.str();
  1364. +       data += ")";
  1365. +       return data;
  1366. +   }
  1367. +
  1368. +   ObjectGuid GetFirstPlayerGuid(Battleground* team)
  1369. +   {
  1370. +       for (Battleground::BattlegroundPlayerMap::const_iterator itr = team->GetPlayers().begin(); itr != team->GetPlayers().end(); ++itr)
  1371. +           if (Player* player = ObjectAccessor::FindPlayer(itr->first))
  1372. +               return itr->first;
  1373. +       return ObjectGuid::Empty;
  1374. +   }
  1375. +
  1376. +   void ShowPage(Player* player, uint16 page, uint32 IsTop)
  1377. +   {      
  1378. +       uint32 firstTeamId = 0;
  1379. +       uint16 TypeOne = 0;
  1380. +       uint16 TypeTwo = 0;
  1381. +       uint16 TypeThree = 0;
  1382. +       uint16 mmr = 0;
  1383. +       uint16 mmrTwo = 0;
  1384. +       bool haveNextPage = false;
  1385. +       for (uint8 i = 0; i <= MAX_BATTLEGROUND_TYPE_ID; ++i)
  1386. +       {
  1387. +           if (!sBattlegroundMgr->IsArenaType(BattlegroundTypeId(i)))
  1388. +               continue;
  1389. +
  1390. +           //BattlegroundContainer arenas = sBattlegroundMgr->GetBattlegroundsByType((BattlegroundTypeId)i);
  1391. +           BattlegroundData* arenas = sBattlegroundMgr->GetAllBattlegroundsWithTypeId(BattlegroundTypeId(i));
  1392. +
  1393. +           if (!arenas || arenas->m_Battlegrounds.empty())
  1394. +               continue;
  1395. +
  1396. +           for (BattlegroundContainer::const_iterator itr = arenas->m_Battlegrounds.begin(); itr != arenas->m_Battlegrounds.end(); ++itr)
  1397. +           {
  1398. +               Battleground* arena = itr->second;
  1399. +               Player* target = ObjectAccessor::FindPlayer(GetFirstPlayerGuid(arena));
  1400. +               if (target && (target->HasAura(32728) || target->HasAura(32727)))
  1401. +                   continue;
  1402. +
  1403. +               if (!arena->GetPlayersSize())
  1404. +                   continue;
  1405. +
  1406. +               if (arena->GetArenaType() == ARENA_TYPE_2v2)
  1407. +               {
  1408. +                   mmr = arena->GetArenaMatchmakerRating(0);
  1409. +                   firstTeamId = target->GetArenaTeamId(0);
  1410. +                   Battleground::BattlegroundPlayerMap::const_iterator citr = arena->GetPlayers().begin();
  1411. +                   for (; citr != arena->GetPlayers().end(); ++citr)
  1412. +                       if (Player* plrs = ObjectAccessor::FindPlayer(citr->first))
  1413. +                           if (plrs->GetArenaTeamId(0) != firstTeamId)
  1414. +                               mmrTwo = arena->GetArenaMatchmakerRating(citr->second.Team);
  1415. +               }
  1416. +               else if (arena->GetArenaType() == ARENA_TYPE_3v3)
  1417. +               {
  1418. +                   mmr = arena->GetArenaMatchmakerRating(1);
  1419. +                   firstTeamId = target->GetArenaTeamId(1);
  1420. +                   Battleground::BattlegroundPlayerMap::const_iterator citr = arena->GetPlayers().begin();
  1421. +                   for (; citr != arena->GetPlayers().end(); ++citr)
  1422. +                       if (Player* plrs = ObjectAccessor::FindPlayer(citr->first))
  1423. +                           if (plrs->GetArenaTeamId(1) != firstTeamId)
  1424. +                               mmrTwo = arena->GetArenaMatchmakerRating(citr->second.Team);
  1425. +               }
  1426. +               else if (arena->GetArenaType() == ARENA_TYPE_5v5)
  1427. +               {
  1428. +                   mmr = arena->GetArenaMatchmakerRating(2);
  1429. +                   firstTeamId = target->GetArenaTeamId(2);
  1430. +                   Battleground::BattlegroundPlayerMap::const_iterator citr = arena->GetPlayers().begin();
  1431. +                   for (; citr != arena->GetPlayers().end(); ++citr)
  1432. +                       if (Player* plrs = ObjectAccessor::FindPlayer(citr->first))
  1433. +                           if (plrs->GetArenaTeamId(2) != firstTeamId)
  1434. +                               mmrTwo = arena->GetArenaMatchmakerRating(citr->second.Team);
  1435. +               }
  1436. +
  1437. +               if (IsTop == 1 && arena->GetArenaType() == ARENA_TYPE_2v2)
  1438. +               {
  1439. +                   TypeOne++;
  1440. +                   if (TypeOne > (page + 1) * GamesOnPage)
  1441. +                   {
  1442. +                       haveNextPage = true;
  1443. +                       break;
  1444. +                   }
  1445. +
  1446. +                   if (TypeOne >= page * GamesOnPage)
  1447. +                       player->ADD_GOSSIP_ITEM(GOSSIP_ICON_BATTLE, GetGamesStringData(arena, mmr, mmrTwo), GOSSIP_SENDER_MAIN, NPC_SPECTATOR_ACTION_SELECTED_PLAYER + GetFirstPlayerGuid(arena));
  1448. +               }
  1449. +               else if (IsTop == 2 && arena->GetArenaType() == ARENA_TYPE_3v3)
  1450. +               {
  1451. +                   TypeTwo++;
  1452. +                   if (TypeTwo > (page + 1) * GamesOnPage)
  1453. +                   {
  1454. +                       haveNextPage = true;
  1455. +                       break;
  1456. +                   }
  1457. +
  1458. +                   if (TypeTwo >= page * GamesOnPage)
  1459. +                       player->ADD_GOSSIP_ITEM(GOSSIP_ICON_BATTLE, GetGamesStringData(arena, mmr, mmrTwo), GOSSIP_SENDER_MAIN, NPC_SPECTATOR_ACTION_SELECTED_PLAYER + GetFirstPlayerGuid(arena));
  1460. +               }
  1461. +
  1462. +               else if (IsTop == 3 && arena->GetArenaType() == ARENA_TYPE_5v5)
  1463. +               {
  1464. +                   TypeThree++;
  1465. +                   if (TypeThree > (page + 1) * GamesOnPage)
  1466. +                   {
  1467. +                       haveNextPage = true;
  1468. +                       break;
  1469. +                   }
  1470. +                   if (TypeThree >= page * GamesOnPage)
  1471. +                       player->ADD_GOSSIP_ITEM(GOSSIP_ICON_BATTLE, GetGamesStringData(arena, mmr, mmrTwo), GOSSIP_SENDER_MAIN, NPC_SPECTATOR_ACTION_SELECTED_PLAYER + GetFirstPlayerGuid(arena));
  1472. +               }
  1473. +           }
  1474. +       }
  1475. +
  1476. +       if (page > 0)
  1477. +       {
  1478. +           player->ADD_GOSSIP_ITEM(GOSSIP_ICON_DOT, "Prev..", GOSSIP_SENDER_MAIN, NPC_SPECTATOR_ACTION_2V2_GAMES + page - 1);
  1479. +           player->ADD_GOSSIP_ITEM(GOSSIP_ICON_DOT, "Prev..", GOSSIP_SENDER_MAIN, NPC_SPECTATOR_ACTION_3V3_GAMES + page - 1);
  1480. +           player->ADD_GOSSIP_ITEM(GOSSIP_ICON_DOT, "Prev..", GOSSIP_SENDER_MAIN, NPC_SPECTATOR_ACTION_5V5_GAMES + page - 1);
  1481. +       }
  1482. +
  1483. +       if (haveNextPage)
  1484. +       {
  1485. +           player->ADD_GOSSIP_ITEM(GOSSIP_ICON_DOT, "Next..", GOSSIP_SENDER_MAIN, NPC_SPECTATOR_ACTION_2V2_GAMES + page + 1);
  1486. +           player->ADD_GOSSIP_ITEM(GOSSIP_ICON_DOT, "Next..", GOSSIP_SENDER_MAIN, NPC_SPECTATOR_ACTION_3V3_GAMES + page + 1);
  1487. +           player->ADD_GOSSIP_ITEM(GOSSIP_ICON_DOT, "Next..", GOSSIP_SENDER_MAIN, NPC_SPECTATOR_ACTION_5V5_GAMES + page + 1);
  1488. +       }
  1489. +   }
  1490. +
  1491. +   bool OnGossipSelectCode(Player* player, Creature* creature, uint32 sender, uint32 action, const char* code)
  1492. +   {
  1493. +       if (!player)
  1494. +           return true;
  1495. +
  1496. +       player->PlayerTalkClass->ClearMenus();
  1497. +       player->CLOSE_GOSSIP_MENU();
  1498. +       if (sender == GOSSIP_SENDER_MAIN)
  1499. +       {
  1500. +           switch (action)
  1501. +           {
  1502. +           case NPC_SPECTATOR_ACTION_SPECIFIC: // choosing a player
  1503. +
  1504. +               const char* plrName = code;
  1505. +
  1506. +               char playerName[50];
  1507. +               strcpy(playerName, plrName);
  1508. +
  1509. +               for (int i = 0; i < 13; i++)
  1510. +               {
  1511. +                   if (playerName[i] == NULL)
  1512. +                       break;
  1513. +                   if (i == 0 && playerName[i] > 96)
  1514. +                       playerName[0] -= 32;
  1515. +                   else if (playerName[i] < 97)
  1516. +                       playerName[i] += 32;
  1517. +               }
  1518. +
  1519. +               if (Player* target = ObjectAccessor::FindPlayerByName(playerName))
  1520. +               {
  1521. +                   ChatHandler handler(player->GetSession());
  1522. +                   char const* pTarget = target->GetName().c_str();
  1523. +                   arena_spectator_commands::HandleSpectateCommand(&handler, pTarget);
  1524. +               }
  1525. +               ChatHandler(player->GetSession()).PSendSysMessage("Player is not online or does not exist.");
  1526. +               return true;
  1527. +           }
  1528. +       }
  1529. +
  1530. +       return false;
  1531. +   }
  1532. +};
  1533. +
  1534. +
  1535. +void AddSC_arena_spectator_script()
  1536. +{
  1537. +   new arena_spectator_commands();
  1538. +   new npc_arena_spectator();
  1539. +}
  1540. \ No newline at end of file
  1541. --
  1542. 2.1.4
Advertisement
Add Comment
Please, Sign In to add comment