Project SkyFire Core
SkyFire 5.4.8 server core API documentation
Loading...
Searching...
No Matches
boss_deathbringer_saurfang.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 "ObjectMgr.h"
7#include "ScriptMgr.h"
8#include "ScriptedCreature.h"
9#include "ScriptedGossip.h"
10#include "SpellAuras.h"
11#include "icecrown_citadel.h"
12#include "Player.h"
13
15{
16 // Deathbringer Saurfang
32
33 // High Overlord Saurfang
41 SAY_OUTRO_ALLIANCE_12 = 7, // kneel after WP reached
49
50 // Muradin Bronzebeard
64
65 // Lady Jaina Proudmoore
68
69 // King Varian Wrynn
74};
75
107
108// Helper to get id of the aura on different modes (HasAura(baseId) wont work)
109#define BOILING_BLOOD_HELPER RAID_MODE<int32>(72385, 72441, 72442, 72443)
110
112{
120
130
132
139
161
170};
171
178
189
191{
192 DATA_MADE_A_MESS = 45374613 // 4537, 4613 are achievement IDs
193};
194
196{
197 POINT_SAURFANG = 3781300,
199 POINT_CHARGE = 3781302,
200 POINT_CHOKE = 3781303,
201 POINT_CORPSE = 3781304,
202 POINT_FINAL = 3781305,
203 POINT_EXIT = 5, // waypoint id
204};
205
206Position const deathbringerPos = {-496.3542f, 2211.33f, 541.1138f, 0.0f};
207Position const firstStepPos = {-541.3177f, 2211.365f, 539.2921f, 0.0f};
208
210{
211 {-509.6505f, 2211.377f, 539.2872f, 0.0f}, // High Overlord Saurfang/Muradin Bronzebeard
212 {-508.7480f, 2211.897f, 539.2870f, 0.0f}, // front left
213 {-509.2929f, 2211.411f, 539.2870f, 0.0f}, // front right
214 {-506.6607f, 2211.367f, 539.2870f, 0.0f}, // back middle
215 {-506.1137f, 2213.306f, 539.2870f, 0.0f}, // back left
216 {-509.0040f, 2211.743f, 539.2870f, 0.0f} // back right
217};
218
220{
221 {-514.4834f, 2211.334f, 549.2887f, 0.0f}, // High Overlord Saurfang/Muradin Bronzebeard
222 {-510.1081f, 2211.592f, 546.3773f, 0.0f}, // front left
223 {-513.3210f, 2211.396f, 551.2882f, 0.0f}, // front right
224 {-507.3684f, 2210.353f, 545.7497f, 0.0f}, // back middle
225 {-507.0486f, 2212.999f, 545.5512f, 0.0f}, // back left
226 {-510.7041f, 2211.069f, 546.5298f, 0.0f} // back right
227};
228
229Position const finalPos = {-563.7552f, 2211.328f, 538.7848f, 0.0f};
230
232{
233 public:
234 boss_deathbringer_saurfang() : CreatureScript("boss_deathbringer_saurfang") { }
235
237 {
239 {
240 ASSERT(creature->GetVehicleKit()); // we dont actually use it, just check if exists
241 _introDone = false;
243 }
244
246 {
247 _Reset();
248 me->SetReactState(REACT_DEFENSIVE);
249 events.SetPhase(PHASE_COMBAT);
250 _frenzied = false;
251 _dead = false;
252 me->SetPower(POWER_ENERGY, 0);
253 DoCast(me, SPELL_ZERO_POWER, true);
254 DoCast(me, SPELL_BLOOD_LINK, true);
258 me->RemoveAurasDueToSpell(SPELL_BERSERK);
259 me->RemoveAurasDueToSpell(SPELL_FRENZY);
260 }
261
263 {
264 if (_dead)
265 return;
266
267 if (!instance->CheckRequiredBosses(DATA_DEATHBRINGER_SAURFANG, who->ToPlayer()))
268 {
270 instance->DoCastSpellOnPlayers(LIGHT_S_HAMMER_TELEPORT);
271 return;
272 }
273
274 // oh just screw intro, enter combat - no exploits please
275 me->setActive(true);
277
278 events.Reset();
279 events.SetPhase(PHASE_COMBAT);
281 if (!_introDone)
282 {
285 creature->AI()->DoAction(ACTION_INTERRUPT_INTRO);
286 }
287
288 _introDone = true;
289
291 events.ScheduleEvent(EVENT_SUMMON_BLOOD_BEAST, 30000, 0, PHASE_COMBAT);
292 events.ScheduleEvent(EVENT_BERSERK, IsHeroic() ? 360000 : 480000, 0, PHASE_COMBAT);
293 events.ScheduleEvent(EVENT_BOILING_BLOOD, 15500, 0, PHASE_COMBAT);
294 events.ScheduleEvent(EVENT_BLOOD_NOVA, 17000, 0, PHASE_COMBAT);
295 events.ScheduleEvent(EVENT_RUNE_OF_BLOOD, 20000, 0, PHASE_COMBAT);
296
298 instance->DoRemoveAurasDueToSpellOnPlayers(SPELL_MARK_OF_THE_FALLEN_CHAMPION);
300 }
301
302 void JustDied(Unit* /*killer*/) OVERRIDE
303 {
304 }
305
307 {
309 return;
310
312 }
313
320
322 {
325 instance->DoRemoveAurasDueToSpellOnPlayers(SPELL_MARK_OF_THE_FALLEN_CHAMPION);
326 }
327
329 {
330 if (victim->GetTypeId() == TypeID::TYPEID_PLAYER)
331 Talk(SAY_KILL);
332 }
333
334 void DamageTaken(Unit* /*attacker*/, uint32& damage) OVERRIDE
335 {
336 if (damage >= me->GetHealth())
337 damage = me->GetHealth() - 1;
338
339 if (!_frenzied && HealthBelowPct(31)) // AT 30%, not below
340 {
341 _frenzied = true;
344 }
345
346 if (!_dead && me->GetHealth() < FightWonValue)
347 {
348 _dead = true;
349 _JustDied();
352
356
357 //instance->DoRemoveAurasDueToSpellOnPlayers(SPELL_MARK_OF_THE_FALLEN_CHAMPION);
360 creature->AI()->DoAction(ACTION_START_OUTRO);
361 }
362 }
363
365 {
366 if (Unit* target = SelectTarget(SELECT_TARGET_RANDOM, 1, 0.0f, true))
367 summon->AI()->AttackStart(target);
368
369 summon->CastSpell(summon, SPELL_BLOOD_LINK_BEAST, true);
370 summon->CastSpell(summon, SPELL_RESISTANT_SKIN, true);
371 summons.Summon(summon);
372 DoZoneInCombat(summon);
373 }
374
375 void SummonedCreatureDies(Creature* summon, Unit* /*killer*/) OVERRIDE
376 {
377 summons.Despawn(summon);
378 }
379
381 {
382 if (type != POINT_MOTION_TYPE && id != POINT_SAURFANG)
383 return;
384
385 instance->HandleGameObject(instance->GetData64(GO_SAURFANG_S_DOOR), false);
386 }
387
388 void SpellHitTarget(Unit* target, SpellInfo const* spell) OVERRIDE
389 {
390 switch (spell->Id)
391 {
394 break;
395 case 72255: // Mark of the Fallen Champion, triggered id
396 case 72444:
397 case 72445:
398 case 72446:
399 if (me->GetPower(POWER_ENERGY) != me->GetMaxPower(POWER_ENERGY))
400 target->CastCustomSpell(SPELL_BLOOD_LINK_DUMMY, SPELLVALUE_BASE_POINT0, 1, me, true);
401 break;
402 default:
403 break;
404 }
405 }
406
407 void SpellHit(Unit* /*caster*/, SpellInfo const* spell) OVERRIDE
408 {
409 if (spell->Id == SPELL_BLOOD_LINK_POWER)
410 if (Aura* bloodPower = me->GetAura(SPELL_BLOOD_POWER))
411 bloodPower->RecalculateAmountOfEffects();
412 }
413
415 {
416 if (!UpdateVictim() && !(events.IsInPhase(PHASE_INTRO_A) || events.IsInPhase(PHASE_INTRO_H)))
417 return;
418
419 events.Update(diff);
420
421 if (me->HasUnitState(UNIT_STATE_CASTING))
422 return;
423
424 while (uint32 eventId = events.ExecuteEvent())
425 {
426 switch (eventId)
427 {
430 break;
433 break;
438 break;
441 break;
444 break;
448 break;
450 events.SetPhase(PHASE_COMBAT);
451 _introDone = true;
453 break;
455 for (uint32 i10 = 0; i10 < 2; ++i10)
457 if (Is25ManRaid())
458 for (uint32 i25 = 0; i25 < 3; ++i25)
461 events.ScheduleEvent(EVENT_SUMMON_BLOOD_BEAST, 40000, 0, PHASE_COMBAT);
462 if (IsHeroic())
463 events.ScheduleEvent(EVENT_SCENT_OF_BLOOD, 10000, 0, PHASE_COMBAT);
464 break;
465 case EVENT_BLOOD_NOVA:
467 events.ScheduleEvent(EVENT_BLOOD_NOVA, std::rand() % 25000 + 20000, 0, PHASE_COMBAT);
468 break;
471 events.ScheduleEvent(EVENT_RUNE_OF_BLOOD, std::rand() % 25000 + 20000, 0, PHASE_COMBAT);
472 break;
475 events.ScheduleEvent(EVENT_BOILING_BLOOD, std::rand() % 20000 + 15000, 0, PHASE_COMBAT);
476 break;
477 case EVENT_BERSERK:
480 break;
482 if (!summons.empty())
483 {
486 }
487 break;
488 default:
489 break;
490 }
491 }
492
494 }
495
497 {
498 if (type == DATA_MADE_A_MESS)
500 return 1;
501
502 return 0;
503 }
504
505 // intro setup
507 {
508 switch (action)
509 {
510 case PHASE_INTRO_A:
511 case PHASE_INTRO_H:
512 {
514 {
515 instance->HandleGameObject(0, false, teleporter);
516 teleporter->SetFlag(GAMEOBJECT_FIELD_FLAGS, GO_FLAG_IN_USE);
517 }
518
520 // controls what events will execute
521 events.SetPhase(uint32(action));
522
523 me->SetHomePosition(deathbringerPos.GetPositionX(), deathbringerPos.GetPositionY(), deathbringerPos.GetPositionZ(), me->GetOrientation());
524 me->GetMotionMaster()->MovePoint(POINT_SAURFANG, deathbringerPos.GetPositionX(), deathbringerPos.GetPositionY(), deathbringerPos.GetPositionZ());
525
526 events.ScheduleEvent(EVENT_INTRO_ALLIANCE_2, 2500, 0, PHASE_INTRO_A);
527 events.ScheduleEvent(EVENT_INTRO_ALLIANCE_3, 20000, 0, PHASE_INTRO_A);
528
529 events.ScheduleEvent(EVENT_INTRO_HORDE_2, 5000, 0, PHASE_INTRO_H);
530 break;
531 }
533 {
534 if (_introDone)
535 return;
536
537 events.ScheduleEvent(EVENT_INTRO_ALLIANCE_6, 6500+500, 0, PHASE_INTRO_A);
538 events.ScheduleEvent(EVENT_INTRO_FINISH, 8000, 0, PHASE_INTRO_A);
539
540 events.ScheduleEvent(EVENT_INTRO_HORDE_4, 6500, 0, PHASE_INTRO_H);
541 events.ScheduleEvent(EVENT_INTRO_HORDE_9, 46700+1000+500, 0, PHASE_INTRO_H);
542 events.ScheduleEvent(EVENT_INTRO_FINISH, 46700+1000+8000, 0, PHASE_INTRO_H);
543 break;
544 }
546 {
548 {
551 me->SetPower(POWER_ENERGY, 0);
552 if (Aura* bloodPower = me->GetAura(SPELL_BLOOD_POWER))
553 bloodPower->RecalculateAmountOfEffects();
554 }
555 break;
556 }
557 default:
558 break;
559 }
560 }
561
562 static uint32 const FightWonValue;
563
564 private:
567 bool _frenzied; // faster than iterating all auras to find Frenzy
568 bool _dead;
569 };
570
572 {
574 }
575};
576
578
580{
581 public:
582 npc_high_overlord_saurfang_icc() : CreatureScript("npc_high_overlord_saurfang_icc") { }
583
585 {
587 {
588 ASSERT(creature->GetVehicleKit());
589 _instance = me->GetInstanceScript();
590 }
591
593 {
594 _events.Reset();
595 }
596
598 {
599 switch (action)
600 {
602 {
603 // Prevent crashes
604 if (_events.IsInPhase(PHASE_INTRO_A) || _events.IsInPhase(PHASE_INTRO_H))
605 return;
606
609 uint32 x = 1;
610 for (std::list<Creature*>::iterator itr = _guardList.begin(); itr != _guardList.end(); ++x, ++itr)
611 (*itr)->AI()->SetData(0, x);
612
615 _events.SetPhase(PHASE_INTRO_H);
616 _events.ScheduleEvent(EVENT_INTRO_HORDE_3, 18500, 0, PHASE_INTRO_H);
617 _instance->HandleGameObject(_instance->GetData64(GO_SAURFANG_S_DOOR), true);
619 deathbringer->AI()->DoAction(PHASE_INTRO_H);
620 break;
621 }
623 {
624 me->RemoveAurasDueToSpell(SPELL_GRIP_OF_AGONY);
626 _events.ScheduleEvent(EVENT_OUTRO_HORDE_2, 10000); // say
627 _events.ScheduleEvent(EVENT_OUTRO_HORDE_3, 18000); // say
628 _events.ScheduleEvent(EVENT_OUTRO_HORDE_4, 24000); // cast
629 _events.ScheduleEvent(EVENT_OUTRO_HORDE_5, 30000); // move
630 me->SetDisableGravity(false);
631 me->GetMotionMaster()->MoveFall();
632 for (std::list<Creature*>::iterator itr = _guardList.begin(); itr != _guardList.end(); ++itr)
633 (*itr)->AI()->DoAction(ACTION_DESPAWN);
634 break;
635 }
637 {
638 _events.Reset();
639 for (std::list<Creature*>::iterator itr = _guardList.begin(); itr != _guardList.end(); ++itr)
640 (*itr)->AI()->DoAction(ACTION_DESPAWN);
641 break;
642 }
643 default:
644 break;
645 }
646 }
647
648 void SpellHit(Unit* /*caster*/, SpellInfo const* spell) OVERRIDE
649 {
650 if (spell->Id == SPELL_GRIP_OF_AGONY)
651 {
652 me->SetDisableGravity(true);
653 me->GetMotionMaster()->MovePoint(POINT_CHOKE, chokePos[0]);
654 }
655 }
656
658 {
659 if (type == POINT_MOTION_TYPE)
660 {
661 switch (id)
662 {
663 case POINT_FIRST_STEP:
664 me->SetWalk(false);
666 _events.ScheduleEvent(EVENT_INTRO_HORDE_5, 15500, 0, PHASE_INTRO_H);
667 _events.ScheduleEvent(EVENT_INTRO_HORDE_6, 29500, 0, PHASE_INTRO_H);
668 _events.ScheduleEvent(EVENT_INTRO_HORDE_7, 43800, 0, PHASE_INTRO_H);
669 _events.ScheduleEvent(EVENT_INTRO_HORDE_8, 47000, 0, PHASE_INTRO_H);
671 deathbringer->AI()->DoAction(ACTION_CONTINUE_INTRO);
672 break;
673 case POINT_CORPSE:
675 {
676 deathbringer->CastSpell(me, SPELL_RIDE_VEHICLE, true); // for the packet logs.
677 deathbringer->SetFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NOT_SELECTABLE);
678 deathbringer->SetUInt32Value(UNIT_FIELD_NPC_EMOTESTATE, EMOTE_STATE_DROWNED);
679 }
680 _events.ScheduleEvent(EVENT_OUTRO_HORDE_5, 1000); // move
681 _events.ScheduleEvent(EVENT_OUTRO_HORDE_6, 4000); // say
682 break;
683 case POINT_FINAL:
685 deathbringer->DespawnOrUnsummon();
686 me->DespawnOrUnsummon();
687 break;
688 default:
689 break;
690 }
691 }
692 else if (type == WAYPOINT_MOTION_TYPE && id == POINT_EXIT)
693 {
694 std::list<Creature*> guards;
696 for (std::list<Creature*>::iterator itr = guards.begin(); itr != guards.end(); ++itr)
697 (*itr)->DespawnOrUnsummon();
698 me->DespawnOrUnsummon();
699 }
700 }
701
703 {
704 _events.Update(diff);
705 while (uint32 eventId = _events.ExecuteEvent())
706 {
707 switch (eventId)
708 {
710 me->SetWalk(true);
711 me->GetMotionMaster()->MovePoint(POINT_FIRST_STEP, firstStepPos.GetPositionX(), firstStepPos.GetPositionY(), firstStepPos.GetPositionZ());
712 break;
715 break;
718 break;
721 break;
724 for (std::list<Creature*>::iterator itr = _guardList.begin(); itr != _guardList.end(); ++itr)
725 (*itr)->AI()->DoAction(ACTION_CHARGE);
726 me->GetMotionMaster()->MoveCharge(chargePos[0].GetPositionX(), chargePos[0].GetPositionY(), chargePos[0].GetPositionZ(), 8.5f, POINT_CHARGE);
727 break;
728 case EVENT_OUTRO_HORDE_2: // say
730 me->SetFacingToObject(deathbringer);
732 break;
733 case EVENT_OUTRO_HORDE_3: // say
735 break;
736 case EVENT_OUTRO_HORDE_4: // move
738 {
739 float x, y, z;
740 deathbringer->GetClosePoint(x, y, z, deathbringer->GetObjectSize());
741 me->SetWalk(true);
742 me->GetMotionMaster()->MovePoint(POINT_CORPSE, x, y, z);
743 }
744 break;
745 case EVENT_OUTRO_HORDE_5: // move
746 me->GetMotionMaster()->MovePoint(POINT_FINAL, finalPos);
747 break;
748 case EVENT_OUTRO_HORDE_6: // say
750 break;
751 }
752 }
753 }
754
755 private:
758 std::list<Creature*> _guardList;
759 };
760
761 bool OnGossipHello(Player* player, Creature* creature) OVERRIDE
762 {
763 InstanceScript* instance = creature->GetInstanceScript();
764 if (instance && instance->GetBossState(DATA_DEATHBRINGER_SAURFANG) != DONE)
765 {
766 player->ADD_GOSSIP_ITEM(GOSSIP_ICON_CHAT, "We are ready to go, High Overlord. The Lich King must fall!", 631, -ACTION_START_EVENT);
767 player->SEND_GOSSIP_MENU(DEFAULT_GOSSIP_MESSAGE, creature->GetGUID());
768 }
769
770 return true;
771 }
772
773 bool OnGossipSelect(Player* player, Creature* creature, uint32 /*sender*/, uint32 action) OVERRIDE
774 {
775 player->PlayerTalkClass->ClearMenus();
776 player->CLOSE_GOSSIP_MENU();
777 if (action == -ACTION_START_EVENT)
778 creature->AI()->DoAction(ACTION_START_EVENT);
779
780 return true;
781 }
782
784 {
786 }
787};
788
790{
791 public:
792 npc_muradin_bronzebeard_icc() : CreatureScript("npc_muradin_bronzebeard_icc") { }
793
795 {
797 {
798 _instance = me->GetInstanceScript();
799 }
800
802 {
803 _events.Reset();
804 }
805
807 {
808 switch (action)
809 {
811 {
812 // Prevent crashes
813 if (_events.IsInPhase(PHASE_INTRO_A) || _events.IsInPhase(PHASE_INTRO_H))
814 return;
815
816 _events.SetPhase(PHASE_INTRO_A);
819 uint32 x = 1;
820 for (std::list<Creature*>::iterator itr = _guardList.begin(); itr != _guardList.end(); ++x, ++itr)
821 (*itr)->AI()->SetData(0, x);
822
825 _events.ScheduleEvent(EVENT_INTRO_ALLIANCE_4, 2500+17500+9500, 0, PHASE_INTRO_A);
826 _instance->HandleGameObject(_instance->GetData64(GO_SAURFANG_S_DOOR), true);
828 deathbringer->AI()->DoAction(PHASE_INTRO_A);
829 break;
830 }
832 {
833 me->RemoveAurasDueToSpell(SPELL_GRIP_OF_AGONY);
835 me->SetDisableGravity(false);
836 me->GetMotionMaster()->MoveFall();
837 for (std::list<Creature*>::iterator itr = _guardList.begin(); itr != _guardList.end(); ++itr)
838 (*itr)->AI()->DoAction(ACTION_DESPAWN);
839
840 // temp until outro fully done - to put deathbringer on respawn timer (until next reset)
842 deathbringer->DespawnOrUnsummon(5000);
843 break;
844 }
846 _events.Reset();
847 for (std::list<Creature*>::iterator itr = _guardList.begin(); itr != _guardList.end(); ++itr)
848 (*itr)->AI()->DoAction(ACTION_DESPAWN);
849 break;
850 }
851 }
852
853 void SpellHit(Unit* /*caster*/, SpellInfo const* spell) OVERRIDE
854 {
855 if (spell->Id == SPELL_GRIP_OF_AGONY)
856 {
857 me->SetDisableGravity(true);
858 me->GetMotionMaster()->MovePoint(POINT_CHOKE, chokePos[0]);
859 }
860 }
861
863 {
864 if (type == POINT_MOTION_TYPE && id == POINT_FIRST_STEP)
865 {
866 me->SetWalk(false);
868 _events.ScheduleEvent(EVENT_INTRO_ALLIANCE_5, 5000, 0, PHASE_INTRO_A);
870 deathbringer->AI()->DoAction(ACTION_CONTINUE_INTRO);
871 }
872 else if (type == WAYPOINT_MOTION_TYPE && id == POINT_EXIT)
873 {
874 std::list<Creature*> guards;
876 for (std::list<Creature*>::iterator itr = guards.begin(); itr != guards.end(); ++itr)
877 (*itr)->DespawnOrUnsummon();
878 me->DespawnOrUnsummon();
879 }
880 }
881
883 {
884 _events.Update(diff);
885 while (uint32 eventId = _events.ExecuteEvent())
886 {
887 switch (eventId)
888 {
890 me->SetWalk(true);
891 me->GetMotionMaster()->MovePoint(POINT_FIRST_STEP, firstStepPos.GetPositionX(), firstStepPos.GetPositionY(), firstStepPos.GetPositionZ());
892 break;
895 for (std::list<Creature*>::iterator itr = _guardList.begin(); itr != _guardList.end(); ++itr)
896 (*itr)->AI()->DoAction(ACTION_CHARGE);
897 me->GetMotionMaster()->MoveCharge(chargePos[0].GetPositionX(), chargePos[0].GetPositionY(), chargePos[0].GetPositionZ(), 8.5f, POINT_CHARGE);
898 break;
899 }
900 }
901 }
902
903 private:
906 std::list<Creature*> _guardList;
907 };
908
909 bool OnGossipHello(Player* player, Creature* creature) OVERRIDE
910 {
911 InstanceScript* instance = creature->GetInstanceScript();
912 if (instance && instance->GetBossState(DATA_DEATHBRINGER_SAURFANG) != DONE)
913 {
914 player->ADD_GOSSIP_ITEM(0, "Let it begin...", 631, -ACTION_START_EVENT + 1);
915 player->SEND_GOSSIP_MENU(DEFAULT_GOSSIP_MESSAGE, creature->GetGUID());
916 }
917
918 return true;
919 }
920
921 bool OnGossipSelect(Player* player, Creature* creature, uint32 /*sender*/, uint32 action) OVERRIDE
922 {
923 player->PlayerTalkClass->ClearMenus();
924 player->CLOSE_GOSSIP_MENU();
925 if (action == -ACTION_START_EVENT + 1)
926 creature->AI()->DoAction(ACTION_START_EVENT);
927
928 return true;
929 }
930
932 {
934 }
935};
936
938{
939 public:
940 npc_saurfang_event() : CreatureScript("npc_saurfang_event") { }
941
943 {
945 {
946 _index = 0;
947 }
948
949 void SetData(uint32 type, uint32 data) OVERRIDE
950 {
951 ASSERT(!type && data && data < 6);
952 _index = data;
953 }
954
955 void SpellHit(Unit* /*caster*/, SpellInfo const* spell) OVERRIDE
956 {
957 if (spell->Id == SPELL_GRIP_OF_AGONY)
958 {
959 me->SetDisableGravity(true);
960 me->GetMotionMaster()->MovePoint(POINT_CHOKE, chokePos[_index]);
961 }
962 }
963
965 {
966 if (action == ACTION_CHARGE && _index)
967 me->GetMotionMaster()->MoveCharge(chargePos[_index].GetPositionX(), chargePos[_index].GetPositionY(), chargePos[_index].GetPositionZ(), 13.0f, POINT_CHARGE);
968 else if (action == ACTION_DESPAWN)
969 me->DespawnOrUnsummon();
970 }
971
972 private:
974 };
975
977 {
979 }
980};
981
983{
984 public:
985 spell_deathbringer_blood_link() : SpellScriptLoader("spell_deathbringer_blood_link") { }
986
1011
1016};
1017
1019{
1020 public:
1021 spell_deathbringer_blood_link_aura() : SpellScriptLoader("spell_deathbringer_blood_link_aura") { }
1022
1024 {
1026
1027 bool Validate(SpellInfo const* /*spellInfo*/) OVERRIDE
1028 {
1029 if (!sSpellMgr->GetSpellInfo(SPELL_MARK_OF_THE_FALLEN_CHAMPION))
1030 return false;
1031 return true;
1032 }
1033
1034 void HandlePeriodicTick(AuraEffect const* /*aurEff*/)
1035 {
1037 if (GetUnitOwner()->getPowerType() == POWER_ENERGY && GetUnitOwner()->GetPower(POWER_ENERGY) == GetUnitOwner()->GetMaxPower(POWER_ENERGY))
1038 if (Creature* saurfang = GetUnitOwner()->ToCreature())
1039 saurfang->AI()->DoAction(ACTION_MARK_OF_THE_FALLEN_CHAMPION);
1040 }
1041
1046 };
1047
1052};
1053
1055{
1056 public:
1057 spell_deathbringer_blood_power() : SpellScriptLoader("spell_deathbringer_blood_power") { }
1058
1060 {
1062
1064 {
1065 if (Aura* aura = GetHitAura())
1066 aura->RecalculateAmountOfEffects();
1067 }
1068
1073 };
1074
1091
1096
1101};
1102
1104{
1105 public:
1106 spell_deathbringer_rune_of_blood() : SpellScriptLoader("spell_deathbringer_rune_of_blood") { }
1107
1109 {
1111
1112 bool Validate(SpellInfo const* /*spellInfo*/) OVERRIDE
1113 {
1114 if (!sSpellMgr->GetSpellInfo(SPELL_BLOOD_LINK_DUMMY))
1115 return false;
1116 return true;
1117 }
1118
1120 {
1121 PreventHitDefaultEffect(effIndex); // make this the default handler
1122 if (GetCaster()->GetPower(POWER_ENERGY) != GetCaster()->GetMaxPower(POWER_ENERGY))
1124 }
1125
1130 };
1131
1136};
1137
1139{
1140 public:
1141 spell_deathbringer_blood_nova() : SpellScriptLoader("spell_deathbringer_blood_nova") { }
1142
1144 {
1146
1147 bool Validate(SpellInfo const* /*spellInfo*/) OVERRIDE
1148 {
1149 if (!sSpellMgr->GetSpellInfo(SPELL_BLOOD_LINK_DUMMY))
1150 return false;
1151 return true;
1152 }
1153
1155 {
1156 PreventHitDefaultEffect(effIndex); // make this the default handler
1157 if (GetCaster()->GetPower(POWER_ENERGY) != GetCaster()->GetMaxPower(POWER_ENERGY))
1159 }
1160
1165 };
1166
1171};
1172
1174{
1175 public:
1176 spell_deathbringer_blood_nova_targeting() : SpellScriptLoader("spell_deathbringer_blood_nova_targeting") { }
1177
1179 {
1181
1183 {
1184 // initialize variable
1185 target = NULL;
1186 return true;
1187 }
1188
1189 void FilterTargetsInitial(std::list<WorldObject*>& targets)
1190 {
1191 if (targets.empty())
1192 return;
1193
1194 // select one random target, with preference of ranged targets
1195 uint32 targetsAtRange = 0;
1196 uint32 const minTargets = uint32(GetCaster()->GetMap()->GetSpawnMode() & 1 ? 10 : 4);
1197 targets.sort(Skyfire::ObjectDistanceOrderPred(GetCaster(), false));
1198
1199 // get target count at range
1200 for (std::list<WorldObject*>::iterator itr = targets.begin(); itr != targets.end(); ++itr, ++targetsAtRange)
1201 if ((*itr)->GetDistance(GetCaster()) < 12.0f)
1202 break;
1203
1204 // set the upper cap
1205 if (targetsAtRange < minTargets)
1206 targetsAtRange = std::min<uint32>(targets.size() - 1, minTargets);
1207
1208 if (!targetsAtRange)
1209 {
1210 targets.clear();
1211 return;
1212 }
1213
1214 std::list<WorldObject*>::const_iterator itr = targets.begin();
1215 std::advance(itr, std::rand() % (targetsAtRange));
1216 target = *itr;
1217 targets.clear();
1218 targets.push_back(target);
1219 }
1220
1221 // use the same target for first and second effect
1222 void FilterTargetsSubsequent(std::list<WorldObject*>& unitList)
1223 {
1224 unitList.clear();
1225 if (!target)
1226 return;
1227
1228 unitList.push_back(target);
1229 }
1230
1235
1242
1244 };
1245
1250};
1251
1253{
1254 public:
1255 spell_deathbringer_boiling_blood() : SpellScriptLoader("spell_deathbringer_boiling_blood") { }
1256
1258 {
1260
1262 {
1264 }
1265
1266 void FilterTargets(std::list<WorldObject*>& targets)
1267 {
1268 targets.remove(GetCaster()->GetVictim());
1269 if (targets.empty())
1270 return;
1271
1273 targets.clear();
1274 targets.push_back(target);
1275 }
1276
1281 };
1282
1287};
1288
1315
1317{
1318 public:
1319 achievement_ive_gone_and_made_a_mess() : AchievementCriteriaScript("achievement_ive_gone_and_made_a_mess") { }
1320
1321 bool OnCheck(Player* /*source*/, Unit* target) OVERRIDE
1322 {
1323 if (target)
1324 if (Creature* saurfang = target->ToCreature())
1325 if (saurfang->AI()->GetData(DATA_MADE_A_MESS))
1326 return true;
1327
1328 return false;
1329 }
1330};
1331
Actions
std::int32_t int32
Definition Define.h:73
std::uint32_t uint32
Definition Define.h:77
#define OVERRIDE
Definition Define.h:60
#define ASSERT
Definition Errors.h:29
#define DEFAULT_GOSSIP_MESSAGE
Definition GossipDef.h:16
@ GOSSIP_ICON_CHAT
Definition GossipDef.h:46
@ IN_PROGRESS
@ FAIL
@ DONE
@ WAYPOINT_MOTION_TYPE
@ POINT_MOTION_TYPE
@ TYPEID_PLAYER
Definition Object.h:55
@ TYPEID_UNIT
Definition Object.h:54
void GetCreatureListWithEntryInGrid(std::list< Creature * > &list, WorldObject *source, uint32 entry, float maxSearchRange)
SpellEffIndex
@ EFFECT_1
@ EFFECT_0
@ EMOTE_STATE_DROWNED
@ POWER_ENERGY
@ SPELL_EFFECT_DUMMY
@ SPELL_EFFECT_SCRIPT_EFFECT
@ SPELL_EFFECT_FORCE_CAST
@ TARGET_UNIT_SRC_AREA_ENEMY
@ GO_FLAG_IN_USE
@ SPELL_AURA_MOD_DAMAGE_PERCENT_DONE
@ SPELL_AURA_MOD_SCALE
@ SPELL_AURA_PERIODIC_DUMMY
#define sSpellMgr
Definition SpellMgr.h:744
#define SpellEffectFn(F, I, N)
#define AuraEffectCalcAmountFn(F, I, N)
#define SpellObjectAreaTargetSelectFn(F, I, N)
#define AuraEffectPeriodicFn(F, I, N)
#define SpellHitFn(F)
@ UNIT_NPC_FLAG_GOSSIP
Definition Unit.h:687
@ SPELLVALUE_BASE_POINT0
Definition Unit.h:114
@ TRIGGERED_FULL_MASK
Will ignore most target checks (mostly DBC target checks).
Definition Unit.h:435
@ UNIT_STATE_CASTING
Definition Unit.h:527
@ REACT_DEFENSIVE
Definition Unit.h:1157
@ UNIT_FLAG_NOT_SELECTABLE
Definition Unit.h:650
@ UNIT_FLAG_IMMUNE_TO_PC
Definition Unit.h:633
@ SELECT_TARGET_RANDOM
Definition UnitAI.h:23
@ UNIT_FIELD_NPC_FLAGS
@ UNIT_FIELD_FLAGS
@ UNIT_FIELD_NPC_EMOTESTATE
@ GAMEOBJECT_FIELD_FLAGS
@ SAY_BERSERK
@ PHASE_COMBAT
#define SAY_DEATH
#define SAY_AGGRO
#define SAY_KILL
@ ACTION_MARK_OF_THE_FALLEN_CHAMPION
Position const deathbringerPos
Position const chargePos[6]
@ SPELL_MARK_OF_THE_FALLEN_CHAMPION
@ SPELL_SUMMON_BLOOD_BEAST_25_MAN
@ SPELL_REMOVE_MARKS_OF_THE_FALLEN_CHAMPION
@ SPELL_MARK_OF_THE_FALLEN_CHAMPION_S
Position const finalPos
void AddSC_boss_deathbringer_saurfang()
Position const chokePos[6]
@ SAY_MARK_OF_THE_FALLEN_CHAMPION
Position const firstStepPos
@ SPELL_FRENZY
#define SPELL_BERSERK
@ EVENT_BERSERK
MovePoints
AchievementCriteriaScript(const char *name)
void PreventDefaultAction()
HookList< EffectPeriodicHandler > OnEffectPeriodic
HookList< EffectCalcAmountHandler > DoEffectCalcAmount
Unit * GetUnitOwner() const
InstanceScript *const instance
void _JustReachedHome()
SummonList summons
EventMap events
BossAI(Creature *creature, uint32 bossId)
void DoZoneInCombat(Creature *creature=NULL, float maxRangeToNearestTarget=50.0f)
bool _EnterEvadeMode()
void Talk(uint8 id, WorldObject const *whisperTarget=NULL)
bool UpdateVictim()
virtual void EnterEvadeMode()
CreatureScript(const char *name)
static GameObject * GetGameObject(WorldObject &object, uint64 guid)
EncounterState GetBossState(uint32 id) const
static Creature * GetCreature(WorldObject const &u, uint64 guid)
TypeID GetTypeId() const
Definition Object.h:131
Creature * ToCreature()
Definition Object.h:207
Aura * GetHitAura()
HookList< HitHandler > AfterHit
void PreventHitDefaultEffect(SpellEffIndex effIndex)
HookList< EffectHandler > OnEffectHitTarget
Unit * GetHitUnit()
int32 GetEffectValue()
Unit * GetCaster()
HookList< ObjectAreaTargetSelectHandler > OnObjectAreaTargetSelect
SpellScriptLoader(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
void DoCastAOE(uint32 spellId, bool triggered=false)
Definition UnitAI.cpp:176
Definition Unit.h:1367
void CastSpell(SpellCastTargets const &targets, SpellInfo const *spellInfo, CustomSpellValues const *value, TriggerCastFlags triggerFlags=TRIGGERED_NONE, Item *castItem=NULL, AuraEffect const *triggeredByAura=NULL, uint64 originalCaster=0)
void RemoveAurasDueToSpell(uint32 spellId, uint64 casterGUID=0, uint32 reqEffMask=0, AuraRemoveMode removeMode=AURA_REMOVE_BY_DEFAULT)
void CastCustomSpell(Unit *victim, uint32 spellId, int32 const *bp0, int32 const *bp1, int32 const *bp2, bool triggered, Item *castItem=NULL, AuraEffect const *triggeredByAura=NULL, uint64 originalCaster=0)
Vehicle * GetVehicleKit() const
Definition Unit.h:2739
bool OnCheck(Player *, Unit *target) OVERRIDE
CreatureAI * GetAI(Creature *creature) const OVERRIDE
bool OnGossipSelect(Player *player, Creature *creature, uint32, uint32 action) OVERRIDE
CreatureAI * GetAI(Creature *creature) const OVERRIDE
bool OnGossipHello(Player *player, Creature *creature) OVERRIDE
CreatureAI * GetAI(Creature *creature) const OVERRIDE
bool OnGossipHello(Player *player, Creature *creature) OVERRIDE
bool OnGossipSelect(Player *player, Creature *creature, uint32, uint32 action) OVERRIDE
CreatureAI * GetAI(Creature *creature) const OVERRIDE
SpellScript * GetSpellScript() const OVERRIDE
void RecalculateHook(AuraEffect const *, int32 &amount, bool &canBeRecalculated)
AuraScript * GetAuraScript() const OVERRIDE
SpellScript * GetSpellScript() const OVERRIDE
SpellScript * GetSpellScript() const OVERRIDE
SpellScript * GetSpellScript() const OVERRIDE
SpellScript * GetSpellScript() const OVERRIDE
@ NPC_ALLIANCE_COMMANDER
@ NPC_KOR_KRON_GENERAL
@ NPC_SE_SKYBREAKER_MARINE
@ NPC_SE_KOR_KRON_REAVER
CreatureAI * GetIcecrownCitadelAI(Creature *creature)
@ LIGHT_S_HAMMER_TELEPORT
@ GO_SAURFANG_S_DOOR
@ GO_SCOURGE_TRANSPORTER_SAURFANG
@ DATA_DEATHBRINGER_SAURFANG
@ DATA_SAURFANG_EVENT_NPC
C::value_type const & SelectRandomContainerElement(C const &container)
Definition Containers.h:48
bool IsHeroic() const
Creature * me
bool HealthBelowPct(uint32 pct) const
const T & RAID_MODE(const T &normal10, const T &normal25) const
ScriptedAI(Creature *creature)
bool Is25ManRaid() const
void AttackStart(Unit *) OVERRIDE
void SpellHitTarget(Unit *target, SpellInfo const *spell) OVERRIDE
void UpdateAI(uint32 diff) OVERRIDE
== Triggered Actions Requested ==================
void UpdateAI(uint32 diff) OVERRIDE
== Triggered Actions Requested ==================
void UpdateAI(uint32 diff) OVERRIDE
== Triggered Actions Requested ==================
void SetData(uint32 type, uint32 data) OVERRIDE
void SpellHit(Unit *, SpellInfo const *spell) OVERRIDE