#include "../../sc_defines.h" #include "../../../../../shared/WorldPacket.h" #include "../../../../../game/TargetedMovementGenerator.h" /* #include "../../../../../game/Player.h" #include "../../../../../game/GossipDef.h" */ // 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. // Air 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!" #define SAY_DEATH "!!DEATH!![debag]" #define SOUND_DEATH 9454 #define SAY_PRE_AGGRO "!!PRE_AGGRO!![debag]" #define SOUND_PRE_AGGRO 9455 #define SAY_AGGRO "!!AGGRO!![debag]" #define SOUND_AGGRO 9456 #define SAY_ATTACK "!!ATTACK!![debag]" #define SOUND_ATTACK 9451 #define SAY_WOUND "!!WOUND!![debag]" #define SOUND_WOUND 9452 #define SAY_WOUND_CRIT "!!WOUND_CRIT!![debag]" #define SOUND_WOUND_CRIT 9453 #define SAY_LOOP "!!LOOP!![debag]" #define SOUND_LOOP 9457 #define SAY_PHASE1 "PHASE 1" #define SAY_PHASE2 "PHASE 2" #define SAY_PHASE3 "PHASE 3" #define SAY_PHASE4 "PHASE 4" #define SAY_PHASE5 "PHASE 5" #define SAY_PHASE6 "PHASE 6" #define SAY_PHASE7 "PHASE 7" // summon (Air 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 #define AIR_MOVE_X -11174 #define AIR_MOVE_Y -1964 #define AIR_MOVE_Z 101 #define AIR_MOVE_O 0.5 #define GROUND_MOVE_X -11159 #define GROUND_MOVE_Y -1949 #define GROUND_MOVE_Z 93 #define GROUND_MOVE_O 0.5 struct Locations { float x, y, z; }; // áóäóò ðàíäîñíûå òî÷êè =) ÷óòîê îñòàëîñü =) static Locations Flight[]= { {-11174, -1964, 101}, {-11174, -1964, 101}, {-11174, -1964, 101}, {-11174, -1964, 101}, {-11174, -1964, 101} }; 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 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 = 1000; // Fly State Fly_Timer = 45000+rand()%15000; Rain_Timer = 1000; Smoking_Timer = 2000; Fireball_Timer = 2500; 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; DoYell(SAY_AGGRO, LANG_UNIVERSAL, NULL); DoPlaySoundToSet(m_creature, SOUND_AGGRO); InCombat = true; } DoYell(SAY_ATTACK, LANG_UNIVERSAL, NULL); DoPlaySoundToSet(m_creature, SOUND_ATTACK); } } } void UpdateAI(const uint32 diff) { if (!m_creature->SelectHostilTarget() || !m_creature->getVictim()) return; // Ground State if ( Phase == 1 || Phase == 3 || Phase == 5 || Phase == 7 ) { // Bellowing Roar -fear Fly_Timer = 60000; 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 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) { m_creature->InterruptSpell(CURRENT_GENERIC_SPELL); uint32 random = rand()%5; Move(Flight[random].x, Flight[random].y, Flight[random].z, 3000, m_creature); if(Fly_Timer < diff) { Phase++; }else Fly_Timer -= diff; 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); Rain_Timer = 3500; }else Rain_Timer -= diff; if(Summon_Timer < diff) { Unit* target = NULL; target = SelectUnit(SELECT_TARGET_RANDOM,0); // summon 3 mobs and attack random player switch (rand()%2) { case 0: Summoned = m_creature->SummonCreature(SUMMON,ADD_0X,ADD_0Y,ADD_0Z,0,TEMPSUMMON_TIMED_OR_CORPSE_DESPAWN,900000); ((CreatureAI*)Summoned->AI())->AttackStart(target); Summoned = m_creature->SummonCreature(SUMMON,ADD_0X,ADD_0Y,ADD_0Z,0,TEMPSUMMON_TIMED_OR_CORPSE_DESPAWN,900000); ((CreatureAI*)Summoned->AI())->AttackStart(target); Summoned = m_creature->SummonCreature(SUMMON,ADD_0X,ADD_0Y,ADD_0Z,0,TEMPSUMMON_TIMED_OR_CORPSE_DESPAWN,900000); ((CreatureAI*)Summoned->AI())->AttackStart(target); break; case 1: Summoned = m_creature->SummonCreature(SUMMON,ADD_1X,ADD_1Y,ADD_1Z,0,TEMPSUMMON_TIMED_OR_CORPSE_DESPAWN,900000); ((CreatureAI*)Summoned->AI())->AttackStart(target); Summoned = m_creature->SummonCreature(SUMMON,ADD_1X,ADD_1Y,ADD_1Z,0,TEMPSUMMON_TIMED_OR_CORPSE_DESPAWN,900000); ((CreatureAI*)Summoned->AI())->AttackStart(target); Summoned = m_creature->SummonCreature(SUMMON,ADD_1X,ADD_1Y,ADD_1Z,0,TEMPSUMMON_TIMED_OR_CORPSE_DESPAWN,900000); ((CreatureAI*)Summoned->AI())->AttackStart(target); break; case 2: Summoned = m_creature->SummonCreature(SUMMON,ADD_2X,ADD_2Y,ADD_2Z,0,TEMPSUMMON_TIMED_OR_CORPSE_DESPAWN,900000); ((CreatureAI*)Summoned->AI())->AttackStart(target); Summoned = m_creature->SummonCreature(SUMMON,ADD_2X,ADD_2Y,ADD_2Z,0,TEMPSUMMON_TIMED_OR_CORPSE_DESPAWN,900000); ((CreatureAI*)Summoned->AI())->AttackStart(target); Summoned = m_creature->SummonCreature(SUMMON,ADD_2X,ADD_2Y,ADD_2Z,0,TEMPSUMMON_TIMED_OR_CORPSE_DESPAWN,900000); ((CreatureAI*)Summoned->AI())->AttackStart(target); break; } Summon_Timer = 15000; }else Summon_Timer -= diff; if (Smoking_Timer < diff) { 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 = (30+rand()%10)*1000; }else Smoking_Timer -= diff; if (Fireball_Timer < diff) { DoCast(m_creature->getVictim(),SPELL_FIREBALL_BARRAGE); Fireball_Timer = 4000+rand()%1000; }else Fireball_Timer -= diff; } if( Phase == 1 && (m_creature->GetHealth()*100 / m_creature->GetMaxHealth() < 75)) Phase = 2; if( Phase == 3 && (m_creature->GetHealth()*100 / m_creature->GetMaxHealth() < 50) ) Phase = 4; if( Phase == 5 && (m_creature->GetHealth()*100 / m_creature->GetMaxHealth() < 25) ) Phase = 6; /* if ( Phase == 5 && (m_creature->GetHealth()*100) / m_creature->GetMaxHealth() < 25 ) { m_creature->InterruptSpell(CURRENT_GENERIC_SPELL); SpecialMove(AIR_MOVE_X,AIR_MOVE_Y,AIR_MOVE_Z,7500); m_creature->Relocate(AIR_MOVE_X,AIR_MOVE_Y,AIR_MOVE_Z,AIR_MOVE_O); AirState_Timer = 60000; Phase == 6; } if ( (m_creature->GetHealth()*100) / m_creature->GetMaxHealth() == 75 || (m_creature->GetHealth()*100) / m_creature->GetMaxHealth() == 50 || (m_creature->GetHealth()*100) / m_creature->GetMaxHealth() == 25 ) Phase = 2; */ } 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; }