Advertisement
Guest User

sas

a guest
Apr 27th, 2015
195
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
text 64.28 KB | None | 0 0
  1. #define NPC_ID_MADNESS_VISUAL 56173 // at center of the black hole. At phase 2 he will lean forward
  2. #define NPC_ID_MADNESS_ATTACKTARGET 57962 // spawned between platform 1 and 2 and can be reached by attacks and spells
  3. #define NPC_ID_MADNESS_FIGHT_CONTROLLER 56174 // spawned at teleport location and will spawn dynamic spawns
  4. #define MADNESS_INDEX_GUID_VISUAL 0
  5. #define MADNESS_INDEX_GUID_ATTACK 1
  6. #define MADNESS_INDEX_ACTIVE_PLATFORM 2
  7. #define MADNESS_INDEX_ACTIVE_PLATFORMS 3
  8. #define MADNESS_LOOSE_HP_PCT_TENTACLE 15
  9. #define SPELL_ID_ASSAULT_ASPECT 1
  10. #define SPELL_COOL_ASSAULT_ASPECT 900000
  11. #define SPELL_ID_CATACLYSM 106523
  12. #define SPELL_COOL_CATACLYSM 900000
  13. //#define SPELL_ID_ELEMENTIUM_BOLT 1
  14. //#define SPELL_COOL_ELEMENTIUM_BOLT 1
  15. #define NPC_ID_ELEMENTIUM_BOLT 56262
  16. #define NPC_MINPROC_ELEMENTIUM_BOLT 1
  17. #define NPC_COOL_ELEMENTIUM_BOLT 600000
  18. #define SPELL_ID_ELEMNTIUM_BLAST 105723
  19. #define SPELL_ID_ELEMNTIUM_BLAST_PULSE 110632
  20. #define SPELL_COOL_ELEMNTIUM_BLAST 5000
  21. #define SPELL_ID_CORRUPTING_PARASITE 108649
  22. #define SPELL_COOL_CORRUPTING_PARASITE 18000
  23. #define SPELL_MINPROC_CORRUPTING_PARASITE 5
  24. #define NPC_ID_CORRUPTING_PARASITE 57479 //auto created by spell when it ends
  25. #define SPELL_ID_CORRUPTING_PARASITE_BACKLASH 108597
  26. #define SPELL_ID_UNSTABLE_CORRUPTION 108813
  27. #define SPELL_COOL_UNSTABLE_CORRUPTION 10000 //this does about 600k DMG / tick
  28. #define NPC_ID_HEMORRHAGE_VISUAL_LOC 56359
  29. //#define SPELL_ID_HEMORRHAGE 105875 //or 106767 actually spawns the mobs
  30. //#define SPELL_ID_HEMORRHAGE_VISUAL 105861
  31. //#define SPELL_COOL_HEMORRHAGE 40000
  32. #define NPC_ID_REGENERATIVE_BLOOD 56263 //or 56710
  33. #define NPC_COOL_REGENERATIVE_BLOOD 37000
  34. #define NPC_MINPROC_REGENERATIVE_BLOOD 4
  35. #define SPELL_ID_REGENERATIVE 105937
  36. #define SPELL_COOL_REGENERATIVE 1000 //1.4M health => needs 140k dps
  37. #define SPELL_ID_DEGENRATIVE_BITE 105841
  38. #define SPELL_COOL_DEGENRATIVE_BITE 1000
  39. #define NPC_ID_LIMB0 56168
  40. #define NPC_ID_LIMB1 56846
  41. #define NPC_ID_LIMB2 56167
  42. #define NPC_ID_LIMB3 56168
  43. #define TENTACLE_START_FIGHT_HP_PCT 95
  44. #define NPC_ID_BLISTERING_TENTACLE 56188
  45. #define NPC_COOL_LIMB_TENTACLE 600000 //at 25% health pct drop
  46. #define NPC_MINPROC_LIMB_TENTACLE 3
  47. #define SPELL_ID_BURNING_BLOOD 105408
  48. #define SPELL_COOL_BURNING_BLOOD 2000
  49. //#define SPELL_ID_BLISTERING_TENTACLE 1
  50. //#define SPELL_COOL_BLISTERING_TENTACLE 1
  51. #define SPELL_ID_BLISTERING_HEAT 105444 //aura that periodically does AOE DMG
  52. #define SPELL_COOL_BLISTERING_HEAT 2000
  53. #define SPELL_ID_AGONIZING_PAIN 106548
  54. //#define SPELL_COOL_AGONIZING_PAIN 1
  55. #define NPC_ID_MUTATED_CORRUPTION 56471
  56. #define NPC_COOL_MUTATED_CORRUPTION 600000
  57. #define NPC_MINPROC_MUTATED_CORRUPTION 1
  58. #define SPELL_ID_CRUSH 106385
  59. #define SPELL_COOL_CRUSH 8000
  60. #define SPELL_ID_IMPALE 106400 //for full cast. Players have a chance to pop defense
  61. #define SPELL_COOL_IMPALE 12000
  62. #define NPC_ID_CONGEALING_BLOOD 57798
  63. #define NPC_COOL_CONGEALING_BLOOD 37000
  64. #define NPC_MINPROC_CONGEALING_BLOOD 5
  65. #define SPELL_ID_CONGEALING_BLOOD_HEAL 109102
  66. #define NPC_ID_ELEMENTIUM_FRAGMENT 56724
  67. #define NPC_COOL_ELEMENTIUM_FRAGMENT 25000
  68. #define NPC_MINPROC_ELEMENTIUM_FRAGMENT 3
  69. #define SPELL_ID_SHRAPNEL_TARGETED 106794
  70. #define SPELL_ID_SHRAPNEL_DMG 106791
  71. #define SPELL_COOL_SHRAPNEL 15000
  72. #define NPC_ID_ELEMNTIUM_TERROR 56710
  73. #define NPC_COOL_ELEMNTIUM_TERROR 30000
  74. #define NPC_MINPROC_ELEMENTIUM_TERROR 5
  75. #define SPELL_ID_TETANUS 106730
  76. #define SPELL_COOL_TETANUS 2000
  77. #define SPELL_ID_CORRUPTED_BLOOD 106835
  78. #define SPELL_COOL_CORRUPTED_BLOOD 2000
  79. #define SPELL_ID_ALEXTRASZA_PRESENCE 106028
  80. #define SPELL_ID_CAUTERIZE 109045
  81. #define SPELL_COOL_CAUTERIZE 1000
  82. #define SPELL_ID_NOZDORMU_PRESENCE 106027
  83. #define SPELL_ID_TIME_ZONE 1
  84. #define SPELL_ID_YSERA_PRESENCE 106457
  85. #define SPELL_ID_ENTER_THE_DREAM 106464 //cancel dream to enter dreamer effect
  86. #define SPELL_ID_ENTER_THE_DREAM_EFFECT 106466
  87. #define SPELL_ID_KALECGOS_PRESENCE 106029
  88. #define SPELL_ID_SPELLWEAVING 106040
  89. #define SPELL_ID_CARRYING_WINDS 106664
  90. #define NPC_ID_ASPECT_ALEXSTRASZA 56099
  91. #define NPC_ID_ASPECT_NOZDORMU 56102
  92. #define NPC_ID_ASPECT_KALECGOS 56101
  93. #define NPC_ID_ASPECT_YSERA 56100
  94. #define NPC_ID_ASPECT_THRALL 56103
  95. #define LIMIT_SPAWN_COUNT_OF_SAME_TYPE 20
  96.  
  97. #ifdef _DEBUG
  98. /*
  99. #define TEMP_DISABLE_TENTACLE_SAPWNS
  100. #define TEMP_DISABLE_BLOOD_SAPWNS
  101. #define TEMP_DISABLE_PHASE1
  102. #define TEMP_DISABLE_REQ_HEROIC
  103. */
  104. #endif
  105.  
  106. #define MADNESSPLATFORM_COUNT 4
  107.  
  108. #define MadnessZdifference -105.0f
  109.  
  110. const float MadnessSpawnLocation[4] = { -11903.9f, 11989.0f, -113.1f, 2.1f };
  111. const float MadnessAttackSpawnLocation[4] = { -12063.5f, 12198.9f, -12.9f, 2.16f };
  112. const float MadnessPhaseLocation[4] = { -12137.9f, 12079.0f, -113.1f, 2.1f };
  113. const float CorruptionLocations[MADNESSPLATFORM_COUNT][3] = { { -11929.0f, 12297.0f, -2.0f },{ -12028.0f, 12265.5f, -6.1f },{ -12107.4f, 12201.9f, -5.2f },{ -12160.9f, 12057.0f, 2.5f} };
  114. const float PlatformCenterLocations[MADNESSPLATFORM_COUNT][3] = { { -11956.0f, 12270.0f, 1.5f },{ -12035.6f, 12221.6f, -6.1f },{ -12097.4f, 12161.0f, -2.7f },{ -12122.4f, 12074.2f, 2.3f } };
  115. const float LimbLocations[MADNESSPLATFORM_COUNT][5] = { { -11941.0f, 12248.9f, 12.2f, 1.98f, NPC_ID_LIMB0 },{ -12005.8f, 12190.2f, -6.4f, 2.12f, NPC_ID_LIMB1 },{ -12065.0f, 12127.2f, -3.1f, 2.33f, NPC_ID_LIMB2 },{ -12097.0f, 12067.0f, 13.5f, 2.21f, NPC_ID_LIMB3 } };
  116. const float LimbTentacleLocations[MADNESSPLATFORM_COUNT][3] = { { -11941.0f, 12248.9f, 12.2f },{ -12025.8f, 12208.2f, -6.4f },{ -12073.0f, 12145.2f, -3.1f },{ -12097.0f, 12067.0f, 13.5f } };
  117. const uint32 DespawnOldEncounterDynamicEntries[] = { NPC_ID_MADNESS_VISUAL, NPC_ID_MADNESS_ATTACKTARGET, NPC_ID_ELEMENTIUM_BOLT, NPC_ID_CORRUPTING_PARASITE, NPC_ID_HEMORRHAGE_VISUAL_LOC, NPC_ID_REGENERATIVE_BLOOD, NPC_ID_BLISTERING_TENTACLE, NPC_ID_LIMB0, NPC_ID_LIMB1, NPC_ID_LIMB2, NPC_ID_LIMB3, NPC_ID_MUTATED_CORRUPTION, NPC_ID_CONGEALING_BLOOD, NPC_ID_ELEMENTIUM_FRAGMENT, NPC_ID_ELEMNTIUM_TERROR, 0 }; //despawn these in case encounter resets
  118. const float ElementiumBoltStart[MADNESSPLATFORM_COUNT][3] ={ { -11961.0f, 12228.0f, 21.0f }, { -12015.0f, 12143.0f, 21.0f }, { -12015.0f, 12143.0f, 21.0f }, { -12071.0f, 12087.0f, 21.0f } };
  119.  
  120. class DeathwingMadnessController : public CreatureAIScript
  121. {
  122. public:
  123. ADD_CREATURE_FACTORY_FUNCTION(DeathwingMadnessController);
  124. /*
  125. http://www.youtube.com/watch?v=qxScIr3UlTg&feature=player_detailpage#t=278s
  126. Stage One: The Final Assault
  127. Deathwing assaults his enemies while attached to the platforms by his twisted limbs.
  128. Assault Aspect – Deathwing searches for his next enemy to assault. Deathwing assaults the platform with the largest number of players and an attached limb.
  129. Cataclysm – Deathwing attempts to finish the job he started by bringing forth a second Cataclysm, inflicting 1462500 to 1537500 Fire damage to all players.
  130. Elementium Bolt – Deathwing creates an Elementium Bolt, sending it to the target platform.
  131. Elementium Blast – If the Elementium Bolt reaches its destination, the bolt inflicts 380250 to 399750 Fire damage to all players and an additional 380250 to 399750 Fire damage every 5 sec until players destroy the Elementium Bolt. The initial damage decreases the further the player stands from the targeted location.
  132. Corrupting Parasite – A Corrupting Parasite inflicts increasing Shadow damage periodically. When Corrupting Parasite's duration ends, the parasite detaches from the player and causes a Parasitic Backlash. This inflicts 243750 to 256250 Fire damage to players within 10 yards of the host.
  133. Corrupting Parasite – After the Corrupting Parasite's duration ends, the parasite detaches from the host.
  134. Unstable Corruption – The Corrupting Parasite casts Unstable Corruption, inflicting 10% of the Corrupted Parasite's health as Fire damage to all players.
  135. Hemorrhage – Deathwing's tentacle begins to Hemorrhage, creating several Regenerative Blood at a nearby location.
  136. Regenerative Blood – The Regenerative Blood of Deathwing forms. Regenerative Bloods gain ten energy every 1 sec. The melee attacks of a Regenerative Blood also cause Degenerative Bite.
  137. Regenerative – A Regenerative Blood heals to full health when it reaches maximum energy.
  138. In Looking for Raid Difficulty, Regenerative Blood heals 50% of max health when it reaches maximum energy.
  139. Degenerative Bite – Melee attacks cause Degenerative Bite, inflicting 1462 to 1537 Shadow damage every 1 sec for 10 sec. This effect stacks.
  140. Limb Tentacle – Deathwing grasps onto each platform with one of his limbs.
  141. Burning Blood – The Burning Blood gushes from the Tentacle, inflicting Fire damage every 2 sec. The damage increases as the Limb Tentacle's health lowers.
  142. Blistering Tentacle – At 75%, 50%, and 25% remaining health the Limb Tentacle sprouts several Blistering Tentacles that are immune to Area of Effect abilities.
  143. Blistering Heat – The Blistering Heat inflicts 2500 Fire damage every 2 sec, and increases its damage by 5% for 3 sec. This effect stacks.
  144. Agonizing Pain – The pain from severing Deathwing's limb interrupts his concentration, stunning him and inflicting 20% of his health in damage.
  145. Mutated Corruption – A Mutated Corruption appears shortly after assaulting a platform.
  146. Crush – The crushing weight of the Mutated Corruption inflicts 100000 Physical damage to enemies in a cone in front of the Corruption.
  147. Impale – The Mutated Corruption impales its target, inflicting 400000 Physical damage to the target.
  148. Stage Two: The Last Stand
  149. At 20% remaining health, Deathwing falls forward onto the platform.
  150. Congealing Blood – Deathwing begins to Hemorrhage, creating several Congealing Blood at a nearby location. The Blood then moves towards Deathwing.
  151. Congealing Blood – If a Congealing Blood reaches Deathwing, it heals him for 1% of his maximum health.
  152. Elementium Fragment – Pieces of Deathwing's armor chip off, forming three Elementium Fragments nearby.
  153. In 25 player raids, eight Elementium Fragments form.
  154. Shrapnel – The Fragment fires a piece of Shrapnel at a random player, inflicting 195000 to 205000 unresistable Physical damage.
  155. Elementium Terror – Pieces of Deathwing's armor chip off, forming two Elementium Terrors nearby.
  156. Tetanus – The Elementium Terror's melee attacks cause Tetanus, inflicting 58500 to 61500 Physical damage and an additional 19500 to 20500 Physical damage every 1 sec. The effect stacks.
  157. Corrupted Blood – Corrupted Blood gushes from Deathwing, inflicting Fire damage every 2 sec. The damage increases as Deathwing's health lowers. At 15%, 10%, and 5% remaining health, Deathwing hemorrages. This increases the damage dealt by Corrupted Blood.
  158. The Aspects
  159. The Dragon Aspects assist in the fight against Deathwing. Each aspect channels Expose Weakness on their respective Limb Tentacle when Deathwing begins to cast Cataclysm. Expose Weakness increases the damage done to the Tentacle by 100%. Each Aspect also channels Concentration after the players destroy their respective tentacle, preventing the Aspect from assisting the players with their presence and their special powers. The Aspects resume assisting the players when Stage Two begins.
  160. Alexstrasza
  161. Alexstrasza's Presence – The Presence of Alexstrasza increases the player's maximum health by 20%.
  162. Cauterize – Alexstrasza Cauterizes the Blistering Tentacles, inflicting lethal damage over 5 sec. Cauterize also reduces the damage inflicted by Corrupted Blood.
  163. In Heroic Difficulty Alexstrasza Cauterizes the Corrupting Parasite, inflicting 3% Fire damage every 0.5 sec.
  164. Nozdormu
  165. Nozdormu's Presence – The Presence of Nozdormu increases the player's haste by 20%.
  166. Time Zone – Nozdormu forms a Time Zone at the target location, causing the Elementium Meteor to lapse in time and decrease its travel speed dramatically upon entering the zone. Any enemy creatures within the Time Zone have their attack speed decreased by 50%.
  167. In Heroic Difficulty the Time Zone slows the effects of Corrupting Parasite.
  168. Ysera
  169. Ysera's Presence – The Presence of Ysera increases player healing done by 20%.
  170. Enter the Dream – The Presence of Ysera allows players to enter the Dream, decreasing damage taken by 50% for 2 sec.
  171. Kalecgos
  172. Kalecgos' Presence – The Presence of Kalecgos increases player damage dealt by 20%.
  173. Spellweaving – The Presence of Kalecgos allows attacks and abilities to cause Spellweaving. Spellweaving inflicts 22425 to 23575 Arcane damage to enemies within 6 yards, excluding the current target.
  174. Thrall
  175. Carrying Winds – The Carrying Winds take players between adjacent platforms, and increase their movement speed by 60% for 10 sec. This effect stacks.
  176. */
  177. uint32 YellIndex;
  178. uint32 TalkCooldown;
  179. uint32 phase;
  180. float DifficultyScale;
  181. uint32 AssaultAspectTimer;
  182. uint32 CataclysmTimer;
  183. uint64 LimbGUIDs[MADNESSPLATFORM_COUNT];
  184. uint32 FaintTimer;
  185.  
  186. DeathwingMadnessController(Creature* pCreature) : CreatureAIScript(pCreature)
  187. {
  188. phase = 0;
  189. }
  190.  
  191. void OnLoad()
  192. {
  193. DifficultyScale = 1.0f;
  194. if( _unit->GetMapMgr()->instance_difficulty & INSTANCE_FLAG_RAID_10_MEN_HEROIC )
  195. DifficultyScale = SPEED_SCALE_DIFF_10HEROIC;
  196. else if( _unit->GetMapMgr()->instance_difficulty & INSTANCE_FLAG_RAID_25_MEN )
  197. DifficultyScale = SPEED_SCALE_DIFF_25NORMAL;
  198. else if( _unit->GetMapMgr()->instance_difficulty & INSTANCE_FLAG_RAID_25_MEN_HEROIC )
  199. DifficultyScale = SPEED_SCALE_DIFF_25HEROIC;
  200. //make him attack faster as difficulty increases
  201. // uint32 attacktime_now = _unit->GetUInt32Value( UNIT_FIELD_BASEATTACKTIME );
  202. // _unit->SetUInt32Value( UNIT_FIELD_BASEATTACKTIME, MAX( 500, attacktime_now * DifficultyScale ) ); //attack a bit faster cause there are more healers
  203.  
  204. _unit->GetAIInterface()->disable_melee = true;
  205. _unit->GetAIInterface()->m_canMove = false;
  206. _unit->GetAIInterface()->disable_combat = true;
  207. _unit->GetAIInterface()->disable_targeting = true;
  208. _unit->GetAIInterface()->setOutOfCombatRange( 700.0f * 700.0f );
  209. // _unit->bInvincible = true;
  210. // _unit->static_object = true; //do not deactivate. Need to monitor the fight all the time
  211.  
  212. // int64 *MadnessGUID = _unit->GetMapMgr()->GetCreateIn64Extension( NPC_ID_MADNESS_VISUAL + MADNESS_INDEX_GUID_VISUAL );
  213. // *MadnessGUID = _unit->GetGUID();
  214.  
  215. RegisterAIUpdateEvent( 1000 );
  216.  
  217. ConvertToStaticSpawn( _unit, true );
  218. }
  219.  
  220. void OnDied(Unit *mKiller)
  221. {
  222. RemoveAIUpdateEvent();
  223. }
  224.  
  225. void AIUpdate()
  226. {
  227. if( _unit->isAlive() == false )
  228. return;
  229. int64 *EncounterStatus = _unit->GetMapMgr()->GetCreateIn64Extension( EXTENSION_MAP_BOS_KILLS );
  230. if( *EncounterStatus & EXTENSION_FLAG_MADNESS_DIED )
  231. return;
  232. // Unit *tank = _unit->GetAIInterface()->GetNextTarget();
  233. InrangeLoopExitAutoCallback AutoLock;
  234. if( _unit->GetInRangePlayerSetBegin( AutoLock ) == _unit->GetInRangePlayerSetEnd() )
  235. return;
  236. Unit *tank = *_unit->GetInRangePlayerSetBegin( AutoLock );
  237. if( tank == NULL )
  238. {
  239. phase = 0;
  240. return;
  241. }
  242. uint32 TickNow = GetTickCount();
  243.  
  244. // Init phase
  245. Creature *Madness;
  246. if( phase == 0 )
  247. {
  248. TalkCooldown = TickNow + RandomUInt() % 25000;
  249. YellIndex = 0;
  250. phase = 1;
  251. AssaultAspectTimer = TickNow + RandomUInt() % 25000;
  252. CataclysmTimer = TickNow + RandomUInt() % 25000;
  253. // HemorrhageTimer = TickNow + RandomUInt() % 25000;
  254. //activate nearby mapmanager cells
  255. float distX = _unit->GetPositionX() - MadnessSpawnLocation[0];
  256. float distY = _unit->GetPositionY() - MadnessSpawnLocation[1];
  257. int32 dist = sqrt( distX * distX + distY * distY );
  258. dist += 50;
  259. dist = dist / _cellSize;
  260. uint32 x = _unit->GetMapMgr()->GetPosX(_unit->GetPositionX());
  261. uint32 y = _unit->GetMapMgr()->GetPosY(_unit->GetPositionY());
  262. _unit->GetMapMgr()->UpdateCellActivity( x, y, dist, 2 );
  263. //despawn all dynamic spawns
  264. DespawnEncounterSpawns( _unit, DespawnOldEncounterDynamicEntries );
  265. //spawn madness
  266. {
  267. Madness = _unit->GetMapMgr()->CreateCreature( NPC_ID_MADNESS_VISUAL, true, MadnessSpawnLocation[0], MadnessSpawnLocation[1], MadnessSpawnLocation[2], MadnessSpawnLocation[3] );
  268. ConvertToStaticSpawn( Madness, true );
  269. }
  270. Madness->CastSpell( Madness, SPELL_ID_CATACLYSM, false );
  271. {
  272. Creature *c;
  273. c = _unit->GetMapMgr()->GetCreatureByEntry( NPC_ID_ASPECT_ALEXSTRASZA );
  274. ConvertToStaticSpawn( c, true );
  275. c = _unit->GetMapMgr()->GetCreatureByEntry( NPC_ID_ASPECT_NOZDORMU );
  276. ConvertToStaticSpawn( c, true );
  277. c = _unit->GetMapMgr()->GetCreatureByEntry( NPC_ID_ASPECT_KALECGOS );
  278. ConvertToStaticSpawn( c, true );
  279. c = _unit->GetMapMgr()->GetCreatureByEntry( NPC_ID_ASPECT_YSERA );
  280. ConvertToStaticSpawn( c, true );
  281. }
  282. //spawn new limbs
  283. #ifndef TEMP_DISABLE_PHASE1
  284. for( int i=0;i<MADNESSPLATFORM_COUNT;i++)
  285. {
  286. uint32 LimbEntry = LimbLocations[i][4];
  287. Creature *c = _unit->GetMapMgr()->CreateCreature( LimbEntry, true, LimbLocations[i][0], LimbLocations[i][1], LimbLocations[i][2], LimbLocations[i][3] );
  288. if( c )
  289. {
  290. LimbGUIDs[i] = c->GetGUID();
  291. int64 *LimbIndex = c->GetCreateIn64Extension( NPC_ID_LIMB0 );
  292. *LimbIndex = i; //self awarness for inter object comunication if required
  293. int64 *CanActivePlatformIndex = _unit->GetMapMgr()->GetCreateIn64Extension( NPC_ID_MADNESS_VISUAL + MADNESS_INDEX_ACTIVE_PLATFORMS + *LimbIndex );
  294. *CanActivePlatformIndex = 1;
  295. }
  296. // c = _unit->GetMapMgr()->CreateCreature( NPC_ID_HEMORRHAGE_VISUAL_LOC, true, LimbTentacleLocations[i][0], LimbTentacleLocations[i][1], LimbTentacleLocations[i][2] );
  297. // if( c )
  298. // {
  299. // int64 *HemoTargetNPCGUID = _unit->GetMapMgr()->GetCreateIn64Extension( NPC_ID_HEMORRHAGE_VISUAL_LOC + i );
  300. // *HemoTargetNPCGUID = c->GetGUID();
  301. // }
  302. }
  303. #endif
  304. // Madness->SetPosition( MadnessSpawnLocation[0], MadnessSpawnLocation[1], MadnessSpawnLocation[2], _unit->GetOrientation() );
  305. // Madness->GetAIInterface()->StopMovement( 0 );
  306. }
  307.  
  308. int64 *MadnessGUID = _unit->GetMapMgr()->GetCreateIn64Extension( NPC_ID_MADNESS_VISUAL + MADNESS_INDEX_GUID_VISUAL );
  309. Madness = _unit->GetMapMgr()->GetCreature( *MadnessGUID );
  310. if( Madness == NULL )
  311. return;
  312.  
  313. if (phase == 1)
  314. {
  315. if( TalkCooldown < TickNow )
  316. {
  317. Madness->SendChatMessage( CHAT_MSG_MONSTER_YELL, LANG_UNIVERSAL, DeathwingMadnessYells[ YellIndex ] );
  318. YellIndex = ( YellIndex + 1 ) % 15;
  319. TalkCooldown = TickNow + (20000 + RandomUInt() % 10000);
  320. }
  321. //count platform players
  322. /* uint32 PlatformPlayerCount[MADNESSPLATFORM_COUNT];
  323. memset( PlatformPlayerCount, 0, sizeof( PlatformPlayerCount ) );
  324. float PlatformRadius = 40.0f * 40.0f;
  325. InRangePlayerSet::iterator itr3;
  326. _unit->AquireInrangeLock(); //make sure to release lock before exit function !
  327. InrangeLoopExitAutoCallback AutoLock;
  328. for( itr3 = _unit->GetInRangePlayerSetBegin( AutoLock ); itr3 != _unit->GetInRangePlayerSetEnd(); itr3++)
  329. {
  330. if( (*itr3)->isAlive() == false )
  331. continue;
  332. float BestPlatformDist = 99999999999999.0f;
  333. uint32 BestPlatformIndex = 0;
  334. for( uint32 i=0;i<MADNESSPLATFORM_COUNT;i++)
  335. {
  336. float dist = Distance2DSq( PlatformCenterLocations[ i ][0], PlatformCenterLocations[ i ][1], (*itr3)->GetPositionX(), (*itr3)->GetPositionY() );
  337. if( dist < BestPlatformDist )
  338. {
  339. BestPlatformDist = dist;
  340. BestPlatformIndex = i;
  341. }
  342. }
  343. PlatformPlayerCount[ BestPlatformIndex ]++;
  344. }
  345. _unit->ReleaseInrangeLock();
  346. //get which platform has most players on it
  347. uint32 BestPlayerCount = 0;
  348. uint32 BestPlayerCountIndex = 0;
  349. for( uint32 i=0;i<MADNESSPLATFORM_COUNT;i++)
  350. {
  351. int64 *CanActivePlatformIndex = _unit->GetMapMgr()->GetCreateIn64Extension( NPC_ID_MADNESS_VISUAL + MADNESS_INDEX_ACTIVE_PLATFORMS + i );
  352. if( *CanActivePlatformIndex == 1 && PlatformPlayerCount[i] > BestPlayerCount )
  353. {
  354. BestPlayerCount = PlatformPlayerCount[i];
  355. BestPlayerCountIndex = i;
  356. }
  357. }
  358. //set as active platform
  359. int64 *AcctivePlatformIndex = _unit->GetMapMgr()->GetCreateIn64Extension( NPC_ID_MADNESS_VISUAL + MADNESS_INDEX_ACTIVE_PLATFORM );
  360. *AcctivePlatformIndex = BestPlayerCountIndex;
  361. //get the tank of this platform
  362. Unit *PlatformCorruption = _unit->GetMapMgr()->GetCreature( LimbGUIDs[ BestPlayerCountIndex ] );
  363. Unit *PlatformTank = NULL;
  364. if( PlatformCorruption )
  365. PlatformTank = PlatformCorruption->GetAIInterface()->GetMostHated();
  366. if( PlatformTank )
  367. {
  368. if( AssaultAspectTimer < TickNow )
  369. {
  370. Madness->CastSpell( PlatformTank, SPELL_ID_ASSAULT_ASPECT, false );
  371. AssaultAspectTimer = TickNow + (SPELL_COOL_ASSAULT_ASPECT + RandomUInt() % SPELL_COOL_ASSAULT_ASPECT)*DifficultyScale;
  372. }
  373. if( CataclysmTimer < TickNow )
  374. {
  375. Madness->CastSpell( PlatformTank, SPELL_ID_CATACLYSM, false );
  376. CataclysmTimer = TickNow + (SPELL_COOL_CATACLYSM + RandomUInt() % SPELL_COOL_CATACLYSM)*DifficultyScale;
  377. }
  378. } */
  379. //time to enter next phase ?
  380. bool LimbsLeft = false;
  381. char LimbKilled = false;
  382. for( uint32 i=0;i<MADNESSPLATFORM_COUNT;i++)
  383. {
  384. int64 *CanActivePlatformIndex = _unit->GetMapMgr()->GetCreateIn64Extension( NPC_ID_MADNESS_VISUAL + MADNESS_INDEX_ACTIVE_PLATFORMS + i );
  385. if( *CanActivePlatformIndex )
  386. LimbsLeft = true;
  387. else
  388. LimbKilled++;
  389. }
  390. if( Madness->GetHealthPct() <= 100 + 5 - MADNESS_LOOSE_HP_PCT_TENTACLE * MADNESSPLATFORM_COUNT || LimbsLeft == false
  391. // || LimbKilled != 0
  392. )
  393. {
  394. phase = 2;
  395. //move head between platform 2-3
  396. Madness->SetUInt32Value( UNIT_NPC_EMOTESTATE, EMOTE_ONESHOT_CUSTOMSPELL01 );
  397. FaintTimer = TickNow + 5000;
  398. // Madness->bInvincible = false;
  399. //EMOTE_ONESHOT_CUSTOMSPELL05 ->sparkling explode
  400. //spawn madness attack target
  401. {
  402. Creature *c = _unit->GetMapMgr()->CreateCreature( NPC_ID_MADNESS_ATTACKTARGET, true, MadnessAttackSpawnLocation[0], MadnessAttackSpawnLocation[1], MadnessAttackSpawnLocation[2], MadnessAttackSpawnLocation[3] );
  403. ConvertToStaticSpawn( c, true );
  404. // Madness->bInvincible = true;
  405. Madness->SetUInt32Value( UNIT_FIELD_FLAGS, UNIT_FLAG_NOT_SELECTABLE | UNIT_FLAG_NOT_ATTACKABLE_2 | UNIT_FLAG_NOT_ATTACKABLE_9 );
  406. }
  407. {
  408. char buff[500];
  409. sprintf( buff, "Debug MSG : You should go to the platform where taxi ported you" );
  410. Madness->SendChatMessage( CHAT_MSG_MONSTER_PARTY, LANG_UNIVERSAL, buff );
  411. }
  412. }
  413. }
  414. else if (phase == 2)
  415. {
  416. //keep head forward
  417. if( FaintTimer < TickNow )
  418. {
  419. Madness->SetUInt32Value( UNIT_NPC_EMOTESTATE, EMOTE_ONESHOT_CUSTOMSPELL02 );
  420. for( uint32 i=0;i<MADNESSPLATFORM_COUNT;i++)
  421. {
  422. int64 *CanActivePlatformIndex = _unit->GetMapMgr()->GetCreateIn64Extension( NPC_ID_MADNESS_VISUAL + MADNESS_INDEX_ACTIVE_PLATFORMS + i );
  423. *CanActivePlatformIndex = 1;
  424. }
  425. }
  426. }
  427. }
  428. };
  429.  
  430. class DeathwingMadnessVisual : public CreatureAIScript
  431. {
  432. public:
  433. ADD_CREATURE_FACTORY_FUNCTION(DeathwingMadnessVisual);
  434.  
  435. DeathwingMadnessVisual(Creature* pCreature) : CreatureAIScript(pCreature) { }
  436. void OnLoad()
  437. {
  438. _unit->GetAIInterface()->setOutOfCombatRange( 700.0f * 700.0f );
  439. _unit->m_canRegenerateHP = false;
  440. _unit->GetAIInterface()->disable_melee = true;
  441. _unit->GetAIInterface()->disable_combat = true;
  442. _unit->GetAIInterface()->disable_targeting = true;
  443. _unit->bInvincible = true;
  444. }
  445. void OnDied(Unit *mKiller)
  446. {
  447. }
  448. };
  449.  
  450. class DeathwingMadnessAttackTarget : public CreatureAIScript
  451. {
  452. public:
  453. ADD_CREATURE_FACTORY_FUNCTION(DeathwingMadnessAttackTarget);
  454. DeathwingMadnessAttackTarget(Creature* pCreature) : CreatureAIScript(pCreature) { }
  455.  
  456. uint32 CongealingBloodTimer,CongealingBloodCounter;
  457. uint32 ElementiumFragmentTimer,ElementiumFragmentCounter;
  458. uint32 ElementiumTerrorTimer,ElementiumTerrorCounter;
  459. uint32 CorruptedBloodTimer;
  460. uint32 phase;
  461. float DifficultyScale;
  462.  
  463. void OnLoad()
  464. {
  465. _unit->GetAIInterface()->setOutOfCombatRange( 700.0f * 700.0f );
  466. ConvertToStaticSpawn( _unit, true );
  467. _unit->m_canRegenerateHP = false;
  468. _unit->GetAIInterface()->disable_melee = true;
  469. _unit->GetAIInterface()->disable_combat = true;
  470. _unit->GetAIInterface()->disable_targeting = true;
  471. //copy health from visual target
  472. int64 *MadnessGUID = _unit->GetMapMgr()->GetCreateIn64Extension( NPC_ID_MADNESS_VISUAL + MADNESS_INDEX_GUID_VISUAL );
  473. Creature *Madness = _unit->GetMapMgr()->GetCreature( *MadnessGUID );
  474. if( Madness )
  475. {
  476. _unit->SetMaxHealth( Madness->GetMaxHealth() );
  477. _unit->SetHealth( Madness->GetHealth() );
  478. }
  479. RegisterAIUpdateEvent( 2000 );
  480. phase = 0;
  481. DifficultyScale = 1.0f;
  482. if( _unit->GetMapMgr()->instance_difficulty & INSTANCE_FLAG_RAID_10_MEN_HEROIC )
  483. DifficultyScale = SPEED_SCALE_DIFF_10HEROIC;
  484. else if( _unit->GetMapMgr()->instance_difficulty & INSTANCE_FLAG_RAID_25_MEN )
  485. DifficultyScale = SPEED_SCALE_DIFF_25NORMAL;
  486. else if( _unit->GetMapMgr()->instance_difficulty & INSTANCE_FLAG_RAID_25_MEN_HEROIC )
  487. DifficultyScale = SPEED_SCALE_DIFF_25HEROIC;
  488. }
  489. void AIUpdate()
  490. {
  491. Unit *tank = _unit->GetAIInterface()->GetNextTarget();
  492. if( tank == NULL )
  493. {
  494. phase = 0;
  495. return;
  496. }
  497. uint32 TickNow = GetTickCount();
  498. if( phase == 0 )
  499. {
  500. phase = 1;
  501. CongealingBloodTimer = TickNow + 5000 + RandomUInt() % 25000;
  502. CongealingBloodCounter = 0;
  503. ElementiumFragmentTimer = TickNow + 10000 + RandomUInt() % 25000;
  504. ElementiumFragmentCounter = 0;
  505. ElementiumTerrorTimer = TickNow + 15000 + RandomUInt() % 25000;
  506. ElementiumTerrorCounter = 0;
  507. CorruptedBloodTimer = TickNow + 20000 + RandomUInt() % 25000;
  508. }
  509. if( phase == 1 )
  510. {
  511. //this happens when raid wipes :( Health resets to full. Maybe later reset the whole encounter ?
  512. if( _unit->GetHealthPct() > ( 100 + - MADNESS_LOOSE_HP_PCT_TENTACLE * MADNESSPLATFORM_COUNT ) )
  513. {
  514. _unit->SetHealth( _unit->GetMaxHealth() / 100 * ( 100 + - MADNESS_LOOSE_HP_PCT_TENTACLE * MADNESSPLATFORM_COUNT ) );
  515. }
  516. uint32 PlatformPlayerCount[MADNESSPLATFORM_COUNT];
  517. memset( PlatformPlayerCount, 0, sizeof( PlatformPlayerCount ) );
  518. float PlatformRadius = 40.0f * 40.0f;
  519. InRangePlayerSetRecProt::iterator itr3;
  520. _unit->AquireInrangeLock(); //make sure to release lock before exit function !
  521. InrangeLoopExitAutoCallback AutoLock;
  522. for( itr3 = _unit->GetInRangePlayerSetBegin( AutoLock ); itr3 != _unit->GetInRangePlayerSetEnd(); itr3++)
  523. {
  524. if( (*itr3)->isAlive() == false )
  525. continue;
  526. float BestPlatformDist = 99999999999999.0f;
  527. uint32 BestPlatformIndex = 0;
  528. for( uint32 i=0;i<MADNESSPLATFORM_COUNT;i++)
  529. {
  530. float dist = Distance2DSq( PlatformCenterLocations[ i ][0], PlatformCenterLocations[ i ][1], (*itr3)->GetPositionX(), (*itr3)->GetPositionY() );
  531. if( dist < BestPlatformDist )
  532. {
  533. BestPlatformDist = dist;
  534. BestPlatformIndex = i;
  535. }
  536. }
  537. PlatformPlayerCount[ BestPlatformIndex ]++;
  538. }
  539. _unit->ReleaseInrangeLock();
  540. //get which platform has most players on it
  541. uint32 BestPlayerCount = 0;
  542. uint32 BestPlayerCountIndex = 0;
  543. for( uint32 i=0;i<MADNESSPLATFORM_COUNT;i++)
  544. {
  545. if( PlatformPlayerCount[i] > BestPlayerCount )
  546. {
  547. BestPlayerCount = PlatformPlayerCount[i];
  548. BestPlayerCountIndex = i;
  549. }
  550. }
  551. //set as active platform
  552. uint32 SelectedPlatform = BestPlayerCountIndex;
  553.  
  554. if( CongealingBloodTimer < TickNow
  555. #ifndef TEMP_DISABLE_REQ_HEROIC
  556. && IS_HEROIC_INSTANCE_DIFFICULTIE( _unit->GetMapMgr()->instance_difficulty )
  557. #endif
  558. )
  559. {
  560. int64 *ActiveSpawnCount = _unit->GetMapMgr()->GetCreateIn64Extension( NPC_ID_CONGEALING_BLOOD );
  561. if( *ActiveSpawnCount < LIMIT_SPAWN_COUNT_OF_SAME_TYPE )
  562. {
  563. // uint32 BloodsToCreateCount = float2int32( 5 / DifficultyScale );
  564. uint32 BloodsToCreateCount = float2int32( 3 / DifficultyScale );
  565. for(uint32 i=0;i<BloodsToCreateCount;i++)
  566. {
  567. float RandX = PlatformCenterLocations[ SelectedPlatform ][0] + 5.0f - ( RandomUInt() % 100 ) / 10.0f;
  568. float RandY = PlatformCenterLocations[ SelectedPlatform ][1] + 5.0f - ( RandomUInt() % 100 ) / 10.0f;
  569. Creature *c = _unit->GetMapMgr()->CreateCreature( NPC_ID_CONGEALING_BLOOD, true, RandX, RandY, PlatformCenterLocations[ SelectedPlatform ][2] );
  570. *ActiveSpawnCount += 1;
  571. }
  572. CongealingBloodTimer = TickNow + (NPC_COOL_CONGEALING_BLOOD + RandomUInt() % NPC_COOL_CONGEALING_BLOOD)*DifficultyScale;
  573. CongealingBloodCounter++;
  574. }
  575. }
  576. else if( ShouldForceProc( _unit, CongealingBloodCounter, NPC_MINPROC_CONGEALING_BLOOD, MADNESS_LOOSE_HP_PCT_TENTACLE * MADNESSPLATFORM_COUNT ) )
  577. CongealingBloodTimer = 1;
  578.  
  579. if( ElementiumFragmentTimer < TickNow )
  580. {
  581. int64 *ActiveSpawnCount = _unit->GetMapMgr()->GetCreateIn64Extension( NPC_ID_ELEMENTIUM_FRAGMENT );
  582. if( *ActiveSpawnCount < LIMIT_SPAWN_COUNT_OF_SAME_TYPE )
  583. {
  584. float RandX = PlatformCenterLocations[ SelectedPlatform ][0] + 15.0f - ( RandomUInt() % 300 ) / 10.0f;
  585. float RandY = PlatformCenterLocations[ SelectedPlatform ][1] + 15.0f - ( RandomUInt() % 300 ) / 10.0f;
  586. Creature *c = _unit->GetMapMgr()->CreateCreature( NPC_ID_ELEMENTIUM_FRAGMENT, true, RandX, RandY, PlatformCenterLocations[ SelectedPlatform ][2] );
  587. *ActiveSpawnCount += 1;
  588. ElementiumFragmentTimer = TickNow + (NPC_COOL_ELEMENTIUM_FRAGMENT + RandomUInt() % NPC_COOL_ELEMENTIUM_FRAGMENT)*DifficultyScale;
  589.  
  590. ElementiumFragmentCounter++;
  591. }
  592. }
  593. else if( ShouldForceProc( _unit, ElementiumFragmentCounter, NPC_MINPROC_ELEMENTIUM_FRAGMENT, MADNESS_LOOSE_HP_PCT_TENTACLE * MADNESSPLATFORM_COUNT ) )
  594. ElementiumFragmentTimer = 1;
  595.  
  596. if( ElementiumTerrorTimer < TickNow )
  597. {
  598. int64 *ActiveSpawnCount = _unit->GetMapMgr()->GetCreateIn64Extension( NPC_ID_ELEMNTIUM_TERROR );
  599. if( *ActiveSpawnCount < LIMIT_SPAWN_COUNT_OF_SAME_TYPE )
  600. {
  601. float RandX = PlatformCenterLocations[ SelectedPlatform ][0] + 15.0f - ( RandomUInt() % 300 ) / 10.0f;
  602. float RandY = PlatformCenterLocations[ SelectedPlatform ][1] + 15.0f - ( RandomUInt() % 300 ) / 10.0f;
  603. Creature *c = _unit->GetMapMgr()->CreateCreature( NPC_ID_ELEMNTIUM_TERROR, true, RandX, RandY, PlatformCenterLocations[ SelectedPlatform ][2] );
  604. *ActiveSpawnCount += 1;
  605. ElementiumTerrorTimer = TickNow + (NPC_COOL_ELEMNTIUM_TERROR + RandomUInt() % NPC_COOL_ELEMNTIUM_TERROR)*DifficultyScale;
  606. ElementiumTerrorCounter++;
  607. }
  608. }
  609. else if( ShouldForceProc( _unit, ElementiumTerrorCounter, NPC_MINPROC_ELEMENTIUM_TERROR, MADNESS_LOOSE_HP_PCT_TENTACLE * MADNESSPLATFORM_COUNT ) )
  610. ElementiumTerrorTimer = 1;
  611. if( CorruptedBloodTimer < TickNow )
  612. {
  613. //each lost health pct adds 100% dmg. Should scale up to 35000 DPS ( base is 350 )
  614. int32 BurningBloodDMGPCT = 100 * ( ( 101 + - MADNESS_LOOSE_HP_PCT_TENTACLE * MADNESSPLATFORM_COUNT ) - _unit->GetHealthPct() * DifficultyScale );
  615. InRangePlayerSetRecProt::iterator itr3;
  616. _unit->AquireInrangeLock(); //make sure to release lock before exit function !
  617. InrangeLoopExitAutoCallback AutoLock;
  618. for( itr3 = _unit->GetInRangePlayerSetBegin( AutoLock ); itr3 != _unit->GetInRangePlayerSetEnd(); itr3++)
  619. {
  620. if( (*itr3)->isAlive() == false )
  621. continue;
  622.  
  623. SpellEntry *spellInfo = dbcSpell.LookupEntryForced( SPELL_ID_CORRUPTED_BLOOD );
  624. Spell *spell = SpellPool.PooledNew( __FILE__, __LINE__ );
  625. spell->Init( _unit, spellInfo ,true, NULL);
  626. SpellCastTargets targets( (*itr3)->GetGUID() );
  627. spell->forced_pct_mod[0] = BurningBloodDMGPCT;
  628. spell->prepare(&targets);
  629. }
  630. _unit->ReleaseInrangeLock();
  631. CorruptedBloodTimer = TickNow + SPELL_COOL_CORRUPTED_BLOOD; //needs to be fixed or it will not stack
  632. }
  633. }
  634. }
  635. void OnDied(Unit *mKiller)
  636. {
  637. int64 *EncounterStatus = _unit->GetMapMgr()->GetCreateIn64Extension( EXTENSION_MAP_BOS_KILLS );
  638. *EncounterStatus |= EXTENSION_FLAG_MADNESS_DIED;
  639. // _unit->GetMapMgr()->CreateCreature( MOB_ENTRY_DRAGONSOUL_TELEPORTER, true, _unit->GetPositionX(), _unit->GetPositionY(), _unit->GetPositionZ() );
  640. RemoveAIUpdateEvent();
  641. //try to see players lie about BOSS difficulty
  642. LOG_CREATURE_DEATH( _unit->GetEntry(), mKiller );
  643. int64 *MadnessGUID = _unit->GetMapMgr()->GetCreateIn64Extension( NPC_ID_MADNESS_VISUAL + MADNESS_INDEX_GUID_VISUAL );
  644. Creature *Madness = _unit->GetMapMgr()->GetCreature( *MadnessGUID );
  645. if( Madness )
  646. {
  647. Madness->bInvincible = false;
  648. Madness->SetHealth( 1 );
  649. Madness->DealDamage( Madness, 100, NULL );
  650. }
  651. //spawn GO that players can loot
  652. /* GameObject *go = u_caster->GetMapMgr()->CreateGameObject(210220);
  653. if( go == NULL )
  654. {
  655. sLog.outDebug("Missing GO proto 210220");
  656. return;
  657. }
  658. go->CreateFromProto( 210220, _unit->GetMapId(), -12100.5f, 12173.6f, -2.73425f, 5.09636f );
  659. go->SetUInt64Value( OBJECT_FIELD_CREATED_BY, m_caster->GetGUID() );
  660. go->SetInstanceID( _unit->GetInstanceID() );
  661. go->PushToWorld( _unit->GetMapMgr() );
  662. sEventMgr.AddEvent(go, &GameObject::ExpireAndDelete, EVENT_GAMEOBJECT_EXPIRE, 5*60*1000, 1,0);
  663. */
  664. _unit->SetUInt32Value( UNIT_FIELD_DISPLAYID, 35268 );
  665. _unit->SetScale( 0.5f );
  666. if( mKiller && mKiller->IsPlayer() && SafePlayerCast( mKiller )->GetGuild() )
  667. SafePlayerCast( mKiller )->GetGuild()->GuildNewsAdd( GUILD_NEWS_LOG_DUNGEON_ENCOUNTER, mKiller->GetGUID(), 1299 );
  668. }
  669. };
  670.  
  671. const uint32 DespawnOldLimbEncounterDynamicEntries[] = { NPC_ID_ELEMENTIUM_BOLT, NPC_ID_CORRUPTING_PARASITE, NPC_ID_HEMORRHAGE_VISUAL_LOC, NPC_ID_REGENERATIVE_BLOOD, NPC_ID_BLISTERING_TENTACLE, NPC_ID_MUTATED_CORRUPTION, 0 }; //despawn these in case encounter resets
  672.  
  673. class LimbGeneric : public CreatureAIScript
  674. {
  675. public:
  676. ADD_CREATURE_FACTORY_FUNCTION(LimbGeneric);
  677.  
  678. uint32 phase;
  679. float DifficultyScale;
  680. uint32 RegenerativeBloodTimer,RegenerativeBloodCounter;
  681. uint32 CorruptionTimer,CorruptionCounter;
  682. uint32 LimbTentacleTimer,LimbTentacleCounter;
  683. uint32 BurningBloodTimer;
  684. uint32 AlexStraszaCauterizeTimer;
  685. uint32 ElementiumBoltTimer,ElementiumBoltCounter;
  686. uint32 CorruptingParasiteTimer,CorruptingParasiteCounter;
  687.  
  688. LimbGeneric(Creature* pCreature) : CreatureAIScript(pCreature) { }
  689. void OnLoad()
  690. {
  691. DifficultyScale = 1.0f;
  692. if( _unit->GetMapMgr()->instance_difficulty & INSTANCE_FLAG_RAID_10_MEN_HEROIC )
  693. DifficultyScale = SPEED_SCALE_DIFF_10HEROIC;
  694. else if( _unit->GetMapMgr()->instance_difficulty & INSTANCE_FLAG_RAID_25_MEN )
  695. DifficultyScale = SPEED_SCALE_DIFF_25NORMAL;
  696. else if( _unit->GetMapMgr()->instance_difficulty & INSTANCE_FLAG_RAID_25_MEN_HEROIC )
  697. DifficultyScale = SPEED_SCALE_DIFF_25HEROIC;
  698.  
  699. _unit->GetAIInterface()->disable_melee = true;
  700. _unit->GetAIInterface()->m_canMove = false;
  701. _unit->GetAIInterface()->disable_combat = true;
  702. _unit->GetAIInterface()->disable_targeting = true;
  703. _unit->GetAIInterface()->setOutOfCombatRange( 700.0f * 700.0f ); //once we start combat we should try to not reset
  704.  
  705. RegisterAIUpdateEvent( 1000 );
  706. phase = 0;
  707.  
  708. //self root to not face the tank as we gain agro
  709. // _unit->CastSpell( _unit, 105451, true );
  710. }
  711. void AIUpdate()
  712. {
  713. //wait for some DPS
  714. if( _unit->GetHealthPct() > TENTACLE_START_FIGHT_HP_PCT )
  715. {
  716. return;
  717. }
  718. Unit *tank = _unit->GetAIInterface()->GetNextTarget();
  719. //try to get an alive player near us if we did not agro any
  720. if( tank == NULL )
  721. {
  722. InRangePlayerSetRecProt::iterator itr3;
  723. _unit->AquireInrangeLock(); //make sure to release lock before exit function !
  724. InrangeLoopExitAutoCallback AutoLock;
  725. float Radius = 70.0f * 70.0f;
  726. for( itr3 = _unit->GetInRangePlayerSetBegin( AutoLock ); itr3 != _unit->GetInRangePlayerSetEnd(); itr3++)
  727. {
  728. if( (*itr3)->isAlive() == false )
  729. continue;
  730. if( Distance2DSq( (*itr3)->GetPositionX(), (*itr3)->GetPositionY(), _unit->GetPositionX(), _unit->GetPositionY() ) > Radius )
  731. continue;
  732. tank = (*itr3);
  733. break;
  734. }
  735. _unit->ReleaseInrangeLock();
  736. }
  737. if( tank == NULL )
  738. {
  739. //stop spamming the server and let people port to us again
  740. if( phase != 0 )
  741. {
  742. DespawnEncounterSpawns( _unit, DespawnOldLimbEncounterDynamicEntries );
  743. _unit->SetHealth( _unit->GetMaxHealth() );
  744. }
  745. phase = 0;
  746. return;
  747. }
  748. uint32 TickNow = GetTickCount();
  749.  
  750. // Init phase
  751. if( phase == 0 )
  752. {
  753. phase = 1;
  754. CorruptionTimer = TickNow + 15000 + RandomUInt() % 25000;
  755. CorruptionCounter = 0;
  756. LimbTentacleTimer = TickNow + 25000 * DifficultyScale + RandomUInt() % 25000;
  757. LimbTentacleCounter = 0;
  758. RegenerativeBloodTimer = TickNow + 35000 * DifficultyScale + RandomUInt() % 25000;
  759. RegenerativeBloodCounter = 0;
  760. BurningBloodTimer = TickNow + 35000 * DifficultyScale + RandomUInt() % 25000;
  761. AlexStraszaCauterizeTimer = TickNow;
  762. ElementiumBoltTimer = TickNow + 5000 * DifficultyScale + RandomUInt() % 25000;
  763. ElementiumBoltCounter = 0;
  764. CorruptingParasiteTimer = TickNow + 10000 * DifficultyScale + RandomUInt() % 25000;
  765. CorruptingParasiteCounter = 0;
  766. _unit->SetHealth( _unit->GetMaxHealth() );
  767. }
  768. if( phase == 1 )
  769. {
  770. //only spawn on active platform
  771. int64 *LimbIndex = _unit->GetCreateIn64Extension( NPC_ID_LIMB0 );
  772. // int64 *AcctivePlatformIndex = _unit->GetMapMgr()->GetCreateIn64Extension( NPC_ID_MADNESS_VISUAL + MADNESS_INDEX_ACTIVE_PLATFORM );
  773. // if( *LimbIndex != *AcctivePlatformIndex )
  774. //////////////////////////////////////////////////
  775. //AOE dps
  776. if( BurningBloodTimer < TickNow )
  777. {
  778. //each lost health pct adds 100% dmg. Should scale up to 35000 DPS ( base is 350 )
  779. int32 BurningBloodDMGPCT = 100 * ( 101 - _unit->GetHealthPct() * DifficultyScale );
  780. float Radius = 70.0f * 70.0f;
  781. InRangePlayerSetRecProt::iterator itr3;
  782. _unit->AquireInrangeLock(); //make sure to release lock before exit function !
  783. InrangeLoopExitAutoCallback AutoLock;
  784. for( itr3 = _unit->GetInRangePlayerSetBegin( AutoLock ); itr3 != _unit->GetInRangePlayerSetEnd(); itr3++)
  785. {
  786. if( (*itr3)->isAlive() == false )
  787. continue;
  788.  
  789. if( Distance2DSq( (*itr3)->GetPositionX(), (*itr3)->GetPositionY(), _unit->GetPositionX(), _unit->GetPositionY() ) > Radius )
  790. continue;
  791.  
  792. SpellEntry *spellInfo = dbcSpell.LookupEntryForced( SPELL_ID_BURNING_BLOOD );
  793. Spell *spell = SpellPool.PooledNew( __FILE__, __LINE__ );
  794. spell->Init( _unit, spellInfo ,true, NULL);
  795. SpellCastTargets targets( (*itr3)->GetGUID() );
  796. spell->forced_pct_mod[0] = BurningBloodDMGPCT;
  797. spell->prepare(&targets);
  798. }
  799. _unit->ReleaseInrangeLock();
  800. BurningBloodTimer = TickNow + SPELL_COOL_BURNING_BLOOD; //needs to be fixed or it will not stack
  801. }
  802.  
  803.  
  804. //////////////////////////////////////////////////
  805. if( CorruptionTimer!= 0 && CorruptionTimer < TickNow )
  806. {
  807. Creature *c = _unit->GetMapMgr()->CreateCreature( NPC_ID_MUTATED_CORRUPTION, true, CorruptionLocations[*LimbIndex][0], CorruptionLocations[*LimbIndex][1], CorruptionLocations[*LimbIndex][2] );
  808. if( c )
  809. c->GetAIInterface()->AttackReaction( tank, 10, 0 );
  810. CorruptionTimer = 0;
  811. CorruptionCounter++;
  812. }
  813. //protection against imba DPS. Will flood events also
  814. else if( ShouldForceProc( _unit, CorruptionCounter, NPC_MINPROC_MUTATED_CORRUPTION, TENTACLE_START_FIGHT_HP_PCT ) )
  815. CorruptionTimer = 1;
  816.  
  817. //////////////////////////////////////////////////
  818. if( RegenerativeBloodTimer < TickNow )
  819. {
  820. int64 *ActiveBloodCount = _unit->GetMapMgr()->GetCreateIn64Extension( NPC_ID_REGENERATIVE_BLOOD );
  821. if( *ActiveBloodCount < LIMIT_SPAWN_COUNT_OF_SAME_TYPE )
  822. {
  823. // int64 *HemoTargetNPCGUID = _unit->GetMapMgr()->GetCreateIn64Extension( NPC_ID_HEMORRHAGE_VISUAL_LOC + *LimbIndex );
  824. // Creature *HemoTarget = _unit->GetMapMgr()->GetCreature( *HemoTargetNPCGUID );
  825. // if( HemoTarget )
  826. // HemoTarget->CastSpell( HemoTarget, SPELL_ID_HEMORRHAGE_VISUAL, true ); //we should have dedicated NPCs for these. They look like red circle on the ground
  827. //spawn a hemmorhage NPC that just marks the spawn location of the regenerative bloods
  828. // uint32 RegenerativeBloodSpawnCount = 6 / DifficultyScale; // [6,8]
  829. uint32 RegenerativeBloodSpawnCount = 4 / DifficultyScale; // [6,8]
  830. for( uint32 i=0;i<RegenerativeBloodSpawnCount;i++)
  831. {
  832. float RandX = 5.0f - ( RandomUInt() % 100 ) / 10.0f;
  833. float RandY = 5.0f - ( RandomUInt() % 100 ) / 10.0f;
  834. #ifndef TEMP_DISABLE_BLOOD_SAPWNS
  835. Creature *c = _unit->GetMapMgr()->CreateCreature( NPC_ID_REGENERATIVE_BLOOD, true, LimbTentacleLocations[*LimbIndex][0] + RandX, LimbTentacleLocations[*LimbIndex][1] + RandY, PlatformCenterLocations[*LimbIndex][2] );
  836. #endif
  837. *ActiveBloodCount += 1;
  838. }
  839. RegenerativeBloodCounter++;
  840. /*{
  841. char buff[500];
  842. sprintf( buff, "Debug MSG : Number of bloods %d, casts %d", (int32)(*ActiveBloodCount), RegenerativeBloodCounter );
  843. _unit->SendChatMessage( CHAT_MSG_MONSTER_PARTY, LANG_UNIVERSAL, buff );
  844. }*/
  845. }
  846. RegenerativeBloodTimer = TickNow + (NPC_COOL_REGENERATIVE_BLOOD + RandomUInt() % NPC_COOL_REGENERATIVE_BLOOD)*DifficultyScale;
  847. //do not spawn everything at the same time pls. Extend our spawn timer
  848. LimbTentacleTimer = MAX( TickNow + MIN( 10000, NPC_COOL_REGENERATIVE_BLOOD / 2 ), LimbTentacleTimer );
  849. }
  850. //protection against imba DPS. Will flood events also
  851. else if( ShouldForceProc( _unit, RegenerativeBloodCounter, NPC_MINPROC_REGENERATIVE_BLOOD, TENTACLE_START_FIGHT_HP_PCT ) )
  852. RegenerativeBloodTimer = 1;
  853.  
  854. //////////////////////////////////////////////////
  855. if( LimbTentacleTimer < TickNow ) //blistering tentactle
  856. {
  857. int64 *ActiveTentacleCount = _unit->GetMapMgr()->GetCreateIn64Extension( NPC_ID_BLISTERING_TENTACLE );
  858. if( *ActiveTentacleCount < LIMIT_SPAWN_COUNT_OF_SAME_TYPE )
  859. {
  860. // uint32 LimbTentacleSpawnCount = 7 / DifficultyScale; // [7,10]
  861. uint32 LimbTentacleSpawnCount = 5 / DifficultyScale; // [7,10]
  862. for( uint32 i=0;i<LimbTentacleSpawnCount;i++)
  863. {
  864. float RandX = 5.0f - ( RandomUInt() % 100 ) / 10.0f;
  865. float RandY = 5.0f - ( RandomUInt() % 100 ) / 10.0f;
  866. #ifndef TEMP_DISABLE_TENTACLE_SAPWNS
  867. Creature *c = _unit->GetMapMgr()->CreateCreature( NPC_ID_BLISTERING_TENTACLE, true, LimbTentacleLocations[*LimbIndex][0] + RandX, LimbTentacleLocations[*LimbIndex][1] + RandY, PlatformCenterLocations[*LimbIndex][2] );
  868. #endif
  869. *ActiveTentacleCount += 1;
  870. }
  871. LimbTentacleCounter++;
  872. /*{
  873. char buff[500];
  874. sprintf( buff, "Debug MSG : Number of tentacles %d, casts %d", (int32)(*ActiveTentacleCount), LimbTentacleCounter );
  875. _unit->SendChatMessage( CHAT_MSG_MONSTER_PARTY, LANG_UNIVERSAL, buff );
  876. }*/
  877. }
  878. LimbTentacleTimer = TickNow + (NPC_COOL_LIMB_TENTACLE + RandomUInt() % NPC_COOL_LIMB_TENTACLE)*DifficultyScale;
  879. //do not spawn everything at the same time pls
  880. RegenerativeBloodTimer = MAX( TickNow + MIN( 10000, NPC_COOL_LIMB_TENTACLE / 2 ), RegenerativeBloodTimer );
  881. }
  882. //protection against imba DPS. Will flood events also
  883. else if( ShouldForceProc( _unit, LimbTentacleCounter, NPC_MINPROC_LIMB_TENTACLE, TENTACLE_START_FIGHT_HP_PCT ) )
  884. LimbTentacleTimer = 1;
  885.  
  886. if( ElementiumBoltTimer < TickNow )
  887. {
  888. int64 *ActiveSpawnCount = _unit->GetMapMgr()->GetCreateIn64Extension( NPC_ID_ELEMENTIUM_BOLT );
  889. if( *ActiveSpawnCount < LIMIT_SPAWN_COUNT_OF_SAME_TYPE )
  890. {
  891. Creature *c = _unit->GetMapMgr()->CreateCreature( NPC_ID_ELEMENTIUM_BOLT, true, ElementiumBoltStart[ *LimbIndex ][0], ElementiumBoltStart[ *LimbIndex ][1], ElementiumBoltStart[ *LimbIndex ][2] );
  892. if( c )
  893. {
  894. int64 *MyLimIndex = c->GetCreateIn64Extension( NPC_ID_ELEMENTIUM_BOLT );
  895. *MyLimIndex = *LimbIndex;
  896. // c->GetAIInterface()->MoveTo( PlatformCenterLocations[ *LimbIndex ][0], PlatformCenterLocations[ *LimbIndex ][1], PlatformCenterLocations[ *LimbIndex ][2], 0.0f );
  897. }
  898. ElementiumBoltTimer = TickNow + (NPC_COOL_ELEMENTIUM_BOLT + RandomUInt() % NPC_COOL_ELEMENTIUM_BOLT)*DifficultyScale;
  899. ElementiumBoltCounter++;
  900. *ActiveSpawnCount += 1;
  901. }
  902. }
  903. else if( _unit->GetHealthPct() < 50 && ShouldForceProc( _unit, ElementiumBoltCounter, NPC_MINPROC_ELEMENTIUM_BOLT, TENTACLE_START_FIGHT_HP_PCT ) )
  904. ElementiumBoltTimer = 1;
  905.  
  906. if(
  907. #ifndef TEMP_DISABLE_REQ_HEROIC
  908. IS_HEROIC_INSTANCE_DIFFICULTIE( _unit->GetMapMgr()->instance_difficulty ) &&
  909. #endif
  910. CorruptingParasiteTimer < TickNow )
  911. {
  912. AI_Spell sp;
  913. sp.spelltargetType = TTYPE_ENEMY_FOR_BUFF;
  914. sp.minrange = 0.0f;
  915. sp.maxrange = 20.0f;
  916. sp.procChance = 100;
  917. sp.spell = dbcSpell.LookupEntryForced( SPELL_ID_CORRUPTING_PARASITE );
  918. Unit *t = _unit->GetAIInterface()->FindTargetForSpellTargetType( &sp );
  919. if( t )
  920. {
  921. _unit->CastSpell( t, SPELL_ID_CORRUPTING_PARASITE, false );
  922. CorruptingParasiteTimer = TickNow + (SPELL_COOL_CORRUPTING_PARASITE + RandomUInt() % SPELL_COOL_CORRUPTING_PARASITE)*DifficultyScale;
  923. CorruptingParasiteCounter++;
  924. }
  925. }
  926. else if( ShouldForceProc( _unit, CorruptingParasiteCounter, SPELL_MINPROC_CORRUPTING_PARASITE, TENTACLE_START_FIGHT_HP_PCT ) )
  927. CorruptingParasiteTimer = 1;
  928.  
  929. //get the tentacle of the active platform
  930. if( AlexStraszaCauterizeTimer < TickNow )
  931. {
  932. AlexStraszaCauterizeTimer = TickNow + SPELL_COOL_CAUTERIZE; //3% HP every X seconds
  933. uint32 RequiresPlatform = 0;
  934. int64 *CanActivePlatformIndex = _unit->GetMapMgr()->GetCreateIn64Extension( NPC_ID_MADNESS_VISUAL + MADNESS_INDEX_ACTIVE_PLATFORMS + RequiresPlatform );
  935. if( *CanActivePlatformIndex == 1 )
  936. {
  937. int64 *AspectGUID = _unit->GetMapMgr()->GetCreateIn64Extension( NPC_ID_ASPECT_ALEXSTRASZA );
  938. Creature *Aspect = _unit->GetMapMgr()->GetCreature( *AspectGUID );
  939. if( Aspect )
  940. {
  941. //cauterize the blistering tentacles and corrupted parasites
  942. InRangeSetRecProt::iterator itr,itr2;
  943. _unit->AquireInrangeLock(); //make sure to release lock before exit function !
  944. InrangeLoopExitAutoCallback AutoLock;
  945. for( itr2 = _unit->GetInRangeSetBegin( AutoLock ); itr2 != _unit->GetInRangeSetEnd();)
  946. {
  947. itr = itr2;
  948. itr2++; //maybe scripts can change list. Should use lock instead of this to prevent multiple changes. This protects to 1 deletion only
  949. if( (*itr)->IsCreature() == false || SafeUnitCast( *itr )->isAlive() == false )
  950. continue;
  951. if( (*itr)->GetEntry() == NPC_ID_BLISTERING_TENTACLE // NPC_ID_BLISTERING_TENTACLE
  952. || ( (*itr)->GetEntry() == NPC_ID_CORRUPTING_PARASITE )
  953. )
  954. {
  955. Aspect->CastSpell( SafeCreatureCast(*itr), SPELL_ID_CAUTERIZE, false );
  956. }
  957. }
  958. _unit->ReleaseInrangeLock();
  959. }
  960. }
  961. }
  962. }
  963. }
  964. void OnDied(Unit *mKiller)
  965. {
  966. RemoveAIUpdateEvent();
  967. //cast Agonizing Pain on deathwing
  968. int64 *MadnessGUID = _unit->GetMapMgr()->GetCreateIn64Extension( NPC_ID_MADNESS_VISUAL + MADNESS_INDEX_GUID_VISUAL );
  969. // *MadnessGUID = _unit->GetGUID();
  970. Creature *DW = _unit->GetMapMgr()->GetCreature( *MadnessGUID );
  971. if( DW )
  972. {
  973. DW->InterruptSpell( ); //in case he is channeling "cataclysm"
  974. // DW->CastSpell( DW, SPELL_ID_AGONIZING_PAIN, false );
  975. //loose 20% of health
  976. int32 HealthLost = -(int32)DW->GetMaxHealth() / 100 * MADNESS_LOOSE_HP_PCT_TENTACLE;
  977. DW->ModHealth( HealthLost );
  978. /*{
  979. char buff[500];
  980. sprintf( buff, "Debug MSG : Limb died. Madness GUID %d, health mod %d", (int32)(*MadnessGUID), HealthLost );
  981. _unit->SendChatMessage( CHAT_MSG_MONSTER_PARTY, LANG_UNIVERSAL, buff );
  982. }/**/
  983. }
  984. //mark that the limb on this platform is dead and there is no point to activate it anymore
  985. int64 *LimbIndex = _unit->GetCreateIn64Extension( NPC_ID_LIMB0 );
  986. int64 *CanActivePlatformIndex = _unit->GetMapMgr()->GetCreateIn64Extension( NPC_ID_MADNESS_VISUAL + MADNESS_INDEX_ACTIVE_PLATFORMS + *LimbIndex );
  987. *CanActivePlatformIndex = 0;
  988. //no need to block vision. Just begone
  989. _unit->Despawn( 1, 0 );
  990. }
  991. };
  992.  
  993. //sub spawn of limbs
  994. class BlisteringTentacle : public CreatureAIScript
  995. {
  996. public:
  997. ADD_CREATURE_FACTORY_FUNCTION(BlisteringTentacle);
  998.  
  999. BlisteringTentacle(Creature* pCreature) : CreatureAIScript(pCreature) { }
  1000. void OnLoad()
  1001. {
  1002. _unit->GetAIInterface()->m_canMove = false;
  1003. for(uint32 i=0;i<SCHOOL_COUNT;i++)
  1004. _unit->AoeDamageTakenPctMod[ i ] = 0.0f;
  1005. _unit->CastSpell( _unit, SPELL_ID_BLISTERING_HEAT, false );
  1006. }
  1007. void OnDied(Unit *mKiller)
  1008. {
  1009. //no need to block vision. Just begone
  1010. _unit->Despawn( 1, 0 );
  1011. int64 *ActiveSpawnCount = _unit->GetMapMgr()->GetCreateIn64Extension( _unit->GetEntry() );
  1012. *ActiveSpawnCount -= 1;
  1013. }
  1014. };
  1015.  
  1016. class MutatedCorruption : public CreatureAIScript
  1017. {
  1018. public:
  1019. ADD_CREATURE_FACTORY_FUNCTION(MutatedCorruption);
  1020.  
  1021. MutatedCorruption(Creature* pCreature) : CreatureAIScript(pCreature) { }
  1022. uint32 CrushTimer;
  1023. uint32 ImpaleTimer;
  1024. float DifficultyScale;
  1025. void OnLoad()
  1026. {
  1027. DifficultyScale = 1.0f;
  1028. if( _unit->GetMapMgr()->instance_difficulty & INSTANCE_FLAG_RAID_10_MEN_HEROIC )
  1029. DifficultyScale = SPEED_SCALE_DIFF_10HEROIC;
  1030. else if( _unit->GetMapMgr()->instance_difficulty & INSTANCE_FLAG_RAID_25_MEN )
  1031. DifficultyScale = SPEED_SCALE_DIFF_25NORMAL;
  1032. else if( _unit->GetMapMgr()->instance_difficulty & INSTANCE_FLAG_RAID_25_MEN_HEROIC )
  1033. DifficultyScale = SPEED_SCALE_DIFF_25HEROIC;
  1034.  
  1035. _unit->GetAIInterface()->m_canMove = false;
  1036. CrushTimer = SPELL_COOL_CRUSH;
  1037. ImpaleTimer = SPELL_COOL_IMPALE;
  1038.  
  1039. _unit->GetAIInterface()->setOutOfCombatRange( 120.0f * 120.0f ); //once we start combat we should try to not reset
  1040. RegisterAIUpdateEvent( 5000 );
  1041. }
  1042. void AIUpdate()
  1043. {
  1044. Unit *tank = _unit->GetAIInterface()->GetNextTarget();
  1045. if( tank == NULL )
  1046. {
  1047. return;
  1048. }
  1049. uint32 TickNow = GetTickCount();
  1050. if( CrushTimer < TickNow && _unit->isCasting() == false )
  1051. {
  1052. _unit->CastSpell( tank, SPELL_ID_CRUSH, false );
  1053. CrushTimer = TickNow + (SPELL_COOL_CRUSH + RandomUInt() % SPELL_COOL_CRUSH)*DifficultyScale;
  1054. }
  1055. if( ImpaleTimer < TickNow && _unit->isCasting() == false )
  1056. {
  1057. _unit->CastSpell( tank, SPELL_ID_IMPALE, false );
  1058. ImpaleTimer = TickNow + (SPELL_COOL_IMPALE + RandomUInt() % SPELL_COOL_IMPALE)*DifficultyScale;
  1059. }
  1060. }
  1061. void OnDied(Unit *mKiller)
  1062. {
  1063. RemoveAIUpdateEvent();
  1064. }
  1065. };
  1066.  
  1067. class RegenerativeBlood : public CreatureAIScript
  1068. {
  1069. public:
  1070. ADD_CREATURE_FACTORY_FUNCTION(RegenerativeBlood);
  1071.  
  1072. RegenerativeBlood(Creature* pCreature) : CreatureAIScript(pCreature) { }
  1073. void OnLoad()
  1074. {
  1075. //proc on attack
  1076. SpellEntry *sp = dbcSpell.LookupEntryForced( SPELL_ID_DEGENRATIVE_BITE ); //Degenerative Bite
  1077. ProcTriggerSpell pts( sp, NULL );
  1078. pts.caster = _unit->GetGUID();
  1079. pts.spellId = sp->Id;
  1080. pts.procFlags = PROC_ON_MELEE_ATTACK;
  1081. pts.created_with_value = sp->eff[0].EffectBasePoints + 1;
  1082. pts.procCharges = 0;
  1083. pts.procChance = 100;
  1084. pts.procInterval = SPELL_COOL_DEGENRATIVE_BITE;
  1085. _unit->RegisterScriptProcStruct( pts );
  1086.  
  1087. _unit->PctPowerRegenModifier[POWER_TYPE_MANA] = 0.0f;
  1088.  
  1089. _unit->SetPower( POWER_TYPE_MANA, 0 );
  1090. _unit->SetPowerType( POWER_TYPE_MANA );
  1091. _unit->SetMaxPower( POWER_TYPE_MANA, 100 );
  1092. RegisterAIUpdateEvent( SPELL_COOL_REGENERATIVE );
  1093. }
  1094. void AIUpdate()
  1095. {
  1096. _unit->ModPower( POWER_TYPE_MANA, 10 );
  1097. // _unit->UpdatePowerAmm( true, POWER_TYPE_MANA );
  1098. if( _unit->GetPower( POWER_TYPE_MANA ) == 100 )
  1099. {
  1100. _unit->SetPower( POWER_TYPE_MANA, 0 );
  1101. _unit->CastSpell( _unit, SPELL_ID_REGENERATIVE, false ); //self heal to max
  1102. }
  1103. }
  1104. void OnDied(Unit *mKiller)
  1105. {
  1106. RemoveAIUpdateEvent();
  1107. //no need to block vision. Just begone
  1108. _unit->Despawn( 1, 0 );
  1109. int64 *ActiveSpawnCount = _unit->GetMapMgr()->GetCreateIn64Extension( _unit->GetEntry() );
  1110. *ActiveSpawnCount -= 1;
  1111. }
  1112. };
  1113.  
  1114. class CorruptingParasite : public CreatureAIScript
  1115. {
  1116. public:
  1117. ADD_CREATURE_FACTORY_FUNCTION(CorruptingParasite);
  1118.  
  1119. CorruptingParasite(Creature* pCreature) : CreatureAIScript(pCreature) { }
  1120. void OnLoad()
  1121. {
  1122. //cast backlash
  1123. _unit->CastSpell( _unit, SPELL_ID_CORRUPTING_PARASITE_BACKLASH, true );
  1124. RegisterAIUpdateEvent( SPELL_COOL_UNSTABLE_CORRUPTION );
  1125. }
  1126. void AIUpdate()
  1127. {
  1128. SpellEntry *spellInfo = dbcSpell.LookupEntryForced( SPELL_ID_UNSTABLE_CORRUPTION );
  1129. Spell *spell = SpellPool.PooledNew( __FILE__, __LINE__ );
  1130. spell->Init( _unit, spellInfo ,true, NULL);
  1131. SpellCastTargets targets( _unit->GetGUID() );
  1132. spell->forced_basepoints[0] = spellInfo->eff[0].EffectBasePoints * _unit->GetHealth() / 100; //with 6M health this does 600k dmg / tick ? :O
  1133. spell->prepare(&targets);
  1134. }
  1135. void OnDied(Unit *mKiller)
  1136. {
  1137. RemoveAIUpdateEvent();
  1138. }
  1139. };
  1140.  
  1141. class ElementiumBolt : public CreatureAIScript
  1142. {
  1143. public:
  1144. ADD_CREATURE_FACTORY_FUNCTION(ElementiumBolt);
  1145.  
  1146. ElementiumBolt(Creature* pCreature) : CreatureAIScript(pCreature) { }
  1147. uint8 phase;
  1148. uint32 StartMoveTimer;
  1149. uint32 ElementiumPulseTick;
  1150. void OnLoad()
  1151. {
  1152. _unit->m_walkSpeed = 2.5f ;
  1153. _unit->m_runSpeed = _unit->m_walkSpeed;
  1154. _unit->m_base_runSpeed = _unit->m_runSpeed;
  1155. _unit->m_base_walkSpeed = _unit->m_walkSpeed;
  1156. _unit->m_flySpeed = _unit->m_walkSpeed;
  1157. _unit->m_backFlySpeed = 4.5f / 2;
  1158. _unit->m_backWalkSpeed = 4.5f / 2; // this should really be named m_backRunSpeed
  1159. _unit->m_swimSpeed = 4.722222f / 2;
  1160. _unit->m_backSwimSpeed = 2.5f / 2;
  1161. _unit->m_turnRate = 3.141593f / 2;
  1162. _unit->m_pitchRate = 3.141593f / 2;
  1163.  
  1164. _unit->GetAIInterface()->disable_melee = true;
  1165. _unit->GetAIInterface()->disable_combat = true;
  1166. _unit->GetAIInterface()->disable_targeting = true;
  1167. RegisterAIUpdateEvent( 1000 );
  1168. StartMoveTimer = GetTickCount() + 5000;
  1169. phase = 0;
  1170. ElementiumPulseTick = 0;
  1171. }
  1172. void AIUpdate()
  1173. {
  1174. if( phase == 0 )
  1175. {
  1176. if( StartMoveTimer != 0 )
  1177. {
  1178. if( StartMoveTimer < GetTickCount() )
  1179. {
  1180. int64 *MyLimIndex = _unit->GetCreateIn64Extension( NPC_ID_ELEMENTIUM_BOLT );
  1181. _unit->GetAIInterface()->MoveTo( PlatformCenterLocations[ *MyLimIndex ][0], PlatformCenterLocations[ *MyLimIndex ][1], PlatformCenterLocations[ *MyLimIndex ][2], 0.0f );
  1182. StartMoveTimer = 0;
  1183. }
  1184. else
  1185. {
  1186. return;
  1187. }
  1188. }
  1189.  
  1190. //we are getting updated but we did not even started moving
  1191. if( _unit->GetAIInterface()->m_creatureState == STOPPED )
  1192. phase = 1;
  1193. }
  1194. else if( phase == 1 )
  1195. {
  1196. _unit->CastSpell( _unit, SPELL_ID_ELEMNTIUM_BLAST, false ); //AOE
  1197. phase = 2;
  1198. ElementiumPulseTick = GetTickCount() + SPELL_COOL_ELEMNTIUM_BLAST;
  1199. }
  1200. else if( phase == 2 )
  1201. {
  1202. uint32 TickNow = GetTickCount();
  1203. if( ElementiumPulseTick < TickNow )
  1204. {
  1205. _unit->CastSpell( _unit, SPELL_ID_ELEMNTIUM_BLAST_PULSE, false ); //AOE pulse until destroyed
  1206. ElementiumPulseTick = TickNow + SPELL_COOL_ELEMNTIUM_BLAST;
  1207. }
  1208. }
  1209.  
  1210. }
  1211. void OnDied(Unit *mKiller)
  1212. {
  1213. RemoveAIUpdateEvent();
  1214. //no need to block vision. Just begone
  1215. _unit->Despawn( 1, 0 );
  1216. int64 *ActiveSpawnCount = _unit->GetMapMgr()->GetCreateIn64Extension( _unit->GetEntry() );
  1217. *ActiveSpawnCount -= 1;
  1218. }
  1219. };
  1220.  
  1221. class CongealingBlood : public CreatureAIScript
  1222. {
  1223. public:
  1224. ADD_CREATURE_FACTORY_FUNCTION(CongealingBlood);
  1225.  
  1226. CongealingBlood(Creature* pCreature) : CreatureAIScript(pCreature) { }
  1227. void OnLoad()
  1228. {
  1229. _unit->m_walkSpeed = 1.2f ;
  1230. _unit->m_runSpeed = _unit->m_walkSpeed;
  1231. _unit->m_base_runSpeed = _unit->m_runSpeed;
  1232. _unit->m_base_walkSpeed = _unit->m_walkSpeed;
  1233. _unit->m_flySpeed = _unit->m_walkSpeed;
  1234. _unit->m_backFlySpeed = 4.5f / 2;
  1235. _unit->m_backWalkSpeed = 4.5f / 2; // this should really be named m_backRunSpeed
  1236. _unit->m_swimSpeed = 4.722222f / 2;
  1237. _unit->m_backSwimSpeed = 2.5f / 2;
  1238. _unit->m_turnRate = 3.141593f / 2;
  1239. _unit->m_pitchRate = 3.141593f / 2;
  1240. _unit->GetAIInterface()->disable_melee = true;
  1241. _unit->GetAIInterface()->disable_combat = true;
  1242. _unit->GetAIInterface()->disable_targeting = true;
  1243. RegisterAIUpdateEvent( 3000 );
  1244. }
  1245. void AIUpdate()
  1246. {
  1247. int64 *MadnessGUID = _unit->GetMapMgr()->GetCreateIn64Extension( NPC_ID_MADNESS_ATTACKTARGET );
  1248. Creature *DW = _unit->GetMapMgr()->GetCreature( *MadnessGUID );
  1249. if( DW == NULL )
  1250. return;
  1251. //always try to move closer
  1252. if( _unit->GetAIInterface()->m_creatureState == STOPPED )
  1253. _unit->GetAIInterface()->MoveTo( DW->GetPositionX(), DW->GetPositionY(), -6.1f, 0.0f );
  1254. //if we reach owner we heal him 1% HP and suicide
  1255. if( DW->GetDistance2dSq( _unit ) < 5.0f*5.0f )
  1256. {
  1257. uint32 PCT1HP = DW->GetMaxHealth() * 1 / 100;
  1258. if( DW->isAlive() )
  1259. _unit->Heal( DW, SPELL_ID_CONGEALING_BLOOD_HEAL, PCT1HP );
  1260. RemoveAIUpdateEvent();
  1261. _unit->Despawn( 1, 0 );
  1262. }
  1263. }
  1264. void OnDied(Unit *mKiller)
  1265. {
  1266. RemoveAIUpdateEvent();
  1267. int64 *ActiveSpawnCount = _unit->GetMapMgr()->GetCreateIn64Extension( _unit->GetEntry() );
  1268. *ActiveSpawnCount -= 1;
  1269. }
  1270. };
  1271.  
  1272. //periodically cast shrapnel at a nearby player
  1273. class ElementiumFragment : public CreatureAIScript
  1274. {
  1275. public:
  1276. ADD_CREATURE_FACTORY_FUNCTION(ElementiumFragment);
  1277.  
  1278. uint32 ShrapnelTimer;
  1279. float DifficultyScale;
  1280. ElementiumFragment(Creature* pCreature) : CreatureAIScript(pCreature) { }
  1281. void OnLoad()
  1282. {
  1283. DifficultyScale = 1.0f;
  1284. if( _unit->GetMapMgr()->instance_difficulty & INSTANCE_FLAG_RAID_10_MEN_HEROIC )
  1285. DifficultyScale = SPEED_SCALE_DIFF_10HEROIC;
  1286. else if( _unit->GetMapMgr()->instance_difficulty & INSTANCE_FLAG_RAID_25_MEN )
  1287. DifficultyScale = SPEED_SCALE_DIFF_25NORMAL;
  1288. else if( _unit->GetMapMgr()->instance_difficulty & INSTANCE_FLAG_RAID_25_MEN_HEROIC )
  1289. DifficultyScale = SPEED_SCALE_DIFF_25HEROIC;
  1290. _unit->GetAIInterface()->m_canMove = false;
  1291. ShrapnelTimer = 0;
  1292. RegisterAIUpdateEvent( 5000 );
  1293. }
  1294. void AIUpdate()
  1295. {
  1296. Unit *tank = _unit->GetAIInterface()->GetNextTarget();
  1297. if( tank == NULL )
  1298. {
  1299. ShrapnelTimer = SPELL_COOL_SHRAPNEL;
  1300. return;
  1301. }
  1302. uint32 TickNow = GetTickCount();
  1303. if( ShrapnelTimer - 7000 < TickNow && ShrapnelTimer > TickNow && _unit->isCasting() == false )
  1304. {
  1305. _unit->CastSpell( tank, SPELL_ID_SHRAPNEL_TARGETED, false );
  1306. }
  1307. else if( ShrapnelTimer < TickNow && _unit->isCasting() == false )
  1308. {
  1309. _unit->CastSpell( tank, SPELL_ID_SHRAPNEL_DMG, false );
  1310. ShrapnelTimer = TickNow + (SPELL_COOL_SHRAPNEL + RandomUInt() % SPELL_COOL_SHRAPNEL)*DifficultyScale;
  1311. }
  1312. }
  1313. void OnDied(Unit *mKiller)
  1314. {
  1315. RemoveAIUpdateEvent();
  1316. int64 *ActiveSpawnCount = _unit->GetMapMgr()->GetCreateIn64Extension( _unit->GetEntry() );
  1317. *ActiveSpawnCount -= 1;
  1318. }
  1319. };
  1320.  
  1321. //large melee dmg
  1322. class ElementiumTerror : public CreatureAIScript
  1323. {
  1324. public:
  1325. ADD_CREATURE_FACTORY_FUNCTION(ElementiumTerror);
  1326.  
  1327. ElementiumTerror(Creature* pCreature) : CreatureAIScript(pCreature) { }
  1328. void OnLoad()
  1329. {
  1330. //proc on attack
  1331. SpellEntry *sp = dbcSpell.LookupEntryForced( SPELL_ID_TETANUS ); //Degenerative Bite
  1332. ProcTriggerSpell pts( sp, NULL );
  1333. pts.caster = _unit->GetGUID();
  1334. pts.spellId = sp->Id;
  1335. pts.procFlags = PROC_ON_MELEE_ATTACK;
  1336. pts.created_with_value = sp->eff[0].EffectBasePoints + 1;
  1337. pts.procCharges = 0;
  1338. pts.procChance = 100;
  1339. pts.procInterval = SPELL_COOL_TETANUS;
  1340. _unit->RegisterScriptProcStruct( pts );
  1341. }
  1342. void AIUpdate()
  1343. {
  1344. }
  1345. void OnDied(Unit *mKiller)
  1346. {
  1347. RemoveAIUpdateEvent();
  1348. int64 *ActiveSpawnCount = _unit->GetMapMgr()->GetCreateIn64Extension( _unit->GetEntry() );
  1349. *ActiveSpawnCount -= 1;
  1350. }
  1351. };
  1352.  
  1353. class AspectAIGeneric : public CreatureAIScript
  1354. {
  1355. public:
  1356. ADD_CREATURE_FACTORY_FUNCTION(AspectAIGeneric);
  1357.  
  1358. AspectAIGeneric(Creature* pCreature) : CreatureAIScript(pCreature) { }
  1359. uint32 CastSpell1,CastSpell2;
  1360. uint32 RequiresPlatform;
  1361. void OnLoad()
  1362. {
  1363. _unit->GetAIInterface()->disable_melee = true;
  1364. _unit->GetAIInterface()->disable_combat = true;
  1365. _unit->GetAIInterface()->disable_targeting = true;
  1366. _unit->bInvincible = true;
  1367. _unit->GetAIInterface()->m_moveFly = true;
  1368. //aura that will buff nearby players
  1369. CastSpell1 = CastSpell2 = 0;
  1370. RequiresPlatform = MADNESSPLATFORM_COUNT + 1;
  1371. if( _unit->GetEntry() == NPC_ID_ASPECT_ALEXSTRASZA )
  1372. {
  1373. CastSpell1 = SPELL_ID_ALEXTRASZA_PRESENCE;
  1374. RequiresPlatform = 0;
  1375. }
  1376. else if( _unit->GetEntry() == NPC_ID_ASPECT_NOZDORMU )
  1377. {
  1378. CastSpell1 = SPELL_ID_NOZDORMU_PRESENCE;
  1379. RequiresPlatform = 1;
  1380. }
  1381. else if( _unit->GetEntry() == NPC_ID_ASPECT_YSERA )
  1382. {
  1383. CastSpell1 = SPELL_ID_YSERA_PRESENCE;
  1384. CastSpell2 = SPELL_ID_ENTER_THE_DREAM;
  1385. RequiresPlatform = 2;
  1386. }
  1387. else if( _unit->GetEntry() == NPC_ID_ASPECT_KALECGOS )
  1388. {
  1389. CastSpell1 = SPELL_ID_KALECGOS_PRESENCE;
  1390. CastSpell2 = SPELL_ID_SPELLWEAVING;
  1391. RequiresPlatform = 3;
  1392. }
  1393. else if( _unit->GetEntry() == NPC_ID_ASPECT_THRALL ) //thrall
  1394. {
  1395. // CastSpell1 = SPELL_ID_CARRYING_WINDS;
  1396. RequiresPlatform = MADNESSPLATFORM_COUNT + 1;
  1397. }
  1398. //do not unload us until map gets destroyed to not go out of range :(
  1399. // _unit->GetMapMgr()->PushStaticObject( _unit );
  1400. // _unit->static_object = true; //do not go out of visual range
  1401. _unit->GetAIInterface()->setOutOfCombatRange( 700.0f * 700.0f );
  1402. RegisterAIUpdateEvent( 5000 ); //less then the duration of the presence spell
  1403. }
  1404. void AIUpdate()
  1405. {
  1406. if( RequiresPlatform < MADNESSPLATFORM_COUNT )
  1407. {
  1408. int64 *CanActivePlatformIndex = _unit->GetMapMgr()->GetCreateIn64Extension( NPC_ID_MADNESS_VISUAL + MADNESS_INDEX_ACTIVE_PLATFORMS + RequiresPlatform );
  1409. if( *CanActivePlatformIndex == 0 )
  1410. return;
  1411. }
  1412. InRangePlayerSetRecProt::iterator itr2;
  1413. _unit->AquireInrangeLock(); //make sure to release lock before exit function !
  1414. InrangeLoopExitAutoCallback AutoLock;
  1415. for( itr2 = _unit->GetInRangePlayerSetBegin( AutoLock ); itr2 != _unit->GetInRangePlayerSetEnd(); itr2++)
  1416. {
  1417. if( (*itr2)->isAlive() == false )
  1418. continue;
  1419. float dist = (*itr2)->GetDistance2dSq( _unit );
  1420. if( dist > (700.0f * 700.0f) )
  1421. continue;
  1422. if( CastSpell1 )
  1423. _unit->CastSpell( (*itr2), CastSpell1, true );
  1424. if( CastSpell2 )
  1425. _unit->CastSpell( (*itr2), CastSpell2, true );
  1426. }
  1427. _unit->ReleaseInrangeLock();
  1428. }
  1429. void OnDied(Unit *mKiller)
  1430. {
  1431. RemoveAIUpdateEvent();
  1432. }
  1433. };
  1434.  
  1435. void DeathwingMadnessPlatformAreatriggers(Player * pPlayer, uint32 AreaTrigger)
  1436. {
  1437. /* 7412 - left areatrigger fall in abyss
  1438. 7110, 7315
  1439. 7111 - back to 7110
  1440. 7112, 7317
  1441. 7113, 7318 - back to 7112
  1442. 7114, 7319
  1443. 7115, 7320 - back to 7114
  1444. */
  1445.  
  1446. bool DoJump = false;
  1447. float m_destX;
  1448. float m_destY;
  1449. float m_destZ;
  1450. switch(AreaTrigger)
  1451. {
  1452. case 7412:
  1453. {
  1454. pPlayer->SafeTeleport( pPlayer->GetMapId(), pPlayer->GetInstanceID(), -12128.0f, 12181.0f, 2.0f, 5.50f );
  1455. }break;
  1456. case 7110:
  1457. // case 7315: //land trigger
  1458. {
  1459. m_destX = -12028.0f;
  1460. m_destY = 12229.0f;
  1461. m_destZ = -6.0f;
  1462. DoJump = true;
  1463. } break;
  1464. case 7111:
  1465. // case 7316: //land trigger
  1466. {
  1467. m_destX = -11967.0f;
  1468. m_destY = 12262.0f;
  1469. m_destZ = 2.0f;
  1470. DoJump = true;
  1471. } break;
  1472. case 7112:
  1473. // case 7317: //land trigger
  1474. {
  1475. m_destX = -12089.0f;
  1476. m_destY = 12163.0f;
  1477. m_destZ = -2.0f;
  1478. DoJump = true;
  1479. } break;
  1480. case 7113:
  1481. // case 7318: //land trigger
  1482. {
  1483. m_destX = -12047.0f;
  1484. m_destY = 12210.0f;
  1485. m_destZ = -5.0f;
  1486. DoJump = true;
  1487. } break;
  1488. case 7114:
  1489. // case 7319: //land trigger
  1490. {
  1491. m_destX = -12117.0f;
  1492. m_destY = 12085.0f;
  1493. m_destZ = 3.0f;
  1494. DoJump = true;
  1495. } break;
  1496. case 7115:
  1497. // case 7320: //land trigger
  1498. {
  1499. m_destX = -12101.0f;
  1500. m_destY = 12149.0f;
  1501. m_destZ = -2.0f;
  1502. DoJump = true;
  1503. } break;
  1504. }
  1505. if( DoJump == true )
  1506. {
  1507. float radius = sqrt( Distance2DSq( pPlayer->GetPositionX(), pPlayer->GetPositionY(), m_destX, m_destY ) );
  1508. float speed = 137.0f / 15.0f; //well this is just 1 example from blizz :p
  1509. uint32 timetofly = (uint32)(radius * speed);
  1510. float raise_mob_to_height = radius * 2.5f; //no idea about this value, should be parabolic parameter some sort
  1511. pPlayer->SpeedCheatDelay( radius * 1000 / speed + MIN( 5000, pPlayer->GetSession()->GetLatency() ) + 2000 ); //should start sampling again after we land
  1512. pPlayer->GetAIInterface()->SendMoveToPacket( m_destX, m_destY, m_destZ, 0.0f, timetofly, MONSTER_MOVE_FLAG_HEROIC_LEAP, raise_mob_to_height );
  1513. pPlayer->CastSpell( pPlayer, SPELL_ID_CARRYING_WINDS, true ); //comes from Thrall
  1514. }
  1515. }
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement