#include "../../sc_defines.h" #include "../../../../../shared/WorldPacket.h" #include "../../../../../game/TargetedMovementGenerator.h" /* for SD2 */ // Ground Abilities #define SPELL_BELLOWING_ROAR 36922 // Bellowing Roar1.5 sec cast 8 sec cooldown - Fleeing in fear. 4 seconds remaining #define SPELL_BONE_SHARDS 17014 //#define SPELL_CLEAVE ??????? #define SPELL_CHARRED_EARTH 30129 // Chars the ground, setting it flame, 2188 to 2812 Fire damage every 3 sec #define SPELL_DISTRACTING_ASH 30130 // Reduces the chance to hit with spells and abilities by 30%. #define SPELL_SMOLDERING_BREATH 39385 // Inflicts 3700 to 4300 Fire damage to enemies in a cone in front of the caster and ~1700 tvery 3 sec (5 ticks) //#define SPELL_TAIL_SWEEP 25653 // Inflicts 450 damage on enemies in a cone behind the caster, knocking them back. // Fly Abilities #define SPELL_RAIN_OF_BONES 37098 // Bombards the target and nearby allies with bone fragments, summoning 3 skeletons in the process. #define SPELL_SMOKING_BLAST 37057 // Deals 1850 to 2150 physical damage to the target and additional fire damage over time. #define SPELL_RIGHTEOUS_FURY 25780 #define SPELL_FIREBALL_BARRAGE 30282 // Throws fireballs at any enemies farther than 40 yards away. #define SAY_DIED "Ihr seid meiner halt unwuerdig!" // used(145) //#define SOUND_DIED ??? #define SAY_DEATH "!!DEATH!![debag]" //used (150-151) #define SOUND_DEATH 9454 #define SAY_PRE_AGGRO "!!PRE_AGGRO!![debag]" #define SOUND_PRE_AGGRO 9455 #define SAY_AGGRO "!!AGGRO!![debag]" // no used #define SOUND_AGGRO 9456 // no used #define SAY_ATTACK "!!ATTACK!![debag]" // no used #define SOUND_ATTACK 9451 // no used #define SAY_WOUND "!!WOUND!![debag]" // no used #define SOUND_WOUND 9452 // no used #define SAY_WOUND_CRIT "!!WOUND_CRIT!![debag]" // no used #define SOUND_WOUND_CRIT 9453 // no used #define SAY_LOOP "!!LOOP!![debag]" // no used #define SOUND_LOOP 9457 // no used // summon (Fly Phase) #define SUMMON 17261 #define ADD_0X -11173.214 #define ADD_0Y -1929.956 #define ADD_0Z 91.473 #define ADD_1X -11168.723 #define ADD_1Y -1927.489 #define ADD_1Z 91.473 #define ADD_2X -11163.718 #define ADD_2Y -1924.036 #define ADD_2Z 91.473 // Move boss - new struct Locations { float x, y, z; }; // random point static Locations Flight[]= { {-11132, -1889, 104}, }; static Locations Summons[]= { {-11086, -1897, 92}, {-11088, -1901, 92}, {-11093, -1907, 92}, {-11107, -1892, 92}, {-11108, -1885, 92}, {-11103, -1883, 92} }; struct MANGOS_DLL_DECL boss_nightbaneAI : public ScriptedAI { boss_nightbaneAI(Creature *c) : ScriptedAI(c) {Reset();} // Ground State uint32 Bellowing_Timer; uint32 Charred_Timer; uint32 Distracting_Timer; uint32 Smoldering_Timer; uint32 Boneshards_Timer; //uint32 Tail_Timer; // Air State uint32 Global_Timer; uint32 Fly_Timer; uint32 Rain_Timer; uint32 Smoking_Timer; uint32 Fireball_Timer; uint32 Phase; Creature* Summoned; uint32 Summon_Timer; bool InCombat; void Reset() { // Ground State Bellowing_Timer = 50000; Charred_Timer = 90000; Distracting_Timer = 70000; Smoldering_Timer = 70000; Boneshards_Timer = (10+rand()%5)*1000; // Fly State Fly_Timer = 45000+rand()%15000; Rain_Timer = 2000; Smoking_Timer = 5000; Fireball_Timer = 8500; Phase = 1; InCombat = false; } void KilledUnit(Unit* Victim) { if(rand()%2) return; DoYell(SAY_DIED,LANG_UNIVERSAL,Victim); } void JustDied(Unit* Killer) { DoYell(SAY_DEATH,LANG_UNIVERSAL,NULL); DoPlaySoundToSet(m_creature, SOUND_DEATH); } void AttackStart(Unit *who) { if (!who) return; if (who->isTargetableForAttack() && who!= m_creature) { if (!InCombat) { DoYell(SAY_AGGRO, LANG_UNIVERSAL, NULL); DoPlaySoundToSet(m_creature, SOUND_AGGRO); InCombat = true; } DoStartMeleeAttack(who); } } void MoveInLineOfSight(Unit *who) { if (!who || m_creature->getVictim()) return; if (who->isTargetableForAttack() && who->isInAccessablePlaceFor(m_creature) && m_creature->IsHostileTo(who)) { float attackRadius = m_creature->GetAttackDistance(who); if (m_creature->IsWithinDistInMap(who, attackRadius) && m_creature->GetDistanceZ(who) <= CREATURE_Z_ATTACK_RANGE && m_creature->IsWithinLOSInMap(who)) { if(who->HasStealthAura()) who->RemoveSpellsCausingAura(SPELL_AURA_MOD_STEALTH); DoStartMeleeAttack(who); if (!InCombat) { InCombat = true; } } } } void UpdateAI(const uint32 diff) { if (!m_creature->SelectHostilTarget() || !m_creature->getVictim()) return; // Ground State if ( Phase == 1 || Phase == 3 || Phase == 5 || Phase == 7 ) { Fly_Timer = 45000+rand()%15000; // Bellowing Roar -fear if (Bellowing_Timer < diff) { DoCast(m_creature,SPELL_BELLOWING_ROAR); Bellowing_Timer = (30+rand()%50)*1000; }else Bellowing_Timer -= diff; // Distracting Ash - 30% mele/spell attack power (30 sec) if (Distracting_Timer < diff) { DoCast(m_creature->getVictim(),SPELL_DISTRACTING_ASH); Distracting_Timer = (30+rand()%60)*1000; }else Distracting_Timer -= diff; // Charred Earth ~2.8 fire damage every 3 sec (10 ticks*2.8k dmg) if (Charred_Timer < diff) { Unit* target = NULL; target = SelectUnit(SELECT_TARGET_RANDOM,0); if (target) DoCast(target,SPELL_CHARRED_EARTH); else DoCast(m_creature->getVictim(),SPELL_CHARRED_EARTH); Charred_Timer = (30+rand()%25)*1000; }else Charred_Timer -= diff; // Bone Shards -12-14 dmg per second all player with mele radius if (Boneshards_Timer < diff) { DoCast(m_creature,SPELL_BONE_SHARDS); Boneshards_Timer = (10+rand()%5)*1000; }else Boneshards_Timer -= diff; // Smoldering Breath(3k + 1.2k fire dmg per tick, 15 sec) if(Smoldering_Timer getVictim(),SPELL_SMOLDERING_BREATH); Smoldering_Timer = (30+rand()%15)*1000; }else Smoldering_Timer -= diff; DoMeleeAttackIfReady(); } // Fly State if (Phase == 2 || Phase == 4 || Phase == 6) { // Fly State timer uint32 random = rand()%1; m_creature->InterruptSpell(CURRENT_GENERIC_SPELL); Move(Flight[random].x, Flight[random].y, Flight[random].z, 3000, m_creature); while( Fly_Timer > diff ) { // Rain of Bones - Bombards the target and nearby allies with bone fragments, summoning 3 skeletons in the process. if (Rain_Timer < diff) { Unit* target = NULL; target = SelectUnit(SELECT_TARGET_RANDOM,0); if (target) DoCast(target,SPELL_RAIN_OF_BONES); else DoCast(m_creature->getVictim(),SPELL_RAIN_OF_BONES); // summon 3 mobs and attack random player random = rand()%6; Summoned = m_creature->SummonCreature(SUMMON,Summons[random].x, Summons[random].y, Summons[random].z,0,TEMPSUMMON_TIMED_OR_CORPSE_DESPAWN,900000); ((CreatureAI*)Summoned->AI())->AttackStart(target); /* random = rand()%3; Summoned = m_creature->SummonCreature(SUMMON,Summons[random].x, Summons[random].y, Summons[random].z,0,TEMPSUMMON_TIMED_OR_CORPSE_DESPAWN,900000); ((CreatureAI*)Summoned->AI())->AttackStart(target); random = rand()%3; Summoned = m_creature->SummonCreature(SUMMON,Summons[random].x, Summons[random].y, Summons[random].z,0,TEMPSUMMON_TIMED_OR_CORPSE_DESPAWN,900000); ((CreatureAI*)Summoned->AI())->AttackStart(target); */ Rain_Timer = 3500; }else Rain_Timer -= diff; // Smoking Blast - Deals 1850 to 2150 phys dmg + 500 dmg per tick if (Smoking_Timer < diff) { if( Rain_Timer > 1500 ) { Rain_Timer = 60000; Unit* target = NULL; target = SelectUnit(SELECT_TARGET_RANDOM,0); if (target) DoCast(target,SPELL_SMOKING_BLAST); else DoCast(m_creature->getVictim(),SPELL_SMOKING_BLAST); } Smoking_Timer = 3000; }else Smoking_Timer -= diff; // Fireball Barrage - fire balls 2550-3450 dmg all in radius 40 yd if (Fireball_Timer < diff) { Rain_Timer += 60000; DoCast(m_creature->getVictim(),SPELL_FIREBALL_BARRAGE); Fireball_Timer = 1000+rand()%500; }else Fireball_Timer -= diff; //if () - SPELL_RIGHTEOUS_FURY Fly_Timer -= diff; } Phase++; } if( Phase == 1 && (m_creature->GetHealth()*100 / m_creature->GetMaxHealth() < 75)) { Fly_Timer = 45000+rand()%15000; Phase = 2; } if( Phase == 3 && (m_creature->GetHealth()*100 / m_creature->GetMaxHealth() < 50) ) { Fly_Timer = 45000+rand()%15000; Phase = 4; } if( Phase == 5 && (m_creature->GetHealth()*100 / m_creature->GetMaxHealth() < 25) ) { Fly_Timer = 45000+rand()%15000; Phase = 6; } } void Move(float X, float Y, float Z, uint32 Time, Unit* c, uint32 flags = 0x0200) { WorldPacket data( SMSG_MONSTER_MOVE, (41+c->GetPackGUID().size()) ); data.append(c->GetPackGUID()); data << c->GetPositionX() << c->GetPositionY() << c->GetPositionZ(); // unknown field - unrelated to orientation // seems to increment about 1000 for every 1.7 seconds // for now, we'll just use mstime data << getMSTime(); data << uint8(0); // walkback when walking from A to B data << uint32(flags); // flags data << Time; // Time in between points data << uint32(1); // 1 single waypoint data << X << Y << Z; // the single waypoint Point B c->SendMessageToSet( &data, true ); c->Relocate(X, Y, Z); } }; CreatureAI* GetAI_boss_nightbane(Creature *_Creature) { return new boss_nightbaneAI (_Creature); } void AddSC_boss_nightbane() { Script *newscript; newscript = new Script; newscript->Name="boss_nightbane"; newscript->GetAI = GetAI_boss_nightbane; m_scripts[nrscripts++] = newscript; }