TrinityCore
Loading...
Searching...
No Matches
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 "ScriptMgr.h"
19#include "Containers.h"
20#include "ScriptedCreature.h"
21#include "SpellScript.h"
22#include "the_underbog.h"
23
24/*
25 * How levitation sequence works: boss casts Levitate and it triggers a chain of spells, target(any target, player or pet, any position in
26 threat list) eventually gets pulled towards by randomly selected trigger. Then target becomes protected from Pull Towards by Suspension
27 aura which is triggered every 1 sec up to 4 times. Since it has stun mechanic, diminishing returns cuts off its duration every cast in
28 half (20 > 10 > 5 > 0). Eventually player becomes immune to Suspension and vulnerable to another pull towards.
29 Whole levitate sequence is designed to pull player towards up to 3 times. Usually it works like this: player gets pulled towards,
30 gets protected by Suspension from Pull Towards next 2 times. If player is unlucky, boss can cast Levitate on same player again, in that case
31 player can be pulled towards 2 times in a row without any protection from fall damage by Suspension(case from sniffs).
32 However currently diminishing returns affects Suspension after first cast, its duration is 10 instead of 20 seconds and player will be
33 immune to 4th cast. That allows to pull player towards when levitation sequence ends. Levitation sequence has sensetive design and looks
34 like lack of delays between packets makes it work differently too.
35 Of course as was said above player can be pulled towards 2 times in a row but that looks like a rare case.
36 * Timers requires to be revisited
37 */
38
40{
41 // Combat
44 SPELL_STATIC_CHARGE = 31715, // Never seen any cast on retail, probably because of shared cooldown with Chain Lightning
46
47 // Scripts
54};
55
64
69
70// 17882 - The Black Stalker
72{
74
86
87 void UpdateAI(uint32 diff) override
88 {
89 if (!UpdateVictim())
90 return;
91
92 events.Update(diff);
93
95 return;
96
97 while (uint32 eventId = events.ExecuteEvent())
98 {
99 switch (eventId)
100 {
102 if (me->GetPositionX() < 100.0f || me->GetPositionY() < -30.0f)
104 events.Repeat(1s);
105 break;
106 case EVENT_LEVITATE:
108 events.Repeat(18s, 24s);
109 break;
112 events.Repeat(6s, 12s);
113 break;
115 if (Unit* target = SelectTarget(SelectTargetMethod::Random, 0, 30, true))
117 events.Repeat(10s);
118 break;
121 events.Repeat(15s, 25s);
122 break;
123 default:
124 break;
125 }
126
128 return;
129 }
130 }
131
132 void WaypointReached(uint32 waypointId, uint32 pathId) override
133 {
134 if (pathId != PATH_BLACK_STALKER_IDLE)
135 return;
136
137 if (waypointId == 2 || waypointId == 4 || waypointId == 6)
138 {
139 scheduler.Schedule(2s, [this](TaskContext const& /*task*/)
140 {
142 });
143 }
144 }
145};
146
147// 31704 - Levitate
149{
150 bool Validate(SpellInfo const* /*spellInfo*/) override
151 {
153 }
154
155 void HandleScript(SpellEffIndex /*effIndex*/)
156 {
158 }
159
164};
165
166// 31701 - Levitation Pulse
168{
169 bool Validate(SpellInfo const* /*spellInfo*/) override
170 {
172 }
173
174 void HandleScript(SpellEffIndex /*effIndex*/)
175 {
176 GetCaster()->CastSpell(nullptr, SPELL_SOMEONE_GRAB_ME, true);
177 }
178
183};
184
185// 31702 - Someone Grab Me
210
211// 31703 - Magnetic Pull
213{
214 bool Validate(SpellInfo const* /*spellInfo*/) override
215 {
217 }
218
219 void HandleScript(SpellEffIndex /*effIndex*/)
220 {
222 }
223
228};
229
230// 38756 - Summon Spore Strider
232{
233 bool Validate(SpellInfo const* /*spellInfo*/) override
234 {
236 }
237
238 void HandleScript(SpellEffIndex /*effIndex*/)
239 {
240 Unit* caster = GetCaster();
241 for (uint8 i = 0; i < 3; i++)
242 caster->CastSpell(nullptr, SPELL_SUMMON_SPORE_STRIDER_EFFECT, true);
243 }
244
249};
250
uint8_t uint8
Definition Define.h:156
uint32_t uint32
Definition Define.h:154
#define RegisterSpellScript(spell_script)
Definition ScriptMgr.h:1383
SpellEffIndex
@ EFFECT_1
@ EFFECT_0
@ SPELL_EFFECT_SCRIPT_EFFECT
@ TARGET_UNIT_SRC_AREA_ENTRY
@ EMOTE_ONESHOT_EAT
#define SpellEffectFn(F, I, N)
#define SpellObjectAreaTargetSelectFn(F, I, N)
@ UNIT_STATE_CASTING
Definition Unit.h:290
@ EVENT_CHAIN_LIGHTNING
@ EVENT_STATIC_CHARGE
@ EVENT_SUMMON_SPORE_STRIDER
@ SPELL_SUSPENSION_PRIMER
@ SPELL_MAGNETIC_PULL
@ SPELL_SUMMON_SPORE_STRIDER
@ SPELL_SOMEONE_GRAB_ME
@ SPELL_SUMMON_SPORE_STRIDER_EFFECT
@ SPELL_CHAIN_LIGHTNING
@ SPELL_STATIC_CHARGE
@ SPELL_LEVITATION_PULSE
@ PATH_BLACK_STALKER_IDLE
void AddSC_boss_the_black_stalker()
void JustEngagedWith(Unit *who) override
TaskScheduler scheduler
EventMap events
virtual void EnterEvadeMode(EvadeReason why=EvadeReason::Other)
bool UpdateVictim()
Creature *const me
Definition CreatureAI.h:63
void Update(uint32 time)
Definition EventMap.h:77
void Repeat(Milliseconds time)
Definition EventMap.cpp:67
EventId ExecuteEvent()
Definition EventMap.cpp:77
void ScheduleEvent(EventId eventId, Milliseconds time, GroupIndex group=0u, PhaseIndex phase=0u)
Definition EventMap.cpp:40
static bool ValidateSpellInfo(std::initializer_list< uint32 > spellIds)
Unit * GetCaster() const
HookList< EffectHandler > OnEffectHit
Unit * GetHitUnit() const
HookList< EffectHandler > OnEffectHitTarget
HookList< ObjectAreaTargetSelectHandler > OnObjectAreaTargetSelect
TaskScheduler & Schedule(duration_t time, task_handler_t task)
SpellCastResult DoCastSelf(uint32 spellId, CastSpellExtraArgs const &args={})
Definition UnitAI.h:160
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
bool HasUnitState(const uint32 f) const
Definition Unit.h:755
void HandleEmoteCommand(Emote emoteId, Player *target=nullptr, Trinity::IteratorPair< int32 const * > spellVisualKitIds={}, int32 sequenceVariation=0)
Definition Unit.cpp:1662
SpellCastResult CastSpell(CastSpellTargetArg const &targets, uint32 spellId, CastSpellExtraArgs const &args={ })
Definition Object.cpp:2222
bool Validate(SpellInfo const *) override
bool Validate(SpellInfo const *) override
void FilterTargets(std::list< WorldObject * > &targets)
void RandomResize(C &container, std::size_t requestedSize)
Definition Containers.h:67
constexpr float GetPositionX() const
Definition Position.h:87
constexpr float GetPositionY() const
Definition Position.h:88
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)
@ DATA_THE_BLACK_STALKER