TrinityCore
Loading...
Searching...
No Matches
boss_midnight.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_Midnight
20SD%Complete: 100
21SDComment:
22SDCategory: Karazhan
23EndScriptData */
24
25#include "ScriptMgr.h"
26#include "Containers.h"
27#include "karazhan.h"
28#include "MotionMaster.h"
29#include "ObjectAccessor.h"
30#include "ScriptedCreature.h"
31#include "SpellInfo.h"
32
48
50{
51 // Attumen
55 SPELL_CHARGE = 29847,
56
57 // Midnight
60 SPELL_MOUNT = 29770,
62};
63
70
72{
73public:
74 boss_attumen() : CreatureScript("boss_attumen") { }
75
76 struct boss_attumenAI : public BossAI
77 {
79 {
80 Initialize();
81 }
82
84 {
87 }
88
89 void Reset() override
90 {
91 Initialize();
93 }
94
95 void EnterEvadeMode(EvadeReason /*why*/) override
96 {
98 BossAI::_DespawnAtEvade(Seconds(10), midnight);
99
101 }
102
103 void ScheduleTasks() override
104 {
105 scheduler.Schedule(Seconds(15), Seconds(25), [this](TaskContext& task)
106 {
108 task.Repeat(Seconds(15), Seconds(25));
109 });
110
111 scheduler.Schedule(Seconds(25), Seconds(45), [this](TaskContext& task)
112 {
115
116 task.Repeat(Seconds(25), Seconds(45));
117 });
118
119 scheduler.Schedule(Seconds(30), Seconds(60), [this](TaskContext& task)
120 {
122 task.Repeat(Seconds(30), Seconds(60));
123 });
124 }
125
126 void DamageTaken(Unit* /*attacker*/, uint32& damage, DamageEffectType /*damageType*/, SpellInfo const* /*spellInfo = nullptr*/) override
127 {
128 // Attumen does not die until he mounts Midnight, let health fall to 1 and prevent further damage.
129 if (damage >= me->GetHealth() && _phase != PHASE_MOUNTED)
130 damage = me->GetHealth() - 1;
131
133 {
135
137 midnight->AI()->DoCastAOE(SPELL_MOUNT, true);
138 }
139 }
140
141 void KilledUnit(Unit* /*victim*/) override
142 {
143 Talk(SAY_KILL);
144 }
145
146 void JustSummoned(Creature* summon) override
147 {
148 if (summon->GetEntry() == NPC_ATTUMEN_MOUNTED)
150 {
151 if (midnight->GetHealth() > me->GetHealth())
152 summon->SetHealth(midnight->GetHealth());
153 else
154 summon->SetHealth(me->GetHealth());
155
156 summon->AI()->DoZoneInCombat();
158 }
159
160 BossAI::JustSummoned(summon);
161 }
162
163 void IsSummonedBy(WorldObject* summoner) override
164 {
165 if (summoner->GetEntry() == NPC_MIDNIGHT)
167
168 if (summoner->GetEntry() == NPC_ATTUMEN_UNMOUNTED)
169 {
172
173 scheduler.Schedule(Seconds(10), Seconds(25), [this](TaskContext& task)
174 {
175 Unit* target = nullptr;
176 std::vector<Unit*> target_list;
177
178 for (auto* ref : me->GetThreatManager().GetUnsortedThreatList())
179 {
180 target = ref->GetVictim();
181 if (target && !target->IsWithinDist(me, 8.00f, false) && target->IsWithinDist(me, 25.0f, false))
182 target_list.push_back(target);
183
184 target = nullptr;
185 }
186
187 if (!target_list.empty())
189
190 DoCast(target, SPELL_CHARGE);
191 task.Repeat(Seconds(10), Seconds(25));
192 });
193
194 scheduler.Schedule(Seconds(25), Seconds(35), [this](TaskContext& task)
195 {
197 task.Repeat(Seconds(25), Seconds(35));
198 });
199 }
200 }
201
202 void JustDied(Unit* /*killer*/) override
203 {
205 if (Unit* midnight = ObjectAccessor::GetUnit(*me, _midnightGUID))
206 midnight->KillSelf();
207
208 _JustDied();
209 }
210
211 void SetGUID(ObjectGuid const& guid, int32 id) override
212 {
213 if (id == NPC_MIDNIGHT)
214 _midnightGUID = guid;
215 }
216
217 void UpdateAI(uint32 diff) override
218 {
219 if (!UpdateVictim() && _phase != PHASE_NONE)
220 return;
221
222 scheduler.Update(diff);
223 }
224
225 void SpellHit(WorldObject* /*caster*/, SpellInfo const* spellInfo) override
226 {
227 if (spellInfo->Mechanic == MECHANIC_DISARM)
229
230 if (spellInfo->Id == SPELL_MOUNT)
231 {
233 {
236
237 midnight->AttackStop();
238 midnight->RemoveAllAttackers();
239 midnight->SetReactState(REACT_PASSIVE);
240 midnight->GetMotionMaster()->MoveFollow(me, 2.0f, 0.0f);
241 midnight->AI()->Talk(EMOTE_MOUNT_UP);
242
243 me->AttackStop();
246 me->GetMotionMaster()->MoveFollow(midnight, 2.0f, 0.0f);
248
249 scheduler.Schedule(Seconds(1), [this](TaskContext& task)
250 {
252 {
253 if (me->IsWithinDist2d(midnight, 5.0f))
254 {
255 DoCastAOE(SPELL_SUMMON_ATTUMEN_MOUNTED);
256 me->SetVisible(false);
257 me->GetMotionMaster()->Clear();
258 midnight->SetVisible(false);
259 }
260 else
261 {
262 midnight->GetMotionMaster()->MoveFollow(me, 2.0f, 0.0f);
263 me->GetMotionMaster()->MoveFollow(midnight, 2.0f, 0.0f);
264 task.Repeat();
265 }
266 }
267 });
268 }
269 }
270 }
271
272 private:
275 };
276
277 CreatureAI* GetAI(Creature* creature) const override
278 {
279 return GetKarazhanAI<boss_attumenAI>(creature);
280 }
281};
282
284{
285public:
286 boss_midnight() : CreatureScript("boss_midnight") { }
287
288 struct boss_midnightAI : public BossAI
289 {
291 {
292 Initialize();
293 }
294
296 {
298 }
299
300 void Reset() override
301 {
302 Initialize();
304 me->SetVisible(true);
306 }
307
308 void DamageTaken(Unit* /*attacker*/, uint32& damage, DamageEffectType /*damageType*/, SpellInfo const* /*spellInfo = nullptr*/) override
309 {
310 // Midnight never dies, let health fall to 1 and prevent further damage.
311 if (damage >= me->GetHealth())
312 damage = me->GetHealth() - 1;
313
314 if (_phase == PHASE_NONE && me->HealthBelowPctDamaged(95, damage))
315 {
319 }
320 else if (_phase == PHASE_ATTUMEN_ENGAGES && me->HealthBelowPctDamaged(25, damage))
321 {
323 DoCastAOE(SPELL_MOUNT, true);
324 }
325 }
326
327 void JustSummoned(Creature* summon) override
328 {
329 if (summon->GetEntry() == NPC_ATTUMEN_UNMOUNTED)
330 {
331 _attumenGUID = summon->GetGUID();
332 summon->AI()->SetGUID(me->GetGUID(), NPC_MIDNIGHT);
333 summon->AI()->AttackStart(me->GetVictim());
334 summon->AI()->Talk(SAY_APPEAR);
335 }
336
337 BossAI::JustSummoned(summon);
338 }
339
340 void JustEngagedWith(Unit* who) override
341 {
343
344 scheduler.Schedule(Seconds(15), Seconds(25), [this](TaskContext& task)
345 {
347 task.Repeat(Seconds(15), Seconds(25));
348 });
349 }
350
351 void EnterEvadeMode(EvadeReason /*why*/) override
352 {
354 }
355
356 void KilledUnit(Unit* /*victim*/) override
357 {
359 {
361 Talk(SAY_MIDNIGHT_KILL, unit);
362 }
363 }
364
365 void UpdateAI(uint32 diff) override
366 {
367 if (!UpdateVictim() || _phase == PHASE_MOUNTED)
368 return;
369
370 scheduler.Update(diff);
371 }
372
373 private:
376 };
377
378 CreatureAI* GetAI(Creature* creature) const override
379 {
380 return GetKarazhanAI<boss_midnightAI>(creature);
381 }
382};
383
385{
386 new boss_attumen();
387 new boss_midnight();
388}
uint8_t uint8
Definition Define.h:156
int32_t int32
Definition Define.h:150
uint32_t uint32
Definition Define.h:154
std::chrono::seconds Seconds
Seconds shorthand typedef.
Definition Duration.h:28
Spells
Definition PlayerAI.cpp:32
@ MECHANIC_DISARM
EvadeReason
@ REACT_DEFENSIVE
@ REACT_PASSIVE
DamageEffectType
void AddSC_boss_attumen()
@ SPELL_SHADOWCLEAVE
@ SPELL_MOUNT
@ SPELL_CHARGE
@ SPELL_SUMMON_ATTUMEN
@ SPELL_SUMMON_ATTUMEN_MOUNTED
@ SPELL_INTANGIBLE_PRESENCE
@ SPELL_SPAWN_SMOKE
@ SPELL_KNOCKDOWN
@ PHASE_MOUNTED
@ PHASE_NONE
@ PHASE_ATTUMEN_ENGAGES
@ SAY_DEATH
@ SAY_DISARMED
@ SAY_MIDNIGHT_KILL
@ EMOTE_MOUNT_UP
@ SAY_KILL
@ SAY_MOUNT
@ SAY_APPEAR
@ SAY_RANDOM
@ EMOTE_CALL_ATTUMEN
ObjectGuid const & GetGUID() const
Definition BaseEntity.h:163
void JustEngagedWith(Unit *who) override
void JustSummoned(Creature *summon) override
void _DespawnAtEvade(Seconds delayToRespawn=30s, Creature *who=nullptr)
TaskScheduler scheduler
void Reset() override
void DoZoneInCombat()
Definition CreatureAI.h:169
void Talk(uint8 id, WorldObject const *whisperTarget=nullptr)
bool UpdateVictim()
void AttackStart(Unit *victim) override
== Triggered Actions Requested ==================
Creature *const me
Definition CreatureAI.h:63
void SetReactState(ReactStates st)
Definition Creature.h:174
void DespawnOrUnsummon(Milliseconds timeToDespawn=0s, Seconds forceRespawnTime=0s)
CreatureAI * AI() const
Definition Creature.h:228
void MoveFollow(Unit *target, float dist, Optional< ChaseAngle > angle={}, Optional< Milliseconds > duration={}, bool ignoreTargetWalk=false, MovementSlot slot=MOTION_SLOT_ACTIVE, Scripting::v2::ActionResultSetter< MovementStopReason > &&scriptResult={})
void Clear()
Definition ObjectGuid.h:329
uint32 GetEntry() const
Definition Object.h:89
uint32 const Id
Definition SpellInfo.h:328
uint32 Mechanic
Definition SpellInfo.h:332
TaskContext & Repeat(TaskScheduler::duration_t duration)
TaskScheduler & CancelAll()
TaskScheduler & Schedule(duration_t time, task_handler_t task)
TaskScheduler & Update()
Update the scheduler to the current time.
Trinity::IteratorPair< ThreatListIterator, std::nullptr_t > GetUnsortedThreatList() const
SpellCastResult DoCastSelf(uint32 spellId, CastSpellExtraArgs const &args={})
Definition UnitAI.h:160
virtual void SetGUID(ObjectGuid const &guid, int32 id)
Definition UnitAI.h:76
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 DoCastAOE(uint32 spellId, CastSpellExtraArgs const &args={})
Definition UnitAI.h:162
SpellCastResult DoCast(uint32 spellId)
Definition UnitAI.cpp:89
Definition Unit.h:635
void SetVisible(bool x)
Definition Unit.cpp:8768
void SetHealth(uint64 val)
Definition Unit.cpp:9973
ThreatManager & GetThreatManager()
Definition Unit.h:1078
MotionMaster * GetMotionMaster()
Definition Unit.h:1723
uint64 GetHealth() const
Definition Unit.h:788
bool HealthBelowPctDamaged(float pct, uint32 damage) const
Definition Unit.h:793
Unit * GetVictim() const
Definition Unit.h:726
void RemoveAllAttackers()
Definition Unit.cpp:6066
bool AttackStop()
Definition Unit.cpp:5965
bool IsWithinDist2d(float x, float y, float dist) const
Definition Object.cpp:486
bool IsWithinDist(WorldObject const *obj, float dist2compare, bool is3D=true, bool incOwnRadius=true, bool incTargetRadius=true) const
Definition Object.cpp:496
CreatureAI * GetAI(Creature *creature) const override
CreatureAI * GetAI(Creature *creature) const override
@ NPC_ATTUMEN_MOUNTED
Definition karazhan.h:78
@ NPC_ATTUMEN_UNMOUNTED
Definition karazhan.h:77
@ NPC_MIDNIGHT
Definition karazhan.h:79
@ DATA_ATTUMEN
Definition karazhan.h:30
TC_GAME_API Unit * GetUnit(WorldObject const &, ObjectGuid const &guid)
TC_GAME_API Creature * GetCreature(WorldObject const &u, ObjectGuid const &guid)
auto SelectRandomContainerElement(C const &container) -> std::add_const_t< decltype(*std::ranges::begin(container))> &
Definition Containers.h:110
void KilledUnit(Unit *) override
void SpellHit(WorldObject *, SpellInfo const *spellInfo) override
void SetGUID(ObjectGuid const &guid, int32 id) override
void DamageTaken(Unit *, uint32 &damage, DamageEffectType, SpellInfo const *) override
boss_attumenAI(Creature *creature)
void IsSummonedBy(WorldObject *summoner) override
void EnterEvadeMode(EvadeReason) override
void JustDied(Unit *) override
void JustSummoned(Creature *summon) override
void UpdateAI(uint32 diff) override
void DamageTaken(Unit *, uint32 &damage, DamageEffectType, SpellInfo const *) override
void JustSummoned(Creature *summon) override
void UpdateAI(uint32 diff) override
void JustEngagedWith(Unit *who) override
void EnterEvadeMode(EvadeReason) override
void KilledUnit(Unit *) override
boss_midnightAI(Creature *creature)