Skip to content

Commit 8c3c751

Browse files
authored
refactor(Scripts/MagistersTerrace): Felblood Kael'thas (azerothcore#20642)
* Felblood kael (azerothcore#14) * init * initial ready version * make scheduler repeatable and correct intro sequence * some debug and OOC scheduler * Update boss_felblood_kaelthas.cpp * finale * Update boss_felblood_kaelthas.cpp * Update boss_felblood_kaelthas.cpp * Update boss_felblood_kaelthas.cpp * Update boss_felblood_kaelthas.cpp * simplify target selection
1 parent bda74c1 commit 8c3c751

File tree

1 file changed

+107
-161
lines changed

1 file changed

+107
-161
lines changed

src/server/scripts/EasternKingdoms/MagistersTerrace/boss_felblood_kaelthas.cpp

Lines changed: 107 additions & 161 deletions
Original file line numberDiff line numberDiff line change
@@ -56,20 +56,6 @@ enum Spells
5656

5757
enum Misc
5858
{
59-
EVENT_INIT_COMBAT = 1,
60-
EVENT_SPELL_FIREBALL = 2,
61-
EVENT_SPELL_PHOENIX = 3,
62-
EVENT_SPELL_FLAMESTRIKE = 4,
63-
EVENT_SPELL_SHOCK_BARRIER = 5,
64-
EVENT_CHECK_HEALTH = 6,
65-
EVENT_GRAVITY_LAPSE_1_1 = 7,
66-
EVENT_GRAVITY_LAPSE_1_2 = 8,
67-
EVENT_GRAVITY_LAPSE_2 = 9,
68-
EVENT_GRAVITY_LAPSE_3 = 10,
69-
EVENT_GRAVITY_LAPSE_4 = 11,
70-
EVENT_GRAVITY_LAPSE_5 = 12,
71-
EVENT_FINISH_TALK = 13,
72-
7359
ACTION_TELEPORT_PLAYERS = 1,
7460
ACTION_KNOCKUP = 2,
7561
ACTION_ALLOW_FLY = 3,
@@ -78,216 +64,176 @@ enum Misc
7864
CREATURE_ARCANE_SPHERE = 24708
7965
};
8066

81-
struct boss_felblood_kaelthas : public ScriptedAI
67+
struct boss_felblood_kaelthas : public BossAI
8268
{
83-
boss_felblood_kaelthas(Creature* creature) : ScriptedAI(creature), summons(me)
69+
boss_felblood_kaelthas(Creature* creature) : BossAI(creature, DATA_KAELTHAS)
8470
{
85-
instance = creature->GetInstanceScript();
86-
introSpeak = false;
71+
_hasDoneIntro = false;
8772
}
8873

89-
InstanceScript* instance;
90-
EventMap events;
91-
EventMap events2;
92-
SummonList summons;
93-
bool introSpeak;
94-
9574
void Reset() override
9675
{
97-
events.Reset();
98-
summons.DespawnAll();
76+
BossAI::Reset();
77+
_OOCScheduler.CancelAll();
78+
_gravityLapseCounter = 0;
9979
me->ApplySpellImmune(0, IMMUNITY_EFFECT, SPELL_EFFECT_INTERRUPT_CAST, false);
100-
instance->SetBossState(DATA_KAELTHAS, NOT_STARTED);
10180
me->SetImmuneToAll(false);
81+
ScheduleHealthCheckEvent(50, [&]{
82+
me->CastStop();
83+
me->ApplySpellImmune(0, IMMUNITY_EFFECT, SPELL_EFFECT_INTERRUPT_CAST, true);
84+
DoCastSelf(SPELL_TELEPORT_CENTER, true);
85+
scheduler.CancelAll();
86+
87+
me->StopMoving();
88+
me->GetMotionMaster()->Clear();
89+
me->GetMotionMaster()->MoveIdle();
90+
ScheduleTimedEvent(5s, [&]{
91+
summons.DoForAllSummons([&](WorldObject* summon){
92+
if (Unit* player = SelectTarget(SelectTargetMethod::Random, 0, 0.0f, true))
93+
if (Creature* summonedCreature = summon->ToCreature())
94+
summonedCreature->GetMotionMaster()->MoveChase(player);
95+
});
96+
}, 10s, 15s);
97+
GravityLapseSequence(true);
98+
});
10299
}
103100

104101
void JustSummoned(Creature* summon) override
105102
{
106-
for (SummonList::const_iterator itr = summons.begin(); itr != summons.end(); ++itr)
107-
if (*itr == summon->GetGUID())
108-
return;
109-
summons.Summon(summon);
103+
BossAI::JustSummoned(summon);
104+
summon->SetReactState(REACT_PASSIVE);
105+
}
106+
107+
void GravityLapseSequence(bool firstTime)
108+
{
109+
Talk(firstTime ? SAY_GRAVITY_LAPSE : SAY_RECAST_GRAVITY);
110+
DoCastSelf(SPELL_GRAVITY_LAPSE_INITIAL);
111+
scheduler.Schedule(2s, [this](TaskContext){
112+
LapseAction(ACTION_TELEPORT_PLAYERS);
113+
}).Schedule(3s, [this](TaskContext){
114+
LapseAction(ACTION_KNOCKUP);
115+
}).Schedule(4s, [this](TaskContext){
116+
LapseAction(ACTION_ALLOW_FLY);
117+
for (uint8 i = 0; i < 3; ++i)
118+
DoCastSelf(SPELL_SUMMON_ARCANE_SPHERE, true);
119+
DoCastSelf(SPELL_GRAVITY_LAPSE_CHANNEL);
120+
scheduler.Schedule(30s, [this](TaskContext){
121+
LapseAction(ACTION_REMOVE_FLY);
122+
me->InterruptNonMeleeSpells(false);
123+
Talk(SAY_TIRED);
124+
DoCastSelf(SPELL_POWER_FEEDBACK);
125+
scheduler.Schedule(10s, [this](TaskContext){
126+
GravityLapseSequence(false);
127+
});
128+
});
129+
});
110130
}
111131

112132
void InitializeAI() override
113133
{
114-
ScriptedAI::InitializeAI();
134+
BossAI::InitializeAI();
115135
me->SetImmuneToAll(true);
116136
}
117137

118-
void JustDied(Unit*) override
138+
void JustDied(Unit* killer) override
119139
{
120-
instance->SetBossState(DATA_KAELTHAS, DONE);
121-
summons.DespawnAll();
122-
140+
BossAI::JustDied(killer);
123141
if (GameObject* orb = instance->GetGameObject(DATA_ESCAPE_ORB))
124142
orb->RemoveGameObjectFlag(GO_FLAG_NOT_SELECTABLE);
125143
}
126144

127-
void JustEngagedWith(Unit* /*who*/) override
145+
void JustEngagedWith(Unit* who) override
128146
{
129-
instance->SetBossState(DATA_KAELTHAS, IN_PROGRESS);
130-
me->SetInCombatWithZone();
147+
BossAI::JustEngagedWith(who);
131148

132-
events.ScheduleEvent(EVENT_SPELL_FIREBALL, 0);
133-
events.ScheduleEvent(EVENT_SPELL_PHOENIX, 15000);
134-
events.ScheduleEvent(EVENT_SPELL_FLAMESTRIKE, 22000);
135-
events.ScheduleEvent(EVENT_CHECK_HEALTH, 1000);
149+
ScheduleTimedEvent(0ms, [&]{
150+
DoCastVictim(SPELL_FIREBALL);
151+
}, 3000ms, 4500ms);
152+
ScheduleTimedEvent(15s, [&]{
153+
Talk(SAY_PHOENIX);
154+
DoCastSelf(SPELL_PHOENIX);
155+
}, 60s);
156+
ScheduleTimedEvent(22s, [&]{
157+
DoCastRandomTarget(SPELL_FLAMESTRIKE_SUMMON, 0, 100.0f);
158+
Talk(SAY_FLAMESTRIKE);
159+
}, 25s);
136160

137161
if (IsHeroic())
138-
events.ScheduleEvent(EVENT_SPELL_SHOCK_BARRIER, 50000);
162+
ScheduleTimedEvent(50s, [&]{
163+
DoCastSelf(SPELL_SHOCK_BARRIER, true);
164+
me->CastCustomSpell(SPELL_PYROBLAST, SPELLVALUE_MAX_TARGETS, 1, (Unit*)nullptr, false);
165+
}, 50s);
139166
}
140167

141168
void MoveInLineOfSight(Unit* who) override
142169
{
143-
if (!introSpeak && me->IsWithinDistInMap(who, 40.0f) && who->IsPlayer())
170+
if (!_hasDoneIntro && me->IsWithinDistInMap(who, 40.0f) && who->IsPlayer())
144171
{
145172
Talk(SAY_AGGRO);
146-
introSpeak = true;
147-
events2.ScheduleEvent(EVENT_INIT_COMBAT, 35000);
173+
_hasDoneIntro = true;
174+
_OOCScheduler.Schedule(35s, [this](TaskContext){
175+
me->SetReactState(REACT_AGGRESSIVE);
176+
me->SetImmuneToAll(false);
177+
me->SetInCombatWithZone();
178+
});
148179
}
149-
150-
ScriptedAI::MoveInLineOfSight(who);
180+
BossAI::MoveInLineOfSight(who);
151181
}
152182

153-
void DamageTaken(Unit*, uint32& damage, DamageEffectType, SpellSchoolMask) override
183+
void DamageTaken(Unit* attacker, uint32& damage, DamageEffectType damagetype, SpellSchoolMask damageSchoolMask) override
154184
{
155185
if (damage >= me->GetHealth())
156186
{
157187
damage = me->GetHealth() - 1;
158188
if (me->isRegeneratingHealth())
159189
{
190+
me->CastStop();
160191
me->SetRegeneratingHealth(false);
161192
me->SetUnitFlag(UNIT_FLAG_DISABLE_MOVE);
162193
me->SetImmuneToAll(true);
194+
me->SetStandState(UNIT_STAND_STATE_KNEEL);
163195
me->CombatStop();
164196
me->SetReactState(REACT_PASSIVE);
165197
LapseAction(ACTION_REMOVE_FLY);
166-
events.Reset();
167-
events2.ScheduleEvent(EVENT_FINISH_TALK, 6000);
198+
scheduler.CancelAll();
199+
_OOCScheduler.Schedule(6s, [this](TaskContext){
200+
me->KillSelf();
201+
});
168202
Talk(SAY_DEATH);
169203
}
170204
}
205+
BossAI::DamageTaken(attacker, damage, damagetype, damageSchoolMask);
171206
}
172207

173208
void LapseAction(uint8 action)
174209
{
175-
uint8 counter = 0;
176-
Map::PlayerList const& playerList = me->GetMap()->GetPlayers();
177-
for (Map::PlayerList::const_iterator itr = playerList.begin(); itr != playerList.end(); ++itr, ++counter)
178-
if (Player* player = itr->GetSource())
210+
_gravityLapseCounter = 0;
211+
me->GetMap()->DoForAllPlayers([&](Player* player)
212+
{
213+
if (action == ACTION_TELEPORT_PLAYERS)
214+
DoCast(player, SPELL_GRAVITY_LAPSE_PLAYER + _gravityLapseCounter, true);
215+
else if (action == ACTION_KNOCKUP)
216+
player->CastSpell(player, SPELL_GRAVITY_LAPSE_DOT, true, nullptr, nullptr, me->GetGUID());
217+
else if (action == ACTION_ALLOW_FLY)
218+
player->CastSpell(player, SPELL_GRAVITY_LAPSE_FLY, true, nullptr, nullptr, me->GetGUID());
219+
else if (action == ACTION_REMOVE_FLY)
179220
{
180-
if (action == ACTION_TELEPORT_PLAYERS)
181-
me->CastSpell(player, SPELL_GRAVITY_LAPSE_PLAYER + counter, true);
182-
else if (action == ACTION_KNOCKUP)
183-
player->CastSpell(player, SPELL_GRAVITY_LAPSE_DOT, true, nullptr, nullptr, me->GetGUID());
184-
else if (action == ACTION_ALLOW_FLY)
185-
player->CastSpell(player, SPELL_GRAVITY_LAPSE_FLY, true, nullptr, nullptr, me->GetGUID());
186-
else if (action == ACTION_REMOVE_FLY)
187-
{
188-
player->RemoveAurasDueToSpell(SPELL_GRAVITY_LAPSE_FLY);
189-
player->RemoveAurasDueToSpell(SPELL_GRAVITY_LAPSE_DOT);
190-
}
221+
player->RemoveAurasDueToSpell(SPELL_GRAVITY_LAPSE_FLY);
222+
player->RemoveAurasDueToSpell(SPELL_GRAVITY_LAPSE_DOT);
191223
}
224+
++_gravityLapseCounter;
225+
});
192226
}
193227

194228
void UpdateAI(uint32 diff) override
195229
{
196-
events2.Update(diff);
197-
switch (events2.ExecuteEvent())
198-
{
199-
case EVENT_INIT_COMBAT:
200-
me->SetImmuneToAll(false);
201-
if (Unit* target = SelectTargetFromPlayerList(50.0f))
202-
AttackStart(target);
203-
return;
204-
case EVENT_FINISH_TALK:
205-
me->KillSelf();
206-
return;
207-
}
208-
209-
if (!UpdateVictim())
210-
return;
211-
212-
events.Update(diff);
213-
if (me->HasUnitState(UNIT_STATE_CASTING))
214-
return;
215-
216-
switch (uint32 eventId = events.ExecuteEvent())
217-
{
218-
case EVENT_SPELL_FIREBALL:
219-
me->CastSpell(me->GetVictim(), SPELL_FIREBALL, false);
220-
events.ScheduleEvent(EVENT_SPELL_FIREBALL, urand(3000, 4500));
221-
break;
222-
case EVENT_SPELL_FLAMESTRIKE:
223-
if (Unit* target = SelectTarget(SelectTargetMethod::Random, 0, 100, true))
224-
{
225-
me->CastSpell(target, SPELL_FLAMESTRIKE_SUMMON, true);
226-
Talk(SAY_FLAMESTRIKE);
227-
}
228-
events.ScheduleEvent(EVENT_SPELL_FLAMESTRIKE, 25000);
229-
break;
230-
case EVENT_SPELL_SHOCK_BARRIER:
231-
me->CastSpell(me, SPELL_SHOCK_BARRIER, true);
232-
me->CastCustomSpell(SPELL_PYROBLAST, SPELLVALUE_MAX_TARGETS, 1, (Unit*)nullptr, false);
233-
events.ScheduleEvent(EVENT_SPELL_SHOCK_BARRIER, 50000);
234-
break;
235-
case EVENT_SPELL_PHOENIX:
236-
Talk(SAY_PHOENIX);
237-
me->CastSpell(me, SPELL_PHOENIX, false);
238-
events.ScheduleEvent(EVENT_SPELL_PHOENIX, 60000);
239-
break;
240-
case EVENT_CHECK_HEALTH:
241-
if (HealthBelowPct(50))
242-
{
243-
me->ApplySpellImmune(0, IMMUNITY_EFFECT, SPELL_EFFECT_INTERRUPT_CAST, true);
244-
me->CastSpell(me, SPELL_TELEPORT_CENTER, true);
245-
events.Reset();
246-
247-
me->StopMoving();
248-
me->GetMotionMaster()->Clear();
249-
me->GetMotionMaster()->MoveIdle();
250-
251-
events.SetPhase(1);
252-
events.ScheduleEvent(EVENT_GRAVITY_LAPSE_1_1, 0);
253-
break;
254-
}
255-
events.ScheduleEvent(EVENT_CHECK_HEALTH, 500);
256-
break;
257-
case EVENT_GRAVITY_LAPSE_1_1:
258-
case EVENT_GRAVITY_LAPSE_1_2:
259-
Talk(eventId == EVENT_GRAVITY_LAPSE_1_1 ? SAY_GRAVITY_LAPSE : SAY_RECAST_GRAVITY);
260-
me->CastSpell(me, SPELL_GRAVITY_LAPSE_INITIAL, false);
261-
events.ScheduleEvent(EVENT_GRAVITY_LAPSE_2, 2000);
262-
break;
263-
case EVENT_GRAVITY_LAPSE_2:
264-
LapseAction(ACTION_TELEPORT_PLAYERS);
265-
events.ScheduleEvent(EVENT_GRAVITY_LAPSE_3, 1000);
266-
break;
267-
case EVENT_GRAVITY_LAPSE_3:
268-
LapseAction(ACTION_KNOCKUP);
269-
events.ScheduleEvent(EVENT_GRAVITY_LAPSE_4, 1000);
270-
break;
271-
case EVENT_GRAVITY_LAPSE_4:
272-
LapseAction(ACTION_ALLOW_FLY);
273-
for (uint8 i = 0; i < 3; ++i)
274-
me->CastSpell(me, SPELL_SUMMON_ARCANE_SPHERE, true);
275-
276-
me->CastSpell(me, SPELL_GRAVITY_LAPSE_CHANNEL, false);
277-
events.ScheduleEvent(EVENT_GRAVITY_LAPSE_5, 30000);
278-
break;
279-
case EVENT_GRAVITY_LAPSE_5:
280-
LapseAction(ACTION_REMOVE_FLY);
281-
me->InterruptNonMeleeSpells(false);
282-
Talk(SAY_TIRED);
283-
me->CastSpell(me, SPELL_POWER_FEEDBACK, false);
284-
events.ScheduleEvent(EVENT_GRAVITY_LAPSE_1_2, 10000);
285-
break;
286-
}
287-
288-
if (events.GetPhaseMask() == 0)
289-
DoMeleeAttackIfReady();
230+
_OOCScheduler.Update(diff);
231+
BossAI::UpdateAI(diff);
290232
}
233+
private:
234+
TaskScheduler _OOCScheduler;
235+
bool _hasDoneIntro;
236+
uint8 _gravityLapseCounter;
291237
};
292238

293239
class spell_mt_phoenix_burn : public SpellScript

0 commit comments

Comments
 (0)