TrinityCore
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
34{
41
43
44 // Midnight
47};
48
50{
51 // Attumen
55 SPELL_CHARGE = 29847,
56
57 // Midnight
60 SPELL_MOUNT = 29770,
62};
63
65{
69};
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}
Texts
uint8_t uint8
Definition: Define.h:144
int32_t int32
Definition: Define.h:138
uint32_t uint32
Definition: Define.h:142
std::chrono::seconds Seconds
Seconds shorthand typedef.
Definition: Duration.h:32
Spells
Definition: PlayerAI.cpp:32
if(posix_memalign(&__mallocedMemory, __align, __size)) return NULL
@ MECHANIC_DISARM
EvadeReason
Definition: UnitAICommon.h:30
@ REACT_DEFENSIVE
Definition: UnitDefines.h:507
@ REACT_PASSIVE
Definition: UnitDefines.h:506
DamageEffectType
Definition: UnitDefines.h:131
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
void JustEngagedWith(Unit *who) override
void JustSummoned(Creature *summon) override
void _DespawnAtEvade(Seconds delayToRespawn=30s, Creature *who=nullptr)
TaskScheduler scheduler
void Reset() override
void _JustDied()
void DoZoneInCombat()
Definition: CreatureAI.h:161
void Talk(uint8 id, WorldObject const *whisperTarget=nullptr)
Definition: CreatureAI.cpp:56
bool UpdateVictim()
Definition: CreatureAI.cpp:245
void AttackStart(Unit *victim) override
== Triggered Actions Requested ==================
Definition: CreatureAI.cpp:328
Creature *const me
Definition: CreatureAI.h:61
void SetReactState(ReactStates st)
Definition: Creature.h:160
void DespawnOrUnsummon(Milliseconds timeToDespawn=0s, Seconds forceRespawnTime=0s)
Definition: Creature.cpp:2415
CreatureAI * AI() const
Definition: Creature.h:214
void MoveFollow(Unit *target, float dist, ChaseAngle angle, Optional< Milliseconds > duration={}, MovementSlot slot=MOTION_SLOT_ACTIVE)
void Clear()
Definition: ObjectGuid.h:286
uint32 GetEntry() const
Definition: Object.h:161
static ObjectGuid GetGUID(Object const *o)
Definition: Object.h:159
uint32 const Id
Definition: SpellInfo.h:325
uint32 Mechanic
Definition: SpellInfo.h:329
TaskContext & Repeat(std::chrono::duration< Rep, Period > duration)
TaskScheduler & CancelAll()
TaskScheduler & Schedule(std::chrono::duration< Rep, Period > time, task_handler_t task)
TaskScheduler & Update(success_t const &callback=nullptr)
Trinity::IteratorPair< ThreatListIterator, std::nullptr_t > GetUnsortedThreatList() const
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
virtual void SetGUID(ObjectGuid const &, int32=0)
Definition: UnitAI.h:75
SpellCastResult DoCastAOE(uint32 spellId, CastSpellExtraArgs const &args={})
Definition: UnitAI.h:161
SpellCastResult DoCast(uint32 spellId)
Definition: UnitAI.cpp:89
Definition: Unit.h:627
void SetVisible(bool x)
Definition: Unit.cpp:8351
void SetHealth(uint64 val)
Definition: Unit.cpp:9346
ThreatManager & GetThreatManager()
Definition: Unit.h:1063
MotionMaster * GetMotionMaster()
Definition: Unit.h:1652
uint64 GetHealth() const
Definition: Unit.h:776
Unit * GetVictim() const
Definition: Unit.h:715
void RemoveAllAttackers()
Definition: Unit.cpp:5881
bool HealthBelowPctDamaged(int32 pct, uint32 damage) const
Definition: Unit.h:781
bool AttackStop()
Definition: Unit.cpp:5781
bool IsWithinDist2d(float x, float y, float dist) const
Definition: Object.cpp:1132
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) -> typename std::add_const< decltype(*std::begin(container))>::type &
Definition: Containers.h:109
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)