TrinityCore
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 "Item.h"
29#include "MotionMaster.h"
30#include "ObjectAccessor.h"
31#include "Player.h"
32#include "ScriptedCreature.h"
33#include "SpellInfo.h"
34#include "TemporarySummon.h"
35
37{
48
49 //Spells
57 SPELL_AOE_CS = 29961,
64 SPELL_DRINK = 30024,
65 SPELL_POTION = 32453,
67
68 //Creature Spells
72
73 //Creatures
77};
78
80{
84};
85
87{
92};
93
95{
100};
101
103{
104public:
105 boss_shade_of_aran() : CreatureScript("boss_shade_of_aran") { }
106
107 CreatureAI* GetAI(Creature* creature) const override
108 {
109 return GetKarazhanAI<boss_aranAI>(creature);
110 }
111
112 struct boss_aranAI : public ScriptedAI
113 {
114 boss_aranAI(Creature* creature) : ScriptedAI(creature), SeenAtiesh(false)
115 {
116 Initialize();
117 instance = creature->GetInstanceScript();
118 }
119
121 {
122 SecondarySpellTimer = 5000;
123 NormalCastTimer = 0;
124 SuperCastTimer = 35000;
125 BerserkTimer = 720000;
126 CloseDoorTimer = 15000;
127
128 LastSuperSpell = rand32() % 3;
129
132
134 ArcaneCooldown = 0;
135 FireCooldown = 0;
136 FrostCooldown = 0;
137
138 DrinkInterruptTimer = 10000;
139
140 ElementalsSpawned = false;
141 Drinking = false;
142 DrinkInturrupted = false;
143 }
144
146
151 uint32 CloseDoorTimer; // Don't close the door right on aggro in case some people are still entering.
152
154
158 float FWTargPosX[3];
159 float FWTargPosY[3];
160
165
167
172
173 void Reset() override
174 {
175 Initialize();
176 me->SetCanMelee(true);
177
178 // Not in progress
181 }
182
183 void KilledUnit(Unit* /*victim*/) override
184 {
185 Talk(SAY_KILL);
186 }
187
188 void JustDied(Unit* /*killer*/) override
189 {
191
194 }
195
196 void JustEngagedWith(Unit* /*who*/) override
197 {
199
202 }
203
205 {
206 std::vector<Unit*> targets;
207 //store the threat list in a different container
208 for (auto* ref : me->GetThreatManager().GetUnsortedThreatList())
209 {
210 Unit* target = ref->GetVictim();
211 if (ref->GetVictim()->GetTypeId() == TYPEID_PLAYER && ref->GetVictim()->IsAlive())
212 targets.push_back(target);
213 }
214
215 //cut down to size if we have more than 3 targets
216 while (targets.size() > 3)
217 targets.erase(targets.begin() + rand32() % targets.size());
218
219 uint32 i = 0;
220 for (std::vector<Unit*>::const_iterator itr = targets.begin(); itr!= targets.end(); ++itr)
221 {
222 if (*itr)
223 {
224 FlameWreathTarget[i] = (*itr)->GetGUID();
225 FWTargPosX[i] = (*itr)->GetPositionX();
226 FWTargPosY[i] = (*itr)->GetPositionY();
227 DoCast((*itr), SPELL_FLAME_WREATH, true);
228 ++i;
229 }
230 }
231 }
232
233 void UpdateAI(uint32 diff) override
234 {
235 if (!UpdateVictim())
236 return;
237
238 if (CloseDoorTimer)
239 {
240 if (CloseDoorTimer <= diff)
241 {
243 CloseDoorTimer = 0;
244 } else CloseDoorTimer -= diff;
245 }
246
247 //Cooldowns for casts
248 if (ArcaneCooldown)
249 {
250 if (ArcaneCooldown >= diff)
251 ArcaneCooldown -= diff;
252 else ArcaneCooldown = 0;
253 }
254
255 if (FireCooldown)
256 {
257 if (FireCooldown >= diff)
258 FireCooldown -= diff;
259 else FireCooldown = 0;
260 }
261
262 if (FrostCooldown)
263 {
264 if (FrostCooldown >= diff)
265 FrostCooldown -= diff;
266 else FrostCooldown = 0;
267 }
268
270 {
271 Drinking = true;
273
275
276 if (!DrinkInturrupted)
277 {
278 DoCast(me, SPELL_MASS_POLY, true);
279 DoCast(me, SPELL_CONJURE, false);
280 DoCast(me, SPELL_DRINK, false);
282 DrinkInterruptTimer = 10000;
283 }
284 }
285
286 //Drink Interrupt
288 {
289 Drinking = false;
293 DoCast(me, SPELL_POTION, false);
294 }
295
296 //Drink Interrupt Timer
298 {
299 if (DrinkInterruptTimer >= diff)
300 DrinkInterruptTimer -= diff;
301 else
302 {
304 DoCast(me, SPELL_POTION, true);
306 DrinkInturrupted = true;
307 Drinking = false;
308 }
309 }
310
311 //Don't execute any more code if we are drinking
312 if (Drinking)
313 return;
314
315 //Normal casts
316 if (NormalCastTimer <= diff)
317 {
318 if (!me->IsNonMeleeSpellCast(false))
319 {
320 Unit* target = SelectTarget(SelectTargetMethod::Random, 0, 100, true);
321 if (!target)
322 return;
323
324 uint32 Spells[3];
325 uint8 AvailableSpells = 0;
326
327 //Check for what spells are not on cooldown
328 if (!ArcaneCooldown)
329 {
330 Spells[AvailableSpells] = SPELL_ARCMISSLE;
331 ++AvailableSpells;
332 }
333 if (!FireCooldown)
334 {
335 Spells[AvailableSpells] = SPELL_FIREBALL;
336 ++AvailableSpells;
337 }
338 if (!FrostCooldown)
339 {
340 Spells[AvailableSpells] = SPELL_FROSTBOLT;
341 ++AvailableSpells;
342 }
343
344 //If no available spells wait 1 second and try again
345 if (AvailableSpells)
346 {
347 CurrentNormalSpell = Spells[rand32() % AvailableSpells];
348 DoCast(target, CurrentNormalSpell);
349 }
350 }
351 NormalCastTimer = 1000;
352 } else NormalCastTimer -= diff;
353
354 if (SecondarySpellTimer <= diff)
355 {
356 switch (urand(0, 1))
357 {
358 case 0:
360 break;
361 case 1:
362 if (Unit* target = SelectTarget(SelectTargetMethod::Random, 0, 100, true))
363 DoCast(target, SPELL_CHAINSOFICE);
364 break;
365 }
366 SecondarySpellTimer = urand(5000, 20000);
367 } else SecondarySpellTimer -= diff;
368
369 if (SuperCastTimer <= diff)
370 {
371 uint8 Available[2];
372
373 switch (LastSuperSpell)
374 {
375 case SUPER_AE:
378 break;
379 case SUPER_FLAME:
380 Available[0] = SUPER_AE;
382 break;
383 case SUPER_BLIZZARD:
385 Available[1] = SUPER_AE;
386 break;
387 default:
388 Available[0] = 0;
389 Available[1] = 0;
390 break;
391 }
392
394
395 switch (LastSuperSpell)
396 {
397 case SUPER_AE:
399
401 DoCast(me, SPELL_PLAYERPULL, true);
402 DoCast(me, SPELL_MASSSLOW, true);
403 DoCast(me, SPELL_AEXPLOSION, false);
404 break;
405
406 case SUPER_FLAME:
408
409 FlameWreathTimer = 20000;
411
415
417 break;
418
419 case SUPER_BLIZZARD:
421
422 if (Creature* pSpawn = me->SummonCreature(CREATURE_ARAN_BLIZZARD, 0.0f, 0.0f, 0.0f, 0.0f, TEMPSUMMON_TIMED_DESPAWN, 25s))
423 {
424 pSpawn->SetFaction(me->GetFaction());
425 pSpawn->CastSpell(pSpawn, SPELL_CIRCULAR_BLIZZARD, false);
426 }
427 break;
428 }
429
430 SuperCastTimer = urand(35000, 40000);
431 } else SuperCastTimer -= diff;
432
434 {
435 ElementalsSpawned = true;
436
437 for (uint32 i = 0; i < 4; ++i)
438 {
439 if (Creature* unit = me->SummonCreature(CREATURE_WATER_ELEMENTAL, 0.0f, 0.0f, 0.0f, 0.0f, TEMPSUMMON_TIMED_DESPAWN, 90s))
440 {
441 unit->Attack(me->GetVictim(), true);
442 unit->SetFaction(me->GetFaction());
443 }
444 }
445
447 }
448
449 if (BerserkTimer <= diff)
450 {
451 for (uint32 i = 0; i < 5; ++i)
452 {
454 {
455 unit->Attack(me->GetVictim(), true);
456 unit->SetFaction(me->GetFaction());
457 }
458 }
459
461
462 BerserkTimer = 60000;
463 } else BerserkTimer -= diff;
464
465 //Flame Wreath check
467 {
468 if (FlameWreathTimer >= diff)
469 FlameWreathTimer -= diff;
470 else FlameWreathTimer = 0;
471
472 if (FlameWreathCheckTime <= diff)
473 {
474 for (uint8 i = 0; i < 3; ++i)
475 {
476 if (!FlameWreathTarget[i])
477 continue;
478
480 if (unit && !unit->IsWithinDist2d(FWTargPosX[i], FWTargPosY[i], 3))
481 {
483 .SetOriginalCaster(me->GetGUID()));
484 unit->CastSpell(unit, 11027, true);
486 }
487 }
489 } else FlameWreathCheckTime -= diff;
490 }
491
493 }
494
495 void DamageTaken(Unit* /*pAttacker*/, uint32& damage, DamageEffectType /*damageType*/, SpellInfo const* /*spellInfo = nullptr*/) override
496 {
497 if (!DrinkInturrupted && Drinking && damage)
498 DrinkInturrupted = true;
499 }
500
501 void SpellHit(WorldObject* /*caster*/, SpellInfo const* spellInfo) override
502 {
503 //We only care about interrupt effects and only if they are durring a spell currently being cast
504 if (!spellInfo->HasEffect(SPELL_EFFECT_INTERRUPT_CAST) || !me->IsNonMeleeSpellCast(false))
505 return;
506
507 //Interrupt effect
509
510 //Normally we would set the cooldown equal to the spell duration
511 //but we do not have access to the DurationStore
512
513 switch (CurrentNormalSpell)
514 {
515 case SPELL_ARCMISSLE: ArcaneCooldown = 5000; break;
516 case SPELL_FIREBALL: FireCooldown = 5000; break;
517 case SPELL_FROSTBOLT: FrostCooldown = 5000; break;
518 }
519 }
520
521 void MoveInLineOfSight(Unit* who) override
522 {
524
525 if (SeenAtiesh || me->IsInCombat() || me->GetDistance2d(who) > me->GetAttackDistance(who) + 10.0f)
526 return;
527
528 Player* player = who->ToPlayer();
529 if (!player)
530 return;
531
532 for (uint32 id : AtieshStaves)
533 {
534 if (!PlayerHasWeaponEquipped(player, id))
535 continue;
536
537 SeenAtiesh = true;
542 break;
543 }
544 }
545
546 private:
547 bool PlayerHasWeaponEquipped(Player* player, uint32 itemEntry)
548 {
550 if (item && item->GetEntry() == itemEntry)
551 return true;
552
553 return false;
554 }
555 };
556};
557
559{
560public:
561 npc_aran_elemental() : CreatureScript("npc_aran_elemental") { }
562
563 CreatureAI* GetAI(Creature* creature) const override
564 {
565 return GetKarazhanAI<water_elementalAI>(creature);
566 }
567
569 {
570 water_elementalAI(Creature* creature) : ScriptedAI(creature)
571 {
572 Initialize();
573 }
574
576 {
577 CastTimer = 2000 + (rand32() % 3000);
578 }
579
581
582 void Reset() override
583 {
584 Initialize();
585 }
586
587 void JustEngagedWith(Unit* /*who*/) override { }
588
589 void UpdateAI(uint32 diff) override
590 {
591 if (!UpdateVictim())
592 return;
593
594 if (CastTimer <= diff)
595 {
597 CastTimer = urand(2000, 5000);
598 } else CastTimer -= diff;
599 }
600 };
601};
602
604{
605 new boss_shade_of_aran();
606 new npc_aran_elemental();
607}
@ IN_MILLISECONDS
Definition: Common.h:35
uint8_t uint8
Definition: Define.h:144
uint32_t uint32
Definition: Define.h:142
@ IN_PROGRESS
@ DONE
@ NOT_STARTED
@ TEMPSUMMON_TIMED_DESPAWN
Definition: ObjectDefines.h:65
@ TEMPSUMMON_TIMED_DESPAWN_OUT_OF_COMBAT
Definition: ObjectDefines.h:66
@ TYPEID_PLAYER
Definition: ObjectGuid.h:41
Spells
Definition: PlayerAI.cpp:32
@ EQUIPMENT_SLOT_MAINHAND
Definition: Player.h:646
#define INVENTORY_SLOT_BAG_0
Definition: Player.h:625
uint32 urand(uint32 min, uint32 max)
Definition: Random.cpp:42
uint32 rand32()
Definition: Random.cpp:70
@ SPELL_EFFECT_INTERRUPT_CAST
@ POWER_MANA
@ TRIGGERED_FULL_MASK
Used when doing CastSpell with triggered == true.
Definition: SpellDefines.h:266
@ UNIT_STAND_STATE_STAND
Definition: UnitDefines.h:42
@ UNIT_STAND_STATE_SIT
Definition: UnitDefines.h:43
DamageEffectType
Definition: UnitDefines.h:131
@ UNIT_STATE_MOVING
Definition: Unit.h:294
void AddSC_boss_shade_of_aran()
@ SUPER_AE
@ SUPER_FLAME
@ SUPER_BLIZZARD
@ SAY_DEATH
@ SPELL_CHAINSOFICE
@ SPELL_DRINK
@ SPELL_ELEMENTALS
@ SPELL_WATERBOLT
@ SPELL_FROSTBOLT
@ SPELL_ARCMISSLE
@ SAY_AGGRO
@ SPELL_PLAYERPULL
@ SPELL_AOE_CS
@ CREATURE_ARAN_BLIZZARD
@ SAY_KILL
@ 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
@ SAY_ATIESH
@ SPELL_SHADOW_PYRO
@ SAY_DRINK
@ SPELL_POTION
@ SPELL_CIRCULAR_BLIZZARD
@ SAY_EXPLOSION
@ ITEM_ATIESH_WARLOCK
@ ITEM_ATIESH_MAGE
@ ITEM_ATIESH_DRUID
@ ITEM_ATIESH_PRIEST
uint32 const AtieshStaves[4]
virtual void MoveInLineOfSight(Unit *)
Definition: CreatureAI.cpp:122
void Talk(uint8 id, WorldObject const *whisperTarget=nullptr)
Definition: CreatureAI.cpp:56
bool UpdateVictim()
Definition: CreatureAI.cpp:245
Creature *const me
Definition: CreatureAI.h:61
void SetCanMelee(bool canMelee, bool fleeFromMelee=false)
Definition: Creature.cpp:2822
float GetAttackDistance(Unit const *player) const
Definition: Creature.cpp:2153
virtual bool SetBossState(uint32 id, EncounterState state)
void HandleGameObject(ObjectGuid guid, bool open, GameObject *go=nullptr)
virtual ObjectGuid GetGuidData(uint32 type) const override
Definition: Item.h:170
void MoveDistract(uint32 time, float orientation)
void Clear()
Definition: ObjectGuid.h:286
uint32 GetEntry() const
Definition: Object.h:161
static ObjectGuid GetGUID(Object const *o)
Definition: Object.h:159
static Player * ToPlayer(Object *o)
Definition: Object.h:213
Item * GetItemByPos(uint16 pos) const
Definition: Player.cpp:9582
bool HasEffect(SpellEffectName effect) const
Definition: SpellInfo.cpp:1391
Trinity::IteratorPair< ThreatListIterator, std::nullptr_t > GetUnsortedThreatList() const
SpellCastResult DoCastVictim(uint32 spellId, CastSpellExtraArgs const &args={})
Definition: UnitAI.cpp:180
Unit * SelectTarget(SelectTargetMethod targetType, uint32 offset=0, float dist=0.0f, bool playerOnly=false, bool withTank=true, int32 aura=0)
Definition: UnitAI.cpp:79
SpellCastResult DoCast(uint32 spellId)
Definition: UnitAI.cpp:89
Definition: Unit.h:627
void ClearUnitState(uint32 f)
Definition: Unit.h:733
void SetStandState(UnitStandStateType state, uint32 animKitID=0)
Definition: Unit.cpp:10100
ThreatManager & GetThreatManager()
Definition: Unit.h:1063
void SetPower(Powers power, int32 val, bool withPowerUpdate=true)
Definition: Unit.cpp:9419
void InterruptNonMeleeSpells(bool withDelayed, uint32 spellid=0, bool withInstant=true)
Definition: Unit.cpp:3089
MotionMaster * GetMotionMaster()
Definition: Unit.h:1652
bool IsNonMeleeSpellCast(bool withDelayed, bool skipChanneled=false, bool skipAutorepeat=false, bool isAutoshoot=false, bool skipInstant=true) const
Definition: Unit.cpp:3059
int32 GetMaxPower(Powers power) const
Definition: Unit.cpp:9410
uint32 GetFaction() const override
Definition: Unit.h:858
Unit * GetVictim() const
Definition: Unit.h:715
void SetFacingTo(float const ori, bool force=true)
Definition: Unit.cpp:12653
float GetPowerPct(Powers power) const
Definition: Unit.h:807
void RemoveAurasDueToSpell(uint32 spellId, ObjectGuid casterGUID=ObjectGuid::Empty, uint32 reqEffMask=0, AuraRemoveMode removeMode=AURA_REMOVE_BY_DEFAULT)
Definition: Unit.cpp:3831
bool IsInCombat() const
Definition: Unit.h:1043
bool IsWithinDist2d(float x, float y, float dist) const
Definition: Object.cpp:1132
InstanceScript * GetInstanceScript() const
Definition: Object.cpp:1042
SpellCastResult CastSpell(CastSpellTargetArg const &targets, uint32 spellId, CastSpellExtraArgs const &args={ })
Definition: Object.cpp:2896
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:2025
float GetDistance2d(WorldObject const *obj) const
Definition: Object.cpp:1096
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)
float GetAbsoluteAngle(float x, float y) const
Definition: Position.h:125
bool HealthBelowPct(uint32 pct) const
bool PlayerHasWeaponEquipped(Player *player, uint32 itemEntry)
void SpellHit(WorldObject *, SpellInfo const *spellInfo) override
void UpdateAI(uint32 diff) override
void DamageTaken(Unit *, uint32 &damage, DamageEffectType, SpellInfo const *) override
void MoveInLineOfSight(Unit *who) override