Guest User

npc_npc_special.cpp

a guest
Aug 26th, 2015
334
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
  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. };
  4802.  
  4803. class npc_void_tendrils : public CreatureScript
  4804. {
  4805. public:
  4806. npc_void_tendrils() : CreatureScript("npc_void_tendrils") { }
  4807.  
  4808. struct npc_void_tendrilsAI : public Scripted_NoMovementAI
  4809. {
  4810. npc_void_tendrilsAI(Creature* c) : Scripted_NoMovementAI(c)
  4811. {
  4812. me->SetReactState(REACT_AGGRESSIVE);
  4813. targetGUID = 0;
  4814. }
  4815.  
  4816. uint64 targetGUID;
  4817.  
  4818. void Reset()
  4819. {
  4820. if (!me->HasAura(31336))
  4821. me->AddAura(31336, me);
  4822. }
  4823.  
  4824. void SetGUID(uint64 guid, int32)
  4825. {
  4826. targetGUID = guid;
  4827.  
  4828. me->setFaction(14);
  4829. }
  4830.  
  4831. void JustDied(Unit* killer)
  4832. {
  4833. if (Unit* m_target = ObjectAccessor::FindUnit(targetGUID))
  4834. m_target->RemoveAura(SPELL_VOID_TENDRILS_ROOT);
  4835. }
  4836.  
  4837. void IsSummonedBy(Unit* owner)
  4838. {
  4839. if (owner && owner->GetTypeId() == TYPEID_PLAYER)
  4840. {
  4841. me->SetLevel(owner->getLevel());
  4842. me->SetMaxHealth(CalculatePct(owner->GetMaxHealth(), 2.5f));
  4843. me->SetHealth(me->GetMaxHealth());
  4844. // Set no damage
  4845. me->SetBaseWeaponDamage(BASE_ATTACK, MINDAMAGE, 0.0f);
  4846. me->SetBaseWeaponDamage(BASE_ATTACK, MAXDAMAGE, 0.0f);
  4847.  
  4848. me->AddAura(31336, me);
  4849. }
  4850. else
  4851. me->DespawnOrUnsummon();
  4852. }
  4853.  
  4854. void UpdateAI(uint32 const diff)
  4855. {
  4856. if (!(ObjectAccessor::FindUnit(targetGUID)))
  4857. me->DespawnOrUnsummon();
  4858. }
  4859. };
  4860.  
  4861. CreatureAI* GetAI(Creature *creature) const
  4862. {
  4863. return new npc_void_tendrilsAI(creature);
  4864. }
  4865. };
  4866.  
  4867. /*######
  4868. ## npc_psyfiend -- 59190
  4869. ######*/
  4870.  
  4871. enum PsyfiendSpells
  4872. {
  4873. SPELL_PSYCHIC_HORROR = 113792,
  4874. PSYCHIC_TERROR_TIMER = 2000
  4875. };
  4876.  
  4877. class npc_psyfiend : public CreatureScript {
  4878. public:
  4879. npc_psyfiend() : CreatureScript("npc_psyfiend") { }
  4880.  
  4881. class npc_psyfiend_ScriptedAI : public ScriptedAI
  4882. {
  4883. public:
  4884. npc_psyfiend_ScriptedAI(Creature *creature) : ScriptedAI(creature)
  4885. {
  4886. _uiPsychicTerrorTimer = PSYCHIC_TERROR_TIMER;
  4887. creature->SetFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_DISABLE_MOVE);
  4888. }
  4889.  
  4890. void UpdateAI(uint32 const diff)
  4891. {
  4892. Unit* owner = me->GetOwner();
  4893. if (!owner || !owner->isAlive())
  4894. {
  4895. me->DisappearAndDie();
  4896. return;
  4897. }
  4898.  
  4899. if (_uiPsychicTerrorTimer <= diff)
  4900. {
  4901. DoCastAOE(SPELL_PSYCHIC_HORROR);
  4902. _uiPsychicTerrorTimer = PSYCHIC_TERROR_TIMER;
  4903. }
  4904. else
  4905. _uiPsychicTerrorTimer -= diff;
  4906. }
  4907.  
  4908. private:
  4909. ///< Timer before next Psychic Terror cast
  4910. uint32 _uiPsychicTerrorTimer;
  4911. };
  4912.  
  4913. CreatureAI *GetAI(Creature *creature) const
  4914. {
  4915. return new npc_psyfiend_ScriptedAI(creature);
  4916. }
  4917. };
  4918.  
  4919.  
  4920. /*######
  4921. ## npc_spectral_guise -- 59607
  4922. ######*/
  4923.  
  4924. enum spectralGuiseSpells
  4925. {
  4926. SPELL_SPECTRAL_GUISE_CLONE = 119012,
  4927. SPELL_SPECTRAL_GUISE_CHARGES = 119030,
  4928. SPELL_SPECTRAL_GUISE_STEALTH = 119032,
  4929. };
  4930.  
  4931. class npc_spectral_guise : public CreatureScript
  4932. {
  4933. public:
  4934. npc_spectral_guise() : CreatureScript("npc_spectral_guise") { }
  4935.  
  4936. struct npc_spectral_guiseAI : public Scripted_NoMovementAI
  4937. {
  4938. npc_spectral_guiseAI(Creature* c) : Scripted_NoMovementAI(c)
  4939. {
  4940. me->SetReactState(REACT_PASSIVE);
  4941. }
  4942.  
  4943. void Reset()
  4944. {
  4945. if (!me->HasAura(31336))
  4946. me->AddAura(31336, me);
  4947. }
  4948.  
  4949. void IsSummonedBy(Unit* owner)
  4950. {
  4951. if (owner && owner->GetTypeId() == TYPEID_PLAYER)
  4952. {
  4953. me->SetLevel(owner->getLevel());
  4954. me->SetMaxHealth(owner->GetMaxHealth() / 2);
  4955. me->SetHealth(me->GetMaxHealth());
  4956.  
  4957. owner->AddAura(102284, me);
  4958. owner->AddAura(SPELL_SPECTRAL_GUISE_CLONE, me);
  4959.  
  4960. me->CastSpell(me, SPELL_SPECTRAL_GUISE_CHARGES, true);
  4961. Aura::TryRefreshStackOrCreate(sSpellMgr->GetSpellInfo(SPELL_SPECTRAL_GUISE_STEALTH), MAX_EFFECT_MASK, owner, owner, sSpellMgr->GetSpellInfo(SPELL_SPECTRAL_GUISE_STEALTH)->spellPower);
  4962.  
  4963. std::list<HostileReference*> threatList = owner->getThreatManager().getThreatList();
  4964. for (std::list<HostileReference*>::const_iterator itr = threatList.begin(); itr != threatList.end(); ++itr)
  4965. if (Unit* unit = (*itr)->getTarget())
  4966. if (unit->GetTypeId() == TYPEID_UNIT)
  4967. if (Creature* creature = unit->ToCreature())
  4968. if (creature->canStartAttack(me, false))
  4969. creature->Attack(me, true);
  4970.  
  4971. // Set no damage
  4972. me->SetBaseWeaponDamage(BASE_ATTACK, MINDAMAGE, 0.0f);
  4973. me->SetBaseWeaponDamage(BASE_ATTACK, MAXDAMAGE, 0.0f);
  4974.  
  4975. me->AddAura(31336, me);
  4976. }
  4977. else
  4978. me->DespawnOrUnsummon();
  4979. }
  4980. };
  4981.  
  4982. CreatureAI* GetAI(Creature *creature) const
  4983. {
  4984. return new npc_spectral_guiseAI(creature);
  4985. }
  4986. };
  4987.  
  4988. // Winter Weil - Metzen
  4989. enum GossipMenuMetzen
  4990. {
  4991. SPELL_REINDEER_DUST_EFFECT = 25952,
  4992. GOSSIP_METZEN = 15664
  4993. };
  4994.  
  4995. class npc_metzen : public CreatureScript
  4996. {
  4997. public:
  4998. npc_metzen() : CreatureScript("npc_metzen") { }
  4999.  
  5000. bool OnGossipHello(Player* player, Creature* creature)
  5001. {
  5002. uint32 questid_metz;
  5003.  
  5004. if (player->getRaceMask() & RACEMASK_ALLIANCE)
  5005. questid_metz = 8762;
  5006. else
  5007. questid_metz = 8746;
  5008.  
  5009. if (player->GetQuestStatus(questid_metz) == QUEST_STATUS_INCOMPLETE && !creature->HasUnitState(UNIT_STATE_CASTING))
  5010. player->ADD_GOSSIP_ITEM(GOSSIP_ICON_CHAT, "Sprinkle the fairy dust", GOSSIP_SENDER_MAIN, GOSSIP_ACTION_INFO_DEF + 1);
  5011.  
  5012. player->PlayerTalkClass->SendGossipMenu(GOSSIP_METZEN, creature->GetGUID());
  5013. return true;
  5014. }
  5015.  
  5016. bool OnGossipSelect(Player* player, Creature* creature, uint32 /*uiSender*/, uint32 uiAction)
  5017. {
  5018. player->PlayerTalkClass->ClearMenus();
  5019.  
  5020. switch (uiAction)
  5021. {
  5022. case GOSSIP_ACTION_INFO_DEF + 1:
  5023. {
  5024. player->KilledMonsterCredit(creature->GetEntry(), creature->GetGUID());
  5025. creature->CastSpell(creature, SPELL_REINDEER_DUST_EFFECT, false);
  5026. }
  5027. break;
  5028. }
  5029.  
  5030. player->PlayerTalkClass->SendCloseGossip();
  5031. return true;
  5032. }
  5033. };
  5034.  
  5035. class npc_moonwell_chalice : public CreatureScript
  5036. {
  5037. public:
  5038. npc_moonwell_chalice() : CreatureScript("npc_moonwell_chalice") {}
  5039.  
  5040. CreatureAI *GetAI(Creature *creature) const
  5041. {
  5042. return new npc_moonwell_chaliceAI(creature);
  5043. }
  5044.  
  5045. struct npc_moonwell_chaliceAI : public Scripted_NoMovementAI
  5046. {
  5047. npc_moonwell_chaliceAI(Creature *c) : Scripted_NoMovementAI(c)
  5048. {
  5049. me->SetReactState(REACT_PASSIVE);
  5050. uiTimer = 500;
  5051. bReady = false;
  5052. owner = NULL;
  5053. }
  5054.  
  5055. uint32 uiTimer;
  5056. bool bReady;
  5057. Unit* owner;
  5058.  
  5059. void IsSummonedBy(Unit* who)
  5060. {
  5061. if (who)
  5062. owner = who;
  5063. }
  5064.  
  5065. void UpdateAI(const uint32 diff)
  5066. {
  5067. if (!bReady)
  5068. {
  5069. if (uiTimer <= diff)
  5070. {
  5071. bReady = true;
  5072. if (owner)
  5073. DoCast(owner, 100403);
  5074. }
  5075. else
  5076. uiTimer -= diff;
  5077. }
  5078. }
  5079. };
  5080. };
  5081.  
  5082. /*######
  5083. # npc_shadowfiend
  5084. ######*/
  5085. #define GLYPH_OF_SHADOWFIEND_MANA 58227
  5086. #define GLYPH_OF_SHADOWFIEND 58228
  5087.  
  5088. class npc_shadowfiend : public CreatureScript
  5089. {
  5090. public:
  5091. npc_shadowfiend() : CreatureScript("npc_shadowfiend") { }
  5092.  
  5093. struct npc_shadowfiendAI : public PetAI
  5094. {
  5095. npc_shadowfiendAI(Creature* creature) : PetAI(creature) {}
  5096.  
  5097. void IsSummonedBy(Unit* owner)
  5098. {
  5099. me->SetReactState(REACT_AGGRESSIVE);
  5100. Unit* target = NULL;
  5101. if (owner->GetTypeId() == TYPEID_PLAYER)
  5102. target = owner->ToPlayer()->GetSelectedUnit();
  5103. else
  5104. target = owner->getVictim();
  5105.  
  5106. if (target && me->IsValidAttackTarget(target))
  5107. AttackStart(target);
  5108. }
  5109.  
  5110. void JustDied(Unit* /*killer*/)
  5111. {
  5112. if (me->isSummon())
  5113. if (Unit* owner = me->ToTempSummon()->GetSummoner())
  5114. if (owner->HasAura(GLYPH_OF_SHADOWFIEND))
  5115. owner->CastSpell(owner, GLYPH_OF_SHADOWFIEND_MANA, true);
  5116. }
  5117. };
  5118.  
  5119. CreatureAI* GetAI(Creature* creature) const
  5120. {
  5121. return new npc_shadowfiendAI(creature);
  5122. }
  5123. };
  5124.  
  5125. enum CustomCasterGuardian
  5126. {
  5127. NPC_DOOM_GUARD = 11859,
  5128. NPC_BURNING_TREANT = 53432,
  5129. NPC_FIERY_IMP = 53491,
  5130.  
  5131. SPELL_DOOM_BOLT = 85692,
  5132. SPELL_FIRESEED = 99026,
  5133. SPELL_FLAME_BLAST = 99226,
  5134.  
  5135. SPELL_DOOM = 603,
  5136. SPELL_AGONY = 980,
  5137.  
  5138. EVENT_CAST_SPELL = 1,
  5139. };
  5140.  
  5141. class npc_custom_caster_guard : public CreatureScript
  5142. {
  5143. public:
  5144. npc_custom_caster_guard() : CreatureScript("npc_custom_caster_guard") { }
  5145.  
  5146. CreatureAI* GetAI(Creature* creature) const
  5147. {
  5148. return new npc_custom_caster_guardAI(creature);
  5149. }
  5150.  
  5151. struct npc_custom_caster_guardAI : CasterAI
  5152. {
  5153. npc_custom_caster_guardAI(Creature* creature) : CasterAI(creature)
  5154. {
  5155. curTarget = NULL;
  5156. switch (me->GetEntry())
  5157. {
  5158. case NPC_DOOM_GUARD: // Doom Guard
  5159. spellId = SPELL_DOOM_BOLT;
  5160. maxRange = 30.0f;
  5161. castTime = 3000;
  5162. break;
  5163. case NPC_BURNING_TREANT: // Burning Treant
  5164. spellId = SPELL_DOOM_BOLT;
  5165. maxRange = 40.0f;
  5166. castTime = 2000;
  5167. break;
  5168. case NPC_FIERY_IMP:
  5169. spellId = SPELL_FLAME_BLAST;
  5170. maxRange = 40.0f;
  5171. castTime = 1500;
  5172. break;
  5173. default:
  5174. spellId = 0;
  5175. maxRange = 0.0f;
  5176. castTime = 0;
  5177. break;
  5178. }
  5179. }
  5180.  
  5181. void EnterCombat(Unit* who)
  5182. {
  5183. if (spellId)
  5184. events.ScheduleEvent(EVENT_CAST_SPELL, 1);
  5185. }
  5186.  
  5187. void OwnerSpellHit(Unit* target, SpellInfo const* spell)
  5188. {
  5189. if (me->GetEntry() == NPC_DOOM_GUARD)
  5190. if (spell->Id == SPELL_DOOM || spell->Id == SPELL_AGONY)
  5191. if (target && me->getVictim() != target)
  5192. AttackStart(target);
  5193. }
  5194.  
  5195. void UpdateAI(const uint32 diff)
  5196. {
  5197. if (!UpdateVictim())
  5198. return;
  5199.  
  5200. events.Update(diff);
  5201.  
  5202. if (Unit * victim = me->getVictim())
  5203. {
  5204. if (victim->HasCrowdControlAura(me))
  5205. {
  5206. me->InterruptNonMeleeSpells(false);
  5207. return;
  5208. }
  5209. }
  5210.  
  5211. if (me->HasUnitState(UNIT_STATE_CASTING))
  5212. return;
  5213.  
  5214. if (curTarget && curTarget->IsInWorld() && (me->getVictim() != curTarget))
  5215. AttackStart(curTarget);
  5216.  
  5217. if (uint32 event_id = events.ExecuteEvent())
  5218. {
  5219. if (me->GetEntry() == NPC_DOOM_GUARD)
  5220. {
  5221. UnitList targets;
  5222. DebuffCheck u_check(me, me->GetOwnerGUID());
  5223.  
  5224. WoWSource::UnitListSearcher<DebuffCheck> searcher(me, targets, u_check);
  5225. me->VisitNearbyObject(100.0f, searcher);
  5226. if (!targets.empty())
  5227. {
  5228. if (targets.size() > 1)
  5229. {
  5230. targets.sort(WoWSource::DistanceOrderPred(me));
  5231. WoWSource::Containers::RandomResizeList(targets, 1);
  5232. }
  5233. Unit* newTarget = *(targets.begin());
  5234. if (me->getVictim() != newTarget)
  5235. AttackStart(newTarget);
  5236. }
  5237. else
  5238. {
  5239. if (Unit* owner = me->GetOwner())
  5240. if (Unit* newTarget = owner->getVictim())
  5241. if (newTarget != owner->getVictim())
  5242. AttackStart(newTarget);
  5243. }
  5244. }
  5245. else
  5246. {
  5247. if (Unit* owner = me->GetOwner())
  5248. if (Unit* newTarget = owner->getVictim())
  5249. if (newTarget != owner->getVictim())
  5250. AttackStart(newTarget);
  5251. }
  5252.  
  5253. float normalRange = maxRange / 1.2f;
  5254.  
  5255. if (Unit* victim = me->getVictim())
  5256. {
  5257. if (maxRange && !me->IsWithinDistInMap(victim, maxRange))
  5258. me->GetMotionMaster()->MoveChase(victim, normalRange);
  5259.  
  5260. if (maxRange && !me->IsWithinLOSInMap(victim))
  5261. me->GetMotionMaster()->MoveChase(victim, MELEE_RANGE);
  5262. }
  5263.  
  5264. DoCastVictim(spellId);
  5265. events.ScheduleEvent(EVENT_CAST_SPELL, castTime);
  5266. }
  5267. }
  5268. private:
  5269. Unit* curTarget;
  5270. uint32 spellId;
  5271. float maxRange;
  5272. uint32 castTime;
  5273.  
  5274. class DebuffCheck
  5275. {
  5276. public:
  5277. DebuffCheck(WorldObject const* obj, uint64 casterGuid) : i_obj(obj), i_casterGuid(casterGuid) {}
  5278.  
  5279. bool operator()(Unit* u)
  5280. {
  5281. if (!u->isAlive())
  5282. return false;
  5283.  
  5284. if (!i_obj->IsWithinDistInMap(u, 100.0f))
  5285. return false;
  5286.  
  5287. if (!u->HasAura(SPELL_DOOM, i_casterGuid) && !u->HasAura(SPELL_AGONY, i_casterGuid))
  5288. return false;
  5289.  
  5290. return true;
  5291. }
  5292. private:
  5293. WorldObject const* i_obj;
  5294. uint64 i_casterGuid;
  5295. };
  5296. };
  5297. };
  5298.  
  5299. /*######
  5300. ## npc_force_of_nature
  5301. ######*/
  5302.  
  5303. class npc_force_of_nature : public CreatureScript
  5304. {
  5305. public:
  5306. npc_force_of_nature() : CreatureScript("npc_force_of_nature") { }
  5307.  
  5308. struct npc_force_of_natureAI : public ScriptedAI
  5309. {
  5310. uint64 own;
  5311. uint64 tar;
  5312. bool init;
  5313. bool rakeCast;
  5314.  
  5315. npc_force_of_natureAI(Creature* pCreature) : ScriptedAI(pCreature)
  5316. {
  5317. init = false;
  5318. own = 0;
  5319. tar = 0;
  5320. rakeCast = false;
  5321. }
  5322.  
  5323. void InitializeAI()
  5324. {
  5325. init = true;
  5326. Unit* owner;
  5327.  
  5328. if (TempSummon* temp = me->ToTempSummon())
  5329. owner = temp->GetSummoner();
  5330.  
  5331. if (owner == NULL)
  5332. return;
  5333.  
  5334. Player* player = owner->ToPlayer();
  5335.  
  5336. if (player == NULL)
  5337. return;
  5338.  
  5339. own = player->GetGUID();
  5340.  
  5341. if (Unit* target = player->GetSelectedUnit())
  5342. {
  5343. tar = target->GetGUID();
  5344. CastStartSpell(owner, target);
  5345. }
  5346. }
  5347.  
  5348. void CastStartSpell(Unit* o, Unit* t)
  5349. {
  5350. if (me->GetEntry() == ENTRY_TREANT_RESTO)
  5351. {
  5352. me->CastSpell(t->IsFriendlyTo(o) ? t : o, 142423, true);
  5353. return;
  5354. }
  5355. else if (t->IsFriendlyTo(o))
  5356. return;
  5357.  
  5358. switch (me->GetEntry())
  5359. {
  5360. case ENTRY_TREANT_GUARDIAN:
  5361. me->CastSpell(t, 113830, true); // Taunt
  5362. break;
  5363. case ENTRY_TREANT_FERAL:
  5364. case ENTRY_TREANT_BALANCE:
  5365. me->CastSpell(t, 113770, true); // Root
  5366. // on creatures 30seconds
  5367. if (t->GetTypeId() !=TYPEID_PLAYER)
  5368. if (AuraPtr root = t->GetAura(113770, me->GetGUID()))
  5369. root->SetDuration(30000);
  5370. break;
  5371. default:
  5372. break;
  5373. }
  5374.  
  5375. AttackStart(t);
  5376. }
  5377.  
  5378. void Reset() {}
  5379.  
  5380. bool UpdateTarget()
  5381. {
  5382. if (!(me->getVictim()) && me->GetEntry() != ENTRY_TREANT_RESTO)
  5383. {
  5384. Player* owner = Unit::GetPlayer((*me), own);
  5385. if (owner)
  5386. {
  5387. if (Unit* target = owner->getAttackerForHelper())
  5388. {
  5389. tar = target->GetGUID();
  5390. me->SetTarget(tar);
  5391. me->SetInCombatWith(target);
  5392. AttackStart(target);
  5393. }
  5394. else
  5395. return false;
  5396. }
  5397. else
  5398. {
  5399. own = 0;
  5400. return false;
  5401. }
  5402. }
  5403.  
  5404. return true;
  5405. }
  5406.  
  5407. void UpdateAI(const uint32 diff)
  5408. {
  5409. if (!init)
  5410. InitializeAI();
  5411.  
  5412. if (!own)
  5413. return;
  5414.  
  5415. if (me->IsNonMeleeSpellCasted(false))
  5416. return;
  5417.  
  5418. if (!UpdateTarget())
  5419. return;
  5420.  
  5421. switch (me->GetEntry())
  5422. {
  5423. case ENTRY_TREANT_RESTO:
  5424. me->CastSpell(me, 113828);
  5425. return;
  5426. case ENTRY_TREANT_BALANCE:
  5427. if (Unit* target = Unit::GetUnit((*me), tar))
  5428. me->CastSpell(target, 113769, false);
  5429. break;
  5430. case ENTRY_TREANT_FERAL:
  5431. // Special case
  5432. if (!rakeCast)
  5433. {
  5434. if (Unit* target = Unit::GetUnit((*me), tar))
  5435. {
  5436. if (me->IsWithinDistInMap(target, 5.0f, false))
  5437. {
  5438. rakeCast = true;
  5439. me->CastSpell(target, 150017, true);
  5440. }
  5441. }
  5442. }
  5443. default:
  5444. break;
  5445. }
  5446.  
  5447. DoMeleeAttackIfReady();
  5448. }
  5449. };
  5450.  
  5451. CreatureAI* GetAI(Creature* pCreature) const
  5452. {
  5453. return new npc_force_of_natureAI(pCreature);
  5454. }
  5455. };
  5456.  
  5457. /*######
  5458. ## npc_luo_meng
  5459. ######*/
  5460.  
  5461. #define MAGIC_BAMBOO_SHOOT 93314
  5462.  
  5463. class npc_luo_meng : public CreatureScript
  5464. {
  5465. public:
  5466. npc_luo_meng() : CreatureScript("npc_luo_meng") { }
  5467.  
  5468. struct npc_luo_mengAI : public ScriptedAI
  5469. {
  5470. npc_luo_mengAI(Creature* pCreature) : ScriptedAI(pCreature) { }
  5471.  
  5472. void ReceiveEmote(Player* player, uint32 emote)
  5473. {
  5474. if (emote != TEXT_EMOTE_HUG)
  5475. return;
  5476.  
  5477. ItemTemplate const* itemTemplate = sObjectMgr->GetItemTemplate(MAGIC_BAMBOO_SHOOT);
  5478. if (!itemTemplate)
  5479. return;
  5480.  
  5481. // Adding items
  5482. uint32 noSpaceForCount = 0;
  5483. uint32 count = 1;
  5484.  
  5485. // check space and find places
  5486. ItemPosCountVec dest;
  5487. InventoryResult msg = player->CanStoreNewItem(NULL_BAG, NULL_SLOT, dest, MAGIC_BAMBOO_SHOOT, count, &noSpaceForCount);
  5488. if (msg != EQUIP_ERR_OK) // convert to possible store amount
  5489. count -= noSpaceForCount;
  5490.  
  5491. if (count == 0 || dest.empty()) // can't add any
  5492. return;
  5493.  
  5494. Item* item = player->StoreNewItem(dest, MAGIC_BAMBOO_SHOOT, true, Item::GenerateItemRandomPropertyId(MAGIC_BAMBOO_SHOOT));
  5495. if (count > 0 && item)
  5496. player->SendNewItem(item, count, true, false);
  5497. }
  5498. };
  5499.  
  5500. CreatureAI* GetAI(Creature* pCreature) const
  5501. {
  5502. return new npc_luo_mengAI(pCreature);
  5503. }
  5504. };
  5505.  
  5506. /*######
  5507. ## npc_monk_spirit - 69791
  5508. ######*/
  5509.  
  5510. enum eSpiritEntries
  5511. {
  5512. NPC_STORM_SPIRIT = 69680,
  5513. NPC_EARTH_SPIRIT = 69792,
  5514. NPC_FIRE_SPIRIT = 69791
  5515. };
  5516.  
  5517. enum eSpiritEquips
  5518. {
  5519. EQUIP_STORM_TWO_HANDS = 25197,
  5520. EQUIP_EARTH_STAFF = 86218,
  5521. EQUIP_FIRE_TWO_HANDS = 82224
  5522. };
  5523.  
  5524. enum eSpiritActions
  5525. {
  5526. ACTION_DESPAWN_SPIRIT
  5527. };
  5528.  
  5529. enum eSpiritMoves
  5530. {
  5531. MOVE_DESPAWN = 1
  5532. };
  5533.  
  5534. const uint32 visualMorph[3] = { 138080, 138083, 138081 }; // Storm, Earth and Fire
  5535.  
  5536. class npc_monk_spirit : public CreatureScript
  5537. {
  5538. public:
  5539. npc_monk_spirit() : CreatureScript("npc_monk_spirit") { }
  5540.  
  5541. struct npc_monk_spiritAI : public ScriptedAI
  5542. {
  5543. npc_monk_spiritAI(Creature* creature) : ScriptedAI(creature)
  5544. {
  5545. targetGuid = 0;
  5546. }
  5547.  
  5548. uint64 targetGuid;
  5549.  
  5550. void Reset()
  5551. {
  5552. me->SetDisplayId(38551);
  5553.  
  5554. Unit* owner = me->GetOwner();
  5555. if (!owner)
  5556. return;
  5557.  
  5558. me->SetShapeshiftForm(owner->GetShapeshiftForm());
  5559.  
  5560. switch (me->GetEntry())
  5561. {
  5562. case NPC_STORM_SPIRIT:
  5563. me->CastSpell(me, visualMorph[0], true);
  5564. SetEquipmentSlots(false, EQUIP_STORM_TWO_HANDS, EQUIP_STORM_TWO_HANDS, EQUIP_NO_CHANGE);
  5565. me->SetBaseWeaponDamage(BASE_ATTACK, MINDAMAGE, owner->GetWeaponDamageRange(BASE_ATTACK, MINDAMAGE));
  5566. me->SetBaseWeaponDamage(BASE_ATTACK, MAXDAMAGE, owner->GetWeaponDamageRange(BASE_ATTACK, MAXDAMAGE));
  5567. me->SetBaseWeaponDamage(OFF_ATTACK, MINDAMAGE, owner->GetWeaponDamageRange(OFF_ATTACK, MINDAMAGE) / 2);
  5568. me->SetBaseWeaponDamage(OFF_ATTACK, MAXDAMAGE, owner->GetWeaponDamageRange(OFF_ATTACK, MAXDAMAGE) / 2);
  5569. break;
  5570. case NPC_EARTH_SPIRIT:
  5571. me->CastSpell(me, visualMorph[1], true);
  5572. SetEquipmentSlots(false, EQUIP_EARTH_STAFF, EQUIP_NO_CHANGE, EQUIP_NO_CHANGE);
  5573. me->SetBaseWeaponDamage(BASE_ATTACK, MINDAMAGE, owner->GetWeaponDamageRange(BASE_ATTACK, MINDAMAGE));
  5574. me->SetBaseWeaponDamage(BASE_ATTACK, MAXDAMAGE, owner->GetWeaponDamageRange(BASE_ATTACK, MAXDAMAGE));
  5575. break;
  5576. case NPC_FIRE_SPIRIT:
  5577. me->CastSpell(me, visualMorph[2], true);
  5578. SetEquipmentSlots(false, EQUIP_FIRE_TWO_HANDS, EQUIP_FIRE_TWO_HANDS, EQUIP_NO_CHANGE);
  5579. me->SetBaseWeaponDamage(BASE_ATTACK, MINDAMAGE, owner->GetWeaponDamageRange(BASE_ATTACK, MINDAMAGE));
  5580. me->SetBaseWeaponDamage(BASE_ATTACK, MAXDAMAGE, owner->GetWeaponDamageRange(BASE_ATTACK, MAXDAMAGE));
  5581. me->SetBaseWeaponDamage(OFF_ATTACK, MINDAMAGE, owner->GetWeaponDamageRange(OFF_ATTACK, MINDAMAGE) / 2);
  5582. me->SetBaseWeaponDamage(OFF_ATTACK, MAXDAMAGE, owner->GetWeaponDamageRange(OFF_ATTACK, MAXDAMAGE) / 2);
  5583. break;
  5584. }
  5585. }
  5586.  
  5587. void SetGUID(uint64 guid, int32 data /*= 0*/)
  5588. {
  5589. targetGuid = guid;
  5590.  
  5591. if (Unit* victim = Unit::GetUnit(*me, targetGuid))
  5592. {
  5593. me->CastSpell(victim, 138104, true); // Jump
  5594. me->CastSpell(me, 138130, true);
  5595. AttackStart(victim);
  5596. }
  5597. }
  5598.  
  5599. uint64 GetGUID(int32 data /*= 0*/)
  5600. {
  5601. return targetGuid;
  5602. }
  5603.  
  5604. void IsSummonedBy(Unit* summoner)
  5605. {
  5606. if (!summoner || summoner->GetTypeId() != TYPEID_PLAYER)
  5607. return;
  5608.  
  5609. summoner->CastSpell(me, 119051, true);
  5610. me->SetLevel(summoner->getLevel());
  5611. me->SetHealth(summoner->CountPctFromMaxHealth(10));
  5612. me->SetMaxHealth(summoner->CountPctFromMaxHealth(10));
  5613. me->SetFullHealth();
  5614. }
  5615.  
  5616. void DoAction(const int32 action)
  5617. {
  5618. switch (action)
  5619. {
  5620. case ACTION_DESPAWN_SPIRIT:
  5621. {
  5622. if (Unit* owner = me->GetOwner())
  5623. {
  5624. me->GetMotionMaster()->Clear();
  5625. me->GetMotionMaster()->MoveJump(owner->GetPositionX(), owner->GetPositionY(), owner->GetPositionZ(), 15.0f, 10.0f, me->GetOrientation(), MOVE_DESPAWN);
  5626. }
  5627.  
  5628. break;
  5629. }
  5630. default:
  5631. break;
  5632. }
  5633. }
  5634.  
  5635. void KilledUnit(Unit* victim)
  5636. {
  5637. if (victim->GetGUID() == targetGuid)
  5638. DoAction(ACTION_DESPAWN_SPIRIT);
  5639. }
  5640.  
  5641. void MovementInform(uint32 type, uint32 id)
  5642. {
  5643. if (id == MOVE_DESPAWN)
  5644. me->DespawnOrUnsummon(500);
  5645. }
  5646.  
  5647. void UpdateAI(const uint32 diff)
  5648. {
  5649. if (targetGuid)
  5650. {
  5651. if (me->getVictim() && me->getVictim()->GetGUID() != targetGuid)
  5652. DoAction(0);
  5653. else if (!me->getVictim())
  5654. DoAction(0);
  5655. }
  5656.  
  5657. DoMeleeAttackIfReady();
  5658. }
  5659. };
  5660.  
  5661. CreatureAI* GetAI(Creature* creature) const
  5662. {
  5663. return new npc_monk_spiritAI(creature);
  5664. }
  5665. };
  5666.  
  5667. /*######
  5668. ## npc_army_of_the_dead - 24207
  5669. ######*/
  5670.  
  5671. const uint32 displayIds[6] = { 26079, 25286, 10971, 201, 28292, 27870 };
  5672.  
  5673. class npc_army_of_the_dead : public CreatureScript
  5674. {
  5675. public:
  5676. npc_army_of_the_dead() : CreatureScript("npc_army_of_the_dead") { }
  5677.  
  5678. struct npc_army_of_the_deadAI : public ScriptedAI
  5679. {
  5680. npc_army_of_the_deadAI(Creature* c) : ScriptedAI(c) { }
  5681.  
  5682. void IsSummonedBy(Unit* owner)
  5683. {
  5684. if (!owner)
  5685. return;
  5686.  
  5687. if (owner->HasAura(58642))
  5688. me->SetDisplayId(displayIds[urand(0, 5)]);
  5689. }
  5690. };
  5691.  
  5692. CreatureAI* GetAI(Creature *creature) const
  5693. {
  5694. return new npc_army_of_the_deadAI(creature);
  5695. }
  5696. };
  5697.  
  5698. /*######
  5699. ## npc_transcendence_spirit -- 54569
  5700. ######*/
  5701.  
  5702. enum TranscendenceSpiritSpells
  5703. {
  5704. SPELL_INITIALIZE_IMAGES = 102284,
  5705. SPELL_CLONE_CASTER = 102288,
  5706. SPELL_VISUAL_SPIRIT = 119053,
  5707. SPELL_MEDITATE = 124416,
  5708. SPELL_ROOT_FOR_EVER = 31366,
  5709. };
  5710.  
  5711. enum transcendenceActions
  5712. {
  5713. ACTION_TELEPORT = 1,
  5714. };
  5715.  
  5716. class npc_transcendence_spirit : public CreatureScript
  5717. {
  5718. public:
  5719. npc_transcendence_spirit() : CreatureScript("npc_transcendence_spirit") { }
  5720.  
  5721. struct npc_transcendence_spiritAI : public Scripted_NoMovementAI
  5722. {
  5723. npc_transcendence_spiritAI(Creature* c) : Scripted_NoMovementAI(c)
  5724. {
  5725. me->SetReactState(REACT_PASSIVE);
  5726. me->SetFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NOT_SELECTABLE | UNIT_FLAG_NON_ATTACKABLE);
  5727. }
  5728.  
  5729. void InitializeAI()
  5730. {
  5731. auto owner = me->GetOwner();
  5732. if (owner && owner->GetTypeId() == TYPEID_PLAYER)
  5733. {
  5734. me->CastSpell(me, SPELL_VISUAL_SPIRIT, true);
  5735. owner->CastSpell(me, 45204, true);
  5736. owner->CastSpell(me, SPELL_CLONE_CASTER, true);
  5737. owner->AddAura(SPELL_MEDITATE, me);
  5738. me->AddAura(SPELL_ROOT_FOR_EVER, me);
  5739. }
  5740. else
  5741. me->DespawnOrUnsummon();
  5742. }
  5743.  
  5744. void Reset()
  5745. {
  5746. if (!me->HasAura(SPELL_MEDITATE))
  5747. me->AddAura(SPELL_MEDITATE, me);
  5748. }
  5749.  
  5750. void DoAction(int32 const action)
  5751. {
  5752. switch (action)
  5753. {
  5754. case ACTION_TELEPORT:
  5755. {
  5756. auto owner = me->GetOwner();
  5757. if (!owner)
  5758. {
  5759. me->DespawnOrUnsummon(500);
  5760. break;
  5761. }
  5762.  
  5763. // Switch positions
  5764. Position ownerPos;
  5765. owner->GetPosition(&ownerPos);
  5766.  
  5767. owner->NearTeleportTo(me->GetPositionX(), me->GetPositionY(),
  5768. me->GetPositionZ(), me->GetOrientation());
  5769.  
  5770. me->NearTeleportTo(ownerPos.GetPositionX(), ownerPos.GetPositionY(),
  5771. ownerPos.GetPositionZ(), ownerPos.GetOrientation());
  5772.  
  5773. me->SetOrientation(me->GetOwner()->GetOrientation());
  5774. break;
  5775. }
  5776. default:
  5777. break;
  5778. }
  5779. }
  5780.  
  5781. void EnterEvadeMode() {}
  5782. };
  5783.  
  5784. CreatureAI* GetAI(Creature *creature) const
  5785. {
  5786. return new npc_transcendence_spiritAI(creature);
  5787. }
  5788. };
  5789.  
  5790.  
  5791. void AddSC_npcs_special()
  5792. {
  5793. new npc_air_force_bots();
  5794. new npc_lunaclaw_spirit();
  5795. new npc_chicken_cluck();
  5796. new npc_dancing_flames();
  5797. new npc_doctor();
  5798. new npc_injured_patient();
  5799. new npc_garments_of_quests();
  5800. new npc_guardian();
  5801. new npc_mount_vendor();
  5802. new npc_rogue_trainer();
  5803. new npc_sayge();
  5804. new npc_steam_tonk();
  5805. new npc_tonk_mine();
  5806. new npc_winter_reveler();
  5807. new npc_brewfest_reveler();
  5808. new npc_snake_trap();
  5809. new npc_mirror_image();
  5810. new npc_ebon_gargoyle();
  5811. new npc_new_lightwell();
  5812. new npc_lightwell();
  5813. new mob_mojo();
  5814. new npc_training_dummy();
  5815. new npc_wormhole();
  5816. new npc_pet_trainer();
  5817. new npc_locksmith();
  5818. new npc_experience();
  5819. new npc_fire_elemental();
  5820. new npc_earth_elemental();
  5821. new npc_firework();
  5822. new npc_spring_rabbit();
  5823. new npc_generic_harpoon_cannon();
  5824. new npc_choose_faction();
  5825. new npc_rate_xp_modifier();
  5826. new npc_capacitor_totem();
  5827. new npc_feral_spirit();
  5828. new npc_spirit_link_totem();
  5829. new npc_demoralizing_banner();
  5830. new npc_frozen_orb();
  5831. new npc_guardian_of_ancient_kings();
  5832. new npc_power_word_barrier();
  5833. new npc_demonic_gateway();
  5834. new npc_xuen_the_white_tiger();
  5835. new npc_murder_of_crows();
  5836. new npc_dire_beast();
  5837. new npc_wild_imp();
  5838. new npc_stone_bulwark_totem();
  5839. new npc_earthgrab_totem();
  5840. new npc_windwalk_totem();
  5841. new npc_healing_tide_totem();
  5842. new npc_ring_of_frost();
  5843. new npc_wild_mushroom();
  5844. new npc_fungal_growth();
  5845. new npc_bloodworm();
  5846. new npc_past_self();
  5847. new npc_void_tendrils();
  5848. new npc_psyfiend();
  5849. new npc_spectral_guise();
  5850. new npc_metzen();
  5851. new npc_moonwell_chalice();
  5852. new npc_shadowfiend();
  5853. new npc_custom_caster_guard();
  5854. new npc_force_of_nature();
  5855. new npc_luo_meng();
  5856. new npc_monk_spirit();
  5857. new npc_army_of_the_dead();
  5858. new npc_transcendence_spirit();
  5859. }
RAW Paste Data