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
144 me->SetDisplayId(me->GetDisplayId(), true);
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;
282 }
283
285 {
286 switch (uiFlightCount)
287 {
288 case 0:
289 //me->AttackStop();
292 me->StopMoving();
295 break;
296 case 1:
298 break;
299 case 2:
300 {
301 Unit* target = SelectTarget(SelectTargetMethod::Random, 0, 150, true);
302 if (!target)
304
305 if (!target)
306 {
308 return;
309 }
310
311 if (Creature* Vapor = me->SummonCreature(NPC_VAPOR, target->GetPositionX() - 5 + rand32() % 10, target->GetPositionY() - 5 + rand32() % 10, target->GetPositionZ(), 0, TEMPSUMMON_TIMED_DESPAWN, 9s))
312 {
313 Vapor->AI()->AttackStart(target);
315 DoCast(Vapor, SPELL_VAPOR_CHANNEL, false); // core bug
316 Vapor->CastSpell(Vapor, SPELL_VAPOR_TRIGGER, true);
317 }
318
320 break;
321 }
322 case 3:
323 {
325 //DoCast(me, SPELL_VAPOR_SELECT); need core support
326
327 Unit* target = SelectTarget(SelectTargetMethod::Random, 0, 150, true);
328 if (!target)
330
331 if (!target)
332 {
334 return;
335 }
336
337 //target->CastSpell(target, SPELL_VAPOR_SUMMON, true); need core support
338 if (Creature* pVapor = me->SummonCreature(NPC_VAPOR, target->GetPositionX() - 5 + rand32() % 10, target->GetPositionY() - 5 + rand32() % 10, target->GetPositionZ(), 0, TEMPSUMMON_TIMED_DESPAWN, 9s))
339 {
340 if (pVapor->AI())
341 pVapor->AI()->AttackStart(target);
343 DoCast(pVapor, SPELL_VAPOR_CHANNEL, false); // core bug
344 pVapor->CastSpell(pVapor, SPELL_VAPOR_TRIGGER, true);
345 }
346
348 break;
349 }
350 case 4:
353 break;
354 case 5:
355 {
356 Unit* target = SelectTarget(SelectTargetMethod::Random, 0, 150, true);
357 if (!target)
359
360 if (!target)
361 {
363 return;
364 }
365
366 breathX = target->GetPositionX();
367 breathY = target->GetPositionY();
368 float x, y, z;
369 target->GetContactPoint(me, x, y, z, 70);
370 me->GetMotionMaster()->MovePoint(0, x, y, z+10);
371 break;
372 }
373 case 6:
375 //DoTextEmote("takes a deep breath.", nullptr);
377 break;
378 case 7:
379 {
380 DoCast(me, SPELL_FOG_BREATH, true);
381 float x, y, z;
382 me->GetPosition(x, y, z);
383 x = 2 * breathX - x;
384 y = 2 * breathY - y;
385 me->GetMotionMaster()->MovePoint(0, x, y, z);
387 break;
388 }
389 case 8:
394 if (uiBreathCount < 3)
395 uiFlightCount = 4;
396 break;
397 case 9:
399 DoStartMovement(target);
400 else
401 {
403 return;
404 }
405 break;
406 case 10:
407 me->SetDisableGravity(false);
411 break;
412 }
414 }
415
416 void UpdateAI(uint32 diff) override
417 {
418 if (!UpdateVictim())
419 {
420 if (phase == PHASE_FLIGHT && !me->IsInEvadeMode())
422 return;
423 }
424
425 events.Update(diff);
426
427 if (me->IsNonMeleeSpellCast(false))
428 return;
429
430 if (phase == PHASE_GROUND)
431 {
432 switch (events.ExecuteEvent())
433 {
434 case EVENT_BERSERK:
436 DoCast(me, SPELL_BERSERK, true);
438 break;
439 case EVENT_CLEAVE:
442 break;
443 case EVENT_CORROSION:
446 break;
447 case EVENT_GAS_NOVA:
448 DoCast(me, SPELL_GAS_NOVA, false);
450 break;
452 if (Unit* target = SelectTarget(SelectTargetMethod::Random, 0, 150, true))
453 DoCast(target, SPELL_ENCAPSULATE_CHANNEL, false);
455 break;
456 case EVENT_FLIGHT:
458 break;
459 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{
552 bool Validate(SpellInfo const* /*spellInfo*/) override
553 {
555 }
556
561
566};
567
uint32_t uint32
Definition Define.h:154
@ SPECIAL
@ TEMPSUMMON_TIMED_DESPAWN
@ TEMPSUMMON_TIMED_DESPAWN_OUT_OF_COMBAT
Spells
Definition PlayerAI.cpp:32
uint32 rand32()
Definition Random.cpp:71
#define RegisterSpellScript(spell_script)
Definition ScriptMgr.h:1383
@ EMOTE_ONESHOT_LAND
@ EMOTE_ONESHOT_LIFTOFF
@ SPELL_SCHOOL_MASK_NORMAL
#define SpellHitFn(F)
EvadeReason
@ MOVE_RUN
DamageEffectType
@ DIRECT_DAMAGE
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
ObjectGuid const & GetGUID() const
Definition BaseEntity.h:163
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 *)
void DoZoneInCombat()
Definition CreatureAI.h:169
bool UpdateVictim()
void AttackStart(Unit *victim) override
== Triggered Actions Requested ==================
Creature *const me
Definition CreatureAI.h:63
void SetCanMelee(bool canMelee, bool fleeFromMelee=false)
void SetDisplayFromModel(uint32 modelIdx)
void SetTarget(ObjectGuid const &guid) override
void SetDisplayId(uint32 displayId, bool setNative=false) override
bool IsInEvadeMode() const
Definition Creature.h:224
CreatureAI * AI() const
Definition Creature.h:235
void Update(uint32 time)
Definition EventMap.h:77
EventId ExecuteEvent()
Definition EventMap.cpp:77
void ScheduleEvent(EventId eventId, Milliseconds time, GroupIndex group=0u, PhaseIndex phase=0u)
Definition EventMap.cpp:40
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={}, Optional< MovementFadeObject > fadeObject={}, Scripting::v2::ActionResultSetter< MovementStopReason > &&scriptResult={})
uint32 GetEntry() const
Definition ObjectGuid.h:334
uint32 GetEntry() const
Definition Object.h:89
Unit * ToUnit()
Definition Object.h:116
uint32 const Id
Definition SpellInfo.h:328
static bool ValidateSpellInfo(std::initializer_list< uint32 > spellIds)
HookList< HitHandler > AfterHit
Unit * GetHitUnit() const
void DespawnIf(T const &predicate)
virtual void AttackStart(Unit *victim)
Definition UnitAI.cpp:29
SpellCastResult DoCastVictim(uint32 spellId, CastSpellExtraArgs const &args={})
Definition UnitAI.cpp:172
Unit * SelectTarget(SelectTargetMethod targetType, uint32 offset=0, float dist=0.0f, bool playerOnly=false, bool withTank=true, int32 aura=0)
Definition UnitAI.cpp:71
SpellCastResult DoCast(uint32 spellId)
Definition UnitAI.cpp:81
Definition Unit.h:647
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:825
void CastStop(uint32 except_spellid=0)
Definition Unit.cpp:1191
bool IsNonMeleeSpellCast(bool withDelayed, bool skipChanneled=false, bool skipAutorepeat=false, bool isAutoshoot=false, bool skipInstant=true, bool skipChanneledAllowingActions=false) const
Definition Unit.cpp:3219
void StopMoving(bool force=false)
Definition Unit.cpp:10753
void InterruptNonMeleeSpells(bool withDelayed, uint32 spellid=0, bool withInstant=true)
Definition Unit.cpp:3253
MotionMaster * GetMotionMaster()
Definition Unit.h:1750
void SetBoundingRadius(float boundingRadius)
Definition Unit.h:720
void SetCombatReach(float combatReach)
Definition Unit.h:718
uint32 GetDisplayId() const
Definition Unit.h:1637
uint64 GetMaxHealth() const
Definition Unit.h:801
uint64 GetHealth() const
Definition Unit.h:800
Unit * GetVictim() const
Definition Unit.h:738
void SetSpeedRate(UnitMoveType mtype, float rate)
Definition Unit.cpp:8961
void SetFacingTo(float ori, bool force=true, uint32 movementId=EVENT_FACE)
Definition Unit.cpp:13385
void HandleEmoteCommand(Emote emoteId, Player *target=nullptr, Trinity::IteratorPair< int32 const * > spellVisualKitIds={}, int32 sequenceVariation=0)
Definition Unit.cpp:1662
bool SetDisableGravity(bool disable, bool updateAnimTier=true, bool updatePlayHoverAnim=true)
Definition Unit.cpp:13440
void RemoveAurasDueToSpell(uint32 spellId, ObjectGuid casterGUID=ObjectGuid::Empty, uint32 reqEffMask=0, AuraRemoveMode removeMode=AURA_REMOVE_BY_DEFAULT)
Definition Unit.cpp:3992
SpellCastResult CastSpell(CastSpellTargetArg const &targets, uint32 spellId, CastSpellExtraArgs const &args={ })
Definition Object.cpp:2222
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:1403
void GetContactPoint(WorldObject const *obj, float &x, float &y, float &z, float distance2d=CONTACT_DISTANCE) const
Definition Object.cpp:2781
void UpdateGroundPositionZ(float x, float y, float &z) const
Definition Object.cpp:698
bool Validate(SpellInfo const *) override
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:87
constexpr float GetPositionY() const
Definition Position.h:88
float GetAbsoluteAngle(float x, float y) const
Definition Position.h:136
constexpr void GetPosition(float &x, float &y) const
Definition Position.h:92
constexpr void Relocate(float x, float y)
Definition Position.h:74
constexpr float GetPositionZ() const
Definition Position.h:89
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
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
== 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