TrinityCore
Loading...
Searching...
No Matches
boss_felmyst.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_Felmyst
20SD%Complete: 0
21SDComment:
22EndScriptData */
23
24#include "ScriptMgr.h"
25#include "InstanceScript.h"
26#include "MotionMaster.h"
27#include "ObjectAccessor.h"
28#include "ScriptedCreature.h"
29#include "SpellInfo.h"
30#include "SpellScript.h"
31#include "sunwell_plateau.h"
32#include "TemporarySummon.h"
33
35{
42 //YELL_KALECGOS = 6, Not used. After felmyst's death spawned and say this
43};
44
46{
47 //Aura
50
51 //Land phase
52 SPELL_CLEAVE = 19983,
56
57 //Flight phase
58 SPELL_VAPOR_SELECT = 45391, // fel to player, force cast 45392, 50000y selete target
59 SPELL_VAPOR_SUMMON = 45392, // player summon vapor, radius around caster, 5y,
60 SPELL_VAPOR_FORCE = 45388, // vapor to fel, force cast 45389
61 SPELL_VAPOR_CHANNEL = 45389, // fel to vapor, green beam channel
62 SPELL_VAPOR_TRIGGER = 45411, // linked to 45389, vapor to self, trigger 45410 and 46931
63 SPELL_VAPOR_DAMAGE = 46931, // vapor damage, 4000
64 SPELL_TRAIL_SUMMON = 45410, // vapor summon trail
65 SPELL_TRAIL_TRIGGER = 45399, // trail to self, trigger 45402
66 SPELL_TRAIL_DAMAGE = 45402, // trail damage, 2000 + 2000 dot
67 SPELL_DEAD_SUMMON = 45400, // summon blazing dead, 5min
69 SPELL_FOG_BREATH = 45495, // fel to self, speed burst
70 SPELL_FOG_TRIGGER = 45582, // fog to self, trigger 45782
71 SPELL_FOG_FORCE = 45782, // fog to player, force cast 45714
72 SPELL_FOG_INFORM = 45714, // player let fel cast 45717, script effect
73 SPELL_FOG_CHARM = 45717, // fel to player
74 SPELL_FOG_CHARM2 = 45726, // link to 45717
75
76 SPELL_TRANSFORM_TRIGGER = 44885, // madrigosa to self, trigger 46350
77 SPELL_TRANSFORM_VISUAL = 46350, // 46411stun?
78 SPELL_TRANSFORM_FELMYST = 45068, // become fel
80
81 //Other
85
86 // Scripts
88};
89
96
112
113struct boss_felmyst : public BossAI
114{
115 boss_felmyst(Creature* creature) : BossAI(creature, DATA_FELMYST)
116 {
117 Initialize();
118 uiBreathCount = 0;
119 breathX = 0.f;
120 breathY = 0.f;
121 }
122
124 {
126 uiFlightCount = 0;
127 }
128
130
133
135
136 void InitializeAI() override
137 {
138 // for intro sequence
140 if (Creature* madrigosa = instance->GetCreature(DATA_MADRIGOSA))
141 me->Relocate(madrigosa);
142
145 }
146
147 void Reset() override
148 {
149 Initialize();
150
152
153 me->SetDisableGravity(true);
155 me->SetCombatReach(10);
156 }
157
158 void JustEngagedWith(Unit* who) override
159 {
161
163
167 }
168
169 void AttackStart(Unit* who) override
170 {
171 if (phase != PHASE_FLIGHT)
173 }
174
175 void MoveInLineOfSight(Unit* who) override
176 {
177 if (phase != PHASE_FLIGHT)
179 }
180
181 void KilledUnit(Unit* /*victim*/) override
182 {
184 }
185
186 void JustAppeared() override
187 {
189 }
190
191 void JustDied(Unit* killer) override
192 {
194
195 BossAI::JustDied(killer);
196 }
197
198 void EnterEvadeMode(EvadeReason /*why*/) override
199 {
200 Reset();
202 }
203
204 void SpellHit(WorldObject* caster, SpellInfo const* spellInfo) override
205 {
206 Unit* unitCaster = caster->ToUnit();
207 if (!unitCaster)
208 return;
209
210 // workaround for linked aura
211 /*if (spell->Id == SPELL_VAPOR_FORCE)
212 {
213 caster->CastSpell(caster, SPELL_VAPOR_TRIGGER, true);
214 }*/
215 // workaround for mind control
216 if (spellInfo->Id == SPELL_FOG_INFORM)
217 {
218 float x, y, z;
219 unitCaster->GetPosition(x, y, z);
221 {
222 summon->SetMaxHealth(unitCaster->GetMaxHealth());
223 summon->SetHealth(unitCaster->GetMaxHealth());
224 summon->CastSpell(summon, SPELL_FOG_CHARM, true);
225 summon->CastSpell(summon, SPELL_FOG_CHARM2, true);
226 }
227 Unit::DealDamage(me, unitCaster, unitCaster->GetHealth(), nullptr, DIRECT_DAMAGE, SPELL_SCHOOL_MASK_NORMAL, nullptr, false);
228 }
229 }
230
231 void JustSummoned(Creature* summon) override
232 {
233 if (summon->GetEntry() == NPC_DEAD)
234 {
236 DoZoneInCombat(summon);
237 summon->CastSpell(summon, SPELL_DEAD_PASSIVE, true);
238 }
239
240 BossAI::JustSummoned(summon);
241 }
242
244 {
245 if (phase == PHASE_FLIGHT)
247 }
248
249 void DamageTaken(Unit*, uint32& damage, DamageEffectType /*damageType*/, SpellInfo const* /*spellInfo = nullptr*/) override
250 {
251 if (phase != PHASE_GROUND && damage >= me->GetHealth())
252 damage = 0;
253 }
254
255 void EnterPhase(PhaseFelmyst NextPhase)
256 {
257 switch (NextPhase)
258 {
259 case PHASE_GROUND:
262 me->StopMoving();
263 me->SetSpeedRate(MOVE_RUN, 2.0f);
264
270 break;
271 case PHASE_FLIGHT:
272 me->SetDisableGravity(true);
274 uiFlightCount = 0;
275 uiBreathCount = 0;
276 break;
277 default:
278 break;
279 }
280 phase = NextPhase;
281 }
282
284 {
285 switch (uiFlightCount)
286 {
287 case 0:
288 //me->AttackStop();
291 me->StopMoving();
294 break;
295 case 1:
297 break;
298 case 2:
299 {
300 Unit* target = SelectTarget(SelectTargetMethod::Random, 0, 150, true);
301 if (!target)
303
304 if (!target)
305 {
307 return;
308 }
309
310 if (Creature* Vapor = me->SummonCreature(NPC_VAPOR, target->GetPositionX() - 5 + rand32() % 10, target->GetPositionY() - 5 + rand32() % 10, target->GetPositionZ(), 0, TEMPSUMMON_TIMED_DESPAWN, 9s))
311 {
312 Vapor->AI()->AttackStart(target);
314 DoCast(Vapor, SPELL_VAPOR_CHANNEL, false); // core bug
315 Vapor->CastSpell(Vapor, SPELL_VAPOR_TRIGGER, true);
316 }
317
319 break;
320 }
321 case 3:
322 {
324 //DoCast(me, SPELL_VAPOR_SELECT); need core support
325
326 Unit* target = SelectTarget(SelectTargetMethod::Random, 0, 150, true);
327 if (!target)
329
330 if (!target)
331 {
333 return;
334 }
335
336 //target->CastSpell(target, SPELL_VAPOR_SUMMON, true); need core support
337 if (Creature* pVapor = me->SummonCreature(NPC_VAPOR, target->GetPositionX() - 5 + rand32() % 10, target->GetPositionY() - 5 + rand32() % 10, target->GetPositionZ(), 0, TEMPSUMMON_TIMED_DESPAWN, 9s))
338 {
339 if (pVapor->AI())
340 pVapor->AI()->AttackStart(target);
342 DoCast(pVapor, SPELL_VAPOR_CHANNEL, false); // core bug
343 pVapor->CastSpell(pVapor, SPELL_VAPOR_TRIGGER, true);
344 }
345
347 break;
348 }
349 case 4:
352 break;
353 case 5:
354 {
355 Unit* target = SelectTarget(SelectTargetMethod::Random, 0, 150, true);
356 if (!target)
358
359 if (!target)
360 {
362 return;
363 }
364
365 breathX = target->GetPositionX();
366 breathY = target->GetPositionY();
367 float x, y, z;
368 target->GetContactPoint(me, x, y, z, 70);
369 me->GetMotionMaster()->MovePoint(0, x, y, z+10);
370 break;
371 }
372 case 6:
374 //DoTextEmote("takes a deep breath.", nullptr);
376 break;
377 case 7:
378 {
379 DoCast(me, SPELL_FOG_BREATH, true);
380 float x, y, z;
381 me->GetPosition(x, y, z);
382 x = 2 * breathX - x;
383 y = 2 * breathY - y;
384 me->GetMotionMaster()->MovePoint(0, x, y, z);
386 break;
387 }
388 case 8:
393 if (uiBreathCount < 3)
394 uiFlightCount = 4;
395 break;
396 case 9:
398 DoStartMovement(target);
399 else
400 {
402 return;
403 }
404 break;
405 case 10:
406 me->SetDisableGravity(false);
410 break;
411 }
413 }
414
415 void UpdateAI(uint32 diff) override
416 {
417 if (!UpdateVictim())
418 {
419 if (phase == PHASE_FLIGHT && !me->IsInEvadeMode())
421 return;
422 }
423
424 events.Update(diff);
425
426 if (me->IsNonMeleeSpellCast(false))
427 return;
428
429 if (phase == PHASE_GROUND)
430 {
431 switch (events.ExecuteEvent())
432 {
433 case EVENT_BERSERK:
435 DoCast(me, SPELL_BERSERK, true);
437 break;
438 case EVENT_CLEAVE:
441 break;
442 case EVENT_CORROSION:
445 break;
446 case EVENT_GAS_NOVA:
447 DoCast(me, SPELL_GAS_NOVA, false);
449 break;
451 if (Unit* target = SelectTarget(SelectTargetMethod::Random, 0, 150, true))
452 DoCast(target, SPELL_ENCAPSULATE_CHANNEL, false);
454 break;
455 case EVENT_FLIGHT:
457 break;
458 default:
460 break;
461 }
462 }
463
464 if (phase == PHASE_FLIGHT)
465 {
466 switch (events.ExecuteEvent())
467 {
468 case EVENT_BERSERK:
470 DoCast(me, SPELL_BERSERK, true);
471 break;
474 break;
475 case EVENT_SUMMON_FOG:
476 {
477 float x, y, z;
478 me->GetPosition(x, y, z);
479 me->UpdateGroundPositionZ(x, y, z);
481 {
482 Fog->RemoveAurasDueToSpell(SPELL_TRAIL_TRIGGER);
483 Fog->CastSpell(Fog, SPELL_FOG_TRIGGER, true);
484 me->CastSpell(Fog, SPELL_FOG_FORCE, true);
485 }
486 }
488 break;
489 }
490 }
491 }
492
494 {
495 std::vector<Position> unyieldingDeadPositions;
497 {
498 if (guid.GetEntry() != entry)
499 return false;
500
501 if (guid.GetEntry() == NPC_VAPOR_TRAIL && phase == PHASE_FLIGHT)
502 if (Creature const* vapor = ObjectAccessor::GetCreature(*me, guid))
503 unyieldingDeadPositions.push_back(vapor->GetPosition());
504
505 return true;
506 });
507
508 for (Position const& unyieldingDeadPosition : unyieldingDeadPositions)
510 }
511};
512
514{
515 npc_felmyst_vapor(Creature* creature) : ScriptedAI(creature) { }
516
517 void Reset() override { }
518 void JustEngagedWith(Unit* /*who*/) override
519 {
521 //DoCast(me, SPELL_VAPOR_FORCE, true); core bug
522 }
523
524 void UpdateAI(uint32 /*diff*/) override
525 {
526 if (!me->GetVictim())
527 if (Unit* target = SelectTarget(SelectTargetMethod::Random, 0, 100, true))
528 AttackStart(target);
529 }
530};
531
533{
534 npc_felmyst_trail(Creature* creature) : ScriptedAI(creature)
535 {
537 me->SetTarget(me->GetGUID());
538 me->SetBoundingRadius(0.01f); // core bug
539 }
540
541 void Reset() override { }
542 void JustEngagedWith(Unit* /*who*/) override { }
543 void AttackStart(Unit* /*who*/) override { }
544 void MoveInLineOfSight(Unit* /*who*/) override { }
545
546 void UpdateAI(uint32 /*diff*/) override { }
547};
548
549// 45661 - Encapsulate
551{
553
554 bool Validate(SpellInfo const* /*spellInfo*/) override
555 {
557 }
558
563
568};
569
uint32_t uint32
Definition Define.h:133
@ SPECIAL
@ TEMPSUMMON_TIMED_DESPAWN
@ TEMPSUMMON_TIMED_DESPAWN_OUT_OF_COMBAT
Spells
Definition PlayerAI.cpp:32
uint32 rand32()
Definition Random.cpp:70
#define RegisterSpellScript(spell_script)
Definition ScriptMgr.h:1128
@ EMOTE_ONESHOT_LAND
@ EMOTE_ONESHOT_LIFTOFF
@ SPELL_SCHOOL_MASK_NORMAL
#define SpellHitFn(F)
@ MOVE_RUN
DamageEffectType
Definition Unit.h:352
@ DIRECT_DAMAGE
Definition Unit.h:353
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_ENCAPSULATE_EFFECT
@ 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()
Yells
InstanceScript *const instance
void JustEngagedWith(Unit *who) override
void JustDied(Unit *) override
void JustSummoned(Creature *summon) override
void _DespawnAtEvade(Seconds delayToRespawn=30s, Creature *who=nullptr)
SummonList summons
EventMap events
void Reset() override
virtual void MoveInLineOfSight(Unit *)
@ EVADE_REASON_NO_HOSTILES
Definition CreatureAI.h:94
void DoZoneInCombat(Creature *creature=nullptr)
bool UpdateVictim()
Creature *const me
Definition CreatureAI.h:82
void SetDisplayId(uint32 modelId) override
void SetTarget(ObjectGuid guid) override
CreatureTemplate const * GetCreatureTemplate() const
Definition Creature.h:186
bool IsInEvadeMode() const
Definition Creature.h:146
CreatureAI * AI() const
Definition Creature.h:154
void Update(uint32 time)
Definition EventMap.h:67
EventId ExecuteEvent()
Definition EventMap.cpp:73
void ScheduleEvent(EventId eventId, Milliseconds time, GroupIndex group=0u, PhaseIndex phase=0u)
Definition EventMap.cpp:36
Creature * GetCreature(uint32 type)
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={})
uint32 GetEntry() const
Definition ObjectGuid.h:155
static Unit * ToUnit(Object *o)
Definition Object.h:192
uint32 GetEntry() const
Definition Object.h:81
static ObjectGuid GetGUID(Object const *o)
Definition Object.h:78
uint32 Id
Definition SpellInfo.h:289
HookList< HitHandler > AfterHit
Unit * GetHitUnit() const
void DespawnIf(T const &predicate)
void DoMeleeAttackIfReady()
Definition UnitAI.cpp:54
SpellCastResult DoCastVictim(uint32 spellId, CastSpellExtraArgs const &args={})
Definition UnitAI.cpp:166
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 AttackStart(Unit *)
Definition UnitAI.cpp:30
SpellCastResult DoCast(uint32 spellId)
Definition UnitAI.cpp:106
Definition Unit.h:769
static uint32 DealDamage(Unit *attacker, Unit *victim, uint32 damage, CleanDamage const *cleanDamage=nullptr, DamageEffectType damagetype=DIRECT_DAMAGE, SpellSchoolMask damageSchoolMask=SPELL_SCHOOL_MASK_NORMAL, SpellInfo const *spellProto=nullptr, bool durabilityLoss=true)
Definition Unit.cpp:716
void CastStop(uint32 except_spellid=0)
Definition Unit.cpp:988
void StopMoving(bool force=false)
Definition Unit.cpp:10312
void InterruptNonMeleeSpells(bool withDelayed, uint32 spellid=0, bool withInstant=true)
Definition Unit.cpp:3093
MotionMaster * GetMotionMaster()
Definition Unit.h:1667
bool IsNonMeleeSpellCast(bool withDelayed, bool skipChanneled=false, bool skipAutorepeat=false, bool isAutoshoot=false, bool skipInstant=true) const
Definition Unit.cpp:3063
uint32 GetMaxHealth() const
Definition Unit.h:914
void SetNativeDisplayId(uint32 displayId)
Definition Unit.h:1586
bool SetDisableGravity(bool disable, bool updateAnimTier=true)
Definition Unit.cpp:13286
void SetBoundingRadius(float boundingRadius)
Definition Unit.h:842
void SetCombatReach(float combatReach)
Definition Unit.h:840
uint32 GetHealth() const
Definition Unit.h:913
void RemoveAurasDueToSpell(uint32 spellId, ObjectGuid casterGUID=ObjectGuid::Empty, uint8 reqEffMask=0, AuraRemoveMode removeMode=AURA_REMOVE_BY_DEFAULT)
Definition Unit.cpp:3784
Unit * GetVictim() const
Definition Unit.h:859
void SetSpeedRate(UnitMoveType mtype, float rate)
Definition Unit.cpp:8678
void HandleEmoteCommand(Emote emoteId)
Definition Unit.cpp:1568
void SetFacingTo(float ori, bool force=true, uint32 movementId=EVENT_FACE)
Definition Unit.cpp:13250
SpellCastResult CastSpell(CastSpellTargetArg const &targets, uint32 spellId, CastSpellExtraArgs const &args={ })
Definition Object.cpp:2832
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:1992
void GetContactPoint(WorldObject const *obj, float &x, float &y, float &z, float distance2d=CONTACT_DISTANCE) const
Definition Object.cpp:3271
void UpdateGroundPositionZ(float x, float y, float &z) const
Definition Object.cpp:1405
static bool ValidateSpellInfo(std::initializer_list< uint32 > spellIds)
bool Validate(SpellInfo const *) override
PrepareSpellScript(spell_felmyst_encapsulate)
TC_GAME_API Unit * GetUnit(WorldObject const &, ObjectGuid const &guid)
TC_GAME_API Creature * GetCreature(WorldObject const &u, ObjectGuid const &guid)
float GetPositionZ() const
Definition Position.h:81
float GetAbsoluteAngle(float x, float y) const
Definition Position.h:128
float GetPositionX() const
Definition Position.h:79
void GetPosition(float &x, float &y) const
Definition Position.h:84
float GetPositionY() const
Definition Position.h:80
void Relocate(float x, float y)
Definition Position.h:66
void AttackStart(Unit *) override
void DoStartMovement(Unit *target, float distance=0.0f, float angle=0.0f)
void DespawnSummons(uint32 entry)
void SpellHit(WorldObject *caster, SpellInfo const *spellInfo) override
void UpdateAI(uint32 diff) override
void EnterPhase(PhaseFelmyst NextPhase)
void JustDied(Unit *killer) override
void JustAppeared() override
void JustEngagedWith(Unit *who) override
boss_felmyst(Creature *creature)
void MoveInLineOfSight(Unit *who) override
void MovementInform(uint32, uint32) override
void DamageTaken(Unit *, uint32 &damage, DamageEffectType, SpellInfo const *) override
PhaseFelmyst phase
void Reset() override
void AttackStart(Unit *who) override
void JustSummoned(Creature *summon) override
void EnterEvadeMode(EvadeReason) override
void HandleFlightSequence()
void InitializeAI() override
void KilledUnit(Unit *) override
void AttackStart(Unit *) override
void JustEngagedWith(Unit *) override
void MoveInLineOfSight(Unit *) override
void UpdateAI(uint32) override
npc_felmyst_trail(Creature *creature)
void Reset() override
npc_felmyst_vapor(Creature *creature)
void Reset() override
void JustEngagedWith(Unit *) override
void UpdateAI(uint32) override
#define RegisterSunwellPlateauCreatureAI(ai_name)
@ DATA_FELMYST
@ DATA_PLAYER_GUID
@ DATA_MADRIGOSA
@ NPC_VAPOR_TRAIL
@ NPC_VAPOR
@ NPC_DEAD