TrinityCore
Loading...
Searching...
No Matches
boss_sapphiron.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#include "ScriptMgr.h"
19#include "GameObject.h"
20#include "GameObjectAI.h"
21#include "InstanceScript.h"
22#include "MotionMaster.h"
23#include "naxxramas.h"
24#include "ObjectAccessor.h"
25#include "Player.h"
26#include "ScriptedCreature.h"
27#include "SpellInfo.h"
28#include "SpellScript.h"
29#include "TemporarySummon.h"
30
38
40{
42 SPELL_CLEAVE = 19983,
47 SPELL_FROST_BREATH_ANTICHEAT = 29318, // damage effect ignoring LoS on the entrance platform to prevent cheese
48 SPELL_FROST_BREATH = 28524, // damage effect below sapphiron
49 SPELL_FROST_MISSILE = 30101, // visual only
51 SPELL_DIES = 29357,
57};
58
65
83
84enum Misc
85{
86 NPC_BLIZZARD = 16474,
87 GO_ICEBLOCK = 181247,
88
89 // The Hundred Club
94};
95
96typedef std::map<ObjectGuid, ObjectGuid> IceBlockMap;
97
99{
100public:
101 BlizzardTargetSelector(std::vector<Unit*> const& blizzards) : _blizzards(blizzards) { }
102
103 bool operator()(Unit* unit) const
104 {
105 if (unit->GetTypeId() != TYPEID_PLAYER)
106 return false;
107
108 // Check if unit is target of some blizzard
109 for (Unit* blizzard : _blizzards)
110 if (blizzard->GetAI()->GetGUID(DATA_BLIZZARD_TARGET) == unit->GetGUID())
111 return false;
112
113 return true;
114 }
115
116private:
117 std::vector<Unit*> const& _blizzards;
118};
119
120struct boss_sapphiron : public BossAI
121{
123 BossAI(creature, BOSS_SAPPHIRON)
124 {
125 Initialize();
126 }
127
129 {
130 _delayedDrain = false;
131 _canTheHundredClub = true;
132 }
133
134 void InitializeAI() override
135 {
137 return;
138
139 _canTheHundredClub = true;
140
142 {
143 me->SetVisible(false);
146 }
147
149 }
150
151 void Reset() override
152 {
154 {
157 if (me->IsHovering())
158 {
160 me->SetHover(false);
161 }
162 }
163
164 _Reset();
165 Initialize();
166 }
167
168 void DamageTaken(Unit* /*who*/, uint32& damage, DamageEffectType /*damageType*/, SpellInfo const* /*spellInfo = nullptr*/) override
169 {
170 if (damage < me->GetHealth() || !events.IsInPhase(PHASE_FLIGHT))
171 return;
172 damage = me->GetHealth()-1; // don't die during air phase
173 }
174
186
187 void SpellHitTarget(WorldObject* target, SpellInfo const* spellInfo) override
188 {
189 Unit* unitTarget = target->ToUnit();
190 if (!unitTarget)
191 return;
192
193 switch(spellInfo->Id)
194 {
197 _canTheHundredClub = false;
198 break;
199 }
200 }
201
202 void JustDied(Unit* /*killer*/) override
203 {
204 _JustDied();
205 me->CastSpell(me, SPELL_DIES, true);
206 }
207
208 void MovementInform(uint32 /*type*/, uint32 id) override
209 {
210 if (id == 1)
212 }
213
214 void DoAction(int32 param) override
215 {
216 if (param == ACTION_BIRTH)
217 {
220 }
221 }
222
237
243
244 uint32 GetData(uint32 data) const override
245 {
246 if (data == DATA_THE_HUNDRED_CLUB)
247 return _canTheHundredClub;
248
249 return 0;
250 }
251
252 ObjectGuid GetGUID(int32 data) const override
253 {
254 if (data == DATA_BLIZZARD_TARGET)
255 {
256 // Filtering blizzards from summon list
257 std::vector<Unit*> blizzards;
258 for (ObjectGuid summonGuid : summons)
259 if (summonGuid.GetEntry() == NPC_BLIZZARD)
260 if (Unit* temp = ObjectAccessor::GetUnit(*me, summonGuid))
261 blizzards.push_back(temp);
262
263 if (Unit* newTarget = me->AI()->SelectTarget(SelectTargetMethod::Random, 1, BlizzardTargetSelector(blizzards)))
264 return newTarget->GetGUID();
265 }
266
267 return ObjectGuid::Empty;
268 }
269
270 void UpdateAI(uint32 diff) override
271 {
272 events.Update(diff);
273
275 return;
276
278 {
279 while (uint32 eventId = events.ExecuteEvent())
280 {
281 switch (eventId)
282 {
285 events.Repeat(Seconds(30));
286 return;
287 case EVENT_GROUND:
288 EnterPhaseGround(false);
289 return;
290 case EVENT_BERSERK:
293 return;
294 case EVENT_CLEAVE:
297 return;
298 case EVENT_TAIL:
301 return;
302 case EVENT_DRAIN:
303 CastDrain();
304 return;
305 case EVENT_BLIZZARD:
308 break;
309 case EVENT_FLIGHT:
310 if (HealthAbovePct(10))
311 {
312 _delayedDrain = false;
315 me->AttackStop();
316 float x, y, z, o;
317 me->GetHomePosition(x, y, z, o);
318 me->GetMotionMaster()->MovePoint(1, x, y, z);
319 return;
320 }
321 break;
322 }
323 }
324
326 }
327 else
328 {
329 if (uint32 eventId = events.ExecuteEvent())
330 {
331 switch (eventId)
332 {
335 events.Repeat(Seconds(30));
336 return;
337 case EVENT_LIFTOFF:
338 {
342 me->SetHover(true);
344
345 _iceboltTargets.clear();
346 std::list<Unit*> targets;
347 SelectTargetList(targets, RAID_MODE(2, 3), SelectTargetMethod::Random, 0, 200.0f, true);
348 for (Unit* target : targets)
349 if (target)
350 _iceboltTargets.push_back(target->GetGUID());
351 return;
352 }
353 case EVENT_ICEBOLT:
354 {
355 if (_iceboltTargets.empty())
356 {
358 return;
359 }
360 ObjectGuid target = _iceboltTargets.back();
361 if (Player* pTarget = ObjectAccessor::GetPlayer(*me, target))
362 if (pTarget->IsAlive())
363 DoCast(pTarget, SPELL_ICEBOLT);
364 _iceboltTargets.pop_back();
365
366 if (_iceboltTargets.empty())
368 else
370 return;
371 }
372 case EVENT_BREATH:
373 {
377 return;
378 }
379 case EVENT_EXPLOSION:
384 return;
385 case EVENT_LAND:
387 if (_delayedDrain)
388 CastDrain();
391 me->SetHover(false);
394 return;
395 case EVENT_BIRTH:
396 me->SetVisible(true);
399 return;
400 case EVENT_DRAIN:
401 _delayedDrain = true;
402 break;
403 }
404 }
405 }
406 }
407
408private:
412};
413
415{
416 npc_sapphiron_blizzard(Creature* creature) : ScriptedAI(creature) { }
417
418 void Reset() override
419 {
421 _scheduler.Schedule(Seconds(3), [this](TaskContext chill)
422 {
423 DoCastSelf(me->m_spells[0], true);
424 chill.Repeat();
425 });
426 }
427
428 ObjectGuid GetGUID(int32 data) const override
429 {
431 }
432
433 void SetGUID(ObjectGuid const& guid, int32 id) override
434 {
435 if (id == DATA_BLIZZARD_TARGET)
436 _targetGuid = guid;
437 }
438
439 void UpdateAI(uint32 diff) override
440 {
441 _scheduler.Update(diff);
442 }
443
444private:
447};
448
450{
452
453 void InitializeAI() override
454 {
456 }
457
463};
464
466{
467 go_sapphiron_birth(GameObject* go) : GameObjectAI(go), instance(go->GetInstanceScript()) { }
468
469 void OnLootStateChanged(uint32 state, Unit* who) override
470 {
471 if (state == GO_ACTIVATED)
472 {
473 if (who)
474 {
476 sapphiron->AI()->DoAction(ACTION_BIRTH);
478 }
479 }
480 else if (state == GO_JUST_DEACTIVATED)
481 { // prevent ourselves from going back to _READY and resetting the client anim
482 me->SetRespawnTime(0);
483 me->Delete();
484 }
485 }
486
488};
489
490// 24780 - Dream Fog
492{
494
495 void HandlePeriodic(AuraEffect const* /*eff*/)
496 {
498 if (Creature* owner = me ? me->GetSummonerCreatureBase() : nullptr)
499 {
501 if (Unit* newTarget = ObjectAccessor::GetUnit(*owner, owner->AI()->GetGUID(DATA_BLIZZARD_TARGET)))
502 {
503 me->GetAI()->SetGUID(newTarget->GetGUID(), DATA_BLIZZARD_TARGET);
504 me->GetMotionMaster()->MoveFollow(newTarget, 0.1f, 0.0f);
505 }
506 else
507 {
508 me->StopMoving();
509 me->GetMotionMaster()->Clear();
510 }
511 }
512 }
513
518};
519
520// 28522 - Icebolt
559
560// 28560 - Summon Blizzard
562{
564
565 bool Validate(SpellInfo const* /*spell*/) override
566 {
568 }
569
570 void HandleDummy(SpellEffIndex /*effIndex*/)
571 {
572 if (Unit* target = GetHitUnit())
573 if (Creature* blizzard = GetCaster()->SummonCreature(NPC_BLIZZARD, *target, TEMPSUMMON_TIMED_DESPAWN, randtime(25s, 30s)))
574 {
575 blizzard->CastSpell(nullptr, blizzard->m_spells[0], TRIGGERED_NONE);
576 if (Creature* creatureCaster = GetCaster()->ToCreature())
577 {
578 blizzard->AI()->SetGUID(ObjectGuid::Empty, DATA_BLIZZARD_TARGET);
579 if (Unit* newTarget = ObjectAccessor::GetUnit(*creatureCaster, creatureCaster->AI()->GetGUID(DATA_BLIZZARD_TARGET)))
580 {
581 blizzard->AI()->SetGUID(newTarget->GetGUID(), DATA_BLIZZARD_TARGET);
582 blizzard->GetMotionMaster()->MoveFollow(newTarget, 0.1f, 0.0f);
583 return;
584 }
585 }
586 blizzard->GetMotionMaster()->MoveFollow(target, 0.1f, 0.0f);
587 }
588 }
589
594};
595
596// 29330 - Sapphiron's Wing Buffet Despawn
613
614// 29336 - Despawn Buffet
630
632{
633 public:
634 achievement_the_hundred_club() : AchievementCriteriaScript("achievement_the_hundred_club") { }
635
636 bool OnCheck(Player* /*source*/, Unit* target) override
637 {
638 return target && target->GetAI()->GetData(DATA_THE_HUNDRED_CLUB);
639 }
640};
641
int32_t int32
Definition Define.h:129
uint32_t uint32
Definition Define.h:133
std::chrono::seconds Seconds
Seconds shorthand typedef.
Definition Duration.h:27
std::chrono::milliseconds Milliseconds
Milliseconds shorthand typedef.
Definition Duration.h:24
std::chrono::minutes Minutes
Minutes shorthand typedef.
Definition Duration.h:30
@ GO_ACTIVATED
Definition GameObject.h:78
@ GO_JUST_DEACTIVATED
Definition GameObject.h:79
@ DONE
@ TEMPSUMMON_TIMED_DESPAWN
@ TYPEID_PLAYER
Definition ObjectGuid.h:39
std::vector< ObjectGuid > GuidVector
Definition ObjectGuid.h:262
Spells
Definition PlayerAI.cpp:32
Milliseconds randtime(Milliseconds min, Milliseconds max)
Definition Random.cpp:62
#define RegisterSpellScript(spell_script)
Definition ScriptMgr.h:1128
SpellEffIndex
@ EFFECT_0
@ EFFECT_2
@ SPELL_SCHOOL_FROST
@ SPELL_EFFECT_SCRIPT_EFFECT
@ EMOTE_ONESHOT_LAND
@ EMOTE_ONESHOT_LIFTOFF
@ SPELL_SCHOOL_MASK_FROST
@ IMMUNITY_DAMAGE
AuraEffectHandleModes
@ AURA_EFFECT_HANDLE_REAL
@ SPELL_AURA_PERIODIC_TRIGGER_SPELL
@ SPELL_AURA_MOD_STUN
@ TRIGGERED_NONE
#define SpellEffectFn(F, I, N)
#define AuraEffectPeriodicFn(F, I, N)
#define AuraEffectApplyFn(F, I, N, M)
#define AuraEffectRemoveFn(F, I, N, M)
@ REACT_PASSIVE
@ REACT_AGGRESSIVE
@ UNIT_FLAG_NON_ATTACKABLE
DamageEffectType
Definition Unit.h:352
@ DATA_BLIZZARD_TARGET
@ DATA_THE_HUNDRED_CLUB
@ NPC_BLIZZARD
@ MAX_FROST_RESISTANCE
@ ACTION_BIRTH
@ GO_ICEBLOCK
@ EMOTE_AIR_PHASE
@ EMOTE_BREATH
@ EMOTE_ENRAGE
@ EMOTE_GROUND_PHASE
std::map< ObjectGuid, ObjectGuid > IceBlockMap
@ SPELL_ICEBOLT
@ SPELL_CLEAVE
@ SPELL_FROST_BREATH
@ SPELL_FROST_BREATH_ANTICHEAT
@ SPELL_WING_BUFFET_PERIODIC
@ SPELL_LIFE_DRAIN
@ SPELL_FROST_AURA
@ SPELL_DESPAWN_BUFFET
@ SPELL_DIES
@ SPELL_WING_BUFFET_DESPAWN_PERIODIC
@ SPELL_SUMMON_BLIZZARD
@ SPELL_SUMMON_WING_BUFFET
@ SPELL_FROST_MISSILE
@ SPELL_BERSERK
@ SPELL_TAIL_SWEEP
@ SPELL_CHECK_RESISTS
@ PHASE_BIRTH
@ PHASE_FLIGHT
@ PHASE_GROUND
void AddSC_boss_sapphiron()
@ EVENT_TAIL
@ EVENT_EXPLOSION
@ EVENT_GROUND
@ EVENT_BIRTH
@ EVENT_FLIGHT
@ EVENT_BERSERK
@ EVENT_BREATH
@ EVENT_CHECK_RESISTS
@ EVENT_LIFTOFF
@ EVENT_BLIZZARD
@ EVENT_DRAIN
@ EVENT_CLEAVE
@ EVENT_LAND
@ EVENT_ICEBOLT
Yells
HookList< EffectApplyHandler > AfterEffectRemove
HookList< EffectPeriodicHandler > OnEffectPeriodic
HookList< EffectApplyHandler > AfterEffectApply
Unit * GetTarget() const
bool operator()(Unit *unit) const
BlizzardTargetSelector(std::vector< Unit * > const &blizzards)
std::vector< Unit * > const & _blizzards
InstanceScript *const instance
void JustEngagedWith(Unit *who) override
SummonList summons
EventMap events
bool UpdateVictim()
Creature *const me
Definition CreatureAI.h:82
uint32 m_spells[MAX_CREATURE_SPELLS]
Definition Creature.h:229
void GetHomePosition(float &x, float &y, float &z, float &ori) const
Definition Creature.h:295
void SetReactState(ReactStates st)
Definition Creature.h:119
CreatureAI * AI() const
Definition Creature.h:154
void Update(uint32 time)
Definition EventMap.h:67
void Repeat(Milliseconds time)
Definition EventMap.cpp:63
EventId ExecuteEvent()
Definition EventMap.cpp:73
bool IsInPhase(PhaseIndex phase) const
Definition EventMap.h:236
void SetPhase(PhaseIndex phase)
Definition EventMap.cpp:28
void ScheduleEvent(EventId eventId, Milliseconds time, GroupIndex group=0u, PhaseIndex phase=0u)
Definition EventMap.cpp:36
GameObject *const me
void Delete()
void SetRespawnTime(int32 respawn)
void DoRemoveAurasDueToSpellOnPlayers(uint32 spell, bool includePets=false, bool includeControlled=false)
virtual ObjectGuid GetGuidData(uint32 type) const override
EncounterState GetBossState(uint32 id) const
void MovePoint(uint32 id, Position const &pos, bool generatePath=true, Optional< float > finalOrient={})
void MoveFollow(Unit *target, float dist, ChaseAngle angle, MovementSlot slot=MOTION_SLOT_ACTIVE)
static ObjectGuid const Empty
Definition ObjectGuid.h:140
bool IsEmpty() const
Definition ObjectGuid.h:172
static Creature * ToCreature(Object *o)
Definition Object.h:186
static Unit * ToUnit(Object *o)
Definition Object.h:192
TypeID GetTypeId() const
Definition Object.h:93
static ObjectGuid GetGUID(Object const *o)
Definition Object.h:78
uint32 Id
Definition SpellInfo.h:289
Creature * GetHitCreature() const
Unit * GetCaster() const
Unit * GetHitUnit() const
HookList< EffectHandler > OnEffectHitTarget
TaskContext & Repeat(std::chrono::duration< _Rep, _Period > const &duration)
TaskScheduler & Schedule(std::chrono::duration< _Rep, _Period > const &time, task_handler_t const &task)
TaskScheduler & Update(success_t const &callback=EmptyCallback)
Creature * GetSummonerCreatureBase() const
void DoMeleeAttackIfReady()
Definition UnitAI.cpp:54
SpellCastResult DoCastSelf(uint32 spellId, CastSpellExtraArgs const &args={})
Definition UnitAI.h:241
virtual void InitializeAI()
Definition UnitAI.cpp:36
virtual uint32 GetData(uint32) const
Definition UnitAI.h:155
SpellCastResult DoCastVictim(uint32 spellId, CastSpellExtraArgs const &args={})
Definition UnitAI.cpp:166
void SelectTargetList(std::list< Unit * > &targetList, uint32 num, SelectTargetMethod targetType, uint32 offset=0, float dist=0.0f, bool playerOnly=false, bool withTank=true, int32 aura=0)
Definition UnitAI.cpp:101
Unit * SelectTarget(SelectTargetMethod targetType, uint32 offset=0, float dist=0.0f, bool playerOnly=false, bool withTank=true, int32 aura=0)
Definition UnitAI.cpp:96
virtual void SetGUID(ObjectGuid const &, int32=0)
Definition UnitAI.h:157
SpellCastResult DoCastAOE(uint32 spellId, CastSpellExtraArgs const &args={})
Definition UnitAI.h:243
SpellCastResult DoCast(uint32 spellId)
Definition UnitAI.cpp:106
Definition Unit.h:769
void SetVisible(bool x)
Definition Unit.cpp:8513
void StopMoving(bool force=false)
Definition Unit.cpp:10312
MotionMaster * GetMotionMaster()
Definition Unit.h:1667
bool SetHover(bool enable, bool updateAnimTier=true)
Definition Unit.cpp:13503
TempSummon * ToTempSummon()
Definition Unit.h:1794
UnitAI * GetAI() const
Definition Unit.h:800
bool IsHovering() const
Definition Unit.h:1220
uint32 GetHealth() const
Definition Unit.h:913
void ApplySpellImmune(uint32 spellId, uint32 op, uint32 type, bool apply)
Definition Unit.cpp:8142
void HandleEmoteCommand(Emote emoteId)
Definition Unit.cpp:1568
void SetUnitFlag(UnitFlags flags)
Definition Unit.h:954
int32 GetResistance(SpellSchools school) const
Definition Unit.h:908
bool AttackStop()
Definition Unit.cpp:5645
void RemoveUnitFlag(UnitFlags flags)
Definition Unit.h:955
SpellCastResult CastSpell(CastSpellTargetArg const &targets, uint32 spellId, CastSpellExtraArgs const &args={ })
Definition Object.cpp:2832
virtual uint32 GetData(uint32) const
Definition ZoneScript.h:55
virtual void SetData(uint32, uint32)
Definition ZoneScript.h:56
static bool ValidateSpellInfo(std::initializer_list< uint32 > spellIds)
bool OnCheck(Player *, Unit *target) override
PrepareAuraScript(spell_sapphiron_change_blizzard_target)
PrepareSpellScript(spell_sapphiron_despawn_buffet)
void HandleScriptEffect(SpellEffIndex)
void HandleRemove(AuraEffect const *, AuraEffectHandleModes)
void HandlePeriodic(AuraEffect const *)
PrepareAuraScript(spell_sapphiron_icebolt)
void HandleApply(AuraEffect const *, AuraEffectHandleModes)
PrepareSpellScript(spell_sapphiron_summon_blizzard)
bool Validate(SpellInfo const *) override
PrepareAuraScript(spell_sapphiron_wing_buffet_despawn_periodic)
TC_GAME_API Unit * GetUnit(WorldObject const &, ObjectGuid const &guid)
TC_GAME_API GameObject * GetGameObject(WorldObject const &u, ObjectGuid const &guid)
TC_GAME_API Player * GetPlayer(Map const *, ObjectGuid const &guid)
TC_GAME_API Creature * GetCreature(WorldObject const &u, ObjectGuid const &guid)
@ BOSS_SAPPHIRON
Definition naxxramas.h:43
#define RegisterNaxxramasGameObjectAI(ai_name)
Definition naxxramas.h:222
@ DATA_HAD_SAPPHIRON_BIRTH
Definition naxxramas.h:50
@ DATA_SAPPHIRON
Definition naxxramas.h:76
#define RegisterNaxxramasCreatureAI(ai_name)
Definition naxxramas.h:221
void GetPosition(float &x, float &y) const
Definition Position.h:84
bool HealthAbovePct(uint32 pct) const
T const & RAID_MODE(T const &normal10, T const &normal25) const
void JustEngagedWith(Unit *who) override
void JustDied(Unit *) override
ObjectGuid GetGUID(int32 data) const override
void DamageTaken(Unit *, uint32 &damage, DamageEffectType, SpellInfo const *) override
boss_sapphiron(Creature *creature)
void EnterPhaseGround(bool initial)
void MovementInform(uint32, uint32 id) override
void InitializeAI() override
uint32 GetData(uint32 data) const override
void UpdateAI(uint32 diff) override
void Reset() override
GuidVector _iceboltTargets
void DoAction(int32 param) override
void SpellHitTarget(WorldObject *target, SpellInfo const *spellInfo) override
InstanceScript * instance
go_sapphiron_birth(GameObject *go)
void OnLootStateChanged(uint32 state, Unit *who) override
void SetGUID(ObjectGuid const &guid, int32 id) override
ObjectGuid GetGUID(int32 data) const override
npc_sapphiron_blizzard(Creature *creature)
void UpdateAI(uint32 diff) override
npc_sapphiron_wing_buffet(Creature *creature)