TrinityCore
boss_the_black_stalker.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#include "ScriptedCreature.h"
19#include "ScriptMgr.h"
20#include "SpellScript.h"
21#include "the_underbog.h"
22
23/*
24How levitation sequence works: boss casts Levitate and it triggers a chain of spells, target(any target, player or pet, any position in
25threat list) eventually gets pulled towards by randomly selected trigger. Then target becomes protected from Pull Towards by Suspension
26aura which is triggered every 1 sec up to 4 times. Since it has stun mechanic, diminishing returns cuts off its duration every cast in
27half (20 > 10 > 5 > 0). Eventually player becomes immune to Suspension and vulnerable to another pull towards.
28Whole levitate sequence is designed to pull player towards up to 3 times. Usually it works like this: player gets pulled towards,
29gets protected by Suspension from Pull Towards next 2 times. If player is unlucky, boss can cast Levitate on same player again, in that case
30player can be pulled towards 2 times in a row without any protection from fall damage by Suspension(case from sniffs).
31
32However currently diminishing returns affects Suspension after first cast, its duration is 10 instead of 20 seconds and player will be
33immune to 4th cast. That allows to pull player towards when levitation sequence ends. Levitation sequence has sensetive design and looks
34like lack of delays between packets makes it work differently too.
35Of course as was said above player can be pulled towards 2 times in a row but that looks like a rare case.
36*/
37
39{
42 SPELL_STATIC_CHARGE = 31715, // Never seen any cast on retail, probably because of shared cooldown with Chain Lightning
43 SPELL_SUMMON_PLAYER = 20279, // NYI, may be 20311 or any other
45
51
53};
54
56{
62};
63
65{
67};
68
70{
72
73 void JustEngagedWith(Unit* who) override
74 {
77
82 if (IsHeroic())
84 }
85
86 void UpdateAI(uint32 diff) override
87 {
88 if (!UpdateVictim())
89 return;
90
91 _events.Update(diff);
92
94 return;
95
96 while (uint32 eventId = _events.ExecuteEvent())
97 {
98 switch (eventId)
99 {
101 {
102 float x, y, z, o;
103 me->GetHomePosition(x, y, z, o);
104 if (!me->IsWithinDist3d(x, y, z, 60))
105 {
107 return;
108 }
109 _events.Repeat(1s);
110 break;
111 }
112 case EVENT_LEVITATE:
114 _events.Repeat(18s, 24s);
115 break;
118 _events.Repeat(6s, 12s);
119 break;
121 if (Unit* target = SelectTarget(SelectTargetMethod::Random, 0, 30, true))
123 _events.Repeat(10s);
124 break;
127 _events.Repeat(15s, 25s);
128 break;
129 default:
130 break;
131 }
132
134 return;
135 }
136 }
137
138 void WaypointReached(uint32 waypointId, uint32 pathId) override
139 {
140 if (pathId != PATH_BLACK_STALKER_IDLE)
141 return;
142
143 if (waypointId == 2 || waypointId == 4 || waypointId == 6)
144 {
145 scheduler.Schedule(2s, [this](TaskContext /*task*/)
146 {
148 });
149 }
150 }
151
152private:
155};
156
157// 31704 - Levitate
159{
160 bool Validate(SpellInfo const* /*spellInfo*/) override
161 {
163 }
164
165 void HandleScript(SpellEffIndex /*effIndex*/)
166 {
168 }
169
170 void Register() override
171 {
173 }
174};
175
176// 31701 - Levitation Pulse
178{
179 bool Validate(SpellInfo const* /*spellInfo*/) override
180 {
182 }
183
184 void HandleScript(SpellEffIndex /*effIndex*/)
185 {
187 }
188
189 void Register() override
190 {
192 }
193};
194
195// 31702 - Someone Grab Me
197{
198 bool Validate(SpellInfo const* /*spellInfo*/) override
199 {
201 }
202
203 void HandleScript(SpellEffIndex /*effIndex*/)
204 {
207 }
208
209 void Register() override
210 {
212 }
213};
214
215// 31703 - Magnetic Pull
217{
218 bool Validate(SpellInfo const* /*spellInfo*/) override
219 {
221 }
222
223 void HandleScript(SpellEffIndex /*effIndex*/)
224 {
226 }
227
228 void Register() override
229 {
231 }
232};
233
234// 38756 - Summon Spore Strider
236{
237 bool Validate(SpellInfo const* /*spellInfo*/) override
238 {
240 }
241
242 void HandleScript(SpellEffIndex /*effIndex*/)
243 {
244 for (uint8 i = 0; i < 3; i++)
246 }
247
248 void Register() override
249 {
251 }
252};
253
255{
262}
uint8_t uint8
Definition: Define.h:144
uint32_t uint32
Definition: Define.h:142
#define RegisterSpellScript(spell_script)
Definition: ScriptMgr.h:1369
SpellEffIndex
Definition: SharedDefines.h:29
@ EFFECT_1
Definition: SharedDefines.h:31
@ EFFECT_0
Definition: SharedDefines.h:30
@ EMOTE_ONESHOT_EAT
@ SPELL_EFFECT_SCRIPT_EFFECT
#define SpellEffectFn(F, I, N)
Definition: SpellScript.h:842
@ UNIT_STATE_CASTING
Definition: Unit.h:270
@ EVENT_CHAIN_LIGHTNING
@ EVENT_STATIC_CHARGE
@ EVENT_LEASH_CHECK
@ EVENT_SUMMON_SPORE_STRIDER
@ SPELL_SUSPENSION
@ SPELL_SUSPENSION_PRIMER
@ SPELL_MAGNETIC_PULL
@ SPELL_SUMMON_PLAYER
@ SPELL_SUMMON_SPORE_STRIDER
@ SPELL_SOMEONE_GRAB_ME
@ SPELL_CHAIN_LIGHTNING
@ SPELL_STATIC_CHARGE
@ SPELL_LEVITATION_PULSE
@ SPELL_SUMMON_SPORE_STRIDER_SCRIPT
@ PATH_BLACK_STALKER_IDLE
void AddSC_boss_the_black_stalker()
void JustEngagedWith(Unit *who) override
TaskScheduler scheduler
virtual void EnterEvadeMode(EvadeReason why=EvadeReason::Other)
Definition: CreatureAI.cpp:219
bool UpdateVictim()
Definition: CreatureAI.cpp:245
Creature *const me
Definition: CreatureAI.h:61
void GetHomePosition(float &x, float &y, float &z, float &ori) const
Definition: Creature.h:373
uint32 ExecuteEvent()
Definition: EventMap.cpp:73
void Update(uint32 time)
Definition: EventMap.h:56
void Repeat(Milliseconds time)
Definition: EventMap.cpp:63
void ScheduleEvent(uint32 eventId, Milliseconds time, uint32 group=0, uint8 phase=0)
Definition: EventMap.cpp:36
static bool ValidateSpellInfo(std::initializer_list< uint32 > spellIds)
Definition: SpellScript.h:162
Unit * GetCaster() const
HookList< EffectHandler > OnEffectHit
Definition: SpellScript.h:839
Unit * GetHitUnit() const
HookList< EffectHandler > OnEffectHitTarget
Definition: SpellScript.h:840
TaskScheduler & CancelAll()
TaskScheduler & Schedule(std::chrono::duration< Rep, Period > time, task_handler_t task)
SpellCastResult DoCastSelf(uint32 spellId, CastSpellExtraArgs const &args={})
Definition: UnitAI.h:159
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
bool HasUnitState(const uint32 f) const
Definition: Unit.h:732
void HandleEmoteCommand(Emote emoteId, Player *target=nullptr, Trinity::IteratorPair< int32 const * > spellVisualKitIds={}, int32 sequenceVariation=0)
Definition: Unit.cpp:1598
bool IsWithinDist3d(float x, float y, float z, float dist) const
Definition: Object.cpp:1122
SpellCastResult CastSpell(CastSpellTargetArg const &targets, uint32 spellId, CastSpellExtraArgs const &args={ })
Definition: Object.cpp:2896
bool Validate(SpellInfo const *) override
bool Validate(SpellInfo const *) override
bool Validate(SpellInfo const *) override
bool IsHeroic() const
void UpdateAI(uint32 diff) override
void JustEngagedWith(Unit *who) override
boss_the_black_stalker(Creature *creature)
void WaypointReached(uint32 waypointId, uint32 pathId) override
#define RegisterTheUnderbogCreatureAI(ai_name)
Definition: the_underbog.h:48
@ DATA_THE_BLACK_STALKER
Definition: the_underbog.h:33