Project SkyFire Core
SkyFire 5.4.8 server core API documentation
Loading...
Searching...
No Matches
boss_nefarian.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#include "ScriptMgr.h"
7#include "ScriptedGossip.h"
8#include "ScriptedCreature.h"
9#include "blackwing_lair.h"
10#include "Player.h"
11
34
35enum Says
36{
37 // Nefarius
38 // UBRS
42 // BWL
45 // SAY_VAEL_INTRO = 14, Not used - when he corrupts Vaelastrasz
46
47 // Nefarian
52
63};
64
66{
67 GOSSIP_ID = 21332,
69};
70
72{
73 NEFARIUS_PATH_2 = 1379671,
75};
76
82
95
97{
98 // Victor Nefarius
99 // UBRS Spells
100 SPELL_CHROMATIC_CHAOS = 16337, // Self Cast hits 10339
101 SPELL_VAELASTRASZZ_SPAWN = 16354, // Self Cast Depawn one sec after
102 // BWL Spells
106 SPELL_FEAR = 22678,
107
109
110 // Nefarian
117
118 SPELL_MAGE = 23410, // wild magic
119 SPELL_WARRIOR = 23397, // beserk
120 SPELL_DRUID = 23398, // cat form
121 SPELL_PRIEST = 23401, // corrupted healing
122 SPELL_PALADIN = 23418, // syphon blessing
123 SPELL_SHAMAN = 23425, // totems
124 SPELL_WARLOCK = 23427, // infernals
125 SPELL_HUNTER = 23436, // bow broke
126 SPELL_ROGUE = 23414, // Paralise
127 SPELL_DEATH_KNIGHT = 49576 // Death Grip
128
129// 19484
130// 22664
131// 22674
132// 22666
133};
134
135Position const DrakeSpawnLoc[2] = // drakonid
136{
137 {-7591.151855f, -1204.051880f, 476.800476f, 3.0f},
138 {-7514.598633f, -1150.448853f, 476.796570f, 3.0f}
139};
140
142{
143 {-7449.763672f, -1387.816040f, 526.783691f, 3.0f}, // nefarian spawn
144 {-7535.456543f, -1279.562500f, 476.798706f, 3.0f} // nefarian move
145};
146
148
150{
151public:
152 boss_victor_nefarius() : CreatureScript("boss_victor_nefarius") { }
153
155 {
157
159 {
160 if (me->GetMapId() == 469)
161 {
162 if (!me->FindNearestCreature(NPC_NEFARIAN, 1000.0f, true))
163 _Reset();
164 SpawnedAdds = 0;
165
166 me->SetVisible(true);
167 me->SetPhaseMask(1, true);
168 me->SetUInt32Value(UNIT_FIELD_NPC_FLAGS, 1);
169 me->setFaction(35);
170 me->SetStandState(UNIT_STAND_STATE_SIT_HIGH_CHAIR);
171 me->RemoveAura(SPELL_NEFARIANS_BARRIER);
172 }
173 }
174
176 {
177 Reset();
178 }
179
180 void BeginEvent(Player* target)
181 {
182 _EnterCombat();
183
185
186 me->setFaction(103);
187 me->SetUInt32Value(UNIT_FIELD_NPC_FLAGS, 0);
189 me->SetStandState(UNIT_STAND_STATE_STAND);
190 AttackStart(target);
191 events.ScheduleEvent(EVENT_SHADOW_BOLT, std::rand() % 10000 + 3000);
192 events.ScheduleEvent(EVENT_FEAR, std::rand() % 20000 + 10000);
193 //events.ScheduleEvent(EVENT_MIND_CONTROL, std::rand() % 35000 + 30000);
194 events.ScheduleEvent(EVENT_SPAWN_ADD, 10000);
195 }
196
197 void SummonedCreatureDies(Creature* summon, Unit* /*killer*/) OVERRIDE
198 {
199 if (summon->GetEntry() != NPC_NEFARIAN)
200 {
201 summon->UpdateEntry(NPC_BONE_CONSTRUCT);
203 summon->SetReactState(REACT_PASSIVE);
204 summon->SetStandState(UNIT_STAND_STATE_DEAD);
205 }
206 }
207
208 void JustSummoned(Creature* /*summon*/) OVERRIDE { }
209
210 void SetData(uint32 type, uint32 data) OVERRIDE
211 {
212 if (instance && type == 1 && data == 1)
213 {
214 me->StopMoving();
215 events.ScheduleEvent(EVENT_PATH_2, 9000);
216 }
217
218 if (instance && type == 1 && data == 2)
219 {
220 events.ScheduleEvent(EVENT_SUCCESS_1, 5000);
221 }
222 }
223
225 {
226 if (!UpdateVictim())
227 {
228 events.Update(diff);
229
230 while (uint32 eventId = events.ExecuteEvent())
231 {
232 switch (eventId)
233 {
234 case EVENT_PATH_2:
235 me->GetMotionMaster()->MovePath(NEFARIUS_PATH_2, false);
236 events.ScheduleEvent(EVENT_CHAOS_1, 7000);
237 break;
238 case EVENT_CHAOS_1:
239 if (Creature* gyth = me->FindNearestCreature(NPC_GYTH, 75.0f, true))
240 {
241 me->SetFacingToObject(gyth);
243 }
244 events.ScheduleEvent(EVENT_CHAOS_2, 2000);
245 break;
246 case EVENT_CHAOS_2:
248 me->SetFacingTo(1.570796f);
249 break;
250 case EVENT_SUCCESS_1:
251 if (Unit* player = me->SelectNearestPlayer(60.0f))
252 {
253 me->SetFacingToObject(player);
255 if (GameObject* portcullis1 = me->FindNearestGameObject(GO_PORTCULLIS_ACTIVE, 65.0f))
256 portcullis1->SetGoState(GOState::GO_STATE_ACTIVE);
257 if (GameObject* portcullis2 = me->FindNearestGameObject(GO_PORTCULLIS_TOBOSSROOMS, 80.0f))
258 portcullis2->SetGoState(GOState::GO_STATE_ACTIVE);
259 }
260 events.ScheduleEvent(EVENT_SUCCESS_2, 4000);
261 break;
262 case EVENT_SUCCESS_2:
264 me->DespawnOrUnsummon(1000);
265 break;
266 case EVENT_PATH_3:
267 me->GetMotionMaster()->MovePath(NEFARIUS_PATH_3, false);
268 break;
269 default:
270 break;
271 }
272 }
273 return;
274 }
275
276 // Only do this if we haven't spawned nefarian yet
277 if (UpdateVictim() && SpawnedAdds <= 42)
278 {
279 events.Update(diff);
280
281 if (me->HasUnitState(UNIT_STATE_CASTING))
282 return;
283
284 while (uint32 eventId = events.ExecuteEvent())
285 {
286 switch (eventId)
287 {
289 switch (std::rand() % 1)
290 {
291 case 0:
293 break;
294 case 1:
295 if (Unit* target = SelectTarget(SELECT_TARGET_RANDOM, 0, 40, true))
296 DoCast(target, SPELL_SHADOWBOLT);
297 break;
298 }
300 events.ScheduleEvent(EVENT_SHADOW_BOLT, std::rand() % 10000 + 3000);
301 break;
302 case EVENT_FEAR:
303 if (Unit* target = SelectTarget(SELECT_TARGET_RANDOM, 0, 40, true))
304 DoCast(target, SPELL_FEAR);
305 events.ScheduleEvent(EVENT_FEAR, std::rand() % 20000 + 10000);
306 break;
308 if (Unit* target = SelectTarget(SELECT_TARGET_RANDOM, 0, 40, true))
310 events.ScheduleEvent(EVENT_MIND_CONTROL, std::rand() % 35000 + 30000);
311 break;
312 case EVENT_SPAWN_ADD:
313 for (uint8 i=0; i<2; ++i)
314 {
316 if ((std::rand() % 2) == 0)
318 else
319 CreatureID = Entry[std::rand() % 4];
320 if (Creature* dragon = me->SummonCreature(CreatureID, DrakeSpawnLoc[i]))
321 {
322 dragon->setFaction(103);
323 dragon->AI()->AttackStart(me->GetVictim());
324 }
325
326 if (++SpawnedAdds >= 42)
327 {
328 if (Creature* nefarian = me->SummonCreature(NPC_NEFARIAN, NefarianLoc[0]))
329 {
330 nefarian->setActive(true);
331 nefarian->SetCanFly(true);
332 nefarian->SetDisableGravity(true);
333 nefarian->AI()->DoCastAOE(SPELL_SHADOWFLAME_INITIAL);
334 nefarian->GetMotionMaster()->MovePoint(1, NefarianLoc[1]);
335 }
336 events.CancelEvent(EVENT_MIND_CONTROL);
337 events.CancelEvent(EVENT_FEAR);
338 events.CancelEvent(EVENT_SHADOW_BOLT);
339 me->SetVisible(false);
340 return;
341 }
342 }
343 events.ScheduleEvent(EVENT_SPAWN_ADD, 4000);
344 break;
345 }
346 }
347 }
348 }
349
350 void sGossipSelect(Player* player, uint32 sender, uint32 action) OVERRIDE
351 {
352 if (sender == GOSSIP_ID && action == GOSSIP_OPTION_ID)
353 {
354 player->CLOSE_GOSSIP_MENU();
356 BeginEvent(player);
357 }
358 }
359
360 private:
362 };
363
365 {
366 return new boss_victor_nefariusAI(creature);
367 }
368};
369
371{
372public:
373 boss_nefarian() : CreatureScript("boss_nefarian") { }
374
375 struct boss_nefarianAI : public BossAI
376 {
377 boss_nefarianAI(Creature* creature) : BossAI(creature, BOSS_NEFARIAN) { }
378
380 {
381 Phase3 = false;
382 canDespawn = false;
383 DespawnTimer = 30000;
384 }
385
387 {
388 canDespawn = true;
389 }
390
391 void EnterCombat(Unit* /*who*/) OVERRIDE
392 {
393 events.ScheduleEvent(EVENT_SHADOWFLAME, 12000);
394 events.ScheduleEvent(EVENT_FEAR, std::rand() % 35000 + 25000);
395 events.ScheduleEvent(EVENT_VEILOFSHADOW, std::rand() % 35000 + 25000);
396 events.ScheduleEvent(EVENT_CLEAVE, 7000);
397 //events.ScheduleEvent(EVENT_TAILLASH, 10000);
398 events.ScheduleEvent(EVENT_CLASSCALL, std::rand() % 35000 + 30000);
400 }
401
402 void JustDied(Unit* /*Killer*/) OVERRIDE
403 {
404 _JustDied();
406 }
407
409 {
410 if (rand()%5)
411 return;
412
413 Talk(SAY_SLAY, victim);
414 }
415
417 {
418 if (type != POINT_MOTION_TYPE)
419 return;
420
421 if (id == 1)
422 {
423 me->SetInCombatWithZone();
424 if (me->GetVictim())
425 AttackStart(me->GetVictim());
426 }
427 }
428
430 {
431 if (canDespawn && DespawnTimer <= diff)
432 {
433 if (instance)
434 instance->SetBossState(BOSS_NEFARIAN, FAIL);
435
436 std::list<Creature*> constructList;
437 me->GetCreatureListWithEntryInGrid(constructList, NPC_BONE_CONSTRUCT, 500.0f);
438 for (std::list<Creature*>::const_iterator itr = constructList.begin(); itr != constructList.end(); ++itr)
439 (*itr)->DespawnOrUnsummon();
440
441 } else DespawnTimer -= diff;
442
443 if (!UpdateVictim())
444 return;
445
446 if (canDespawn)
447 canDespawn = false;
448
449 events.Update(diff);
450
451 if (me->HasUnitState(UNIT_STATE_CASTING))
452 return;
453
454 while (uint32 eventId = events.ExecuteEvent())
455 {
456 switch (eventId)
457 {
460 events.ScheduleEvent(EVENT_SHADOWFLAME, 12000);
461 break;
462 case EVENT_FEAR:
464 events.ScheduleEvent(EVENT_FEAR, std::rand() % 35000 + 25000);
465 break;
468 events.ScheduleEvent(EVENT_VEILOFSHADOW, std::rand() % 35000 + 25000);
469 break;
470 case EVENT_CLEAVE:
472 events.ScheduleEvent(EVENT_CLEAVE, 7000);
473 break;
474 case EVENT_TAILLASH:
475 // Cast NYI since we need a better check for behind target
477 events.ScheduleEvent(EVENT_TAILLASH, 10000);
478 break;
479 case EVENT_CLASSCALL:
480 if (Unit* target = SelectTarget(SELECT_TARGET_RANDOM, 0, 100.0f, true))
481 switch (target->getClass())
482 {
483 case CLASS_MAGE:
484 Talk(SAY_MAGE);
486 break;
487 case CLASS_WARRIOR:
490 break;
491 case CLASS_DRUID:
493 DoCast(target, SPELL_DRUID);
494 break;
495 case CLASS_PRIEST:
498 break;
499 case CLASS_PALADIN:
502 break;
503 case CLASS_SHAMAN:
506 break;
507 case CLASS_WARLOCK:
510 break;
511 case CLASS_HUNTER:
514 break;
515 case CLASS_ROGUE:
518 break;
522 break;
523 default:
524 break;
525 }
526 events.ScheduleEvent(EVENT_CLASSCALL, std::rand() % 35000 + 30000);
527 break;
528 }
529 }
530
531 // Phase3 begins when health below 20 pct
532 if (!Phase3 && HealthBelowPct(20))
533 {
534 std::list<Creature*> constructList;
535 me->GetCreatureListWithEntryInGrid(constructList, NPC_BONE_CONSTRUCT, 500.0f);
536 for (std::list<Creature*>::const_iterator itr = constructList.begin(); itr != constructList.end(); ++itr)
537 if ((*itr) && !(*itr)->IsAlive())
538 {
539 (*itr)->Respawn();
540 (*itr)->SetInCombatWithZone();
541 (*itr)->RemoveFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NOT_SELECTABLE);
542 (*itr)->SetReactState(REACT_AGGRESSIVE);
543 (*itr)->SetStandState(UNIT_STAND_STATE_STAND);
544 }
545
546 Phase3 = true;
548 }
549
551 }
552
553 private:
556 bool Phase3;
557 };
558
560 {
561 return new boss_nefarianAI(creature);
562 }
563};
564
566{
568 new boss_nefarian();
569}
std::uint8_t uint8
Definition Define.h:79
std::uint32_t uint32
Definition Define.h:77
#define OVERRIDE
Definition Define.h:60
@ GO_STATE_ACTIVE
Definition GameObject.h:576
@ FAIL
@ POINT_MOTION_TYPE
@ CLASS_HUNTER
@ CLASS_DRUID
@ CLASS_SHAMAN
@ CLASS_PRIEST
@ CLASS_WARRIOR
@ CLASS_WARLOCK
@ CLASS_MAGE
@ CLASS_DEATH_KNIGHT
@ CLASS_PALADIN
@ CLASS_ROGUE
@ UNIT_STAND_STATE_SIT_HIGH_CHAIR
Definition Unit.h:168
@ UNIT_STAND_STATE_DEAD
Definition Unit.h:169
@ UNIT_STAND_STATE_STAND
Definition Unit.h:162
@ UNIT_STATE_CASTING
Definition Unit.h:527
@ REACT_PASSIVE
Definition Unit.h:1156
@ REACT_AGGRESSIVE
Definition Unit.h:1158
@ UNIT_FLAG_NOT_SELECTABLE
Definition Unit.h:650
@ SELECT_TARGET_RANDOM
Definition UnitAI.h:23
@ UNIT_FIELD_NPC_FLAGS
@ UNIT_FIELD_FLAGS
Creatures
@ SPELL_CLEAVE
@ EVENT_CLEAVE
@ NPC_GYTH
@ GO_PORTCULLIS_TOBOSSROOMS
@ GO_PORTCULLIS_ACTIVE
@ NPC_NEFARIAN
@ BOSS_NEFARIAN
@ SAY_SLAY
@ SPELL_SHADOWBOLT
#define SAY_DEATH
@ SPELL_SHADOWFLAME
@ EVENT_SHADOWFLAME
@ NEFARIUS_PATH_2
Definition boss_gyth.cpp:22
@ NEFARIUS_PATH_3
Definition boss_gyth.cpp:23
Position const NefarianLoc[2]
@ GO_PORTCULLIS_TOBOSSROOMS
@ GO_PORTCULLIS_ACTIVE
@ SAY_DEATH
@ SAY_PALADIN
@ SAY_CHAOS_SPELL
@ SAY_WARRIOR
@ SAY_SUCCESS
@ SAY_PRIEST
@ SAY_DRUID
@ SAY_SHAMAN
@ SAY_GAMESBEGIN_2
@ SAY_ROGUE
@ SAY_SLAY
@ SAY_MAGE
@ SAY_GAMESBEGIN_1
@ SAY_RAISE_SKELETONS
@ SAY_RANDOM
@ SAY_HUNTER
@ SAY_DEATH_KNIGHT
@ SAY_WARLOCK
@ SAY_FAILURE
@ NPC_BLACK_DRAKANOID
@ NPC_BONE_CONSTRUCT
@ NPC_BLUE_DRAKANOID
@ NPC_CHROMATIC_DRAKANOID
@ NPC_GREEN_DRAKANOID
@ NPC_GYTH
@ NPC_BRONZE_DRAKANOID
@ NPC_RED_DRAKANOID
uint32 const Entry[5]
@ SPELL_CLEAVE
@ SPELL_SHADOW_COMMAND
@ SPELL_VEILOFSHADOW
@ SPELL_DEATH_KNIGHT
@ SPELL_BELLOWINGROAR
@ SPELL_SHAMAN
@ SPELL_FEAR
@ SPELL_DRUID
@ SPELL_PRIEST
@ SPELL_SHADOWBOLT
@ SPELL_NEFARIANS_BARRIER
@ SPELL_CHROMATIC_CHAOS
@ SPELL_SHADOWBOLT_VOLLEY
@ SPELL_VAELASTRASZZ_SPAWN
@ SPELL_ROGUE
@ SPELL_SHADOWFLAME_INITIAL
@ SPELL_TAILLASH
@ SPELL_PALADIN
@ SPELL_SHADOWFLAME
@ SPELL_WARLOCK
@ SPELL_WARRIOR
@ SPELL_MAGE
@ SPELL_HUNTER
void AddSC_boss_nefarian()
Position const DrakeSpawnLoc[2]
@ NEFARIUS_PATH_2
@ NEFARIUS_PATH_3
@ GOSSIP_OPTION_ID
@ GOSSIP_ID
@ EVENT_SUCCESS_3
@ EVENT_CHAOS_1
@ EVENT_SUCCESS_1
@ EVENT_VEILOFSHADOW
@ EVENT_CLASSCALL
@ EVENT_TAILLASH
@ EVENT_CHAOS_2
@ EVENT_SPAWN_ADD
@ EVENT_MIND_CONTROL
@ EVENT_PATH_2
@ EVENT_FEAR
@ EVENT_CLEAVE
@ EVENT_SHADOWFLAME
@ EVENT_PATH_3
@ EVENT_SUCCESS_2
@ EVENT_SHADOW_BOLT
InstanceScript *const instance
EventMap events
BossAI(Creature *creature, uint32 bossId)
void _EnterCombat()
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
CreatureAI * GetAI(Creature *creature) const OVERRIDE
CreatureAI * GetAI(Creature *creature) const OVERRIDE
Creature * me
bool HealthBelowPct(uint32 pct) const
void AttackStart(Unit *) OVERRIDE
void JustDied(Unit *) OVERRIDE
void EnterCombat(Unit *) OVERRIDE
void UpdateAI(uint32 diff) OVERRIDE
== Triggered Actions Requested ==================
void KilledUnit(Unit *victim) OVERRIDE
boss_nefarianAI(Creature *creature)
void MovementInform(uint32 type, uint32 id) OVERRIDE
void SetData(uint32 type, uint32 data) OVERRIDE
void UpdateAI(uint32 diff) OVERRIDE
== Triggered Actions Requested ==================
void SummonedCreatureDies(Creature *summon, Unit *) OVERRIDE
void sGossipSelect(Player *player, uint32 sender, uint32 action) OVERRIDE
CreatureID