TrinityCore
Loading...
Searching...
No Matches
boss_archimonde.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_Archimonde
20SD%Complete: 85
21SDComment: Doomfires not completely offlike due to core limitations for random moving. Tyrande and second phase not fully implemented.
22SDCategory: Caverns of Time, Mount Hyjal
23EndScriptData */
24
25#include "ScriptMgr.h"
26#include "hyjal.h"
27#include "InstanceScript.h"
28#include "MotionMaster.h"
29#include "ObjectAccessor.h"
30#include "ScriptedCreature.h"
31#include "SpellScript.h"
32
34{
42 // YELL_ARCHIMONDE_INTRO = 8
43};
44
70
85
87{
88 NPC_DOOMFIRE = 18095,
90 NPC_ANCIENT_WISP = 17946
91};
92
98
100{
101public:
102 npc_ancient_wisp() : CreatureScript("npc_ancient_wisp") { }
103
104 CreatureAI* GetAI(Creature* creature) const override
105 {
106 return GetHyjalAI<npc_ancient_wispAI>(creature);
107 }
108
110 {
112 {
113 Initialize();
114 instance = creature->GetInstanceScript();
115 }
116
118 {
119 CheckTimer = 1000;
121 }
122
126
135
136 void JustEngagedWith(Unit* /*who*/) override { }
137
138 void DamageTaken(Unit* /*done_by*/, uint32& damage, DamageEffectType /*damageType*/, SpellInfo const* /*spellInfo = nullptr*/) override
139 {
140 damage = 0;
141 }
142
143 void UpdateAI(uint32 diff) override
144 {
145 if (CheckTimer <= diff)
146 {
147 if (Creature* Archimonde = instance->GetCreature(DATA_ARCHIMONDE))
148 {
149 if (Archimonde->HealthBelowPct(2) || !Archimonde->IsAlive())
151 else
152 DoCast(Archimonde, SPELL_ANCIENT_SPARK);
153 }
154 CheckTimer = 1000;
155 } else CheckTimer -= diff;
156 }
157 };
158};
159
160/* This script is merely a placeholder for the Doomfire that triggers Doomfire spell. It will
161 MoveChase the Doomfire Spirit always, until despawn (AttackStart is called upon it's spawn) */
163{
164public:
165 npc_doomfire() : CreatureScript("npc_doomfire") { }
166
167 CreatureAI* GetAI(Creature* creature) const override
168 {
169 return GetHyjalAI<npc_doomfireAI>(creature);
170 }
171
173 {
174 npc_doomfireAI(Creature* creature) : ScriptedAI(creature) { }
175
176 void Reset() override { }
177
178 void MoveInLineOfSight(Unit* /*who*/) override { }
179
180 void JustEngagedWith(Unit* /*who*/) override { }
181
182 void DamageTaken(Unit* /*done_by*/, uint32& damage, DamageEffectType /*damageType*/, SpellInfo const* /*spellInfo = nullptr*/) override
183 {
184 damage = 0;
185 }
186 };
187};
188
189/* This is the script for the Doomfire Spirit Mob. This mob simply follow players or
190 travels in random directions if target cannot be found. */
192{
193public:
194 npc_doomfire_targetting() : CreatureScript("npc_doomfire_targetting") { }
195
196 CreatureAI* GetAI(Creature* creature) const override
197 {
198 return GetHyjalAI<npc_doomfire_targettingAI>(creature);
199 }
200
202 {
204 {
205 Initialize();
206 }
207
209 {
211 ChangeTargetTimer = 5000;
212 }
213
216
217 void Reset() override
218 {
219 Initialize();
220 }
221
222 void MoveInLineOfSight(Unit* who) override
223 {
224 //will update once TargetGUID is 0. In case noone actually moves(not likely) and this is 0
225 //when UpdateAI needs it, it will be forced to select randomPoint
226 if (!TargetGUID && who->GetTypeId() == TYPEID_PLAYER)
227 TargetGUID = who->GetGUID();
228 }
229
230 void JustEngagedWith(Unit* /*who*/) override { }
231
232 void DamageTaken(Unit* /*done_by*/, uint32& damage, DamageEffectType /*damageType*/, SpellInfo const* /*spellInfo = nullptr*/) override
233 {
234 damage = 0;
235 }
236
237 void UpdateAI(uint32 diff) override
238 {
239 if (ChangeTargetTimer <= diff)
240 {
242 {
243 me->GetMotionMaster()->MoveFollow(temp, 0.0f, 0.0f);
245 }
246 else
247 {
250 }
251
252 ChangeTargetTimer = 5000;
253 } else ChangeTargetTimer -= diff;
254 }
255 };
256};
257
258/* Finally, Archimonde's script. His script isn't extremely complex, most are simply spells on timers.
259 The only complicated aspect of the battle is Finger of Death and Doomfire, with Doomfire being the
260 hardest bit to code. Finger of Death is simply a distance check - if no one is in melee range, then
261 select a random target and cast the spell on them. However, if someone IS in melee range, and this
262 is NOT the main tank (creature's victim), then we aggro that player and they become the new victim.
263 For Doomfire, we summon a mob (Doomfire Spirit) for the Doomfire mob to follow. It's spirit will
264 randomly select it's target to follow and then we create the random movement making it unpredictable. */
265
267{
268public:
269 boss_archimonde() : CreatureScript("boss_archimonde") { }
270
271 struct boss_archimondeAI : public BossAI
272 {
274 {
275 Initialize();
276 }
277
279 {
280
281 SoulChargeCount = 0;
282 WispCount = 0; // When ~30 wisps are summoned, Archimonde dies
283 _unleashSpell = 0;
284 _chargeSpell = 0;
285
286 Enraged = false;
287 HasProtected = false;
288 }
289
290 void InitializeAI() override
291 {
293 }
294
295 void Reset() override
296 {
297 Initialize();
298 _Reset();
303 {
304 DoCast(WorldtreeTraget, SPELL_DRAIN_WORLD_TREE);
305 }
306 me->RemoveAllAuras(); // Reset Soul Charge auras.
307 }
308
323
324 void ExecuteEvent(uint32 eventId) override
325 {
326 switch (eventId)
327 {
331 break;
333 _chargeSpell = 0;
334 _unleashSpell = 0;
336 switch (urand(0, 2))
337 {
338 case 0:
341 break;
342 case 1:
345 break;
346 case 2:
349 break;
350 }
351
352 if (me->HasAura(_chargeSpell))
353 {
358 }
359 break;
361 if (!SelectTarget(SelectTargetMethod::Random, 0, 5.0f)) // Checks if there are no targets in melee range
362 {
365 }
366 else
368 break;
373 break;
374 case EVENT_AIR_BURST:
377 DoCast(target, SPELL_AIR_BURST); //not on tank
379 break;
380 case EVENT_FEAR:
383 break;
384 case EVENT_DOOMFIRE:
387 SummonDoomfire(temp);
388 else
391 break;
393 if (Creature* channelTrigger = instance->GetCreature(DATA_CHANNEL_TARGET))
394 if (me->IsWithinDistInMap(channelTrigger, 75.0f))
397 break;
398 case EVENT_PROTECTION_OF_ELUNE: // hp below 10% only cast finger of death
399 events.Reset();
404 break;
407 ++WispCount;
408 if (WispCount >= 30)
409 {
410 me->KillSelf();
411 return;
412 }
414 break;
418 break;
419 default:
420 break;
421 }
422 }
423
424 void DamageTaken(Unit* /*attacker*/, uint32& damage, DamageEffectType /*damageType*/, SpellInfo const* /*spellInfo = nullptr*/) override
425 {
426 if (me->HealthBelowPctDamaged(10, damage))
427 {
428 if (!Enraged)
430
431 if (!HasProtected)
432 {
435 // All members of raid must get this buff
437 HasProtected = true;
438 }
439 }
440 }
441
442 void KilledUnit(Unit* victim) override
443 {
444 Talk(SAY_SLAY);
445
446 if (victim->GetTypeId() == TYPEID_PLAYER)
447 {
448 switch (victim->GetClass())
449 {
450 case CLASS_PRIEST:
451 case CLASS_PALADIN:
452 case CLASS_WARLOCK:
453 victim->CastSpell(me, SPELL_SOUL_CHARGE_RED, true);
454 break;
455 case CLASS_MAGE:
456 case CLASS_ROGUE:
457 case CLASS_WARRIOR:
458 victim->CastSpell(me, SPELL_SOUL_CHARGE_YELLOW, true);
459 break;
460 case CLASS_DRUID:
461 case CLASS_SHAMAN:
462 case CLASS_HUNTER:
463 victim->CastSpell(me, SPELL_SOUL_CHARGE_GREEN, true);
464 break;
465 }
466
469 }
470 }
471
472 void JustReachedHome() override
473 {
475 }
476
477 void JustDied(Unit* /*killer*/) override
478 {
481 _JustDied();
482 // @todo: remove this when instance script gets updated, kept for compatibility only
484 }
485
486 void JustSummoned(Creature* summoned) override
487 {
488 switch (summoned->GetEntry())
489 {
490 case NPC_ANCIENT_WISP:
491 summoned->AI()->AttackStart(me);
492 break;
494 DoomfireSpiritGUID = summoned->GetGUID();
495 break;
496 case NPC_DOOMFIRE:
497 {
498 summoned->CastSpell(summoned, SPELL_DOOMFIRE_SPAWN, false);
499
501 .SetOriginalCaster(me->GetGUID()));
502
503 if (Unit* DoomfireSpirit = ObjectAccessor::GetUnit(*me, DoomfireSpiritGUID))
504 {
505 summoned->GetMotionMaster()->MoveFollow(DoomfireSpirit, 0.0f, 0.0f);
507 }
508 break;
509 }
510 default:
511 break;
512 }
513 }
514
515 void DoAction(int32 actionId) override
516 {
517 switch (actionId)
518 {
519 case ACTION_ENRAGE:
522 Enraged = true;
524 break;
527 break;
528 default:
529 break;
530 }
531 }
532
533 //this is code doing close to what the summoning spell would do (spell 31903)
534 void SummonDoomfire(Unit* target)
535 {
536 if (!target)
537 return;
538
540 target->GetPositionX()+15.0f, target->GetPositionY()+15.0f, target->GetPositionZ(), 0,
543 target->GetPositionX()-15.0f, target->GetPositionY()-15.0f, target->GetPositionZ(), 0,
545 }
546
547 private:
556 };
557
558 CreatureAI* GetAI(Creature* creature) const override
559 {
560 return GetHyjalAI<boss_archimondeAI>(creature);
561 }
562};
563
564// 39142 - Drain World Tree Dummy
566{
567 public:
568 spell_archimonde_drain_world_tree_dummy() : SpellScriptLoader("spell_archimonde_drain_world_tree_dummy") { }
569
571 {
572 bool Validate(SpellInfo const* /*spellInfo*/) override
573 {
575 }
576
577 void HandleScript(SpellEffIndex /*effIndex*/)
578 {
579 if (Unit* target = GetHitUnit())
580 target->CastSpell(GetCaster(), SPELL_DRAIN_WORLD_TREE_TRIGGERED, true);
581 }
582
587 };
588
593};
594
595// Protection of Elune 38528
597{
598 bool Validate(SpellInfo const* /*spellInfo*/) override
599 {
600 return ValidateSpellInfo(
601 {
603 });
604 }
605
614
623
629};
630
uint8_t uint8
Definition Define.h:156
int32_t int32
Definition Define.h:150
uint32_t uint32
Definition Define.h:154
@ DONE
@ TEMPSUMMON_TIMED_DESPAWN
@ TEMPSUMMON_TIMED_DESPAWN_OUT_OF_COMBAT
@ TYPEID_PLAYER
Definition ObjectGuid.h:44
Spells
Definition PlayerAI.cpp:32
uint32 urand(uint32 min, uint32 max)
Definition Random.cpp:42
uint32 rand32()
Definition Random.cpp:70
#define RegisterSpellScript(spell_script)
Definition ScriptMgr.h:1383
SpellEffIndex
@ EFFECT_0
@ CLASS_HUNTER
@ CLASS_DRUID
@ CLASS_SHAMAN
@ CLASS_PRIEST
@ CLASS_WARRIOR
@ CLASS_WARLOCK
@ CLASS_MAGE
@ CLASS_PALADIN
@ CLASS_ROGUE
@ SPELL_EFFECT_DUMMY
@ IMMUNITY_ID
AuraEffectHandleModes
@ AURA_EFFECT_HANDLE_REAL
@ SPELL_AURA_SCHOOL_IMMUNITY
@ TRIGGERED_FULL_MASK
Used when doing CastSpell with triggered == true.
#define SpellEffectFn(F, I, N)
#define AuraEffectApplyFn(F, I, N, M)
#define AuraEffectRemoveFn(F, I, N, M)
DamageEffectType
@ UNIT_FLAG_NON_ATTACKABLE
@ CURRENT_CHANNELED_SPELL
Definition Unit.h:599
void AddSC_boss_archimonde()
@ ACTION_ENRAGE
@ ACTION_CHANNEL_WORLD_TREE
@ SPELL_DRAIN_WORLD_TREE
@ SPELL_SOUL_CHARGE_RED
@ SPELL_DOOMFIRE
@ SPELL_PROTECTION_OF_ELUNE
@ SPELL_FINGER_OF_DEATH
@ SPELL_UNLEASH_SOUL_GREEN
@ SPELL_FINGER_OF_DEATH_LAST_PHASE
@ SPELL_DOOMFIRE_SPAWN
@ SPELL_SOUL_CHARGE_GREEN
@ SPELL_DRAIN_WORLD_TREE_TRIGGERED
@ SPELL_FEAR
@ SPELL_UNLEASH_SOUL_RED
@ SPELL_ANCIENT_SPARK
@ SPELL_DENOUEMENT_WISP
@ SPELL_DOOMFIRE_STRIKE
@ SPELL_HAND_OF_DEATH
@ SPELL_GRIP_OF_THE_LEGION
@ SPELL_UNLEASH_SOUL_YELLOW
@ SPELL_AIR_BURST
@ SPELL_SOUL_CHARGE_YELLOW
@ SAY_DEATH
@ SAY_SOUL_CHARGE
@ SAY_AGGRO
@ SAY_AIR_BURST
@ SAY_SLAY
@ SAY_DOOMFIRE
@ SAY_ENRAGE
@ NPC_ANCIENT_WISP
@ NPC_DOOMFIRE
@ NPC_DOOMFIRE_SPIRIT
@ EVENT_FINGER_OF_DEATH_LAST_PHASE
@ EVENT_DISTANCE_CHECK
@ EVENT_AIR_BURST
@ EVENT_SUMMON_WHISP
@ EVENT_GRIP_OF_THE_LEGION
@ EVENT_FINGER_OF_DEATH
@ EVENT_DOOMFIRE
@ EVENT_FEAR
@ EVENT_PROTECTION_OF_ELUNE
@ EVENT_UNLEASH_SOUL_CHARGE
@ EVENT_HAND_OF_DEATH
HookList< EffectApplyHandler > AfterEffectRemove
HookList< EffectApplyHandler > AfterEffectApply
Unit * GetTarget() const
ObjectGuid const & GetGUID() const
Definition BaseEntity.h:163
TypeID GetTypeId() const
Definition BaseEntity.h:166
InstanceScript *const instance
void JustEngagedWith(Unit *who) override
SummonList summons
EventMap events
void AttackStart(Unit *victim) override
== Triggered Actions Requested ==================
Creature *const me
Definition CreatureAI.h:63
CreatureAI * AI() const
Definition Creature.h:228
void ScheduleEvent(uint32 eventId, Milliseconds time, uint32 group=0, uint8 phase=0)
Definition EventMap.cpp:40
void Reset()
Definition EventMap.cpp:25
Creature * GetCreature(uint32 type)
virtual ObjectGuid GetGuidData(uint32 type) const override
void MoveFollow(Unit *target, float dist, Optional< ChaseAngle > angle={}, Optional< Milliseconds > duration={}, bool ignoreTargetWalk=false, MovementSlot slot=MOTION_SLOT_ACTIVE, Scripting::v2::ActionResultSetter< MovementStopReason > &&scriptResult={})
void MovePoint(uint32 id, Position const &pos, bool generatePath=true, Optional< float > finalOrient={}, Optional< float > speed={}, MovementWalkRunSpeedSelectionMode speedSelectionMode=MovementWalkRunSpeedSelectionMode::Default, Optional< float > closeEnoughDistance={}, Optional< MovementFadeObject > fadeObject={}, Scripting::v2::ActionResultSetter< MovementStopReason > &&scriptResult={})
void Clear()
Definition ObjectGuid.h:329
uint32 GetEntry() const
Definition Object.h:89
static bool ValidateSpellInfo(std::initializer_list< uint32 > spellIds)
Unit * GetCaster() const
Unit * GetHitUnit() const
HookList< EffectHandler > OnEffectHitTarget
virtual void InitializeAI()
Definition UnitAI.cpp:43
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 DoCastAOE(uint32 spellId, CastSpellExtraArgs const &args={})
Definition UnitAI.h:162
SpellCastResult DoCast(uint32 spellId)
Definition UnitAI.cpp:89
Definition Unit.h:635
void ApplySpellImmune(uint32 spellId, SpellImmunity op, uint32 type, bool apply)
Definition Unit.cpp:8242
uint8 GetClass() const
Definition Unit.h:764
void InterruptNonMeleeSpells(bool withDelayed, uint32 spellid=0, bool withInstant=true)
Definition Unit.cpp:3231
MotionMaster * GetMotionMaster()
Definition Unit.h:1723
bool HealthBelowPctDamaged(float pct, uint32 damage) const
Definition Unit.h:793
void RemoveAuraFromStack(uint32 spellId, ObjectGuid casterGUID=ObjectGuid::Empty, AuraRemoveMode removeMode=AURA_REMOVE_BY_DEFAULT, uint16 num=1)
Definition Unit.cpp:3990
Unit * GetVictim() const
Definition Unit.h:726
bool HasAura(uint32 spellId, ObjectGuid casterGUID=ObjectGuid::Empty, ObjectGuid itemCasterGUID=ObjectGuid::Empty, uint32 reqEffMask=0) const
Definition Unit.cpp:4804
void RemoveAllAuras()
Definition Unit.cpp:4382
void SetUnitFlag(UnitFlags flags)
Definition Unit.h:846
void KillSelf(bool durabilityLoss=true, bool skipSettingDeathState=false)
Definition Unit.h:936
void InterruptSpell(CurrentSpellTypes spellType, bool withDelayed=true, bool withInstant=true)
Definition Unit.cpp:3159
InstanceScript * GetInstanceScript() const
Definition Object.cpp:396
SpellCastResult CastSpell(CastSpellTargetArg const &targets, uint32 spellId, CastSpellExtraArgs const &args={ })
Definition Object.cpp:2217
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:1398
Position GetRandomNearPosition(float radius)
Definition Object.cpp:2769
bool IsWithinDistInMap(WorldObject const *obj, float dist2compare, bool is3D=true, bool incOwnRadius=true, bool incTargetRadius=true) const
Definition Object.cpp:501
virtual void SetData(uint32, uint32)
Definition ZoneScript.h:100
CreatureAI * GetAI(Creature *creature) const override
CreatureAI * GetAI(Creature *creature) const override
CreatureAI * GetAI(Creature *creature) const override
CreatureAI * GetAI(Creature *creature) const override
SpellScript * GetSpellScript() const override
void HandleEffectRemove(AuraEffect const *, AuraEffectHandleModes)
bool Validate(SpellInfo const *) override
void HandleEffectApply(AuraEffect const *, AuraEffectHandleModes)
@ DATA_CHANNEL_TARGET
Definition hyjal.h:46
@ DATA_ARCHIMONDE
Definition hyjal.h:34
TC_GAME_API Unit * GetUnit(WorldObject const &, ObjectGuid const &guid)
TC_GAME_API Creature * GetCreature(WorldObject const &u, ObjectGuid const &guid)
constexpr float GetPositionX() const
Definition Position.h:87
float m_positionZ
Definition Position.h:66
constexpr float GetPositionY() const
Definition Position.h:88
float m_positionX
Definition Position.h:64
float m_positionY
Definition Position.h:65
constexpr float GetPositionZ() const
Definition Position.h:89
Creature * DoSpawnCreature(uint32 entry, float offsetX, float offsetY, float offsetZ, float angle, uint32 type, Milliseconds despawntime)
void JustSummoned(Creature *summoned) override
void KilledUnit(Unit *victim) override
void JustEngagedWith(Unit *who) override
void DamageTaken(Unit *, uint32 &damage, DamageEffectType, SpellInfo const *) override
void ExecuteEvent(uint32 eventId) override
void DoAction(int32 actionId) override
void DamageTaken(Unit *, uint32 &damage, DamageEffectType, SpellInfo const *) override
void UpdateAI(uint32 diff) override
void JustEngagedWith(Unit *) override
void MoveInLineOfSight(Unit *) override
void DamageTaken(Unit *, uint32 &damage, DamageEffectType, SpellInfo const *) override
npc_doomfireAI(Creature *creature)
void DamageTaken(Unit *, uint32 &damage, DamageEffectType, SpellInfo const *) override