Project SkyFire Core
SkyFire 5.4.8 server core API documentation
Loading...
Searching...
No Matches
boss_nightbane.cpp
Go to the documentation of this file.
1/*
2* This file is part of Project SkyFire https://www.projectskyfire.org.
3* See LICENSE.md file for Copyright information
4*/
5
6/* ScriptData
7SDName: Boss_Nightbane
8SD%Complete: 80
9SDComment: SDComment: Timers may incorrect
10SDCategory: Karazhan
11EndScriptData */
12
13#include "ScriptMgr.h"
14#include "ScriptedCreature.h"
15#include "karazhan.h"
16
32
33enum Says
34{
35 EMOTE_SUMMON = 0, // Not used in script
40};
41
42float IntroWay[8][3] =
43{
44 {-11053.37f, -1794.48f, 149.00f},
45 {-11141.07f, -1841.40f, 125.00f},
46 {-11187.28f, -1890.23f, 125.00f},
47 {-11189.20f, -1931.25f, 125.00f},
48 {-11153.76f, -1948.93f, 125.00f},
49 {-11128.73f, -1929.75f, 125.00f},
50 {-11140.00f, -1915.00f, 122.00f},
51 {-11163.00f, -1903.00f, 91.473f}
52};
53
55{
56public:
57 boss_nightbane() : CreatureScript("boss_nightbane") { }
58
60 {
61 boss_nightbaneAI(Creature* creature) : ScriptedAI(creature)
62 {
63 instance = creature->GetInstanceScript();
64 Intro = true;
65 uint32 Phase = 0;
66
67 bool RainBones = false;
68 bool Skeletons = false;
69
79
80 uint32 FlyCount = 0;
81 uint32 FlyTimer = 0;
82
83 bool Flying = false;
84 bool Movement = false;
85
86 uint32 WaitTimer = 0;
87 uint32 MovePhase = 0;
88 }
89
91 {
92 BellowingRoarTimer = 30000;
93 CharredEarthTimer = 15000;
94 DistractingAshTimer = 20000;
96 TailSweepTimer = 12000;
97 RainofBonesTimer = 10000;
98 SmokingBlastTimer = 20000;
100 SearingCindersTimer = 14000;
101 WaitTimer = 1000;
102
103 Phase =1;
104 FlyCount = 0;
105 MovePhase = 0;
106
107 me->SetSpeed(MOVE_RUN, 2.0f);
108 me->SetDisableGravity(true);
109 me->SetWalk(false);
110 me->setActive(true);
111
112 if (instance)
113 {
114 if (instance->GetData(TYPE_NIGHTBANE) == DONE || instance->GetData(TYPE_NIGHTBANE) == IN_PROGRESS)
115 me->DisappearAndDie();
116 else
118 }
119
120 HandleTerraceDoors(true);
121
122 Flying = false;
123 Movement = false;
124
125 if (!Intro)
126 {
127 me->SetHomePosition(IntroWay[7][0], IntroWay[7][1], IntroWay[7][2], 0);
128 me->GetMotionMaster()->MoveTargetedHome();
129 }
130 }
131
132 void HandleTerraceDoors(bool open)
133 {
134 if (instance)
135 {
136 instance->HandleGameObject(instance->GetData64(DATA_MASTERS_TERRACE_DOOR_1), open);
137 instance->HandleGameObject(instance->GetData64(DATA_MASTERS_TERRACE_DOOR_2), open);
138 }
139 }
140
141 void EnterCombat(Unit* /*who*/) OVERRIDE
142 {
143 if (instance)
145
146 HandleTerraceDoors(false);
148 }
149
151 {
152 if (!Intro && !Flying)
154 }
155
156 void JustDied(Unit* /*killer*/) OVERRIDE
157 {
158 if (instance)
159 instance->SetData(TYPE_NIGHTBANE, DONE);
160
161 HandleTerraceDoors(true);
162 }
163
165
166 {
167 if (!Intro && !Flying)
169 }
170
172 {
173 if (type != POINT_MOTION_TYPE)
174 return;
175
176 if (Intro)
177 {
178 if (id >= 8)
179 {
180 Intro = false;
181 me->SetHomePosition(IntroWay[7][0], IntroWay[7][1], IntroWay[7][2], 0);
182 return;
183 }
184
185 WaitTimer = 1;
186 }
187
188 if (Flying)
189 {
190 if (id == 0)
191 {
193 Flying = false;
194 Phase = 2;
195 return;
196 }
197
198 if (id == 3)
199 {
200 MovePhase = 4;
201 WaitTimer = 1;
202 return;
203 }
204
205 if (id == 8)
206 {
207 Flying = false;
208 Phase = 1;
209 Movement = true;
210 return;
211 }
212
213 WaitTimer = 1;
214 }
215 }
216
218 {
219 summoned->AI()->AttackStart(me->GetVictim());
220 }
221
222 void TakeOff()
223 {
225
226 me->InterruptSpell(CURRENT_GENERIC_SPELL);
227 me->HandleEmoteCommand(EMOTE_ONESHOT_LIFTOFF);
228 me->SetDisableGravity(true);
229 (*me).GetMotionMaster()->Clear(false);
230 (*me).GetMotionMaster()->MovePoint(0, IntroWay[2][0], IntroWay[2][1], IntroWay[2][2]);
231
232 Flying = true;
233
234 FlyTimer = std::rand() % 60000 + 45000; //timer wrong between 45 and 60 seconds
235 ++FlyCount;
236
237 RainofBonesTimer = 5000; //timer wrong (maybe)
238 RainBones = false;
239 Skeletons = false;
240 }
241
243 {
244 /* The timer for this was never setup apparently, not sure if the code works properly:
245 if (WaitTimer <= diff)
246 {
247 if (Intro)
248 {
249 if (MovePhase >= 7)
250 {
251 me->SetLevitate(false);
252 me->HandleEmoteCommand(EMOTE_ONESHOT_LAND);
253 me->GetMotionMaster()->MovePoint(8, IntroWay[7][0], IntroWay[7][1], IntroWay[7][2]);
254 }
255 else
256 {
257 me->GetMotionMaster()->MovePoint(MovePhase, IntroWay[MovePhase][0], IntroWay[MovePhase][1], IntroWay[MovePhase][2]);
258 ++MovePhase;
259 }
260 }
261 if (Flying)
262 {
263 if (MovePhase >= 7)
264 {
265 me->SetLevitate(false);
266 me->HandleEmoteCommand(EMOTE_ONESHOT_LAND);
267 me->GetMotionMaster()->MovePoint(8, IntroWay[7][0], IntroWay[7][1], IntroWay[7][2]);
268 }
269 else
270 {
271 me->GetMotionMaster()->MovePoint(MovePhase, IntroWay[MovePhase][0], IntroWay[MovePhase][1], IntroWay[MovePhase][2]);
272 ++MovePhase;
273 }
274 }
275
276 WaitTimer = 0;
277 } else WaitTimer -= diff;
278 */
279
280 if (!UpdateVictim())
281 return;
282
283 if (Flying)
284 return;
285
286 // Phase 1 "GROUND FIGHT"
287 if (Phase == 1)
288 {
289 if (Movement)
290 {
291 DoStartMovement(me->GetVictim());
292 Movement = false;
293 }
294
295 if (BellowingRoarTimer <= diff)
296 {
298 BellowingRoarTimer = std::rand() % 40000 + 30000;
299 } else BellowingRoarTimer -= diff;
300
301 if (SmolderingBreathTimer <= diff)
302 {
304 SmolderingBreathTimer = 20000;
305 } else SmolderingBreathTimer -= diff;
306
307 if (CharredEarthTimer <= diff)
308 {
309 if (Unit* target = SelectTarget(SELECT_TARGET_RANDOM, 0, 100, true))
311 CharredEarthTimer = 20000;
312 } else CharredEarthTimer -= diff;
313
314 if (TailSweepTimer <= diff)
315 {
316 if (Unit* target = SelectTarget(SELECT_TARGET_RANDOM, 0, 100, true))
317 if (!me->HasInArc(M_PI, target))
318 DoCast(target, SPELL_TAIL_SWEEP);
319 TailSweepTimer = 15000;
320 } else TailSweepTimer -= diff;
321
322 if (SearingCindersTimer <= diff)
323 {
324 if (Unit* target = SelectTarget(SELECT_TARGET_RANDOM, 0, 100, true))
326 SearingCindersTimer = 10000;
327 } else SearingCindersTimer -= diff;
328
329 uint32 Prozent = uint32(me->GetHealthPct());
330
331 if (Prozent < 75 && FlyCount == 0) // first take off 75%
332 TakeOff();
333
334 if (Prozent < 50 && FlyCount == 1) // secound take off 50%
335 TakeOff();
336
337 if (Prozent < 25 && FlyCount == 2) // third take off 25%
338 TakeOff();
339
341 }
342
343 //Phase 2 "FLYING FIGHT"
344 if (Phase == 2)
345 {
346 if (!RainBones)
347 {
348 if (!Skeletons)
349 {
350 for (uint8 i = 0; i <= 3; ++i)
351 {
353 Skeletons = true;
354 }
355 }
356
357 if (RainofBonesTimer < diff && !RainBones) // only once at the beginning of phase 2
358 {
360 RainBones = true;
361 SmokingBlastTimer = 20000;
362 } else RainofBonesTimer -= diff;
363
364 if (DistractingAshTimer <= diff)
365 {
366 if (Unit* target = SelectTarget(SELECT_TARGET_RANDOM, 0, 100, true))
368 DistractingAshTimer = 2000; //timer wrong
369 } else DistractingAshTimer -= diff;
370 }
371
372 if (RainBones)
373 {
374 if (SmokingBlastTimer <= diff)
375 {
377 SmokingBlastTimer = 1500; //timer wrong
378 } else SmokingBlastTimer -= diff;
379 }
380
381 if (FireballBarrageTimer <= diff)
382 {
383 if (Unit* target = SelectTarget(SELECT_TARGET_FARTHEST, 0))
385 FireballBarrageTimer = 20000;
386 } else FireballBarrageTimer -= diff;
387
388 if (FlyTimer <= diff) //landing
389 {
391
392 me->GetMotionMaster()->Clear(false);
393 me->GetMotionMaster()->MovePoint(3, IntroWay[3][0], IntroWay[3][1], IntroWay[3][2]);
394
395 Flying = true;
396 } else FlyTimer -= diff;
397 }
398 }
399
400 private:
402
404
407
417
420
421 bool Intro;
422 bool Flying;
424
427 };
428
430 {
431 return new boss_nightbaneAI(creature);
432 }
433};
434
436{
437 new boss_nightbane();
438}
#define M_PI
Definition Common.h:192
std::uint8_t uint8
Definition Define.h:79
std::uint32_t uint32
Definition Define.h:77
#define OVERRIDE
Definition Define.h:60
@ IN_PROGRESS
@ DONE
@ NOT_STARTED
@ POINT_MOTION_TYPE
@ EMOTE_ONESHOT_LIFTOFF
@ CURRENT_GENERIC_SPELL
Definition Unit.h:1109
@ MOVE_RUN
Definition Unit.h:556
@ SELECT_TARGET_FARTHEST
Definition UnitAI.h:27
@ SELECT_TARGET_RANDOM
Definition UnitAI.h:23
@ YELL_AGGRO
@ YELL_FLY_PHASE
@ EMOTE_BREATH
@ EMOTE_SUMMON
@ YELL_AGGRO
@ YELL_LAND_PHASE
float IntroWay[8][3]
@ SPELL_SMOLDERING_BREATH
@ SPELL_CHARRED_EARTH
@ SPELL_DISTRACTING_ASH
@ SPELL_BELLOWING_ROAR
@ SPELL_RAIN_OF_BONES
@ SPELL_FIREBALL_BARRAGE
@ SPELL_SEARING_CINDERS
@ SPELL_SMOKING_BLAST
@ SPELL_TAIL_SWEEP
@ SPELL_SUMMON_SKELETON
void AddSC_boss_nightbane()
virtual void MoveInLineOfSight(Unit *)
void Talk(uint8 id, WorldObject const *whisperTarget=NULL)
bool UpdateVictim()
CreatureScript(const char *name)
void DoMeleeAttackIfReady()
Definition UnitAI.cpp:28
void DoCast(uint32 spellId)
Definition UnitAI.cpp:110
Unit * SelectTarget(SelectAggroTarget targetType, uint32 position=0, float dist=0.0f, bool playerOnly=false, int32 aura=0)
Definition UnitAI.cpp:66
void DoCastVictim(uint32 spellId, bool triggered=false)
Definition UnitAI.cpp:168
Definition Unit.h:1367
InstanceScript * GetInstanceScript()
Definition Object.cpp:1612
CreatureAI * GetAI(Creature *creature) const OVERRIDE
@ DATA_MASTERS_TERRACE_DOOR_1
Definition karazhan.h:40
@ DATA_MASTERS_TERRACE_DOOR_2
Definition karazhan.h:41
@ TYPE_NIGHTBANE
Definition karazhan.h:22
Creature * me
ScriptedAI(Creature *creature)
void AttackStart(Unit *) OVERRIDE
void DoStartMovement(Unit *target, float distance=0.0f, float angle=0.0f)
void AttackStart(Unit *who) OVERRIDE
void MovementInform(uint32 type, uint32 id) OVERRIDE
void UpdateAI(uint32 diff) OVERRIDE
== Triggered Actions Requested ==================
void JustSummoned(Creature *summoned) OVERRIDE
void MoveInLineOfSight(Unit *who) OVERRIDE