TrinityCore
Loading...
Searching...
No Matches
boss_shade_of_aran.cpp
Go to the documentation of this file.
1/*
2 * This file is part of the TrinityCore Project. See AUTHORS file for Copyright information
3 *
4 * This program is free software; you can redistribute it and/or modify it
5 * under the terms of the GNU General Public License as published by the
6 * Free Software Foundation; either version 2 of the License, or (at your
7 * option) any later version.
8 *
9 * This program is distributed in the hope that it will be useful, but WITHOUT
10 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
11 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
12 * more details.
13 *
14 * You should have received a copy of the GNU General Public License along
15 * with this program. If not, see <http://www.gnu.org/licenses/>.
16 */
17
18/* ScriptData
19SDName: Boss_Shade_of_Aran
20SD%Complete: 95
21SDComment: Flame wreath missing cast animation, mods won't triggere.
22SDCategory: Karazhan
23EndScriptData */
24
25#include "ScriptMgr.h"
26#include "karazhan.h"
27#include "InstanceScript.h"
28#include "GameObject.h"
29#include "ObjectAccessor.h"
30#include "ScriptedCreature.h"
31#include "SpellInfo.h"
32#include "TemporarySummon.h"
33
76
83
85{
86public:
87 boss_shade_of_aran() : CreatureScript("boss_shade_of_aran") { }
88
89 CreatureAI* GetAI(Creature* creature) const override
90 {
91 return GetKarazhanAI<boss_aranAI>(creature);
92 }
93
94 struct boss_aranAI : public ScriptedAI
95 {
96 boss_aranAI(Creature* creature) : ScriptedAI(creature)
97 {
98 Initialize();
99 instance = creature->GetInstanceScript();
100 }
101
103 {
104 SecondarySpellTimer = 5000;
105 NormalCastTimer = 0;
106 SuperCastTimer = 35000;
107 BerserkTimer = 720000;
108 CloseDoorTimer = 15000;
109
110 LastSuperSpell = rand32() % 3;
111
114
116 ArcaneCooldown = 0;
117 FireCooldown = 0;
118 FrostCooldown = 0;
119
120 DrinkInterruptTimer = 10000;
121
122 ElementalsSpawned = false;
123 Drinking = false;
124 DrinkInturrupted = false;
125 }
126
128
133 uint32 CloseDoorTimer; // Don't close the door right on aggro in case some people are still entering.
134
136
140 float FWTargPosX[3];
141 float FWTargPosY[3];
142
147
149
153
154 void Reset() override
155 {
156 Initialize();
157
158 // Not in progress
161 }
162
163 void KilledUnit(Unit* /*victim*/) override
164 {
165 Talk(SAY_KILL);
166 }
167
168 void JustDied(Unit* /*killer*/) override
169 {
171
174 }
175
183
185 {
186 std::vector<Unit*> targets;
187 //store the threat list in a different container
188 for (auto* ref : me->GetThreatManager().GetUnsortedThreatList())
189 {
190 Unit* target = ref->GetVictim();
191 if (ref->GetVictim()->GetTypeId() == TYPEID_PLAYER && ref->GetVictim()->IsAlive())
192 targets.push_back(target);
193 }
194
195 //cut down to size if we have more than 3 targets
196 while (targets.size() > 3)
197 targets.erase(targets.begin() + rand32() % targets.size());
198
199 uint32 i = 0;
200 for (std::vector<Unit*>::const_iterator itr = targets.begin(); itr!= targets.end(); ++itr)
201 {
202 if (*itr)
203 {
204 FlameWreathTarget[i] = (*itr)->GetGUID();
205 FWTargPosX[i] = (*itr)->GetPositionX();
206 FWTargPosY[i] = (*itr)->GetPositionY();
207 DoCast((*itr), SPELL_FLAME_WREATH, true);
208 ++i;
209 }
210 }
211 }
212
213 void UpdateAI(uint32 diff) override
214 {
215 if (!UpdateVictim())
216 return;
217
218 if (CloseDoorTimer)
219 {
220 if (CloseDoorTimer <= diff)
221 {
223 CloseDoorTimer = 0;
224 } else CloseDoorTimer -= diff;
225 }
226
227 //Cooldowns for casts
228 if (ArcaneCooldown)
229 {
230 if (ArcaneCooldown >= diff)
231 ArcaneCooldown -= diff;
232 else ArcaneCooldown = 0;
233 }
234
235 if (FireCooldown)
236 {
237 if (FireCooldown >= diff)
238 FireCooldown -= diff;
239 else FireCooldown = 0;
240 }
241
242 if (FrostCooldown)
243 {
244 if (FrostCooldown >= diff)
245 FrostCooldown -= diff;
246 else FrostCooldown = 0;
247 }
248
250 {
251 Drinking = true;
253
255
256 if (!DrinkInturrupted)
257 {
258 DoCast(me, SPELL_MASS_POLY, true);
259 DoCast(me, SPELL_CONJURE, false);
260 DoCast(me, SPELL_DRINK, false);
262 DrinkInterruptTimer = 10000;
263 }
264 }
265
266 //Drink Interrupt
268 {
269 Drinking = false;
273 DoCast(me, SPELL_POTION, false);
274 }
275
276 //Drink Interrupt Timer
278 {
279 if (DrinkInterruptTimer >= diff)
280 DrinkInterruptTimer -= diff;
281 else
282 {
284 DoCast(me, SPELL_POTION, true);
286 DrinkInturrupted = true;
287 Drinking = false;
288 }
289 }
290
291 //Don't execute any more code if we are drinking
292 if (Drinking)
293 return;
294
295 //Normal casts
296 if (NormalCastTimer <= diff)
297 {
298 if (!me->IsNonMeleeSpellCast(false))
299 {
300 Unit* target = SelectTarget(SelectTargetMethod::Random, 0, 100, true);
301 if (!target)
302 return;
303
304 uint32 Spells[3];
305 uint8 AvailableSpells = 0;
306
307 //Check for what spells are not on cooldown
308 if (!ArcaneCooldown)
309 {
310 Spells[AvailableSpells] = SPELL_ARCMISSLE;
311 ++AvailableSpells;
312 }
313 if (!FireCooldown)
314 {
315 Spells[AvailableSpells] = SPELL_FIREBALL;
316 ++AvailableSpells;
317 }
318 if (!FrostCooldown)
319 {
320 Spells[AvailableSpells] = SPELL_FROSTBOLT;
321 ++AvailableSpells;
322 }
323
324 //If no available spells wait 1 second and try again
325 if (AvailableSpells)
326 {
327 CurrentNormalSpell = Spells[rand32() % AvailableSpells];
328 DoCast(target, CurrentNormalSpell);
329 }
330 }
331 NormalCastTimer = 1000;
332 } else NormalCastTimer -= diff;
333
334 if (SecondarySpellTimer <= diff)
335 {
336 switch (urand(0, 1))
337 {
338 case 0:
340 break;
341 case 1:
342 if (Unit* target = SelectTarget(SelectTargetMethod::Random, 0, 100, true))
343 DoCast(target, SPELL_CHAINSOFICE);
344 break;
345 }
346 SecondarySpellTimer = urand(5000, 20000);
347 } else SecondarySpellTimer -= diff;
348
349 if (SuperCastTimer <= diff)
350 {
351 uint8 Available[2];
352
353 switch (LastSuperSpell)
354 {
355 case SUPER_AE:
356 Available[0] = SUPER_FLAME;
357 Available[1] = SUPER_BLIZZARD;
358 break;
359 case SUPER_FLAME:
360 Available[0] = SUPER_AE;
361 Available[1] = SUPER_BLIZZARD;
362 break;
363 case SUPER_BLIZZARD:
364 Available[0] = SUPER_FLAME;
365 Available[1] = SUPER_AE;
366 break;
367 default:
368 Available[0] = 0;
369 Available[1] = 0;
370 break;
371 }
372
373 LastSuperSpell = Available[urand(0, 1)];
374
375 switch (LastSuperSpell)
376 {
377 case SUPER_AE:
379
381 DoCast(me, SPELL_PLAYERPULL, true);
382 DoCast(me, SPELL_MASSSLOW, true);
383 DoCast(me, SPELL_AEXPLOSION, false);
384 break;
385
386 case SUPER_FLAME:
388
389 FlameWreathTimer = 20000;
391
395
397 break;
398
399 case SUPER_BLIZZARD:
401
402 if (Creature* pSpawn = me->SummonCreature(CREATURE_ARAN_BLIZZARD, 0.0f, 0.0f, 0.0f, 0.0f, TEMPSUMMON_TIMED_DESPAWN, 25s))
403 {
404 pSpawn->SetFaction(me->GetFaction());
405 pSpawn->CastSpell(pSpawn, SPELL_CIRCULAR_BLIZZARD, false);
406 }
407 break;
408 }
409
410 SuperCastTimer = urand(35000, 40000);
411 } else SuperCastTimer -= diff;
412
414 {
415 ElementalsSpawned = true;
416
417 for (uint32 i = 0; i < 4; ++i)
418 {
419 if (Creature* unit = me->SummonCreature(CREATURE_WATER_ELEMENTAL, 0.0f, 0.0f, 0.0f, 0.0f, TEMPSUMMON_TIMED_DESPAWN, 90s))
420 {
421 unit->Attack(me->GetVictim(), true);
422 unit->SetFaction(me->GetFaction());
423 }
424 }
425
427 }
428
429 if (BerserkTimer <= diff)
430 {
431 for (uint32 i = 0; i < 5; ++i)
432 {
434 {
435 unit->Attack(me->GetVictim(), true);
436 unit->SetFaction(me->GetFaction());
437 }
438 }
439
441
442 BerserkTimer = 60000;
443 } else BerserkTimer -= diff;
444
445 //Flame Wreath check
447 {
448 if (FlameWreathTimer >= diff)
449 FlameWreathTimer -= diff;
450 else FlameWreathTimer = 0;
451
452 if (FlameWreathCheckTime <= diff)
453 {
454 for (uint8 i = 0; i < 3; ++i)
455 {
456 if (!FlameWreathTarget[i])
457 continue;
458
460 if (unit && !unit->IsWithinDist2d(FWTargPosX[i], FWTargPosY[i], 3))
461 {
462 unit->CastSpell(unit, 20476, me->GetGUID());
463 unit->CastSpell(unit, 11027, true);
465 }
466 }
468 } else FlameWreathCheckTime -= diff;
469 }
470
473 }
474
475 void DamageTaken(Unit* /*pAttacker*/, uint32& damage, DamageEffectType /*damageType*/, SpellInfo const* /*spellInfo = nullptr*/) override
476 {
477 if (!DrinkInturrupted && Drinking && damage)
478 DrinkInturrupted = true;
479 }
480
481 void SpellHit(WorldObject* /*caster*/, SpellInfo const* spellInfo) override
482 {
483 //We only care about interrupt effects and only if they are durring a spell currently being cast
484 if (!spellInfo->HasEffect(SPELL_EFFECT_INTERRUPT_CAST) || !me->IsNonMeleeSpellCast(false))
485 return;
486
487 //Interrupt effect
489
490 //Normally we would set the cooldown equal to the spell duration
491 //but we do not have access to the DurationStore
492
493 switch (CurrentNormalSpell)
494 {
495 case SPELL_ARCMISSLE: ArcaneCooldown = 5000; break;
496 case SPELL_FIREBALL: FireCooldown = 5000; break;
497 case SPELL_FROSTBOLT: FrostCooldown = 5000; break;
498 }
499 }
500 };
501};
502
504{
505public:
506 npc_aran_elemental() : CreatureScript("npc_aran_elemental") { }
507
508 CreatureAI* GetAI(Creature* creature) const override
509 {
510 return GetKarazhanAI<water_elementalAI>(creature);
511 }
512
514 {
515 water_elementalAI(Creature* creature) : ScriptedAI(creature)
516 {
517 Initialize();
518 }
519
521 {
522 CastTimer = 2000 + (rand32() % 3000);
523 }
524
526
527 void Reset() override
528 {
529 Initialize();
530 }
531
532 void JustEngagedWith(Unit* /*who*/) override { }
533
534 void UpdateAI(uint32 diff) override
535 {
536 if (!UpdateVictim())
537 return;
538
539 if (CastTimer <= diff)
540 {
542 CastTimer = urand(2000, 5000);
543 } else CastTimer -= diff;
544 }
545 };
546};
547
uint8_t uint8
Definition Define.h:135
uint32_t uint32
Definition Define.h:133
@ IN_PROGRESS
@ DONE
@ NOT_STARTED
@ TEMPSUMMON_TIMED_DESPAWN
@ TEMPSUMMON_TIMED_DESPAWN_OUT_OF_COMBAT
@ TYPEID_PLAYER
Definition ObjectGuid.h:39
Spells
Definition PlayerAI.cpp:32
uint32 urand(uint32 min, uint32 max)
Definition Random.cpp:42
uint32 rand32()
Definition Random.cpp:70
@ SPELL_EFFECT_INTERRUPT_CAST
@ POWER_MANA
@ UNIT_STAND_STATE_STAND
Definition UnitDefines.h:34
@ UNIT_STAND_STATE_SIT
Definition UnitDefines.h:35
DamageEffectType
Definition Unit.h:352
void AddSC_boss_shade_of_aran()
@ SUPER_FLAME
@ SUPER_BLIZZARD
@ SPELL_CHAINSOFICE
@ SPELL_DRINK
@ SPELL_ELEMENTALS
@ SPELL_WATERBOLT
@ SPELL_FROSTBOLT
@ SPELL_ARCMISSLE
@ SPELL_PLAYERPULL
@ SPELL_AOE_CS
@ CREATURE_ARAN_BLIZZARD
@ SPELL_FLAME_WREATH
@ SPELL_FIREBALL
@ CREATURE_SHADOW_OF_ARAN
@ SAY_ELEMENTALS
@ SPELL_MASSSLOW
@ SPELL_CONJURE
@ SPELL_AOE_PYROBLAST
@ SAY_FLAMEWREATH
@ SPELL_BLINK_CENTER
@ SPELL_AEXPLOSION
@ CREATURE_WATER_ELEMENTAL
@ SAY_TIMEOVER
@ SPELL_DRAGONSBREATH
@ SAY_BLIZZARD
@ SPELL_MASS_POLY
@ SPELL_SHADOW_PYRO
@ SPELL_POTION
@ SPELL_CIRCULAR_BLIZZARD
@ SAY_EXPLOSION
bool UpdateVictim()
Creature *const me
Definition CreatureAI.h:82
virtual bool SetBossState(uint32 id, EncounterState state)
void HandleGameObject(ObjectGuid guid, bool open, GameObject *go=nullptr)
virtual ObjectGuid GetGuidData(uint32 type) const override
void Clear()
Definition ObjectGuid.h:150
static ObjectGuid GetGUID(Object const *o)
Definition Object.h:78
bool HasEffect(SpellEffects effect) const
Trinity::IteratorPair< ThreatListIterator, std::nullptr_t > GetUnsortedThreatList() const
void DoMeleeAttackIfReady()
Definition UnitAI.cpp:54
SpellCastResult DoCastVictim(uint32 spellId, CastSpellExtraArgs const &args={})
Definition UnitAI.cpp:166
Unit * SelectTarget(SelectTargetMethod targetType, uint32 offset=0, float dist=0.0f, bool playerOnly=false, bool withTank=true, int32 aura=0)
Definition UnitAI.cpp:96
SpellCastResult DoCast(uint32 spellId)
Definition UnitAI.cpp:106
Definition Unit.h:769
ThreatManager & GetThreatManager()
Definition Unit.h:1155
void InterruptNonMeleeSpells(bool withDelayed, uint32 spellid=0, bool withInstant=true)
Definition Unit.cpp:3093
bool IsNonMeleeSpellCast(bool withDelayed, bool skipChanneled=false, bool skipAutorepeat=false, bool isAutoshoot=false, bool skipInstant=true) const
Definition Unit.cpp:3063
uint32 GetMaxPower(Powers power) const
Definition Unit.h:936
uint32 GetFaction() const override
Definition Unit.h:973
void SetPower(Powers power, uint32 val, bool withPowerUpdate=true, bool force=false)
Definition Unit.cpp:9421
void RemoveAurasDueToSpell(uint32 spellId, ObjectGuid casterGUID=ObjectGuid::Empty, uint8 reqEffMask=0, AuraRemoveMode removeMode=AURA_REMOVE_BY_DEFAULT)
Definition Unit.cpp:3784
Unit * GetVictim() const
Definition Unit.h:859
float GetPowerPct(Powers power) const
Definition Unit.h:937
void SetStandState(UnitStandStateType state)
Definition Unit.cpp:10363
bool IsWithinDist2d(float x, float y, float dist) const
Definition Object.cpp:1177
InstanceScript * GetInstanceScript() const
Definition Object.cpp:1087
SpellCastResult CastSpell(CastSpellTargetArg const &targets, uint32 spellId, CastSpellExtraArgs const &args={ })
Definition Object.cpp:2832
TempSummon * SummonCreature(uint32 entry, Position const &pos, TempSummonType despawnType=TEMPSUMMON_MANUAL_DESPAWN, Milliseconds despawnTime=0s, uint32 vehId=0, uint32 spellId=0, ObjectGuid privateObjectOwner=ObjectGuid::Empty)
Definition Object.cpp:1992
CreatureAI * GetAI(Creature *creature) const override
CreatureAI * GetAI(Creature *creature) const override
@ DATA_ARAN
Definition karazhan.h:36
@ DATA_GO_LIBRARY_DOOR
Definition karazhan.h:49
TC_GAME_API Unit * GetUnit(WorldObject const &, ObjectGuid const &guid)
bool HealthBelowPct(uint32 pct) const
void SpellHit(WorldObject *, SpellInfo const *spellInfo) override
void UpdateAI(uint32 diff) override
void DamageTaken(Unit *, uint32 &damage, DamageEffectType, SpellInfo const *) override