Project SkyFire Core
SkyFire 5.4.8 server core API documentation
Loading...
Searching...
No Matches
boss_general_vezax.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 "SpellScript.h"
9#include "SpellAuraEffects.h"
10#include "ulduar.h"
11#include "Player.h"
12
22
24{
28
29 // Saronite Vapor
31};
32
56
63
80
81enum Misc
82{
85};
86
88{
89 public:
90 boss_general_vezax() : CreatureScript("boss_general_vezax") { }
91
93 {
95 {
96 }
97
99 bool smellSaronite; // HardMode
100 bool animusDead; // Check against getting a HardMode achievement before killing Saronite Animus
102
104 {
105 _Reset();
106
107 shadowDodger = true;
108 smellSaronite = true;
109 animusDead = false;
110 vaporCount = 0;
111 }
112
113 void EnterCombat(Unit* /*who*/) OVERRIDE
114 {
115 _EnterCombat();
116
120
121 events.ScheduleEvent(EVENT_SHADOW_CRASH, std::rand() % 10000 + 8000);
122 events.ScheduleEvent(EVENT_SEARING_FLAMES, 12000);
123 events.ScheduleEvent(EVENT_MARK_OF_THE_FACELESS, std::rand() % 40000 + 35000);
124 events.ScheduleEvent(EVENT_SARONITE_VAPORS, 30000);
125 events.ScheduleEvent(EVENT_SURGE_OF_DARKNESS, 60000);
126 events.ScheduleEvent(EVENT_BERSERK, 600000);
127 }
128
130 {
131 if (!UpdateVictim())
132 return;
133
134 events.Update(diff);
135
136 if (me->HasUnitState(UNIT_STATE_CASTING))
137 return;
138
139 while (uint32 eventId = events.ExecuteEvent())
140 {
141 switch (eventId)
142 {
144 {
145 Unit* target = CheckPlayersInRange(RAID_MODE<uint8>(4, 9), 15.0f, 50.0f);
146 if (!target)
147 target = SelectTarget(SELECT_TARGET_RANDOM, 0, 150.0f, true);
148 if (target)
149 DoCast(target, SPELL_SHADOW_CRASH);
150 events.ScheduleEvent(EVENT_SHADOW_CRASH, std::rand() % 12000 + 8000);
151 break;
152 }
155 events.ScheduleEvent(EVENT_SEARING_FLAMES, std::rand() % 17500 + 14000);
156 break;
158 {
159 Unit* target = CheckPlayersInRange(RAID_MODE<uint8>(4, 9), 15.0f, 50.0f);
160 if (!target)
161 target = SelectTarget(SELECT_TARGET_RANDOM, 0, 150.0f, true);
162 if (target)
164 events.ScheduleEvent(EVENT_MARK_OF_THE_FACELESS, std::rand() % 45000 + 35000);
165 break;
166 }
171 events.ScheduleEvent(EVENT_SURGE_OF_DARKNESS, std::rand() % 70000 + 50000);
172 break;
175 events.ScheduleEvent(EVENT_SARONITE_VAPORS, std::rand() % 35000 + 30000);
176 if (++vaporCount == 6 && smellSaronite)
177 {
180 summons.DespawnAll();
183 me->AddLootMode(LOOT_MODE_HARD_MODE_1);
184 events.CancelEvent(EVENT_SARONITE_VAPORS);
185 events.CancelEvent(EVENT_SEARING_FLAMES);
186 }
187 break;
188 case EVENT_BERSERK:
191 break;
192 }
193 }
194
196 }
197
198 void SpellHitTarget(Unit* who, SpellInfo const* spell) OVERRIDE
199 {
200 if (who && who->GetTypeId() == TypeID::TYPEID_PLAYER && spell->Id == SPELL_SHADOW_CRASH_HIT)
201 shadowDodger = false;
202 }
203
205 {
206 if (who->GetTypeId() == TypeID::TYPEID_PLAYER)
207 Talk(SAY_SLAY);
208 }
209
210 void JustDied(Unit* /*killer*/) OVERRIDE
211 {
212 _JustDied();
214 instance->DoRemoveAurasDueToSpellOnPlayers(SPELL_AURA_OF_DESPAIR);
215 }
216
218 {
219 Map* map = me->GetMap();
220 if (map && map->IsDungeon())
221 {
222 // If Shaman has Shamanistic Rage and use it during the fight, it will cast Corrupted Rage on him
223 Map::PlayerList const& Players = map->GetPlayers();
224 for (Map::PlayerList::const_iterator itr = Players.begin(); itr != Players.end(); ++itr)
225 if (Player* player = itr->GetSource())
226 if (player->HasSpell(SPELL_SHAMANTIC_RAGE))
227 player->CastSpell(player, SPELL_CORRUPTED_RAGE, false);
228 }
229 }
230
232 {
233 switch (type)
234 {
236 return shadowDodger ? 1 : 0;
238 return smellSaronite ? 1 : 0;
239 }
240
241 return 0;
242 }
243
245 {
246 switch (action)
247 {
249 smellSaronite = false;
250 break;
252 me->RemoveAurasDueToSpell(SPELL_SARONITE_BARRIER);
253 events.ScheduleEvent(EVENT_SEARING_FLAMES, std::rand() % 12000 + 7000);
254 animusDead = true;
255 break;
256 }
257 }
258
259 /* Player Range Check
260 Purpose: If there are playersMin people within rangeMin, rangeMax: return a random players in that range.
261 If not, return NULL and allow other target selection
262 */
263 Unit* CheckPlayersInRange(uint8 playersMin, float rangeMin, float rangeMax)
264 {
265 Map* map = me->GetMap();
266 if (map && map->IsDungeon())
267 {
268 std::list<Player*> PlayerList;
269 Map::PlayerList const& Players = map->GetPlayers();
270 for (Map::PlayerList::const_iterator itr = Players.begin(); itr != Players.end(); ++itr)
271 {
272 if (Player* player = itr->GetSource())
273 {
274 float distance = player->GetDistance(me->GetPositionX(), me->GetPositionY(), me->GetPositionZ());
275 if (rangeMin > distance || distance > rangeMax)
276 continue;
277
278 PlayerList.push_back(player);
279 }
280 }
281
282 if (PlayerList.empty())
283 return NULL;
284
285 size_t size = PlayerList.size();
286 if (size < playersMin)
287 return NULL;
288
290 }
291
292 return NULL;
293 }
294 };
295
297 {
298 return GetUlduarAI<boss_general_vezaxAI>(creature);
299 }
300};
301
303{
304 public:
305 boss_saronite_animus() : CreatureScript("npc_saronite_animus") { }
306
308 {
310 {
311 instance = me->GetInstanceScript();
312 }
313
315 {
317 events.Reset();
318 events.ScheduleEvent(EVENT_PROFOUND_OF_DARKNESS, 3000);
319 }
320
321 void JustDied(Unit* /*killer*/) OVERRIDE
322 {
323 if (Creature* Vezax = me->GetCreature(*me, instance->GetData64(BOSS_VEZAX)))
324 Vezax->AI()->DoAction(ACTION_ANIMUS_DIE);
325 }
326
328 {
329 if (!UpdateVictim())
330 return;
331
332 events.Update(diff);
333
334 if (me->HasUnitState(UNIT_STATE_CASTING))
335 return;
336
337 while (uint32 eventId = events.ExecuteEvent())
338 {
339 switch (eventId)
340 {
343 events.ScheduleEvent(EVENT_PROFOUND_OF_DARKNESS, 3000);
344 break;
345 default:
346 break;
347 }
348 }
349
351 }
352
353 private:
356 };
357
359 {
360 return new boss_saronite_animusAI(creature);
361 }
362};
363
365{
366 public:
367 npc_saronite_vapors() : CreatureScript("npc_saronite_vapors") { }
368
370 {
372 {
374 instance = me->GetInstanceScript();
375 me->ApplySpellImmune(0, IMMUNITY_EFFECT, SPELL_EFFECT_KNOCK_BACK, true);
376 me->ApplySpellImmune(0, IMMUNITY_ID, 49560, true); // Death Grip jump effect
377 me->SetReactState(REACT_PASSIVE);
378 }
379
381 {
382 events.Reset();
383 events.ScheduleEvent(EVENT_RANDOM_MOVE, std::rand() % 7500 + 5000);
384 }
385
387 {
388 events.Update(diff);
389
390 while (uint32 eventId = events.ExecuteEvent())
391 {
392 switch (eventId)
393 {
395 me->GetMotionMaster()->MoveRandom(30.0f);
396 events.ScheduleEvent(EVENT_RANDOM_MOVE, std::rand() % 7500 + 5000);
397 break;
398 default:
399 break;
400 }
401 }
402 }
403
404 void DamageTaken(Unit* /*who*/, uint32& damage) OVERRIDE
405 {
406 // This can't be on JustDied. In 63322 dummy handler caster needs to be this NPC
407 // if caster == target then damage mods will increase the damage taken
408 if (damage >= me->GetHealth())
409 {
410 damage = 0;
412 me->SetStandState(UNIT_STAND_STATE_DEAD);
413 me->SetHealth(me->GetMaxHealth());
414 me->RemoveAllAuras();
416 me->DespawnOrUnsummon(30000);
417
418 if (Creature* Vezax = me->GetCreature(*me, instance->GetData64(BOSS_VEZAX)))
419 Vezax->AI()->DoAction(ACTION_VAPORS_DIE);
420 }
421 }
422
423 private:
426 };
427
429 {
430 return new npc_saronite_vaporsAI(creature);
431 }
432};
433
467
496
498{
499 public:
500 spell_general_vezax_saronite_vapors() : SpellScriptLoader("spell_general_vezax_saronite_vapors") { }
501
503 {
505
506 bool Validate(SpellInfo const* /*spell*/) OVERRIDE
507 {
509 return false;
510 return true;
511 }
512
514 {
515 if (Unit* caster = GetCaster())
516 {
517 int32 mana = int32(aurEff->GetAmount() * pow(2.0f, GetStackAmount())); // mana restore - bp * 2^stackamount
518 int32 damage = mana * 2;
519 caster->CastCustomSpell(GetTarget(), SPELL_SARONITE_VAPORS_ENERGIZE, &mana, NULL, NULL, true);
520 caster->CastCustomSpell(GetTarget(), SPELL_SARONITE_VAPORS_DAMAGE, &damage, NULL, NULL, true);
521 }
522 }
523
528 };
529
534};
535
537{
538 public:
540 {
541 }
542
543 bool OnCheck(Player* /*player*/, Unit* target) OVERRIDE
544 {
545 if (!target)
546 return false;
547
548 if (Creature* Vezax = target->ToCreature())
549 if (Vezax->AI()->GetData(DATA_SHADOWDODGER))
550 return true;
551
552 return false;
553 }
554};
555
557{
558 public:
560 {
561 }
562
563 bool OnCheck(Player* /*player*/, Unit* target) OVERRIDE
564 {
565 if (!target)
566 return false;
567
568 if (Creature* Vezax = target->ToCreature())
569 if (Vezax->AI()->GetData(DATA_SMELL_SARONITE))
570 return true;
571
572 return false;
573 }
574};
575
std::int32_t int32
Definition Define.h:73
std::uint8_t uint8
Definition Define.h:79
std::uint32_t uint32
Definition Define.h:77
#define OVERRIDE
Definition Define.h:60
@ TYPEID_PLAYER
Definition Object.h:55
@ EFFECT_1
@ EFFECT_0
@ SPELL_EFFECT_KNOCK_BACK
@ TARGET_UNIT_DEST_AREA_ENEMY
@ IMMUNITY_EFFECT
@ IMMUNITY_ID
@ LOOT_MODE_HARD_MODE_1
@ SPELL_AURA_DUMMY
@ SPELL_AURA_PERIODIC_DUMMY
AuraEffectHandleModes
@ AURA_EFFECT_HANDLE_REAL_OR_REAPPLY_MASK
#define sSpellMgr
Definition SpellMgr.h:744
#define SpellObjectAreaTargetSelectFn(F, I, N)
#define AuraEffectPeriodicFn(F, I, N)
#define AuraEffectApplyFn(F, I, N, M)
@ SPELLVALUE_BASE_POINT1
Definition Unit.h:115
@ UNIT_STAND_STATE_DEAD
Definition Unit.h:169
@ UNIT_STATE_CASTING
Definition Unit.h:527
@ REACT_PASSIVE
Definition Unit.h:1156
@ UNIT_FLAG_NON_ATTACKABLE
Definition Unit.h:626
@ UNIT_FLAG_DISABLE_MOVE
Definition Unit.h:627
@ UNIT_FLAG_NOT_SELECTABLE
Definition Unit.h:650
@ SELECT_TARGET_RANDOM
Definition UnitAI.h:23
@ UNIT_FIELD_FLAGS
@ SAY_BERSERK
@ SAY_SLAY
#define SAY_DEATH
#define SAY_AGGRO
#define SPELL_BERSERK
@ EVENT_SHADOW_CRASH
@ EVENT_MARK_OF_THE_FACELESS
@ EVENT_RANDOM_MOVE
@ EVENT_BERSERK
@ EVENT_PROFOUND_OF_DARKNESS
@ EVENT_SARONITE_VAPORS
@ EVENT_SURGE_OF_DARKNESS
@ EVENT_SEARING_FLAMES
@ ACTION_VAPORS_SPAWN
@ ACTION_ANIMUS_DIE
@ ACTION_VAPORS_DIE
@ DATA_SMELL_SARONITE
@ DATA_SHADOWDODGER
@ SPELL_SHADOW_CRASH
@ SPELL_CORRUPTED_RAGE
@ SPELL_SARONITE_VAPORS_DAMAGE
@ SPELL_SUMMON_SARONITE_VAPORS
@ SPELL_SURGE_OF_DARKNESS
@ SPELL_VISUAL_SARONITE_ANIMUS
@ SPELL_SARONITE_VAPORS_ENERGIZE
@ SPELL_SARONITE_BARRIER
@ SPELL_SARONITE_VAPORS
@ SPELL_AURA_OF_DESPAIR
@ SPELL_SEARING_FLAMES
@ SPELL_SHADOW_CRASH_HIT
@ SPELL_SUMMON_SARONITE_ANIMUS
@ SPELL_BERSERK
@ SPELL_SHAMANTIC_RAGE
@ SPELL_PROFOUND_OF_DARKNESS
@ SPELL_MARK_OF_THE_FACELESS_DAMAGE
@ SPELL_MARK_OF_THE_FACELESS
@ SAY_SURGE_OF_DARKNESS
@ SAY_BERSERK
@ SAY_HARDMODE
@ EMOTE_SURGE_OF_DARKNESS
@ EMOTE_BARRIER
@ EMOTE_VAPORS
@ EMOTE_ANIMUS
void AddSC_boss_general_vezax()
@ EVENT_BERSERK
AchievementCriteriaScript(const char *name)
int32 GetAmount() const
HookList< EffectPeriodicHandler > OnEffectPeriodic
HookList< EffectApplyHandler > AfterEffectApply
Unit * GetCaster() const
Unit * GetTarget() const
uint8 GetStackAmount() const
InstanceScript *const instance
SummonList summons
EventMap events
BossAI(Creature *creature, uint32 bossId)
void _EnterCombat()
void Talk(uint8 id, WorldObject const *whisperTarget=NULL)
bool UpdateVictim()
CreatureScript(const char *name)
Definition Map.h:238
bool IsDungeon() const
Definition Map.h:369
MapRefManager PlayerList
Definition Map.h:406
PlayerList const & GetPlayers() const
Definition Map.h:407
iterator end()
iterator begin()
LinkedListHead::Iterator< MapReference const > const_iterator
Creature * ToCreature()
Definition Object.h:207
void FinishCast(SpellCastResult result)
WorldObject * GetExplTargetWorldObject()
HookList< ObjectAreaTargetSelectHandler > OnObjectAreaTargetSelect
SpellScriptLoader(const char *name)
void DoMeleeAttackIfReady()
Definition UnitAI.cpp:28
void DoCast(uint32 spellId)
Definition UnitAI.cpp:110
Unit * SelectTarget(SelectAggroTarget targetType, uint32 position=0, float dist=0.0f, bool playerOnly=false, int32 aura=0)
Definition UnitAI.cpp:66
void DoCastAOE(uint32 spellId, bool triggered=false)
Definition UnitAI.cpp:176
Definition Unit.h:1367
bool OnCheck(Player *, Unit *target) OVERRIDE
bool OnCheck(Player *, Unit *target) OVERRIDE
CreatureAI * GetAI(Creature *creature) const OVERRIDE
CreatureAI * GetAI(Creature *creature) const OVERRIDE
CreatureAI * GetAI(Creature *creature) const OVERRIDE
AuraScript * GetAuraScript() const OVERRIDE
AuraScript * GetAuraScript() const OVERRIDE
C::value_type const & SelectRandomContainerElement(C const &container)
Definition Containers.h:48
Creature * me
const T & RAID_MODE(const T &normal10, const T &normal25) const
ScriptedAI(Creature *creature)
void SpellHitTarget(Unit *who, SpellInfo const *spell) OVERRIDE
void UpdateAI(uint32 diff) OVERRIDE
== Triggered Actions Requested ==================
Unit * CheckPlayersInRange(uint8 playersMin, float rangeMin, float rangeMax)
uint32 GetData(uint32 type) const OVERRIDE
void UpdateAI(uint32 diff) OVERRIDE
== Triggered Actions Requested ==================
void DamageTaken(Unit *, uint32 &damage) OVERRIDE
void UpdateAI(uint32 diff) OVERRIDE
== Triggered Actions Requested ==================
@ BOSS_VEZAX
Definition ulduar.h:34
AI * GetUlduarAI(T *obj)
Definition ulduar.h:336