TrinityCore
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 "sunwell_plateau.h"
31#include "TemporarySummon.h"
32
34{
41 //YELL_KALECGOS = 6, Not used. After felmyst's death spawned and say this
42};
43
45{
46 //Aura
49
50 //Land phase
51 SPELL_CLEAVE = 19983,
55 // SPELL_ENCAPSULATE_EFFECT = 45665,
56 // SPELL_ENCAPSULATE_AOE = 45662,
57
58 //Flight phase
59 SPELL_VAPOR_SELECT = 45391, // fel to player, force cast 45392, 50000y selete target
60 SPELL_VAPOR_SUMMON = 45392, // player summon vapor, radius around caster, 5y,
61 SPELL_VAPOR_FORCE = 45388, // vapor to fel, force cast 45389
62 SPELL_VAPOR_CHANNEL = 45389, // fel to vapor, green beam channel
63 SPELL_VAPOR_TRIGGER = 45411, // linked to 45389, vapor to self, trigger 45410 and 46931
64 SPELL_VAPOR_DAMAGE = 46931, // vapor damage, 4000
65 SPELL_TRAIL_SUMMON = 45410, // vapor summon trail
66 SPELL_TRAIL_TRIGGER = 45399, // trail to self, trigger 45402
67 SPELL_TRAIL_DAMAGE = 45402, // trail damage, 2000 + 2000 dot
68 SPELL_DEAD_SUMMON = 45400, // summon blazing dead, 5min
70 SPELL_FOG_BREATH = 45495, // fel to self, speed burst
71 SPELL_FOG_TRIGGER = 45582, // fog to self, trigger 45782
72 SPELL_FOG_FORCE = 45782, // fog to player, force cast 45714
73 SPELL_FOG_INFORM = 45714, // player let fel cast 45717, script effect
74 SPELL_FOG_CHARM = 45717, // fel to player
75 SPELL_FOG_CHARM2 = 45726, // link to 45717
76
77 SPELL_TRANSFORM_TRIGGER = 44885, // madrigosa to self, trigger 46350
78 SPELL_TRANSFORM_VISUAL = 46350, // 46411stun?
79 SPELL_TRANSFORM_FELMYST = 45068, // become fel
81
82 //Other
85 SPELL_CLOUD_SUMMON = 45884
86};
87
89{
93};
94
96{
99
105
110
111struct boss_felmyst : public BossAI
112{
113 boss_felmyst(Creature* creature) : BossAI(creature, DATA_FELMYST)
114 {
115 Initialize();
116 uiBreathCount = 0;
117 breathX = 0.f;
118 breathY = 0.f;
119 }
120
122 {
124 uiFlightCount = 0;
125 }
126
128
131
133
134 void InitializeAI() override
135 {
136 // for intro sequence
138 if (Creature* madrigosa = instance->GetCreature(DATA_MADRIGOSA))
139 me->Relocate(madrigosa);
140
142 me->SetDisplayId(me->GetDisplayId(), true);
143 }
144
145 void Reset() override
146 {
147 Initialize();
148
150
151 me->SetDisableGravity(true);
153 me->SetCombatReach(10);
154 }
155
156 void JustEngagedWith(Unit* who) override
157 {
159
161
165 }
166
167 void AttackStart(Unit* who) override
168 {
169 if (phase != PHASE_FLIGHT)
171 }
172
173 void MoveInLineOfSight(Unit* who) override
174 {
175 if (phase != PHASE_FLIGHT)
177 }
178
179 void KilledUnit(Unit* /*victim*/) override
180 {
182 }
183
184 void JustAppeared() override
185 {
187 }
188
189 void JustDied(Unit* killer) override
190 {
192
193 BossAI::JustDied(killer);
194 }
195
196 void EnterEvadeMode(EvadeReason /*why*/) override
197 {
198 Reset();
200 }
201
202 void SpellHit(WorldObject* caster, SpellInfo const* spellInfo) override
203 {
204 Unit* unitCaster = caster->ToUnit();
205 if (!unitCaster)
206 return;
207
208 // workaround for linked aura
209 /*if (spell->Id == SPELL_VAPOR_FORCE)
210 {
211 caster->CastSpell(caster, SPELL_VAPOR_TRIGGER, true);
212 }*/
213 // workaround for mind control
214 if (spellInfo->Id == SPELL_FOG_INFORM)
215 {
216 float x, y, z;
217 unitCaster->GetPosition(x, y, z);
219 {
220 summon->SetMaxHealth(unitCaster->GetMaxHealth());
221 summon->SetHealth(unitCaster->GetMaxHealth());
222 summon->CastSpell(summon, SPELL_FOG_CHARM, true);
223 summon->CastSpell(summon, SPELL_FOG_CHARM2, true);
224 }
225 Unit::DealDamage(me, unitCaster, unitCaster->GetHealth(), nullptr, DIRECT_DAMAGE, SPELL_SCHOOL_MASK_NORMAL, nullptr, false);
226 }
227 }
228
229 void JustSummoned(Creature* summon) override
230 {
231 if (summon->GetEntry() == NPC_DEAD)
232 {
234 DoZoneInCombat(summon);
235 summon->CastSpell(summon, SPELL_DEAD_PASSIVE, true);
236 }
237
238 BossAI::JustSummoned(summon);
239 }
240
242 {
243 if (phase == PHASE_FLIGHT)
245 }
246
247 void DamageTaken(Unit*, uint32& damage, DamageEffectType /*damageType*/, SpellInfo const* /*spellInfo = nullptr*/) override
248 {
249 if (phase != PHASE_GROUND && damage >= me->GetHealth())
250 damage = 0;
251 }
252
253 void EnterPhase(PhaseFelmyst NextPhase)
254 {
255 switch (NextPhase)
256 {
257 case PHASE_GROUND:
260 me->StopMoving();
261 me->SetSpeedRate(MOVE_RUN, 2.0f);
262
268 break;
269 case PHASE_FLIGHT:
270 me->SetDisableGravity(true);
272 uiFlightCount = 0;
273 uiBreathCount = 0;
274 break;
275 default:
276 break;
277 }
278 phase = NextPhase;
280 }
281
283 {
284 switch (uiFlightCount)
285 {
286 case 0:
287 //me->AttackStop();
290 me->StopMoving();
293 break;
294 case 1:
296 break;
297 case 2:
298 {
299 Unit* target = SelectTarget(SelectTargetMethod::Random, 0, 150, true);
300 if (!target)
302
303 if (!target)
304 {
306 return;
307 }
308
309 if (Creature* Vapor = me->SummonCreature(NPC_VAPOR, target->GetPositionX() - 5 + rand32() % 10, target->GetPositionY() - 5 + rand32() % 10, target->GetPositionZ(), 0, TEMPSUMMON_TIMED_DESPAWN, 9s))
310 {
311 Vapor->AI()->AttackStart(target);
313 DoCast(Vapor, SPELL_VAPOR_CHANNEL, false); // core bug
314 Vapor->CastSpell(Vapor, SPELL_VAPOR_TRIGGER, true);
315 }
316
318 break;
319 }
320 case 3:
321 {
323 //DoCast(me, SPELL_VAPOR_SELECT); need core support
324
325 Unit* target = SelectTarget(SelectTargetMethod::Random, 0, 150, true);
326 if (!target)
328
329 if (!target)
330 {
332 return;
333 }
334
335 //target->CastSpell(target, SPELL_VAPOR_SUMMON, true); need core support
336 if (Creature* pVapor = me->SummonCreature(NPC_VAPOR, target->GetPositionX() - 5 + rand32() % 10, target->GetPositionY() - 5 + rand32() % 10, target->GetPositionZ(), 0, TEMPSUMMON_TIMED_DESPAWN, 9s))
337 {
338 if (pVapor->AI())
339 pVapor->AI()->AttackStart(target);
341 DoCast(pVapor, SPELL_VAPOR_CHANNEL, false); // core bug
342 pVapor->CastSpell(pVapor, SPELL_VAPOR_TRIGGER, true);
343 }
344
346 break;
347 }
348 case 4:
351 break;
352 case 5:
353 {
354 Unit* target = SelectTarget(SelectTargetMethod::Random, 0, 150, true);
355 if (!target)
357
358 if (!target)
359 {
361 return;
362 }
363
364 breathX = target->GetPositionX();
365 breathY = target->GetPositionY();
366 float x, y, z;
367 target->GetContactPoint(me, x, y, z, 70);
368 me->GetMotionMaster()->MovePoint(0, x, y, z+10);
369 break;
370 }
371 case 6:
373 //DoTextEmote("takes a deep breath.", nullptr);
375 break;
376 case 7:
377 {
378 DoCast(me, SPELL_FOG_BREATH, true);
379 float x, y, z;
380 me->GetPosition(x, y, z);
381 x = 2 * breathX - x;
382 y = 2 * breathY - y;
383 me->GetMotionMaster()->MovePoint(0, x, y, z);
385 break;
386 }
387 case 8:
392 if (uiBreathCount < 3)
393 uiFlightCount = 4;
394 break;
395 case 9:
397 DoStartMovement(target);
398 else
399 {
401 return;
402 }
403 break;
404 case 10:
405 me->SetDisableGravity(false);
409 break;
410 }
412 }
413
414 void UpdateAI(uint32 diff) override
415 {
416 if (!UpdateVictim())
417 {
418 if (phase == PHASE_FLIGHT && !me->IsInEvadeMode())
420 return;
421 }
422
423 events.Update(diff);
424
425 if (me->IsNonMeleeSpellCast(false))
426 return;
427
428 if (phase == PHASE_GROUND)
429 {
430 switch (events.ExecuteEvent())
431 {
432 case EVENT_BERSERK:
434 DoCast(me, SPELL_BERSERK, true);
436 break;
437 case EVENT_CLEAVE:
440 break;
441 case EVENT_CORROSION:
444 break;
445 case EVENT_GAS_NOVA:
446 DoCast(me, SPELL_GAS_NOVA, false);
448 break;
450 if (Unit* target = SelectTarget(SelectTargetMethod::Random, 0, 150, true))
451 DoCast(target, SPELL_ENCAPSULATE_CHANNEL, false);
453 break;
454 case EVENT_FLIGHT:
456 break;
457 default:
458 break;
459 }
460 }
461
462 if (phase == PHASE_FLIGHT)
463 {
464 switch (events.ExecuteEvent())
465 {
466 case EVENT_BERSERK:
468 DoCast(me, SPELL_BERSERK, true);
469 break;
472 break;
473 case EVENT_SUMMON_FOG:
474 {
475 float x, y, z;
476 me->GetPosition(x, y, z);
477 me->UpdateGroundPositionZ(x, y, z);
479 {
480 Fog->RemoveAurasDueToSpell(SPELL_TRAIL_TRIGGER);
481 Fog->CastSpell(Fog, SPELL_FOG_TRIGGER, true);
482 me->CastSpell(Fog, SPELL_FOG_FORCE, true);
483 }
484 }
486 break;
487 }
488 }
489 }
490
492 {
493 std::vector<Position> unyieldingDeadPositions;
495 {
496 if (guid.GetEntry() != entry)
497 return false;
498
500 if (Creature const* vapor = ObjectAccessor::GetCreature(*me, guid))
501 unyieldingDeadPositions.push_back(vapor->GetPosition());
502
503 return true;
504 });
505
506 for (Position const& unyieldingDeadPosition : unyieldingDeadPositions)
508 }
509};
510
512{
513 npc_felmyst_vapor(Creature* creature) : ScriptedAI(creature) { }
514
515 void Reset() override { }
516 void JustEngagedWith(Unit* /*who*/) override
517 {
519 //DoCast(me, SPELL_VAPOR_FORCE, true); core bug
520 }
521
522 void UpdateAI(uint32 /*diff*/) override
523 {
524 if (!me->GetVictim())
525 if (Unit* target = SelectTarget(SelectTargetMethod::Random, 0, 100, true))
526 AttackStart(target);
527 }
528};
529
531{
532 npc_felmyst_trail(Creature* creature) : ScriptedAI(creature)
533 {
535 me->SetTarget(me->GetGUID());
536 me->SetBoundingRadius(0.01f); // core bug
537 }
538
539 void Reset() override { }
540 void JustEngagedWith(Unit* /*who*/) override { }
541 void AttackStart(Unit* /*who*/) override { }
542 void MoveInLineOfSight(Unit* /*who*/) override { }
543
544 void UpdateAI(uint32 /*diff*/) override { }
545};
546
548{
552}
uint32_t uint32
Definition: Define.h:142
@ SPECIAL
@ TEMPSUMMON_TIMED_DESPAWN
Definition: ObjectDefines.h:65
@ TEMPSUMMON_TIMED_DESPAWN_OUT_OF_COMBAT
Definition: ObjectDefines.h:66
Spells
Definition: PlayerAI.cpp:32
uint32 rand32()
Definition: Random.cpp:70
if(posix_memalign(&__mallocedMemory, __align, __size)) return NULL
@ EMOTE_ONESHOT_LAND
@ EMOTE_ONESHOT_LIFTOFF
@ SPELL_SCHOOL_MASK_NORMAL
EvadeReason
Definition: UnitAICommon.h:30
@ MOVE_RUN
Definition: UnitDefines.h:118
DamageEffectType
Definition: UnitDefines.h:131
@ DIRECT_DAMAGE
Definition: UnitDefines.h:132
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()
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 *)
Definition: CreatureAI.cpp:122
void DoZoneInCombat()
Definition: CreatureAI.h:161
void Talk(uint8 id, WorldObject const *whisperTarget=nullptr)
Definition: CreatureAI.cpp:56
bool UpdateVictim()
Definition: CreatureAI.cpp:245
void AttackStart(Unit *victim) override
== Triggered Actions Requested ==================
Definition: CreatureAI.cpp:328
Creature *const me
Definition: CreatureAI.h:61
void SetCanMelee(bool canMelee, bool fleeFromMelee=false)
Definition: Creature.cpp:2822
void SetDisplayFromModel(uint32 modelIdx)
Definition: Creature.cpp:3413
void SetTarget(ObjectGuid const &guid) override
Definition: Creature.cpp:3419
void SetDisplayId(uint32 displayId, bool setNative=false) override
Definition: Creature.cpp:3402
bool IsInEvadeMode() const
Definition: Creature.h:203
CreatureAI * AI() const
Definition: Creature.h:214
uint32 ExecuteEvent()
Definition: EventMap.cpp:73
void Update(uint32 time)
Definition: EventMap.h:56
void ScheduleEvent(uint32 eventId, Milliseconds time, uint32 group=0, uint8 phase=0)
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={}, Optional< float > speed={}, MovementWalkRunSpeedSelectionMode speedSelectionMode=MovementWalkRunSpeedSelectionMode::Default, Optional< float > closeEnoughDistance={})
uint32 GetEntry() const
Definition: ObjectGuid.h:291
static Unit * ToUnit(Object *o)
Definition: Object.h:225
uint32 GetEntry() const
Definition: Object.h:161
static ObjectGuid GetGUID(Object const *o)
Definition: Object.h:159
uint32 const Id
Definition: SpellInfo.h:325
void DespawnIf(T const &predicate)
SpellCastResult DoCastVictim(uint32 spellId, CastSpellExtraArgs const &args={})
Definition: UnitAI.cpp:180
Unit * SelectTarget(SelectTargetMethod targetType, uint32 offset=0, float dist=0.0f, bool playerOnly=false, bool withTank=true, int32 aura=0)
Definition: UnitAI.cpp:79
SpellCastResult DoCast(uint32 spellId)
Definition: UnitAI.cpp:89
Definition: Unit.h:627
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:769
void CastStop(uint32 except_spellid=0)
Definition: Unit.cpp:1135
void InterruptNonMeleeSpells(bool withDelayed, uint32 spellid=0, bool withInstant=true)
Definition: Unit.cpp:3089
MotionMaster * GetMotionMaster()
Definition: Unit.h:1652
bool IsNonMeleeSpellCast(bool withDelayed, bool skipChanneled=false, bool skipAutorepeat=false, bool isAutoshoot=false, bool skipInstant=true) const
Definition: Unit.cpp:3059
void StopMoving()
Definition: Unit.cpp:10049
bool SetDisableGravity(bool disable, bool updateAnimTier=true)
Definition: Unit.cpp:12725
void SetBoundingRadius(float boundingRadius)
Definition: Unit.h:697
void SetCombatReach(float combatReach)
Definition: Unit.h:695
uint32 GetDisplayId() const
Definition: Unit.h:1567
uint64 GetMaxHealth() const
Definition: Unit.h:777
uint64 GetHealth() const
Definition: Unit.h:776
Unit * GetVictim() const
Definition: Unit.h:715
void SetSpeedRate(UnitMoveType mtype, float rate)
Definition: Unit.cpp:8525
void SetFacingTo(float const ori, bool force=true)
Definition: Unit.cpp:12653
void HandleEmoteCommand(Emote emoteId, Player *target=nullptr, Trinity::IteratorPair< int32 const * > spellVisualKitIds={}, int32 sequenceVariation=0)
Definition: Unit.cpp:1598
void RemoveAurasDueToSpell(uint32 spellId, ObjectGuid casterGUID=ObjectGuid::Empty, uint32 reqEffMask=0, AuraRemoveMode removeMode=AURA_REMOVE_BY_DEFAULT)
Definition: Unit.cpp:3831
SpellCastResult CastSpell(CastSpellTargetArg const &targets, uint32 spellId, CastSpellExtraArgs const &args={ })
Definition: Object.cpp:2896
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:2025
void GetContactPoint(WorldObject const *obj, float &x, float &y, float &z, float distance2d=CONTACT_DISTANCE) const
Definition: Object.cpp:3430
void UpdateGroundPositionZ(float x, float y, float &z) const
Definition: Object.cpp:1360
TC_GAME_API Unit * GetUnit(WorldObject const &, ObjectGuid const &guid)
TC_GAME_API Creature * GetCreature(WorldObject const &u, ObjectGuid const &guid)
constexpr float GetPositionX() const
Definition: Position.h:76
constexpr float GetPositionY() const
Definition: Position.h:77
float GetAbsoluteAngle(float x, float y) const
Definition: Position.h:125
constexpr void GetPosition(float &x, float &y) const
Definition: Position.h:81
constexpr void Relocate(float x, float y)
Definition: Position.h:63
constexpr float GetPositionZ() const
Definition: Position.h:78
void AttackStart(Unit *) override
== Triggered Actions Requested ==================
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
uint32 uiBreathCount
uint32 uiFlightCount
void DamageTaken(Unit *, uint32 &damage, DamageEffectType, SpellInfo const *) override
PhaseFelmyst phase
void Reset() override
void AttackStart(Unit *who) override
== Triggered Actions Requested ==================
void JustSummoned(Creature *summon) override
void EnterEvadeMode(EvadeReason) override
void HandleFlightSequence()
void InitializeAI() override
void KilledUnit(Unit *) override
void AttackStart(Unit *) override
== Triggered Actions Requested ==================
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