mirror of
https://github.com/TrinityCore/TrinityCore.git
synced 2026-01-15 23:20:36 +01:00
Scripts/The Sunwell: Move Brutallus and Felmyst to BossAI
This commit is contained in:
@@ -64,284 +64,268 @@ enum Spells
|
||||
SPELL_INTRO_ENCAPSULATE_CHANELLING = 45661
|
||||
};
|
||||
|
||||
class boss_brutallus : public CreatureScript
|
||||
struct boss_brutallus : public BossAI
|
||||
{
|
||||
public:
|
||||
boss_brutallus() : CreatureScript("boss_brutallus") { }
|
||||
|
||||
struct boss_brutallusAI : public ScriptedAI
|
||||
boss_brutallus(Creature* creature) : BossAI(creature, DATA_BRUTALLUS)
|
||||
{
|
||||
boss_brutallusAI(Creature* creature) : ScriptedAI(creature)
|
||||
Initialize();
|
||||
Intro = true;
|
||||
}
|
||||
|
||||
void Initialize()
|
||||
{
|
||||
SlashTimer = 11000;
|
||||
StompTimer = 30000;
|
||||
BurnTimer = 60000;
|
||||
BerserkTimer = 360000;
|
||||
|
||||
IntroPhase = 0;
|
||||
IntroPhaseTimer = 0;
|
||||
IntroFrostBoltTimer = 0;
|
||||
|
||||
IsIntro = false;
|
||||
Enraged = false;
|
||||
}
|
||||
|
||||
uint32 SlashTimer;
|
||||
uint32 BurnTimer;
|
||||
uint32 StompTimer;
|
||||
uint32 BerserkTimer;
|
||||
|
||||
uint32 IntroPhase;
|
||||
uint32 IntroPhaseTimer;
|
||||
uint32 IntroFrostBoltTimer;
|
||||
|
||||
bool Intro;
|
||||
bool IsIntro;
|
||||
bool Enraged;
|
||||
|
||||
void Reset() override
|
||||
{
|
||||
Initialize();
|
||||
|
||||
DoCast(me, SPELL_DUAL_WIELD, true);
|
||||
|
||||
BossAI::Reset();
|
||||
}
|
||||
|
||||
void JustEngagedWith(Unit* who) override
|
||||
{
|
||||
Talk(YELL_AGGRO);
|
||||
|
||||
BossAI::JustEngagedWith(who);
|
||||
}
|
||||
|
||||
void KilledUnit(Unit* /*victim*/) override
|
||||
{
|
||||
Talk(YELL_KILL);
|
||||
}
|
||||
|
||||
void JustDied(Unit* killer) override
|
||||
{
|
||||
Talk(YELL_DEATH);
|
||||
|
||||
instance->SetBossState(DATA_FELMYST, SPECIAL);
|
||||
BossAI::JustDied(killer);
|
||||
}
|
||||
|
||||
void EnterEvadeMode(EvadeReason why) override
|
||||
{
|
||||
if (!Intro)
|
||||
BossAI::EnterEvadeMode(why);
|
||||
}
|
||||
|
||||
void StartIntro()
|
||||
{
|
||||
if (!Intro || IsIntro)
|
||||
return;
|
||||
|
||||
if (Creature* Madrigosa = instance->GetCreature(DATA_MADRIGOSA))
|
||||
{
|
||||
Initialize();
|
||||
instance = creature->GetInstanceScript();
|
||||
Intro = true;
|
||||
Madrigosa->Respawn();
|
||||
Madrigosa->setActive(true);
|
||||
Madrigosa->SetFarVisible(true);
|
||||
IsIntro = true;
|
||||
Madrigosa->SetMaxHealth(me->GetMaxHealth());
|
||||
Madrigosa->SetHealth(me->GetMaxHealth());
|
||||
me->SetUnitFlag(UNIT_FLAG_NON_ATTACKABLE);
|
||||
me->Attack(Madrigosa, true);
|
||||
Madrigosa->Attack(me, true);
|
||||
}
|
||||
|
||||
void Initialize()
|
||||
else
|
||||
{
|
||||
SlashTimer = 11000;
|
||||
StompTimer = 30000;
|
||||
BurnTimer = 60000;
|
||||
BerserkTimer = 360000;
|
||||
|
||||
IntroPhase = 0;
|
||||
IntroPhaseTimer = 0;
|
||||
IntroFrostBoltTimer = 0;
|
||||
|
||||
IsIntro = false;
|
||||
Enraged = false;
|
||||
// Madrigosa not found, end intro
|
||||
TC_LOG_ERROR("scripts", "Madrigosa was not found");
|
||||
EndIntro();
|
||||
}
|
||||
}
|
||||
|
||||
InstanceScript* instance;
|
||||
void EndIntro()
|
||||
{
|
||||
me->RemoveUnitFlag(UNIT_FLAG_NON_ATTACKABLE);
|
||||
Intro = false;
|
||||
IsIntro = false;
|
||||
}
|
||||
|
||||
uint32 SlashTimer;
|
||||
uint32 BurnTimer;
|
||||
uint32 StompTimer;
|
||||
uint32 BerserkTimer;
|
||||
void AttackStart(Unit* who) override
|
||||
{
|
||||
if (!who || Intro || IsIntro)
|
||||
return;
|
||||
BossAI::AttackStart(who);
|
||||
}
|
||||
|
||||
uint32 IntroPhase;
|
||||
uint32 IntroPhaseTimer;
|
||||
uint32 IntroFrostBoltTimer;
|
||||
void DoIntro()
|
||||
{
|
||||
Creature* Madrigosa = instance->GetCreature(DATA_MADRIGOSA);
|
||||
if (!Madrigosa)
|
||||
return;
|
||||
|
||||
bool Intro;
|
||||
bool IsIntro;
|
||||
bool Enraged;
|
||||
|
||||
void Reset() override
|
||||
switch (IntroPhase)
|
||||
{
|
||||
Initialize();
|
||||
|
||||
DoCast(me, SPELL_DUAL_WIELD, true);
|
||||
|
||||
instance->SetBossState(DATA_BRUTALLUS, NOT_STARTED);
|
||||
}
|
||||
|
||||
void JustEngagedWith(Unit* /*who*/) override
|
||||
{
|
||||
Talk(YELL_AGGRO);
|
||||
|
||||
instance->SetBossState(DATA_BRUTALLUS, IN_PROGRESS);
|
||||
}
|
||||
|
||||
void KilledUnit(Unit* /*victim*/) override
|
||||
{
|
||||
Talk(YELL_KILL);
|
||||
}
|
||||
|
||||
void JustDied(Unit* /*killer*/) override
|
||||
{
|
||||
Talk(YELL_DEATH);
|
||||
|
||||
instance->SetBossState(DATA_BRUTALLUS, DONE);
|
||||
float x, y, z;
|
||||
me->GetPosition(x, y, z);
|
||||
me->SummonCreature(NPC_FELMYST, x, y, z + 30, me->GetOrientation(), TEMPSUMMON_MANUAL_DESPAWN);
|
||||
}
|
||||
|
||||
void EnterEvadeMode(EvadeReason why) override
|
||||
{
|
||||
if (!Intro)
|
||||
ScriptedAI::EnterEvadeMode(why);
|
||||
}
|
||||
|
||||
void StartIntro()
|
||||
{
|
||||
if (!Intro || IsIntro)
|
||||
return;
|
||||
|
||||
if (Creature* Madrigosa = instance->GetCreature(DATA_MADRIGOSA))
|
||||
{
|
||||
Madrigosa->Respawn();
|
||||
Madrigosa->setActive(true);
|
||||
Madrigosa->SetFarVisible(true);
|
||||
IsIntro = true;
|
||||
Madrigosa->SetMaxHealth(me->GetMaxHealth());
|
||||
Madrigosa->SetHealth(me->GetMaxHealth());
|
||||
me->SetUnitFlag(UNIT_FLAG_NON_ATTACKABLE);
|
||||
me->Attack(Madrigosa, true);
|
||||
Madrigosa->Attack(me, true);
|
||||
}
|
||||
else
|
||||
{
|
||||
// Madrigosa not found, end intro
|
||||
TC_LOG_ERROR("scripts", "Madrigosa was not found");
|
||||
case 0:
|
||||
Madrigosa->AI()->Talk(YELL_MADR_ICE_BARRIER);
|
||||
IntroPhaseTimer = 7000;
|
||||
++IntroPhase;
|
||||
break;
|
||||
case 1:
|
||||
me->SetFacingToObject(Madrigosa);
|
||||
Madrigosa->SetFacingToObject(me);
|
||||
Madrigosa->AI()->Talk(YELL_MADR_INTRO, me);
|
||||
IntroPhaseTimer = 9000;
|
||||
++IntroPhase;
|
||||
break;
|
||||
case 2:
|
||||
Talk(YELL_INTRO, Madrigosa);
|
||||
IntroPhaseTimer = 13000;
|
||||
++IntroPhase;
|
||||
break;
|
||||
case 3:
|
||||
DoCast(me, SPELL_INTRO_FROST_BLAST);
|
||||
Madrigosa->SetDisableGravity(true);
|
||||
me->AttackStop();
|
||||
Madrigosa->AttackStop();
|
||||
IntroFrostBoltTimer = 3000;
|
||||
IntroPhaseTimer = 28000;
|
||||
++IntroPhase;
|
||||
break;
|
||||
case 4:
|
||||
Talk(YELL_INTRO_BREAK_ICE);
|
||||
IntroPhaseTimer = 6000;
|
||||
++IntroPhase;
|
||||
break;
|
||||
case 5:
|
||||
Madrigosa->CastSpell(me, SPELL_INTRO_ENCAPSULATE_CHANELLING, false);
|
||||
Madrigosa->AI()->Talk(YELL_MADR_TRAP);
|
||||
DoCast(me, SPELL_INTRO_ENCAPSULATE);
|
||||
IntroPhaseTimer = 11000;
|
||||
++IntroPhase;
|
||||
break;
|
||||
case 6:
|
||||
Talk(YELL_INTRO_CHARGE);
|
||||
IntroPhaseTimer = 5000;
|
||||
++IntroPhase;
|
||||
break;
|
||||
case 7:
|
||||
Unit::Kill(me, Madrigosa);
|
||||
Madrigosa->AI()->Talk(YELL_MADR_DEATH);
|
||||
me->SetFullHealth();
|
||||
me->AttackStop();
|
||||
IntroPhaseTimer = 4000;
|
||||
++IntroPhase;
|
||||
break;
|
||||
case 8:
|
||||
Talk(YELL_INTRO_KILL_MADRIGOSA);
|
||||
me->SetOrientation(0.14f);
|
||||
me->StopMoving();
|
||||
Madrigosa->setDeathState(CORPSE);
|
||||
IntroPhaseTimer = 8000;
|
||||
++IntroPhase;
|
||||
break;
|
||||
case 9:
|
||||
Talk(YELL_INTRO_TAUNT);
|
||||
IntroPhaseTimer = 5000;
|
||||
++IntroPhase;
|
||||
break;
|
||||
case 10:
|
||||
EndIntro();
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
void EndIntro()
|
||||
void MoveInLineOfSight(Unit* who) override
|
||||
{
|
||||
if (!me->IsValidAttackTarget(who))
|
||||
return;
|
||||
|
||||
if (Intro)
|
||||
instance->SetBossState(DATA_BRUTALLUS, SPECIAL);
|
||||
|
||||
if (Intro && !IsIntro)
|
||||
StartIntro();
|
||||
|
||||
if (!Intro)
|
||||
BossAI::MoveInLineOfSight(who);
|
||||
}
|
||||
|
||||
void UpdateAI(uint32 diff) override
|
||||
{
|
||||
if (IsIntro)
|
||||
{
|
||||
me->RemoveUnitFlag(UNIT_FLAG_NON_ATTACKABLE);
|
||||
Intro = false;
|
||||
IsIntro = false;
|
||||
}
|
||||
if (IntroPhaseTimer <= diff)
|
||||
DoIntro();
|
||||
else IntroPhaseTimer -= diff;
|
||||
|
||||
void AttackStart(Unit* who) override
|
||||
{
|
||||
if (!who || Intro || IsIntro)
|
||||
return;
|
||||
ScriptedAI::AttackStart(who);
|
||||
}
|
||||
|
||||
void DoIntro()
|
||||
{
|
||||
Creature* Madrigosa = instance->GetCreature(DATA_MADRIGOSA);
|
||||
if (!Madrigosa)
|
||||
return;
|
||||
|
||||
switch (IntroPhase)
|
||||
if (IntroPhase == 3 + 1)
|
||||
{
|
||||
case 0:
|
||||
Madrigosa->AI()->Talk(YELL_MADR_ICE_BARRIER);
|
||||
IntroPhaseTimer = 7000;
|
||||
++IntroPhase;
|
||||
break;
|
||||
case 1:
|
||||
me->SetFacingToObject(Madrigosa);
|
||||
Madrigosa->SetFacingToObject(me);
|
||||
Madrigosa->AI()->Talk(YELL_MADR_INTRO, me);
|
||||
IntroPhaseTimer = 9000;
|
||||
++IntroPhase;
|
||||
break;
|
||||
case 2:
|
||||
Talk(YELL_INTRO, Madrigosa);
|
||||
IntroPhaseTimer = 13000;
|
||||
++IntroPhase;
|
||||
break;
|
||||
case 3:
|
||||
DoCast(me, SPELL_INTRO_FROST_BLAST);
|
||||
Madrigosa->SetDisableGravity(true);
|
||||
me->AttackStop();
|
||||
Madrigosa->AttackStop();
|
||||
IntroFrostBoltTimer = 3000;
|
||||
IntroPhaseTimer = 28000;
|
||||
++IntroPhase;
|
||||
break;
|
||||
case 4:
|
||||
Talk(YELL_INTRO_BREAK_ICE);
|
||||
IntroPhaseTimer = 6000;
|
||||
++IntroPhase;
|
||||
break;
|
||||
case 5:
|
||||
Madrigosa->CastSpell(me, SPELL_INTRO_ENCAPSULATE_CHANELLING, false);
|
||||
Madrigosa->AI()->Talk(YELL_MADR_TRAP);
|
||||
DoCast(me, SPELL_INTRO_ENCAPSULATE);
|
||||
IntroPhaseTimer = 11000;
|
||||
++IntroPhase;
|
||||
break;
|
||||
case 6:
|
||||
Talk(YELL_INTRO_CHARGE);
|
||||
IntroPhaseTimer = 5000;
|
||||
++IntroPhase;
|
||||
break;
|
||||
case 7:
|
||||
Unit::Kill(me, Madrigosa);
|
||||
Madrigosa->AI()->Talk(YELL_MADR_DEATH);
|
||||
me->SetFullHealth();
|
||||
me->AttackStop();
|
||||
IntroPhaseTimer = 4000;
|
||||
++IntroPhase;
|
||||
break;
|
||||
case 8:
|
||||
Talk(YELL_INTRO_KILL_MADRIGOSA);
|
||||
me->SetOrientation(0.14f);
|
||||
me->StopMoving();
|
||||
Madrigosa->setDeathState(CORPSE);
|
||||
IntroPhaseTimer = 8000;
|
||||
++IntroPhase;
|
||||
break;
|
||||
case 9:
|
||||
Talk(YELL_INTRO_TAUNT);
|
||||
IntroPhaseTimer = 5000;
|
||||
++IntroPhase;
|
||||
break;
|
||||
case 10:
|
||||
EndIntro();
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
void MoveInLineOfSight(Unit* who) override
|
||||
{
|
||||
if (!me->IsValidAttackTarget(who))
|
||||
return;
|
||||
|
||||
if (Intro)
|
||||
instance->SetBossState(DATA_BRUTALLUS, SPECIAL);
|
||||
|
||||
if (Intro && !IsIntro)
|
||||
StartIntro();
|
||||
|
||||
if (!Intro)
|
||||
ScriptedAI::MoveInLineOfSight(who);
|
||||
}
|
||||
|
||||
void UpdateAI(uint32 diff) override
|
||||
{
|
||||
if (IsIntro)
|
||||
{
|
||||
if (IntroPhaseTimer <= diff)
|
||||
DoIntro();
|
||||
else IntroPhaseTimer -= diff;
|
||||
|
||||
if (IntroPhase == 3 + 1)
|
||||
if (IntroFrostBoltTimer <= diff)
|
||||
{
|
||||
if (IntroFrostBoltTimer <= diff)
|
||||
if (Creature* Madrigosa = instance->GetCreature(DATA_MADRIGOSA))
|
||||
{
|
||||
if (Creature* Madrigosa = instance->GetCreature(DATA_MADRIGOSA))
|
||||
{
|
||||
Madrigosa->CastSpell(me, SPELL_INTRO_FROSTBOLT, true);
|
||||
IntroFrostBoltTimer = 2000;
|
||||
}
|
||||
Madrigosa->CastSpell(me, SPELL_INTRO_FROSTBOLT, true);
|
||||
IntroFrostBoltTimer = 2000;
|
||||
}
|
||||
else
|
||||
IntroFrostBoltTimer -= diff;
|
||||
}
|
||||
|
||||
if (!UpdateVictim())
|
||||
return;
|
||||
|
||||
DoMeleeAttackIfReady();
|
||||
else
|
||||
IntroFrostBoltTimer -= diff;
|
||||
}
|
||||
|
||||
if (!UpdateVictim() || IsIntro)
|
||||
if (!UpdateVictim())
|
||||
return;
|
||||
|
||||
if (SlashTimer <= diff)
|
||||
{
|
||||
DoCastVictim(SPELL_METEOR_SLASH);
|
||||
SlashTimer = 11000;
|
||||
} else SlashTimer -= diff;
|
||||
|
||||
if (StompTimer <= diff)
|
||||
{
|
||||
Talk(YELL_LOVE);
|
||||
DoCastVictim(SPELL_STOMP);
|
||||
StompTimer = 30000;
|
||||
} else StompTimer -= diff;
|
||||
|
||||
if (BurnTimer <= diff)
|
||||
{
|
||||
if (Unit* target = SelectTarget(SelectTargetMethod::Random, 0, 100.0f, true, true, -SPELL_BURN))
|
||||
target->CastSpell(target, SPELL_BURN, true);
|
||||
BurnTimer = urand(60000, 180000);
|
||||
} else BurnTimer -= diff;
|
||||
|
||||
if (BerserkTimer < diff && !Enraged)
|
||||
{
|
||||
Talk(YELL_BERSERK);
|
||||
DoCast(me, SPELL_BERSERK);
|
||||
Enraged = true;
|
||||
} else BerserkTimer -= diff;
|
||||
|
||||
DoMeleeAttackIfReady();
|
||||
}
|
||||
};
|
||||
|
||||
CreatureAI* GetAI(Creature* creature) const override
|
||||
{
|
||||
return GetSunwellPlateauAI<boss_brutallusAI>(creature);
|
||||
if (!UpdateVictim() || IsIntro)
|
||||
return;
|
||||
|
||||
if (SlashTimer <= diff)
|
||||
{
|
||||
DoCastVictim(SPELL_METEOR_SLASH);
|
||||
SlashTimer = 11000;
|
||||
} else SlashTimer -= diff;
|
||||
|
||||
if (StompTimer <= diff)
|
||||
{
|
||||
Talk(YELL_LOVE);
|
||||
DoCastVictim(SPELL_STOMP);
|
||||
StompTimer = 30000;
|
||||
} else StompTimer -= diff;
|
||||
|
||||
if (BurnTimer <= diff)
|
||||
{
|
||||
if (Unit* target = SelectTarget(SelectTargetMethod::Random, 0, 100.0f, true, true, -SPELL_BURN))
|
||||
target->CastSpell(target, SPELL_BURN, true);
|
||||
BurnTimer = urand(60000, 180000);
|
||||
} else BurnTimer -= diff;
|
||||
|
||||
if (BerserkTimer < diff && !Enraged)
|
||||
{
|
||||
Talk(YELL_BERSERK);
|
||||
DoCast(me, SPELL_BERSERK);
|
||||
Enraged = true;
|
||||
} else BerserkTimer -= diff;
|
||||
|
||||
DoMeleeAttackIfReady();
|
||||
}
|
||||
};
|
||||
|
||||
@@ -385,7 +369,7 @@ class spell_brutallus_stomp : public SpellScript
|
||||
|
||||
void AddSC_boss_brutallus()
|
||||
{
|
||||
new boss_brutallus();
|
||||
RegisterSunwellPlateauCreatureAI(boss_brutallus);
|
||||
RegisterSpellScript(spell_brutallus_burn);
|
||||
RegisterSpellScript(spell_brutallus_stomp);
|
||||
}
|
||||
|
||||
@@ -22,12 +22,11 @@ SDComment:
|
||||
EndScriptData */
|
||||
|
||||
#include "ScriptMgr.h"
|
||||
#include "CellImpl.h"
|
||||
#include "GridNotifiersImpl.h"
|
||||
#include "InstanceScript.h"
|
||||
#include "MotionMaster.h"
|
||||
#include "ObjectAccessor.h"
|
||||
#include "ScriptedCreature.h"
|
||||
#include "SpellInfo.h"
|
||||
#include "sunwell_plateau.h"
|
||||
#include "TemporarySummon.h"
|
||||
|
||||
@@ -109,472 +108,428 @@ enum EventFelmyst
|
||||
EVENT_SUMMON_FOG
|
||||
};
|
||||
|
||||
class boss_felmyst : public CreatureScript
|
||||
struct boss_felmyst : public BossAI
|
||||
{
|
||||
public:
|
||||
boss_felmyst() : CreatureScript("boss_felmyst") { }
|
||||
|
||||
struct boss_felmystAI : public ScriptedAI
|
||||
boss_felmyst(Creature* creature) : BossAI(creature, DATA_FELMYST)
|
||||
{
|
||||
boss_felmystAI(Creature* creature) : ScriptedAI(creature)
|
||||
Initialize();
|
||||
uiBreathCount = 0;
|
||||
breathX = 0.f;
|
||||
breathY = 0.f;
|
||||
}
|
||||
|
||||
void Initialize()
|
||||
{
|
||||
phase = PHASE_NONE;
|
||||
uiFlightCount = 0;
|
||||
}
|
||||
|
||||
PhaseFelmyst phase;
|
||||
|
||||
uint32 uiFlightCount;
|
||||
uint32 uiBreathCount;
|
||||
|
||||
float breathX, breathY;
|
||||
|
||||
void Reset() override
|
||||
{
|
||||
Initialize();
|
||||
|
||||
BossAI::Reset();
|
||||
|
||||
me->SetDisableGravity(true);
|
||||
me->SetBoundingRadius(10);
|
||||
me->SetCombatReach(10);
|
||||
}
|
||||
|
||||
void JustEngagedWith(Unit* who) override
|
||||
{
|
||||
BossAI::JustEngagedWith(who);
|
||||
|
||||
events.ScheduleEvent(EVENT_BERSERK, 10min);
|
||||
|
||||
DoCast(me, AURA_SUNWELL_RADIANCE, true);
|
||||
DoCast(me, AURA_NOXIOUS_FUMES, true);
|
||||
EnterPhase(PHASE_GROUND);
|
||||
}
|
||||
|
||||
void AttackStart(Unit* who) override
|
||||
{
|
||||
if (phase != PHASE_FLIGHT)
|
||||
BossAI::AttackStart(who);
|
||||
}
|
||||
|
||||
void MoveInLineOfSight(Unit* who) override
|
||||
{
|
||||
if (phase != PHASE_FLIGHT)
|
||||
BossAI::MoveInLineOfSight(who);
|
||||
}
|
||||
|
||||
void KilledUnit(Unit* /*victim*/) override
|
||||
{
|
||||
Talk(YELL_KILL);
|
||||
}
|
||||
|
||||
void JustAppeared() override
|
||||
{
|
||||
Talk(YELL_BIRTH);
|
||||
}
|
||||
|
||||
void JustDied(Unit* killer) override
|
||||
{
|
||||
Talk(YELL_DEATH);
|
||||
|
||||
BossAI::JustDied(killer);
|
||||
}
|
||||
|
||||
void SpellHit(WorldObject* caster, SpellInfo const* spellInfo) override
|
||||
{
|
||||
Unit* unitCaster = caster->ToUnit();
|
||||
if (!unitCaster)
|
||||
return;
|
||||
|
||||
// workaround for linked aura
|
||||
/*if (spell->Id == SPELL_VAPOR_FORCE)
|
||||
{
|
||||
Initialize();
|
||||
instance = creature->GetInstanceScript();
|
||||
uiBreathCount = 0;
|
||||
breathX = 0.f;
|
||||
breathY = 0.f;
|
||||
}
|
||||
|
||||
void Initialize()
|
||||
caster->CastSpell(caster, SPELL_VAPOR_TRIGGER, true);
|
||||
}*/
|
||||
// workaround for mind control
|
||||
if (spellInfo->Id == SPELL_FOG_INFORM)
|
||||
{
|
||||
phase = PHASE_NONE;
|
||||
uiFlightCount = 0;
|
||||
}
|
||||
|
||||
InstanceScript* instance;
|
||||
PhaseFelmyst phase;
|
||||
EventMap events;
|
||||
|
||||
uint32 uiFlightCount;
|
||||
uint32 uiBreathCount;
|
||||
|
||||
float breathX, breathY;
|
||||
|
||||
void Reset() override
|
||||
{
|
||||
Initialize();
|
||||
|
||||
events.Reset();
|
||||
|
||||
me->SetDisableGravity(true);
|
||||
me->SetBoundingRadius(10);
|
||||
me->SetCombatReach(10);
|
||||
|
||||
DespawnSummons(NPC_VAPOR_TRAIL);
|
||||
me->setActive(false);
|
||||
|
||||
instance->SetBossState(DATA_FELMYST, NOT_STARTED);
|
||||
}
|
||||
|
||||
void JustEngagedWith(Unit* /*who*/) override
|
||||
{
|
||||
events.ScheduleEvent(EVENT_BERSERK, 10min);
|
||||
|
||||
me->setActive(true);
|
||||
DoZoneInCombat();
|
||||
DoCast(me, AURA_SUNWELL_RADIANCE, true);
|
||||
DoCast(me, AURA_NOXIOUS_FUMES, true);
|
||||
EnterPhase(PHASE_GROUND);
|
||||
|
||||
instance->SetBossState(DATA_FELMYST, IN_PROGRESS);
|
||||
}
|
||||
|
||||
void AttackStart(Unit* who) override
|
||||
{
|
||||
if (phase != PHASE_FLIGHT)
|
||||
ScriptedAI::AttackStart(who);
|
||||
}
|
||||
|
||||
void MoveInLineOfSight(Unit* who) override
|
||||
{
|
||||
if (phase != PHASE_FLIGHT)
|
||||
ScriptedAI::MoveInLineOfSight(who);
|
||||
}
|
||||
|
||||
void KilledUnit(Unit* /*victim*/) override
|
||||
{
|
||||
Talk(YELL_KILL);
|
||||
}
|
||||
|
||||
void JustAppeared() override
|
||||
{
|
||||
Talk(YELL_BIRTH);
|
||||
}
|
||||
|
||||
void JustDied(Unit* /*killer*/) override
|
||||
{
|
||||
Talk(YELL_DEATH);
|
||||
|
||||
instance->SetBossState(DATA_FELMYST, DONE);
|
||||
}
|
||||
|
||||
void SpellHit(WorldObject* caster, SpellInfo const* spellInfo) override
|
||||
{
|
||||
Unit* unitCaster = caster->ToUnit();
|
||||
if (!unitCaster)
|
||||
return;
|
||||
|
||||
// workaround for linked aura
|
||||
/*if (spell->Id == SPELL_VAPOR_FORCE)
|
||||
float x, y, z;
|
||||
unitCaster->GetPosition(x, y, z);
|
||||
if (Unit* summon = me->SummonCreature(NPC_DEAD, x, y, z, 0, TEMPSUMMON_TIMED_DESPAWN_OUT_OF_COMBAT, 5s))
|
||||
{
|
||||
caster->CastSpell(caster, SPELL_VAPOR_TRIGGER, true);
|
||||
}*/
|
||||
// workaround for mind control
|
||||
if (spellInfo->Id == SPELL_FOG_INFORM)
|
||||
summon->SetMaxHealth(unitCaster->GetMaxHealth());
|
||||
summon->SetHealth(unitCaster->GetMaxHealth());
|
||||
summon->CastSpell(summon, SPELL_FOG_CHARM, true);
|
||||
summon->CastSpell(summon, SPELL_FOG_CHARM2, true);
|
||||
}
|
||||
Unit::DealDamage(me, unitCaster, unitCaster->GetHealth(), nullptr, DIRECT_DAMAGE, SPELL_SCHOOL_MASK_NORMAL, nullptr, false);
|
||||
}
|
||||
}
|
||||
|
||||
void JustSummoned(Creature* summon) override
|
||||
{
|
||||
if (summon->GetEntry() == NPC_DEAD)
|
||||
{
|
||||
summon->AI()->AttackStart(SelectTarget(SelectTargetMethod::Random));
|
||||
DoZoneInCombat(summon);
|
||||
summon->CastSpell(summon, SPELL_DEAD_PASSIVE, true);
|
||||
}
|
||||
|
||||
BossAI::JustSummoned(summon);
|
||||
}
|
||||
|
||||
void MovementInform(uint32, uint32) override
|
||||
{
|
||||
if (phase == PHASE_FLIGHT)
|
||||
events.ScheduleEvent(EVENT_FLIGHT_SEQUENCE, 1ms);
|
||||
}
|
||||
|
||||
void DamageTaken(Unit*, uint32& damage, DamageEffectType /*damageType*/, SpellInfo const* /*spellInfo = nullptr*/) override
|
||||
{
|
||||
if (phase != PHASE_GROUND && damage >= me->GetHealth())
|
||||
damage = 0;
|
||||
}
|
||||
|
||||
void EnterPhase(PhaseFelmyst NextPhase)
|
||||
{
|
||||
switch (NextPhase)
|
||||
{
|
||||
case PHASE_GROUND:
|
||||
me->CastStop(SPELL_FOG_BREATH);
|
||||
me->RemoveAurasDueToSpell(SPELL_FOG_BREATH);
|
||||
me->StopMoving();
|
||||
me->SetSpeedRate(MOVE_RUN, 2.0f);
|
||||
|
||||
events.ScheduleEvent(EVENT_CLEAVE, 5s, 10s);
|
||||
events.ScheduleEvent(EVENT_CORROSION, 10s, 20s);
|
||||
events.ScheduleEvent(EVENT_GAS_NOVA, 15s, 20s);
|
||||
events.ScheduleEvent(EVENT_ENCAPSULATE, 20s, 25s);
|
||||
events.ScheduleEvent(EVENT_FLIGHT, 1min);
|
||||
break;
|
||||
case PHASE_FLIGHT:
|
||||
me->SetDisableGravity(true);
|
||||
events.ScheduleEvent(EVENT_FLIGHT_SEQUENCE, 1s);
|
||||
uiFlightCount = 0;
|
||||
uiBreathCount = 0;
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
phase = NextPhase;
|
||||
}
|
||||
|
||||
void HandleFlightSequence()
|
||||
{
|
||||
switch (uiFlightCount)
|
||||
{
|
||||
case 0:
|
||||
//me->AttackStop();
|
||||
me->GetMotionMaster()->Clear();
|
||||
me->HandleEmoteCommand(EMOTE_ONESHOT_LIFTOFF);
|
||||
me->StopMoving();
|
||||
Talk(YELL_TAKEOFF);
|
||||
events.ScheduleEvent(EVENT_FLIGHT_SEQUENCE, 2s);
|
||||
break;
|
||||
case 1:
|
||||
me->GetMotionMaster()->MovePoint(0, me->GetPositionX()+1, me->GetPositionY(), me->GetPositionZ()+10);
|
||||
break;
|
||||
case 2:
|
||||
{
|
||||
float x, y, z;
|
||||
unitCaster->GetPosition(x, y, z);
|
||||
if (Unit* summon = me->SummonCreature(NPC_DEAD, x, y, z, 0, TEMPSUMMON_TIMED_DESPAWN_OUT_OF_COMBAT, 5s))
|
||||
Unit* target = SelectTarget(SelectTargetMethod::Random, 0, 150, true);
|
||||
if (!target)
|
||||
target = ObjectAccessor::GetUnit(*me, instance->GetGuidData(DATA_PLAYER_GUID));
|
||||
|
||||
if (!target)
|
||||
{
|
||||
summon->SetMaxHealth(unitCaster->GetMaxHealth());
|
||||
summon->SetHealth(unitCaster->GetMaxHealth());
|
||||
summon->CastSpell(summon, SPELL_FOG_CHARM, true);
|
||||
summon->CastSpell(summon, SPELL_FOG_CHARM2, true);
|
||||
EnterEvadeMode();
|
||||
return;
|
||||
}
|
||||
Unit::DealDamage(me, unitCaster, unitCaster->GetHealth(), nullptr, DIRECT_DAMAGE, SPELL_SCHOOL_MASK_NORMAL, nullptr, false);
|
||||
}
|
||||
}
|
||||
|
||||
void JustSummoned(Creature* summon) override
|
||||
{
|
||||
if (summon->GetEntry() == NPC_DEAD)
|
||||
if (Creature* Vapor = me->SummonCreature(NPC_VAPOR, target->GetPositionX() - 5 + rand32() % 10, target->GetPositionY() - 5 + rand32() % 10, target->GetPositionZ(), 0, TEMPSUMMON_TIMED_DESPAWN, 9s))
|
||||
{
|
||||
Vapor->AI()->AttackStart(target);
|
||||
me->InterruptNonMeleeSpells(false);
|
||||
DoCast(Vapor, SPELL_VAPOR_CHANNEL, false); // core bug
|
||||
Vapor->CastSpell(Vapor, SPELL_VAPOR_TRIGGER, true);
|
||||
}
|
||||
|
||||
events.ScheduleEvent(EVENT_FLIGHT_SEQUENCE, 10s);
|
||||
break;
|
||||
}
|
||||
case 3:
|
||||
{
|
||||
summon->AI()->AttackStart(SelectTarget(SelectTargetMethod::Random));
|
||||
DoZoneInCombat(summon);
|
||||
summon->CastSpell(summon, SPELL_DEAD_PASSIVE, true);
|
||||
}
|
||||
}
|
||||
DespawnSummons(NPC_VAPOR_TRAIL);
|
||||
//DoCast(me, SPELL_VAPOR_SELECT); need core support
|
||||
|
||||
void MovementInform(uint32, uint32) override
|
||||
{
|
||||
if (phase == PHASE_FLIGHT)
|
||||
Unit* target = SelectTarget(SelectTargetMethod::Random, 0, 150, true);
|
||||
if (!target)
|
||||
target = ObjectAccessor::GetUnit(*me, instance->GetGuidData(DATA_PLAYER_GUID));
|
||||
|
||||
if (!target)
|
||||
{
|
||||
EnterEvadeMode();
|
||||
return;
|
||||
}
|
||||
|
||||
//target->CastSpell(target, SPELL_VAPOR_SUMMON, true); need core support
|
||||
if (Creature* pVapor = me->SummonCreature(NPC_VAPOR, target->GetPositionX() - 5 + rand32() % 10, target->GetPositionY() - 5 + rand32() % 10, target->GetPositionZ(), 0, TEMPSUMMON_TIMED_DESPAWN, 9s))
|
||||
{
|
||||
if (pVapor->AI())
|
||||
pVapor->AI()->AttackStart(target);
|
||||
me->InterruptNonMeleeSpells(false);
|
||||
DoCast(pVapor, SPELL_VAPOR_CHANNEL, false); // core bug
|
||||
pVapor->CastSpell(pVapor, SPELL_VAPOR_TRIGGER, true);
|
||||
}
|
||||
|
||||
events.ScheduleEvent(EVENT_FLIGHT_SEQUENCE, 10s);
|
||||
break;
|
||||
}
|
||||
case 4:
|
||||
DespawnSummons(NPC_VAPOR_TRAIL);
|
||||
events.ScheduleEvent(EVENT_FLIGHT_SEQUENCE, 1ms);
|
||||
}
|
||||
|
||||
void DamageTaken(Unit*, uint32& damage, DamageEffectType /*damageType*/, SpellInfo const* /*spellInfo = nullptr*/) override
|
||||
{
|
||||
if (phase != PHASE_GROUND && damage >= me->GetHealth())
|
||||
damage = 0;
|
||||
}
|
||||
|
||||
void EnterPhase(PhaseFelmyst NextPhase)
|
||||
{
|
||||
switch (NextPhase)
|
||||
break;
|
||||
case 5:
|
||||
{
|
||||
case PHASE_GROUND:
|
||||
me->CastStop(SPELL_FOG_BREATH);
|
||||
me->RemoveAurasDueToSpell(SPELL_FOG_BREATH);
|
||||
me->StopMoving();
|
||||
me->SetSpeedRate(MOVE_RUN, 2.0f);
|
||||
Unit* target = SelectTarget(SelectTargetMethod::Random, 0, 150, true);
|
||||
if (!target)
|
||||
target = ObjectAccessor::GetUnit(*me, instance->GetGuidData(DATA_PLAYER_GUID));
|
||||
|
||||
events.ScheduleEvent(EVENT_CLEAVE, 5s, 10s);
|
||||
events.ScheduleEvent(EVENT_CORROSION, 10s, 20s);
|
||||
events.ScheduleEvent(EVENT_GAS_NOVA, 15s, 20s);
|
||||
events.ScheduleEvent(EVENT_ENCAPSULATE, 20s, 25s);
|
||||
events.ScheduleEvent(EVENT_FLIGHT, 1min);
|
||||
if (!target)
|
||||
{
|
||||
EnterEvadeMode();
|
||||
return;
|
||||
}
|
||||
|
||||
breathX = target->GetPositionX();
|
||||
breathY = target->GetPositionY();
|
||||
float x, y, z;
|
||||
target->GetContactPoint(me, x, y, z, 70);
|
||||
me->GetMotionMaster()->MovePoint(0, x, y, z+10);
|
||||
break;
|
||||
}
|
||||
case 6:
|
||||
me->SetFacingTo(me->GetAbsoluteAngle(breathX, breathY));
|
||||
//DoTextEmote("takes a deep breath.", nullptr);
|
||||
events.ScheduleEvent(EVENT_FLIGHT_SEQUENCE, 10s);
|
||||
break;
|
||||
case 7:
|
||||
{
|
||||
DoCast(me, SPELL_FOG_BREATH, true);
|
||||
float x, y, z;
|
||||
me->GetPosition(x, y, z);
|
||||
x = 2 * breathX - x;
|
||||
y = 2 * breathY - y;
|
||||
me->GetMotionMaster()->MovePoint(0, x, y, z);
|
||||
events.ScheduleEvent(EVENT_SUMMON_FOG, 1ms);
|
||||
break;
|
||||
}
|
||||
case 8:
|
||||
me->CastStop(SPELL_FOG_BREATH);
|
||||
me->RemoveAurasDueToSpell(SPELL_FOG_BREATH);
|
||||
++uiBreathCount;
|
||||
events.ScheduleEvent(EVENT_FLIGHT_SEQUENCE, 1ms);
|
||||
if (uiBreathCount < 3)
|
||||
uiFlightCount = 4;
|
||||
break;
|
||||
case 9:
|
||||
if (Unit* target = SelectTarget(SelectTargetMethod::MaxThreat))
|
||||
DoStartMovement(target);
|
||||
else
|
||||
{
|
||||
EnterEvadeMode();
|
||||
return;
|
||||
}
|
||||
break;
|
||||
case 10:
|
||||
me->SetDisableGravity(false);
|
||||
me->HandleEmoteCommand(EMOTE_ONESHOT_LAND);
|
||||
EnterPhase(PHASE_GROUND);
|
||||
AttackStart(SelectTarget(SelectTargetMethod::MaxThreat));
|
||||
break;
|
||||
}
|
||||
++uiFlightCount;
|
||||
}
|
||||
|
||||
void UpdateAI(uint32 diff) override
|
||||
{
|
||||
if (!UpdateVictim())
|
||||
{
|
||||
if (phase == PHASE_FLIGHT && !me->IsInEvadeMode())
|
||||
EnterEvadeMode();
|
||||
return;
|
||||
}
|
||||
|
||||
events.Update(diff);
|
||||
|
||||
if (me->IsNonMeleeSpellCast(false))
|
||||
return;
|
||||
|
||||
if (phase == PHASE_GROUND)
|
||||
{
|
||||
switch (events.ExecuteEvent())
|
||||
{
|
||||
case EVENT_BERSERK:
|
||||
Talk(YELL_BERSERK);
|
||||
DoCast(me, SPELL_BERSERK, true);
|
||||
events.ScheduleEvent(EVENT_BERSERK, 10s);
|
||||
break;
|
||||
case PHASE_FLIGHT:
|
||||
me->SetDisableGravity(true);
|
||||
events.ScheduleEvent(EVENT_FLIGHT_SEQUENCE, 1s);
|
||||
uiFlightCount = 0;
|
||||
uiBreathCount = 0;
|
||||
case EVENT_CLEAVE:
|
||||
DoCastVictim(SPELL_CLEAVE, false);
|
||||
events.ScheduleEvent(EVENT_CLEAVE, 5s, 10s);
|
||||
break;
|
||||
case EVENT_CORROSION:
|
||||
DoCastVictim(SPELL_CORROSION, false);
|
||||
events.ScheduleEvent(EVENT_CORROSION, 20s, 30s);
|
||||
break;
|
||||
case EVENT_GAS_NOVA:
|
||||
DoCast(me, SPELL_GAS_NOVA, false);
|
||||
events.ScheduleEvent(EVENT_GAS_NOVA, 20s, 25s);
|
||||
break;
|
||||
case EVENT_ENCAPSULATE:
|
||||
if (Unit* target = SelectTarget(SelectTargetMethod::Random, 0, 150, true))
|
||||
DoCast(target, SPELL_ENCAPSULATE_CHANNEL, false);
|
||||
events.ScheduleEvent(EVENT_ENCAPSULATE, 25s, 30s);
|
||||
break;
|
||||
case EVENT_FLIGHT:
|
||||
EnterPhase(PHASE_FLIGHT);
|
||||
break;
|
||||
default:
|
||||
DoMeleeAttackIfReady();
|
||||
break;
|
||||
}
|
||||
phase = NextPhase;
|
||||
}
|
||||
|
||||
void HandleFlightSequence()
|
||||
if (phase == PHASE_FLIGHT)
|
||||
{
|
||||
switch (uiFlightCount)
|
||||
switch (events.ExecuteEvent())
|
||||
{
|
||||
case 0:
|
||||
//me->AttackStop();
|
||||
me->GetMotionMaster()->Clear();
|
||||
me->HandleEmoteCommand(EMOTE_ONESHOT_LIFTOFF);
|
||||
me->StopMoving();
|
||||
Talk(YELL_TAKEOFF);
|
||||
events.ScheduleEvent(EVENT_FLIGHT_SEQUENCE, 2s);
|
||||
case EVENT_BERSERK:
|
||||
Talk(YELL_BERSERK);
|
||||
DoCast(me, SPELL_BERSERK, true);
|
||||
break;
|
||||
case 1:
|
||||
me->GetMotionMaster()->MovePoint(0, me->GetPositionX()+1, me->GetPositionY(), me->GetPositionZ()+10);
|
||||
case EVENT_FLIGHT_SEQUENCE:
|
||||
HandleFlightSequence();
|
||||
break;
|
||||
case 2:
|
||||
{
|
||||
Unit* target = SelectTarget(SelectTargetMethod::Random, 0, 150, true);
|
||||
if (!target)
|
||||
target = ObjectAccessor::GetUnit(*me, instance->GetGuidData(DATA_PLAYER_GUID));
|
||||
|
||||
if (!target)
|
||||
case EVENT_SUMMON_FOG:
|
||||
{
|
||||
EnterEvadeMode();
|
||||
return;
|
||||
}
|
||||
|
||||
if (Creature* Vapor = me->SummonCreature(NPC_VAPOR, target->GetPositionX() - 5 + rand32() % 10, target->GetPositionY() - 5 + rand32() % 10, target->GetPositionZ(), 0, TEMPSUMMON_TIMED_DESPAWN, 9s))
|
||||
{
|
||||
Vapor->AI()->AttackStart(target);
|
||||
me->InterruptNonMeleeSpells(false);
|
||||
DoCast(Vapor, SPELL_VAPOR_CHANNEL, false); // core bug
|
||||
Vapor->CastSpell(Vapor, SPELL_VAPOR_TRIGGER, true);
|
||||
}
|
||||
|
||||
events.ScheduleEvent(EVENT_FLIGHT_SEQUENCE, 10s);
|
||||
break;
|
||||
}
|
||||
case 3:
|
||||
{
|
||||
DespawnSummons(NPC_VAPOR_TRAIL);
|
||||
//DoCast(me, SPELL_VAPOR_SELECT); need core support
|
||||
|
||||
Unit* target = SelectTarget(SelectTargetMethod::Random, 0, 150, true);
|
||||
if (!target)
|
||||
target = ObjectAccessor::GetUnit(*me, instance->GetGuidData(DATA_PLAYER_GUID));
|
||||
|
||||
if (!target)
|
||||
{
|
||||
EnterEvadeMode();
|
||||
return;
|
||||
}
|
||||
|
||||
//target->CastSpell(target, SPELL_VAPOR_SUMMON, true); need core support
|
||||
if (Creature* pVapor = me->SummonCreature(NPC_VAPOR, target->GetPositionX() - 5 + rand32() % 10, target->GetPositionY() - 5 + rand32() % 10, target->GetPositionZ(), 0, TEMPSUMMON_TIMED_DESPAWN, 9s))
|
||||
{
|
||||
if (pVapor->AI())
|
||||
pVapor->AI()->AttackStart(target);
|
||||
me->InterruptNonMeleeSpells(false);
|
||||
DoCast(pVapor, SPELL_VAPOR_CHANNEL, false); // core bug
|
||||
pVapor->CastSpell(pVapor, SPELL_VAPOR_TRIGGER, true);
|
||||
}
|
||||
|
||||
events.ScheduleEvent(EVENT_FLIGHT_SEQUENCE, 10s);
|
||||
break;
|
||||
}
|
||||
case 4:
|
||||
DespawnSummons(NPC_VAPOR_TRAIL);
|
||||
events.ScheduleEvent(EVENT_FLIGHT_SEQUENCE, 1ms);
|
||||
break;
|
||||
case 5:
|
||||
{
|
||||
Unit* target = SelectTarget(SelectTargetMethod::Random, 0, 150, true);
|
||||
if (!target)
|
||||
target = ObjectAccessor::GetUnit(*me, instance->GetGuidData(DATA_PLAYER_GUID));
|
||||
|
||||
if (!target)
|
||||
{
|
||||
EnterEvadeMode();
|
||||
return;
|
||||
}
|
||||
|
||||
breathX = target->GetPositionX();
|
||||
breathY = target->GetPositionY();
|
||||
float x, y, z;
|
||||
target->GetContactPoint(me, x, y, z, 70);
|
||||
me->GetMotionMaster()->MovePoint(0, x, y, z+10);
|
||||
break;
|
||||
}
|
||||
case 6:
|
||||
me->SetFacingTo(me->GetAbsoluteAngle(breathX, breathY));
|
||||
//DoTextEmote("takes a deep breath.", nullptr);
|
||||
events.ScheduleEvent(EVENT_FLIGHT_SEQUENCE, 10s);
|
||||
break;
|
||||
case 7:
|
||||
{
|
||||
DoCast(me, SPELL_FOG_BREATH, true);
|
||||
float x, y, z;
|
||||
me->GetPosition(x, y, z);
|
||||
x = 2 * breathX - x;
|
||||
y = 2 * breathY - y;
|
||||
me->GetMotionMaster()->MovePoint(0, x, y, z);
|
||||
events.ScheduleEvent(EVENT_SUMMON_FOG, 1ms);
|
||||
break;
|
||||
}
|
||||
case 8:
|
||||
me->CastStop(SPELL_FOG_BREATH);
|
||||
me->RemoveAurasDueToSpell(SPELL_FOG_BREATH);
|
||||
++uiBreathCount;
|
||||
events.ScheduleEvent(EVENT_FLIGHT_SEQUENCE, 1ms);
|
||||
if (uiBreathCount < 3)
|
||||
uiFlightCount = 4;
|
||||
break;
|
||||
case 9:
|
||||
if (Unit* target = SelectTarget(SelectTargetMethod::MaxThreat))
|
||||
DoStartMovement(target);
|
||||
else
|
||||
{
|
||||
EnterEvadeMode();
|
||||
return;
|
||||
}
|
||||
break;
|
||||
case 10:
|
||||
me->SetDisableGravity(false);
|
||||
me->HandleEmoteCommand(EMOTE_ONESHOT_LAND);
|
||||
EnterPhase(PHASE_GROUND);
|
||||
AttackStart(SelectTarget(SelectTargetMethod::MaxThreat));
|
||||
break;
|
||||
}
|
||||
++uiFlightCount;
|
||||
}
|
||||
|
||||
void UpdateAI(uint32 diff) override
|
||||
{
|
||||
if (!UpdateVictim())
|
||||
{
|
||||
if (phase == PHASE_FLIGHT && !me->IsInEvadeMode())
|
||||
EnterEvadeMode();
|
||||
return;
|
||||
}
|
||||
|
||||
events.Update(diff);
|
||||
|
||||
if (me->IsNonMeleeSpellCast(false))
|
||||
return;
|
||||
|
||||
if (phase == PHASE_GROUND)
|
||||
{
|
||||
switch (events.ExecuteEvent())
|
||||
{
|
||||
case EVENT_BERSERK:
|
||||
Talk(YELL_BERSERK);
|
||||
DoCast(me, SPELL_BERSERK, true);
|
||||
events.ScheduleEvent(EVENT_BERSERK, 10s);
|
||||
break;
|
||||
case EVENT_CLEAVE:
|
||||
DoCastVictim(SPELL_CLEAVE, false);
|
||||
events.ScheduleEvent(EVENT_CLEAVE, 5s, 10s);
|
||||
break;
|
||||
case EVENT_CORROSION:
|
||||
DoCastVictim(SPELL_CORROSION, false);
|
||||
events.ScheduleEvent(EVENT_CORROSION, 20s, 30s);
|
||||
break;
|
||||
case EVENT_GAS_NOVA:
|
||||
DoCast(me, SPELL_GAS_NOVA, false);
|
||||
events.ScheduleEvent(EVENT_GAS_NOVA, 20s, 25s);
|
||||
break;
|
||||
case EVENT_ENCAPSULATE:
|
||||
if (Unit* target = SelectTarget(SelectTargetMethod::Random, 0, 150, true))
|
||||
DoCast(target, SPELL_ENCAPSULATE_CHANNEL, false);
|
||||
events.ScheduleEvent(EVENT_ENCAPSULATE, 25s, 30s);
|
||||
break;
|
||||
case EVENT_FLIGHT:
|
||||
EnterPhase(PHASE_FLIGHT);
|
||||
break;
|
||||
default:
|
||||
DoMeleeAttackIfReady();
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (phase == PHASE_FLIGHT)
|
||||
{
|
||||
switch (events.ExecuteEvent())
|
||||
{
|
||||
case EVENT_BERSERK:
|
||||
Talk(YELL_BERSERK);
|
||||
DoCast(me, SPELL_BERSERK, true);
|
||||
break;
|
||||
case EVENT_FLIGHT_SEQUENCE:
|
||||
HandleFlightSequence();
|
||||
break;
|
||||
case EVENT_SUMMON_FOG:
|
||||
float x, y, z;
|
||||
me->GetPosition(x, y, z);
|
||||
me->UpdateGroundPositionZ(x, y, z);
|
||||
if (Creature* Fog = me->SummonCreature(NPC_VAPOR_TRAIL, x, y, z, 0, TEMPSUMMON_TIMED_DESPAWN, 10s))
|
||||
{
|
||||
float x, y, z;
|
||||
me->GetPosition(x, y, z);
|
||||
me->UpdateGroundPositionZ(x, y, z);
|
||||
if (Creature* Fog = me->SummonCreature(NPC_VAPOR_TRAIL, x, y, z, 0, TEMPSUMMON_TIMED_DESPAWN, 10s))
|
||||
{
|
||||
Fog->RemoveAurasDueToSpell(SPELL_TRAIL_TRIGGER);
|
||||
Fog->CastSpell(Fog, SPELL_FOG_TRIGGER, true);
|
||||
me->CastSpell(Fog, SPELL_FOG_FORCE, true);
|
||||
}
|
||||
Fog->RemoveAurasDueToSpell(SPELL_TRAIL_TRIGGER);
|
||||
Fog->CastSpell(Fog, SPELL_FOG_TRIGGER, true);
|
||||
me->CastSpell(Fog, SPELL_FOG_FORCE, true);
|
||||
}
|
||||
events.ScheduleEvent(EVENT_SUMMON_FOG, 1s);
|
||||
break;
|
||||
}
|
||||
}
|
||||
events.ScheduleEvent(EVENT_SUMMON_FOG, 1s);
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void DespawnSummons(uint32 entry)
|
||||
void DespawnSummons(uint32 entry)
|
||||
{
|
||||
summons.DespawnIf([&](ObjectGuid guid)
|
||||
{
|
||||
std::list<Creature*> templist;
|
||||
float x, y, z;
|
||||
me->GetPosition(x, y, z);
|
||||
if (guid.GetEntry() != entry)
|
||||
return false;
|
||||
|
||||
Trinity::AllCreaturesOfEntryInRange check(me, entry, 100);
|
||||
Trinity::CreatureListSearcher<Trinity::AllCreaturesOfEntryInRange> searcher(me, templist, check);
|
||||
Cell::VisitGridObjects(me, searcher, me->GetGridActivationRange());
|
||||
|
||||
for (std::list<Creature*>::const_iterator i = templist.begin(); i != templist.end(); ++i)
|
||||
if (guid.GetEntry() == NPC_VAPOR_TRAIL && phase == PHASE_FLIGHT)
|
||||
{
|
||||
if (entry == NPC_VAPOR_TRAIL && phase == PHASE_FLIGHT)
|
||||
{
|
||||
(*i)->GetPosition(x, y, z);
|
||||
me->SummonCreature(NPC_DEAD, x, y, z, 0, TEMPSUMMON_TIMED_DESPAWN_OUT_OF_COMBAT, 5s);
|
||||
}
|
||||
(*i)->SetVisible(false);
|
||||
(*i)->DespawnOrUnsummon();
|
||||
Position const* pos = ObjectAccessor::GetCreature(*me, guid);
|
||||
if (!pos)
|
||||
pos = me;
|
||||
|
||||
me->SummonCreature(NPC_DEAD, *pos, TEMPSUMMON_TIMED_DESPAWN_OUT_OF_COMBAT, 5s);
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
CreatureAI* GetAI(Creature* creature) const override
|
||||
{
|
||||
return GetSunwellPlateauAI<boss_felmystAI>(creature);
|
||||
return true;
|
||||
});
|
||||
}
|
||||
};
|
||||
|
||||
class npc_felmyst_vapor : public CreatureScript
|
||||
struct npc_felmyst_vapor : public ScriptedAI
|
||||
{
|
||||
public:
|
||||
npc_felmyst_vapor() : CreatureScript("npc_felmyst_vapor") { }
|
||||
npc_felmyst_vapor(Creature* creature) : ScriptedAI(creature) { }
|
||||
|
||||
CreatureAI* GetAI(Creature* creature) const override
|
||||
void Reset() override { }
|
||||
void JustEngagedWith(Unit* /*who*/) override
|
||||
{
|
||||
return GetSunwellPlateauAI<npc_felmyst_vaporAI>(creature);
|
||||
DoZoneInCombat();
|
||||
//DoCast(me, SPELL_VAPOR_FORCE, true); core bug
|
||||
}
|
||||
|
||||
struct npc_felmyst_vaporAI : public ScriptedAI
|
||||
void UpdateAI(uint32 /*diff*/) override
|
||||
{
|
||||
npc_felmyst_vaporAI(Creature* creature) : ScriptedAI(creature) { }
|
||||
|
||||
void Reset() override { }
|
||||
void JustEngagedWith(Unit* /*who*/) override
|
||||
{
|
||||
DoZoneInCombat();
|
||||
//DoCast(me, SPELL_VAPOR_FORCE, true); core bug
|
||||
}
|
||||
|
||||
void UpdateAI(uint32 /*diff*/) override
|
||||
{
|
||||
if (!me->GetVictim())
|
||||
if (Unit* target = SelectTarget(SelectTargetMethod::Random, 0, 100, true))
|
||||
AttackStart(target);
|
||||
}
|
||||
};
|
||||
if (!me->GetVictim())
|
||||
if (Unit* target = SelectTarget(SelectTargetMethod::Random, 0, 100, true))
|
||||
AttackStart(target);
|
||||
}
|
||||
};
|
||||
|
||||
class npc_felmyst_trail : public CreatureScript
|
||||
struct npc_felmyst_trail : public ScriptedAI
|
||||
{
|
||||
public:
|
||||
npc_felmyst_trail() : CreatureScript("npc_felmyst_trail") { }
|
||||
|
||||
CreatureAI* GetAI(Creature* creature) const override
|
||||
npc_felmyst_trail(Creature* creature) : ScriptedAI(creature)
|
||||
{
|
||||
return GetSunwellPlateauAI<npc_felmyst_trailAI>(creature);
|
||||
DoCast(me, SPELL_TRAIL_TRIGGER, true);
|
||||
me->SetTarget(me->GetGUID());
|
||||
me->SetBoundingRadius(0.01f); // core bug
|
||||
}
|
||||
|
||||
struct npc_felmyst_trailAI : public ScriptedAI
|
||||
{
|
||||
npc_felmyst_trailAI(Creature* creature) : ScriptedAI(creature)
|
||||
{
|
||||
DoCast(me, SPELL_TRAIL_TRIGGER, true);
|
||||
me->SetTarget(me->GetGUID());
|
||||
me->SetBoundingRadius(0.01f); // core bug
|
||||
}
|
||||
void Reset() override { }
|
||||
void JustEngagedWith(Unit* /*who*/) override { }
|
||||
void AttackStart(Unit* /*who*/) override { }
|
||||
void MoveInLineOfSight(Unit* /*who*/) override { }
|
||||
|
||||
void Reset() override { }
|
||||
void JustEngagedWith(Unit* /*who*/) override { }
|
||||
void AttackStart(Unit* /*who*/) override { }
|
||||
void MoveInLineOfSight(Unit* /*who*/) override { }
|
||||
|
||||
void UpdateAI(uint32 /*diff*/) override { }
|
||||
};
|
||||
void UpdateAI(uint32 /*diff*/) override { }
|
||||
};
|
||||
|
||||
void AddSC_boss_felmyst()
|
||||
{
|
||||
new boss_felmyst();
|
||||
new npc_felmyst_vapor();
|
||||
new npc_felmyst_trail();
|
||||
RegisterSunwellPlateauCreatureAI(boss_felmyst);
|
||||
RegisterSunwellPlateauCreatureAI(npc_felmyst_vapor);
|
||||
RegisterSunwellPlateauCreatureAI(npc_felmyst_trail);
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user