aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--sql/updates/world/2015_11_06_29_world_2015_11_02_00.sql26
-rw-r--r--src/server/scripts/Northrend/Naxxramas/boss_anubrekhan.cpp209
-rw-r--r--src/server/scripts/Northrend/Naxxramas/instance_naxxramas.cpp16
-rw-r--r--src/server/scripts/Northrend/Naxxramas/naxxramas.h3
4 files changed, 185 insertions, 69 deletions
diff --git a/sql/updates/world/2015_11_06_29_world_2015_11_02_00.sql b/sql/updates/world/2015_11_06_29_world_2015_11_02_00.sql
new file mode 100644
index 00000000000..19379ad7d71
--- /dev/null
+++ b/sql/updates/world/2015_11_06_29_world_2015_11_02_00.sql
@@ -0,0 +1,26 @@
+-- Anub'Rekhan cleanup
+-- areatrigger for greeting upon entering room
+DELETE FROM `areatrigger_scripts` WHERE `entry`=4119;
+INSERT INTO `areatrigger_scripts` (`entry`,`ScriptName`) VALUES
+(4119,"at_anubrekhan_entrance");
+
+-- make crypt guards aggro anub when pulled
+DELETE FROM `smart_scripts` WHERE `entryorguid`=16573 AND `source_type`=0 AND `id` IN (6,7);
+INSERT INTO `smart_scripts` (`entryorguid`,`source_type`,`id`,`link`,`event_type`,`event_chance`,`event_flags`,`action_type`,`action_param1`,`action_param2`,`action_param3`,`target_type`,`comment`) VALUES
+(16573,0, 6, 0, 4,100,0,39, 25, 0, 0, 0, "Crypt Guard - On Aggro - Call For Help (25yd)"),
+(16573,0, 7, 5,61,100,0,1, 0, 0, 0, 0, "Crypt Guard - On Cast Frenzy - Say EMOTE_FRENZY");
+UPDATE `smart_scripts` SET `link`=7 WHERE `entryorguid`=16573 AND `source_type`=0 AND `id`=5;
+
+DELETE FROM `creature_text` WHERE `entry`=16573;
+DELETE FROM `creature_text` WHERE `entry`=15956 AND `groupid`=3;
+INSERT INTO `creature_text` (`entry`,`groupid`,`id`,`text`,`type`,`probability`,`BroadcastTextId`,`TextRange`,`comment`) VALUES
+(16573,0,0,"%s goes into a frenzy!",16,100,1191,3,"Crypt Guard EMOTE_FRENZY"),
+(16573,1,0,"A Crypt Guard joins the fight!",41,100,29887,3,"Crypt Guard EMOTE_SPAWN"),
+(16573,2,0,"Corpse Scarabs appear from a Crypt Guard's corpse!",41,100,32796,3,"Crypt Guard EMOTE_SCARAB"),
+(15956,3,0,"Anub'Rekhan begins to unleash an insect swarm!",41,100,13443,3,"Anub'Rekhan EMOTE_LOCUST");
+
+DELETE FROM `creature_summon_groups` WHERE `summonerId`=15956;
+INSERT INTO `creature_summon_groups` (`summonerId`,`summonerType`,`groupId`,`entry`,`position_x`,`position_y`,`position_z`,`orientation`,`summonType`) VALUES
+(15956,0,1,16573, 3300.503, -3503.574, 287.1606, 2.321288, 8),
+(15956,0,1,16573, 3299.283, -3450.938, 287.1606, 3.839724, 8),
+(15956,0,2,16573, 3334.41 , -3476.84 , 287.1553, 0, 8);
diff --git a/src/server/scripts/Northrend/Naxxramas/boss_anubrekhan.cpp b/src/server/scripts/Northrend/Naxxramas/boss_anubrekhan.cpp
index 28d181a990e..471a7adc9d6 100644
--- a/src/server/scripts/Northrend/Naxxramas/boss_anubrekhan.cpp
+++ b/src/server/scripts/Northrend/Naxxramas/boss_anubrekhan.cpp
@@ -17,39 +17,61 @@
#include "ScriptMgr.h"
#include "ScriptedCreature.h"
+#include "Player.h"
#include "naxxramas.h"
-enum Says
+enum AnubSays
{
SAY_AGGRO = 0,
SAY_GREET = 1,
- SAY_SLAY = 2
+ SAY_SLAY = 2,
+
+ EMOTE_LOCUST = 3
};
-Position const GuardSummonPos = {3333.72f, -3476.30f, 287.1f, 6.2801f};
+enum GuardSays
+{
+ EMOTE_FRENZY = 0,
+ EMOTE_SPAWN = 1,
+ EMOTE_SCARAB = 2
+};
enum Events
{
- EVENT_IMPALE = 1,
- EVENT_LOCUST,
- EVENT_SPAWN_GUARDIAN_NORMAL,
- EVENT_BERSERK
+ EVENT_IMPALE = 1, // Cast Impale on a random target
+ EVENT_LOCUST, // Begin channeling Locust Swarm
+ EVENT_LOCUST_ENDS, // Locust swarm dissipates
+ EVENT_SPAWN_GUARD, // 10-man only - crypt guard has delayed spawn; also used for the locust swarm crypt guard in both modes
+ EVENT_SCARABS, // spawn corpse scarabs
+ EVENT_BERSERK // Berserk
};
enum Spells
{
- SPELL_IMPALE = 28783,
- SPELL_LOCUST_SWARM = 28785,
+ SPELL_IMPALE = 28783, // 25-man: 56090
+ SPELL_LOCUST_SWARM = 28785, // 25-man: 54021
SPELL_SUMMON_CORPSE_SCARABS_PLR = 29105, // This spawns 5 corpse scarabs on top of player
SPELL_SUMMON_CORPSE_SCARABS_MOB = 28864, // This spawns 10 corpse scarabs on top of dead guards
SPELL_BERSERK = 27680
};
+enum SpawnGroups
+{
+ GROUP_INITIAL_25M = 1,
+ GROUP_SINGLE_SPAWN = 2
+};
+
enum Misc
{
ACHIEV_TIMED_START_EVENT = 9891
};
+enum Phases
+{
+ PHASE_NORMAL = 1,
+ PHASE_SWARM
+};
+
class boss_anubrekhan : public CreatureScript
{
public:
@@ -62,46 +84,64 @@ public:
struct boss_anubrekhanAI : public BossAI
{
- boss_anubrekhanAI(Creature* creature) : BossAI(creature, BOSS_ANUBREKHAN)
+ boss_anubrekhanAI(Creature* creature) : BossAI(creature, BOSS_ANUBREKHAN) { }
+
+ void SummonGuards()
{
- Initialize();
+ if (Is25ManRaid())
+ me->SummonCreatureGroup(GROUP_INITIAL_25M);
}
- void Initialize()
+ void InitializeAI() override
{
- hasTaunted = false;
+ if (!me->isDead())
+ {
+ Reset();
+ SummonGuards();
+ }
}
- bool hasTaunted;
-
void Reset() override
{
_Reset();
+ guardCorpses.clear();
+ }
- Initialize();
+ void JustReachedHome() override
+ {
+ _JustReachedHome();
+ SummonGuards();
+ }
- if (GetDifficulty() == DIFFICULTY_25_N)
- {
- Position pos;
+ void JustSummoned(Creature* summon) override
+ {
+ BossAI::JustSummoned(summon);
+
+ if (me->IsInCombat())
+ if (summon->GetEntry() == NPC_CRYPT_GUARD)
+ summon->AI()->Talk(EMOTE_SPAWN, me);
+ }
- // respawn guard using home position,
- // otherwise, after a wipe, they respawn where boss was at wipe moment.
- pos = me->GetHomePosition();
- pos.m_positionY -= 10.0f;
- me->SummonCreature(NPC_CRYPT_GUARD, pos, TEMPSUMMON_CORPSE_DESPAWN);
+ void SummonedCreatureDies(Creature* summon, Unit* killer) override
+ {
+ BossAI::SummonedCreatureDies(summon, killer);
- pos = me->GetHomePosition();
- pos.m_positionY += 10.0f;
- me->SummonCreature(NPC_CRYPT_GUARD, pos, TEMPSUMMON_CORPSE_DESPAWN);
- }
+ if (summon->GetEntry() == NPC_CRYPT_GUARD)
+ guardCorpses.insert(summon->GetGUID());
+ }
+
+ void SummonedCreatureDespawn(Creature* summon) override
+ {
+ BossAI::SummonedCreatureDespawn(summon);
+
+ if (summon->GetEntry() == NPC_CRYPT_GUARD)
+ guardCorpses.erase(summon->GetGUID());
}
void KilledUnit(Unit* victim) override
{
- /// Force the player to spawn corpse scarabs via spell, @todo Check percent chance for scarabs, 20% at the moment
- if (!(rand32() % 5))
- if (victim->GetTypeId() == TYPEID_PLAYER)
- victim->CastSpell(victim, SPELL_SUMMON_CORPSE_SCARABS_PLR, true, NULL, NULL, me->GetGUID());
+ if (victim->GetTypeId() == TYPEID_PLAYER)
+ victim->CastSpell(victim, SPELL_SUMMON_CORPSE_SCARABS_PLR, true, nullptr, nullptr, me->GetGUID());
Talk(SAY_SLAY);
}
@@ -113,37 +153,22 @@ public:
// start achievement timer (kill Maexna within 20 min)
instance->DoStartTimedAchievement(ACHIEVEMENT_TIMED_TYPE_EVENT, ACHIEV_TIMED_START_EVENT);
}
+
void EnterCombat(Unit* /*who*/) override
{
_EnterCombat();
Talk(SAY_AGGRO);
- events.ScheduleEvent(EVENT_IMPALE, urand(10000, 20000));
- events.ScheduleEvent(EVENT_LOCUST, 90000);
- events.ScheduleEvent(EVENT_BERSERK, 600000);
-
- if (GetDifficulty() == DIFFICULTY_10_N)
- events.ScheduleEvent(EVENT_SPAWN_GUARDIAN_NORMAL, urand(15000, 20000));
- }
- void MoveInLineOfSight(Unit* who) override
- {
- if (!hasTaunted && me->IsWithinDistInMap(who, 60.0f) && who->GetTypeId() == TYPEID_PLAYER)
- {
- Talk(SAY_GREET);
- hasTaunted = true;
- }
- ScriptedAI::MoveInLineOfSight(who);
- }
-
- void SummonedCreatureDespawn(Creature* summon) override
- {
- BossAI::SummonedCreatureDespawn(summon);
-
- // check if it is an actual killed guard
- if (!me->IsAlive() || summon->IsAlive() || summon->GetEntry() != NPC_CRYPT_GUARD)
- return;
+ summons.DoZoneInCombat();
+
+ events.SetPhase(PHASE_NORMAL);
+ events.ScheduleEvent(EVENT_IMPALE, urand(10 * IN_MILLISECONDS, 20 * IN_MILLISECONDS), 0, PHASE_NORMAL);
+ events.ScheduleEvent(EVENT_SCARABS, urand(20 * IN_MILLISECONDS, 30 * IN_MILLISECONDS), 0, PHASE_NORMAL);
+ events.ScheduleEvent(EVENT_LOCUST, urand(80,120) * IN_MILLISECONDS, 0, PHASE_NORMAL);
+ events.ScheduleEvent(EVENT_BERSERK, 10 * MINUTE * IN_MILLISECONDS);
- summon->CastSpell(summon, SPELL_SUMMON_CORPSE_SCARABS_MOB, true, NULL, NULL, me->GetGUID());
+ if (!Is25ManRaid())
+ events.ScheduleEvent(EVENT_SPAWN_GUARD, urand(15, 20) * IN_MILLISECONDS);
}
void UpdateAI(uint32 diff) override
@@ -158,22 +183,44 @@ public:
switch (eventId)
{
case EVENT_IMPALE:
- //Cast Impale on a random target
- //Do NOT cast it when we are afflicted by locust swarm
- if (!me->HasAura(SPELL_LOCUST_SWARM))
- if (Unit* target = SelectTarget(SELECT_TARGET_RANDOM, 0))
- DoCast(target, SPELL_IMPALE);
- events.ScheduleEvent(EVENT_IMPALE, urand(10000, 20000));
+ if (events.GetTimeUntilEvent(EVENT_LOCUST) < 5 * IN_MILLISECONDS) break; // don't chain impale tank -> locust swarm
+ if (Unit* target = SelectTarget(SELECT_TARGET_RANDOM, 0))
+ DoCast(target, SPELL_IMPALE);
+ else
+ EnterEvadeMode();
+
+ events.ScheduleEvent(EVENT_IMPALE, urand(10 * IN_MILLISECONDS, 20 * IN_MILLISECONDS), 0, PHASE_NORMAL);
+ break;
+ case EVENT_SCARABS:
+ events.ScheduleEvent(EVENT_SCARABS, urand(40 * IN_MILLISECONDS, 60 * IN_MILLISECONDS), 0, PHASE_NORMAL);
+
+ if (!guardCorpses.empty())
+ {
+ if (ObjectGuid target = Trinity::Containers::SelectRandomContainerElement(guardCorpses))
+ if(Creature* creatureTarget = ObjectAccessor::GetCreature(*me, target))
+ {
+ creatureTarget->CastSpell(creatureTarget, SPELL_SUMMON_CORPSE_SCARABS_MOB, true, nullptr, nullptr, me->GetGUID());
+ creatureTarget->AI()->Talk(EMOTE_SCARAB);
+ creatureTarget->DespawnOrUnsummon();
+ }
+ }
break;
case EVENT_LOCUST:
- /// @todo Add Text
+ Talk(EMOTE_LOCUST);
DoCast(me, SPELL_LOCUST_SWARM);
- DoSummon(NPC_CRYPT_GUARD, GuardSummonPos, 0, TEMPSUMMON_CORPSE_DESPAWN);
+ events.ScheduleEvent(EVENT_SPAWN_GUARD, 3 * IN_MILLISECONDS);
+
+ events.ScheduleEvent(EVENT_LOCUST_ENDS, RAID_MODE(19, 23) * IN_MILLISECONDS);
events.ScheduleEvent(EVENT_LOCUST, 90000);
+ events.SetPhase(PHASE_SWARM);
+ break;
+ case EVENT_LOCUST_ENDS:
+ events.ScheduleEvent(EVENT_IMPALE, urand(10 * IN_MILLISECONDS, 20 * IN_MILLISECONDS), 0, PHASE_NORMAL);
+ events.ScheduleEvent(EVENT_SCARABS, urand(20 * IN_MILLISECONDS, 30 * IN_MILLISECONDS), 0, PHASE_NORMAL);
+ events.SetPhase(PHASE_NORMAL);
break;
- case EVENT_SPAWN_GUARDIAN_NORMAL:
- /// @todo Add Text
- DoSummon(NPC_CRYPT_GUARD, GuardSummonPos, 0, TEMPSUMMON_CORPSE_DESPAWN);
+ case EVENT_SPAWN_GUARD:
+ me->SummonCreatureGroup(GROUP_SINGLE_SPAWN);
break;
case EVENT_BERSERK:
DoCast(me, SPELL_BERSERK, true);
@@ -182,13 +229,37 @@ public:
}
}
- DoMeleeAttackIfReady();
+ if (events.IsInPhase(PHASE_NORMAL))
+ DoMeleeAttackIfReady();
}
+ private:
+ GuidSet guardCorpses;
};
};
+class at_anubrekhan_entrance : public AreaTriggerScript
+{
+ public:
+ at_anubrekhan_entrance() : AreaTriggerScript("at_anubrekhan_entrance") { }
+
+ bool OnTrigger(Player* player, AreaTriggerEntry const* /*areaTrigger*/) override
+ {
+ InstanceScript* instance = player->GetInstanceScript();
+ if (!instance || instance->GetData(DATA_HAD_ANUBREKHAN_GREET) || instance->GetBossState(BOSS_ANUBREKHAN) != NOT_STARTED)
+ return true;
+
+ if (Creature* anub = ObjectAccessor::GetCreature(*player, instance->GetGuidData(DATA_ANUBREKHAN)))
+ anub->AI()->Talk(SAY_GREET);
+ instance->SetData(DATA_HAD_ANUBREKHAN_GREET, 1u);
+
+ return true;
+ }
+};
+
void AddSC_boss_anubrekhan()
{
new boss_anubrekhan();
+
+ new at_anubrekhan_entrance();
}
diff --git a/src/server/scripts/Northrend/Naxxramas/instance_naxxramas.cpp b/src/server/scripts/Northrend/Naxxramas/instance_naxxramas.cpp
index fc0f0e2b833..f0348c408b1 100644
--- a/src/server/scripts/Northrend/Naxxramas/instance_naxxramas.cpp
+++ b/src/server/scripts/Northrend/Naxxramas/instance_naxxramas.cpp
@@ -125,6 +125,7 @@ class instance_naxxramas : public InstanceMapScript
minHorsemenDiedTime = 0;
maxHorsemenDiedTime = 0;
AbominationCount = 0;
+ hadAnubRekhanGreet = false;
hadFaerlinaGreet = false;
CurrentWingTaunt = SAY_KELTHUZAD_FIRST_WING_TAUNT;
@@ -135,6 +136,9 @@ class instance_naxxramas : public InstanceMapScript
{
switch (creature->GetEntry())
{
+ case NPC_ANUBREKHAN:
+ AnubRekhanGUID = creature->GetGUID();
+ break;
case NPC_FAERLINA:
FaerlinaGUID = creature->GetGUID();
break;
@@ -319,9 +323,14 @@ class instance_naxxramas : public InstanceMapScript
case DATA_ABOMINATION_KILLED:
AbominationCount = value;
break;
+ case DATA_HAD_ANUBREKHAN_GREET:
+ hadAnubRekhanGreet = (value == 1u);
+ break;
case DATA_HAD_FAERLINA_GREET:
hadFaerlinaGreet = (value == 1u);
break;
+ default:
+ break;
}
}
@@ -331,6 +340,8 @@ class instance_naxxramas : public InstanceMapScript
{
case DATA_ABOMINATION_KILLED:
return AbominationCount;
+ case DATA_HAD_ANUBREKHAN_GREET:
+ return (uint32)hadAnubRekhanGreet;
case DATA_HAD_FAERLINA_GREET:
return (uint32)hadFaerlinaGreet;
default:
@@ -344,6 +355,8 @@ class instance_naxxramas : public InstanceMapScript
{
switch (id)
{
+ case DATA_ANUBREKHAN:
+ return AnubRekhanGUID;
case DATA_FAERLINA:
return FaerlinaGUID;
case DATA_THANE:
@@ -604,6 +617,8 @@ class instance_naxxramas : public InstanceMapScript
protected:
/* The Arachnid Quarter */
+ // Anub'rekhan
+ ObjectGuid AnubRekhanGUID;
// Grand Widow Faerlina
ObjectGuid FaerlinaGUID;
@@ -640,6 +655,7 @@ class instance_naxxramas : public InstanceMapScript
ObjectGuid KelthuzadDoorGUID;
ObjectGuid LichKingGUID;
uint8 AbominationCount;
+ bool hadAnubRekhanGreet;
bool hadFaerlinaGreet;
uint8 CurrentWingTaunt;
diff --git a/src/server/scripts/Northrend/Naxxramas/naxxramas.h b/src/server/scripts/Northrend/Naxxramas/naxxramas.h
index 6795e2cc337..6289b707411 100644
--- a/src/server/scripts/Northrend/Naxxramas/naxxramas.h
+++ b/src/server/scripts/Northrend/Naxxramas/naxxramas.h
@@ -46,6 +46,7 @@ enum Data
DATA_HEIGAN_ERUPT,
DATA_GOTHIK_GATE,
DATA_SAPPHIRON_BIRTH,
+ DATA_HAD_ANUBREKHAN_GREET,
DATA_HAD_FAERLINA_GREET,
@@ -63,6 +64,7 @@ enum Data
enum Data64
{
+ DATA_ANUBREKHAN,
DATA_FAERLINA,
DATA_THANE,
DATA_LADY,
@@ -83,6 +85,7 @@ enum Data64
enum CreaturesIds
{
+ NPC_ANUBREKHAN = 15956,
NPC_FAERLINA = 15953,
NPC_THANE = 16064,
NPC_LADY = 16065,