Project SkyFire Core
SkyFire 5.4.8 server core API documentation
Loading...
Searching...
No Matches
boss_felmyst.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/* ScriptData
7SDName: Boss_Felmyst
8SD%Complete: 0
9SDComment:
10EndScriptData */
11
12#include "ScriptMgr.h"
13#include "ScriptedCreature.h"
14#include "GridNotifiers.h"
15#include "GridNotifiersImpl.h"
16#include "Cell.h"
17#include "CellImpl.h"
18#include "sunwell_plateau.h"
19
21{
28 //YELL_KALECGOS = 6, Not used. After felmyst's death spawned and say this
29};
30
32{
33 //Aura
36
37 //Land phase
38 SPELL_CLEAVE = 19983,
42 // SPELL_ENCAPSULATE_EFFECT = 45665,
43 // SPELL_ENCAPSULATE_AOE = 45662,
44
45 //Flight phase
46 SPELL_VAPOR_SELECT = 45391, // fel to player, force cast 45392, 50000y selete target
47 SPELL_VAPOR_SUMMON = 45392, // player summon vapor, radius around caster, 5y,
48 SPELL_VAPOR_FORCE = 45388, // vapor to fel, force cast 45389
49 SPELL_VAPOR_CHANNEL = 45389, // fel to vapor, green beam channel
50 SPELL_VAPOR_TRIGGER = 45411, // linked to 45389, vapor to self, trigger 45410 and 46931
51 SPELL_VAPOR_DAMAGE = 46931, // vapor damage, 4000
52 SPELL_TRAIL_SUMMON = 45410, // vapor summon trail
53 SPELL_TRAIL_TRIGGER = 45399, // trail to self, trigger 45402
54 SPELL_TRAIL_DAMAGE = 45402, // trail damage, 2000 + 2000 dot
55 SPELL_DEAD_SUMMON = 45400, // summon blazing dead, 5min
57 SPELL_FOG_BREATH = 45495, // fel to self, speed burst
58 SPELL_FOG_TRIGGER = 45582, // fog to self, trigger 45782
59 SPELL_FOG_FORCE = 45782, // fog to player, force cast 45714
60 SPELL_FOG_INFORM = 45714, // player let fel cast 45717, script effect
61 SPELL_FOG_CHARM = 45717, // fel to player
62 SPELL_FOG_CHARM2 = 45726, // link to 45717
63
64 SPELL_TRANSFORM_TRIGGER = 44885, // madrigosa to self, trigger 46350
65 SPELL_TRANSFORM_VISUAL = 46350, // 46411stun?
66 SPELL_TRANSFORM_FELMYST = 45068, // become fel
68
69 //Other
73};
74
81
97
99{
100public:
101 boss_felmyst() : CreatureScript("boss_felmyst") { }
102
104 {
105 return new boss_felmystAI(creature);
106 }
107
109 {
110 boss_felmystAI(Creature* creature) : ScriptedAI(creature)
111 {
112 instance = creature->GetInstanceScript();
113 }
114
118
121
123
125 {
127
128 events.Reset();
129
130 uiFlightCount = 0;
131
132 me->SetDisableGravity(true);
133 me->SetFloatValue(UNIT_FIELD_BOUNDING_RADIUS, 10);
134 me->SetFloatValue(UNIT_FIELD_COMBAT_REACH, 10);
135
137 me->setActive(false);
138
139 if (instance)
141 }
142
143 void EnterCombat(Unit* /*who*/) OVERRIDE
144 {
145 events.ScheduleEvent(EVENT_BERSERK, 600000);
146
147 me->setActive(true);
152
153 if (instance)
155 }
156
158 {
159 if (phase != PHASE_FLIGHT)
161 }
162
164
165 {
166 if (phase != PHASE_FLIGHT)
168 }
169
170 void KilledUnit(Unit* /*victim*/) OVERRIDE
171 {
173 }
174
176 {
178 }
179
180 void JustDied(Unit* /*killer*/) OVERRIDE
181 {
183
184 if (instance)
186 }
187
188 void SpellHit(Unit* caster, const SpellInfo* spell) OVERRIDE
189 {
190 // workaround for linked aura
191 /*if (spell->Id == SPELL_VAPOR_FORCE)
192 {
193 caster->CastSpell(caster, SPELL_VAPOR_TRIGGER, true);
194 }*/
195 // workaround for mind control
196 if (spell->Id == SPELL_FOG_INFORM)
197 {
198 float x, y, z;
199 caster->GetPosition(x, y, z);
200 if (Unit* summon = me->SummonCreature(NPC_DEAD, x, y, z, 0, TempSummonType::TEMPSUMMON_TIMED_DESPAWN_OUT_OF_COMBAT, 5000))
201 {
202 summon->SetMaxHealth(caster->GetMaxHealth());
203 summon->SetHealth(caster->GetMaxHealth());
204 summon->CastSpell(summon, SPELL_FOG_CHARM, true);
205 summon->CastSpell(summon, SPELL_FOG_CHARM2, true);
206 }
207 me->DealDamage(caster, caster->GetHealth(), NULL, DIRECT_DAMAGE, SPELL_SCHOOL_MASK_NORMAL, NULL, false);
208 }
209 }
210
212 {
213 if (summon->GetEntry() == NPC_DEAD)
214 {
215 summon->AI()->AttackStart(SelectTarget(SELECT_TARGET_RANDOM));
216 DoZoneInCombat(summon);
217 summon->CastSpell(summon, SPELL_DEAD_PASSIVE, true);
218 }
219 }
220
222 {
223 if (phase == PHASE_FLIGHT)
224 events.ScheduleEvent(EVENT_FLIGHT_SEQUENCE, 1);
225 }
226
228 {
229 if (phase != PHASE_GROUND && damage >= me->GetHealth())
230 damage = 0;
231 }
232
233 void EnterPhase(PhaseFelmyst NextPhase)
234 {
235 switch (NextPhase)
236 {
237 case PHASE_GROUND:
238 me->CastStop(SPELL_FOG_BREATH);
239 me->RemoveAurasDueToSpell(SPELL_FOG_BREATH);
240 me->StopMoving();
241 me->SetSpeed(MOVE_RUN, 2.0f);
242
243 events.ScheduleEvent(EVENT_CLEAVE, std::rand() % 10000 + 5000);
244 events.ScheduleEvent(EVENT_CORROSION, std::rand() % 20000 + 10000);
245 events.ScheduleEvent(EVENT_GAS_NOVA, std::rand() % 20000 + 15000);
246 events.ScheduleEvent(EVENT_ENCAPSULATE, std::rand() % 25000 + 20000);
247 events.ScheduleEvent(EVENT_FLIGHT, 60000);
248 break;
249 case PHASE_FLIGHT:
250 me->SetDisableGravity(true);
251 events.ScheduleEvent(EVENT_FLIGHT_SEQUENCE, 1000);
252 uiFlightCount = 0;
253 uiBreathCount = 0;
254 break;
255 default:
256 break;
257 }
258 phase = NextPhase;
259 }
260
262 {
263 switch (uiFlightCount)
264 {
265 case 0:
266 //me->AttackStop();
267 me->GetMotionMaster()->Clear(false);
268 me->HandleEmoteCommand(EMOTE_ONESHOT_LIFTOFF);
269 me->StopMoving();
271 events.ScheduleEvent(EVENT_FLIGHT_SEQUENCE, 2000);
272 break;
273 case 1:
274 me->GetMotionMaster()->MovePoint(0, me->GetPositionX()+1, me->GetPositionY(), me->GetPositionZ()+10);
275 break;
276 case 2:
277 {
278 Unit* target = SelectTarget(SELECT_TARGET_RANDOM, 0, 150, true);
279 if (!target)
280 target = Unit::GetUnit(*me, instance ? instance->GetData64(DATA_PLAYER_GUID) : 0);
281
282 if (!target)
283 {
285 return;
286 }
287
288 Creature* Vapor = me->SummonCreature(NPC_VAPOR, target->GetPositionX()-5+rand()%10, target->GetPositionY()-5+rand()%10, target->GetPositionZ(), 0, TempSummonType::TEMPSUMMON_TIMED_DESPAWN, 9000);
289 if (Vapor)
290 {
291 Vapor->AI()->AttackStart(target);
292 me->InterruptNonMeleeSpells(false);
293 DoCast(Vapor, SPELL_VAPOR_CHANNEL, false); // core bug
294 Vapor->CastSpell(Vapor, SPELL_VAPOR_TRIGGER, true);
295 }
296
297 events.ScheduleEvent(EVENT_FLIGHT_SEQUENCE, 10000);
298 break;
299 }
300 case 3:
301 {
303 //DoCast(me, SPELL_VAPOR_SELECT); need core support
304
305 Unit* target = SelectTarget(SELECT_TARGET_RANDOM, 0, 150, true);
306 if (!target)
307 target = Unit::GetUnit(*me, instance ? instance->GetData64(DATA_PLAYER_GUID) : 0);
308
309 if (!target)
310 {
312 return;
313 }
314
315 //target->CastSpell(target, SPELL_VAPOR_SUMMON, true); need core support
316 Creature* pVapor = me->SummonCreature(NPC_VAPOR, target->GetPositionX()-5+rand()%10, target->GetPositionY()-5+rand()%10, target->GetPositionZ(), 0, TempSummonType::TEMPSUMMON_TIMED_DESPAWN, 9000);
317 if (pVapor)
318 {
319 if (pVapor->AI())
320 pVapor->AI()->AttackStart(target);
321 me->InterruptNonMeleeSpells(false);
322 DoCast(pVapor, SPELL_VAPOR_CHANNEL, false); // core bug
323 pVapor->CastSpell(pVapor, SPELL_VAPOR_TRIGGER, true);
324 }
325
326 events.ScheduleEvent(EVENT_FLIGHT_SEQUENCE, 10000);
327 break;
328 }
329 case 4:
331 events.ScheduleEvent(EVENT_FLIGHT_SEQUENCE, 1);
332 break;
333 case 5:
334 {
335 Unit* target = SelectTarget(SELECT_TARGET_RANDOM, 0, 150, true);
336 if (!target)
337 target = Unit::GetUnit(*me, instance ? instance->GetData64(DATA_PLAYER_GUID) : 0);
338
339 if (!target)
340 {
342 return;
343 }
344
345 breathX = target->GetPositionX();
346 breathY = target->GetPositionY();
347 float x, y, z;
348 target->GetContactPoint(me, x, y, z, 70);
349 me->GetMotionMaster()->MovePoint(0, x, y, z+10);
350 break;
351 }
352 case 6:
353 me->SetOrientation(me->GetAngle(breathX, breathY));
354 me->StopMoving();
355 //DoTextEmote("takes a deep breath.", NULL);
356 events.ScheduleEvent(EVENT_FLIGHT_SEQUENCE, 10000);
357 break;
358 case 7:
359 {
360 DoCast(me, SPELL_FOG_BREATH, true);
361 float x, y, z;
362 me->GetPosition(x, y, z);
363 x = 2 * breathX - x;
364 y = 2 * breathY - y;
365 me->GetMotionMaster()->MovePoint(0, x, y, z);
366 events.ScheduleEvent(EVENT_SUMMON_FOG, 1);
367 break;
368 }
369 case 8:
370 me->CastStop(SPELL_FOG_BREATH);
371 me->RemoveAurasDueToSpell(SPELL_FOG_BREATH);
373 events.ScheduleEvent(EVENT_FLIGHT_SEQUENCE, 1);
374 if (uiBreathCount < 3)
375 uiFlightCount = 4;
376 break;
377 case 9:
379 DoStartMovement(target);
380 else
381 {
383 return;
384 }
385 break;
386 case 10:
387 me->SetDisableGravity(false);
388 me->HandleEmoteCommand(EMOTE_ONESHOT_LAND);
391 break;
392 }
394 }
395
397 {
398 if (!UpdateVictim())
399 {
400 if (phase == PHASE_FLIGHT && !me->IsInEvadeMode())
402 return;
403 }
404
405 events.Update(diff);
406
407 if (me->IsNonMeleeSpellCasted(false))
408 return;
409
410 if (phase == PHASE_GROUND)
411 {
412 switch (events.ExecuteEvent())
413 {
414 case EVENT_BERSERK:
416 DoCast(me, SPELL_BERSERK, true);
417 events.ScheduleEvent(EVENT_BERSERK, 10000);
418 break;
419 case EVENT_CLEAVE:
421 events.ScheduleEvent(EVENT_CLEAVE, std::rand() % 10000 + 5000);
422 break;
423 case EVENT_CORROSION:
425 events.ScheduleEvent(EVENT_CORROSION, std::rand() % 30000 + 20000);
426 break;
427 case EVENT_GAS_NOVA:
428 DoCast(me, SPELL_GAS_NOVA, false);
429 events.ScheduleEvent(EVENT_GAS_NOVA, std::rand() % 25000 + 20000);
430 break;
432 if (Unit* target = SelectTarget(SELECT_TARGET_RANDOM, 0, 150, true))
433 DoCast(target, SPELL_ENCAPSULATE_CHANNEL, false);
434 events.ScheduleEvent(EVENT_ENCAPSULATE, std::rand() % 30000 + 25000);
435 break;
436 case EVENT_FLIGHT:
438 break;
439 default:
441 break;
442 }
443 }
444
445 if (phase == PHASE_FLIGHT)
446 {
447 switch (events.ExecuteEvent())
448 {
449 case EVENT_BERSERK:
451 DoCast(me, SPELL_BERSERK, true);
452 break;
455 break;
456 case EVENT_SUMMON_FOG:
457 {
458 float x, y, z;
459 me->GetPosition(x, y, z);
460 me->UpdateGroundPositionZ(x, y, z);
461 if (Creature* Fog = me->SummonCreature(NPC_VAPOR_TRAIL, x, y, z, 0, TempSummonType::TEMPSUMMON_TIMED_DESPAWN, 10000))
462 {
463 Fog->RemoveAurasDueToSpell(SPELL_TRAIL_TRIGGER);
464 Fog->CastSpell(Fog, SPELL_FOG_TRIGGER, true);
465 me->CastSpell(Fog, SPELL_FOG_FORCE, true);
466 }
467 }
468 events.ScheduleEvent(EVENT_SUMMON_FOG, 1000);
469 break;
470 }
471 }
472 }
473
475 {
476 std::list<Creature*> templist;
477 float x, y, z;
478 me->GetPosition(x, y, z);
479
481 Cell cell(pair);
482 cell.SetNoCreate();
483
484 Skyfire::AllCreaturesOfEntryInRange check(me, entry, 100);
487 cell.Visit(pair, cSearcher, *(me->GetMap()), *me, me->GetGridActivationRange());
488
489 for (std::list<Creature*>::const_iterator i = templist.begin(); i != templist.end(); ++i)
490 {
491 if (entry == NPC_VAPOR_TRAIL && phase == PHASE_FLIGHT)
492 {
493 (*i)->GetPosition(x, y, z);
494 me->SummonCreature(NPC_DEAD, x, y, z, 0, TempSummonType::TEMPSUMMON_TIMED_DESPAWN_OUT_OF_COMBAT, 5000);
495 }
496 (*i)->SetVisible(false);
497 (*i)->setDeathState(DeathState::JUST_DIED);
498 if ((*i)->getDeathState() == DeathState::CORPSE)
499 (*i)->RemoveCorpse();
500 }
501 }
502 };
503};
504
506{
507public:
508 npc_felmyst_vapor() : CreatureScript("npc_felmyst_vapor") { }
509
511 {
512 return new npc_felmyst_vaporAI(creature);
513 }
514
516 {
518 {
520 me->SetSpeed(MOVE_RUN, 0.8f);
521 }
522 void Reset() OVERRIDE { }
523 void EnterCombat(Unit* /*who*/) OVERRIDE
524 {
526 //DoCast(me, SPELL_VAPOR_FORCE, true); core bug
527 }
528 void UpdateAI(uint32 /*diff*/) OVERRIDE
529 {
530 if (!me->GetVictim())
531 if (Unit* target = SelectTarget(SELECT_TARGET_RANDOM, 0, 100, true))
532 AttackStart(target);
533 }
534 };
535};
536
538{
539public:
540 npc_felmyst_trail() : CreatureScript("npc_felmyst_trail") { }
541
543 {
544 return new npc_felmyst_trailAI(creature);
545 }
546
548 {
550 {
553 me->SetTarget(me->GetGUID());
554 me->SetFloatValue(UNIT_FIELD_BOUNDING_RADIUS, 0.01f); // core bug
555 }
556 void Reset() OVERRIDE { }
557 void EnterCombat(Unit* /*who*/) OVERRIDE { }
558 void AttackStart(Unit* /*who*/) OVERRIDE { }
559 void MoveInLineOfSight(Unit* /*who*/) OVERRIDE { }
560
561 void UpdateAI(uint32 /*diff*/) OVERRIDE { }
562 };
563};
564
566{
567 new boss_felmyst();
568 new npc_felmyst_vapor();
569 new npc_felmyst_trail();
570}
std::uint32_t uint32
Definition Define.h:77
#define OVERRIDE
Definition Define.h:60
TypeMapContainer< AllGridObjectTypes > GridTypeMapContainer
Definition GridDefines.h:71
CoordPair< TOTAL_NUMBER_OF_CELLS_PER_MAP > CellCoord
@ IN_PROGRESS
@ DONE
@ NOT_STARTED
@ TEMPSUMMON_TIMED_DESPAWN_OUT_OF_COMBAT
Definition Object.h:71
@ TEMPSUMMON_TIMED_DESPAWN
Definition Object.h:70
@ EMOTE_ONESHOT_LAND
@ EMOTE_ONESHOT_LIFTOFF
@ SPELL_SCHOOL_MASK_NORMAL
@ JUST_DIED
Definition Unit.h:504
@ CORPSE
Definition Unit.h:505
@ MOVE_RUN
Definition Unit.h:556
@ UNIT_FLAG_NOT_SELECTABLE
Definition Unit.h:650
@ DIRECT_DAMAGE
Definition Unit.h:614
@ SELECT_TARGET_TOPAGGRO
Definition UnitAI.h:24
@ SELECT_TARGET_RANDOM
Definition UnitAI.h:23
@ UNIT_FIELD_BOUNDING_RADIUS
@ UNIT_FIELD_FLAGS
@ UNIT_FIELD_COMBAT_REACH
@ SPELL_CLEAVE
@ EVENT_CLEAVE
@ YELL_KILL
@ YELL_DEATH
@ YELL_BERSERK
PhaseFelmyst
@ PHASE_NONE
@ PHASE_FLIGHT
@ PHASE_GROUND
@ YELL_BREATH
@ YELL_TAKEOFF
@ YELL_KILL
@ YELL_DEATH
@ YELL_BERSERK
@ YELL_BIRTH
@ AURA_NOXIOUS_FUMES
@ SPELL_CLEAVE
@ SPELL_TRANSFORM_FELMYST
@ SPELL_FOG_CHARM2
@ SPELL_TRAIL_DAMAGE
@ SPELL_DEAD_SUMMON
@ SPELL_FOG_BREATH
@ SPELL_FOG_FORCE
@ SPELL_VAPOR_SUMMON
@ SPELL_CLOUD_SUMMON
@ SPELL_TRANSFORM_TRIGGER
@ SPELL_TRAIL_SUMMON
@ SPELL_FOG_TRIGGER
@ SPELL_VAPOR_CHANNEL
@ SPELL_CORROSION
@ AURA_SUNWELL_RADIANCE
@ SPELL_DEAD_PASSIVE
@ SPELL_FOG_CHARM
@ SPELL_VAPOR_SELECT
@ SPELL_GAS_NOVA
@ SPELL_ENCAPSULATE_CHANNEL
@ SPELL_FOG_INFORM
@ SPELL_CLOUD_VISUAL
@ SPELL_TRANSFORM_VISUAL
@ SPELL_VAPOR_DAMAGE
@ SPELL_BERSERK
@ SPELL_TRAIL_TRIGGER
@ SPELL_VAPOR_TRIGGER
@ SPELL_VAPOR_FORCE
@ SPELL_FELMYST_SUMMON
EventFelmyst
@ EVENT_CORROSION
@ EVENT_FLIGHT_SEQUENCE
@ EVENT_SUMMON_FOG
@ EVENT_FLIGHT
@ EVENT_NONE
@ EVENT_BERSERK
@ EVENT_SUMMON_DEAD
@ EVENT_CLEAVE
@ EVENT_ENCAPSULATE
@ EVENT_GAS_NOVA
void AddSC_boss_felmyst()
#define SPELL_BERSERK
@ EVENT_BERSERK
virtual void MoveInLineOfSight(Unit *)
void DoZoneInCombat(Creature *creature=NULL, float maxRangeToNearestTarget=50.0f)
void Talk(uint8 id, WorldObject const *whisperTarget=NULL)
bool UpdateVictim()
virtual void EnterEvadeMode()
CreatureAI * AI() const
Definition Creature.h:483
CreatureScript(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 DoCastVictim(uint32 spellId, bool triggered=false)
Definition UnitAI.cpp:168
virtual void AttackStart(Unit *)
Definition UnitAI.cpp:16
Definition Unit.h:1367
void CastSpell(SpellCastTargets const &targets, SpellInfo const *spellInfo, CustomSpellValues const *value, TriggerCastFlags triggerFlags=TRIGGERED_NONE, Item *castItem=NULL, AuraEffect const *triggeredByAura=NULL, uint64 originalCaster=0)
static Unit * GetUnit(WorldObject &object, uint64 guid)
Definition Unit.cpp:4895
InstanceScript * GetInstanceScript()
Definition Object.cpp:1612
void GetContactPoint(WorldObject const *obj, float &x, float &y, float &z, float distance2d=CONTACT_DISTANCE) const
Definition Object.cpp:3094
CreatureAI * GetAI(Creature *creature) const OVERRIDE
CreatureAI * GetAI(Creature *creature) const OVERRIDE
CreatureAI * GetAI(Creature *creature) const OVERRIDE
CellCoord ComputeCellCoord(float x, float y)
Definition Cell.h:37
void SetNoCreate()
Definition Cell.h:66
void Visit(CellCoord const &, TypeContainerVisitor< T, CONTAINER > &visitor, Map &, WorldObject const &, float) const
Definition CellImpl.h:109
float GetPositionZ() const
Definition Object.h:330
float GetPositionX() const
Definition Object.h:328
float GetPositionY() const
Definition Object.h:329
Creature * me
ScriptedAI(Creature *creature)
void AttackStart(Unit *) OVERRIDE
void DoStartMovement(Unit *target, float distance=0.0f, float angle=0.0f)
void JustDied(Unit *) OVERRIDE
void UpdateAI(uint32 diff) OVERRIDE
== Triggered Actions Requested ==================
void MovementInform(uint32, uint32) OVERRIDE
void JustSummoned(Creature *summon) OVERRIDE
void SpellHit(Unit *caster, const SpellInfo *spell) OVERRIDE
void EnterPhase(PhaseFelmyst NextPhase)
void AttackStart(Unit *who) OVERRIDE
void DamageTaken(Unit *, uint32 &damage) OVERRIDE
void EnterCombat(Unit *) OVERRIDE
void MoveInLineOfSight(Unit *who) OVERRIDE
boss_felmystAI(Creature *creature)
void KilledUnit(Unit *) OVERRIDE
void DespawnSummons(uint32 entry)
void UpdateAI(uint32) OVERRIDE
== Triggered Actions Requested ==================
void UpdateAI(uint32) OVERRIDE
== Triggered Actions Requested ==================
@ NPC_VAPOR_TRAIL
@ NPC_VAPOR
@ NPC_DEAD
@ DATA_PLAYER_GUID
@ DATA_FELMYST_EVENT