Project SkyFire Core
SkyFire 5.4.8 server core API documentation
Loading...
Searching...
No Matches
boss_sapphiron.cpp
Go to the documentation of this file.
1/*
2* This file is part of Project SkyFire https://www.projectskyfire.org.
3* See LICENSE.md file for Copyright information
4*/
5
6#include "ScriptMgr.h"
7#include "ScriptedCreature.h"
8#include "Player.h"
9#include "SpellInfo.h"
10#include "naxxramas.h"
11
19
35
43
60
61enum Misc
62{
63 NPC_BLIZZARD = 16474,
64 GO_ICEBLOCK = 181247,
65
66 // The Hundred Club
69};
70
71typedef std::map<uint64, uint64> IceBlockMap;
72
74{
75 public:
76 boss_sapphiron() : CreatureScript("boss_sapphiron") { }
77
78 struct boss_sapphironAI : public BossAI
79 {
82 _map(me->GetMap())
83 { }
84
86 {
87 float x, y, z;
88 me->GetPosition(x, y, z);
89 me->SummonGameObject(GO_BIRTH, x, y, z, 0, 0, 0, 0, 0, 0);
90 me->SetVisible(false);
92 me->SetReactState(REACT_PASSIVE);
93
95 }
96
98 {
99 _Reset();
100
101 if (_phase == PHASE_FLIGHT)
103
105
106 _canTheHundredClub = true;
108 }
109
110 void EnterCombat(Unit* /*who*/) OVERRIDE
111 {
112 _EnterCombat();
113
114 me->CastSpell(me, SPELL_FROST_AURA, true);
115
116 events.ScheduleEvent(EVENT_BERSERK, 15 * MINUTE * IN_MILLISECONDS);
118
120 }
121
122 void SpellHitTarget(Unit* target, SpellInfo const* spell) OVERRIDE
123 {
124 if (spell->Id == SPELL_ICEBOLT)
125 {
126 IceBlockMap::iterator itr = _iceblocks.find(target->GetGUID());
127 if (itr != _iceblocks.end() && !itr->second)
128 {
129 if (GameObject* iceblock = me->SummonGameObject(GO_ICEBLOCK, target->GetPositionX(), target->GetPositionY(), target->GetPositionZ(), 0, 0, 0, 0, 0, 25000))
130 itr->second = iceblock->GetGUID();
131 }
132 }
133 }
134
135 void JustDied(Unit* /*killer*/) OVERRIDE
136 {
137 _JustDied();
138 me->CastSpell(me, SPELL_DIES, true);
139
141 }
142
144 {
145 if (id == 1)
146 events.ScheduleEvent(EVENT_LIFTOFF, 0);
147 }
148
150 {
151 if (param == DATA_SAPPHIRON_BIRTH)
152 {
154 events.ScheduleEvent(EVENT_BIRTH, 23 * IN_MILLISECONDS);
155 }
156 }
157
159 {
160 if (_canTheHundredClub && _map && _map->IsRaid())
161 {
162 Map::PlayerList const &players = _map->GetPlayers();
163 for (Map::PlayerList::const_iterator itr = players.begin(); itr != players.end(); ++itr)
164 {
165 if (itr->GetSource()->GetResistance(SPELL_SCHOOL_FROST) > MAX_FROST_RESISTANCE)
166 {
167 _canTheHundredClub = false;
168 break;
169 }
170 }
171 }
172 }
173
175 {
177 me->SetReactState(REACT_AGGRESSIVE);
178 events.SetPhase(PHASE_GROUND);
179 events.ScheduleEvent(EVENT_CLEAVE, std::rand() % (15 * IN_MILLISECONDS) + (5 * IN_MILLISECONDS), 0, PHASE_GROUND);
180 events.ScheduleEvent(EVENT_TAIL, std::rand() % (15 * IN_MILLISECONDS) + (5 * IN_MILLISECONDS), 0, PHASE_GROUND);
181 events.ScheduleEvent(EVENT_DRAIN, 24 * IN_MILLISECONDS, 0, PHASE_GROUND);
182 events.ScheduleEvent(EVENT_BLIZZARD, std::rand() % (10 * IN_MILLISECONDS) + (5 * IN_MILLISECONDS), 0, PHASE_GROUND);
183 events.ScheduleEvent(EVENT_FLIGHT, 45 * IN_MILLISECONDS);
184 }
185
187 {
188 for (IceBlockMap::const_iterator itr = _iceblocks.begin(); itr != _iceblocks.end(); ++itr)
189 {
190 if (Player* player = ObjectAccessor::GetPlayer(*me, itr->first))
191 player->RemoveAura(SPELL_ICEBOLT);
192
193 if (GameObject* go = ObjectAccessor::GetGameObject(*me, itr->second))
194 go->Delete();
195 }
196 _iceblocks.clear();
197 }
198
200 {
201 if (data == DATA_THE_HUNDRED_CLUB)
202 return _canTheHundredClub;
203
204 return 0;
205 }
206
208 {
209 if (!_phase)
210 return;
211
212 events.Update(diff);
213
214 if ((_phase != PHASE_BIRTH && !UpdateVictim()) || !CheckInRoom())
215 return;
216
218 {
219 if (_checkFrostResistTimer <= diff)
220 {
223 }
224 else
226 }
227
228 if (_phase == PHASE_GROUND)
229 {
230 while (uint32 eventId = events.ExecuteEvent())
231 {
232 switch (eventId)
233 {
234 case EVENT_BERSERK:
237 return;
238 case EVENT_CLEAVE:
240 events.ScheduleEvent(EVENT_CLEAVE, std::rand() % (15 * IN_MILLISECONDS) + (5 * IN_MILLISECONDS), 0, PHASE_GROUND);
241 return;
242 case EVENT_TAIL:
244 events.ScheduleEvent(EVENT_TAIL, std::rand() % (15 * IN_MILLISECONDS) + (5 * IN_MILLISECONDS), 0, PHASE_GROUND);
245 return;
246 case EVENT_DRAIN:
248 events.ScheduleEvent(EVENT_DRAIN, 24 * IN_MILLISECONDS, 0, PHASE_GROUND);
249 return;
250 case EVENT_BLIZZARD:
251 {
252 //DoCastAOE(SPELL_SUMMON_BLIZZARD);
254 summon->GetMotionMaster()->MoveRandom(40);
255 events.ScheduleEvent(EVENT_BLIZZARD, RAID_MODE(20, 7) * IN_MILLISECONDS, 0, PHASE_GROUND);
256 break;
257 }
258 case EVENT_FLIGHT:
259 if (HealthAbovePct(10))
260 {
262 events.SetPhase(PHASE_FLIGHT);
263 me->SetReactState(REACT_PASSIVE);
264 me->AttackStop();
265 float x, y, z, o;
266 me->GetHomePosition(x, y, z, o);
267 me->GetMotionMaster()->MovePoint(1, x, y, z);
268 return;
269 }
270 break;
271 }
272 }
273
275 }
276 else
277 {
278 if (uint32 eventId = events.ExecuteEvent())
279 {
280 switch (eventId)
281 {
282 case EVENT_LIFTOFF:
284 me->SetDisableGravity(true);
285 events.ScheduleEvent(EVENT_ICEBOLT, 1500);
286 _iceboltCount = RAID_MODE(2, 3);
287 return;
288 case EVENT_ICEBOLT:
289 {
290 std::vector<Unit*> targets;
291 std::list<HostileReference*>::const_iterator i = me->getThreatManager().getThreatList().begin();
292 for (; i != me->getThreatManager().getThreatList().end(); ++i)
293 if ((*i)->getTarget()->GetTypeId() == TypeID::TYPEID_PLAYER && !(*i)->getTarget()->HasAura(SPELL_ICEBOLT))
294 targets.push_back((*i)->getTarget());
295
296 if (targets.empty())
297 _iceboltCount = 0;
298 else
299 {
300 std::vector<Unit*>::const_iterator itr = targets.begin();
301 advance(itr, rand()%targets.size());
302 _iceblocks.insert(std::make_pair((*itr)->GetGUID(), 0));
303 DoCast(*itr, SPELL_ICEBOLT);
305 }
306
307 if (_iceboltCount)
308 events.ScheduleEvent(EVENT_ICEBOLT, 1 * IN_MILLISECONDS);
309 else
310 events.ScheduleEvent(EVENT_BREATH, 1 * IN_MILLISECONDS);
311 return;
312 }
313 case EVENT_BREATH:
314 {
317 events.ScheduleEvent(EVENT_EXPLOSION, 8 * IN_MILLISECONDS);
318 return;
319 }
320 case EVENT_EXPLOSION:
323 events.ScheduleEvent(EVENT_LAND, 3 * IN_MILLISECONDS);
324 return;
325 case EVENT_LAND:
326 me->HandleEmoteCommand(EMOTE_ONESHOT_LAND);
328 me->SetDisableGravity(false);
329 events.ScheduleEvent(EVENT_GROUND, 1500);
330 return;
331 case EVENT_GROUND:
333 return;
334 case EVENT_BIRTH:
335 me->SetVisible(true);
337 me->SetReactState(REACT_AGGRESSIVE);
338 return;
339 }
340 }
341 }
342 }
343
345 {
346 DoZoneInCombat(); // make sure everyone is in threatlist
347 std::vector<Unit*> targets;
348 std::list<HostileReference*>::const_iterator i = me->getThreatManager().getThreatList().begin();
349 for (; i != me->getThreatManager().getThreatList().end(); ++i)
350 {
351 Unit* target = (*i)->getTarget();
352 if (target->GetTypeId() != TypeID::TYPEID_PLAYER)
353 continue;
354
355 if (target->HasAura(SPELL_ICEBOLT))
356 {
358 targets.push_back(target);
359 continue;
360 }
361
362 for (IceBlockMap::const_iterator itr = _iceblocks.begin(); itr != _iceblocks.end(); ++itr)
363 {
364 if (GameObject* go = GameObject::GetGameObject(*me, itr->second))
365 {
366 if (go->IsInBetween(me, target, 2.0f)
367 && me->GetExactDist2d(target->GetPositionX(), target->GetPositionY()) - me->GetExactDist2d(go->GetPositionX(), go->GetPositionY()) < 5.0f)
368 {
370 targets.push_back(target);
371 break;
372 }
373 }
374 }
375 }
376
377 me->CastSpell(me, SPELL_FROST_EXPLOSION, true);
378
379 for (std::vector<Unit*>::const_iterator itr = targets.begin(); itr != targets.end(); ++itr)
380 (*itr)->ApplySpellImmune(0, IMMUNITY_ID, SPELL_FROST_EXPLOSION, false);
381 }
382
383 private:
390 };
391
393 {
394 return new boss_sapphironAI(creature);
395 }
396};
397
399{
400 public:
401 achievement_the_hundred_club() : AchievementCriteriaScript("achievement_the_hundred_club") { }
402
403 bool OnCheck(Player* /*source*/, Unit* target) OVERRIDE
404 {
405 return target && target->GetAI()->GetData(DATA_THE_HUNDRED_CLUB);
406 }
407};
408
@ IN_MILLISECONDS
Definition Common.h:125
@ MINUTE
Definition Common.h:119
std::int32_t int32
Definition Define.h:73
std::uint32_t uint32
Definition Define.h:77
#define OVERRIDE
Definition Define.h:60
@ TYPEID_PLAYER
Definition Object.h:55
@ TEMPSUMMON_TIMED_DESPAWN
Definition Object.h:70
@ EMOTE_ONESHOT_LAND
@ SPELL_SCHOOL_FROST
@ IMMUNITY_ID
@ REACT_PASSIVE
Definition Unit.h:1156
@ REACT_AGGRESSIVE
Definition Unit.h:1158
@ UNIT_FLAG_NON_ATTACKABLE
Definition Unit.h:626
@ UNIT_FIELD_FLAGS
@ SPELL_CLEAVE
@ EVENT_CLEAVE
@ SPELL_CHILL
@ PHASE_FLIGHT
@ PHASE_GROUND
@ EVENT_FLIGHT
#define SPELL_BERSERK
@ EVENT_BREATH
@ EMOTE_ENRAGE
@ SPELL_FROST_BREATH
@ EMOTE_BREATH
@ SPELL_TAIL_SWEEP
@ EVENT_GROUND
Definition boss_noth.cpp:56
@ EVENT_BERSERK
@ DATA_THE_HUNDRED_CLUB
@ NPC_BLIZZARD
@ MAX_FROST_RESISTANCE
@ GO_ICEBLOCK
@ EMOTE_AIR_PHASE
@ EMOTE_BREATH
@ EMOTE_ENRAGE
@ EMOTE_GROUND_PHASE
@ SPELL_ICEBOLT
@ SPELL_CLEAVE
@ SPELL_LIFE_DRAIN
@ SPELL_FROST_AURA
@ SPELL_DIES
@ SPELL_FROST_EXPLOSION
@ SPELL_SUMMON_BLIZZARD
@ SPELL_FROST_MISSILE
@ SPELL_BERSERK
@ SPELL_TAIL_SWEEP
@ PHASE_BIRTH
@ PHASE_FLIGHT
@ PHASE_GROUND
@ PHASE_NULL
void AddSC_boss_sapphiron()
std::map< uint64, uint64 > IceBlockMap
@ EVENT_TAIL
@ EVENT_EXPLOSION
@ EVENT_GROUND
@ EVENT_BIRTH
@ EVENT_FLIGHT
@ EVENT_BERSERK
@ EVENT_BREATH
@ EVENT_LIFTOFF
@ EVENT_BLIZZARD
@ EVENT_DRAIN
@ EVENT_CLEAVE
@ EVENT_LAND
@ EVENT_ICEBOLT
@ SPELL_FROST_AURA
@ EVENT_LAND
AchievementCriteriaScript(const char *name)
bool CheckInRoom()
EventMap events
BossAI(Creature *creature, uint32 bossId)
void _EnterCombat()
void DoZoneInCombat(Creature *creature=NULL, float maxRangeToNearestTarget=50.0f)
Creature * DoSummon(uint32 entry, Position const &pos, uint32 despawnTime=30000, TempSummonType summonType=TempSummonType::TEMPSUMMON_CORPSE_TIMED_DESPAWN)
void Talk(uint8 id, WorldObject const *whisperTarget=NULL)
bool UpdateVictim()
CreatureScript(const char *name)
static GameObject * GetGameObject(WorldObject &object, uint64 guid)
Definition Map.h:238
MapRefManager PlayerList
Definition Map.h:406
iterator end()
iterator begin()
LinkedListHead::Iterator< MapReference const > const_iterator
static Player * GetPlayer(WorldObject const &, uint64 guid)
static GameObject * GetGameObject(WorldObject const &u, uint64 guid)
TypeID GetTypeId() const
Definition Object.h:131
void DoMeleeAttackIfReady()
Definition UnitAI.cpp:28
void DoCast(uint32 spellId)
Definition UnitAI.cpp:110
virtual void InitializeAI()
Definition UnitAI.h:118
void DoCastVictim(uint32 spellId, bool triggered=false)
Definition UnitAI.cpp:168
void DoCastAOE(uint32 spellId, bool triggered=false)
Definition UnitAI.cpp:176
Definition Unit.h:1367
bool HasAura(uint32 spellId, uint64 casterGUID=0, uint64 itemCasterGUID=0, uint32 reqEffMask=0) const
void ApplySpellImmune(uint32 spellId, uint32 op, uint32 type, bool apply)
Definition Unit.cpp:3580
bool OnCheck(Player *, Unit *target) OVERRIDE
CreatureAI * GetAI(Creature *creature) const OVERRIDE
@ BOSS_SAPPHIRON
Definition naxxramas.h:26
@ DATA_SAPPHIRON_BIRTH
Definition naxxramas.h:34
@ GO_BIRTH
Definition naxxramas.h:122
float GetPositionX() const
Definition Object.h:328
float GetPositionY() const
Definition Object.h:329
Creature * me
bool HealthAbovePct(uint32 pct) const
const T & RAID_MODE(const T &normal10, const T &normal25) const
void MovementInform(uint32, uint32 id) OVERRIDE
void SpellHitTarget(Unit *target, SpellInfo const *spell) OVERRIDE
void DoAction(int32 param) OVERRIDE
void UpdateAI(uint32 diff) OVERRIDE
== Triggered Actions Requested ==================
uint32 GetData(uint32 data) const OVERRIDE