Advertisement
Guest User

npcs_special.cpp

a guest
Aug 20th, 2015
328
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
C++ 205.68 KB | None | 0 0
  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.  
  19. /* ScriptData
  20. SDName: Npcs_Special
  21. SD%Complete: 100
  22. SDComment: To be used for special NPCs that are located globally.
  23. SDCategory: NPCs
  24. EndScriptData
  25. */
  26.  
  27. /* ContentData
  28. npc_air_force_bots       80%    support for misc (invisible) guard bots in areas where player allowed to fly. Summon guards after a preset time if tagged by spell
  29. npc_lunaclaw_spirit      80%    support for quests 6001/6002 (Body and Heart)
  30. npc_chicken_cluck       100%    support for quest 3861 (Cluck!)
  31. npc_dancing_flames      100%    midsummer event NPC
  32. npc_guardian            100%    guardianAI used to prevent players from accessing off-limits areas. Not in use by SD2
  33. npc_garments_of_quests   80%    NPC's related to all Garments of-quests 5621, 5624, 5625, 5648, 565
  34. npc_injured_patient     100%    patients for triage-quests (6622 and 6624)
  35. npc_doctor              100%    Gustaf Vanhowzen and Gregory Victor, quest 6622 and 6624 (Triage)
  36. npc_mount_vendor        100%    Regular mount vendors all over the world. Display gossip if player doesn't meet the requirements to buy
  37. npc_rogue_trainer        80%    Scripted trainers, so they are able to offer item 17126 for class quest 6681
  38. npc_sayge               100%    Darkmoon event fortune teller, buff player based on answers given
  39. npc_snake_trap_serpents  80%    AI for snakes that summoned by Snake Trap
  40. npc_locksmith            75%    list of keys needs to be confirmed
  41. npc_firework            100%    NPC's summoned by rockets and rocket clusters, for making them cast visual
  42. EndContentData */
  43.  
  44. #include "ScriptMgr.h"
  45. #include "ScriptedCreature.h"
  46. #include "ScriptedGossip.h"
  47. #include "ScriptedEscortAI.h"
  48. #include "ObjectMgr.h"
  49. #include "ScriptMgr.h"
  50. #include "World.h"
  51. #include "PetAI.h"
  52. #include "PassiveAI.h"
  53. #include "CombatAI.h"
  54. #include "GameEventMgr.h"
  55. #include "GridNotifiers.h"
  56. #include "GridNotifiersImpl.h"
  57. #include "Cell.h"
  58. #include "CellImpl.h"
  59. #include "SpellAuras.h"
  60. #include "Vehicle.h"
  61. #include "Player.h"
  62. #include "MoveSplineInit.h"
  63.  
  64. /*########
  65. # npc_air_force_bots
  66. #########*/
  67.  
  68. enum SpawnType
  69. {
  70.     SPAWNTYPE_TRIPWIRE_ROOFTOP,                             // no warning, summon Creature at smaller range
  71.     SPAWNTYPE_ALARMBOT,                                     // cast guards mark and summon npc - if player shows up with that buff duration < 5 seconds attack
  72. };
  73.  
  74. struct SpawnAssociation
  75. {
  76.     uint32 thisCreatureEntry;
  77.     uint32 spawnedCreatureEntry;
  78.     SpawnType spawnType;
  79. };
  80.  
  81. enum eEnums
  82. {
  83.     SPELL_GUARDS_MARK               = 38067,
  84.     AURA_DURATION_TIME_LEFT         = 5000
  85. };
  86.  
  87. float const RANGE_TRIPWIRE          = 15.0f;
  88. float const RANGE_GUARDS_MARK       = 50.0f;
  89.  
  90. SpawnAssociation spawnAssociations[] =
  91. {
  92.     {2614,  15241, SPAWNTYPE_ALARMBOT},                     //Air Force Alarm Bot (Alliance)
  93.     {2615,  15242, SPAWNTYPE_ALARMBOT},                     //Air Force Alarm Bot (Horde)
  94.     {21974, 21976, SPAWNTYPE_ALARMBOT},                     //Air Force Alarm Bot (Area 52)
  95.     {21993, 15242, SPAWNTYPE_ALARMBOT},                     //Air Force Guard Post (Horde - Bat Rider)
  96.     {21996, 15241, SPAWNTYPE_ALARMBOT},                     //Air Force Guard Post (Alliance - Gryphon)
  97.     {21997, 21976, SPAWNTYPE_ALARMBOT},                     //Air Force Guard Post (Goblin - Area 52 - Zeppelin)
  98.     {21999, 15241, SPAWNTYPE_TRIPWIRE_ROOFTOP},             //Air Force Trip Wire - Rooftop (Alliance)
  99.     {22001, 15242, SPAWNTYPE_TRIPWIRE_ROOFTOP},             //Air Force Trip Wire - Rooftop (Horde)
  100.     {22002, 15242, SPAWNTYPE_TRIPWIRE_ROOFTOP},             //Air Force Trip Wire - Ground (Horde)
  101.     {22003, 15241, SPAWNTYPE_TRIPWIRE_ROOFTOP},             //Air Force Trip Wire - Ground (Alliance)
  102.     {22063, 21976, SPAWNTYPE_TRIPWIRE_ROOFTOP},             //Air Force Trip Wire - Rooftop (Goblin - Area 52)
  103.     {22065, 22064, SPAWNTYPE_ALARMBOT},                     //Air Force Guard Post (Ethereal - Stormspire)
  104.     {22066, 22067, SPAWNTYPE_ALARMBOT},                     //Air Force Guard Post (Scryer - Dragonhawk)
  105.     {22068, 22064, SPAWNTYPE_TRIPWIRE_ROOFTOP},             //Air Force Trip Wire - Rooftop (Ethereal - Stormspire)
  106.     {22069, 22064, SPAWNTYPE_ALARMBOT},                     //Air Force Alarm Bot (Stormspire)
  107.     {22070, 22067, SPAWNTYPE_TRIPWIRE_ROOFTOP},             //Air Force Trip Wire - Rooftop (Scryer)
  108.     {22071, 22067, SPAWNTYPE_ALARMBOT},                     //Air Force Alarm Bot (Scryer)
  109.     {22078, 22077, SPAWNTYPE_ALARMBOT},                     //Air Force Alarm Bot (Aldor)
  110.     {22079, 22077, SPAWNTYPE_ALARMBOT},                     //Air Force Guard Post (Aldor - Gryphon)
  111.     {22080, 22077, SPAWNTYPE_TRIPWIRE_ROOFTOP},             //Air Force Trip Wire - Rooftop (Aldor)
  112.     {22086, 22085, SPAWNTYPE_ALARMBOT},                     //Air Force Alarm Bot (Sporeggar)
  113.     {22087, 22085, SPAWNTYPE_ALARMBOT},                     //Air Force Guard Post (Sporeggar - Spore Bat)
  114.     {22088, 22085, SPAWNTYPE_TRIPWIRE_ROOFTOP},             //Air Force Trip Wire - Rooftop (Sporeggar)
  115.     {22090, 22089, SPAWNTYPE_ALARMBOT},                     //Air Force Guard Post (Toshley's Station - Flying Machine)
  116.     {22124, 22122, SPAWNTYPE_ALARMBOT},                     //Air Force Alarm Bot (Cenarion)
  117.     {22125, 22122, SPAWNTYPE_ALARMBOT},                     //Air Force Guard Post (Cenarion - Stormcrow)
  118.     {22126, 22122, SPAWNTYPE_ALARMBOT}                      //Air Force Trip Wire - Rooftop (Cenarion Expedition)
  119. };
  120.  
  121. class npc_air_force_bots : public CreatureScript
  122. {
  123.     public:
  124.         npc_air_force_bots() : CreatureScript("npc_air_force_bots") { }
  125.  
  126.         struct npc_air_force_botsAI : public ScriptedAI
  127.         {
  128.             npc_air_force_botsAI(Creature* creature) : ScriptedAI(creature)
  129.             {
  130.                 SpawnAssoc = NULL;
  131.                 SpawnedGUID = 0;
  132.  
  133.                 // find the correct spawnhandling
  134.                 static uint32 entryCount = sizeof(spawnAssociations) / sizeof(SpawnAssociation);
  135.  
  136.                 for (uint8 i = 0; i < entryCount; ++i)
  137.                 {
  138.                     if (spawnAssociations[i].thisCreatureEntry == creature->GetEntry())
  139.                     {
  140.                         SpawnAssoc = &spawnAssociations[i];
  141.                         break;
  142.                     }
  143.                 }
  144.  
  145.                 if (!SpawnAssoc)
  146.                     sLog->outError(LOG_FILTER_SQL, "TCSR: Creature template entry %u has ScriptName npc_air_force_bots, but it's not handled by that script", creature->GetEntry());
  147.                 else
  148.                 {
  149.                     CreatureTemplate const* spawnedTemplate = sObjectMgr->GetCreatureTemplate(SpawnAssoc->spawnedCreatureEntry);
  150.  
  151.                     if (!spawnedTemplate)
  152.                     {
  153.                         sLog->outError(LOG_FILTER_SQL, "TCSR: Creature template entry %u does not exist in DB, which is required by npc_air_force_bots", SpawnAssoc->spawnedCreatureEntry);
  154.                         SpawnAssoc = NULL;
  155.                         return;
  156.                     }
  157.                 }
  158.             }
  159.  
  160.             SpawnAssociation* SpawnAssoc;
  161.             uint64 SpawnedGUID;
  162.  
  163.             void Reset() {}
  164.  
  165.             Creature* SummonGuard()
  166.             {
  167.                 Creature* summoned = me->SummonCreature(SpawnAssoc->spawnedCreatureEntry, 0.0f, 0.0f, 0.0f, 0.0f, TEMPSUMMON_TIMED_DESPAWN_OUT_OF_COMBAT, 300000);
  168.  
  169.                 if (summoned)
  170.                     SpawnedGUID = summoned->GetGUID();
  171.                 else
  172.                 {
  173.                     sLog->outError(LOG_FILTER_SQL, "TCSR: npc_air_force_bots: wasn't able to spawn Creature %u", SpawnAssoc->spawnedCreatureEntry);
  174.                     SpawnAssoc = NULL;
  175.                 }
  176.  
  177.                 return summoned;
  178.             }
  179.  
  180.             Creature* GetSummonedGuard()
  181.             {
  182.                 Creature* creature = Unit::GetCreature(*me, SpawnedGUID);
  183.  
  184.                 if (creature && creature->isAlive())
  185.                     return creature;
  186.  
  187.                 return NULL;
  188.             }
  189.  
  190.             void MoveInLineOfSight(Unit* who)
  191.             {
  192.                 if (!SpawnAssoc)
  193.                     return;
  194.  
  195.                 if (me->IsValidAttackTarget(who))
  196.                 {
  197.                     Player* playerTarget = who->ToPlayer();
  198.  
  199.                     // airforce guards only spawn for players
  200.                     if (!playerTarget)
  201.                         return;
  202.  
  203.                     if (!playerTarget->isAlive())
  204.                         return;
  205.  
  206.                     Creature* lastSpawnedGuard = SpawnedGUID == 0 ? NULL : GetSummonedGuard();
  207.  
  208.                     // prevent calling Unit::GetUnit at next MoveInLineOfSight call - speedup
  209.                     if (!lastSpawnedGuard)
  210.                         SpawnedGUID = 0;
  211.  
  212.                     switch (SpawnAssoc->spawnType)
  213.                     {
  214.                         case SPAWNTYPE_ALARMBOT:
  215.                         {
  216.                             if (!who->IsWithinDistInMap(me, RANGE_GUARDS_MARK))
  217.                                 return;
  218.  
  219.                             AuraPtr markAura = who->GetAura(SPELL_GUARDS_MARK);
  220.                             if (markAura)
  221.                             {
  222.                                 // the target wasn't able to move out of our range within 25 seconds
  223.                                 if (!lastSpawnedGuard)
  224.                                 {
  225.                                     lastSpawnedGuard = SummonGuard();
  226.  
  227.                                     if (!lastSpawnedGuard)
  228.                                         return;
  229.                                 }
  230.  
  231.                                 if (markAura->GetDuration() < AURA_DURATION_TIME_LEFT)
  232.                                     if (!lastSpawnedGuard->getVictim())
  233.                                         lastSpawnedGuard->AI()->AttackStart(who);
  234.                             }
  235.                             else
  236.                             {
  237.                                 if (!lastSpawnedGuard)
  238.                                     lastSpawnedGuard = SummonGuard();
  239.  
  240.                                 if (!lastSpawnedGuard)
  241.                                     return;
  242.  
  243.                                 lastSpawnedGuard->CastSpell(who, SPELL_GUARDS_MARK, true);
  244.                             }
  245.                             break;
  246.                         }
  247.                         case SPAWNTYPE_TRIPWIRE_ROOFTOP:
  248.                         {
  249.                             if (!who->IsWithinDistInMap(me, RANGE_TRIPWIRE))
  250.                                 return;
  251.  
  252.                             if (!lastSpawnedGuard)
  253.                                 lastSpawnedGuard = SummonGuard();
  254.  
  255.                             if (!lastSpawnedGuard)
  256.                                 return;
  257.  
  258.                             // ROOFTOP only triggers if the player is on the ground
  259.                             if (!playerTarget->IsFlying() && !lastSpawnedGuard->getVictim())
  260.                                 lastSpawnedGuard->AI()->AttackStart(who);
  261.  
  262.                             break;
  263.                         }
  264.                     }
  265.                 }
  266.             }
  267.         };
  268.  
  269.         CreatureAI* GetAI(Creature* creature) const
  270.         {
  271.             return new npc_air_force_botsAI(creature);
  272.         }
  273. };
  274.  
  275. /*######
  276. ## npc_lunaclaw_spirit
  277. ######*/
  278.  
  279. enum
  280. {
  281.     QUEST_BODY_HEART_A      = 6001,
  282.     QUEST_BODY_HEART_H      = 6002,
  283.  
  284.     TEXT_ID_DEFAULT         = 4714,
  285.     TEXT_ID_PROGRESS        = 4715
  286. };
  287.  
  288. #define GOSSIP_ITEM_GRANT   "You have thought well, spirit. I ask you to grant me the strength of your body and the strength of your heart."
  289.  
  290. class npc_lunaclaw_spirit : public CreatureScript
  291. {
  292.     public:
  293.         npc_lunaclaw_spirit() : CreatureScript("npc_lunaclaw_spirit") { }
  294.  
  295.         bool OnGossipHello(Player* player, Creature* creature)
  296.         {
  297.             if (player->GetQuestStatus(QUEST_BODY_HEART_A) == QUEST_STATUS_INCOMPLETE || player->GetQuestStatus(QUEST_BODY_HEART_H) == QUEST_STATUS_INCOMPLETE)
  298.                 player->ADD_GOSSIP_ITEM(GOSSIP_ICON_CHAT, GOSSIP_ITEM_GRANT, GOSSIP_SENDER_MAIN, GOSSIP_ACTION_INFO_DEF + 1);
  299.  
  300.             player->SEND_GOSSIP_MENU(TEXT_ID_DEFAULT, creature->GetGUID());
  301.             return true;
  302.         }
  303.  
  304.         bool OnGossipSelect(Player* player, Creature* creature, uint32 /*sender*/, uint32 action)
  305.         {
  306.             player->PlayerTalkClass->ClearMenus();
  307.             if (action == GOSSIP_ACTION_INFO_DEF + 1)
  308.             {
  309.                 player->SEND_GOSSIP_MENU(TEXT_ID_PROGRESS, creature->GetGUID());
  310.                 player->AreaExploredOrEventHappens(player->GetTeam() == ALLIANCE ? QUEST_BODY_HEART_A : QUEST_BODY_HEART_H);
  311.             }
  312.             return true;
  313.         }
  314. };
  315.  
  316. /*########
  317. # npc_chicken_cluck
  318. #########*/
  319.  
  320. #define EMOTE_HELLO         -1070004
  321. #define EMOTE_CLUCK_TEXT    -1070006
  322.  
  323. #define QUEST_CLUCK         3861
  324. #define FACTION_FRIENDLY    35
  325. #define FACTION_CHICKEN     31
  326.  
  327. class npc_chicken_cluck : public CreatureScript
  328. {
  329.     public:
  330.         npc_chicken_cluck() : CreatureScript("npc_chicken_cluck") { }
  331.  
  332.         struct npc_chicken_cluckAI : public ScriptedAI
  333.         {
  334.             npc_chicken_cluckAI(Creature* creature) : ScriptedAI(creature) {}
  335.  
  336.             uint32 ResetFlagTimer;
  337.  
  338.             void Reset()
  339.             {
  340.                 ResetFlagTimer = 120000;
  341.                 me->setFaction(FACTION_CHICKEN);
  342.                 me->RemoveFlag(UNIT_NPC_FLAGS, UNIT_NPC_FLAG_QUESTGIVER);
  343.             }
  344.  
  345.             void EnterCombat(Unit* /*who*/) {}
  346.  
  347.             void UpdateAI(uint32 const diff)
  348.             {
  349.                 // Reset flags after a certain time has passed so that the next player has to start the 'event' again
  350.                 if (me->HasFlag(UNIT_NPC_FLAGS, UNIT_NPC_FLAG_QUESTGIVER))
  351.                 {
  352.                     if (ResetFlagTimer <= diff)
  353.                     {
  354.                         EnterEvadeMode();
  355.                         return;
  356.                     }
  357.                     else
  358.                         ResetFlagTimer -= diff;
  359.                 }
  360.  
  361.                 if (UpdateVictim())
  362.                     DoMeleeAttackIfReady();
  363.             }
  364.  
  365.             void ReceiveEmote(Player* player, uint32 emote)
  366.             {
  367.                 switch (emote)
  368.                 {
  369.                     case TEXT_EMOTE_CHICKEN:
  370.                         if (player->GetQuestStatus(QUEST_CLUCK) == QUEST_STATUS_NONE && rand() % 30 == 1)
  371.                         {
  372.                             me->SetFlag(UNIT_NPC_FLAGS, UNIT_NPC_FLAG_QUESTGIVER);
  373.                             me->setFaction(FACTION_FRIENDLY);
  374.                             DoScriptText(EMOTE_HELLO, me);
  375.                         }
  376.                         break;
  377.                     case TEXT_EMOTE_CHEER:
  378.                         if (player->GetQuestStatus(QUEST_CLUCK) == QUEST_STATUS_COMPLETE)
  379.                         {
  380.                             me->SetFlag(UNIT_NPC_FLAGS, UNIT_NPC_FLAG_QUESTGIVER);
  381.                             me->setFaction(FACTION_FRIENDLY);
  382.                             DoScriptText(EMOTE_CLUCK_TEXT, me);
  383.                         }
  384.                         break;
  385.                 }
  386.             }
  387.         };
  388.  
  389.         CreatureAI* GetAI(Creature* creature) const
  390.         {
  391.             return new npc_chicken_cluckAI(creature);
  392.         }
  393.  
  394.         bool OnQuestAccept(Player* /*player*/, Creature* creature, Quest const* quest)
  395.         {
  396.             if (quest->GetQuestId() == QUEST_CLUCK)
  397.                 CAST_AI(npc_chicken_cluck::npc_chicken_cluckAI, creature->AI())->Reset();
  398.  
  399.             return true;
  400.         }
  401.  
  402.         bool OnQuestComplete(Player* /*player*/, Creature* creature, Quest const* quest)
  403.         {
  404.             if (quest->GetQuestId() == QUEST_CLUCK)
  405.                 CAST_AI(npc_chicken_cluck::npc_chicken_cluckAI, creature->AI())->Reset();
  406.  
  407.             return true;
  408.         }
  409. };
  410.  
  411. /*######
  412. ## npc_dancing_flames
  413. ######*/
  414.  
  415. #define SPELL_BRAZIER       45423
  416. #define SPELL_SEDUCTION     47057
  417. #define SPELL_FIERY_AURA    45427
  418.  
  419. class npc_dancing_flames : public CreatureScript
  420. {
  421.     public:
  422.         npc_dancing_flames() : CreatureScript("npc_dancing_flames") { }
  423.  
  424.         struct npc_dancing_flamesAI : public ScriptedAI
  425.         {
  426.             npc_dancing_flamesAI(Creature* creature) : ScriptedAI(creature) {}
  427.  
  428.             bool Active;
  429.             uint32 CanIteract;
  430.  
  431.             void Reset()
  432.             {
  433.                 Active = true;
  434.                 CanIteract = 3500;
  435.                 DoCast(me, SPELL_BRAZIER, true);
  436.                 DoCast(me, SPELL_FIERY_AURA, false);
  437.                 float x, y, z;
  438.                 me->GetPosition(x, y, z);
  439.                 me->Relocate(x, y, z + 0.94f);
  440.                 me->SetDisableGravity(true);
  441.                 me->HandleEmoteCommand(EMOTE_ONESHOT_DANCE);
  442.                 WorldPacket data;                       //send update position to client
  443.                 me->BuildHeartBeatMsg(&data);
  444.                 me->SendMessageToSet(&data, true);
  445.             }
  446.  
  447.             void UpdateAI(uint32 const diff)
  448.             {
  449.                 if (!Active)
  450.                 {
  451.                     if (CanIteract <= diff)
  452.                     {
  453.                         Active = true;
  454.                         CanIteract = 3500;
  455.                         me->HandleEmoteCommand(EMOTE_ONESHOT_DANCE);
  456.                     }
  457.                     else
  458.                         CanIteract -= diff;
  459.                 }
  460.             }
  461.  
  462.             void EnterCombat(Unit* /*who*/){}
  463.  
  464.             void ReceiveEmote(Player* player, uint32 emote)
  465.             {
  466.                 if (me->IsWithinLOS(player->GetPositionX(), player->GetPositionY(), player->GetPositionZ()) && me->IsWithinDistInMap(player, 30.0f))
  467.                 {
  468.                     me->SetInFront(player);
  469.                     Active = false;
  470.  
  471.                     WorldPacket data;
  472.                     me->BuildHeartBeatMsg(&data);
  473.                     me->SendMessageToSet(&data, true);
  474.                     switch (emote)
  475.                     {
  476.                         case TEXT_EMOTE_KISS:
  477.                             me->HandleEmoteCommand(EMOTE_ONESHOT_SHY);
  478.                             break;
  479.                         case TEXT_EMOTE_WAVE:
  480.                             me->HandleEmoteCommand(EMOTE_ONESHOT_WAVE);
  481.                             break;
  482.                         case TEXT_EMOTE_BOW:
  483.                             me->HandleEmoteCommand(EMOTE_ONESHOT_BOW);
  484.                             break;
  485.                         case TEXT_EMOTE_JOKE:
  486.                             me->HandleEmoteCommand(EMOTE_ONESHOT_LAUGH);
  487.                             break;
  488.                         case TEXT_EMOTE_DANCE:
  489.                             if (!player->HasAura(SPELL_SEDUCTION))
  490.                                 DoCast(player, SPELL_SEDUCTION, true);
  491.                             break;
  492.                     }
  493.                 }
  494.             }
  495.         };
  496.  
  497.         CreatureAI* GetAI(Creature* creature) const
  498.         {
  499.             return new npc_dancing_flamesAI(creature);
  500.         }
  501. };
  502.  
  503. /*######
  504. ## Triage quest
  505. ######*/
  506.  
  507. //signed for 9623
  508. #define SAY_DOC1    -1000201
  509. #define SAY_DOC2    -1000202
  510. #define SAY_DOC3    -1000203
  511.  
  512. #define DOCTOR_ALLIANCE     12939
  513. #define DOCTOR_HORDE        12920
  514. #define ALLIANCE_COORDS     7
  515. #define HORDE_COORDS        6
  516.  
  517. struct Location
  518. {
  519.     float x, y, z, o;
  520. };
  521.  
  522. static Location AllianceCoords[]=
  523. {
  524.     {-3757.38f, -4533.05f, 14.16f, 3.62f},                      // Top-far-right bunk as seen from entrance
  525.     {-3754.36f, -4539.13f, 14.16f, 5.13f},                      // Top-far-left bunk
  526.     {-3749.54f, -4540.25f, 14.28f, 3.34f},                      // Far-right bunk
  527.     {-3742.10f, -4536.85f, 14.28f, 3.64f},                      // Right bunk near entrance
  528.     {-3755.89f, -4529.07f, 14.05f, 0.57f},                      // Far-left bunk
  529.     {-3749.51f, -4527.08f, 14.07f, 5.26f},                      // Mid-left bunk
  530.     {-3746.37f, -4525.35f, 14.16f, 5.22f},                      // Left bunk near entrance
  531. };
  532.  
  533. //alliance run to where
  534. #define A_RUNTOX -3742.96f
  535. #define A_RUNTOY -4531.52f
  536. #define A_RUNTOZ 11.91f
  537.  
  538. static Location HordeCoords[]=
  539. {
  540.     {-1013.75f, -3492.59f, 62.62f, 4.34f},                      // Left, Behind
  541.     {-1017.72f, -3490.92f, 62.62f, 4.34f},                      // Right, Behind
  542.     {-1015.77f, -3497.15f, 62.82f, 4.34f},                      // Left, Mid
  543.     {-1019.51f, -3495.49f, 62.82f, 4.34f},                      // Right, Mid
  544.     {-1017.25f, -3500.85f, 62.98f, 4.34f},                      // Left, front
  545.     {-1020.95f, -3499.21f, 62.98f, 4.34f}                       // Right, Front
  546. };
  547.  
  548. //horde run to where
  549. #define H_RUNTOX -1016.44f
  550. #define H_RUNTOY -3508.48f
  551. #define H_RUNTOZ 62.96f
  552.  
  553. uint32 const AllianceSoldierId[3] =
  554. {
  555.     12938,                                                  // 12938 Injured Alliance Soldier
  556.     12936,                                                  // 12936 Badly injured Alliance Soldier
  557.     12937                                                   // 12937 Critically injured Alliance Soldier
  558. };
  559.  
  560. uint32 const HordeSoldierId[3] =
  561. {
  562.     12923,                                                  //12923 Injured Soldier
  563.     12924,                                                  //12924 Badly injured Soldier
  564.     12925                                                   //12925 Critically injured Soldier
  565. };
  566.  
  567. /*######
  568. ## npc_doctor (handles both Gustaf Vanhowzen and Gregory Victor)
  569. ######*/
  570.  
  571. class npc_doctor : public CreatureScript
  572. {
  573.     public:
  574.         npc_doctor() : CreatureScript("npc_doctor") {}
  575.  
  576.         struct npc_doctorAI : public ScriptedAI
  577.         {
  578.             npc_doctorAI(Creature* creature) : ScriptedAI(creature) {}
  579.  
  580.             uint64 PlayerGUID;
  581.  
  582.             uint32 SummonPatientTimer;
  583.             uint32 SummonPatientCount;
  584.             uint32 PatientDiedCount;
  585.             uint32 PatientSavedCount;
  586.  
  587.             bool Event;
  588.  
  589.             std::list<uint64> Patients;
  590.             std::vector<Location*> Coordinates;
  591.  
  592.             void Reset()
  593.             {
  594.                 PlayerGUID = 0;
  595.  
  596.                 SummonPatientTimer = 10000;
  597.                 SummonPatientCount = 0;
  598.                 PatientDiedCount = 0;
  599.                 PatientSavedCount = 0;
  600.  
  601.                 Patients.clear();
  602.                 Coordinates.clear();
  603.  
  604.                 Event = false;
  605.  
  606.                 me->RemoveFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NOT_SELECTABLE);
  607.             }
  608.  
  609.             void BeginEvent(Player* player)
  610.             {
  611.                 PlayerGUID = player->GetGUID();
  612.  
  613.                 SummonPatientTimer = 10000;
  614.                 SummonPatientCount = 0;
  615.                 PatientDiedCount = 0;
  616.                 PatientSavedCount = 0;
  617.  
  618.                 switch (me->GetEntry())
  619.                 {
  620.                     case DOCTOR_ALLIANCE:
  621.                         for (uint8 i = 0; i < ALLIANCE_COORDS; ++i)
  622.                             Coordinates.push_back(&AllianceCoords[i]);
  623.                         break;
  624.                     case DOCTOR_HORDE:
  625.                         for (uint8 i = 0; i < HORDE_COORDS; ++i)
  626.                             Coordinates.push_back(&HordeCoords[i]);
  627.                         break;
  628.                 }
  629.  
  630.                 Event = true;
  631.                 me->SetFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NOT_SELECTABLE);
  632.             }
  633.  
  634.             void PatientDied(Location* point)
  635.             {
  636.                 Player* player = Unit::GetPlayer(*me, PlayerGUID);
  637.                 if (player && ((player->GetQuestStatus(6624) == QUEST_STATUS_INCOMPLETE) || (player->GetQuestStatus(6622) == QUEST_STATUS_INCOMPLETE)))
  638.                 {
  639.                     ++PatientDiedCount;
  640.  
  641.                     if (PatientDiedCount > 5 && Event)
  642.                     {
  643.                         if (player->GetQuestStatus(6624) == QUEST_STATUS_INCOMPLETE)
  644.                             player->FailQuest(6624);
  645.                         else if (player->GetQuestStatus(6622) == QUEST_STATUS_INCOMPLETE)
  646.                             player->FailQuest(6622);
  647.  
  648.                         Reset();
  649.                         return;
  650.                     }
  651.  
  652.                     Coordinates.push_back(point);
  653.                 }
  654.                 else
  655.                     // If no player or player abandon quest in progress
  656.                     Reset();
  657.             }
  658.  
  659.             void PatientSaved(Creature* /*soldier*/, Player* player, Location* point)
  660.             {
  661.                 if (player && PlayerGUID == player->GetGUID())
  662.                 {
  663.                     if ((player->GetQuestStatus(6624) == QUEST_STATUS_INCOMPLETE) || (player->GetQuestStatus(6622) == QUEST_STATUS_INCOMPLETE))
  664.                     {
  665.                         ++PatientSavedCount;
  666.  
  667.                         if (PatientSavedCount == 15)
  668.                         {
  669.                             if (!Patients.empty())
  670.                             {
  671.                                 std::list<uint64>::const_iterator itr;
  672.                                 for (itr = Patients.begin(); itr != Patients.end(); ++itr)
  673.                                 {
  674.                                     if (Creature* patient = Unit::GetCreature((*me), *itr))
  675.                                         patient->setDeathState(JUST_DIED);
  676.                                 }
  677.                             }
  678.  
  679.                             if (player->GetQuestStatus(6624) == QUEST_STATUS_INCOMPLETE)
  680.                                 player->AreaExploredOrEventHappens(6624);
  681.                             else if (player->GetQuestStatus(6622) == QUEST_STATUS_INCOMPLETE)
  682.                                 player->AreaExploredOrEventHappens(6622);
  683.  
  684.                             Reset();
  685.                             return;
  686.                         }
  687.  
  688.                         Coordinates.push_back(point);
  689.                     }
  690.                 }
  691.             }
  692.  
  693.             void UpdateAI(uint32 const diff);
  694.  
  695.             void EnterCombat(Unit* /*who*/){}
  696.         };
  697.  
  698.         bool OnQuestAccept(Player* player, Creature* creature, Quest const* quest)
  699.         {
  700.             if ((quest->GetQuestId() == 6624) || (quest->GetQuestId() == 6622))
  701.                 CAST_AI(npc_doctor::npc_doctorAI, creature->AI())->BeginEvent(player);
  702.  
  703.             return true;
  704.         }
  705.  
  706.         CreatureAI* GetAI(Creature* creature) const
  707.         {
  708.             return new npc_doctorAI(creature);
  709.         }
  710. };
  711.  
  712. /*#####
  713. ## npc_injured_patient (handles all the patients, no matter Horde or Alliance)
  714. #####*/
  715.  
  716. class npc_injured_patient : public CreatureScript
  717. {
  718.     public:
  719.         npc_injured_patient() : CreatureScript("npc_injured_patient") { }
  720.  
  721.         struct npc_injured_patientAI : public ScriptedAI
  722.         {
  723.             npc_injured_patientAI(Creature* creature) : ScriptedAI(creature) {}
  724.  
  725.             uint64 DoctorGUID;
  726.             Location* Coord;
  727.  
  728.             void Reset()
  729.             {
  730.                 DoctorGUID = 0;
  731.                 Coord = NULL;
  732.  
  733.                 //no select
  734.                 me->RemoveFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NOT_SELECTABLE);
  735.  
  736.                 //no regen health
  737.                 me->SetFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_IN_COMBAT);
  738.  
  739.                 //to make them lay with face down
  740.                 me->SetUInt32Value(UNIT_FIELD_BYTES_1, UNIT_STAND_STATE_DEAD);
  741.  
  742.                 uint32 mobId = me->GetEntry();
  743.  
  744.                 switch (mobId)
  745.                 {                                                   //lower max health
  746.                     case 12923:
  747.                     case 12938:                                     //Injured Soldier
  748.                         me->SetHealth(me->CountPctFromMaxHealth(75));
  749.                         break;
  750.                     case 12924:
  751.                     case 12936:                                     //Badly injured Soldier
  752.                         me->SetHealth(me->CountPctFromMaxHealth(50));
  753.                         break;
  754.                     case 12925:
  755.                     case 12937:                                     //Critically injured Soldier
  756.                         me->SetHealth(me->CountPctFromMaxHealth(25));
  757.                         break;
  758.                 }
  759.             }
  760.  
  761.             void EnterCombat(Unit* /*who*/){}
  762.  
  763.             void SpellHit(Unit* caster, SpellInfo const* spell)
  764.             {
  765.                 if (caster->GetTypeId() == TYPEID_PLAYER && me->isAlive() && spell->Id == 20804)
  766.                 {
  767.                     if ((CAST_PLR(caster)->GetQuestStatus(6624) == QUEST_STATUS_INCOMPLETE) || (CAST_PLR(caster)->GetQuestStatus(6622) == QUEST_STATUS_INCOMPLETE))
  768.                         if (DoctorGUID)
  769.                             if (Creature* doctor = Unit::GetCreature(*me, DoctorGUID))
  770.                                 CAST_AI(npc_doctor::npc_doctorAI, doctor->AI())->PatientSaved(me, CAST_PLR(caster), Coord);
  771.  
  772.                     //make not selectable
  773.                     me->SetFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NOT_SELECTABLE);
  774.  
  775.                     //regen health
  776.                     me->RemoveFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_IN_COMBAT);
  777.  
  778.                     //stand up
  779.                     me->SetUInt32Value(UNIT_FIELD_BYTES_1, UNIT_STAND_STATE_STAND);
  780.  
  781.                     DoScriptText(RAND(SAY_DOC1, SAY_DOC2, SAY_DOC3), me);
  782.  
  783.                     uint32 mobId = me->GetEntry();
  784.                     me->SetWalk(false);
  785.  
  786.                     switch (mobId)
  787.                     {
  788.                         case 12923:
  789.                         case 12924:
  790.                         case 12925:
  791.                             me->GetMotionMaster()->MovePoint(0, H_RUNTOX, H_RUNTOY, H_RUNTOZ);
  792.                             break;
  793.                         case 12936:
  794.                         case 12937:
  795.                         case 12938:
  796.                             me->GetMotionMaster()->MovePoint(0, A_RUNTOX, A_RUNTOY, A_RUNTOZ);
  797.                             break;
  798.                     }
  799.                 }
  800.             }
  801.  
  802.             void UpdateAI(uint32 const /*diff*/)
  803.             {
  804.                 //lower HP on every world tick makes it a useful counter, not officlone though
  805.                 if (me->isAlive() && me->GetHealth() > 6)
  806.                     me->ModifyHealth(-5);
  807.  
  808.                 if (me->isAlive() && me->GetHealth() <= 6)
  809.                 {
  810.                     me->RemoveFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_IN_COMBAT);
  811.                     me->SetFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NOT_SELECTABLE);
  812.                     me->setDeathState(JUST_DIED);
  813.                     me->SetFlag(OBJECT_FIELD_DYNAMIC_FLAGS, 32);
  814.  
  815.                     if (DoctorGUID)
  816.                         if (Creature* doctor = Unit::GetCreature((*me), DoctorGUID))
  817.                             CAST_AI(npc_doctor::npc_doctorAI, doctor->AI())->PatientDied(Coord);
  818.                 }
  819.             }
  820.         };
  821.  
  822.         CreatureAI* GetAI(Creature* creature) const
  823.         {
  824.             return new npc_injured_patientAI(creature);
  825.         }
  826. };
  827.  
  828. void npc_doctor::npc_doctorAI::UpdateAI(uint32 const diff)
  829. {
  830.     if (Event && SummonPatientCount >= 20)
  831.     {
  832.         Reset();
  833.         return;
  834.     }
  835.  
  836.     if (Event)
  837.     {
  838.         if (SummonPatientTimer <= diff)
  839.         {
  840.             if (Coordinates.empty())
  841.                 return;
  842.  
  843.             std::vector<Location*>::iterator itr = Coordinates.begin() + rand() % Coordinates.size();
  844.             uint32 patientEntry = 0;
  845.  
  846.             switch (me->GetEntry())
  847.             {
  848.                 case DOCTOR_ALLIANCE:
  849.                     patientEntry = AllianceSoldierId[rand() % 3];
  850.                     break;
  851.                 case DOCTOR_HORDE:
  852.                     patientEntry = HordeSoldierId[rand() % 3];
  853.                     break;
  854.                 default:
  855.                     sLog->outError(LOG_FILTER_TSCR, "Invalid entry for Triage doctor. Please check your database");
  856.                     return;
  857.             }
  858.  
  859.             if (Location* point = *itr)
  860.             {
  861.                 if (Creature* Patient = me->SummonCreature(patientEntry, point->x, point->y, point->z, point->o, TEMPSUMMON_TIMED_DESPAWN_OUT_OF_COMBAT, 5000))
  862.                 {
  863.                     //303, this flag appear to be required for client side item->spell to work (TARGET_SINGLE_FRIEND)
  864.                     Patient->SetFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_PVP_ATTACKABLE);
  865.  
  866.                     Patients.push_back(Patient->GetGUID());
  867.                     CAST_AI(npc_injured_patient::npc_injured_patientAI, Patient->AI())->DoctorGUID = me->GetGUID();
  868.                     CAST_AI(npc_injured_patient::npc_injured_patientAI, Patient->AI())->Coord = point;
  869.  
  870.                     Coordinates.erase(itr);
  871.                 }
  872.             }
  873.             SummonPatientTimer = 10000;
  874.             ++SummonPatientCount;
  875.         }
  876.         else
  877.             SummonPatientTimer -= diff;
  878.     }
  879. }
  880.  
  881. /*######
  882. ## npc_garments_of_quests
  883. ######*/
  884.  
  885. //TODO: get text for each NPC
  886.  
  887. enum eGarments
  888. {
  889.     SPELL_LESSER_HEAL_R2    = 2052,
  890.     SPELL_FORTITUDE_R1      = 1243,
  891.  
  892.     QUEST_MOON              = 5621,
  893.     QUEST_LIGHT_1           = 5624,
  894.     QUEST_LIGHT_2           = 5625,
  895.     QUEST_SPIRIT            = 5648,
  896.     QUEST_DARKNESS          = 5650,
  897.  
  898.     ENTRY_SHAYA             = 12429,
  899.     ENTRY_ROBERTS           = 12423,
  900.     ENTRY_DOLF              = 12427,
  901.     ENTRY_KORJA             = 12430,
  902.     ENTRY_DG_KEL            = 12428,
  903.  
  904.     //used by 12429, 12423, 12427, 12430, 12428, but signed for 12429
  905.     SAY_COMMON_HEALED       = -1000164,
  906.     SAY_DG_KEL_THANKS       = -1000165,
  907.     SAY_DG_KEL_GOODBYE      = -1000166,
  908.     SAY_ROBERTS_THANKS      = -1000167,
  909.     SAY_ROBERTS_GOODBYE     = -1000168,
  910.     SAY_KORJA_THANKS        = -1000169,
  911.     SAY_KORJA_GOODBYE       = -1000170,
  912.     SAY_DOLF_THANKS         = -1000171,
  913.     SAY_DOLF_GOODBYE        = -1000172,
  914.     SAY_SHAYA_THANKS        = -1000173,
  915.     SAY_SHAYA_GOODBYE       = -1000174, //signed for 21469
  916. };
  917.  
  918. class npc_garments_of_quests : public CreatureScript
  919. {
  920.     public:
  921.         npc_garments_of_quests() : CreatureScript("npc_garments_of_quests") { }
  922.  
  923.         struct npc_garments_of_questsAI : public npc_escortAI
  924.         {
  925.             npc_garments_of_questsAI(Creature* creature) : npc_escortAI(creature) {Reset();}
  926.  
  927.             uint64 CasterGUID;
  928.  
  929.             bool IsHealed;
  930.             bool CanRun;
  931.  
  932.             uint32 RunAwayTimer;
  933.  
  934.             void Reset()
  935.             {
  936.                 CasterGUID = 0;
  937.  
  938.                 IsHealed = false;
  939.                 CanRun = false;
  940.  
  941.                 RunAwayTimer = 5000;
  942.  
  943.                 me->SetStandState(UNIT_STAND_STATE_KNEEL);
  944.                 //expect database to have RegenHealth=0
  945.                 me->SetHealth(me->CountPctFromMaxHealth(70));
  946.             }
  947.  
  948.             void EnterCombat(Unit* /*who*/) {}
  949.  
  950.             void SpellHit(Unit* caster, SpellInfo const* Spell)
  951.             {
  952.                 if (Spell->Id == SPELL_LESSER_HEAL_R2 || Spell->Id == SPELL_FORTITUDE_R1)
  953.                 {
  954.                     //not while in combat
  955.                     if (me->isInCombat())
  956.                         return;
  957.  
  958.                     //nothing to be done now
  959.                     if (IsHealed && CanRun)
  960.                         return;
  961.  
  962.                     if (Player* player = caster->ToPlayer())
  963.                     {
  964.                         switch (me->GetEntry())
  965.                         {
  966.                             case ENTRY_SHAYA:
  967.                                 if (player->GetQuestStatus(QUEST_MOON) == QUEST_STATUS_INCOMPLETE)
  968.                                 {
  969.                                     if (IsHealed && !CanRun && Spell->Id == SPELL_FORTITUDE_R1)
  970.                                     {
  971.                                         DoScriptText(SAY_SHAYA_THANKS, me, caster);
  972.                                         CanRun = true;
  973.                                     }
  974.                                     else if (!IsHealed && Spell->Id == SPELL_LESSER_HEAL_R2)
  975.                                     {
  976.                                         CasterGUID = caster->GetGUID();
  977.                                         me->SetStandState(UNIT_STAND_STATE_STAND);
  978.                                         DoScriptText(SAY_COMMON_HEALED, me, caster);
  979.                                         IsHealed = true;
  980.                                     }
  981.                                 }
  982.                                 break;
  983.                             case ENTRY_ROBERTS:
  984.                                 if (player->GetQuestStatus(QUEST_LIGHT_1) == QUEST_STATUS_INCOMPLETE)
  985.                                 {
  986.                                     if (IsHealed && !CanRun && Spell->Id == SPELL_FORTITUDE_R1)
  987.                                     {
  988.                                         DoScriptText(SAY_ROBERTS_THANKS, me, caster);
  989.                                         CanRun = true;
  990.                                     }
  991.                                     else if (!IsHealed && Spell->Id == SPELL_LESSER_HEAL_R2)
  992.                                     {
  993.                                         CasterGUID = caster->GetGUID();
  994.                                         me->SetStandState(UNIT_STAND_STATE_STAND);
  995.                                         DoScriptText(SAY_COMMON_HEALED, me, caster);
  996.                                         IsHealed = true;
  997.                                     }
  998.                                 }
  999.                                 break;
  1000.                             case ENTRY_DOLF:
  1001.                                 if (player->GetQuestStatus(QUEST_LIGHT_2) == QUEST_STATUS_INCOMPLETE)
  1002.                                 {
  1003.                                     if (IsHealed && !CanRun && Spell->Id == SPELL_FORTITUDE_R1)
  1004.                                     {
  1005.                                         DoScriptText(SAY_DOLF_THANKS, me, caster);
  1006.                                         CanRun = true;
  1007.                                     }
  1008.                                     else if (!IsHealed && Spell->Id == SPELL_LESSER_HEAL_R2)
  1009.                                     {
  1010.                                         CasterGUID = caster->GetGUID();
  1011.                                         me->SetStandState(UNIT_STAND_STATE_STAND);
  1012.                                         DoScriptText(SAY_COMMON_HEALED, me, caster);
  1013.                                         IsHealed = true;
  1014.                                     }
  1015.                                 }
  1016.                                 break;
  1017.                             case ENTRY_KORJA:
  1018.                                 if (player->GetQuestStatus(QUEST_SPIRIT) == QUEST_STATUS_INCOMPLETE)
  1019.                                 {
  1020.                                     if (IsHealed && !CanRun && Spell->Id == SPELL_FORTITUDE_R1)
  1021.                                     {
  1022.                                         DoScriptText(SAY_KORJA_THANKS, me, caster);
  1023.                                         CanRun = true;
  1024.                                     }
  1025.                                     else if (!IsHealed && Spell->Id == SPELL_LESSER_HEAL_R2)
  1026.                                     {
  1027.                                         CasterGUID = caster->GetGUID();
  1028.                                         me->SetStandState(UNIT_STAND_STATE_STAND);
  1029.                                         DoScriptText(SAY_COMMON_HEALED, me, caster);
  1030.                                         IsHealed = true;
  1031.                                     }
  1032.                                 }
  1033.                                 break;
  1034.                             case ENTRY_DG_KEL:
  1035.                                 if (player->GetQuestStatus(QUEST_DARKNESS) == QUEST_STATUS_INCOMPLETE)
  1036.                                 {
  1037.                                     if (IsHealed && !CanRun && Spell->Id == SPELL_FORTITUDE_R1)
  1038.                                     {
  1039.                                         DoScriptText(SAY_DG_KEL_THANKS, me, caster);
  1040.                                         CanRun = true;
  1041.                                     }
  1042.                                     else if (!IsHealed && Spell->Id == SPELL_LESSER_HEAL_R2)
  1043.                                     {
  1044.                                         CasterGUID = caster->GetGUID();
  1045.                                         me->SetStandState(UNIT_STAND_STATE_STAND);
  1046.                                         DoScriptText(SAY_COMMON_HEALED, me, caster);
  1047.                                         IsHealed = true;
  1048.                                     }
  1049.                                 }
  1050.                                 break;
  1051.                         }
  1052.  
  1053.                         //give quest credit, not expect any special quest objectives
  1054.                         if (CanRun)
  1055.                             player->TalkedToCreature(me->GetEntry(), me->GetGUID());
  1056.                     }
  1057.                 }
  1058.             }
  1059.  
  1060.             void WaypointReached(uint32 /*waypointId*/)
  1061.             {
  1062.  
  1063.             }
  1064.  
  1065.             void UpdateAI(uint32 const diff)
  1066.             {
  1067.                 if (CanRun && !me->isInCombat())
  1068.                 {
  1069.                     if (RunAwayTimer <= diff)
  1070.                     {
  1071.                         if (Unit* unit = Unit::GetUnit(*me, CasterGUID))
  1072.                         {
  1073.                             switch (me->GetEntry())
  1074.                             {
  1075.                                 case ENTRY_SHAYA:
  1076.                                     DoScriptText(SAY_SHAYA_GOODBYE, me, unit);
  1077.                                     break;
  1078.                                 case ENTRY_ROBERTS:
  1079.                                     DoScriptText(SAY_ROBERTS_GOODBYE, me, unit);
  1080.                                     break;
  1081.                                 case ENTRY_DOLF:
  1082.                                     DoScriptText(SAY_DOLF_GOODBYE, me, unit);
  1083.                                     break;
  1084.                                 case ENTRY_KORJA:
  1085.                                     DoScriptText(SAY_KORJA_GOODBYE, me, unit);
  1086.                                     break;
  1087.                                 case ENTRY_DG_KEL:
  1088.                                     DoScriptText(SAY_DG_KEL_GOODBYE, me, unit);
  1089.                                     break;
  1090.                             }
  1091.  
  1092.                             Start(false, true, true);
  1093.                         }
  1094.                         else
  1095.                             EnterEvadeMode();                       //something went wrong
  1096.  
  1097.                         RunAwayTimer = 30000;
  1098.                     }
  1099.                     else
  1100.                         RunAwayTimer -= diff;
  1101.                 }
  1102.  
  1103.                 npc_escortAI::UpdateAI(diff);
  1104.             }
  1105.         };
  1106.  
  1107.         CreatureAI* GetAI(Creature* creature) const
  1108.         {
  1109.             return new npc_garments_of_questsAI(creature);
  1110.         }
  1111. };
  1112.  
  1113. /*######
  1114. ## npc_guardian
  1115. ######*/
  1116.  
  1117. #define SPELL_DEATHTOUCH                5
  1118.  
  1119. class npc_guardian : public CreatureScript
  1120. {
  1121.     public:
  1122.         npc_guardian() : CreatureScript("npc_guardian") { }
  1123.  
  1124.         struct npc_guardianAI : public ScriptedAI
  1125.         {
  1126.             npc_guardianAI(Creature* creature) : ScriptedAI(creature) {}
  1127.  
  1128.             void Reset()
  1129.             {
  1130.                 me->SetFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NON_ATTACKABLE);
  1131.             }
  1132.  
  1133.             void EnterCombat(Unit* /*who*/)
  1134.             {
  1135.             }
  1136.  
  1137.             void UpdateAI(uint32 const /*diff*/)
  1138.             {
  1139.                 if (!UpdateVictim())
  1140.                     return;
  1141.  
  1142.                 if (me->isAttackReady())
  1143.                 {
  1144.                     DoCast(me->getVictim(), SPELL_DEATHTOUCH, true);
  1145.                     me->resetAttackTimer();
  1146.                 }
  1147.             }
  1148.         };
  1149.  
  1150.         CreatureAI* GetAI(Creature* creature) const
  1151.         {
  1152.             return new npc_guardianAI(creature);
  1153.         }
  1154. };
  1155.  
  1156. /*######
  1157. ## npc_mount_vendor
  1158. ######*/
  1159.  
  1160. class npc_mount_vendor : public CreatureScript
  1161. {
  1162.     public:
  1163.         npc_mount_vendor() : CreatureScript("npc_mount_vendor") { }
  1164.  
  1165.         bool OnGossipHello(Player* player, Creature* creature)
  1166.         {
  1167.             if (creature->isQuestGiver())
  1168.                 player->PrepareQuestMenu(creature->GetGUID());
  1169.  
  1170.             bool canBuy = false;
  1171.             uint32 vendor = creature->GetEntry();
  1172.             uint8 race = player->getRace();
  1173.  
  1174.             switch (vendor)
  1175.             {
  1176.                 case 384:                                           //Katie Hunter
  1177.                 case 1460:                                          //Unger Statforth
  1178.                 case 2357:                                          //Merideth Carlson
  1179.                 case 4885:                                          //Gregor MacVince
  1180.                     if (player->GetReputationRank(72) != REP_EXALTED && race != RACE_HUMAN)
  1181.                         player->SEND_GOSSIP_MENU(5855, creature->GetGUID());
  1182.                     else canBuy = true;
  1183.                     break;
  1184.                 case 1261:                                          //Veron Amberstill
  1185.                     if (player->GetReputationRank(47) != REP_EXALTED && race != RACE_DWARF)
  1186.                         player->SEND_GOSSIP_MENU(5856, creature->GetGUID());
  1187.                     else canBuy = true;
  1188.                     break;
  1189.                 case 3362:                                          //Ogunaro Wolfrunner
  1190.                     if (player->GetReputationRank(76) != REP_EXALTED && race != RACE_ORC)
  1191.                         player->SEND_GOSSIP_MENU(5841, creature->GetGUID());
  1192.                     else canBuy = true;
  1193.                     break;
  1194.                 case 3685:                                          //Harb Clawhoof
  1195.                     if (player->GetReputationRank(81) != REP_EXALTED && race != RACE_TAUREN)
  1196.                         player->SEND_GOSSIP_MENU(5843, creature->GetGUID());
  1197.                     else canBuy = true;
  1198.                     break;
  1199.                 case 4730:                                          //Lelanai
  1200.                     if (player->GetReputationRank(69) != REP_EXALTED && race != RACE_NIGHTELF)
  1201.                         player->SEND_GOSSIP_MENU(5844, creature->GetGUID());
  1202.                     else canBuy = true;
  1203.                     break;
  1204.                 case 4731:                                          //Zachariah Post
  1205.                     if (player->GetReputationRank(68) != REP_EXALTED && race != RACE_UNDEAD_PLAYER)
  1206.                         player->SEND_GOSSIP_MENU(5840, creature->GetGUID());
  1207.                     else canBuy = true;
  1208.                     break;
  1209.                 case 7952:                                          //Zjolnir
  1210.                     if (player->GetReputationRank(530) != REP_EXALTED && race != RACE_TROLL)
  1211.                         player->SEND_GOSSIP_MENU(5842, creature->GetGUID());
  1212.                     else canBuy = true;
  1213.                     break;
  1214.                 case 7955:                                          //Milli Featherwhistle
  1215.                     if (player->GetReputationRank(54) != REP_EXALTED && race != RACE_GNOME)
  1216.                         player->SEND_GOSSIP_MENU(5857, creature->GetGUID());
  1217.                     else canBuy = true;
  1218.                     break;
  1219.                 case 16264:                                         //Winaestra
  1220.                     if (player->GetReputationRank(911) != REP_EXALTED && race != RACE_BLOODELF)
  1221.                         player->SEND_GOSSIP_MENU(10305, creature->GetGUID());
  1222.                     else canBuy = true;
  1223.                     break;
  1224.                 case 17584:                                         //Torallius the Pack Handler
  1225.                     if (player->GetReputationRank(930) != REP_EXALTED && race != RACE_DRAENEI)
  1226.                         player->SEND_GOSSIP_MENU(10239, creature->GetGUID());
  1227.                     else canBuy = true;
  1228.                     break;
  1229.                 case 48510:                                         //Kall Worthalon
  1230.                     if (player->GetReputationRank(1133) != REP_EXALTED && race != RACE_GOBLIN)
  1231.                         player->SEND_GOSSIP_MENU(30002, creature->GetGUID());
  1232.                     else canBuy = true;
  1233.                     break;
  1234.                 case 65068:                                         //Old Whitenose
  1235.                     canBuy = true;
  1236.                     break;
  1237.                 case 66022:                                         //Turtlemaster Odai
  1238.                     canBuy = true;
  1239.                     break;
  1240.             }
  1241.  
  1242.             if (canBuy)
  1243.             {
  1244.                 if (creature->isVendor())
  1245.                     player->ADD_GOSSIP_ITEM(GOSSIP_ICON_VENDOR, GOSSIP_TEXT_BROWSE_GOODS, GOSSIP_SENDER_MAIN, GOSSIP_ACTION_TRADE);
  1246.                 player->SEND_GOSSIP_MENU(player->GetGossipTextId(creature), creature->GetGUID());
  1247.             }
  1248.             return true;
  1249.         }
  1250.  
  1251.         bool OnGossipSelect(Player* player, Creature* creature, uint32 /*sender*/, uint32 action)
  1252.         {
  1253.             player->PlayerTalkClass->ClearMenus();
  1254.             if (action == GOSSIP_ACTION_TRADE)
  1255.                 player->GetSession()->SendListInventory(creature->GetGUID());
  1256.  
  1257.             return true;
  1258.         }
  1259. };
  1260.  
  1261. /*######
  1262. ## npc_rogue_trainer
  1263. ######*/
  1264.  
  1265. #define GOSSIP_HELLO_ROGUE1 "I wish to unlearn my talents"
  1266. #define GOSSIP_HELLO_ROGUE2 "<Take the letter>"
  1267. #define GOSSIP_HELLO_ROGUE3 "Purchase a Dual Talent Specialization."
  1268. #define GOSSIP_HELLO_ROGUE4 "I wish to unlearn my specialization"
  1269.  
  1270. class npc_rogue_trainer : public CreatureScript
  1271. {
  1272.     public:
  1273.         npc_rogue_trainer() : CreatureScript("npc_rogue_trainer") { }
  1274.  
  1275.         bool OnGossipHello(Player* player, Creature* creature)
  1276.         {
  1277.             if (creature->isQuestGiver())
  1278.                 player->PrepareQuestMenu(creature->GetGUID());
  1279.  
  1280.             if (creature->isTrainer())
  1281.                 player->ADD_GOSSIP_ITEM(GOSSIP_ICON_TRAINER, GOSSIP_TEXT_TRAIN, GOSSIP_SENDER_MAIN, GOSSIP_ACTION_TRAIN);
  1282.  
  1283.             if (creature->isCanTrainingAndResetTalentsOf(player))
  1284.                 player->ADD_GOSSIP_ITEM(GOSSIP_ICON_TRAINER, GOSSIP_HELLO_ROGUE1, GOSSIP_SENDER_MAIN, GOSSIP_OPTION_UNLEARNTALENTS);
  1285.  
  1286.             if (creature->isCanTrainingAndResetTalentsOf(player))
  1287.                 player->ADD_GOSSIP_ITEM(GOSSIP_ICON_TRAINER, GOSSIP_HELLO_ROGUE4, GOSSIP_SENDER_MAIN, GOSSIP_OPTION_UNLEARNSPECIALIZATION);
  1288.  
  1289.             if (player->GetSpecsCount() == 1 && creature->isCanTrainingAndResetTalentsOf(player) && player->getLevel() >= sWorld->getIntConfig(CONFIG_MIN_DUALSPEC_LEVEL))
  1290.                 player->ADD_GOSSIP_ITEM(GOSSIP_ICON_TRAINER, GOSSIP_HELLO_ROGUE3, GOSSIP_SENDER_MAIN, GOSSIP_OPTION_LEARNDUALSPEC);
  1291.  
  1292.             if (player->getClass() == CLASS_ROGUE && player->getLevel() >= 24 && !player->HasItemCount(17126) && !player->GetQuestRewardStatus(6681))
  1293.             {
  1294.                 player->ADD_GOSSIP_ITEM(GOSSIP_ICON_CHAT, GOSSIP_HELLO_ROGUE2, GOSSIP_SENDER_MAIN, GOSSIP_ACTION_INFO_DEF + 1);
  1295.                 player->SEND_GOSSIP_MENU(5996, creature->GetGUID());
  1296.             } else
  1297.                 player->SEND_GOSSIP_MENU(player->GetGossipTextId(creature), creature->GetGUID());
  1298.  
  1299.             return true;
  1300.         }
  1301.  
  1302.         bool OnGossipSelect(Player* player, Creature* creature, uint32 /*sender*/, uint32 action)
  1303.         {
  1304.             player->PlayerTalkClass->ClearMenus();
  1305.             switch (action)
  1306.             {
  1307.                 case GOSSIP_ACTION_INFO_DEF + 1:
  1308.                     player->CLOSE_GOSSIP_MENU();
  1309.                     player->CastSpell(player, 21100, false);
  1310.                     break;
  1311.                 case GOSSIP_ACTION_TRAIN:
  1312.                     player->GetSession()->SendTrainerList(creature->GetGUID());
  1313.                     break;
  1314.                 case GOSSIP_OPTION_UNLEARNTALENTS:
  1315.                     player->CLOSE_GOSSIP_MENU();
  1316.                     player->SendTalentWipeConfirm(creature->GetGUID(), false);
  1317.                     break;
  1318.                 case GOSSIP_OPTION_UNLEARNSPECIALIZATION:
  1319.                     player->CLOSE_GOSSIP_MENU();
  1320.                     player->SendTalentWipeConfirm(creature->GetGUID(), true);
  1321.                     break;
  1322.                 case GOSSIP_OPTION_LEARNDUALSPEC:
  1323.                     if (player->GetSpecsCount() == 1 && !(player->getLevel() < sWorld->getIntConfig(CONFIG_MIN_DUALSPEC_LEVEL)))
  1324.                     {
  1325.                         if (!player->HasEnoughMoney(uint64(10000000)))
  1326.                         {
  1327.                             player->SendBuyError(BUY_ERR_NOT_ENOUGHT_MONEY, 0, 0, 0);
  1328.                             player->PlayerTalkClass->SendCloseGossip();
  1329.                             break;
  1330.                         }
  1331.                         else
  1332.                         {
  1333.                             player->ModifyMoney(int64(-10000000));
  1334.  
  1335.                             // Cast spells that teach dual spec
  1336.                             // Both are also ImplicitTarget self and must be cast by player
  1337.                             player->CastSpell(player, 63680, true, NULL, NULLAURA_EFFECT, player->GetGUID());
  1338.                             player->CastSpell(player, 63624, true, NULL, NULLAURA_EFFECT, player->GetGUID());
  1339.  
  1340.                             // Should show another Gossip text with "Congratulations..."
  1341.                             player->PlayerTalkClass->SendCloseGossip();
  1342.                         }
  1343.                     }
  1344.                     break;
  1345.             }
  1346.             return true;
  1347.         }
  1348. };
  1349.  
  1350. /*######
  1351. ## npc_sayge
  1352. ######*/
  1353.  
  1354. #define SPELL_DMG       23768                               //dmg
  1355. #define SPELL_RES       23769                               //res
  1356. #define SPELL_ARM       23767                               //arm
  1357. #define SPELL_SPI       23738                               //spi
  1358. #define SPELL_INT       23766                               //int
  1359. #define SPELL_STM       23737                               //stm
  1360. #define SPELL_STR       23735                               //str
  1361. #define SPELL_AGI       23736                               //agi
  1362. #define SPELL_FORTUNE   23765                               //faire fortune
  1363.  
  1364. #define GOSSIP_HELLO_SAYGE  "Yes"
  1365. #define GOSSIP_SENDACTION_SAYGE1    "Slay the Man"
  1366. #define GOSSIP_SENDACTION_SAYGE2    "Turn him over to liege"
  1367. #define GOSSIP_SENDACTION_SAYGE3    "Confiscate the corn"
  1368. #define GOSSIP_SENDACTION_SAYGE4    "Let him go and have the corn"
  1369. #define GOSSIP_SENDACTION_SAYGE5    "Execute your friend painfully"
  1370. #define GOSSIP_SENDACTION_SAYGE6    "Execute your friend painlessly"
  1371. #define GOSSIP_SENDACTION_SAYGE7    "Let your friend go"
  1372. #define GOSSIP_SENDACTION_SAYGE8    "Confront the diplomat"
  1373. #define GOSSIP_SENDACTION_SAYGE9    "Show not so quiet defiance"
  1374. #define GOSSIP_SENDACTION_SAYGE10   "Remain quiet"
  1375. #define GOSSIP_SENDACTION_SAYGE11   "Speak against your brother openly"
  1376. #define GOSSIP_SENDACTION_SAYGE12   "Help your brother in"
  1377. #define GOSSIP_SENDACTION_SAYGE13   "Keep your brother out without letting him know"
  1378. #define GOSSIP_SENDACTION_SAYGE14   "Take credit, keep gold"
  1379. #define GOSSIP_SENDACTION_SAYGE15   "Take credit, share the gold"
  1380. #define GOSSIP_SENDACTION_SAYGE16   "Let the knight take credit"
  1381. #define GOSSIP_SENDACTION_SAYGE17   "Thanks"
  1382.  
  1383. class npc_sayge : public CreatureScript
  1384. {
  1385.     public:
  1386.         npc_sayge() : CreatureScript("npc_sayge") { }
  1387.  
  1388.         bool OnGossipHello(Player* player, Creature* creature)
  1389.         {
  1390.             if (creature->isQuestGiver())
  1391.                 player->PrepareQuestMenu(creature->GetGUID());
  1392.  
  1393.             if (player->HasSpellCooldown(SPELL_INT) ||
  1394.                 player->HasSpellCooldown(SPELL_ARM) ||
  1395.                 player->HasSpellCooldown(SPELL_DMG) ||
  1396.                 player->HasSpellCooldown(SPELL_RES) ||
  1397.                 player->HasSpellCooldown(SPELL_STR) ||
  1398.                 player->HasSpellCooldown(SPELL_AGI) ||
  1399.                 player->HasSpellCooldown(SPELL_STM) ||
  1400.                 player->HasSpellCooldown(SPELL_SPI))
  1401.                 player->SEND_GOSSIP_MENU(7393, creature->GetGUID());
  1402.             else
  1403.             {
  1404.                 player->ADD_GOSSIP_ITEM(GOSSIP_ICON_CHAT, GOSSIP_HELLO_SAYGE, GOSSIP_SENDER_MAIN, GOSSIP_ACTION_INFO_DEF + 1);
  1405.                 player->SEND_GOSSIP_MENU(7339, creature->GetGUID());
  1406.             }
  1407.  
  1408.             return true;
  1409.         }
  1410.  
  1411.         void SendAction(Player* player, Creature* creature, uint32 action)
  1412.         {
  1413.             switch (action)
  1414.             {
  1415.                 case GOSSIP_ACTION_INFO_DEF + 1:
  1416.                     player->ADD_GOSSIP_ITEM(GOSSIP_ICON_CHAT, GOSSIP_SENDACTION_SAYGE1,            GOSSIP_SENDER_MAIN, GOSSIP_ACTION_INFO_DEF + 2);
  1417.                     player->ADD_GOSSIP_ITEM(GOSSIP_ICON_CHAT, GOSSIP_SENDACTION_SAYGE2,            GOSSIP_SENDER_MAIN, GOSSIP_ACTION_INFO_DEF + 3);
  1418.                     player->ADD_GOSSIP_ITEM(GOSSIP_ICON_CHAT, GOSSIP_SENDACTION_SAYGE3,            GOSSIP_SENDER_MAIN, GOSSIP_ACTION_INFO_DEF + 4);
  1419.                     player->ADD_GOSSIP_ITEM(GOSSIP_ICON_CHAT, GOSSIP_SENDACTION_SAYGE4,            GOSSIP_SENDER_MAIN, GOSSIP_ACTION_INFO_DEF + 5);
  1420.                     player->SEND_GOSSIP_MENU(7340, creature->GetGUID());
  1421.                     break;
  1422.                 case GOSSIP_ACTION_INFO_DEF + 2:
  1423.                     player->ADD_GOSSIP_ITEM(GOSSIP_ICON_CHAT, GOSSIP_SENDACTION_SAYGE5,            GOSSIP_SENDER_MAIN + 1, GOSSIP_ACTION_INFO_DEF);
  1424.                     player->ADD_GOSSIP_ITEM(GOSSIP_ICON_CHAT, GOSSIP_SENDACTION_SAYGE6,            GOSSIP_SENDER_MAIN + 2, GOSSIP_ACTION_INFO_DEF);
  1425.                     player->ADD_GOSSIP_ITEM(GOSSIP_ICON_CHAT, GOSSIP_SENDACTION_SAYGE7,            GOSSIP_SENDER_MAIN + 3, GOSSIP_ACTION_INFO_DEF);
  1426.                     player->SEND_GOSSIP_MENU(7341, creature->GetGUID());
  1427.                     break;
  1428.                 case GOSSIP_ACTION_INFO_DEF + 3:
  1429.                     player->ADD_GOSSIP_ITEM(GOSSIP_ICON_CHAT, GOSSIP_SENDACTION_SAYGE8,            GOSSIP_SENDER_MAIN + 4, GOSSIP_ACTION_INFO_DEF);
  1430.                     player->ADD_GOSSIP_ITEM(GOSSIP_ICON_CHAT, GOSSIP_SENDACTION_SAYGE9,            GOSSIP_SENDER_MAIN + 5, GOSSIP_ACTION_INFO_DEF);
  1431.                     player->ADD_GOSSIP_ITEM(GOSSIP_ICON_CHAT, GOSSIP_SENDACTION_SAYGE10,           GOSSIP_SENDER_MAIN + 2, GOSSIP_ACTION_INFO_DEF);
  1432.                     player->SEND_GOSSIP_MENU(7361, creature->GetGUID());
  1433.                     break;
  1434.                 case GOSSIP_ACTION_INFO_DEF + 4:
  1435.                     player->ADD_GOSSIP_ITEM(GOSSIP_ICON_CHAT, GOSSIP_SENDACTION_SAYGE11,           GOSSIP_SENDER_MAIN + 6, GOSSIP_ACTION_INFO_DEF);
  1436.                     player->ADD_GOSSIP_ITEM(GOSSIP_ICON_CHAT, GOSSIP_SENDACTION_SAYGE12,           GOSSIP_SENDER_MAIN + 7, GOSSIP_ACTION_INFO_DEF);
  1437.                     player->ADD_GOSSIP_ITEM(GOSSIP_ICON_CHAT, GOSSIP_SENDACTION_SAYGE13,           GOSSIP_SENDER_MAIN + 8, GOSSIP_ACTION_INFO_DEF);
  1438.                     player->SEND_GOSSIP_MENU(7362, creature->GetGUID());
  1439.                     break;
  1440.                 case GOSSIP_ACTION_INFO_DEF + 5:
  1441.                     player->ADD_GOSSIP_ITEM(GOSSIP_ICON_CHAT, GOSSIP_SENDACTION_SAYGE14,           GOSSIP_SENDER_MAIN + 5, GOSSIP_ACTION_INFO_DEF);
  1442.                     player->ADD_GOSSIP_ITEM(GOSSIP_ICON_CHAT, GOSSIP_SENDACTION_SAYGE15,           GOSSIP_SENDER_MAIN + 4, GOSSIP_ACTION_INFO_DEF);
  1443.                     player->ADD_GOSSIP_ITEM(GOSSIP_ICON_CHAT, GOSSIP_SENDACTION_SAYGE16,           GOSSIP_SENDER_MAIN + 3, GOSSIP_ACTION_INFO_DEF);
  1444.                     player->SEND_GOSSIP_MENU(7363, creature->GetGUID());
  1445.                     break;
  1446.                 case GOSSIP_ACTION_INFO_DEF:
  1447.                     player->ADD_GOSSIP_ITEM(GOSSIP_ICON_CHAT, GOSSIP_SENDACTION_SAYGE17,           GOSSIP_SENDER_MAIN, GOSSIP_ACTION_INFO_DEF + 6);
  1448.                     player->SEND_GOSSIP_MENU(7364, creature->GetGUID());
  1449.                     break;
  1450.                 case GOSSIP_ACTION_INFO_DEF + 6:
  1451.                     creature->CastSpell(player, SPELL_FORTUNE, false);
  1452.                     player->SEND_GOSSIP_MENU(7365, creature->GetGUID());
  1453.                     break;
  1454.             }
  1455.         }
  1456.  
  1457.         bool OnGossipSelect(Player* player, Creature* creature, uint32 sender, uint32 action)
  1458.         {
  1459.             player->PlayerTalkClass->ClearMenus();
  1460.             switch (sender)
  1461.             {
  1462.                 case GOSSIP_SENDER_MAIN:
  1463.                     SendAction(player, creature, action);
  1464.                     break;
  1465.                 case GOSSIP_SENDER_MAIN + 1:
  1466.                     creature->CastSpell(player, SPELL_DMG, false);
  1467.                     player->AddSpellCooldown(SPELL_DMG, 0, time(NULL) + 7200);
  1468.                     SendAction(player, creature, action);
  1469.                     break;
  1470.                 case GOSSIP_SENDER_MAIN + 2:
  1471.                     creature->CastSpell(player, SPELL_RES, false);
  1472.                     player->AddSpellCooldown(SPELL_RES, 0, time(NULL) + 7200);
  1473.                     SendAction(player, creature, action);
  1474.                     break;
  1475.                 case GOSSIP_SENDER_MAIN + 3:
  1476.                     creature->CastSpell(player, SPELL_ARM, false);
  1477.                     player->AddSpellCooldown(SPELL_ARM, 0, time(NULL) + 7200);
  1478.                     SendAction(player, creature, action);
  1479.                     break;
  1480.                 case GOSSIP_SENDER_MAIN + 4:
  1481.                     creature->CastSpell(player, SPELL_SPI, false);
  1482.                     player->AddSpellCooldown(SPELL_SPI, 0, time(NULL) + 7200);
  1483.                     SendAction(player, creature, action);
  1484.                     break;
  1485.                 case GOSSIP_SENDER_MAIN + 5:
  1486.                     creature->CastSpell(player, SPELL_INT, false);
  1487.                     player->AddSpellCooldown(SPELL_INT, 0, time(NULL) + 7200);
  1488.                     SendAction(player, creature, action);
  1489.                     break;
  1490.                 case GOSSIP_SENDER_MAIN + 6:
  1491.                     creature->CastSpell(player, SPELL_STM, false);
  1492.                     player->AddSpellCooldown(SPELL_STM, 0, time(NULL) + 7200);
  1493.                     SendAction(player, creature, action);
  1494.                     break;
  1495.                 case GOSSIP_SENDER_MAIN + 7:
  1496.                     creature->CastSpell(player, SPELL_STR, false);
  1497.                     player->AddSpellCooldown(SPELL_STR, 0, time(NULL) + 7200);
  1498.                     SendAction(player, creature, action);
  1499.                     break;
  1500.                 case GOSSIP_SENDER_MAIN + 8:
  1501.                     creature->CastSpell(player, SPELL_AGI, false);
  1502.                     player->AddSpellCooldown(SPELL_AGI, 0, time(NULL) + 7200);
  1503.                     SendAction(player, creature, action);
  1504.                     break;
  1505.             }
  1506.             return true;
  1507.         }
  1508. };
  1509.  
  1510. class npc_steam_tonk : public CreatureScript
  1511. {
  1512.     public:
  1513.         npc_steam_tonk() : CreatureScript("npc_steam_tonk") { }
  1514.  
  1515.         struct npc_steam_tonkAI : public ScriptedAI
  1516.         {
  1517.             npc_steam_tonkAI(Creature* creature) : ScriptedAI(creature) {}
  1518.  
  1519.             void Reset() {}
  1520.             void EnterCombat(Unit* /*who*/) {}
  1521.  
  1522.             void OnPossess(bool apply)
  1523.             {
  1524.                 if (apply)
  1525.                 {
  1526.                     // Initialize the action bar without the melee attack command
  1527.                     me->InitCharmInfo();
  1528.                     me->GetCharmInfo()->InitEmptyActionBar(false);
  1529.  
  1530.                     me->SetReactState(REACT_PASSIVE);
  1531.                 }
  1532.                 else
  1533.                     me->SetReactState(REACT_AGGRESSIVE);
  1534.             }
  1535.         };
  1536.  
  1537.         CreatureAI* GetAI(Creature* creature) const
  1538.         {
  1539.             return new npc_steam_tonkAI(creature);
  1540.         }
  1541. };
  1542.  
  1543. #define SPELL_TONK_MINE_DETONATE 25099
  1544.  
  1545. class npc_tonk_mine : public CreatureScript
  1546. {
  1547.     public:
  1548.         npc_tonk_mine() : CreatureScript("npc_tonk_mine") { }
  1549.  
  1550.         struct npc_tonk_mineAI : public ScriptedAI
  1551.         {
  1552.             npc_tonk_mineAI(Creature* creature) : ScriptedAI(creature)
  1553.             {
  1554.                 me->SetReactState(REACT_PASSIVE);
  1555.             }
  1556.  
  1557.             uint32 ExplosionTimer;
  1558.  
  1559.             void Reset()
  1560.             {
  1561.                 ExplosionTimer = 3000;
  1562.             }
  1563.  
  1564.             void EnterCombat(Unit* /*who*/) {}
  1565.             void AttackStart(Unit* /*who*/) {}
  1566.             void MoveInLineOfSight(Unit* /*who*/) {}
  1567.  
  1568.             void UpdateAI(uint32 const diff)
  1569.             {
  1570.                 if (ExplosionTimer <= diff)
  1571.                 {
  1572.                     DoCast(me, SPELL_TONK_MINE_DETONATE, true);
  1573.                     me->setDeathState(DEAD); // unsummon it
  1574.                 }
  1575.                 else
  1576.                     ExplosionTimer -= diff;
  1577.             }
  1578.         };
  1579.  
  1580.         CreatureAI* GetAI(Creature* creature) const
  1581.         {
  1582.             return new npc_tonk_mineAI(creature);
  1583.         }
  1584. };
  1585.  
  1586. /*####
  1587. ## npc_brewfest_reveler
  1588. ####*/
  1589.  
  1590. class npc_brewfest_reveler : public CreatureScript
  1591. {
  1592.     public:
  1593.         npc_brewfest_reveler() : CreatureScript("npc_brewfest_reveler") { }
  1594.  
  1595.         struct npc_brewfest_revelerAI : public ScriptedAI
  1596.         {
  1597.             npc_brewfest_revelerAI(Creature* creature) : ScriptedAI(creature) {}
  1598.             void ReceiveEmote(Player* player, uint32 emote)
  1599.             {
  1600.                 if (!IsHolidayActive(HOLIDAY_BREWFEST))
  1601.                     return;
  1602.  
  1603.                 if (emote == TEXT_EMOTE_DANCE)
  1604.                     me->CastSpell(player, 41586, false);
  1605.             }
  1606.         };
  1607.  
  1608.         CreatureAI* GetAI(Creature* creature) const
  1609.         {
  1610.             return new npc_brewfest_revelerAI(creature);
  1611.         }
  1612. };
  1613.  
  1614. /*####
  1615. ## npc_winter_reveler
  1616. ####*/
  1617.  
  1618. enum WinterReveler
  1619. {
  1620.     SPELL_MISTLETOE_DEBUFF       = 26218,
  1621.     SPELL_CREATE_MISTLETOE       = 26206,
  1622.     SPELL_CREATE_HOLLY           = 26207,
  1623.     SPELL_CREATE_SNOWFLAKES      = 45036,
  1624. };
  1625.  
  1626. class npc_winter_reveler : public CreatureScript
  1627. {
  1628.     public:
  1629.         npc_winter_reveler() : CreatureScript("npc_winter_reveler") { }
  1630.  
  1631.         struct npc_winter_revelerAI : public ScriptedAI
  1632.         {
  1633.             npc_winter_revelerAI(Creature* creature) : ScriptedAI(creature) {}
  1634.  
  1635.             void ReceiveEmote(Player* player, uint32 emote)
  1636.             {
  1637.                 if (player->HasAura(SPELL_MISTLETOE_DEBUFF))
  1638.                     return;
  1639.  
  1640.                 if (!IsHolidayActive(HOLIDAY_FEAST_OF_WINTER_VEIL))
  1641.                     return;
  1642.  
  1643.                 if (emote == TEXT_EMOTE_KISS)
  1644.                 {
  1645.                     uint32 spellId = RAND<uint32>(SPELL_CREATE_MISTLETOE, SPELL_CREATE_HOLLY, SPELL_CREATE_SNOWFLAKES);
  1646.                     me->CastSpell(player, spellId, false);
  1647.                     me->CastSpell(player, SPELL_MISTLETOE_DEBUFF, false);
  1648.                 }
  1649.             }
  1650.         };
  1651.  
  1652.         CreatureAI* GetAI(Creature* creature) const
  1653.         {
  1654.             return new npc_winter_revelerAI(creature);
  1655.         }
  1656. };
  1657.  
  1658. /*####
  1659. ## npc_snake_trap_serpents
  1660. ####*/
  1661.  
  1662. #define SPELL_MIND_NUMBING_POISON    25810   //Viper
  1663. #define SPELL_DEADLY_POISON          34655   //Venomous Snake
  1664. #define SPELL_CRIPPLING_POISON       30981   //Viper
  1665.  
  1666. #define VENOMOUS_SNAKE_TIMER 1500
  1667. #define VIPER_TIMER 3000
  1668.  
  1669. #define C_VIPER 19921
  1670.  
  1671. class npc_snake_trap : public CreatureScript
  1672. {
  1673.     public:
  1674.         npc_snake_trap() : CreatureScript("npc_snake_trap_serpents") { }
  1675.  
  1676.         struct npc_snake_trap_serpentsAI : public ScriptedAI
  1677.         {
  1678.             npc_snake_trap_serpentsAI(Creature* creature) : ScriptedAI(creature) {}
  1679.  
  1680.             uint32 SpellTimer;
  1681.             bool IsViper;
  1682.  
  1683.             void EnterCombat(Unit* /*who*/) {}
  1684.  
  1685.             void Reset()
  1686.             {
  1687.                 SpellTimer = 0;
  1688.  
  1689.                 CreatureTemplate const* Info = me->GetCreatureTemplate();
  1690.  
  1691.                 IsViper = Info->Entry == C_VIPER ? true : false;
  1692.  
  1693.                 me->SetMaxHealth(uint32(107 * (me->getLevel() - 40) * 0.025f));
  1694.                 //Add delta to make them not all hit the same time
  1695.                 uint32 delta = (rand() % 7) * 100;
  1696.                 me->SetStatFloatValue(UNIT_FIELD_BASEATTACKTIME, float(Info->baseattacktime + delta));
  1697.                 me->SetStatFloatValue(UNIT_FIELD_RANGED_ATTACK_POWER, float(Info->attackpower));
  1698.  
  1699.                 // Start attacking attacker of owner on first ai update after spawn - move in line of sight may choose better target
  1700.                 if (!me->getVictim() && me->isSummon())
  1701.                     if (Unit* Owner = me->ToTempSummon()->GetSummoner())
  1702.                         if (Owner->getAttackerForHelper())
  1703.                             AttackStart(Owner->getAttackerForHelper());
  1704.             }
  1705.  
  1706.             //Redefined for random target selection:
  1707.             void MoveInLineOfSight(Unit* who)
  1708.             {
  1709.                 if (!me->getVictim() && me->canCreatureAttack(who))
  1710.                 {
  1711.                     if (me->GetDistanceZ(who) > CREATURE_Z_ATTACK_RANGE)
  1712.                         return;
  1713.  
  1714.                     float attackRadius = me->GetAttackDistance(who);
  1715.                     if (me->IsWithinDistInMap(who, attackRadius) && me->IsWithinLOSInMap(who))
  1716.                     {
  1717.                         if (!(rand() % 5))
  1718.                         {
  1719.                             me->setAttackTimer(BASE_ATTACK, (rand() % 10) * 100);
  1720.                             SpellTimer = (rand() % 10) * 100;
  1721.                             AttackStart(who);
  1722.                         }
  1723.                     }
  1724.                 }
  1725.             }
  1726.  
  1727.             void UpdateAI(uint32 const diff)
  1728.             {
  1729.                 if (!UpdateVictim())
  1730.                     return;
  1731.  
  1732.                 if (me->getVictim()->HasCrowdControlAura(me))
  1733.                 {
  1734.                     me->InterruptNonMeleeSpells(false);
  1735.                     return;
  1736.                 }
  1737.  
  1738.                 if (SpellTimer <= diff)
  1739.                 {
  1740.                     if (IsViper) //Viper
  1741.                     {
  1742.                         if (urand(0, 2) == 0) //33% chance to cast
  1743.                         {
  1744.                             uint32 spell;
  1745.                             if (urand(0, 1) == 0)
  1746.                                 spell = SPELL_MIND_NUMBING_POISON;
  1747.                             else
  1748.                                 spell = SPELL_CRIPPLING_POISON;
  1749.  
  1750.                             DoCast(me->getVictim(), spell);
  1751.                         }
  1752.  
  1753.                         SpellTimer = VIPER_TIMER;
  1754.                     }
  1755.                     else //Venomous Snake
  1756.                     {
  1757.                         if (urand(0, 2) == 0) //33% chance to cast
  1758.                             DoCast(me->getVictim(), SPELL_DEADLY_POISON);
  1759.                         SpellTimer = VENOMOUS_SNAKE_TIMER + (rand() % 5) * 100;
  1760.                     }
  1761.                 }
  1762.                 else
  1763.                     SpellTimer -= diff;
  1764.  
  1765.                 DoMeleeAttackIfReady();
  1766.             }
  1767.         };
  1768.  
  1769.         CreatureAI* GetAI(Creature* creature) const
  1770.         {
  1771.             return new npc_snake_trap_serpentsAI(creature);
  1772.         }
  1773. };
  1774.  
  1775. #define SAY_RANDOM_MOJO0    "Now that's what I call froggy-style!"
  1776. #define SAY_RANDOM_MOJO1    "Your lily pad or mine?"
  1777. #define SAY_RANDOM_MOJO2    "This won't take long, did it?"
  1778. #define SAY_RANDOM_MOJO3    "I thought you'd never ask!"
  1779. #define SAY_RANDOM_MOJO4    "I promise not to give you warts..."
  1780. #define SAY_RANDOM_MOJO5    "Feelin' a little froggy, are ya?"
  1781. #define SAY_RANDOM_MOJO6a   "Listen, "
  1782. #define SAY_RANDOM_MOJO6b   ", I know of a little swamp not too far from here...."
  1783. #define SAY_RANDOM_MOJO7    "There's just never enough Mojo to go around..."
  1784.  
  1785. class mob_mojo : public CreatureScript
  1786. {
  1787.     public:
  1788.         mob_mojo() : CreatureScript("mob_mojo") { }
  1789.  
  1790.         struct mob_mojoAI : public ScriptedAI
  1791.         {
  1792.             mob_mojoAI(Creature* creature) : ScriptedAI(creature) {Reset();}
  1793.             uint32 hearts;
  1794.             uint64 victimGUID;
  1795.             void Reset()
  1796.             {
  1797.                 victimGUID = 0;
  1798.                 hearts = 15000;
  1799.                 if (Unit* own = me->GetOwner())
  1800.                     me->GetMotionMaster()->MoveFollow(own, 0, 0);
  1801.             }
  1802.  
  1803.             void EnterCombat(Unit* /*who*/){}
  1804.  
  1805.             void UpdateAI(uint32 const diff)
  1806.             {
  1807.                 if (me->HasAura(20372))
  1808.                 {
  1809.                     if (hearts <= diff)
  1810.                     {
  1811.                         me->RemoveAurasDueToSpell(20372);
  1812.                         hearts = 15000;
  1813.                     } hearts -= diff;
  1814.                 }
  1815.             }
  1816.  
  1817.             void ReceiveEmote(Player* player, uint32 emote)
  1818.             {
  1819.                 me->HandleEmoteCommand(emote);
  1820.                 Unit* own = me->GetOwner();
  1821.                 if (!own || own->GetTypeId() != TYPEID_PLAYER || CAST_PLR(own)->GetTeam() != player->GetTeam())
  1822.                     return;
  1823.                 if (emote == TEXT_EMOTE_KISS)
  1824.                 {
  1825.                     std::string whisp = "";
  1826.                     switch (rand() % 8)
  1827.                     {
  1828.                         case 0:
  1829.                             whisp.append(SAY_RANDOM_MOJO0);
  1830.                             break;
  1831.                         case 1:
  1832.                             whisp.append(SAY_RANDOM_MOJO1);
  1833.                             break;
  1834.                         case 2:
  1835.                             whisp.append(SAY_RANDOM_MOJO2);
  1836.                             break;
  1837.                         case 3:
  1838.                             whisp.append(SAY_RANDOM_MOJO3);
  1839.                             break;
  1840.                         case 4:
  1841.                             whisp.append(SAY_RANDOM_MOJO4);
  1842.                             break;
  1843.                         case 5:
  1844.                             whisp.append(SAY_RANDOM_MOJO5);
  1845.                             break;
  1846.                         case 6:
  1847.                             whisp.append(SAY_RANDOM_MOJO6a);
  1848.                             whisp.append(player->GetName());
  1849.                             whisp.append(SAY_RANDOM_MOJO6b);
  1850.                             break;
  1851.                         case 7:
  1852.                             whisp.append(SAY_RANDOM_MOJO7);
  1853.                             break;
  1854.                     }
  1855.  
  1856.                     me->MonsterWhisper(whisp.c_str(), player->GetGUID());
  1857.                     if (victimGUID)
  1858.                         if (Player* victim = Unit::GetPlayer(*me, victimGUID))
  1859.                             victim->RemoveAura(43906);//remove polymorph frog thing
  1860.                     me->AddAura(43906, player);//add polymorph frog thing
  1861.                     victimGUID = player->GetGUID();
  1862.                     DoCast(me, 20372, true);//tag.hearts
  1863.                     me->GetMotionMaster()->MoveFollow(player, 0, 0);
  1864.                     hearts = 15000;
  1865.                 }
  1866.             }
  1867.         };
  1868.  
  1869.         CreatureAI* GetAI(Creature* creature) const
  1870.         {
  1871.             return new mob_mojoAI(creature);
  1872.         }
  1873. };
  1874.  
  1875. #define SPELL_ARCANE_SPEC 78832
  1876. #define SPELL_FIRE_SPEC 99062
  1877. #define SPELL_FROST_SPEC 59638
  1878.  
  1879. class npc_mirror_image : public CreatureScript
  1880. {
  1881. public:
  1882.     npc_mirror_image() : CreatureScript("npc_mirror_image") { }
  1883.  
  1884.     struct npc_mirror_imageAI : CasterAI
  1885.     {
  1886.         npc_mirror_imageAI(Creature* creature) : CasterAI(creature) {}
  1887.  
  1888.         uint32 spell_id;
  1889.  
  1890.         void InitializeAI()
  1891.         {
  1892.             spell_id = SPELL_FROST_SPEC;
  1893.  
  1894.             CasterAI::InitializeAI();
  1895.             Unit* owner = me->GetOwner();
  1896.             if (!owner)
  1897.                 return;
  1898.  
  1899.             if (Player* player = owner->ToPlayer())
  1900.             {
  1901.                 if (player->HasGlyph(63093))
  1902.                 {
  1903.                     switch (player->GetSpecializationId(player->GetActiveSpec()))
  1904.                     {
  1905.                         case SPEC_MAGE_ARCANE:
  1906.                             spell_id = SPELL_ARCANE_SPEC;
  1907.                             break;
  1908.                         case SPEC_MAGE_FIRE:
  1909.                             spell_id = SPELL_FIRE_SPEC;
  1910.                             break;
  1911.                     }
  1912.                 }
  1913.             }
  1914.  
  1915.             // Inherit Master's Threat List (not yet implemented)
  1916.             owner->CastSpell((Unit*)NULL, 58838, true);
  1917.             // here mirror image casts on summoner spell (not present in client dbc) 49866
  1918.             // here should be auras (not present in client dbc): 35657, 35658, 35659, 35660 selfcasted by mirror images (stats related?)
  1919.             // Clone Me!
  1920.             owner->CastSpell(me, 45204, true);
  1921.         }
  1922.  
  1923.         void UpdateAI(const uint32 diff)
  1924.         {
  1925.             if (!UpdateVictim() || me->HasUnitState(UNIT_STATE_CASTING))
  1926.                 return;
  1927.  
  1928.             DoCastVictim(spell_id);
  1929.         }
  1930.  
  1931.         // Do not reload Creature templates on evade mode enter - prevent visual lost
  1932.         void EnterEvadeMode()
  1933.         {
  1934.             if (me->IsInEvadeMode() || !me->isAlive())
  1935.                 return;
  1936.  
  1937.             Unit* owner = me->GetCharmerOrOwner();
  1938.  
  1939.             me->CombatStop(true);
  1940.             if (owner && !me->HasUnitState(UNIT_STATE_FOLLOW))
  1941.             {
  1942.                 me->GetMotionMaster()->Clear(false);
  1943.                 me->GetMotionMaster()->MoveFollow(owner, PET_FOLLOW_DIST, me->GetFollowAngle(), MOTION_SLOT_ACTIVE);
  1944.             }
  1945.         }
  1946.     };
  1947.  
  1948.     CreatureAI* GetAI(Creature* creature) const
  1949.     {
  1950.         return new npc_mirror_imageAI(creature);
  1951.     }
  1952. };
  1953.  
  1954. class npc_ebon_gargoyle : public CreatureScript
  1955. {
  1956. public:
  1957.     npc_ebon_gargoyle() : CreatureScript("npc_ebon_gargoyle") { }
  1958.  
  1959.     struct npc_ebon_gargoyleAI : CasterAI
  1960.     {
  1961.         npc_ebon_gargoyleAI(Creature* creature) : CasterAI(creature) {}
  1962.  
  1963.         uint32 despawnTimer;
  1964.         uint32 attackTimer;
  1965.         bool justSummoned;
  1966.         bool despawned;
  1967.  
  1968.         void InitializeAI()
  1969.         {
  1970.             // Not needed to be despawned now
  1971.             despawnTimer = 0;
  1972.  
  1973.             CasterAI::InitializeAI();
  1974.             uint64 ownerGuid = me->GetOwnerGUID();
  1975.             if (!ownerGuid)
  1976.                 return;
  1977.  
  1978.             attackTimer = 5000;
  1979.             justSummoned = true;
  1980.             despawned = false;
  1981.  
  1982.             me->SetReactState(REACT_PASSIVE);
  1983.             //me->SetCanFly(true);
  1984.             //me->SetDisableGravity(true);
  1985.             me->SetSpeed(MOVE_FLIGHT, 0.75f, true);
  1986.             me->SetSpeed(MOVE_RUN, 0.75f, true);
  1987.         }
  1988.  
  1989.         void JustDied(Unit* /*killer*/)
  1990.         {
  1991.             // Stop Feeding Gargoyle when it dies
  1992.             if (Unit* owner = me->GetOwner())
  1993.                 owner->RemoveAurasDueToSpell(50514);
  1994.         }
  1995.  
  1996.         void AttackStart(Unit *target)
  1997.         {
  1998.             if (me->GetReactState() == REACT_PASSIVE)
  1999.                 return;
  2000.  
  2001.             if (target && !target->HasAura(49206))
  2002.             {
  2003.                 DoSearchTarget();
  2004.                 return;
  2005.             }
  2006.  
  2007.             AttackStartCaster(target, 30.0f);
  2008.         }
  2009.  
  2010.         void DoSearchTarget()
  2011.         {
  2012.             uint64 ownerGuid = me->GetOwnerGUID();
  2013.             if (!ownerGuid)
  2014.                 return;
  2015.  
  2016.             Unit* owner = me->GetOwner();
  2017.             if (!owner || owner->GetTypeId() != TYPEID_PLAYER)
  2018.                 return;
  2019.  
  2020.             std::list<Unit*> targets;
  2021.             WoWSource::AnyUnfriendlyUnitInObjectRangeCheck u_check(me, me, 60);
  2022.             WoWSource::UnitListSearcher<WoWSource::AnyUnfriendlyUnitInObjectRangeCheck> searcher(me, targets, u_check);
  2023.             me->VisitNearbyObject(30, searcher);
  2024.             for (std::list<Unit*>::const_iterator itr = targets.begin(); itr != targets.end(); ++itr)
  2025.             {
  2026.                 Unit *victim = *itr;
  2027.                 if (victim->GetAura(49206, ownerGuid) && !victim->HasAura(5384))
  2028.                 {
  2029.                     if (me->canStartAttack(victim, true) && owner->canSeeOrDetect(victim, false))
  2030.                     {
  2031.                         me->Attack(victim, false);
  2032.                         return;
  2033.                     }
  2034.                 }
  2035.             }
  2036.  
  2037.             if (Pet* pet = owner->ToPlayer()->GetPet())
  2038.             {
  2039.                 if (Unit* victim = pet->getVictim())
  2040.                 {
  2041.                     if (me->canStartAttack(victim, true) && owner->canSeeOrDetect(victim, false))
  2042.                     {
  2043.                         me->Attack(victim, false);
  2044.                         return;
  2045.                     }
  2046.                 }
  2047.             }
  2048.  
  2049.             if (Unit* target = me->SelectNearbyTarget(0, 40.0f))
  2050.                 if (me->canStartAttack(target, true) && owner->canSeeOrDetect(target, false))
  2051.                     me->Attack(target, false);
  2052.         }
  2053.  
  2054.         // Fly away when dismissed
  2055.         void SpellHit(Unit* source, SpellInfo const* spell)
  2056.         {
  2057.             if (spell->Id != 50515 || !me->isAlive())
  2058.                 return;
  2059.  
  2060.             Unit* owner = me->GetOwner();
  2061.  
  2062.             if (!owner || owner != source)
  2063.                 return;
  2064.  
  2065.             // Stop Fighting
  2066.             me->ApplyModFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NON_ATTACKABLE, true);
  2067.             // Sanctuary
  2068.             me->CastSpell(me, 54661, true);
  2069.             me->SetReactState(REACT_PASSIVE);
  2070.             me->InterruptNonMeleeSpells(false);
  2071.  
  2072.             //! HACK: Creature's can't have MOVEMENTFLAG_FLYING
  2073.             // Fly Away
  2074.             me->AddUnitMovementFlag(MOVEMENTFLAG_CAN_FLY|MOVEMENTFLAG_ASCENDING|MOVEMENTFLAG_FLYING);
  2075.             me->SetSpeed(MOVE_FLIGHT, 0.75f, true);
  2076.             me->SetSpeed(MOVE_RUN, 0.75f, true);
  2077.             float x = me->GetPositionX() + 20 * cos(me->GetOrientation());
  2078.             float y = me->GetPositionY() + 20 * sin(me->GetOrientation());
  2079.             float z = me->GetPositionZ() + 40;
  2080.             me->GetMotionMaster()->Clear(false);
  2081.             me->GetMotionMaster()->MovePoint(0, x, y, z);
  2082.  
  2083.             // Despawn as soon as possible
  2084.             despawnTimer = 4 * IN_MILLISECONDS;
  2085.             despawned = true;
  2086.         }
  2087.  
  2088.         void UpdateAI(const uint32 diff)
  2089.         {
  2090.             if (justSummoned)
  2091.             {
  2092.                 justSummoned = false;
  2093.                 //me->GetMotionMaster()->MovePoint(0, me->GetPositionX(), me->GetPositionY(), me->GetPositionZ() - 25.0f);
  2094.             }
  2095.  
  2096.             if (attackTimer > 0 && !despawned)
  2097.             {
  2098.                 if (attackTimer > diff)
  2099.                     attackTimer -= diff;
  2100.                 else
  2101.                 {
  2102.                     me->SetReactState(REACT_AGGRESSIVE);
  2103.                     DoSearchTarget();
  2104.                 }
  2105.             }
  2106.  
  2107.             if (despawnTimer > 0)
  2108.             {
  2109.                 if (despawnTimer > diff)
  2110.                     despawnTimer -= diff;
  2111.                 else
  2112.                     me->DespawnOrUnsummon();
  2113.                 return;
  2114.             }
  2115.  
  2116.             CasterAI::UpdateAI(diff);
  2117.         }
  2118.     };
  2119.  
  2120.     CreatureAI* GetAI(Creature* creature) const
  2121.     {
  2122.         return new npc_ebon_gargoyleAI(creature);
  2123.     }
  2124. };
  2125.  
  2126. // Lightwell - 64571
  2127. class npc_new_lightwell : public CreatureScript
  2128. {
  2129.     public:
  2130.         npc_new_lightwell() : CreatureScript("npc_new_lightwell") { }
  2131.  
  2132.         struct npc_new_lightwellAI : public PassiveAI
  2133.         {
  2134.             npc_new_lightwellAI(Creature* creature) : PassiveAI(creature)
  2135.             {
  2136.                 DoCast(me, 59907, false);
  2137.                 renewTimer = 1000;
  2138.  
  2139.                 if (AuraPtr charges = me->GetAura(59907))
  2140.                 {
  2141.                     if (Unit* owner = me->GetOwner())
  2142.                     {
  2143.                         // Glyph of Deep Wells
  2144.                         if (owner->HasAura(55673))
  2145.                         {
  2146.                             charges->SetCharges(17);
  2147.                             charges->GetEffect(0)->ChangeAmount(17);
  2148.                         }
  2149.                     }
  2150.                 }
  2151.             }
  2152.  
  2153.             uint32 renewTimer;
  2154.  
  2155.             void Reset()
  2156.             {
  2157.                 me->SetFlag(UNIT_NPC_FLAGS, UNIT_NPC_FLAG_SPELLCLICK);
  2158.                 me->setFaction(35);
  2159.             }
  2160.  
  2161.             void EnterEvadeMode()
  2162.             {
  2163.                 if (!me->isAlive())
  2164.                     return;
  2165.  
  2166.                 me->DeleteThreatList();
  2167.                 me->CombatStop(true);
  2168.                 me->ResetPlayerDamageReq();
  2169.             }
  2170.  
  2171.             void UpdateAI(const uint32 diff)
  2172.             {
  2173.                 if (renewTimer)
  2174.                 {
  2175.                     if (renewTimer <= diff)
  2176.                     {
  2177.                         if (me->GetOwner())
  2178.                         {
  2179.                             if (Player* plr = me->GetOwner()->ToPlayer())
  2180.                             {
  2181.                                 std::list<Unit*> party;
  2182.                                 std::list<Unit*> tempList;
  2183.                                 plr->GetPartyMembers(party);
  2184.  
  2185.                                 for (auto itr : party)
  2186.                                 {
  2187.                                     if (itr->GetHealthPct() >= 50.0f ||
  2188.                                         itr->GetDistance(me) >= 40.0f ||
  2189.                                         itr->HasAura(7001))
  2190.                                         continue;
  2191.  
  2192.                                     tempList.push_back(itr);
  2193.                                 }
  2194.  
  2195.                                 for (auto itr : tempList)
  2196.                                     me->CastSpell(itr, 60123, true);
  2197.                             }
  2198.                         }
  2199.  
  2200.                         renewTimer = 1000;
  2201.                     }
  2202.                     else
  2203.                         renewTimer -= diff;
  2204.                 }
  2205.             }
  2206.         };
  2207.  
  2208.         CreatureAI* GetAI(Creature* creature) const
  2209.         {
  2210.             return new npc_new_lightwellAI(creature);
  2211.         }
  2212. };
  2213.  
  2214. // Lightwell - 31897
  2215. class npc_lightwell : public CreatureScript
  2216. {
  2217.     public:
  2218.         npc_lightwell() : CreatureScript("npc_lightwell") { }
  2219.  
  2220.         struct npc_lightwellAI : public PassiveAI
  2221.         {
  2222.             npc_lightwellAI(Creature* creature) : PassiveAI(creature)
  2223.             {
  2224.                 DoCast(me, 59907, false);
  2225.  
  2226.                 if (AuraPtr charges = me->GetAura(59907))
  2227.                 {
  2228.                     if (Unit* owner = me->GetOwner())
  2229.                     {
  2230.                         // Glyph of Deep Wells
  2231.                         if (owner->HasAura(55673))
  2232.                         {
  2233.                             charges->SetCharges(17);
  2234.                             charges->GetEffect(0)->ChangeAmount(17);
  2235.                         }
  2236.                     }
  2237.                 }
  2238.             }
  2239.  
  2240.             void Reset()
  2241.             {
  2242.                 me->SetFlag(UNIT_NPC_FLAGS, UNIT_NPC_FLAG_SPELLCLICK);
  2243.                 me->setFaction(35);
  2244.             }
  2245.  
  2246.             void EnterEvadeMode()
  2247.             {
  2248.                 if (!me->isAlive())
  2249.                     return;
  2250.  
  2251.                 me->DeleteThreatList();
  2252.                 me->CombatStop(true);
  2253.                 me->ResetPlayerDamageReq();
  2254.             }
  2255.         };
  2256.  
  2257.         CreatureAI* GetAI(Creature* creature) const
  2258.         {
  2259.             return new npc_lightwellAI(creature);
  2260.         }
  2261. };
  2262.  
  2263. enum eTrainingDummy
  2264. {
  2265.     NPC_ADVANCED_TARGET_DUMMY                  = 2674,
  2266.     NPC_TARGET_DUMMY                           = 2673
  2267. };
  2268.  
  2269. class npc_training_dummy : public CreatureScript
  2270. {
  2271.     public:
  2272.         npc_training_dummy() : CreatureScript("npc_training_dummy") { }
  2273.  
  2274.         struct npc_training_dummyAI : Scripted_NoMovementAI
  2275.         {
  2276.             npc_training_dummyAI(Creature* creature) : Scripted_NoMovementAI(creature)
  2277.             {
  2278.                 entry = creature->GetEntry();
  2279.             }
  2280.  
  2281.             uint32 entry;
  2282.             uint32 resetTimer;
  2283.             uint32 despawnTimer;
  2284.  
  2285.             void Reset()
  2286.             {
  2287.                 me->SetControlled(true, UNIT_STATE_STUNNED);//disable rotate
  2288.                 me->ApplySpellImmune(0, IMMUNITY_EFFECT, SPELL_EFFECT_KNOCK_BACK, true);//imune to knock aways like blast wave
  2289.                 me->ApplySpellImmune(0, IMMUNITY_MECHANIC, MECHANIC_GRIP, true);
  2290.                 me->ApplySpellImmune(0, IMMUNITY_EFFECT, SPELL_EFFECT_KNOCK_BACK_DEST, true);   // Immune to knock back effects like Whiplash
  2291.  
  2292.                 resetTimer = 5000;
  2293.                 despawnTimer = 15000;
  2294.             }
  2295.  
  2296.             void EnterEvadeMode()
  2297.             {
  2298.                 if (!_EnterEvadeMode())
  2299.                     return;
  2300.  
  2301.                 Reset();
  2302.             }
  2303.  
  2304.             void DamageTaken(Unit* /*doneBy*/, uint32& damage)
  2305.             {
  2306.                 resetTimer = 5000;
  2307.                 damage = 0;
  2308.             }
  2309.  
  2310.             void EnterCombat(Unit* /*who*/)
  2311.             {
  2312.                 if (entry != NPC_ADVANCED_TARGET_DUMMY && entry != NPC_TARGET_DUMMY)
  2313.                     return;
  2314.             }
  2315.  
  2316.             void UpdateAI(uint32 const diff)
  2317.             {
  2318.                 if (!UpdateVictim())
  2319.                     return;
  2320.  
  2321.                 if (!me->HasUnitState(UNIT_STATE_STUNNED))
  2322.                     me->SetControlled(true, UNIT_STATE_STUNNED);//disable rotate
  2323.  
  2324.                 if (entry != NPC_ADVANCED_TARGET_DUMMY && entry != NPC_TARGET_DUMMY)
  2325.                 {
  2326.                     if (resetTimer <= diff)
  2327.                     {
  2328.                         EnterEvadeMode();
  2329.                         resetTimer = 5000;
  2330.                     }
  2331.                     else
  2332.                         resetTimer -= diff;
  2333.                     return;
  2334.                 }
  2335.                 else
  2336.                 {
  2337.                     if (despawnTimer <= diff)
  2338.                         me->DespawnOrUnsummon();
  2339.                     else
  2340.                         despawnTimer -= diff;
  2341.                 }
  2342.             }
  2343.             void MoveInLineOfSight(Unit* /*who*/){return;}
  2344.         };
  2345.  
  2346.         CreatureAI* GetAI(Creature* creature) const
  2347.         {
  2348.             return new npc_training_dummyAI(creature);
  2349.         }
  2350. };
  2351.  
  2352. /*######
  2353. # npc_fire_elemental
  2354. ######*/
  2355. #define SPELL_FIRENOVA        12470
  2356. #define SPELL_FIRESHIELD      13376
  2357. #define SPELL_FIREBLAST       57984
  2358.  
  2359. enum fireEvents
  2360. {
  2361.     EVENT_FIRE_NOVA     = 1,
  2362.     EVENT_FIRE_BLAST    = 2,
  2363.     EVENT_FIRE_SHIELD   = 3
  2364. };
  2365.  
  2366. enum fireSpells
  2367. {
  2368.     SPELL_SHAMAN_FIRE_BLAST     = 57984,
  2369.     SPELL_SHAMAN_FIRE_NOVA      = 12470,
  2370.     SPELL_SHAMAN_FIRE_SHIELD    = 13376
  2371. };
  2372.  
  2373. class npc_fire_elemental : public CreatureScript
  2374. {
  2375.     public:
  2376.         npc_fire_elemental() : CreatureScript("npc_fire_elemental") { }
  2377.  
  2378.         struct npc_fire_elementalAI : public ScriptedAI
  2379.         {
  2380.             npc_fire_elementalAI(Creature* creature) : ScriptedAI(creature) {}
  2381.  
  2382.             EventMap events;
  2383.  
  2384.             void Reset()
  2385.             {
  2386.                 events.Reset();
  2387.                 events.ScheduleEvent(EVENT_FIRE_NOVA, urand(5000, 20000));
  2388.                 events.ScheduleEvent(EVENT_FIRE_BLAST, urand(5000, 20000));
  2389.                 events.ScheduleEvent(EVENT_FIRE_SHIELD, 0);
  2390.                 me->ApplySpellImmune(0, IMMUNITY_SCHOOL, SPELL_SCHOOL_MASK_FIRE, true);
  2391.             }
  2392.  
  2393.             void UpdateAI(const uint32 diff)
  2394.             {
  2395.                 if (!UpdateVictim())
  2396.                 {
  2397.                     if (Unit* owner = me->GetOwner())
  2398.                     {
  2399.                         Unit* ownerTarget = NULL;
  2400.                         if (Player* plr = owner->ToPlayer())
  2401.                             ownerTarget = plr->GetSelectedUnit();
  2402.                         else
  2403.                             ownerTarget = owner->getVictim();
  2404.  
  2405.                         if (ownerTarget)
  2406.                             AttackStart(ownerTarget);
  2407.                     }
  2408.  
  2409.                     return;
  2410.                 }
  2411.  
  2412.                 if (me->HasUnitState(UNIT_STATE_CASTING))
  2413.                     return;
  2414.  
  2415.                 events.Update(diff);
  2416.  
  2417.                 switch (events.ExecuteEvent())
  2418.                 {
  2419.                     case EVENT_FIRE_NOVA:
  2420.                         DoCastVictim(SPELL_SHAMAN_FIRE_NOVA);
  2421.                         events.ScheduleEvent(EVENT_FIRE_NOVA, urand(5000, 20000));
  2422.                         break;
  2423.                     case EVENT_FIRE_BLAST:
  2424.                         DoCastVictim(SPELL_SHAMAN_FIRE_BLAST);
  2425.                         events.ScheduleEvent(EVENT_FIRE_BLAST, urand(5000, 20000));
  2426.                         break;
  2427.                     case EVENT_FIRE_SHIELD:
  2428.                         DoCastVictim(SPELL_SHAMAN_FIRE_SHIELD);
  2429.                         events.ScheduleEvent(EVENT_FIRE_SHIELD, 4000);
  2430.                         break;
  2431.                     default:
  2432.                         break;
  2433.                 }
  2434.  
  2435.                 DoMeleeAttackIfReady();
  2436.             }
  2437.         };
  2438.  
  2439.         CreatureAI *GetAI(Creature* creature) const
  2440.         {
  2441.             return new npc_fire_elementalAI(creature);
  2442.         }
  2443. };
  2444.  
  2445. /*######
  2446. # npc_earth_elemental
  2447. ######*/
  2448. #define SPELL_ANGEREDEARTH        36213
  2449.  
  2450. class npc_earth_elemental : public CreatureScript
  2451. {
  2452.     public:
  2453.         npc_earth_elemental() : CreatureScript("npc_earth_elemental") { }
  2454.  
  2455.         struct npc_earth_elementalAI : public ScriptedAI
  2456.         {
  2457.             npc_earth_elementalAI(Creature* creature) : ScriptedAI(creature) {}
  2458.  
  2459.             uint32 AngeredEarth_Timer;
  2460.  
  2461.             void Reset()
  2462.             {
  2463.                 AngeredEarth_Timer = 0;
  2464.                 me->ApplySpellImmune(0, IMMUNITY_SCHOOL, SPELL_SCHOOL_MASK_NATURE, true);
  2465.             }
  2466.  
  2467.             void UpdateAI(const uint32 diff)
  2468.             {
  2469.                 if (!UpdateVictim())
  2470.                 {
  2471.                     if (Unit* owner = me->GetOwner())
  2472.                     {
  2473.                         Unit* ownerTarget = NULL;
  2474.                         if (Player* plr = owner->ToPlayer())
  2475.                             ownerTarget = plr->GetSelectedUnit();
  2476.                         else
  2477.                             ownerTarget = owner->getVictim();
  2478.  
  2479.                         if (ownerTarget)
  2480.                             AttackStart(ownerTarget);
  2481.                     }
  2482.  
  2483.                     return;
  2484.                 }
  2485.  
  2486.                 if (AngeredEarth_Timer <= diff)
  2487.                 {
  2488.                     DoCast(me->getVictim(), SPELL_ANGEREDEARTH);
  2489.                     AngeredEarth_Timer = 5000 + rand() % 15000; // 5-20 sec cd
  2490.                 }
  2491.                 else
  2492.                     AngeredEarth_Timer -= diff;
  2493.  
  2494.                 DoMeleeAttackIfReady();
  2495.             }
  2496.         };
  2497.  
  2498.         CreatureAI* GetAI(Creature* creature) const
  2499.         {
  2500.             return new npc_earth_elementalAI(creature);
  2501.         }
  2502. };
  2503.  
  2504. /*######
  2505. # npc_wormhole
  2506. ######*/
  2507.  
  2508. #define GOSSIP_ENGINEERING1   "Borean Tundra"
  2509. #define GOSSIP_ENGINEERING2   "Howling Fjord"
  2510. #define GOSSIP_ENGINEERING3   "Sholazar Basin"
  2511. #define GOSSIP_ENGINEERING4   "Icecrown"
  2512. #define GOSSIP_ENGINEERING5   "Storm Peaks"
  2513. #define GOSSIP_ENGINEERING6   "Underground..."
  2514.  
  2515. enum WormholeSpells
  2516. {
  2517.     SPELL_BOREAN_TUNDRA         = 67834,
  2518.     SPELL_SHOLAZAR_BASIN        = 67835,
  2519.     SPELL_ICECROWN              = 67836,
  2520.     SPELL_STORM_PEAKS           = 67837,
  2521.     SPELL_HOWLING_FJORD         = 67838,
  2522.     SPELL_UNDERGROUND           = 68081,
  2523.  
  2524.     TEXT_WORMHOLE               = 907,
  2525.  
  2526.     DATA_SHOW_UNDERGROUND       = 1,
  2527. };
  2528.  
  2529. class npc_wormhole : public CreatureScript
  2530. {
  2531.     public:
  2532.         npc_wormhole() : CreatureScript("npc_wormhole") {}
  2533.  
  2534.         struct npc_wormholeAI : public PassiveAI
  2535.         {
  2536.             npc_wormholeAI(Creature* creature) : PassiveAI(creature) {}
  2537.  
  2538.             void InitializeAI()
  2539.             {
  2540.                 _showUnderground = urand(0, 100) == 0; // Guessed value, it is really rare though
  2541.             }
  2542.  
  2543.             uint32 GetData(uint32 type)
  2544.             {
  2545.                 return (type == DATA_SHOW_UNDERGROUND && _showUnderground) ? 1 : 0;
  2546.             }
  2547.  
  2548.         private:
  2549.             bool _showUnderground;
  2550.         };
  2551.  
  2552.         bool OnGossipHello(Player* player, Creature* creature)
  2553.         {
  2554.             if (creature->isSummon())
  2555.             {
  2556.                 if (player == creature->ToTempSummon()->GetSummoner())
  2557.                 {
  2558.                     player->ADD_GOSSIP_ITEM(GOSSIP_ICON_CHAT, GOSSIP_ENGINEERING1, GOSSIP_SENDER_MAIN, GOSSIP_ACTION_INFO_DEF + 1);
  2559.                     player->ADD_GOSSIP_ITEM(GOSSIP_ICON_CHAT, GOSSIP_ENGINEERING2, GOSSIP_SENDER_MAIN, GOSSIP_ACTION_INFO_DEF + 2);
  2560.                     player->ADD_GOSSIP_ITEM(GOSSIP_ICON_CHAT, GOSSIP_ENGINEERING3, GOSSIP_SENDER_MAIN, GOSSIP_ACTION_INFO_DEF + 3);
  2561.                     player->ADD_GOSSIP_ITEM(GOSSIP_ICON_CHAT, GOSSIP_ENGINEERING4, GOSSIP_SENDER_MAIN, GOSSIP_ACTION_INFO_DEF + 4);
  2562.                     player->ADD_GOSSIP_ITEM(GOSSIP_ICON_CHAT, GOSSIP_ENGINEERING5, GOSSIP_SENDER_MAIN, GOSSIP_ACTION_INFO_DEF + 5);
  2563.  
  2564.                     if (creature->AI()->GetData(DATA_SHOW_UNDERGROUND))
  2565.                         player->ADD_GOSSIP_ITEM(GOSSIP_ICON_CHAT, GOSSIP_ENGINEERING6, GOSSIP_SENDER_MAIN, GOSSIP_ACTION_INFO_DEF + 6);
  2566.  
  2567.                     player->PlayerTalkClass->SendGossipMenu(TEXT_WORMHOLE, creature->GetGUID());
  2568.                 }
  2569.             }
  2570.  
  2571.             return true;
  2572.         }
  2573.  
  2574.         bool OnGossipSelect(Player* player, Creature* creature, uint32 /*sender*/, uint32 action)
  2575.         {
  2576.             player->PlayerTalkClass->ClearMenus();
  2577.  
  2578.             switch (action)
  2579.             {
  2580.                 case GOSSIP_ACTION_INFO_DEF + 1: // Borean Tundra
  2581.                     player->CLOSE_GOSSIP_MENU();
  2582.                     creature->CastSpell(player, SPELL_BOREAN_TUNDRA, false);
  2583.                     break;
  2584.                 case GOSSIP_ACTION_INFO_DEF + 2: // Howling Fjord
  2585.                     player->CLOSE_GOSSIP_MENU();
  2586.                     creature->CastSpell(player, SPELL_HOWLING_FJORD, false);
  2587.                     break;
  2588.                 case GOSSIP_ACTION_INFO_DEF + 3: // Sholazar Basin
  2589.                     player->CLOSE_GOSSIP_MENU();
  2590.                     creature->CastSpell(player, SPELL_SHOLAZAR_BASIN, false);
  2591.                     break;
  2592.                 case GOSSIP_ACTION_INFO_DEF + 4: // Icecrown
  2593.                     player->CLOSE_GOSSIP_MENU();
  2594.                     creature->CastSpell(player, SPELL_ICECROWN, false);
  2595.                     break;
  2596.                 case GOSSIP_ACTION_INFO_DEF + 5: // Storm peaks
  2597.                     player->CLOSE_GOSSIP_MENU();
  2598.                     creature->CastSpell(player, SPELL_STORM_PEAKS, false);
  2599.                     break;
  2600.                 case GOSSIP_ACTION_INFO_DEF + 6: // Underground
  2601.                     player->CLOSE_GOSSIP_MENU();
  2602.                     creature->CastSpell(player, SPELL_UNDERGROUND, false);
  2603.                     break;
  2604.             }
  2605.  
  2606.             return true;
  2607.         }
  2608.  
  2609.         CreatureAI* GetAI(Creature* creature) const
  2610.         {
  2611.             return new npc_wormholeAI(creature);
  2612.         }
  2613. };
  2614.  
  2615. /*######
  2616. ## npc_pet_trainer
  2617. ######*/
  2618.  
  2619. enum ePetTrainer
  2620. {
  2621.     TEXT_ISHUNTER               = 5838,
  2622.     TEXT_NOTHUNTER              = 5839,
  2623.     TEXT_PETINFO                = 13474,
  2624.     TEXT_CONFIRM                = 7722
  2625. };
  2626.  
  2627. #define GOSSIP_PET1             "How do I train my pet?"
  2628. #define GOSSIP_PET2             "I wish to untrain my pet."
  2629. #define GOSSIP_PET_CONFIRM      "Yes, please do."
  2630.  
  2631. class npc_pet_trainer : public CreatureScript
  2632. {
  2633.     public:
  2634.         npc_pet_trainer() : CreatureScript("npc_pet_trainer") { }
  2635.  
  2636.         bool OnGossipHello(Player* player, Creature* creature)
  2637.         {
  2638.             if (creature->isQuestGiver())
  2639.                 player->PrepareQuestMenu(creature->GetGUID());
  2640.  
  2641.             if (player->getClass() == CLASS_HUNTER)
  2642.             {
  2643.                 player->ADD_GOSSIP_ITEM(GOSSIP_ICON_CHAT, GOSSIP_PET1, GOSSIP_SENDER_MAIN, GOSSIP_ACTION_INFO_DEF + 1);
  2644.                 if (player->GetPet() && player->GetPet()->getPetType() == HUNTER_PET)
  2645.                     player->ADD_GOSSIP_ITEM(GOSSIP_ICON_CHAT, GOSSIP_PET2, GOSSIP_SENDER_MAIN, GOSSIP_ACTION_INFO_DEF + 2);
  2646.  
  2647.                 player->PlayerTalkClass->SendGossipMenu(TEXT_ISHUNTER, creature->GetGUID());
  2648.                 return true;
  2649.             }
  2650.             player->PlayerTalkClass->SendGossipMenu(TEXT_NOTHUNTER, creature->GetGUID());
  2651.             return true;
  2652.         }
  2653.  
  2654.         bool OnGossipSelect(Player* player, Creature* creature, uint32 /*sender*/, uint32 action)
  2655.         {
  2656.             player->PlayerTalkClass->ClearMenus();
  2657.             switch (action)
  2658.             {
  2659.                 case GOSSIP_ACTION_INFO_DEF + 1:
  2660.                     player->PlayerTalkClass->SendGossipMenu(TEXT_PETINFO, creature->GetGUID());
  2661.                     break;
  2662.                 case GOSSIP_ACTION_INFO_DEF + 2:
  2663.                     {
  2664.                         player->ADD_GOSSIP_ITEM(GOSSIP_ICON_CHAT, GOSSIP_PET_CONFIRM, GOSSIP_SENDER_MAIN, GOSSIP_ACTION_INFO_DEF + 3);
  2665.                         player->PlayerTalkClass->SendGossipMenu(TEXT_CONFIRM, creature->GetGUID());
  2666.                     }
  2667.                     break;
  2668.                 case GOSSIP_ACTION_INFO_DEF + 3:
  2669.                     {
  2670.                         player->CLOSE_GOSSIP_MENU();
  2671.                     }
  2672.                     break;
  2673.             }
  2674.             return true;
  2675.         }
  2676. };
  2677.  
  2678. /*######
  2679. ## npc_locksmith
  2680. ######*/
  2681.  
  2682. enum eLockSmith
  2683. {
  2684.     QUEST_HOW_TO_BRAKE_IN_TO_THE_ARCATRAZ = 10704,
  2685.     QUEST_DARK_IRON_LEGACY                = 3802,
  2686.     QUEST_THE_KEY_TO_SCHOLOMANCE_A        = 5505,
  2687.     QUEST_THE_KEY_TO_SCHOLOMANCE_H        = 5511,
  2688.     QUEST_HOTTER_THAN_HELL_A              = 10758,
  2689.     QUEST_HOTTER_THAN_HELL_H              = 10764,
  2690.     QUEST_RETURN_TO_KHAGDAR               = 9837,
  2691.     QUEST_CONTAINMENT                     = 13159,
  2692.     QUEST_ETERNAL_VIGILANCE               = 11011,
  2693.     QUEST_KEY_TO_THE_FOCUSING_IRIS        = 13372,
  2694.     QUEST_HC_KEY_TO_THE_FOCUSING_IRIS     = 13375,
  2695.  
  2696.     ITEM_ARCATRAZ_KEY                     = 31084,
  2697.     ITEM_SHADOWFORGE_KEY                  = 11000,
  2698.     ITEM_SKELETON_KEY                     = 13704,
  2699.     ITEM_SHATTERED_HALLS_KEY              = 28395,
  2700.     ITEM_THE_MASTERS_KEY                  = 24490,
  2701.     ITEM_VIOLET_HOLD_KEY                  = 42482,
  2702.     ITEM_ESSENCE_INFUSED_MOONSTONE        = 32449,
  2703.     ITEM_KEY_TO_THE_FOCUSING_IRIS         = 44582,
  2704.     ITEM_HC_KEY_TO_THE_FOCUSING_IRIS      = 44581,
  2705.  
  2706.     SPELL_ARCATRAZ_KEY                    = 54881,
  2707.     SPELL_SHADOWFORGE_KEY                 = 54882,
  2708.     SPELL_SKELETON_KEY                    = 54883,
  2709.     SPELL_SHATTERED_HALLS_KEY             = 54884,
  2710.     SPELL_THE_MASTERS_KEY                 = 54885,
  2711.     SPELL_VIOLET_HOLD_KEY                 = 67253,
  2712.     SPELL_ESSENCE_INFUSED_MOONSTONE       = 40173,
  2713. };
  2714.  
  2715. #define GOSSIP_LOST_ARCATRAZ_KEY                "I've lost my key to the Arcatraz."
  2716. #define GOSSIP_LOST_SHADOWFORGE_KEY             "I've lost my key to the Blackrock Depths."
  2717. #define GOSSIP_LOST_SKELETON_KEY                "I've lost my key to the Scholomance."
  2718. #define GOSSIP_LOST_SHATTERED_HALLS_KEY         "I've lost my key to the Shattered Halls."
  2719. #define GOSSIP_LOST_THE_MASTERS_KEY             "I've lost my key to the Karazhan."
  2720. #define GOSSIP_LOST_VIOLET_HOLD_KEY             "I've lost my key to the Violet Hold."
  2721. #define GOSSIP_LOST_ESSENCE_INFUSED_MOONSTONE   "I've lost my Essence-Infused Moonstone."
  2722. #define GOSSIP_LOST_KEY_TO_THE_FOCUSING_IRIS    "I've lost my Key to the Focusing Iris."
  2723. #define GOSSIP_LOST_HC_KEY_TO_THE_FOCUSING_IRIS "I've lost my Heroic Key to the Focusing Iris."
  2724.  
  2725. class npc_locksmith : public CreatureScript
  2726. {
  2727.     public:
  2728.         npc_locksmith() : CreatureScript("npc_locksmith") { }
  2729.  
  2730.         bool OnGossipHello(Player* player, Creature* creature)
  2731.         {
  2732.             // Arcatraz Key
  2733.             if (player->GetQuestRewardStatus(QUEST_HOW_TO_BRAKE_IN_TO_THE_ARCATRAZ) && !player->HasItemCount(ITEM_ARCATRAZ_KEY, 1, true))
  2734.                 player->ADD_GOSSIP_ITEM(GOSSIP_ICON_CHAT, GOSSIP_LOST_ARCATRAZ_KEY, GOSSIP_SENDER_MAIN, GOSSIP_ACTION_INFO_DEF + 1);
  2735.  
  2736.             // Shadowforge Key
  2737.             if (player->GetQuestRewardStatus(QUEST_DARK_IRON_LEGACY) && !player->HasItemCount(ITEM_SHADOWFORGE_KEY, 1, true))
  2738.                 player->ADD_GOSSIP_ITEM(GOSSIP_ICON_CHAT, GOSSIP_LOST_SHADOWFORGE_KEY, GOSSIP_SENDER_MAIN, GOSSIP_ACTION_INFO_DEF + 2);
  2739.  
  2740.             // Skeleton Key
  2741.             if ((player->GetQuestRewardStatus(QUEST_THE_KEY_TO_SCHOLOMANCE_A) || player->GetQuestRewardStatus(QUEST_THE_KEY_TO_SCHOLOMANCE_H)) &&
  2742.                 !player->HasItemCount(ITEM_SKELETON_KEY, 1, true))
  2743.                 player->ADD_GOSSIP_ITEM(GOSSIP_ICON_CHAT, GOSSIP_LOST_SKELETON_KEY, GOSSIP_SENDER_MAIN, GOSSIP_ACTION_INFO_DEF + 3);
  2744.  
  2745.             // Shatered Halls Key
  2746.             if ((player->GetQuestRewardStatus(QUEST_HOTTER_THAN_HELL_A) || player->GetQuestRewardStatus(QUEST_HOTTER_THAN_HELL_H)) &&
  2747.                 !player->HasItemCount(ITEM_SHATTERED_HALLS_KEY, 1, true))
  2748.                 player->ADD_GOSSIP_ITEM(GOSSIP_ICON_CHAT, GOSSIP_LOST_SHATTERED_HALLS_KEY, GOSSIP_SENDER_MAIN, GOSSIP_ACTION_INFO_DEF + 4);
  2749.  
  2750.             // Master's Key
  2751.             if (player->GetQuestRewardStatus(QUEST_RETURN_TO_KHAGDAR) && !player->HasItemCount(ITEM_THE_MASTERS_KEY, 1, true))
  2752.                 player->ADD_GOSSIP_ITEM(GOSSIP_ICON_CHAT, GOSSIP_LOST_THE_MASTERS_KEY, GOSSIP_SENDER_MAIN, GOSSIP_ACTION_INFO_DEF + 5);
  2753.  
  2754.             // Violet Hold Key
  2755.             if (player->GetQuestRewardStatus(QUEST_CONTAINMENT) && !player->HasItemCount(ITEM_VIOLET_HOLD_KEY, 1, true))
  2756.                 player->ADD_GOSSIP_ITEM(GOSSIP_ICON_CHAT, GOSSIP_LOST_VIOLET_HOLD_KEY, GOSSIP_SENDER_MAIN, GOSSIP_ACTION_INFO_DEF + 6);
  2757.  
  2758.             // Essence-Infused Moonstone
  2759.             if (player->GetQuestRewardStatus(QUEST_ETERNAL_VIGILANCE) && !player->HasItemCount(ITEM_ESSENCE_INFUSED_MOONSTONE, 1, true))
  2760.                 player->ADD_GOSSIP_ITEM(GOSSIP_ICON_CHAT, GOSSIP_LOST_ESSENCE_INFUSED_MOONSTONE, GOSSIP_SENDER_MAIN, GOSSIP_ACTION_INFO_DEF + 7);
  2761.  
  2762.             // Key to the Focusing Iris
  2763.             if (player->GetQuestRewardStatus(QUEST_KEY_TO_THE_FOCUSING_IRIS) && !player->HasItemCount(ITEM_KEY_TO_THE_FOCUSING_IRIS, 1, true))
  2764.                 player->ADD_GOSSIP_ITEM(GOSSIP_ICON_CHAT, GOSSIP_LOST_KEY_TO_THE_FOCUSING_IRIS, GOSSIP_SENDER_MAIN, GOSSIP_ACTION_INFO_DEF + 8);
  2765.  
  2766.             // Heroic Key to the Focusing Iris
  2767.             if (player->GetQuestRewardStatus(QUEST_HC_KEY_TO_THE_FOCUSING_IRIS) && !player->HasItemCount(ITEM_HC_KEY_TO_THE_FOCUSING_IRIS, 1, true))
  2768.                 player->ADD_GOSSIP_ITEM(GOSSIP_ICON_CHAT, GOSSIP_LOST_HC_KEY_TO_THE_FOCUSING_IRIS, GOSSIP_SENDER_MAIN, GOSSIP_ACTION_INFO_DEF + 9);
  2769.  
  2770.             player->SEND_GOSSIP_MENU(player->GetGossipTextId(creature), creature->GetGUID());
  2771.  
  2772.             return true;
  2773.         }
  2774.  
  2775.         bool OnGossipSelect(Player* player, Creature* /*creature*/, uint32 /*sender*/, uint32 action)
  2776.         {
  2777.             player->PlayerTalkClass->ClearMenus();
  2778.             switch (action)
  2779.             {
  2780.                 case GOSSIP_ACTION_INFO_DEF + 1:
  2781.                     player->CLOSE_GOSSIP_MENU();
  2782.                     player->CastSpell(player, SPELL_ARCATRAZ_KEY, false);
  2783.                     break;
  2784.                 case GOSSIP_ACTION_INFO_DEF + 2:
  2785.                     player->CLOSE_GOSSIP_MENU();
  2786.                     player->CastSpell(player, SPELL_SHADOWFORGE_KEY, false);
  2787.                     break;
  2788.                 case GOSSIP_ACTION_INFO_DEF + 3:
  2789.                     player->CLOSE_GOSSIP_MENU();
  2790.                     player->CastSpell(player, SPELL_SKELETON_KEY, false);
  2791.                     break;
  2792.                 case GOSSIP_ACTION_INFO_DEF + 4:
  2793.                     player->CLOSE_GOSSIP_MENU();
  2794.                     player->CastSpell(player, SPELL_SHATTERED_HALLS_KEY, false);
  2795.                     break;
  2796.                 case GOSSIP_ACTION_INFO_DEF + 5:
  2797.                     player->CLOSE_GOSSIP_MENU();
  2798.                     player->CastSpell(player, SPELL_THE_MASTERS_KEY, false);
  2799.                     break;
  2800.                 case GOSSIP_ACTION_INFO_DEF + 6:
  2801.                     player->CLOSE_GOSSIP_MENU();
  2802.                     player->CastSpell(player, SPELL_VIOLET_HOLD_KEY, false);
  2803.                     break;
  2804.                 case GOSSIP_ACTION_INFO_DEF + 7:
  2805.                     player->CLOSE_GOSSIP_MENU();
  2806.                     player->CastSpell(player, SPELL_ESSENCE_INFUSED_MOONSTONE, false);
  2807.                     break;
  2808.                 case GOSSIP_ACTION_INFO_DEF + 8:
  2809.                     player->CLOSE_GOSSIP_MENU();
  2810.                     player->AddItem(ITEM_KEY_TO_THE_FOCUSING_IRIS,1);
  2811.                     break;
  2812.                 case GOSSIP_ACTION_INFO_DEF + 9:
  2813.                     player->CLOSE_GOSSIP_MENU();
  2814.                     player->AddItem(ITEM_HC_KEY_TO_THE_FOCUSING_IRIS,1);
  2815.                     break;
  2816.             }
  2817.             return true;
  2818.         }
  2819. };
  2820.  
  2821. /*######
  2822. ## npc_experience
  2823. ######*/
  2824.  
  2825. #define EXP_COST                100000 //10 00 00 copper (10golds)
  2826. #define GOSSIP_TEXT_EXP         14736
  2827. #define GOSSIP_XP_OFF           "I no longer wish to gain experience."
  2828. #define GOSSIP_XP_ON            "I wish to start gaining experience again."
  2829.  
  2830. class npc_experience : public CreatureScript
  2831. {
  2832.     public:
  2833.         npc_experience() : CreatureScript("npc_experience") { }
  2834.  
  2835.         bool OnGossipHello(Player* player, Creature* creature)
  2836.         {
  2837.             player->ADD_GOSSIP_ITEM(GOSSIP_ICON_CHAT, GOSSIP_XP_OFF, GOSSIP_SENDER_MAIN, GOSSIP_ACTION_INFO_DEF + 1);
  2838.             player->ADD_GOSSIP_ITEM(GOSSIP_ICON_CHAT, GOSSIP_XP_ON, GOSSIP_SENDER_MAIN, GOSSIP_ACTION_INFO_DEF + 2);
  2839.             player->PlayerTalkClass->SendGossipMenu(GOSSIP_TEXT_EXP, creature->GetGUID());
  2840.             return true;
  2841.         }
  2842.  
  2843.         bool OnGossipSelect(Player* player, Creature* /*creature*/, uint32 /*sender*/, uint32 action)
  2844.         {
  2845.             player->PlayerTalkClass->ClearMenus();
  2846.             bool noXPGain = player->HasFlag(PLAYER_FLAGS, PLAYER_FLAGS_NO_XP_GAIN);
  2847.             bool doSwitch = false;
  2848.  
  2849.             switch (action)
  2850.             {
  2851.                 case GOSSIP_ACTION_INFO_DEF + 1://xp off
  2852.                     {
  2853.                         if (!noXPGain)//does gain xp
  2854.                             doSwitch = true;//switch to don't gain xp
  2855.                     }
  2856.                     break;
  2857.                 case GOSSIP_ACTION_INFO_DEF + 2://xp on
  2858.                     {
  2859.                         if (noXPGain)//doesn't gain xp
  2860.                             doSwitch = true;//switch to gain xp
  2861.                     }
  2862.                     break;
  2863.             }
  2864.             if (doSwitch)
  2865.             {
  2866.                 if (!player->HasEnoughMoney(uint64(EXP_COST)))
  2867.                     player->SendBuyError(BUY_ERR_NOT_ENOUGHT_MONEY, 0, 0, 0);
  2868.                 else if (noXPGain)
  2869.                 {
  2870.                     player->ModifyMoney(-int64(EXP_COST));
  2871.                     player->RemoveFlag(PLAYER_FLAGS, PLAYER_FLAGS_NO_XP_GAIN);
  2872.                 }
  2873.                 else if (!noXPGain)
  2874.                 {
  2875.                     player->ModifyMoney(-EXP_COST);
  2876.                     player->SetFlag(PLAYER_FLAGS, PLAYER_FLAGS_NO_XP_GAIN);
  2877.                 }
  2878.             }
  2879.             player->PlayerTalkClass->SendCloseGossip();
  2880.             return true;
  2881.         }
  2882. };
  2883.  
  2884. enum Fireworks
  2885. {
  2886.     NPC_OMEN                = 15467,
  2887.     NPC_MINION_OF_OMEN      = 15466,
  2888.     NPC_FIREWORK_BLUE       = 15879,
  2889.     NPC_FIREWORK_GREEN      = 15880,
  2890.     NPC_FIREWORK_PURPLE     = 15881,
  2891.     NPC_FIREWORK_RED        = 15882,
  2892.     NPC_FIREWORK_YELLOW     = 15883,
  2893.     NPC_FIREWORK_WHITE      = 15884,
  2894.     NPC_FIREWORK_BIG_BLUE   = 15885,
  2895.     NPC_FIREWORK_BIG_GREEN  = 15886,
  2896.     NPC_FIREWORK_BIG_PURPLE = 15887,
  2897.     NPC_FIREWORK_BIG_RED    = 15888,
  2898.     NPC_FIREWORK_BIG_YELLOW = 15889,
  2899.     NPC_FIREWORK_BIG_WHITE  = 15890,
  2900.  
  2901.     NPC_CLUSTER_BLUE        = 15872,
  2902.     NPC_CLUSTER_RED         = 15873,
  2903.     NPC_CLUSTER_GREEN       = 15874,
  2904.     NPC_CLUSTER_PURPLE      = 15875,
  2905.     NPC_CLUSTER_WHITE       = 15876,
  2906.     NPC_CLUSTER_YELLOW      = 15877,
  2907.     NPC_CLUSTER_BIG_BLUE    = 15911,
  2908.     NPC_CLUSTER_BIG_GREEN   = 15912,
  2909.     NPC_CLUSTER_BIG_PURPLE  = 15913,
  2910.     NPC_CLUSTER_BIG_RED     = 15914,
  2911.     NPC_CLUSTER_BIG_WHITE   = 15915,
  2912.     NPC_CLUSTER_BIG_YELLOW  = 15916,
  2913.     NPC_CLUSTER_ELUNE       = 15918,
  2914.  
  2915.     GO_FIREWORK_LAUNCHER_1  = 180771,
  2916.     GO_FIREWORK_LAUNCHER_2  = 180868,
  2917.     GO_FIREWORK_LAUNCHER_3  = 180850,
  2918.     GO_CLUSTER_LAUNCHER_1   = 180772,
  2919.     GO_CLUSTER_LAUNCHER_2   = 180859,
  2920.     GO_CLUSTER_LAUNCHER_3   = 180869,
  2921.     GO_CLUSTER_LAUNCHER_4   = 180874,
  2922.  
  2923.     SPELL_ROCKET_BLUE       = 26344,
  2924.     SPELL_ROCKET_GREEN      = 26345,
  2925.     SPELL_ROCKET_PURPLE     = 26346,
  2926.     SPELL_ROCKET_RED        = 26347,
  2927.     SPELL_ROCKET_WHITE      = 26348,
  2928.     SPELL_ROCKET_YELLOW     = 26349,
  2929.     SPELL_ROCKET_BIG_BLUE   = 26351,
  2930.     SPELL_ROCKET_BIG_GREEN  = 26352,
  2931.     SPELL_ROCKET_BIG_PURPLE = 26353,
  2932.     SPELL_ROCKET_BIG_RED    = 26354,
  2933.     SPELL_ROCKET_BIG_WHITE  = 26355,
  2934.     SPELL_ROCKET_BIG_YELLOW = 26356,
  2935.     SPELL_LUNAR_FORTUNE     = 26522,
  2936.  
  2937.     ANIM_GO_LAUNCH_FIREWORK = 3,
  2938.     ZONE_MOONGLADE          = 493,
  2939. };
  2940.  
  2941. Position omenSummonPos = {7558.993f, -2839.999f, 450.0214f, 4.46f};
  2942.  
  2943. class npc_firework : public CreatureScript
  2944. {
  2945.     public:
  2946.         npc_firework() : CreatureScript("npc_firework") { }
  2947.  
  2948.         struct npc_fireworkAI : public ScriptedAI
  2949.         {
  2950.             npc_fireworkAI(Creature* creature) : ScriptedAI(creature) {}
  2951.  
  2952.             bool isCluster()
  2953.             {
  2954.                 switch (me->GetEntry())
  2955.                 {
  2956.                     case NPC_FIREWORK_BLUE:
  2957.                     case NPC_FIREWORK_GREEN:
  2958.                     case NPC_FIREWORK_PURPLE:
  2959.                     case NPC_FIREWORK_RED:
  2960.                     case NPC_FIREWORK_YELLOW:
  2961.                     case NPC_FIREWORK_WHITE:
  2962.                     case NPC_FIREWORK_BIG_BLUE:
  2963.                     case NPC_FIREWORK_BIG_GREEN:
  2964.                     case NPC_FIREWORK_BIG_PURPLE:
  2965.                     case NPC_FIREWORK_BIG_RED:
  2966.                     case NPC_FIREWORK_BIG_YELLOW:
  2967.                     case NPC_FIREWORK_BIG_WHITE:
  2968.                         return false;
  2969.                     case NPC_CLUSTER_BLUE:
  2970.                     case NPC_CLUSTER_GREEN:
  2971.                     case NPC_CLUSTER_PURPLE:
  2972.                     case NPC_CLUSTER_RED:
  2973.                     case NPC_CLUSTER_YELLOW:
  2974.                     case NPC_CLUSTER_WHITE:
  2975.                     case NPC_CLUSTER_BIG_BLUE:
  2976.                     case NPC_CLUSTER_BIG_GREEN:
  2977.                     case NPC_CLUSTER_BIG_PURPLE:
  2978.                     case NPC_CLUSTER_BIG_RED:
  2979.                     case NPC_CLUSTER_BIG_YELLOW:
  2980.                     case NPC_CLUSTER_BIG_WHITE:
  2981.                     case NPC_CLUSTER_ELUNE:
  2982.                     default:
  2983.                         return true;
  2984.                 }
  2985.             }
  2986.  
  2987.             GameObject* FindNearestLauncher()
  2988.             {
  2989.                 GameObject* launcher = NULL;
  2990.  
  2991.                 if (isCluster())
  2992.                 {
  2993.                     GameObject* launcher1 = GetClosestGameObjectWithEntry(me, GO_CLUSTER_LAUNCHER_1, 0.5f);
  2994.                     GameObject* launcher2 = GetClosestGameObjectWithEntry(me, GO_CLUSTER_LAUNCHER_2, 0.5f);
  2995.                     GameObject* launcher3 = GetClosestGameObjectWithEntry(me, GO_CLUSTER_LAUNCHER_3, 0.5f);
  2996.                     GameObject* launcher4 = GetClosestGameObjectWithEntry(me, GO_CLUSTER_LAUNCHER_4, 0.5f);
  2997.  
  2998.                     if (launcher1)
  2999.                         launcher = launcher1;
  3000.                     else if (launcher2)
  3001.                         launcher = launcher2;
  3002.                     else if (launcher3)
  3003.                         launcher = launcher3;
  3004.                     else if (launcher4)
  3005.                         launcher = launcher4;
  3006.                 }
  3007.                 else
  3008.                 {
  3009.                     GameObject* launcher1 = GetClosestGameObjectWithEntry(me, GO_FIREWORK_LAUNCHER_1, 0.5f);
  3010.                     GameObject* launcher2 = GetClosestGameObjectWithEntry(me, GO_FIREWORK_LAUNCHER_2, 0.5f);
  3011.                     GameObject* launcher3 = GetClosestGameObjectWithEntry(me, GO_FIREWORK_LAUNCHER_3, 0.5f);
  3012.  
  3013.                     if (launcher1)
  3014.                         launcher = launcher1;
  3015.                     else if (launcher2)
  3016.                         launcher = launcher2;
  3017.                     else if (launcher3)
  3018.                         launcher = launcher3;
  3019.                 }
  3020.  
  3021.                 return launcher;
  3022.             }
  3023.  
  3024.             uint32 GetFireworkSpell(uint32 entry)
  3025.             {
  3026.                 switch (entry)
  3027.                 {
  3028.                     case NPC_FIREWORK_BLUE:
  3029.                         return SPELL_ROCKET_BLUE;
  3030.                     case NPC_FIREWORK_GREEN:
  3031.                         return SPELL_ROCKET_GREEN;
  3032.                     case NPC_FIREWORK_PURPLE:
  3033.                         return SPELL_ROCKET_PURPLE;
  3034.                     case NPC_FIREWORK_RED:
  3035.                         return SPELL_ROCKET_RED;
  3036.                     case NPC_FIREWORK_YELLOW:
  3037.                         return SPELL_ROCKET_YELLOW;
  3038.                     case NPC_FIREWORK_WHITE:
  3039.                         return SPELL_ROCKET_WHITE;
  3040.                     case NPC_FIREWORK_BIG_BLUE:
  3041.                         return SPELL_ROCKET_BIG_BLUE;
  3042.                     case NPC_FIREWORK_BIG_GREEN:
  3043.                         return SPELL_ROCKET_BIG_GREEN;
  3044.                     case NPC_FIREWORK_BIG_PURPLE:
  3045.                         return SPELL_ROCKET_BIG_PURPLE;
  3046.                     case NPC_FIREWORK_BIG_RED:
  3047.                         return SPELL_ROCKET_BIG_RED;
  3048.                     case NPC_FIREWORK_BIG_YELLOW:
  3049.                         return SPELL_ROCKET_BIG_YELLOW;
  3050.                     case NPC_FIREWORK_BIG_WHITE:
  3051.                         return SPELL_ROCKET_BIG_WHITE;
  3052.                     default:
  3053.                         return 0;
  3054.                 }
  3055.             }
  3056.  
  3057.             uint32 GetFireworkGameObjectId()
  3058.             {
  3059.                 uint32 spellId = 0;
  3060.  
  3061.                 switch (me->GetEntry())
  3062.                 {
  3063.                     case NPC_CLUSTER_BLUE:
  3064.                         spellId = GetFireworkSpell(NPC_FIREWORK_BLUE);
  3065.                         break;
  3066.                     case NPC_CLUSTER_GREEN:
  3067.                         spellId = GetFireworkSpell(NPC_FIREWORK_GREEN);
  3068.                         break;
  3069.                     case NPC_CLUSTER_PURPLE:
  3070.                         spellId = GetFireworkSpell(NPC_FIREWORK_PURPLE);
  3071.                         break;
  3072.                     case NPC_CLUSTER_RED:
  3073.                         spellId = GetFireworkSpell(NPC_FIREWORK_RED);
  3074.                         break;
  3075.                     case NPC_CLUSTER_YELLOW:
  3076.                         spellId = GetFireworkSpell(NPC_FIREWORK_YELLOW);
  3077.                         break;
  3078.                     case NPC_CLUSTER_WHITE:
  3079.                         spellId = GetFireworkSpell(NPC_FIREWORK_WHITE);
  3080.                         break;
  3081.                     case NPC_CLUSTER_BIG_BLUE:
  3082.                         spellId = GetFireworkSpell(NPC_FIREWORK_BIG_BLUE);
  3083.                         break;
  3084.                     case NPC_CLUSTER_BIG_GREEN:
  3085.                         spellId = GetFireworkSpell(NPC_FIREWORK_BIG_GREEN);
  3086.                         break;
  3087.                     case NPC_CLUSTER_BIG_PURPLE:
  3088.                         spellId = GetFireworkSpell(NPC_FIREWORK_BIG_PURPLE);
  3089.                         break;
  3090.                     case NPC_CLUSTER_BIG_RED:
  3091.                         spellId = GetFireworkSpell(NPC_FIREWORK_BIG_RED);
  3092.                         break;
  3093.                     case NPC_CLUSTER_BIG_YELLOW:
  3094.                         spellId = GetFireworkSpell(NPC_FIREWORK_BIG_YELLOW);
  3095.                         break;
  3096.                     case NPC_CLUSTER_BIG_WHITE:
  3097.                         spellId = GetFireworkSpell(NPC_FIREWORK_BIG_WHITE);
  3098.                         break;
  3099.                     case NPC_CLUSTER_ELUNE:
  3100.                         spellId = GetFireworkSpell(urand(NPC_FIREWORK_BLUE, NPC_FIREWORK_WHITE));
  3101.                         break;
  3102.                 }
  3103.  
  3104.                 const SpellInfo* spellInfo = sSpellMgr->GetSpellInfo(spellId);
  3105.  
  3106.                 if (spellInfo && spellInfo->Effects[0].Effect == SPELL_EFFECT_SUMMON_OBJECT_WILD)
  3107.                     return spellInfo->Effects[0].MiscValue;
  3108.  
  3109.                 return 0;
  3110.             }
  3111.  
  3112.             void Reset()
  3113.             {
  3114.                 if (GameObject* launcher = FindNearestLauncher())
  3115.                 {
  3116.                     launcher->SendCustomAnim(ANIM_GO_LAUNCH_FIREWORK);
  3117.                     me->SetOrientation(launcher->GetOrientation() + M_PI/2);
  3118.                 }
  3119.                 else
  3120.                     return;
  3121.  
  3122.                 if (isCluster())
  3123.                 {
  3124.                     // Check if we are near Elune'ara lake south, if so try to summon Omen or a minion
  3125.                     if (me->GetZoneId() == ZONE_MOONGLADE)
  3126.                     {
  3127.                         if (!me->FindNearestCreature(NPC_OMEN, 100.0f, false) && me->GetDistance2d(omenSummonPos.GetPositionX(), omenSummonPos.GetPositionY()) <= 100.0f)
  3128.                         {
  3129.                             switch (urand(0,9))
  3130.                             {
  3131.                                 case 0:
  3132.                                 case 1:
  3133.                                 case 2:
  3134.                                 case 3:
  3135.                                     if (Creature* minion = me->SummonCreature(NPC_MINION_OF_OMEN, me->GetPositionX()+frand(-5.0f, 5.0f), me->GetPositionY()+frand(-5.0f, 5.0f), me->GetPositionZ(), 0.0f, TEMPSUMMON_CORPSE_TIMED_DESPAWN, 20000))
  3136.                                         minion->AI()->AttackStart(me->SelectNearestPlayer(20.0f));
  3137.                                     break;
  3138.                                 case 9:
  3139.                                     me->SummonCreature(NPC_OMEN, omenSummonPos);
  3140.                                     break;
  3141.                             }
  3142.                         }
  3143.                     }
  3144.                     if (me->GetEntry() == NPC_CLUSTER_ELUNE)
  3145.                         DoCast(SPELL_LUNAR_FORTUNE);
  3146.  
  3147.                     float displacement = 0.7f;
  3148.                     for (uint8 i = 0; i < 4; i++)
  3149.                         me->SummonGameObject(GetFireworkGameObjectId(), me->GetPositionX() + (i%2 == 0 ? displacement : -displacement), me->GetPositionY() + (i > 1 ? displacement : -displacement), me->GetPositionZ() + 4.0f, me->GetOrientation(), 0.0f, 0.0f, 0.0f, 0.0f, 1);
  3150.                 }
  3151.                 else
  3152.                     //me->CastSpell(me, GetFireworkSpell(me->GetEntry()), true);
  3153.                     me->CastSpell(me->GetPositionX(), me->GetPositionY(), me->GetPositionZ(), GetFireworkSpell(me->GetEntry()), true);
  3154.             }
  3155.         };
  3156.  
  3157.         CreatureAI* GetAI(Creature* creature) const
  3158.         {
  3159.             return new npc_fireworkAI(creature);
  3160.         }
  3161. };
  3162.  
  3163. /*#####
  3164. # npc_spring_rabbit
  3165. #####*/
  3166.  
  3167. enum rabbitSpells
  3168. {
  3169.     SPELL_SPRING_FLING          = 61875,
  3170.     SPELL_SPRING_RABBIT_JUMP    = 61724,
  3171.     SPELL_SPRING_RABBIT_WANDER  = 61726,
  3172.     SPELL_SUMMON_BABY_BUNNY     = 61727,
  3173.     SPELL_SPRING_RABBIT_IN_LOVE = 61728,
  3174.     NPC_SPRING_RABBIT           = 32791
  3175. };
  3176.  
  3177. class npc_spring_rabbit : public CreatureScript
  3178. {
  3179.     public:
  3180.         npc_spring_rabbit() : CreatureScript("npc_spring_rabbit") { }
  3181.  
  3182.         CreatureAI* GetAI(Creature* creature) const
  3183.         {
  3184.             return new npc_spring_rabbitAI(creature);
  3185.         }
  3186.  
  3187.         struct npc_spring_rabbitAI : public ScriptedAI
  3188.         {
  3189.             npc_spring_rabbitAI(Creature* creature) : ScriptedAI(creature) { }
  3190.  
  3191.             bool inLove;
  3192.             uint32 jumpTimer;
  3193.             uint32 bunnyTimer;
  3194.             uint32 searchTimer;
  3195.             uint64 rabbitGUID;
  3196.  
  3197.             void Reset()
  3198.             {
  3199.                 inLove = false;
  3200.                 rabbitGUID = 0;
  3201.                 jumpTimer = urand(5000, 10000);
  3202.                 bunnyTimer = urand(10000, 20000);
  3203.                 searchTimer = urand(5000, 10000);
  3204.                 if (Unit* owner = me->GetOwner())
  3205.                     me->GetMotionMaster()->MoveFollow(owner, PET_FOLLOW_DIST, PET_FOLLOW_ANGLE);
  3206.             }
  3207.  
  3208.             void EnterCombat(Unit * /*who*/) { }
  3209.  
  3210.             void DoAction(const int32 /*param*/)
  3211.             {
  3212.                 inLove = true;
  3213.                 if (Unit* owner = me->GetOwner())
  3214.                     owner->CastSpell(owner, SPELL_SPRING_FLING, true);
  3215.             }
  3216.  
  3217.             void UpdateAI(const uint32 diff)
  3218.             {
  3219.                 if (inLove)
  3220.                 {
  3221.                     if (jumpTimer <= diff)
  3222.                     {
  3223.                         if (Unit* rabbit = Unit::GetUnit(*me, rabbitGUID))
  3224.                             DoCast(rabbit, SPELL_SPRING_RABBIT_JUMP);
  3225.                         jumpTimer = urand(5000, 10000);
  3226.                     } else jumpTimer -= diff;
  3227.  
  3228.                     if (bunnyTimer <= diff)
  3229.                     {
  3230.                         DoCast(SPELL_SUMMON_BABY_BUNNY);
  3231.                         bunnyTimer = urand(20000, 40000);
  3232.                     } else bunnyTimer -= diff;
  3233.                 }
  3234.                 else
  3235.                 {
  3236.                     if (searchTimer <= diff)
  3237.                     {
  3238.                         if (Creature* rabbit = me->FindNearestCreature(NPC_SPRING_RABBIT, 10.0f))
  3239.                         {
  3240.                             if (rabbit == me || rabbit->HasAura(SPELL_SPRING_RABBIT_IN_LOVE))
  3241.                                 return;
  3242.  
  3243.                             me->AddAura(SPELL_SPRING_RABBIT_IN_LOVE, me);
  3244.                             DoAction(1);
  3245.                             rabbit->AddAura(SPELL_SPRING_RABBIT_IN_LOVE, rabbit);
  3246.                             rabbit->AI()->DoAction(1);
  3247.                             rabbit->CastSpell(rabbit, SPELL_SPRING_RABBIT_JUMP, true);
  3248.                             rabbitGUID = rabbit->GetGUID();
  3249.                         }
  3250.                         searchTimer = urand(5000, 10000);
  3251.                     } else searchTimer -= diff;
  3252.                 }
  3253.             }
  3254.         };
  3255. };
  3256.  
  3257. /*######
  3258. ## npc_generic_harpoon_cannon
  3259. ######*/
  3260.  
  3261. class npc_generic_harpoon_cannon : public CreatureScript
  3262. {
  3263.     public:
  3264.         npc_generic_harpoon_cannon() : CreatureScript("npc_generic_harpoon_cannon") { }
  3265.  
  3266.         struct npc_generic_harpoon_cannonAI : public ScriptedAI
  3267.         {
  3268.             npc_generic_harpoon_cannonAI(Creature* creature) : ScriptedAI(creature) {}
  3269.  
  3270.             void Reset()
  3271.             {
  3272.                 me->SetUnitMovementFlags(MOVEMENTFLAG_ROOT);
  3273.             }
  3274.         };
  3275.  
  3276.         CreatureAI* GetAI(Creature* creature) const
  3277.         {
  3278.             return new npc_generic_harpoon_cannonAI(creature);
  3279.         }
  3280. };
  3281.  
  3282. /*######
  3283. ## npc_experience
  3284. ######*/
  3285.  
  3286. #define GOSSIP_CHOOSE_FACTION     "I would like to choose my faction"
  3287. #define GOSSIP_TP_STORMIND        "I would like to go to Stormwind"
  3288. #define GOSSIP_TP_ORGRI           "I would like to go to Orgrimmar"
  3289.  
  3290. class npc_choose_faction : public CreatureScript
  3291. {
  3292.     public:
  3293.         npc_choose_faction() : CreatureScript("npc_choose_faction") { }
  3294.  
  3295.         bool OnGossipHello(Player* player, Creature* creature)
  3296.         {
  3297.             if (player->getRace() == RACE_PANDAREN_NEUTRAL)
  3298.                 player->ADD_GOSSIP_ITEM(GOSSIP_ICON_CHAT, GOSSIP_CHOOSE_FACTION, GOSSIP_SENDER_MAIN, GOSSIP_ACTION_INFO_DEF + 1);
  3299.             else if (player->getRace() == RACE_PANDAREN_ALLI)
  3300.                 player->ADD_GOSSIP_ITEM(GOSSIP_ICON_CHAT, GOSSIP_TP_STORMIND, GOSSIP_SENDER_MAIN, GOSSIP_ACTION_INFO_DEF + 2);
  3301.             else if (player->getRace() == RACE_PANDAREN_HORDE)
  3302.                 player->ADD_GOSSIP_ITEM(GOSSIP_ICON_CHAT, GOSSIP_TP_ORGRI, GOSSIP_SENDER_MAIN, GOSSIP_ACTION_INFO_DEF + 3);
  3303.  
  3304.             player->PlayerTalkClass->SendGossipMenu(GOSSIP_TEXT_EXP, creature->GetGUID());
  3305.             return true;
  3306.         }
  3307.  
  3308.         bool OnGossipSelect(Player* player, Creature* /*creature*/, uint32 /*sender*/, uint32 action)
  3309.         {
  3310.             if (action == GOSSIP_ACTION_INFO_DEF + 1)
  3311.                 player->ShowNeutralPlayerFactionSelectUI();
  3312.             else if (action == GOSSIP_ACTION_INFO_DEF + 2)
  3313.                 player->TeleportTo(0, -8866.55f, 671.93f, 97.90f, 5.31f);
  3314.             else if (action == GOSSIP_ACTION_INFO_DEF + 3)
  3315.                 player->TeleportTo(1, 1577.30f, -4453.64f, 15.68f, 1.84f);
  3316.  
  3317.             player->PlayerTalkClass->SendCloseGossip();
  3318.             return true;
  3319.         }
  3320. };
  3321.  
  3322. class npc_choose_faction_after_shop : public CreatureScript
  3323. {
  3324.     public:
  3325.         npc_choose_faction_after_shop() : CreatureScript("npc_choose_faction_after_shop") { }
  3326.  
  3327.         bool OnGossipHello(Player* player, Creature* creature)
  3328.         {
  3329.             if (player->getRace() == RACE_PANDAREN_NEUTRAL)
  3330.             {
  3331.                 if (player->getLevel() > 69) // minimum level sale = 70
  3332.                     player->ADD_GOSSIP_ITEM(GOSSIP_ICON_CHAT, GOSSIP_CHOOSE_FACTION, GOSSIP_SENDER_MAIN, GOSSIP_ACTION_INFO_DEF + 1);
  3333.             }
  3334.             else if (player->getRace() == RACE_PANDAREN_ALLI)
  3335.                 player->ADD_GOSSIP_ITEM(GOSSIP_ICON_CHAT, GOSSIP_TP_STORMIND, GOSSIP_SENDER_MAIN, GOSSIP_ACTION_INFO_DEF + 2);
  3336.             else if (player->getRace() == RACE_PANDAREN_HORDE)
  3337.                 player->ADD_GOSSIP_ITEM(GOSSIP_ICON_CHAT, GOSSIP_TP_ORGRI, GOSSIP_SENDER_MAIN, GOSSIP_ACTION_INFO_DEF + 3);
  3338.  
  3339.             player->PlayerTalkClass->SendGossipMenu(1, creature->GetGUID());
  3340.             return true;
  3341.         }
  3342.  
  3343.         bool OnGossipSelect(Player* player, Creature* /*creature*/, uint32 /*sender*/, uint32 action)
  3344.         {
  3345.             if (action == GOSSIP_ACTION_INFO_DEF + 1)
  3346.                 player->ShowNeutralPlayerFactionSelectUI();
  3347.             else if (action == GOSSIP_ACTION_INFO_DEF + 2)
  3348.                 player->TeleportTo(0, -8866.55f, 671.93f, 97.90f, 5.31f);
  3349.             else if (action == GOSSIP_ACTION_INFO_DEF + 3)
  3350.                 player->TeleportTo(1, 1577.30f, -4453.64f, 15.68f, 1.84f);
  3351.  
  3352.             player->PlayerTalkClass->SendCloseGossip();
  3353.             return true;
  3354.         }
  3355. };
  3356.  
  3357. /*######
  3358. ## npc_rate_xp_modifier
  3359. ######*/
  3360.  
  3361. #define GOSSIP_TEXT_EXP_MODIF    1587
  3362. #define GOSSIP_TEXT_EXP_MODIF_OK 1588
  3363. #define GOSSIP_TEXT_EXP_NORMAL   1589
  3364. #define GOSSIP_ITEM_XP_CLOSE     "Good bye."
  3365.  
  3366. class npc_rate_xp_modifier : public CreatureScript
  3367. {
  3368.     public:
  3369.         npc_rate_xp_modifier() : CreatureScript("npc_rate_xp_modifier") { }
  3370.  
  3371.         bool OnGossipHello(Player *pPlayer, Creature *pCreature)
  3372.         {
  3373.             uint32 maxRates = sWorld->getRate(RATE_XP_KILL);
  3374.  
  3375.             for (uint32 i = 1; i < sWorld->getRate(RATE_XP_KILL); ++i)
  3376.             {
  3377.                 std::ostringstream gossipText;
  3378.                 gossipText << "I would like to change my rates" << i;
  3379.                 pPlayer->ADD_GOSSIP_ITEM(GOSSIP_ICON_CHAT, gossipText.str(), GOSSIP_SENDER_MAIN, i);
  3380.             }
  3381.  
  3382.             if (pPlayer->GetPersonnalXpRate())
  3383.             {
  3384.                 std::ostringstream gossipText;
  3385.                 gossipText << "I would like to restore my rates (" << sWorld->getRate(RATE_XP_KILL) << ")";
  3386.                 pPlayer->ADD_GOSSIP_ITEM(GOSSIP_ICON_CHAT, gossipText.str(), GOSSIP_SENDER_MAIN, 0);
  3387.             }
  3388.  
  3389.             pPlayer->PlayerTalkClass->SendGossipMenu(GOSSIP_TEXT_EXP_MODIF, pCreature->GetGUID());
  3390.             return true;
  3391.         }
  3392.  
  3393.         bool OnGossipSelect(Player* pPlayer, Creature* pCreature, uint32 /*uiSender*/, uint32 uiAction)
  3394.         {
  3395.             if (uiAction < 0 || uiAction >= sWorld->getRate(RATE_XP_KILL))
  3396.             {
  3397.                 pPlayer->PlayerTalkClass->SendCloseGossip();
  3398.                 return true;
  3399.             }
  3400.        
  3401.             pPlayer->SetPersonnalXpRate(float(uiAction));
  3402.  
  3403.             pPlayer->PlayerTalkClass->ClearMenus();
  3404.             pPlayer->ADD_GOSSIP_ITEM(GOSSIP_ICON_CHAT, GOSSIP_ITEM_XP_CLOSE, GOSSIP_SENDER_MAIN, GOSSIP_ACTION_INFO_DEF);
  3405.             pPlayer->PlayerTalkClass->SendGossipMenu(GOSSIP_TEXT_EXP_MODIF_OK, pCreature->GetGUID());
  3406.  
  3407.             return true;
  3408.         }
  3409. };
  3410.  
  3411. /*######
  3412. ## npc_capacitor_totem
  3413. ######*/
  3414.  
  3415. class npc_capacitor_totem : public CreatureScript
  3416. {
  3417.     public:
  3418.         npc_capacitor_totem() : CreatureScript("npc_capacitor_totem") { }
  3419.  
  3420.     struct npc_capacitor_totemAI : public ScriptedAI
  3421.     {
  3422.         uint32 CastTimer;
  3423.  
  3424.         npc_capacitor_totemAI(Creature* creature) : ScriptedAI(creature) { }
  3425.  
  3426.         void UpdateAI(uint32 const diff)
  3427.         {
  3428.             if (me->HasUnitState(UNIT_STATE_CASTING))
  3429.                 return;
  3430.  
  3431.             me->CastSpell(me, 118905, false);
  3432.         }
  3433.     };
  3434.  
  3435.     CreatureAI* GetAI(Creature* creature) const
  3436.     {
  3437.         return new npc_capacitor_totemAI(creature);
  3438.     }
  3439. };
  3440.  
  3441. /*######
  3442. ## npc_feral_spirit
  3443. ######*/
  3444.  
  3445. class npc_feral_spirit : public CreatureScript
  3446. {
  3447.     public:
  3448.         npc_feral_spirit() : CreatureScript("npc_feral_spirit") { }
  3449.  
  3450.         struct npc_feral_spiritAI : public ScriptedAI
  3451.         {
  3452.             npc_feral_spiritAI(Creature* creature) : ScriptedAI(creature) {}
  3453.  
  3454.             uint32 SpiritBiteTimer;
  3455.  
  3456.             void Reset()
  3457.             {
  3458.                 SpiritBiteTimer = 6000;
  3459.             }
  3460.  
  3461.             void UpdateAI(const uint32 diff)
  3462.             {
  3463.                 if (!UpdateVictim())
  3464.                     return;
  3465.  
  3466.                 if (me->HasUnitState(UNIT_STATE_CASTING))
  3467.                     return;
  3468.  
  3469.                 if (SpiritBiteTimer <= diff)
  3470.                 {
  3471.                     me->CastSpell(me->getVictim(), 58859, true);
  3472.                     SpiritBiteTimer = 6000;
  3473.                 }
  3474.                 else
  3475.                     SpiritBiteTimer -= diff;
  3476.  
  3477.                 DoMeleeAttackIfReady();
  3478.             }
  3479.         };
  3480.  
  3481.         CreatureAI* GetAI(Creature* creature) const
  3482.         {
  3483.             return new npc_feral_spiritAI(creature);
  3484.         }
  3485. };
  3486.  
  3487. /*######
  3488. ## npc_spirit_link_totem
  3489. ######*/
  3490.  
  3491. class npc_spirit_link_totem : public CreatureScript
  3492. {
  3493.     public:
  3494.         npc_spirit_link_totem() : CreatureScript("npc_spirit_link_totem") { }
  3495.  
  3496.     struct npc_spirit_link_totemAI : public ScriptedAI
  3497.     {
  3498.         uint32 CastTimer;
  3499.  
  3500.         npc_spirit_link_totemAI(Creature* creature) : ScriptedAI(creature)
  3501.         {
  3502.             CastTimer = 1000;
  3503.  
  3504.             if (creature->GetOwner() && creature->GetOwner()->GetTypeId() == TYPEID_PLAYER)
  3505.             {
  3506.                 if (creature->GetEntry() == 53006)
  3507.                 {
  3508.                     creature->CastSpell(creature, 98007, false);
  3509.                     creature->CastSpell(creature, 98017, true);
  3510.                 }
  3511.             }
  3512.         }
  3513.  
  3514.         void UpdateAI(uint32 const diff)
  3515.         {
  3516.             if (CastTimer >= diff)
  3517.             {
  3518.                 if (me->GetOwner() && me->GetOwner()->GetTypeId() == TYPEID_PLAYER)
  3519.                 {
  3520.                     if (me->GetEntry() == 53006)
  3521.                     {
  3522.                         me->CastSpell(me, 98007, false);
  3523.                         me->CastSpell(me, 98017, true);
  3524.                     }
  3525.                 }
  3526.             }
  3527.  
  3528.             CastTimer = 0;
  3529.         }
  3530.     };
  3531.  
  3532.     CreatureAI* GetAI(Creature* creature) const
  3533.     {
  3534.         return new npc_spirit_link_totemAI(creature);
  3535.     }
  3536. };
  3537.  
  3538. /*######
  3539. # npc_demoralizing_banner
  3540. ######*/
  3541.  
  3542. class npc_demoralizing_banner : public CreatureScript
  3543. {
  3544.     public:
  3545.         npc_demoralizing_banner() : CreatureScript("npc_demoralizing_banner") { }
  3546.  
  3547.         struct npc_demoralizing_bannerAI : public ScriptedAI
  3548.         {
  3549.             uint32 demoralizingTimer;
  3550.  
  3551.             npc_demoralizing_bannerAI(Creature* creature) : ScriptedAI(creature)
  3552.             {
  3553.                 demoralizingTimer = 1000;
  3554.  
  3555.                 Unit* owner = creature->GetOwner();
  3556.  
  3557.                 if (owner)
  3558.                     owner->CastSpell(creature, 114205, true);
  3559.             }
  3560.  
  3561.             void UpdateAI(const uint32 diff)
  3562.             {
  3563.                 Unit* owner = me->GetOwner();
  3564.  
  3565.                 if (!owner)
  3566.                     return;
  3567.  
  3568.                 if (demoralizingTimer <= diff)
  3569.                 {
  3570.                     owner->CastSpell(me, 114205, true);
  3571.                     demoralizingTimer = 0;
  3572.                 }
  3573.                 else
  3574.                     demoralizingTimer -= diff;
  3575.             }
  3576.         };
  3577.  
  3578.         CreatureAI* GetAI(Creature* creature) const
  3579.         {
  3580.             return new npc_demoralizing_bannerAI(creature);
  3581.         }
  3582. };
  3583.  
  3584. /*######
  3585. # npc_frozen_orb
  3586. ######*/
  3587.  
  3588. enum frozenOrbSpells
  3589. {
  3590.     SPELL_FINGERS_OF_FROST_VISUAL   = 44544,
  3591.     SPELL_SELF_SNARE_90             = 82736,
  3592.     SPELL_SNARE_DAMAGE              = 84721,
  3593.     SPELL_FINGERS_OF_FROST          = 126084,
  3594. };
  3595.  
  3596. class npc_frozen_orb : public CreatureScript
  3597. {
  3598.     public:
  3599.         npc_frozen_orb() : CreatureScript("npc_frozen_orb") { }
  3600.  
  3601.         struct npc_frozen_orbAI : public ScriptedAI
  3602.         {
  3603.             npc_frozen_orbAI(Creature* creature) : ScriptedAI(creature)
  3604.             {
  3605.                 frozenOrbTimer = 0;
  3606.             }
  3607.  
  3608.             uint32 frozenOrbTimer;
  3609.  
  3610.             void IsSummonedBy(Unit* owner)
  3611.             {
  3612.                 if (owner && owner->GetTypeId() == TYPEID_PLAYER)
  3613.                 {
  3614.                     owner->CastSpell(me, SPELL_SNARE_DAMAGE, true);
  3615.                     owner->CastSpell(owner, SPELL_FINGERS_OF_FROST_VISUAL, true);
  3616.                     owner->CastSpell(owner, SPELL_FINGERS_OF_FROST, true);
  3617.                     me->AddAura(SPELL_SELF_SNARE_90, me);
  3618.  
  3619.                     frozenOrbTimer = 1000;
  3620.                 }
  3621.                 else
  3622.                     me->DespawnOrUnsummon();
  3623.             }
  3624.  
  3625.             void UpdateAI(const uint32 diff)
  3626.             {
  3627.                 Unit* owner = me->GetOwner();
  3628.  
  3629.                 if (!owner)
  3630.                     return;
  3631.  
  3632.                 if (frozenOrbTimer <= diff)
  3633.                 {
  3634.                     if (owner && owner->ToPlayer())
  3635.                         if (owner->ToPlayer()->HasSpellCooldown(SPELL_SNARE_DAMAGE))
  3636.                             owner->ToPlayer()->RemoveSpellCooldown(SPELL_SNARE_DAMAGE);
  3637.  
  3638.                     owner->CastSpell(me, SPELL_SNARE_DAMAGE, true);
  3639.                     frozenOrbTimer = 1000;
  3640.                 }
  3641.                 else
  3642.                     frozenOrbTimer -= diff;
  3643.             }
  3644.         };
  3645.  
  3646.         CreatureAI* GetAI(Creature* creature) const
  3647.         {
  3648.             return new npc_frozen_orbAI(creature);
  3649.         }
  3650. };
  3651.  
  3652. /*######
  3653. # npc_guardian_of_ancient_kings
  3654. ######*/
  3655.  
  3656. enum GuardianSpellsAndEntries
  3657. {
  3658.     NPC_PROTECTION_GUARDIAN         = 46490,
  3659.     NPC_HOLY_GUARDIAN               = 46499,
  3660.     NPC_RETRI_GUARDIAN              = 46506,
  3661.     SPELL_ANCIENT_GUARDIAN_VISUAL   = 86657,
  3662.     SPELL_ANCIENT_HEALER            = 86674,
  3663. };
  3664.  
  3665. class npc_guardian_of_ancient_kings : public CreatureScript
  3666. {
  3667.     public:
  3668.         npc_guardian_of_ancient_kings() : CreatureScript("npc_guardian_of_ancient_kings") { }
  3669.  
  3670.         struct npc_guardian_of_ancient_kingsAI : public ScriptedAI
  3671.         {
  3672.             npc_guardian_of_ancient_kingsAI(Creature *creature) : ScriptedAI(creature) {}
  3673.  
  3674.             void Reset()
  3675.             {
  3676.                 if (me->GetEntry() == NPC_RETRI_GUARDIAN || me->GetEntry() == NPC_HOLY_GUARDIAN)
  3677.                     me->SetFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NOT_SELECTABLE | UNIT_FLAG_IMMUNE_TO_PC | UNIT_FLAG_NON_ATTACKABLE);
  3678.                 else if (me->GetEntry() == NPC_PROTECTION_GUARDIAN)
  3679.                     me->SetFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NOT_SELECTABLE | UNIT_FLAG_IMMUNE_TO_PC | UNIT_FLAG_NON_ATTACKABLE | UNIT_FLAG_DISABLE_MOVE);
  3680.  
  3681.                 if (me->GetEntry() == NPC_RETRI_GUARDIAN)
  3682.                     me->SetReactState(REACT_DEFENSIVE);
  3683.                 else
  3684.                     me->SetReactState(REACT_PASSIVE);
  3685.  
  3686.                 if (me->GetEntry() == NPC_PROTECTION_GUARDIAN)
  3687.                 {
  3688.                     if (me->GetOwner())
  3689.                         DoCast(me->GetOwner(), SPELL_ANCIENT_GUARDIAN_VISUAL);
  3690.                 }
  3691.                 else if (me->GetEntry() == NPC_RETRI_GUARDIAN)
  3692.                 {
  3693.                     if (me->GetOwner())
  3694.                     {
  3695.                         if (me->GetOwner()->getVictim())
  3696.                             AttackStart(me->GetOwner()->getVictim());
  3697.  
  3698.                         DoCast(me, 86703, true);
  3699.                     }
  3700.                 }
  3701.                 else if (me->GetEntry() == NPC_HOLY_GUARDIAN)
  3702.                     if (me->GetOwner())
  3703.                         me->GetOwner()->CastSpell(me->GetOwner(), SPELL_ANCIENT_HEALER, true);
  3704.             }
  3705.  
  3706.             void OwnerAttacked(Unit* target)
  3707.             {
  3708.                 if (me->getVictim() != target)
  3709.                     AttackStart(target);
  3710.             }
  3711.  
  3712.             void UpdateAI(const uint32 diff)
  3713.             {
  3714.                 if (!UpdateVictim())
  3715.                     return;
  3716.  
  3717.                 if (me->HasUnitState(UNIT_STATE_CASTING))
  3718.                     return;
  3719.  
  3720.                 DoMeleeAttackIfReady();
  3721.             }
  3722.         };
  3723.  
  3724.         CreatureAI* GetAI(Creature* creature) const
  3725.         {
  3726.             return new npc_guardian_of_ancient_kingsAI(creature);
  3727.         }
  3728. };
  3729.  
  3730. /*######
  3731. # npc_power_word_barrier
  3732. ######*/
  3733.  
  3734. class npc_power_word_barrier : public CreatureScript
  3735. {
  3736.     public:
  3737.         npc_power_word_barrier() : CreatureScript("npc_power_word_barrier") { }
  3738.  
  3739.         struct npc_power_word_barrierAI : public ScriptedAI
  3740.         {
  3741.             uint32 frozenOrbTimer;
  3742.  
  3743.             npc_power_word_barrierAI(Creature* creature) : ScriptedAI(creature)
  3744.             {
  3745.                 Unit* owner = creature->GetOwner();
  3746.  
  3747.                 if (owner)
  3748.                 {
  3749.                     creature->CastSpell(creature, 115725, true); // Barrier visual
  3750.                     creature->CastSpell(creature, 81781, true);  // Periodic Trigger Spell
  3751.                 }
  3752.             }
  3753.  
  3754.             void UpdateAI(const uint32 diff)
  3755.             {
  3756.                 Unit* owner = me->GetOwner();
  3757.  
  3758.                 if (!owner)
  3759.                     return;
  3760.  
  3761.                 if (!me->HasAura(115725))
  3762.                     me->CastSpell(me, 115725, true);
  3763.                 if (!me->HasAura(81781))
  3764.                     me->CastSpell(me, 81781, true);
  3765.             }
  3766.         };
  3767.  
  3768.         CreatureAI* GetAI(Creature* creature) const
  3769.         {
  3770.             return new npc_power_word_barrierAI(creature);
  3771.         }
  3772. };
  3773.  
  3774.  
  3775. // Warlock's Spell: Demonic Gateway
  3776. class npc_demonic_gateway : public CreatureScript
  3777. {
  3778. public:
  3779.     npc_demonic_gateway() : CreatureScript("npc_demonic_gateway") { }
  3780.  
  3781.     struct npc_demonic_gatewayAI : public ScriptedAI
  3782.     {
  3783.         npc_demonic_gatewayAI(Creature* creature) : ScriptedAI(creature)
  3784.         {
  3785.             visual_buff_purple[0] = 113915;
  3786.             visual_buff_purple[1] = 113916;
  3787.             visual_buff_purple[2] = 113917;
  3788.             visual_buff_purple[3] = 113918;
  3789.             visual_buff_purple[4] = 113919;
  3790.  
  3791.             visual_buff_green[0] = 113903;
  3792.             visual_buff_green[1] = 113911;
  3793.             visual_buff_green[2] = 113912;
  3794.             visual_buff_green[3] = 113913;
  3795.             visual_buff_green[4] = 113914;
  3796.  
  3797.             aura_update = 10000;
  3798.         }
  3799.  
  3800.         uint32 aura_update;
  3801.  
  3802.         uint32 visual_buff_purple[5];
  3803.         uint32 visual_buff_green[5];
  3804.  
  3805.         void IsSummonedBy(Unit * summoner) override
  3806.         {
  3807.             me->SetFlag(UNIT_NPC_FLAGS, UNIT_NPC_FLAG_SPELLCLICK);
  3808.             if (!summoner->HasAura(113901))
  3809.             {
  3810.                 summoner->CastSpell(summoner, 113901, true);
  3811.                 if (auto aura = summoner->GetAura(113901))
  3812.                     aura->SetCharges(0);
  3813.             }
  3814.         }
  3815.  
  3816.         void UpdateAI(uint32 const diff)
  3817.         {
  3818.             if (aura_update <= diff)
  3819.             {
  3820.                 aura_update = 10000;
  3821.                 auto owner = me->GetOwner();
  3822.                 if (!owner)
  3823.                 {
  3824.                     me->ForcedDespawn();
  3825.                     return;
  3826.                 }
  3827.  
  3828.                 // Only one gate maintains charging up
  3829.                 if (me->GetEntry() == 59262)
  3830.                     return;
  3831.  
  3832.                 // Get stacking aura
  3833.                 if (auto demonicGateway = owner->GetAura(113901))
  3834.                 {
  3835.                     uint8 charges = demonicGateway->GetCharges() + 1;
  3836.                     if (charges > 5)
  3837.                         return;
  3838.  
  3839.                     demonicGateway->SetCharges(charges);
  3840.                     demonicGateway->GetEffect(EFFECT_0)->SetAmount(charges);
  3841.  
  3842.                     std::list< Creature* > creature_list;
  3843.                     me->GetCreatureListWithEntryInGrid(creature_list, 59262, 101);
  3844.                     // Get second gateway
  3845.                     Creature * target = NULL;
  3846.                     for (auto itr : creature_list)
  3847.                     {
  3848.                         if (itr->GetOwnerGUID() == me->GetOwnerGUID())
  3849.                         {
  3850.                             target = itr;
  3851.                             break;
  3852.                         }
  3853.                     }
  3854.  
  3855.                     if (target)
  3856.                     {
  3857.                         me->CastSpell(me, visual_buff_purple[charges - 1]);
  3858.                         target->CastSpell(target, visual_buff_green[charges - 1]);
  3859.                     }
  3860.                 }
  3861.             }
  3862.             else
  3863.                 aura_update -= diff;
  3864.         }
  3865.  
  3866.         void OnSpellClick(Unit * clicker, bool &)
  3867.         {
  3868.             if (clicker->GetTypeId() != TYPEID_PLAYER)
  3869.                 return;
  3870.  
  3871.             // Cooldown on gateway use
  3872.             if (clicker->HasAura(113942))
  3873.                 return;
  3874.  
  3875.             auto owner = me->GetOwner();
  3876.             if (!owner)
  3877.                 return;
  3878.  
  3879.             // Get stacking aura
  3880.             auto aura = owner->GetAura(113901);
  3881.             if (!aura)
  3882.                 return;
  3883.  
  3884.             uint8 charges = aura->GetCharges();
  3885.             if (!charges)
  3886.                 return;
  3887.  
  3888.             // Players must be in same group
  3889.             if (!clicker->IsInRaidWith(owner))
  3890.                 return;
  3891.  
  3892.             std::list< Creature* > creature_list;
  3893.             me->GetCreatureListWithEntryInGrid(creature_list, (me->GetEntry() == 59262 ? 59271 : 59262), 101);
  3894.             // Get second gateway
  3895.             Creature * target = NULL;
  3896.             for (auto itr : creature_list)
  3897.             {
  3898.                 if (itr->GetOwnerGUID() == me->GetOwnerGUID())
  3899.                 {
  3900.                     target = itr;
  3901.                     break;
  3902.                 }
  3903.             }
  3904.  
  3905.             if (!target)
  3906.                 return;
  3907.  
  3908.             aura->SetCharges(charges - 1);
  3909.             aura->GetEffect(EFFECT_0)->SetAmount(charges - 1);
  3910.  
  3911.             clicker->CastSpell(target, (me->GetEntry() == 59271 ? 120729 : 113896));
  3912.  
  3913.             // Remove charge visual
  3914.             if (auto demonicGateway = me->GetAura((me->GetEntry() == 59271 ? visual_buff_purple[charges - 1] : visual_buff_green[charges - 1])))
  3915.                 me->RemoveAura(demonicGateway);
  3916.  
  3917.             if (auto demonicGateway = target->GetAura((target->GetEntry() == 59271 ? visual_buff_purple[charges - 1] : visual_buff_green[charges - 1])))
  3918.                 target->RemoveAura(demonicGateway);
  3919.         }
  3920.     };
  3921.  
  3922.     CreatureAI* GetAI(Creature* creature) const
  3923.     {
  3924.         return new npc_demonic_gatewayAI(creature);
  3925.     }
  3926. };
  3927.  
  3928. /*######
  3929. # npc_xuen_the_white_tiger
  3930. ######*/
  3931.  
  3932. enum xuenSpells
  3933. {
  3934.     CRACKLING_TIGER_LIGHTNING   = 123996,
  3935.     PROVOKE                     = 130793,
  3936.     TIGER_LEAP                  = 124007,
  3937.     TIGER_LUST                  = 124009,
  3938. };
  3939.  
  3940. enum xuenEvents
  3941. {
  3942.     EVENT_LIGHTNING = 1,
  3943.     EVENT_PROVOKE   = 2,
  3944.     EVENT_LEAP      = 3,
  3945. };
  3946.  
  3947. class npc_xuen_the_white_tiger : public CreatureScript
  3948. {
  3949.     public:
  3950.         npc_xuen_the_white_tiger() : CreatureScript("npc_xuen_the_white_tiger") { }
  3951.  
  3952.         struct npc_xuen_the_white_tigerAI : public ScriptedAI
  3953.         {
  3954.             EventMap events;
  3955.  
  3956.             npc_xuen_the_white_tigerAI(Creature* creature) : ScriptedAI(creature)
  3957.             {
  3958.                 me->SetReactState(REACT_DEFENSIVE);
  3959.             }
  3960.  
  3961.             void Reset()
  3962.             {
  3963.                 events.Reset();
  3964.  
  3965.                 events.ScheduleEvent(EVENT_LIGHTNING, 500);
  3966.                 events.ScheduleEvent(EVENT_LEAP,      200);
  3967.                 events.ScheduleEvent(EVENT_PROVOKE,   200);
  3968.             }
  3969.  
  3970.             void UpdateAI(const uint32 diff)
  3971.             {
  3972.                 if (!UpdateVictim())
  3973.                 {
  3974.                     if (me->GetOwner())
  3975.                         if (Unit* victim = me->GetOwner()->getAttackerForHelper())
  3976.                             AttackStart(victim);
  3977.  
  3978.                     return;
  3979.                 }
  3980.  
  3981.                 if (me->HasUnitState(UNIT_STATE_CASTING))
  3982.                     return;
  3983.  
  3984.                 events.Update(diff);
  3985.  
  3986.                 while (uint32 eventId = events.ExecuteEvent())
  3987.                 {
  3988.                     switch (eventId)
  3989.                     {
  3990.                         case EVENT_LIGHTNING:
  3991.                         {
  3992.                             if (Unit* target = me->getVictim())
  3993.                             {
  3994.                                 me->CastSpell(target, CRACKLING_TIGER_LIGHTNING, false);
  3995.                             }
  3996.                             else if (me->GetOwner())
  3997.                             {
  3998.                                 if (Unit* target = me->GetOwner()->getAttackerForHelper())
  3999.                                     me->CastSpell(target, CRACKLING_TIGER_LIGHTNING, false);
  4000.                             }
  4001.  
  4002.                             events.ScheduleEvent(EVENT_LIGHTNING, 6000);
  4003.                             break;
  4004.                         }
  4005.                         case EVENT_LEAP:
  4006.                         {
  4007.                             if (Unit* target = me->getVictim())
  4008.                             {
  4009.                                 me->CastSpell(target, TIGER_LEAP, false);
  4010.                             }
  4011.                             else if (me->GetOwner())
  4012.                             {
  4013.                                 if (Unit* target = me->GetOwner()->getAttackerForHelper())
  4014.                                     me->CastSpell(target, TIGER_LEAP, false);
  4015.                             }
  4016.  
  4017.                             me->CastSpell(me, TIGER_LUST, false);
  4018.                             events.ScheduleEvent(EVENT_LEAP, 15000);
  4019.  
  4020.                             break;
  4021.                         }
  4022.                         case EVENT_PROVOKE:
  4023.                         {
  4024.                             Unit* m_owner = me->GetOwner();
  4025.                             if (!m_owner || m_owner->GetTypeId() != TYPEID_PLAYER)
  4026.                                 break;
  4027.  
  4028.                             Player* p_owner = m_owner->ToPlayer();
  4029.                             if (p_owner->GetSpecializationId(p_owner->GetActiveSpec()) != SPEC_MONK_BREWMASTER)
  4030.                                 break;
  4031.  
  4032.                             if (Unit* target = me->getVictim())
  4033.                             {
  4034.                                 if (target->GetTypeId() == TYPEID_UNIT)
  4035.                                     if (target->ToCreature()->IsDungeonBoss() || target->ToCreature()->isWorldBoss())
  4036.                                         break;
  4037.  
  4038.                                 me->CastSpell(target, PROVOKE, false);
  4039.                             }
  4040.                             else if (me->GetOwner())
  4041.                             {
  4042.                                 if (Unit* target = me->GetOwner()->getAttackerForHelper())
  4043.                                 {
  4044.                                     if (target->GetTypeId() == TYPEID_UNIT)
  4045.                                         if (target->ToCreature()->IsDungeonBoss() || target->ToCreature()->isWorldBoss())
  4046.                                             break;
  4047.  
  4048.                                     me->CastSpell(target, PROVOKE, false);
  4049.                                 }
  4050.                             }
  4051.  
  4052.                             events.ScheduleEvent(EVENT_PROVOKE, 15000);
  4053.                             break;
  4054.                         }
  4055.                         default:
  4056.                             break;
  4057.                     }
  4058.                 }
  4059.  
  4060.                 DoMeleeAttackIfReady();
  4061.             }
  4062.         };
  4063.  
  4064.         CreatureAI* GetAI(Creature* creature) const
  4065.         {
  4066.             return new npc_xuen_the_white_tigerAI(creature);
  4067.         }
  4068. };
  4069.  
  4070. /*######
  4071. # npc_murder_of_crows
  4072. ######*/
  4073.  
  4074. class npc_murder_of_crows : public CreatureScript
  4075. {
  4076.     public:
  4077.         npc_murder_of_crows() : CreatureScript("npc_murder_of_crows") { }
  4078.  
  4079.         struct npc_murder_of_crowsAI : public ScriptedAI
  4080.         {
  4081.             npc_murder_of_crowsAI(Creature *creature) : ScriptedAI(creature)
  4082.             {
  4083.                 me->SetReactState(REACT_DEFENSIVE);
  4084.             }
  4085.  
  4086.             void UpdateAI(const uint32 diff)
  4087.             {
  4088.                 if (me->GetReactState() != REACT_DEFENSIVE)
  4089.                     me->SetReactState(REACT_DEFENSIVE);
  4090.  
  4091.                 if (!UpdateVictim())
  4092.                     return;
  4093.  
  4094.                 if (me->HasUnitState(UNIT_STATE_CASTING))
  4095.                     return;
  4096.  
  4097.                 DoMeleeAttackIfReady();
  4098.             }
  4099.         };
  4100.  
  4101.         CreatureAI* GetAI(Creature* creature) const
  4102.         {
  4103.             return new npc_murder_of_crowsAI(creature);
  4104.         }
  4105. };
  4106.  
  4107. /*######
  4108. # npc_dire_beast
  4109. ######*/
  4110.  
  4111. class npc_dire_beast : public CreatureScript
  4112. {
  4113.     public:
  4114.         npc_dire_beast() : CreatureScript("npc_dire_beast") { }
  4115.  
  4116.         struct npc_dire_beastAI : public ScriptedAI
  4117.         {
  4118.             npc_dire_beastAI(Creature *creature) : ScriptedAI(creature) {}
  4119.  
  4120.             void Reset()
  4121.             {
  4122.                 me->SetReactState(REACT_DEFENSIVE);
  4123.  
  4124.                 if (me->GetOwner())
  4125.                     if (me->GetOwner()->getVictim() || me->GetOwner()->getAttackerForHelper())
  4126.                         AttackStart(me->GetOwner()->getVictim() ? me->GetOwner()->getVictim() : me->GetOwner()->getAttackerForHelper());
  4127.             }
  4128.  
  4129.             void UpdateAI(const uint32 diff)
  4130.             {
  4131.                 if (me->GetReactState() != REACT_DEFENSIVE)
  4132.                     me->SetReactState(REACT_DEFENSIVE);
  4133.  
  4134.                 if (!UpdateVictim())
  4135.                 {
  4136.                     if (Unit* owner = me->GetOwner())
  4137.                         if (Unit* newVictim = owner->getAttackerForHelper())
  4138.                             AttackStart(newVictim);
  4139.  
  4140.                     return;
  4141.                 }
  4142.  
  4143.                 if (me->getVictim())
  4144.                     if (Unit* owner = me->GetOwner())
  4145.                         if (Unit* ownerVictim = owner->getAttackerForHelper())
  4146.                             if (me->getVictim()->GetGUID() != ownerVictim->GetGUID())
  4147.                                 AttackStart(ownerVictim);
  4148.  
  4149.                 if (me->HasUnitState(UNIT_STATE_CASTING))
  4150.                     return;
  4151.  
  4152.                 DoMeleeAttackIfReady();
  4153.             }
  4154.         };
  4155.  
  4156.         CreatureAI* GetAI(Creature* creature) const
  4157.         {
  4158.             return new npc_dire_beastAI(creature);
  4159.         }
  4160. };
  4161.  
  4162. #define FIREBOLT   104318
  4163.  
  4164. /*######
  4165. # npc_wild_imp
  4166. ######*/
  4167.  
  4168. class npc_wild_imp : public CreatureScript
  4169. {
  4170.     public:
  4171.         npc_wild_imp() : CreatureScript("npc_wild_imp") { }
  4172.  
  4173.         struct npc_wild_impAI : public ScriptedAI
  4174.         {
  4175.             uint32 charges;
  4176.  
  4177.             npc_wild_impAI(Creature *creature) : ScriptedAI(creature)
  4178.             {
  4179.                 charges = 10;
  4180.                 me->SetReactState(REACT_HELPER);
  4181.             }
  4182.  
  4183.             void Reset()
  4184.             {
  4185.                 me->SetReactState(REACT_HELPER);
  4186.  
  4187.                 if (me->GetOwner())
  4188.                     if (me->GetOwner()->getVictim())
  4189.                         AttackStart(me->GetOwner()->getVictim());
  4190.             }
  4191.  
  4192.             void UpdateAI(const uint32 diff)
  4193.             {
  4194.                 if (me->GetReactState() != REACT_HELPER)
  4195.                     me->SetReactState(REACT_HELPER);
  4196.  
  4197.                 Unit* owner = me->GetOwner();
  4198.                 if (!owner)
  4199.                     return;
  4200.  
  4201.                 Player* pOwner = owner->ToPlayer();
  4202.                 if (!pOwner)
  4203.                     return;
  4204.  
  4205.                 if (me->HasUnitState(UNIT_STATE_CASTING))
  4206.                     return;
  4207.  
  4208.                 if (!charges)
  4209.                 {
  4210.                     me->DespawnOrUnsummon();
  4211.                     return;
  4212.                 }
  4213.  
  4214.                 if ((me->getVictim() || pOwner->getAttackerForHelper()))
  4215.                 {
  4216.                     me->CastSpell(me->getVictim() ? me->getVictim() : pOwner->getAttackerForHelper(), FIREBOLT, false);
  4217.                     pOwner->EnergizeBySpell(pOwner, FIREBOLT, 5, POWER_DEMONIC_FURY);
  4218.                     charges--;
  4219.  
  4220.                     if (pOwner->HasAura(122351) && pOwner->getLevel() >= 69)
  4221.                         if (roll_chance_i(8))
  4222.                             pOwner->CastSpell(pOwner, 122355, true);
  4223.                 }
  4224.                 else if (Pet* pet = pOwner->GetPet())
  4225.                 {
  4226.                     if (pet->getAttackerForHelper())
  4227.                     {
  4228.                         me->CastSpell(me->getVictim() ? me->getVictim() : pet->getAttackerForHelper(), FIREBOLT, false);
  4229.                         pOwner->EnergizeBySpell(pOwner, FIREBOLT, 5, POWER_DEMONIC_FURY);
  4230.                         charges--;
  4231.  
  4232.                         if (pOwner->HasAura(122351) && pOwner->getLevel() >= 69)
  4233.                             if (roll_chance_i(8))
  4234.                                 pOwner->CastSpell(pOwner, 122355, true);
  4235.                     }
  4236.                 }
  4237.             }
  4238.         };
  4239.  
  4240.         CreatureAI* GetAI(Creature* creature) const
  4241.         {
  4242.             return new npc_wild_impAI(creature);
  4243.         }
  4244. };
  4245.  
  4246. /*######
  4247. ## npc_stone_bulwark_totem
  4248. ######*/
  4249.  
  4250. #define STONE_BULWARK_TOTEM_ABSORB      114889
  4251.  
  4252. class npc_stone_bulwark_totem : public CreatureScript
  4253. {
  4254.     public:
  4255.         npc_stone_bulwark_totem() : CreatureScript("npc_stone_bulwark_totem") { }
  4256.  
  4257.     struct npc_stone_bulwark_totemAI : public ScriptedAI
  4258.     {
  4259.         npc_stone_bulwark_totemAI(Creature* creature) : ScriptedAI(creature)
  4260.         {
  4261.             creature->CastSpell(creature, STONE_BULWARK_TOTEM_ABSORB, true);
  4262.         }
  4263.  
  4264.         void UpdateAI(uint32 const diff)
  4265.         {
  4266.             if (!me->HasAura(STONE_BULWARK_TOTEM_ABSORB))
  4267.                 me->CastSpell(me, STONE_BULWARK_TOTEM_ABSORB, true);
  4268.         }
  4269.     };
  4270.  
  4271.     CreatureAI* GetAI(Creature* creature) const
  4272.     {
  4273.         return new npc_stone_bulwark_totemAI(creature);
  4274.     }
  4275. };
  4276.  
  4277. /*######
  4278. ## npc_earthgrab_totem
  4279. ######*/
  4280.  
  4281. #define EARTHGRAB       116943
  4282.  
  4283. class npc_earthgrab_totem : public CreatureScript
  4284. {
  4285.     public:
  4286.         npc_earthgrab_totem() : CreatureScript("npc_earthgrab_totem") { }
  4287.  
  4288.     struct npc_earthgrab_totemAI : public ScriptedAI
  4289.     {
  4290.         npc_earthgrab_totemAI(Creature* creature) : ScriptedAI(creature)
  4291.         {
  4292.             creature->CastSpell(creature, EARTHGRAB, true);
  4293.         }
  4294.  
  4295.         void UpdateAI(uint32 const diff)
  4296.         {
  4297.             if (!me->HasAura(EARTHGRAB))
  4298.                 me->CastSpell(me, EARTHGRAB, true);
  4299.         }
  4300.     };
  4301.  
  4302.     CreatureAI* GetAI(Creature* creature) const
  4303.     {
  4304.         return new npc_earthgrab_totemAI(creature);
  4305.     }
  4306. };
  4307.  
  4308. /*######
  4309. ## npc_windwalk_totem
  4310. ######*/
  4311.  
  4312. #define WINDWALK     114896
  4313.  
  4314. class npc_windwalk_totem : public CreatureScript
  4315. {
  4316.     public:
  4317.         npc_windwalk_totem() : CreatureScript("npc_windwalk_totem") { }
  4318.  
  4319.     struct npc_windwalk_totemAI : public ScriptedAI
  4320.     {
  4321.         npc_windwalk_totemAI(Creature* creature) : ScriptedAI(creature)
  4322.         {
  4323.             creature->CastSpell(creature, WINDWALK, true);
  4324.         }
  4325.  
  4326.         void UpdateAI(uint32 const diff)
  4327.         {
  4328.             if (!me->HasAura(WINDWALK))
  4329.                 me->CastSpell(me, WINDWALK, true);
  4330.         }
  4331.     };
  4332.  
  4333.     CreatureAI* GetAI(Creature* creature) const
  4334.     {
  4335.         return new npc_windwalk_totemAI(creature);
  4336.     }
  4337. };
  4338.  
  4339. /*######
  4340. ## npc_healing_tide_totem
  4341. ######*/
  4342.  
  4343. #define HEALING_TIDE     114941
  4344.  
  4345. class npc_healing_tide_totem : public CreatureScript
  4346. {
  4347.     public:
  4348.         npc_healing_tide_totem() : CreatureScript("npc_healing_tide_totem") { }
  4349.  
  4350.     struct npc_healing_tide_totemAI : public ScriptedAI
  4351.     {
  4352.         npc_healing_tide_totemAI(Creature* creature) : ScriptedAI(creature)
  4353.         {
  4354.             creature->CastSpell(creature, HEALING_TIDE, true);
  4355.         }
  4356.  
  4357.         void UpdateAI(uint32 const diff)
  4358.         {
  4359.             if (!me->HasAura(HEALING_TIDE))
  4360.                 me->CastSpell(me, HEALING_TIDE, true);
  4361.         }
  4362.     };
  4363.  
  4364.     CreatureAI* GetAI(Creature* creature) const
  4365.     {
  4366.         return new npc_healing_tide_totemAI(creature);
  4367.     }
  4368. };
  4369.  
  4370. /*######
  4371. ## npc_ring_of_frost
  4372. ######*/
  4373.  
  4374. class npc_ring_of_frost : public CreatureScript
  4375. {
  4376.     public:
  4377.         npc_ring_of_frost() : CreatureScript("npc_ring_of_frost") { }
  4378.  
  4379.         struct npc_ring_of_frostAI : public Scripted_NoMovementAI
  4380.         {
  4381.             npc_ring_of_frostAI(Creature *c) : Scripted_NoMovementAI(c)
  4382.             {
  4383.                 me->SetReactState(REACT_PASSIVE);
  4384.                 me->SetFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NON_ATTACKABLE);
  4385.                 me->SetFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NOT_SELECTABLE);
  4386.             }
  4387.             bool isReady;
  4388.             uint32 releaseTimer;
  4389.  
  4390.             void Reset()
  4391.             {
  4392.                 me->SetReactState(REACT_PASSIVE);
  4393.                 me->SetFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NON_ATTACKABLE);
  4394.                 me->SetFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NOT_SELECTABLE);
  4395.                 releaseTimer = 3000;
  4396.                 isReady = false;
  4397.             }
  4398.  
  4399.             void InitializeAI()
  4400.             {
  4401.                 ScriptedAI::InitializeAI();
  4402.                 Unit * owner = me->GetOwner();
  4403.                 if (!owner || owner->GetTypeId() != TYPEID_PLAYER)
  4404.                     return;
  4405.  
  4406.                 me->SetReactState(REACT_PASSIVE);
  4407.                 me->SetFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NON_ATTACKABLE);
  4408.                 me->SetFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NOT_SELECTABLE);
  4409.  
  4410.                 std::list<Creature*> templist;
  4411.                 me->GetCreatureListWithEntryInGrid(templist, me->GetEntry(), 200.0f);
  4412.                 if (!templist.empty())
  4413.                     for (std::list<Creature*>::const_iterator itr = templist.begin(); itr != templist.end(); ++itr)
  4414.                         if ((*itr)->GetOwner() == me->GetOwner() && *itr != me)
  4415.                             (*itr)->DisappearAndDie();
  4416.             }
  4417.  
  4418.             void CheckIfMoveInRing(Unit *who)
  4419.             {
  4420.                 if (who->isAlive() && me->IsInRange(who, 4.0f, 8.0f, true, false) && me->IsWithinLOSInMap(who) && isReady)
  4421.                 {
  4422.                     if (!who->HasAura(82691))
  4423.                     {
  4424.                         if (!who->HasAura(91264))
  4425.                         {
  4426.                             me->CastSpell(who, 82691, true);
  4427.                             me->CastSpell(who, 91264, true);
  4428.                         }
  4429.                     }
  4430.                     else me->CastSpell(who, 91264, true);
  4431.                 }
  4432.             }
  4433.  
  4434.             void UpdateAI(const uint32 diff)
  4435.             {
  4436.                 if (releaseTimer <= diff)
  4437.                 {
  4438.                     if (!isReady)
  4439.                     {
  4440.                         isReady = true;
  4441.                         releaseTimer = 9000; // 9sec
  4442.                     }
  4443.                     else
  4444.                         me->DisappearAndDie();
  4445.                 }
  4446.                 else releaseTimer -= diff;
  4447.  
  4448.                 // Find all the enemies
  4449.                 std::list<Unit*> targets;
  4450.                 WoWSource::AnyUnfriendlyUnitInObjectRangeCheck u_check(me, me, 5.0f);
  4451.                 WoWSource::UnitListSearcher<WoWSource::AnyUnfriendlyUnitInObjectRangeCheck> searcher(me, targets, u_check);
  4452.                 me->VisitNearbyObject(5.0f, searcher);
  4453.                 for (std::list<Unit*>::const_iterator iter = targets.begin(); iter != targets.end(); ++iter)
  4454.                     if (!(*iter)->isTotem())
  4455.                         CheckIfMoveInRing(*iter);
  4456.             }
  4457.         };
  4458.  
  4459.         CreatureAI* GetAI(Creature* pCreature) const
  4460.         {
  4461.             return new npc_ring_of_frostAI(pCreature);
  4462.         }
  4463. };
  4464.  
  4465. /*######
  4466. # npc_wild_mushroom
  4467. ######*/
  4468.  
  4469. #define WILD_MUSHROOM_INVISIBILITY   92661
  4470.  
  4471. class npc_wild_mushroom : public CreatureScript
  4472. {
  4473.     public:
  4474.         npc_wild_mushroom() : CreatureScript("npc_wild_mushroom") { }
  4475.  
  4476.         struct npc_wild_mushroomAI : public ScriptedAI
  4477.         {
  4478.             uint32 CastTimer;
  4479.             bool stealthed;
  4480.  
  4481.             npc_wild_mushroomAI(Creature *creature) : ScriptedAI(creature)
  4482.             {
  4483.                 CastTimer = 6000;
  4484.                 stealthed = false;
  4485.                 me->SetReactState(REACT_PASSIVE);
  4486.             }
  4487.  
  4488.             void UpdateAI(const uint32 diff)
  4489.             {
  4490.                 if (CastTimer <= diff && !stealthed)
  4491.                 {
  4492.                     DoCast(me, WILD_MUSHROOM_INVISIBILITY, true);
  4493.                     stealthed = true;
  4494.                 }
  4495.                 else
  4496.                 {
  4497.                     CastTimer -= diff;
  4498.  
  4499.                     if (!stealthed)
  4500.                         me->RemoveAura(WILD_MUSHROOM_INVISIBILITY);
  4501.                 }
  4502.             }
  4503.         };
  4504.  
  4505.         CreatureAI* GetAI(Creature* creature) const
  4506.         {
  4507.             return new npc_wild_mushroomAI(creature);
  4508.         }
  4509. };
  4510.  
  4511. /*######
  4512. ## npc_fungal_growth
  4513. ######*/
  4514.  
  4515. #define FUNGAL_GROWTH_PERIODIC  81282
  4516. #define FUNGAL_GROWTH_AREA      94339
  4517.  
  4518. class npc_fungal_growth : public CreatureScript
  4519. {
  4520.     public:
  4521.         npc_fungal_growth() : CreatureScript("npc_fungal_growth") { }
  4522.  
  4523.         struct npc_fungal_growthAI : public Scripted_NoMovementAI
  4524.         {
  4525.             npc_fungal_growthAI(Creature *c) : Scripted_NoMovementAI(c)
  4526.             {
  4527.                 me->SetReactState(REACT_PASSIVE);
  4528.                 me->SetFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NON_ATTACKABLE);
  4529.                 me->SetFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NOT_SELECTABLE);
  4530.             }
  4531.  
  4532.             void Reset()
  4533.             {
  4534.                 me->SetReactState(REACT_PASSIVE);
  4535.                 me->SetFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NON_ATTACKABLE);
  4536.                 me->SetFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NOT_SELECTABLE);
  4537.             }
  4538.  
  4539.             void InitializeAI()
  4540.             {
  4541.                 ScriptedAI::InitializeAI();
  4542.                 Unit * owner = me->GetOwner();
  4543.                 if (!owner || owner->GetTypeId() != TYPEID_PLAYER)
  4544.                     return;
  4545.  
  4546.                 me->SetReactState(REACT_PASSIVE);
  4547.                 me->SetFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NON_ATTACKABLE);
  4548.                 me->SetFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NOT_SELECTABLE);
  4549.  
  4550.                 me->CastSpell(me, FUNGAL_GROWTH_PERIODIC, true);    // Periodic Trigger spell : decrease speed
  4551.                 me->CastSpell(me, FUNGAL_GROWTH_AREA, true);        // Persistent Area
  4552.             }
  4553.  
  4554.             void UpdateAI(const uint32 diff)
  4555.             {
  4556.                 if (!me->HasAura(FUNGAL_GROWTH_PERIODIC))
  4557.                     me->CastSpell(me, FUNGAL_GROWTH_PERIODIC, true);
  4558.             }
  4559.         };
  4560.  
  4561.         CreatureAI* GetAI(Creature* pCreature) const
  4562.         {
  4563.             return new npc_fungal_growthAI(pCreature);
  4564.         }
  4565. };
  4566.  
  4567. /*######
  4568. ## npc_bloodworm
  4569. ######*/
  4570.  
  4571. #define BLOODWORM_BLOOD_GORGED  50453
  4572. #define BLOODWORM_BLOOD_STACKS  81277
  4573. #define BLOODWORM_BLOOD_BURST   81280
  4574.  
  4575. class npc_bloodworm : public CreatureScript
  4576. {
  4577.     public:
  4578.         npc_bloodworm() : CreatureScript("npc_bloodworm") { }
  4579.  
  4580.         struct npc_bloodwormAI : public ScriptedAI
  4581.         {
  4582.             npc_bloodwormAI(Creature* c) : ScriptedAI(c)
  4583.             {
  4584.             }
  4585.  
  4586.             uint32 uiBurstTimer;
  4587.             uint32 uiCheckBloodChargesTimer;
  4588.  
  4589.             void Burst()
  4590.             {
  4591.                 if (AuraPtr bloodGorged = me->GetAura(BLOODWORM_BLOOD_STACKS))
  4592.                 {
  4593.                     uint32 stacks = std::min<uint32>(bloodGorged->GetStackAmount(), 10);
  4594.                     int32 damage = stacks *  10;
  4595.                     me->CastCustomSpell(me, BLOODWORM_BLOOD_BURST, &damage, NULL, NULL, true);
  4596.                     me->DespawnOrUnsummon(500);
  4597.                 }
  4598.             }
  4599.  
  4600.             void JustDied(Unit* killer)
  4601.             {
  4602.                 Burst();
  4603.             }
  4604.  
  4605.             void Reset()
  4606.             {
  4607.                 DoCast(me, BLOODWORM_BLOOD_GORGED, true);
  4608.  
  4609.                 uiBurstTimer = 19000;
  4610.                 uiCheckBloodChargesTimer = 1500;
  4611.             }
  4612.  
  4613.             void UpdateAI(const uint32 diff)
  4614.             {
  4615.                 if (uiBurstTimer <= diff)
  4616.                     Burst();
  4617.                 else
  4618.                     uiBurstTimer -= diff;
  4619.  
  4620.                 if (uiCheckBloodChargesTimer <= diff)
  4621.                 {
  4622.                     if (me->GetOwner())
  4623.                     {
  4624.                         if (AuraPtr bloodGorged = me->GetAura(BLOODWORM_BLOOD_STACKS))
  4625.                         {
  4626.                             // 10% per stack
  4627.                             int32 stacks = bloodGorged->GetStackAmount() * 10;
  4628.                             int32 masterPct = int32(100.0f - me->GetOwner()->GetHealthPct());
  4629.                             AddPct(stacks, masterPct);
  4630.  
  4631.                             if (stacks > 100)
  4632.                                 stacks = 100;
  4633.  
  4634.                             if (roll_chance_i(stacks))
  4635.                                 Burst();
  4636.                             else
  4637.                                 uiCheckBloodChargesTimer = 1500;
  4638.                         }
  4639.                     }
  4640.                 }
  4641.                 else
  4642.                     uiCheckBloodChargesTimer -= diff;
  4643.  
  4644.                 if (!UpdateVictim())
  4645.                 {
  4646.                     if (Unit* target = me->SelectVictim())
  4647.                         me->Attack(target, true);
  4648.                     return;
  4649.                 }
  4650.  
  4651.                 DoMeleeAttackIfReady();
  4652.             }
  4653.         };
  4654.  
  4655.         CreatureAI* GetAI(Creature *creature) const
  4656.         {
  4657.             return new npc_bloodwormAI(creature);
  4658.         }
  4659. };
  4660.  
  4661. /*######
  4662. ## npc_past_self
  4663. ######*/
  4664.  
  4665. enum PastSelfSpells
  4666. {
  4667.     SPELL_FADING                    = 107550,
  4668.     SPELL_ALTER_TIME                = 110909,
  4669.     SPELL_ENCHANTED_REFLECTION      = 102284,
  4670.     SPELL_ENCHANTED_REFLECTION_2    = 102288,
  4671. };
  4672.  
  4673. struct auraData
  4674. {
  4675.     auraData(uint32 id, int32 duration) : m_id(id), m_duration(duration) {}
  4676.     uint32 m_id;
  4677.     int32 m_duration;
  4678. };
  4679.  
  4680. #define ACTION_ALTER_TIME   1
  4681.  
  4682. class npc_past_self : public CreatureScript
  4683. {
  4684.     public:
  4685.         npc_past_self() : CreatureScript("npc_past_self") { }
  4686.  
  4687.         struct npc_past_selfAI : public Scripted_NoMovementAI
  4688.         {
  4689.             npc_past_selfAI(Creature* c) : Scripted_NoMovementAI(c)
  4690.             {
  4691.                 me->SetFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NOT_SELECTABLE | UNIT_FLAG_NON_ATTACKABLE);
  4692.                 me->SetReactState(REACT_PASSIVE);
  4693.                 me->SetMaxHealth(500);
  4694.                 me->SetHealth(me->GetMaxHealth());
  4695.                 mana = 0;
  4696.                 health = 0;
  4697.                 auras.clear();
  4698.             }
  4699.  
  4700.             int32 mana;
  4701.             int32 health;
  4702.             std::set<auraData*> auras;
  4703.  
  4704.             void Reset()
  4705.             {
  4706.                 if (!me->HasAura(SPELL_FADING))
  4707.                     me->AddAura(SPELL_FADING, me);
  4708.             }
  4709.  
  4710.             void IsSummonedBy(Unit* owner)
  4711.             {
  4712.                 if (owner && owner->GetTypeId() == TYPEID_PLAYER)
  4713.                 {
  4714.                     Unit::AuraApplicationMap const& appliedAuras = owner->GetAppliedAuras();
  4715.                     for (Unit::AuraApplicationMap::const_iterator itr = appliedAuras.begin(); itr != appliedAuras.end(); ++itr)
  4716.                     {
  4717.                         if (AuraPtr aura = itr->second->GetBase())
  4718.                         {
  4719.                             SpellInfo const* auraInfo = aura->GetSpellInfo();
  4720.                             if (!auraInfo)
  4721.                                 continue;
  4722.  
  4723.                             if (auraInfo->Id == SPELL_ALTER_TIME)
  4724.                                 continue;
  4725.  
  4726.                             if (auraInfo->IsPassive())
  4727.                                 continue;
  4728.  
  4729.                             if (auraInfo->Id == 23333 || auraInfo->Id == 23335)
  4730.                                 continue;
  4731.  
  4732.                             auras.insert(new auraData(auraInfo->Id, aura->GetDuration()));
  4733.                         }
  4734.                     }
  4735.  
  4736.                     mana = owner->GetPower(POWER_MANA);
  4737.                     health = owner->GetHealth();
  4738.  
  4739.                     owner->AddAura(SPELL_ENCHANTED_REFLECTION, me);
  4740.                     owner->AddAura(SPELL_ENCHANTED_REFLECTION_2, me);
  4741.                 }
  4742.                 else
  4743.                     me->DespawnOrUnsummon();
  4744.             }
  4745.  
  4746.             void DoAction(const int32 action)
  4747.             {
  4748.                 if (action == ACTION_ALTER_TIME)
  4749.                 {
  4750.                     if (TempSummon* pastSelf = me->ToTempSummon())
  4751.                     {
  4752.                         if (Unit* m_owner = pastSelf->GetSummoner())
  4753.                         {
  4754.                             if (m_owner->ToPlayer())
  4755.                             {
  4756.                                 if (!m_owner->isAlive())
  4757.                                     return;
  4758.  
  4759.                                 m_owner->RemoveNonPassivesAuras();
  4760.  
  4761.                                 for (std::set<auraData*>::iterator itr = auras.begin(); itr != auras.end(); ++itr)
  4762.                                 {
  4763.                                     AuraPtr aura = !m_owner->HasAura((*itr)->m_id) ? m_owner->AddAura((*itr)->m_id, m_owner) : m_owner->GetAura((*itr)->m_id);
  4764.                                     if (aura)
  4765.                                     {
  4766.                                         aura->SetDuration((*itr)->m_duration);
  4767.                                         aura->SetNeedClientUpdateForTargets();
  4768.                                     }
  4769.  
  4770.                                     delete (*itr);
  4771.                                 }
  4772.  
  4773.                                 auras.clear();
  4774.  
  4775.                                 m_owner->SetPower(POWER_MANA, mana);
  4776.                                 m_owner->SetHealth(health);
  4777.  
  4778.                                 m_owner->NearTeleportTo(me->GetPositionX(), me->GetPositionY(), me->GetPositionZ(), me->GetOrientation(), true);
  4779.                                 me->DespawnOrUnsummon(100);
  4780.                             }
  4781.                         }
  4782.                     }
  4783.                 }
  4784.             }
  4785.         };
  4786.  
  4787.         CreatureAI* GetAI(Creature *creature) const
  4788.         {
  4789.             return new npc_past_selfAI(creature);
  4790.         }
  4791. };
  4792.  
  4793.  
  4794. /*######
  4795. ## npc_void_tendrils -- 65282
  4796. ######*/
  4797.  
  4798. enum voidTendrilsSpells
  4799. {
  4800.     SPELL_VOID_TENDRILS_ROOT = 108920,
  4801.     SPELL_ROOT_FOR_EVER      = 31366,
  4802. };
  4803.  
  4804. class npc_void_tendrils : public CreatureScript
  4805. {
  4806.     public:
  4807.         npc_void_tendrils() : CreatureScript("npc_void_tendrils") { }
  4808.  
  4809.         struct npc_void_tendrilsAI : public Scripted_NoMovementAI
  4810.         {
  4811.             npc_void_tendrilsAI(Creature* c) : Scripted_NoMovementAI(c)
  4812.             {
  4813.                 me->SetReactState(REACT_AGGRESSIVE);
  4814.                 targetGUID = 0;
  4815.             }
  4816.  
  4817.             uint64 targetGUID;
  4818.  
  4819.             void Reset()
  4820.             {
  4821.                 if (!me->HasAura(SPELL_ROOT_FOR_EVER))
  4822.                     me->AddAura(SPELL_ROOT_FOR_EVER, me);
  4823.             }
  4824.  
  4825.             void SetGUID(uint64 guid, int32)
  4826.             {
  4827.                 targetGUID = guid;
  4828.  
  4829.                 me->setFaction(14);
  4830.             }
  4831.  
  4832.             void JustDied(Unit* killer)
  4833.             {
  4834.                 if (Unit* m_target = ObjectAccessor::FindUnit(targetGUID))
  4835.                     m_target->RemoveAura(SPELL_VOID_TENDRILS_ROOT);
  4836.             }
  4837.  
  4838.             void IsSummonedBy(Unit* owner)
  4839.             {
  4840.                 if (owner && owner->GetTypeId() == TYPEID_PLAYER)
  4841.                 {
  4842.                     me->SetLevel(owner->getLevel());
  4843.                     me->SetMaxHealth(CalculatePct(owner->GetMaxHealth(), 2.5f));
  4844.                     me->SetHealth(me->GetMaxHealth());
  4845.                     // Set no damage
  4846.                     me->SetBaseWeaponDamage(BASE_ATTACK, MINDAMAGE, 0.0f);
  4847.                     me->SetBaseWeaponDamage(BASE_ATTACK, MAXDAMAGE, 0.0f);
  4848.  
  4849.                     me->AddAura(SPELL_ROOT_FOR_EVER, me);
  4850.                 }
  4851.                 else
  4852.                     me->DespawnOrUnsummon();
  4853.             }
  4854.  
  4855.             void UpdateAI(uint32 const diff)
  4856.             {
  4857.                 if (!(ObjectAccessor::FindUnit(targetGUID)))
  4858.                     me->DespawnOrUnsummon();
  4859.             }
  4860.         };
  4861.  
  4862.         CreatureAI* GetAI(Creature *creature) const
  4863.         {
  4864.             return new npc_void_tendrilsAI(creature);
  4865.         }
  4866. };
  4867.  
  4868. /*######
  4869. ## npc_psyfiend -- 59190
  4870. ######*/
  4871.  
  4872. enum PsyfiendSpells
  4873. {
  4874.     SPELL_PSYCHIC_HORROR = 113792,
  4875.     PSYCHIC_TERROR_TIMER = 2000
  4876. };
  4877.  
  4878. class npc_psyfiend : public CreatureScript {
  4879. public:
  4880.     npc_psyfiend() : CreatureScript("npc_psyfiend") { }
  4881.  
  4882.     class npc_psyfiend_ScriptedAI : public ScriptedAI
  4883.     {
  4884.     public:
  4885.         npc_psyfiend_ScriptedAI(Creature *creature) : ScriptedAI(creature)
  4886.         {
  4887.             _uiPsychicTerrorTimer = PSYCHIC_TERROR_TIMER;
  4888.             creature->SetFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_DISABLE_MOVE);
  4889.         }
  4890.  
  4891.         void UpdateAI(uint32 const diff)
  4892.         {
  4893.             Unit* owner = me->GetOwner();
  4894.             if (!owner || !owner->isAlive())
  4895.             {
  4896.                 me->DisappearAndDie();
  4897.                 return;
  4898.             }
  4899.  
  4900.             if (_uiPsychicTerrorTimer <= diff)
  4901.             {
  4902.                 DoCastAOE(SPELL_PSYCHIC_HORROR);
  4903.                 _uiPsychicTerrorTimer = PSYCHIC_TERROR_TIMER;
  4904.             }
  4905.             else
  4906.                 _uiPsychicTerrorTimer -= diff;
  4907.         }
  4908.  
  4909.     private:
  4910.         ///< Timer before next Psychic Terror cast
  4911.         uint32 _uiPsychicTerrorTimer;
  4912.     };
  4913.  
  4914.     CreatureAI *GetAI(Creature *creature) const
  4915.     {
  4916.         return new npc_psyfiend_ScriptedAI(creature);
  4917.     }
  4918. };
  4919.  
  4920.  
  4921. /*######
  4922. ## npc_spectral_guise -- 59607
  4923. ######*/
  4924.  
  4925. enum spectralGuiseSpells
  4926. {
  4927.     SPELL_SPECTRAL_GUISE_CLONE      = 119012,
  4928.     SPELL_SPECTRAL_GUISE_CHARGES    = 119030,
  4929.     SPELL_SPECTRAL_GUISE_STEALTH    = 119032,
  4930.     SPELL_INITIALIZE_IMAGES         = 102284,
  4931. };
  4932.  
  4933. class npc_spectral_guise : public CreatureScript
  4934. {
  4935.     public:
  4936.         npc_spectral_guise() : CreatureScript("npc_spectral_guise") { }
  4937.  
  4938.         struct npc_spectral_guiseAI : public Scripted_NoMovementAI
  4939.         {
  4940.             npc_spectral_guiseAI(Creature* c) : Scripted_NoMovementAI(c)
  4941.             {
  4942.                 me->SetReactState(REACT_PASSIVE);
  4943.             }
  4944.  
  4945.             void Reset()
  4946.             {
  4947.                 if (!me->HasAura(SPELL_ROOT_FOR_EVER))
  4948.                     me->AddAura(SPELL_ROOT_FOR_EVER, me);
  4949.             }
  4950.  
  4951.             void IsSummonedBy(Unit* owner)
  4952.             {
  4953.                 if (owner && owner->GetTypeId() == TYPEID_PLAYER)
  4954.                 {
  4955.                     me->SetLevel(owner->getLevel());
  4956.                     me->SetMaxHealth(owner->GetMaxHealth() / 2);
  4957.                     me->SetHealth(me->GetMaxHealth());
  4958.  
  4959.                     owner->AddAura(SPELL_INITIALIZE_IMAGES, me);
  4960.                     owner->AddAura(SPELL_SPECTRAL_GUISE_CLONE, me);
  4961.  
  4962.                     me->CastSpell(me, SPELL_SPECTRAL_GUISE_CHARGES, true);
  4963.                     Aura::TryRefreshStackOrCreate(sSpellMgr->GetSpellInfo(SPELL_SPECTRAL_GUISE_STEALTH), MAX_EFFECT_MASK, owner, owner, sSpellMgr->GetSpellInfo(SPELL_SPECTRAL_GUISE_STEALTH)->spellPower);
  4964.  
  4965.                     std::list<HostileReference*> threatList = owner->getThreatManager().getThreatList();
  4966.                     for (std::list<HostileReference*>::const_iterator itr = threatList.begin(); itr != threatList.end(); ++itr)
  4967.                         if (Unit* unit = (*itr)->getTarget())
  4968.                             if (unit->GetTypeId() == TYPEID_UNIT)
  4969.                                 if (Creature* creature = unit->ToCreature())
  4970.                                     if (creature->canStartAttack(me, false))
  4971.                                         creature->Attack(me, true);
  4972.  
  4973.                     // Set no damage
  4974.                     me->SetBaseWeaponDamage(BASE_ATTACK, MINDAMAGE, 0.0f);
  4975.                     me->SetBaseWeaponDamage(BASE_ATTACK, MAXDAMAGE, 0.0f);
  4976.  
  4977.                     me->AddAura(SPELL_ROOT_FOR_EVER, me);
  4978.                 }
  4979.                 else
  4980.                     me->DespawnOrUnsummon();
  4981.             }
  4982.         };
  4983.  
  4984.         CreatureAI* GetAI(Creature *creature) const
  4985.         {
  4986.             return new npc_spectral_guiseAI(creature);
  4987.         }
  4988. };
  4989.  
  4990. // Winter Weil - Metzen
  4991. enum GossipMenuMetzen
  4992. {
  4993.     SPELL_REINDEER_DUST_EFFECT  = 25952,
  4994.     GOSSIP_METZEN               = 15664
  4995. };
  4996.  
  4997. class npc_metzen : public CreatureScript
  4998. {
  4999.     public:
  5000.         npc_metzen() : CreatureScript("npc_metzen") { }
  5001.  
  5002.     bool OnGossipHello(Player* player, Creature* creature)
  5003.     {
  5004.         uint32 questid_metz;
  5005.        
  5006.         if (player->getRaceMask() & RACEMASK_ALLIANCE)
  5007.             questid_metz = 8762;
  5008.         else
  5009.             questid_metz = 8746;
  5010.  
  5011.         if (player->GetQuestStatus(questid_metz) == QUEST_STATUS_INCOMPLETE && !creature->HasUnitState(UNIT_STATE_CASTING))
  5012.             player->ADD_GOSSIP_ITEM(GOSSIP_ICON_CHAT, "Sprinkle the fairy dust", GOSSIP_SENDER_MAIN, GOSSIP_ACTION_INFO_DEF + 1);
  5013.  
  5014.         player->PlayerTalkClass->SendGossipMenu(GOSSIP_METZEN, creature->GetGUID());
  5015.         return true;
  5016.     }
  5017.  
  5018.     bool OnGossipSelect(Player* player, Creature* creature, uint32 /*uiSender*/, uint32 uiAction)
  5019.     {
  5020.         player->PlayerTalkClass->ClearMenus();
  5021.  
  5022.         switch (uiAction)
  5023.         {
  5024.             case GOSSIP_ACTION_INFO_DEF + 1:
  5025.             {
  5026.                 player->KilledMonsterCredit(creature->GetEntry(), creature->GetGUID());
  5027.                 creature->CastSpell(creature, SPELL_REINDEER_DUST_EFFECT, false);
  5028.             }
  5029.             break;
  5030.         }
  5031.  
  5032.         player->PlayerTalkClass->SendCloseGossip();
  5033.         return true;
  5034.     }
  5035. };
  5036.  
  5037. class npc_moonwell_chalice : public CreatureScript
  5038. {
  5039.     public:
  5040.         npc_moonwell_chalice() : CreatureScript("npc_moonwell_chalice") {}
  5041.  
  5042.         CreatureAI *GetAI(Creature *creature) const
  5043.         {
  5044.             return new npc_moonwell_chaliceAI(creature);
  5045.         }
  5046.  
  5047.         struct npc_moonwell_chaliceAI : public Scripted_NoMovementAI
  5048.         {
  5049.             npc_moonwell_chaliceAI(Creature *c) : Scripted_NoMovementAI(c)
  5050.             {
  5051.                 me->SetReactState(REACT_PASSIVE);
  5052.                 uiTimer = 500;
  5053.                 bReady = false;
  5054.                 owner = NULL;
  5055.             }
  5056.  
  5057.             uint32 uiTimer;
  5058.             bool bReady;
  5059.             Unit* owner;
  5060.  
  5061.             void IsSummonedBy(Unit* who)
  5062.             {
  5063.                 if (who)
  5064.                     owner = who;
  5065.             }
  5066.  
  5067.             void UpdateAI(const uint32 diff)
  5068.             {
  5069.                 if (!bReady)
  5070.                 {
  5071.                     if (uiTimer <= diff)
  5072.                     {
  5073.                         bReady = true;
  5074.                         if (owner)
  5075.                             DoCast(owner, 100403);
  5076.                     }
  5077.                     else
  5078.                         uiTimer -= diff;
  5079.                 }
  5080.             }
  5081.         };
  5082. };
  5083.  
  5084. /*######
  5085. # npc_shadowfiend
  5086. ######*/
  5087. #define GLYPH_OF_SHADOWFIEND_MANA         58227
  5088. #define GLYPH_OF_SHADOWFIEND              58228
  5089.  
  5090. class npc_shadowfiend : public CreatureScript
  5091. {
  5092.     public:
  5093.         npc_shadowfiend() : CreatureScript("npc_shadowfiend") { }
  5094.  
  5095.         struct npc_shadowfiendAI : public PetAI
  5096.         {
  5097.             npc_shadowfiendAI(Creature* creature) : PetAI(creature) {}
  5098.  
  5099.             void IsSummonedBy(Unit* owner)
  5100.             {
  5101.                 me->SetReactState(REACT_AGGRESSIVE);
  5102.                 Unit* target = NULL;
  5103.                 if (owner->GetTypeId() == TYPEID_PLAYER)
  5104.                     target = owner->ToPlayer()->GetSelectedUnit();
  5105.                 else
  5106.                     target = owner->getVictim();
  5107.  
  5108.                 if (target && me->IsValidAttackTarget(target))
  5109.                     AttackStart(target);                
  5110.             }
  5111.  
  5112.             void JustDied(Unit* /*killer*/)
  5113.             {
  5114.                 if (me->isSummon())
  5115.                     if (Unit* owner = me->ToTempSummon()->GetSummoner())
  5116.                         if (owner->HasAura(GLYPH_OF_SHADOWFIEND))
  5117.                             owner->CastSpell(owner, GLYPH_OF_SHADOWFIEND_MANA, true);
  5118.             }
  5119.         };
  5120.  
  5121.         CreatureAI* GetAI(Creature* creature) const
  5122.         {
  5123.             return new npc_shadowfiendAI(creature);
  5124.         }
  5125. };
  5126.  
  5127. enum CustomCasterGuardian
  5128. {
  5129.     NPC_DOOM_GUARD      = 11859,
  5130.     NPC_BURNING_TREANT  = 53432,
  5131.     NPC_FIERY_IMP       = 53491,
  5132.  
  5133.     SPELL_DOOM_BOLT     = 85692,
  5134.     SPELL_FIRESEED      = 99026,
  5135.     SPELL_FLAME_BLAST   = 99226,
  5136.  
  5137.     SPELL_DOOM          = 603,
  5138.     SPELL_AGONY         = 980,
  5139.  
  5140.     EVENT_CAST_SPELL    = 1,
  5141. };
  5142.  
  5143. class npc_custom_caster_guard : public CreatureScript
  5144. {
  5145.     public:
  5146.         npc_custom_caster_guard() : CreatureScript("npc_custom_caster_guard") { }
  5147.  
  5148.         CreatureAI* GetAI(Creature* creature) const
  5149.         {
  5150.             return new npc_custom_caster_guardAI(creature);
  5151.         }
  5152.  
  5153.         struct npc_custom_caster_guardAI : CasterAI
  5154.         {
  5155.             npc_custom_caster_guardAI(Creature* creature) : CasterAI(creature)
  5156.             {
  5157.                 curTarget = NULL;
  5158.                 switch (me->GetEntry())
  5159.                 {
  5160.                     case NPC_DOOM_GUARD: // Doom Guard
  5161.                         spellId = SPELL_DOOM_BOLT;
  5162.                         maxRange = 30.0f;
  5163.                         castTime = 3000;
  5164.                         break;
  5165.                     case NPC_BURNING_TREANT: // Burning Treant
  5166.                         spellId = SPELL_DOOM_BOLT;
  5167.                         maxRange = 40.0f;
  5168.                         castTime = 2000;
  5169.                         break;
  5170.                     case NPC_FIERY_IMP:
  5171.                         spellId = SPELL_FLAME_BLAST;
  5172.                         maxRange = 40.0f;
  5173.                         castTime = 1500;
  5174.                         break;
  5175.                     default:
  5176.                         spellId = 0;
  5177.                         maxRange = 0.0f;
  5178.                         castTime = 0;
  5179.                         break;
  5180.                 }
  5181.             }
  5182.  
  5183.             void EnterCombat(Unit* who)
  5184.             {
  5185.                 if (spellId)
  5186.                     events.ScheduleEvent(EVENT_CAST_SPELL, 1);
  5187.             }
  5188.  
  5189.             void OwnerSpellHit(Unit* target, SpellInfo const* spell)
  5190.             {
  5191.                 if (me->GetEntry() == NPC_DOOM_GUARD)
  5192.                     if (spell->Id == SPELL_DOOM || spell->Id == SPELL_AGONY)
  5193.                         if (target && me->getVictim() != target)
  5194.                             AttackStart(target);
  5195.             }
  5196.  
  5197.             void UpdateAI(const uint32 diff)
  5198.             {
  5199.                 if (!UpdateVictim())
  5200.                     return;
  5201.  
  5202.                 events.Update(diff);
  5203.  
  5204.                 if (Unit * victim = me->getVictim())
  5205.                 {
  5206.                     if (victim->HasCrowdControlAura(me))
  5207.                     {
  5208.                         me->InterruptNonMeleeSpells(false);
  5209.                         return;
  5210.                     }
  5211.                 }
  5212.  
  5213.                 if (me->HasUnitState(UNIT_STATE_CASTING))
  5214.                     return;
  5215.  
  5216.                 if (curTarget && curTarget->IsInWorld() && (me->getVictim() != curTarget))
  5217.                     AttackStart(curTarget);
  5218.  
  5219.                 if (uint32 event_id = events.ExecuteEvent())
  5220.                 {
  5221.                     if (me->GetEntry() == NPC_DOOM_GUARD)
  5222.                     {
  5223.                         UnitList targets;
  5224.                         DebuffCheck u_check(me, me->GetOwnerGUID());
  5225.                        
  5226.                         WoWSource::UnitListSearcher<DebuffCheck> searcher(me, targets, u_check);
  5227.                         me->VisitNearbyObject(100.0f, searcher);
  5228.                         if (!targets.empty())
  5229.                         {
  5230.                             if (targets.size() > 1)
  5231.                             {
  5232.                                 targets.sort(WoWSource::DistanceOrderPred(me));
  5233.                                 WoWSource::Containers::RandomResizeList(targets, 1);
  5234.                             }
  5235.                             Unit* newTarget = *(targets.begin());
  5236.                             if (me->getVictim() != newTarget)
  5237.                                 AttackStart(newTarget);
  5238.                         }
  5239.                         else
  5240.                         {
  5241.                             if (Unit* owner = me->GetOwner())
  5242.                                 if (Unit* newTarget = owner->getVictim())
  5243.                                     if (newTarget != owner->getVictim())
  5244.                                         AttackStart(newTarget);
  5245.                         }
  5246.                     }
  5247.                     else
  5248.                     {
  5249.                         if (Unit* owner = me->GetOwner())
  5250.                             if (Unit* newTarget = owner->getVictim())
  5251.                                 if (newTarget != owner->getVictim())
  5252.                                     AttackStart(newTarget);
  5253.                     }
  5254.  
  5255.                     float normalRange = maxRange / 1.2f;
  5256.  
  5257.                     if (Unit* victim = me->getVictim())
  5258.                     {
  5259.                         if (maxRange && !me->IsWithinDistInMap(victim, maxRange))
  5260.                             me->GetMotionMaster()->MoveChase(victim, normalRange);
  5261.  
  5262.                         if (maxRange && !me->IsWithinLOSInMap(victim))
  5263.                             me->GetMotionMaster()->MoveChase(victim, MELEE_RANGE);
  5264.                     }
  5265.  
  5266.                     DoCastVictim(spellId);
  5267.                     events.ScheduleEvent(EVENT_CAST_SPELL, castTime);
  5268.                 }
  5269.             }
  5270.         private:
  5271.             Unit* curTarget;
  5272.             uint32 spellId;
  5273.             float maxRange;
  5274.             uint32 castTime;
  5275.  
  5276.             class DebuffCheck
  5277.             {
  5278.                 public:
  5279.                     DebuffCheck(WorldObject const* obj, uint64 casterGuid) : i_obj(obj), i_casterGuid(casterGuid) {}
  5280.                    
  5281.                     bool operator()(Unit* u)
  5282.                     {
  5283.                         if (!u->isAlive())
  5284.                             return false;
  5285.  
  5286.                         if (!i_obj->IsWithinDistInMap(u, 100.0f))
  5287.                             return false;
  5288.  
  5289.                         if (!u->HasAura(SPELL_DOOM, i_casterGuid) && !u->HasAura(SPELL_AGONY, i_casterGuid))
  5290.                             return false;
  5291.  
  5292.                         return true;
  5293.                     }
  5294.                 private:
  5295.                     WorldObject const* i_obj;
  5296.                     uint64 i_casterGuid;
  5297.             };
  5298.         };
  5299. };
  5300.  
  5301. /*######
  5302. ## npc_force_of_nature
  5303. ######*/
  5304.  
  5305. class npc_force_of_nature : public CreatureScript
  5306. {
  5307.     public:
  5308.         npc_force_of_nature() : CreatureScript("npc_force_of_nature") { }
  5309.  
  5310.         struct npc_force_of_natureAI : public ScriptedAI
  5311.         {
  5312.             uint64 own;
  5313.             uint64 tar;
  5314.             bool init;
  5315.             bool rakeCast;
  5316.  
  5317.         npc_force_of_natureAI(Creature* pCreature) : ScriptedAI(pCreature)
  5318.         {
  5319.             init = false;
  5320.             own = 0;
  5321.             tar = 0;
  5322.             rakeCast = false;
  5323.         }
  5324.  
  5325.         void InitializeAI()
  5326.         {
  5327.             init = true;
  5328.             Unit* owner;
  5329.  
  5330.             if (TempSummon* temp = me->ToTempSummon())
  5331.                 owner = temp->GetSummoner();
  5332.  
  5333.             if (owner == NULL)
  5334.                 return;
  5335.  
  5336.             Player* player = owner->ToPlayer();
  5337.  
  5338.             if (player == NULL)
  5339.                 return;
  5340.  
  5341.             own = player->GetGUID();
  5342.  
  5343.             if (Unit* target = player->GetSelectedUnit())
  5344.             {
  5345.                 tar = target->GetGUID();
  5346.                 CastStartSpell(owner, target);
  5347.             }
  5348.         }
  5349.  
  5350.         void CastStartSpell(Unit* o, Unit* t)
  5351.         {
  5352.             if (me->GetEntry() == ENTRY_TREANT_RESTO)
  5353.             {
  5354.                 me->CastSpell(t->IsFriendlyTo(o) ? t : o, 142423, true);
  5355.                 return;
  5356.             }
  5357.             else if (t->IsFriendlyTo(o))
  5358.                 return;
  5359.  
  5360.             switch (me->GetEntry())
  5361.             {
  5362.                 case ENTRY_TREANT_GUARDIAN:
  5363.                     me->CastSpell(t, 113830, true); // Taunt
  5364.                     break;
  5365.                 case ENTRY_TREANT_FERAL:
  5366.                 case ENTRY_TREANT_BALANCE:
  5367.                     me->CastSpell(t, 113770, true); // Root
  5368.                     // on creatures 30seconds
  5369.                     if (t->GetTypeId() !=TYPEID_PLAYER)
  5370.                         if (AuraPtr root = t->GetAura(113770, me->GetGUID()))
  5371.                             root->SetDuration(30000);
  5372.                     break;
  5373.                 default:
  5374.                     break;
  5375.             }
  5376.  
  5377.             AttackStart(t);
  5378.         }
  5379.  
  5380.         void Reset() {}
  5381.  
  5382.         bool UpdateTarget()
  5383.         {
  5384.             if (!(me->getVictim()) && me->GetEntry() != ENTRY_TREANT_RESTO)
  5385.             {
  5386.                 Player* owner = Unit::GetPlayer((*me), own);
  5387.                 if (owner)
  5388.                 {
  5389.                     if (Unit* target = owner->getAttackerForHelper())
  5390.                     {
  5391.                         tar = target->GetGUID();
  5392.                         me->SetTarget(tar);
  5393.                         me->SetInCombatWith(target);
  5394.                         AttackStart(target);
  5395.                     }
  5396.                     else
  5397.                         return false;
  5398.                 }
  5399.                 else
  5400.                 {
  5401.                     own = 0;
  5402.                     return false;
  5403.                 }
  5404.             }
  5405.  
  5406.             return true;
  5407.         }
  5408.  
  5409.         void UpdateAI(const uint32 diff)
  5410.         {
  5411.             if (!init)
  5412.                 InitializeAI();
  5413.  
  5414.             if (!own)
  5415.                 return;
  5416.  
  5417.             if (me->IsNonMeleeSpellCasted(false))
  5418.                 return;
  5419.  
  5420.             if (!UpdateTarget())
  5421.                 return;
  5422.  
  5423.             switch (me->GetEntry())
  5424.             {        
  5425.                 case ENTRY_TREANT_RESTO:
  5426.                     me->CastSpell(me, 113828);
  5427.                     return;
  5428.                 case ENTRY_TREANT_BALANCE:
  5429.                     if (Unit* target = Unit::GetUnit((*me), tar))
  5430.                         me->CastSpell(target, 113769, false);
  5431.                     break;
  5432.                 case ENTRY_TREANT_FERAL:
  5433.                     // Special case
  5434.                     if (!rakeCast)
  5435.                     {
  5436.                         if (Unit* target = Unit::GetUnit((*me), tar))
  5437.                         {
  5438.                             if (me->IsWithinDistInMap(target, 5.0f, false))
  5439.                             {
  5440.                                 rakeCast = true;
  5441.                                 me->CastSpell(target, 150017, true);
  5442.                             }
  5443.                         }
  5444.                     }
  5445.                 default:
  5446.                     break;
  5447.                 }
  5448.  
  5449.                 DoMeleeAttackIfReady();
  5450.             }
  5451.         };
  5452.  
  5453.         CreatureAI* GetAI(Creature* pCreature) const
  5454.         {
  5455.             return new npc_force_of_natureAI(pCreature);
  5456.         }
  5457. };
  5458.  
  5459. /*######
  5460. ## npc_luo_meng
  5461. ######*/
  5462.  
  5463. #define MAGIC_BAMBOO_SHOOT 93314
  5464.  
  5465. class npc_luo_meng : public CreatureScript
  5466. {
  5467.     public:
  5468.         npc_luo_meng() : CreatureScript("npc_luo_meng") { }
  5469.  
  5470.         struct npc_luo_mengAI : public ScriptedAI
  5471.         {
  5472.             npc_luo_mengAI(Creature* pCreature) : ScriptedAI(pCreature) { }
  5473.  
  5474.             void ReceiveEmote(Player* player, uint32 emote)
  5475.             {
  5476.                 if (emote != TEXT_EMOTE_HUG)
  5477.                     return;
  5478.  
  5479.                 ItemTemplate const* itemTemplate = sObjectMgr->GetItemTemplate(MAGIC_BAMBOO_SHOOT);
  5480.                 if (!itemTemplate)
  5481.                     return;
  5482.  
  5483.                 // Adding items
  5484.                 uint32 noSpaceForCount = 0;
  5485.                 uint32 count = 1;
  5486.  
  5487.                 // check space and find places
  5488.                 ItemPosCountVec dest;
  5489.                 InventoryResult msg = player->CanStoreNewItem(NULL_BAG, NULL_SLOT, dest, MAGIC_BAMBOO_SHOOT, count, &noSpaceForCount);
  5490.                 if (msg != EQUIP_ERR_OK)                               // convert to possible store amount
  5491.                     count -= noSpaceForCount;
  5492.  
  5493.                 if (count == 0 || dest.empty())                         // can't add any
  5494.                     return;
  5495.  
  5496.                 Item* item = player->StoreNewItem(dest, MAGIC_BAMBOO_SHOOT, true, Item::GenerateItemRandomPropertyId(MAGIC_BAMBOO_SHOOT));
  5497.                 if (count > 0 && item)
  5498.                     player->SendNewItem(item, count, true, false);
  5499.             }
  5500.         };
  5501.  
  5502.         CreatureAI* GetAI(Creature* pCreature) const
  5503.         {
  5504.             return new npc_luo_mengAI(pCreature);
  5505.         }
  5506. };
  5507.  
  5508. /*######
  5509. ## npc_monk_spirit - 69791
  5510. ######*/
  5511.  
  5512. enum eSpiritEntries
  5513. {
  5514.     NPC_STORM_SPIRIT    = 69680,
  5515.     NPC_EARTH_SPIRIT    = 69792,
  5516.     NPC_FIRE_SPIRIT     = 69791
  5517. };
  5518.  
  5519. enum eSpiritEquips
  5520. {
  5521.     EQUIP_STORM_TWO_HANDS   = 25197,
  5522.     EQUIP_EARTH_STAFF       = 86218,
  5523.     EQUIP_FIRE_TWO_HANDS    = 82224
  5524. };
  5525.  
  5526. enum eSpiritActions
  5527. {
  5528.     ACTION_DESPAWN_SPIRIT
  5529. };
  5530.  
  5531. enum eSpiritMoves
  5532. {
  5533.     MOVE_DESPAWN    = 1
  5534. };
  5535.  
  5536. const uint32 visualMorph[3] = { 138080, 138083, 138081 }; // Storm, Earth and Fire
  5537.  
  5538. class npc_monk_spirit : public CreatureScript
  5539. {
  5540.     public:
  5541.         npc_monk_spirit() : CreatureScript("npc_monk_spirit") { }
  5542.  
  5543.         struct npc_monk_spiritAI : public ScriptedAI
  5544.         {
  5545.             npc_monk_spiritAI(Creature* creature) : ScriptedAI(creature)
  5546.             {
  5547.                 targetGuid = 0;
  5548.             }
  5549.  
  5550.             uint64 targetGuid;
  5551.  
  5552.             void Reset()
  5553.             {
  5554.                 me->SetDisplayId(38551);
  5555.  
  5556.                 Unit* owner = me->GetOwner();
  5557.                 if (!owner)
  5558.                     return;
  5559.  
  5560.                 me->SetShapeshiftForm(owner->GetShapeshiftForm());
  5561.  
  5562.                 switch (me->GetEntry())
  5563.                 {
  5564.                     case NPC_STORM_SPIRIT:
  5565.                         me->CastSpell(me, visualMorph[0], true);
  5566.                         SetEquipmentSlots(false, EQUIP_STORM_TWO_HANDS, EQUIP_STORM_TWO_HANDS, EQUIP_NO_CHANGE);
  5567.                         me->SetBaseWeaponDamage(BASE_ATTACK, MINDAMAGE, owner->GetWeaponDamageRange(BASE_ATTACK, MINDAMAGE));
  5568.                         me->SetBaseWeaponDamage(BASE_ATTACK, MAXDAMAGE, owner->GetWeaponDamageRange(BASE_ATTACK, MAXDAMAGE));
  5569.                         me->SetBaseWeaponDamage(OFF_ATTACK, MINDAMAGE, owner->GetWeaponDamageRange(OFF_ATTACK, MINDAMAGE) / 2);
  5570.                         me->SetBaseWeaponDamage(OFF_ATTACK, MAXDAMAGE, owner->GetWeaponDamageRange(OFF_ATTACK, MAXDAMAGE) / 2);
  5571.                         break;
  5572.                     case NPC_EARTH_SPIRIT:
  5573.                         me->CastSpell(me, visualMorph[1], true);
  5574.                         SetEquipmentSlots(false, EQUIP_EARTH_STAFF, EQUIP_NO_CHANGE, EQUIP_NO_CHANGE);
  5575.                         me->SetBaseWeaponDamage(BASE_ATTACK, MINDAMAGE, owner->GetWeaponDamageRange(BASE_ATTACK, MINDAMAGE));
  5576.                         me->SetBaseWeaponDamage(BASE_ATTACK, MAXDAMAGE, owner->GetWeaponDamageRange(BASE_ATTACK, MAXDAMAGE));
  5577.                         break;
  5578.                     case NPC_FIRE_SPIRIT:
  5579.                         me->CastSpell(me, visualMorph[2], true);
  5580.                         SetEquipmentSlots(false, EQUIP_FIRE_TWO_HANDS, EQUIP_FIRE_TWO_HANDS, EQUIP_NO_CHANGE);
  5581.                         me->SetBaseWeaponDamage(BASE_ATTACK, MINDAMAGE, owner->GetWeaponDamageRange(BASE_ATTACK, MINDAMAGE));
  5582.                         me->SetBaseWeaponDamage(BASE_ATTACK, MAXDAMAGE, owner->GetWeaponDamageRange(BASE_ATTACK, MAXDAMAGE));
  5583.                         me->SetBaseWeaponDamage(OFF_ATTACK, MINDAMAGE, owner->GetWeaponDamageRange(OFF_ATTACK, MINDAMAGE) / 2);
  5584.                         me->SetBaseWeaponDamage(OFF_ATTACK, MAXDAMAGE, owner->GetWeaponDamageRange(OFF_ATTACK, MAXDAMAGE) / 2);
  5585.                         break;
  5586.                 }
  5587.             }
  5588.  
  5589.             void SetGUID(uint64 guid, int32 data /*= 0*/)
  5590.             {
  5591.                 targetGuid = guid;
  5592.  
  5593.                 if (Unit* victim = Unit::GetUnit(*me, targetGuid))
  5594.                 {
  5595.                     me->CastSpell(victim, 138104, true);    // Jump
  5596.                     me->CastSpell(me, 138130, true);
  5597.                     AttackStart(victim);
  5598.                 }
  5599.             }
  5600.  
  5601.             uint64 GetGUID(int32 data /*= 0*/)
  5602.             {
  5603.                 return targetGuid;
  5604.             }
  5605.  
  5606.             void IsSummonedBy(Unit* summoner)
  5607.             {
  5608.                 if (!summoner || summoner->GetTypeId() != TYPEID_PLAYER)
  5609.                     return;
  5610.  
  5611.                 summoner->CastSpell(me, 119051, true);
  5612.                 me->SetLevel(summoner->getLevel());
  5613.                 me->SetHealth(summoner->CountPctFromMaxHealth(10));
  5614.                 me->SetMaxHealth(summoner->CountPctFromMaxHealth(10));
  5615.                 me->SetFullHealth();
  5616.             }
  5617.  
  5618.             void DoAction(const int32 action)
  5619.             {
  5620.                 switch (action)
  5621.                 {
  5622.                     case ACTION_DESPAWN_SPIRIT:
  5623.                     {
  5624.                         if (Unit* owner = me->GetOwner())
  5625.                         {
  5626.                             me->GetMotionMaster()->Clear();
  5627.                             me->GetMotionMaster()->MoveJump(owner->GetPositionX(), owner->GetPositionY(), owner->GetPositionZ(), 15.0f, 10.0f, me->GetOrientation(), MOVE_DESPAWN);
  5628.                         }
  5629.  
  5630.                         break;
  5631.                     }
  5632.                     default:
  5633.                         break;
  5634.                 }
  5635.             }
  5636.  
  5637.             void KilledUnit(Unit* victim)
  5638.             {
  5639.                 if (victim->GetGUID() == targetGuid)
  5640.                     DoAction(ACTION_DESPAWN_SPIRIT);
  5641.             }
  5642.  
  5643.             void MovementInform(uint32 type, uint32 id)
  5644.             {
  5645.                 if (id == MOVE_DESPAWN)
  5646.                     me->DespawnOrUnsummon(500);
  5647.             }
  5648.  
  5649.             void UpdateAI(const uint32 diff)
  5650.             {
  5651.                 if (targetGuid)
  5652.                 {
  5653.                     if (me->getVictim() && me->getVictim()->GetGUID() != targetGuid)
  5654.                         DoAction(0);
  5655.                     else if (!me->getVictim())
  5656.                         DoAction(0);
  5657.                 }
  5658.  
  5659.                 DoMeleeAttackIfReady();
  5660.             }
  5661.         };
  5662.  
  5663.         CreatureAI* GetAI(Creature* creature) const
  5664.         {
  5665.             return new npc_monk_spiritAI(creature);
  5666.         }
  5667. };
  5668.  
  5669. /*######
  5670. ## npc_army_of_the_dead - 24207
  5671. ######*/
  5672.  
  5673. const uint32 displayIds[6] = { 26079, 25286, 10971, 201, 28292, 27870 };
  5674.  
  5675. class npc_army_of_the_dead : public CreatureScript
  5676. {
  5677.     public:
  5678.         npc_army_of_the_dead() : CreatureScript("npc_army_of_the_dead") { }
  5679.  
  5680.         struct npc_army_of_the_deadAI : public ScriptedAI
  5681.         {
  5682.             npc_army_of_the_deadAI(Creature* c) : ScriptedAI(c) { }
  5683.  
  5684.             void IsSummonedBy(Unit* owner)
  5685.             {
  5686.                 if (!owner)
  5687.                     return;
  5688.  
  5689.                 if (owner->HasAura(58642))
  5690.                     me->SetDisplayId(displayIds[urand(0, 5)]);
  5691.             }
  5692.         };
  5693.  
  5694.         CreatureAI* GetAI(Creature *creature) const
  5695.         {
  5696.             return new npc_army_of_the_deadAI(creature);
  5697.         }
  5698. };
  5699.  
  5700. /*######
  5701. ## npc_transcendence_spirit -- 54569
  5702. ######*/
  5703.  
  5704. enum TranscendenceSpiritSpells
  5705. {
  5706.     emu_SPELL_INITIALIZE_IMAGES = 102284,
  5707.     SPELL_CLONE_CASTER = 102288,
  5708.     SPELL_VISUAL_SPIRIT = 119053,
  5709.     SPELL_MEDITATE = 124416,
  5710.     emu_SPELL_ROOT_FOR_EVER = 31366,
  5711. };
  5712.  
  5713. enum transcendenceActions
  5714. {
  5715.     ACTION_TELEPORT = 1,
  5716. };
  5717.  
  5718. class npc_transcendence_spirit : public CreatureScript
  5719. {
  5720. public:
  5721.     npc_transcendence_spirit() : CreatureScript("npc_transcendence_spirit") { }
  5722.  
  5723.     struct npc_transcendence_spiritAI : public Scripted_NoMovementAI
  5724.     {
  5725.         npc_transcendence_spiritAI(Creature* c) : Scripted_NoMovementAI(c)
  5726.         {
  5727.             me->SetReactState(REACT_PASSIVE);
  5728.             me->SetFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NOT_SELECTABLE | UNIT_FLAG_NON_ATTACKABLE);
  5729.         }
  5730.  
  5731.         void InitializeAI()
  5732.         {
  5733.             auto owner = me->GetOwner();
  5734.             if (owner && owner->GetTypeId() == TYPEID_PLAYER)
  5735.             {
  5736.                 me->CastSpell(me, SPELL_VISUAL_SPIRIT, true);
  5737.                 owner->CastSpell(me, 45204, true);
  5738.                 owner->CastSpell(me, SPELL_CLONE_CASTER, true);
  5739.                 owner->AddAura(SPELL_MEDITATE, me);
  5740.                 me->AddAura(SPELL_ROOT_FOR_EVER, me);
  5741.             }
  5742.             else
  5743.                 me->DespawnOrUnsummon();
  5744.         }
  5745.  
  5746.         void Reset()
  5747.         {
  5748.             if (!me->HasAura(SPELL_MEDITATE))
  5749.                 me->AddAura(SPELL_MEDITATE, me);
  5750.         }
  5751.  
  5752.         void DoAction(int32 const action)
  5753.         {
  5754.             switch (action)
  5755.             {
  5756.             case ACTION_TELEPORT:
  5757.             {
  5758.                 auto owner = me->GetOwner();
  5759.                 if (!owner)
  5760.                 {
  5761.                     me->DespawnOrUnsummon(500);
  5762.                     break;
  5763.                 }
  5764.  
  5765.                 // Switch positions
  5766.                 Position ownerPos;
  5767.                 owner->GetPosition(&ownerPos);
  5768.  
  5769.                 owner->NearTeleportTo(me->GetPositionX(), me->GetPositionY(),
  5770.                     me->GetPositionZ(), me->GetOrientation());
  5771.  
  5772.                 me->NearTeleportTo(ownerPos.GetPositionX(), ownerPos.GetPositionY(),
  5773.                     ownerPos.GetPositionZ(), ownerPos.GetOrientation());
  5774.  
  5775.                 me->SetOrientation(me->GetOwner()->GetOrientation());
  5776.                 break;
  5777.             }
  5778.             default:
  5779.                 break;
  5780.             }
  5781.         }
  5782.  
  5783.         void EnterEvadeMode() {}
  5784.     };
  5785.  
  5786.     CreatureAI* GetAI(Creature *creature) const
  5787.     {
  5788.         return new npc_transcendence_spiritAI(creature);
  5789.     }
  5790. };
  5791.  
  5792.  
  5793. void AddSC_npcs_special()
  5794. {
  5795.     new npc_air_force_bots();
  5796.     new npc_lunaclaw_spirit();
  5797.     new npc_chicken_cluck();
  5798.     new npc_dancing_flames();
  5799.     new npc_doctor();
  5800.     new npc_injured_patient();
  5801.     new npc_garments_of_quests();
  5802.     new npc_guardian();
  5803.     new npc_mount_vendor();
  5804.     new npc_rogue_trainer();
  5805.     new npc_sayge();
  5806.     new npc_steam_tonk();
  5807.     new npc_tonk_mine();
  5808.     new npc_winter_reveler();
  5809.     new npc_brewfest_reveler();
  5810.     new npc_snake_trap();
  5811.     new npc_mirror_image();
  5812.     new npc_ebon_gargoyle();
  5813.     new npc_new_lightwell();
  5814.     new npc_lightwell();
  5815.     new mob_mojo();
  5816.     new npc_training_dummy();
  5817.     new npc_wormhole();
  5818.     new npc_pet_trainer();
  5819.     new npc_locksmith();
  5820.     new npc_experience();
  5821.     new npc_fire_elemental();
  5822.     new npc_earth_elemental();
  5823.     new npc_firework();
  5824.     new npc_spring_rabbit();
  5825.     new npc_generic_harpoon_cannon();
  5826.     new npc_choose_faction();
  5827.     new npc_rate_xp_modifier();
  5828.     new npc_capacitor_totem();
  5829.     new npc_feral_spirit();
  5830.     new npc_spirit_link_totem();
  5831.     new npc_demoralizing_banner();
  5832.     new npc_frozen_orb();
  5833.     new npc_guardian_of_ancient_kings();
  5834.     new npc_power_word_barrier();
  5835.     new npc_demonic_gateway();
  5836.     new npc_xuen_the_white_tiger();
  5837.     new npc_murder_of_crows();
  5838.     new npc_dire_beast();
  5839.     new npc_wild_imp();
  5840.     new npc_stone_bulwark_totem();
  5841.     new npc_earthgrab_totem();
  5842.     new npc_windwalk_totem();
  5843.     new npc_healing_tide_totem();
  5844.     new npc_ring_of_frost();
  5845.     new npc_wild_mushroom();
  5846.     new npc_fungal_growth();
  5847.     new npc_bloodworm();
  5848.     new npc_past_self();
  5849.     new npc_void_tendrils();
  5850.     new npc_psyfiend();
  5851.     new npc_spectral_guise();
  5852.     new npc_metzen();
  5853.     new npc_moonwell_chalice();
  5854.     new npc_shadowfiend();
  5855.     new npc_custom_caster_guard();
  5856.     new npc_force_of_nature();
  5857.     new npc_luo_meng();
  5858.     new npc_monk_spirit();
  5859.     new npc_army_of_the_dead();
  5860.     new npc_transcendence_spirit();
  5861. }
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement