aboutsummaryrefslogtreecommitdiff
path: root/src/server/scripts
diff options
context:
space:
mode:
Diffstat (limited to 'src/server/scripts')
-rw-r--r--src/server/scripts/Northrend/IcecrownCitadel/boss_blood_prince_council.cpp86
-rw-r--r--src/server/scripts/Northrend/IcecrownCitadel/boss_deathbringer_saurfang.cpp1
-rw-r--r--src/server/scripts/Northrend/IcecrownCitadel/boss_festergut.cpp1
-rw-r--r--src/server/scripts/Northrend/IcecrownCitadel/boss_lady_deathwhisper.cpp51
-rw-r--r--src/server/scripts/Northrend/IcecrownCitadel/boss_lord_marrowgar.cpp56
-rw-r--r--src/server/scripts/Northrend/IcecrownCitadel/boss_professor_putricide.cpp3
-rw-r--r--src/server/scripts/Northrend/IcecrownCitadel/boss_rotface.cpp5
-rw-r--r--src/server/scripts/Northrend/IcecrownCitadel/boss_sindragosa.cpp7
-rw-r--r--src/server/scripts/Northrend/IcecrownCitadel/icecrown_citadel.h86
-rw-r--r--src/server/scripts/Northrend/IcecrownCitadel/instance_icecrown_citadel.cpp18
-rw-r--r--src/server/scripts/Northrend/Naxxramas/boss_maexxna.cpp150
-rw-r--r--src/server/scripts/Northrend/Naxxramas/boss_razuvious.cpp196
-rw-r--r--src/server/scripts/Northrend/Naxxramas/instance_naxxramas.cpp8
-rw-r--r--src/server/scripts/Northrend/Naxxramas/naxxramas.h2
-rw-r--r--src/server/scripts/Pet/pet_mage.cpp185
15 files changed, 632 insertions, 223 deletions
diff --git a/src/server/scripts/Northrend/IcecrownCitadel/boss_blood_prince_council.cpp b/src/server/scripts/Northrend/IcecrownCitadel/boss_blood_prince_council.cpp
index aeaf8a70ba5..cfeb31d5526 100644
--- a/src/server/scripts/Northrend/IcecrownCitadel/boss_blood_prince_council.cpp
+++ b/src/server/scripts/Northrend/IcecrownCitadel/boss_blood_prince_council.cpp
@@ -136,11 +136,12 @@ enum Events
enum Actions
{
- ACTION_STAND_UP = 1,
- ACTION_CAST_INVOCATION = 2,
- ACTION_REMOVE_INVOCATION = 3,
- ACTION_KINETIC_BOMB_JUMP = 4,
- ACTION_FLAME_BALL_CHASE = 5,
+ ACTION_START_INTRO = 1,
+ ACTION_STAND_UP = 2,
+ ACTION_CAST_INVOCATION = 3,
+ ACTION_REMOVE_INVOCATION = 4,
+ ACTION_KINETIC_BOMB_JUMP = 5,
+ ACTION_FLAME_BALL_CHASE = 6,
};
enum Points
@@ -162,6 +163,7 @@ class StandUpEvent : public BasicEvent
bool Execute(uint64 /*eventTime*/, uint32 /*diff*/)
{
_owner.HandleEmoteCommand(EMOTE_ONESHOT_ROAR);
+ _owner.SetReactState(REACT_AGGRESSIVE);
return true;
}
@@ -382,8 +384,6 @@ class boss_prince_keleseth_icc : public CreatureScript
if (!me->isDead())
JustRespawned();
-
- me->SetReactState(REACT_DEFENSIVE);
}
void Reset() override
@@ -395,7 +395,6 @@ class boss_prince_keleseth_icc : public CreatureScript
_isEmpowered = false;
me->SetHealth(_spawnHealth);
instance->SetData(DATA_ORB_WHISPERER_ACHIEVEMENT, uint32(true));
- me->SetReactState(REACT_DEFENSIVE);
}
void EnterCombat(Unit* /*who*/) override
@@ -597,8 +596,6 @@ class boss_prince_taldaram_icc : public CreatureScript
if (!me->isDead())
JustRespawned();
-
- me->SetReactState(REACT_DEFENSIVE);
}
void Reset() override
@@ -610,12 +607,6 @@ class boss_prince_taldaram_icc : public CreatureScript
_isEmpowered = false;
me->SetHealth(_spawnHealth);
instance->SetData(DATA_ORB_WHISPERER_ACHIEVEMENT, uint32(true));
- me->SetReactState(REACT_DEFENSIVE);
- }
-
- void MoveInLineOfSight(Unit* /*who*/) override
-
- {
}
void EnterCombat(Unit* /*who*/) override
@@ -821,8 +812,6 @@ class boss_prince_valanar_icc : public CreatureScript
if (!me->isDead())
JustRespawned();
-
- me->SetReactState(REACT_DEFENSIVE);
}
void Reset() override
@@ -834,12 +823,6 @@ class boss_prince_valanar_icc : public CreatureScript
_isEmpowered = false;
me->SetHealth(me->GetMaxHealth());
instance->SetData(DATA_ORB_WHISPERER_ACHIEVEMENT, uint32(true));
- me->SetReactState(REACT_DEFENSIVE);
- }
-
- void MoveInLineOfSight(Unit* /*who*/) override
-
- {
}
void EnterCombat(Unit* /*who*/) override
@@ -905,6 +888,7 @@ class boss_prince_valanar_icc : public CreatureScript
default:
break;
}
+
summons.Summon(summon);
if (me->IsInCombat())
DoZoneInCombat(summon);
@@ -1070,25 +1054,28 @@ class npc_blood_queen_lana_thel : public CreatureScript
me->SetVisible(true);
}
- void MoveInLineOfSight(Unit* who) override
-
+ void DoAction(int32 action) override
{
- if (_introDone)
- return;
-
- if (!me->IsWithinDistInMap(who, 35.0f, false))
- return;
-
- _introDone = true;
- Talk(SAY_INTRO_1);
- _events.SetPhase(1);
- _events.ScheduleEvent(EVENT_INTRO_1, 14000);
- // summon a visual trigger
- if (Creature* summon = DoSummon(NPC_FLOATING_TRIGGER, triggerPos, 15000, TEMPSUMMON_TIMED_DESPAWN))
+ switch (action)
{
- summon->CastSpell(summon, SPELL_OOC_INVOCATION_VISUAL, true);
- summon->SetSpeed(MOVE_FLIGHT, 0.15f, true);
- summon->GetMotionMaster()->MovePoint(0, triggerEndPos);
+ case ACTION_START_INTRO:
+ if (!_introDone)
+ {
+ _introDone = true;
+ Talk(SAY_INTRO_1);
+ _events.SetPhase(1);
+ _events.ScheduleEvent(EVENT_INTRO_1, 14000);
+ // summon a visual trigger
+ if (Creature* summon = DoSummon(NPC_FLOATING_TRIGGER, triggerPos, 15000, TEMPSUMMON_TIMED_DESPAWN))
+ {
+ summon->CastSpell(summon, SPELL_OOC_INVOCATION_VISUAL, true);
+ summon->SetSpeed(MOVE_FLIGHT, 0.15f, true); // todo: creature is swimming, check if this is blizzlike or not.
+ summon->GetMotionMaster()->MovePoint(0, triggerEndPos);
+ }
+ }
+ break;
+ default:
+ break;
}
}
@@ -1328,7 +1315,6 @@ class npc_dark_nucleus : public CreatureScript
}
void MoveInLineOfSight(Unit* who) override
-
{
ScriptedAI::MoveInLineOfSight(who);
}
@@ -1670,6 +1656,21 @@ class spell_blood_council_shadow_prison_damage : public SpellScriptLoader
}
};
+class at_blood_prince_council_start_intro : public AreaTriggerScript
+{
+ public:
+ at_blood_prince_council_start_intro() : AreaTriggerScript("at_blood_prince_council_start_intro") { }
+
+ bool OnTrigger(Player* player, AreaTriggerEntry const* /*areaTrigger*/) override
+ {
+ if (InstanceScript* instance = player->GetInstanceScript())
+ if (Creature* bloodQueen = ObjectAccessor::GetCreature(*player, instance->GetGuidData(DATA_BLOOD_QUEEN_LANA_THEL_COUNCIL)))
+ bloodQueen->AI()->DoAction(ACTION_START_INTRO);
+
+ return true;
+ }
+};
+
void AddSC_boss_blood_prince_council()
{
new boss_blood_council_controller();
@@ -1689,4 +1690,5 @@ void AddSC_boss_blood_prince_council()
new spell_valanar_kinetic_bomb_absorb();
new spell_blood_council_shadow_prison();
new spell_blood_council_shadow_prison_damage();
+ new at_blood_prince_council_start_intro();
}
diff --git a/src/server/scripts/Northrend/IcecrownCitadel/boss_deathbringer_saurfang.cpp b/src/server/scripts/Northrend/IcecrownCitadel/boss_deathbringer_saurfang.cpp
index 365e0a1588d..54c24769246 100644
--- a/src/server/scripts/Northrend/IcecrownCitadel/boss_deathbringer_saurfang.cpp
+++ b/src/server/scripts/Northrend/IcecrownCitadel/boss_deathbringer_saurfang.cpp
@@ -268,7 +268,6 @@ class boss_deathbringer_saurfang : public CreatureScript
void Reset() override
{
_Reset();
- me->SetReactState(REACT_DEFENSIVE);
events.SetPhase(PHASE_COMBAT);
Initialize();
me->SetPower(POWER_ENERGY, 0);
diff --git a/src/server/scripts/Northrend/IcecrownCitadel/boss_festergut.cpp b/src/server/scripts/Northrend/IcecrownCitadel/boss_festergut.cpp
index e3e89d865ff..f76c415ab92 100644
--- a/src/server/scripts/Northrend/IcecrownCitadel/boss_festergut.cpp
+++ b/src/server/scripts/Northrend/IcecrownCitadel/boss_festergut.cpp
@@ -93,7 +93,6 @@ class boss_festergut : public CreatureScript
void Reset() override
{
_Reset();
- me->SetReactState(REACT_DEFENSIVE);
events.ScheduleEvent(EVENT_BERSERK, 300000);
events.ScheduleEvent(EVENT_INHALE_BLIGHT, urand(25000, 30000));
events.ScheduleEvent(EVENT_GAS_SPORE, urand(20000, 25000));
diff --git a/src/server/scripts/Northrend/IcecrownCitadel/boss_lady_deathwhisper.cpp b/src/server/scripts/Northrend/IcecrownCitadel/boss_lady_deathwhisper.cpp
index 3a745e2c98c..78a279b94fd 100644
--- a/src/server/scripts/Northrend/IcecrownCitadel/boss_lady_deathwhisper.cpp
+++ b/src/server/scripts/Northrend/IcecrownCitadel/boss_lady_deathwhisper.cpp
@@ -174,6 +174,11 @@ enum DeprogrammingData
POINT_DESPAWN = 384721,
};
+enum Actions
+{
+ ACTION_START_INTRO
+};
+
#define NPC_DARNAVAN RAID_MODE<uint32>(NPC_DARNAVAN_10, NPC_DARNAVAN_25, NPC_DARNAVAN_10, NPC_DARNAVAN_25)
#define NPC_DARNAVAN_CREDIT RAID_MODE<uint32>(NPC_DARNAVAN_CREDIT_10, NPC_DARNAVAN_CREDIT_25, NPC_DARNAVAN_CREDIT_10, NPC_DARNAVAN_CREDIT_25)
#define QUEST_DEPROGRAMMING RAID_MODE<uint32>(QUEST_DEPROGRAMMING_10, QUEST_DEPROGRAMMING_25, QUEST_DEPROGRAMMING_10, QUEST_DEPROGRAMMING_25)
@@ -241,20 +246,26 @@ class boss_lady_deathwhisper : public CreatureScript
me->ApplySpellImmune(0, IMMUNITY_EFFECT, SPELL_EFFECT_ATTACK_ME, false);
}
- void MoveInLineOfSight(Unit* who) override
-
+ void DoAction(int32 action) override
{
- if (!_introDone && me->IsWithinDistInMap(who, 110.0f))
+ switch (action)
{
- _introDone = true;
- Talk(SAY_INTRO_1);
- events.SetPhase(PHASE_INTRO);
- events.ScheduleEvent(EVENT_INTRO_2, 11000, 0, PHASE_INTRO);
- events.ScheduleEvent(EVENT_INTRO_3, 21000, 0, PHASE_INTRO);
- events.ScheduleEvent(EVENT_INTRO_4, 31500, 0, PHASE_INTRO);
- events.ScheduleEvent(EVENT_INTRO_5, 39500, 0, PHASE_INTRO);
- events.ScheduleEvent(EVENT_INTRO_6, 48500, 0, PHASE_INTRO);
- events.ScheduleEvent(EVENT_INTRO_7, 58000, 0, PHASE_INTRO);
+ case ACTION_START_INTRO:
+ if (!_introDone)
+ {
+ _introDone = true;
+ Talk(SAY_INTRO_1);
+ events.SetPhase(PHASE_INTRO);
+ events.ScheduleEvent(EVENT_INTRO_2, 11000, 0, PHASE_INTRO);
+ events.ScheduleEvent(EVENT_INTRO_3, 21000, 0, PHASE_INTRO);
+ events.ScheduleEvent(EVENT_INTRO_4, 31500, 0, PHASE_INTRO);
+ events.ScheduleEvent(EVENT_INTRO_5, 39500, 0, PHASE_INTRO);
+ events.ScheduleEvent(EVENT_INTRO_6, 48500, 0, PHASE_INTRO);
+ events.ScheduleEvent(EVENT_INTRO_7, 58000, 0, PHASE_INTRO);
+ }
+ break;
+ default:
+ break;
}
}
@@ -1024,6 +1035,21 @@ class spell_cultist_dark_martyrdom : public SpellScriptLoader
}
};
+class at_lady_deathwhisper_entrance : public AreaTriggerScript
+{
+ public:
+ at_lady_deathwhisper_entrance() : AreaTriggerScript("at_lady_deathwhisper_entrance") { }
+
+ bool OnTrigger(Player* player, AreaTriggerEntry const* /*areaTrigger*/) override
+ {
+ if (InstanceScript* instance = player->GetInstanceScript())
+ if (Creature* ladyDeathwhisper = ObjectAccessor::GetCreature(*player, instance->GetGuidData(DATA_LADY_DEATHWHISPER)))
+ ladyDeathwhisper->AI()->DoAction(ACTION_START_INTRO);
+
+ return true;
+ }
+};
+
void AddSC_boss_lady_deathwhisper()
{
new boss_lady_deathwhisper();
@@ -1033,4 +1059,5 @@ void AddSC_boss_lady_deathwhisper()
new npc_darnavan();
new spell_deathwhisper_mana_barrier();
new spell_cultist_dark_martyrdom();
+ new at_lady_deathwhisper_entrance();
}
diff --git a/src/server/scripts/Northrend/IcecrownCitadel/boss_lord_marrowgar.cpp b/src/server/scripts/Northrend/IcecrownCitadel/boss_lord_marrowgar.cpp
index 2fbd1293891..993fc75fcde 100644
--- a/src/server/scripts/Northrend/IcecrownCitadel/boss_lord_marrowgar.cpp
+++ b/src/server/scripts/Northrend/IcecrownCitadel/boss_lord_marrowgar.cpp
@@ -89,11 +89,15 @@ enum MiscInfo
//DATA_SPIKE_IMMUNE_1, = 2, // Reserved & used
//DATA_SPIKE_IMMUNE_2, = 3, // Reserved & used
- ACTION_CLEAR_SPIKE_IMMUNITIES = 1,
-
MAX_BONE_SPIKE_IMMUNE = 3,
};
+enum Actions
+{
+ ACTION_CLEAR_SPIKE_IMMUNITIES = 1,
+ ACTION_TALK_ENTER_ZONE = 2
+};
+
class BoneSpikeTargetSelector : public std::unary_function<Unit*, bool>
{
public:
@@ -131,7 +135,6 @@ class boss_lord_marrowgar : public CreatureScript
_boneStormDuration = RAID_MODE<uint32>(20000, 30000, 20000, 30000);
_baseSpeed = creature->GetSpeedRate(MOVE_RUN);
_coldflameLastPos.Relocate(creature);
- _introDone = false;
_boneSlice = false;
}
@@ -146,6 +149,7 @@ class boss_lord_marrowgar : public CreatureScript
events.ScheduleEvent(EVENT_COLDFLAME, 5000, EVENT_GROUP_SPECIAL);
events.ScheduleEvent(EVENT_WARN_BONE_STORM, urand(45000, 50000));
events.ScheduleEvent(EVENT_ENRAGE, 600000);
+ _introDone = false;
_boneSlice = false;
_boneSpikeImmune.clear();
}
@@ -179,16 +183,6 @@ class boss_lord_marrowgar : public CreatureScript
Talk(SAY_KILL);
}
- void MoveInLineOfSight(Unit* who) override
-
- {
- if (!_introDone && me->IsWithinDistInMap(who, 70.0f))
- {
- Talk(SAY_ENTER_ZONE);
- _introDone = true;
- }
- }
-
void UpdateAI(uint32 diff) override
{
if (!UpdateVictim() || !CheckInRoom())
@@ -324,10 +318,21 @@ class boss_lord_marrowgar : public CreatureScript
void DoAction(int32 action) override
{
- if (action != ACTION_CLEAR_SPIKE_IMMUNITIES)
- return;
-
- _boneSpikeImmune.clear();
+ switch (action)
+ {
+ case ACTION_CLEAR_SPIKE_IMMUNITIES:
+ _boneSpikeImmune.clear();
+ break;
+ case ACTION_TALK_ENTER_ZONE:
+ if (!_introDone)
+ {
+ Talk(SAY_ENTER_ZONE);
+ _introDone = true;
+ }
+ break;
+ default:
+ break;
+ }
}
private:
@@ -742,6 +747,22 @@ class spell_marrowgar_bone_slice : public SpellScriptLoader
}
};
+class at_lord_marrowgar_entrance : public AreaTriggerScript
+{
+ public:
+ at_lord_marrowgar_entrance() : AreaTriggerScript("at_lord_marrowgar_entrance") { }
+
+ bool OnTrigger(Player* player, AreaTriggerEntry const* /*areaTrigger*/) override
+ {
+ if (InstanceScript* instance = player->GetInstanceScript())
+ if (Creature* lordMarrowgar = ObjectAccessor::GetCreature(*player, instance->GetGuidData(DATA_LORD_MARROWGAR)))
+ lordMarrowgar->AI()->DoAction(ACTION_TALK_ENTER_ZONE);
+
+ return true;
+ }
+
+};
+
void AddSC_boss_lord_marrowgar()
{
new boss_lord_marrowgar();
@@ -753,4 +774,5 @@ void AddSC_boss_lord_marrowgar()
new spell_marrowgar_bone_spike_graveyard();
new spell_marrowgar_bone_storm();
new spell_marrowgar_bone_slice();
+ new at_lord_marrowgar_entrance();
}
diff --git a/src/server/scripts/Northrend/IcecrownCitadel/boss_professor_putricide.cpp b/src/server/scripts/Northrend/IcecrownCitadel/boss_professor_putricide.cpp
index be134a06173..4c67c0a7163 100644
--- a/src/server/scripts/Northrend/IcecrownCitadel/boss_professor_putricide.cpp
+++ b/src/server/scripts/Northrend/IcecrownCitadel/boss_professor_putricide.cpp
@@ -236,7 +236,6 @@ class boss_professor_putricide : public CreatureScript
summons.DespawnAll();
SetPhase(PHASE_COMBAT_1);
_experimentState = EXPERIMENT_STATE_OOZE;
- me->SetReactState(REACT_DEFENSIVE);
me->SetWalk(false);
if (me->GetMotionMaster()->GetCurrentMovementGeneratorType() == POINT_MOTION_TYPE)
me->GetMotionMaster()->MovementExpired();
@@ -616,7 +615,7 @@ class boss_professor_putricide : public CreatureScript
DoCast(me, SPELL_TEAR_GAS_PERIODIC_TRIGGER, true);
break;
case EVENT_RESUME_ATTACK:
- me->SetReactState(REACT_DEFENSIVE);
+ me->SetReactState(REACT_AGGRESSIVE);
AttackStart(me->GetVictim());
// remove Tear Gas
me->RemoveAurasDueToSpell(SPELL_TEAR_GAS_PERIODIC_TRIGGER);
diff --git a/src/server/scripts/Northrend/IcecrownCitadel/boss_rotface.cpp b/src/server/scripts/Northrend/IcecrownCitadel/boss_rotface.cpp
index 1a2ebd179fe..d03925f734a 100644
--- a/src/server/scripts/Northrend/IcecrownCitadel/boss_rotface.cpp
+++ b/src/server/scripts/Northrend/IcecrownCitadel/boss_rotface.cpp
@@ -168,11 +168,6 @@ class boss_rotface : public CreatureScript
Talk(SAY_SLIME_SPRAY);
}
- void MoveInLineOfSight(Unit* /*who*/) override
- {
- // don't enter combat
- }
-
void JustSummoned(Creature* summon) override
{
if (summon->GetEntry() == NPC_VILE_GAS_STALKER)
diff --git a/src/server/scripts/Northrend/IcecrownCitadel/boss_sindragosa.cpp b/src/server/scripts/Northrend/IcecrownCitadel/boss_sindragosa.cpp
index 65d99b022dc..8917af0038f 100644
--- a/src/server/scripts/Northrend/IcecrownCitadel/boss_sindragosa.cpp
+++ b/src/server/scripts/Northrend/IcecrownCitadel/boss_sindragosa.cpp
@@ -234,7 +234,6 @@ class boss_sindragosa : public CreatureScript
void Reset() override
{
BossAI::Reset();
- me->SetReactState(REACT_DEFENSIVE);
DoCast(me, SPELL_TANK_MARKER, true);
events.ScheduleEvent(EVENT_BERSERK, 600000);
events.ScheduleEvent(EVENT_CLEAVE, 10000, EVENT_GROUP_LAND_PHASE);
@@ -659,7 +658,6 @@ class npc_spinestalker : public CreatureScript
_events.ScheduleEvent(EVENT_BELLOWING_ROAR, urand(20000, 25000));
_events.ScheduleEvent(EVENT_CLEAVE_SPINESTALKER, urand(10000, 15000));
_events.ScheduleEvent(EVENT_TAIL_SWEEP, urand(8000, 12000));
- me->SetReactState(REACT_DEFENSIVE);
if (!_summoned)
{
@@ -699,6 +697,7 @@ class npc_spinestalker : public CreatureScript
me->GetMotionMaster()->MoveIdle();
me->StopMoving();
me->GetMotionMaster()->MovePoint(POINT_FROSTWYRM_FLY_IN, SpinestalkerFlyPos);
+ me->SetReactState(REACT_DEFENSIVE);
}
}
@@ -714,6 +713,7 @@ class npc_spinestalker : public CreatureScript
me->SetHomePosition(SpinestalkerLandPos);
me->SetFacingTo(SpinestalkerLandPos.GetOrientation());
me->RemoveFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NON_ATTACKABLE);
+ me->SetReactState(REACT_AGGRESSIVE);
}
void UpdateAI(uint32 diff) override
@@ -794,7 +794,6 @@ class npc_rimefang : public CreatureScript
_events.Reset();
_events.ScheduleEvent(EVENT_FROST_BREATH_RIMEFANG, urand(12000, 15000));
_events.ScheduleEvent(EVENT_ICY_BLAST, urand(30000, 35000));
- me->SetReactState(REACT_DEFENSIVE);
Initialize();
if (!_summoned)
@@ -835,6 +834,7 @@ class npc_rimefang : public CreatureScript
me->GetMotionMaster()->MoveIdle();
me->StopMoving();
me->GetMotionMaster()->MovePoint(POINT_FROSTWYRM_FLY_IN, RimefangFlyPos);
+ me->SetReactState(REACT_DEFENSIVE);
}
}
@@ -850,6 +850,7 @@ class npc_rimefang : public CreatureScript
me->SetHomePosition(RimefangLandPos);
me->SetFacingTo(RimefangLandPos.GetOrientation());
me->RemoveFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_IMMUNE_TO_PC);
+ me->SetReactState(REACT_AGGRESSIVE);
}
void EnterCombat(Unit* /*victim*/) override
diff --git a/src/server/scripts/Northrend/IcecrownCitadel/icecrown_citadel.h b/src/server/scripts/Northrend/IcecrownCitadel/icecrown_citadel.h
index e739f5a5036..224aa6cda45 100644
--- a/src/server/scripts/Northrend/IcecrownCitadel/icecrown_citadel.h
+++ b/src/server/scripts/Northrend/IcecrownCitadel/icecrown_citadel.h
@@ -72,50 +72,51 @@ enum TeleporterSpells
enum DataTypes
{
// Encounter States/Boss GUIDs
- DATA_LORD_MARROWGAR = 0,
- DATA_LADY_DEATHWHISPER = 1,
- DATA_ICECROWN_GUNSHIP_BATTLE = 2,
- DATA_DEATHBRINGER_SAURFANG = 3,
- DATA_FESTERGUT = 4,
- DATA_ROTFACE = 5,
- DATA_PROFESSOR_PUTRICIDE = 6,
- DATA_BLOOD_PRINCE_COUNCIL = 7,
- DATA_BLOOD_QUEEN_LANA_THEL = 8,
- DATA_SISTER_SVALNA = 9,
- DATA_VALITHRIA_DREAMWALKER = 10,
- DATA_SINDRAGOSA = 11,
- DATA_THE_LICH_KING = 12,
+ DATA_LORD_MARROWGAR = 0,
+ DATA_LADY_DEATHWHISPER = 1,
+ DATA_ICECROWN_GUNSHIP_BATTLE = 2,
+ DATA_DEATHBRINGER_SAURFANG = 3,
+ DATA_FESTERGUT = 4,
+ DATA_ROTFACE = 5,
+ DATA_PROFESSOR_PUTRICIDE = 6,
+ DATA_BLOOD_PRINCE_COUNCIL = 7,
+ DATA_BLOOD_QUEEN_LANA_THEL = 8,
+ DATA_SISTER_SVALNA = 9,
+ DATA_VALITHRIA_DREAMWALKER = 10,
+ DATA_SINDRAGOSA = 11,
+ DATA_THE_LICH_KING = 12,
// Additional data
- DATA_SAURFANG_EVENT_NPC = 13,
- DATA_BONED_ACHIEVEMENT = 14,
- DATA_OOZE_DANCE_ACHIEVEMENT = 15,
- DATA_PUTRICIDE_TABLE = 16,
- DATA_NAUSEA_ACHIEVEMENT = 17,
- DATA_ORB_WHISPERER_ACHIEVEMENT = 18,
- DATA_PRINCE_KELESETH_GUID = 19,
- DATA_PRINCE_TALDARAM_GUID = 20,
- DATA_PRINCE_VALANAR_GUID = 21,
- DATA_BLOOD_PRINCES_CONTROL = 22,
- DATA_SINDRAGOSA_FROSTWYRMS = 23,
- DATA_SPINESTALKER = 24,
- DATA_RIMEFANG = 25,
- DATA_COLDFLAME_JETS = 26,
- DATA_TEAM_IN_INSTANCE = 27,
- DATA_BLOOD_QUICKENING_STATE = 28,
- DATA_HEROIC_ATTEMPTS = 29,
- DATA_CROK_SCOURGEBANE = 30,
- DATA_CAPTAIN_ARNATH = 31,
- DATA_CAPTAIN_BRANDON = 32,
- DATA_CAPTAIN_GRONDEL = 33,
- DATA_CAPTAIN_RUPERT = 34,
- DATA_VALITHRIA_TRIGGER = 35,
- DATA_VALITHRIA_LICH_KING = 36,
- DATA_HIGHLORD_TIRION_FORDRING = 37,
- DATA_ARTHAS_PLATFORM = 38,
- DATA_TERENAS_MENETHIL = 39,
- DATA_ENEMY_GUNSHIP = 40,
- DATA_UPPERSPIRE_TELE_ACT = 41,
+ DATA_SAURFANG_EVENT_NPC = 13,
+ DATA_BONED_ACHIEVEMENT = 14,
+ DATA_OOZE_DANCE_ACHIEVEMENT = 15,
+ DATA_PUTRICIDE_TABLE = 16,
+ DATA_NAUSEA_ACHIEVEMENT = 17,
+ DATA_ORB_WHISPERER_ACHIEVEMENT = 18,
+ DATA_PRINCE_KELESETH_GUID = 19,
+ DATA_PRINCE_TALDARAM_GUID = 20,
+ DATA_PRINCE_VALANAR_GUID = 21,
+ DATA_BLOOD_PRINCES_CONTROL = 22,
+ DATA_SINDRAGOSA_FROSTWYRMS = 23,
+ DATA_SPINESTALKER = 24,
+ DATA_RIMEFANG = 25,
+ DATA_COLDFLAME_JETS = 26,
+ DATA_TEAM_IN_INSTANCE = 27,
+ DATA_BLOOD_QUICKENING_STATE = 28,
+ DATA_HEROIC_ATTEMPTS = 29,
+ DATA_CROK_SCOURGEBANE = 30,
+ DATA_CAPTAIN_ARNATH = 31,
+ DATA_CAPTAIN_BRANDON = 32,
+ DATA_CAPTAIN_GRONDEL = 33,
+ DATA_CAPTAIN_RUPERT = 34,
+ DATA_VALITHRIA_TRIGGER = 35,
+ DATA_VALITHRIA_LICH_KING = 36,
+ DATA_HIGHLORD_TIRION_FORDRING = 37,
+ DATA_ARTHAS_PLATFORM = 38,
+ DATA_TERENAS_MENETHIL = 39,
+ DATA_ENEMY_GUNSHIP = 40,
+ DATA_UPPERSPIRE_TELE_ACT = 41,
+ DATA_BLOOD_QUEEN_LANA_THEL_COUNCIL = 42
};
enum CreaturesIds
@@ -247,6 +248,7 @@ enum CreaturesIds
NPC_KINETIC_BOMB_TARGET = 38458,
NPC_KINETIC_BOMB = 38454,
NPC_SHOCK_VORTEX = 38422,
+ NPC_BLOOD_QUEEN_LANA_THEL_COUNCIL = 38004,
// Blood-Queen Lana'thel
NPC_BLOOD_QUEEN_LANA_THEL = 37955,
diff --git a/src/server/scripts/Northrend/IcecrownCitadel/instance_icecrown_citadel.cpp b/src/server/scripts/Northrend/IcecrownCitadel/instance_icecrown_citadel.cpp
index 5354d1772b6..718c0ebe231 100644
--- a/src/server/scripts/Northrend/IcecrownCitadel/instance_icecrown_citadel.cpp
+++ b/src/server/scripts/Northrend/IcecrownCitadel/instance_icecrown_citadel.cpp
@@ -173,6 +173,12 @@ class instance_icecrown_citadel : public InstanceMapScript
switch (creature->GetEntry())
{
+ case NPC_LORD_MARROWGAR:
+ LordMarrowgarGUID = creature->GetGUID();
+ break;
+ case NPC_LADY_DEATHWHISPER:
+ LadyDeahtwhisperGUID = creature->GetGUID();
+ break;
case NPC_KOR_KRON_GENERAL:
if (TeamInInstance == ALLIANCE)
creature->UpdateEntry(NPC_ALLIANCE_COMMANDER);
@@ -249,6 +255,9 @@ class instance_icecrown_citadel : public InstanceMapScript
case NPC_BLOOD_ORB_CONTROLLER:
BloodCouncilControllerGUID = creature->GetGUID();
break;
+ case NPC_BLOOD_QUEEN_LANA_THEL_COUNCIL:
+ BloodQueenLanaThelCouncilGUID = creature->GetGUID();
+ break;
case NPC_BLOOD_QUEEN_LANA_THEL:
BloodQueenLanaThelGUID = creature->GetGUID();
break;
@@ -712,6 +721,10 @@ class instance_icecrown_citadel : public InstanceMapScript
{
switch (type)
{
+ case DATA_LORD_MARROWGAR:
+ return LordMarrowgarGUID;
+ case DATA_LADY_DEATHWHISPER:
+ return LadyDeahtwhisperGUID;
case DATA_ICECROWN_GUNSHIP_BATTLE:
return GunshipGUID;
case DATA_ENEMY_GUNSHIP:
@@ -738,6 +751,8 @@ class instance_icecrown_citadel : public InstanceMapScript
return BloodCouncilGUIDs[2];
case DATA_BLOOD_PRINCES_CONTROL:
return BloodCouncilControllerGUID;
+ case DATA_BLOOD_QUEEN_LANA_THEL_COUNCIL:
+ return BloodQueenLanaThelCouncilGUID;
case DATA_BLOOD_QUEEN_LANA_THEL:
return BloodQueenLanaThelGUID;
case DATA_CROK_SCOURGEBANE:
@@ -1425,6 +1440,8 @@ class instance_icecrown_citadel : public InstanceMapScript
protected:
EventMap Events;
+ ObjectGuid LordMarrowgarGUID;
+ ObjectGuid LadyDeahtwhisperGUID;
ObjectGuid LadyDeathwisperElevatorGUID;
ObjectGuid GunshipGUID;
ObjectGuid EnemyGunshipGUID;
@@ -1452,6 +1469,7 @@ class instance_icecrown_citadel : public InstanceMapScript
ObjectGuid PutricideTableGUID;
ObjectGuid BloodCouncilGUIDs[3];
ObjectGuid BloodCouncilControllerGUID;
+ ObjectGuid BloodQueenLanaThelCouncilGUID;
ObjectGuid BloodQueenLanaThelGUID;
ObjectGuid CrokScourgebaneGUID;
ObjectGuid CrokCaptainGUIDs[4];
diff --git a/src/server/scripts/Northrend/Naxxramas/boss_maexxna.cpp b/src/server/scripts/Northrend/Naxxramas/boss_maexxna.cpp
index e52731d003e..0d938122f28 100644
--- a/src/server/scripts/Northrend/Naxxramas/boss_maexxna.cpp
+++ b/src/server/scripts/Northrend/Naxxramas/boss_maexxna.cpp
@@ -18,6 +18,7 @@
#include "ScriptMgr.h"
#include "ScriptedCreature.h"
#include "PassiveAI.h"
+#include "SpellScript.h"
#include "naxxramas.h"
enum Spells
@@ -28,6 +29,14 @@ enum Spells
SPELL_NECROTIC_POISON = 28776,
SPELL_FRENZY = 54123
};
+#define SPELL_FRENZY_HELPER RAID_MODE(54123,54124)
+
+enum Emotes
+{
+ EMOTE_SPIDERS = 0,
+ EMOTE_WEB_WRAP = 1,
+ EMOTE_WEB_SPRAY = 2
+};
enum Creatures
{
@@ -35,12 +44,16 @@ enum Creatures
NPC_SPIDERLING = 17055,
};
-#define MAX_POS_WRAP 3
-const Position PosWrap[MAX_POS_WRAP] =
+#define MAX_WRAP_POSITION 7
+const Position WrapPositions[MAX_WRAP_POSITION] =
{
- {3546.796f, -3869.082f, 296.450f, 0.0f},
- {3531.271f, -3847.424f, 299.450f, 0.0f},
- {3497.067f, -3843.384f, 302.384f, 0.0f},
+ {3453.818f, -3854.651f, 308.7581f, 4.362833f},
+ {3535.042f, -3842.383f, 300.795f, 3.179324f},
+ {3538.399f, -3846.088f, 299.964f, 4.310297f},
+ {3548.464f, -3854.676f, 298.6075f, 4.546609f},
+ {3557.663f, -3870.123f, 297.5027f, 3.756433f},
+ {3560.546f, -3879.353f, 297.4843f, 2.508937f},
+ {3562.535f, -3892.507f, 298.532f, 6.022466f},
};
enum Events
@@ -51,7 +64,24 @@ enum Events
EVENT_POISON,
EVENT_WRAP,
EVENT_SUMMON,
- EVENT_FRENZY,
+};
+
+const float WEB_WRAP_MOVE_SPEED = 20.0f;
+
+struct WebTargetSelector : public std::unary_function<Unit*, bool>
+{
+ WebTargetSelector(Unit* maexxna) : _maexxna(maexxna) {}
+ bool operator()(Unit const* target) const
+ {
+ if (_maexxna->GetVictim() == target) // never target tank
+ return false;
+ if (target->HasAura(SPELL_WEB_WRAP)) // never target targets that are already webbed
+ return false;
+ return true;
+ }
+
+ private:
+ const Unit* _maexxna;
};
class boss_maexxna : public CreatureScript
@@ -66,27 +96,22 @@ public:
struct boss_maexxnaAI : public BossAI
{
- boss_maexxnaAI(Creature* creature) : BossAI(creature, BOSS_MAEXXNA)
- {
- Initialize();
- }
+ boss_maexxnaAI(Creature* creature) : BossAI(creature, BOSS_MAEXXNA) { }
- void Initialize()
+ void EnterCombat(Unit* /*who*/) override
{
- enraged = false;
+ _EnterCombat();
+ events.ScheduleEvent(EVENT_WRAP, 20 * IN_MILLISECONDS);
+ events.ScheduleEvent(EVENT_SPRAY, 40 * IN_MILLISECONDS);
+ events.ScheduleEvent(EVENT_SHOCK, urandms(5, 10));
+ events.ScheduleEvent(EVENT_POISON, urandms(10, 15));
+ events.ScheduleEvent(EVENT_SUMMON, 30 * IN_MILLISECONDS);
}
- bool enraged;
-
- void EnterCombat(Unit* /*who*/) override
+ void Reset() override
{
- _EnterCombat();
- Initialize();
- events.ScheduleEvent(EVENT_WRAP, 20000);
- events.ScheduleEvent(EVENT_SPRAY, 40000);
- events.ScheduleEvent(EVENT_SHOCK, urand(5000, 10000));
- events.ScheduleEvent(EVENT_POISON, urand(10000, 15000));
- events.ScheduleEvent(EVENT_SUMMON, 30000);
+ _Reset();
+ instance->DoRemoveAurasDueToSpellOnPlayers(SPELL_WEB_WRAP);
}
void UpdateAI(uint32 diff) override
@@ -94,10 +119,9 @@ public:
if (!UpdateVictim() || !CheckInRoom())
return;
- if (!enraged && HealthBelowPct(30))
+ if (HealthBelowPct(30) && !me->HasAura(SPELL_FRENZY_HELPER))
{
- enraged = true;
- events.ScheduleEvent(EVENT_FRENZY, 0); // will be cast immediately
+ DoCast(SPELL_FRENZY);
}
events.Update(diff);
@@ -107,41 +131,49 @@ public:
switch (eventId)
{
case EVENT_WRAP:
- /// @todo Add missing text
- for (uint8 i = 0; i < RAID_MODE(1, 2); ++i)
+ {
+ std::list<Unit*> targets;
+ SelectTargetList(targets, WebTargetSelector(me), RAID_MODE(1, 2), SELECT_TARGET_RANDOM);
+ if (!targets.empty())
{
- if (Unit* target = SelectTarget(SELECT_TARGET_RANDOM, 1, 0, true, -SPELL_WEB_WRAP))
+ Talk(EMOTE_WEB_WRAP);
+ int8 wrapPos = -1;
+ for (Unit* target : targets)
{
+ if (wrapPos == -1) // allow all positions on the first target
+ wrapPos = urand(0, MAX_WRAP_POSITION - 1);
+ else // on subsequent iterations, only allow positions that are not equal to the previous one (this is sufficient since we should only have two targets at most, ever)
+ wrapPos = (wrapPos + urand(1, MAX_WRAP_POSITION - 1)) % MAX_WRAP_POSITION;
+
target->RemoveAura(sSpellMgr->GetSpellIdForDifficulty(SPELL_WEB_SPRAY, me));
- uint8 pos = rand32() % MAX_POS_WRAP;
- target->GetMotionMaster()->MoveJump(PosWrap[pos].GetPositionX(), PosWrap[pos].GetPositionY(), PosWrap[pos].GetPositionZ(), 20, 20);
- if (Creature* wrap = DoSummon(NPC_WEB_WRAP, PosWrap[pos], 0, TEMPSUMMON_CORPSE_DESPAWN))
- wrap->AI()->SetGUID(target->GetGUID());
+ if (Creature* wrap = DoSummon(NPC_WEB_WRAP, WrapPositions[wrapPos], 70 * IN_MILLISECONDS, TEMPSUMMON_TIMED_DESPAWN))
+ {
+ wrap->AI()->SetGUID(target->GetGUID()); // handles application of debuff
+ target->GetMotionMaster()->MoveJump(WrapPositions[wrapPos], WEB_WRAP_MOVE_SPEED, WEB_WRAP_MOVE_SPEED); // move after stun to avoid stun cancelling move
+ }
}
}
events.ScheduleEvent(EVENT_WRAP, 40000);
break;
+ }
case EVENT_SPRAY:
+ Talk(EMOTE_WEB_SPRAY);
DoCastAOE(SPELL_WEB_SPRAY);
events.ScheduleEvent(EVENT_SPRAY, 40000);
break;
case EVENT_SHOCK:
DoCastAOE(SPELL_POISON_SHOCK);
- events.ScheduleEvent(EVENT_SHOCK, urand(10000, 20000));
+ events.ScheduleEvent(EVENT_SHOCK, urandms(10, 20));
break;
case EVENT_POISON:
DoCastVictim(SPELL_NECROTIC_POISON);
- events.ScheduleEvent(EVENT_POISON, urand(10000, 20000));
- break;
- case EVENT_FRENZY:
- DoCast(me, SPELL_FRENZY, true);
- events.ScheduleEvent(EVENT_FRENZY, 600000);
+ events.ScheduleEvent(EVENT_POISON, urandms(10, 20));
break;
case EVENT_SUMMON:
- /// @todo Add missing text
+ Talk(EMOTE_SPIDERS);
uint8 amount = urand(8, 10);
for (uint8 i = 0; i < amount; ++i)
- DoSummon(NPC_SPIDERLING, me, 0, TEMPSUMMON_CORPSE_DESPAWN);
+ DoSummon(NPC_SPIDERLING, me, 4.0f, 5 * IN_MILLISECONDS, TEMPSUMMON_CORPSE_TIMED_DESPAWN);
events.ScheduleEvent(EVENT_SUMMON, 40000);
break;
}
@@ -165,23 +197,49 @@ public:
struct npc_webwrapAI : public NullCreatureAI
{
- npc_webwrapAI(Creature* creature) : NullCreatureAI(creature) { }
+ npc_webwrapAI(Creature* creature) : NullCreatureAI(creature), visibleTimer(0) { }
ObjectGuid victimGUID;
+ uint32 visibleTimer;
+
+ void InitializeAI() override
+ {
+ me->SetVisible(false);
+ }
void SetGUID(ObjectGuid guid, int32 /*param*/) override
{
+ if (!guid)
+ return;
victimGUID = guid;
- if (me->m_spells[0] && victimGUID)
- if (Unit* victim = ObjectAccessor::GetUnit(*me, victimGUID))
- victim->CastSpell(victim, me->m_spells[0], true, NULL, NULL, me->GetGUID());
+ if (Unit* victim = ObjectAccessor::GetUnit(*me, victimGUID))
+ {
+ visibleTimer = (me->GetDistance2d(victim)/WEB_WRAP_MOVE_SPEED + 0.5f) * IN_MILLISECONDS;
+ victim->CastSpell(victim, SPELL_WEB_WRAP, true, NULL, NULL, me->GetGUID());
+ }
+ }
+
+ void UpdateAI(uint32 diff) override
+ {
+ if (!visibleTimer)
+ return;
+
+ if (diff >= visibleTimer)
+ {
+ visibleTimer = 0;
+ me->SetVisible(true);
+ }
+ else
+ visibleTimer -= diff;
}
void JustDied(Unit* /*killer*/) override
{
- if (me->m_spells[0] && victimGUID)
+ if (victimGUID)
if (Unit* victim = ObjectAccessor::GetUnit(*me, victimGUID))
- victim->RemoveAurasDueToSpell(me->m_spells[0], me->GetGUID());
+ victim->RemoveAurasDueToSpell(SPELL_WEB_WRAP, me->GetGUID());
+
+ me->DespawnOrUnsummon(5 * IN_MILLISECONDS);
}
};
diff --git a/src/server/scripts/Northrend/Naxxramas/boss_razuvious.cpp b/src/server/scripts/Northrend/Naxxramas/boss_razuvious.cpp
index 1683667a02a..f94f7b227bf 100644
--- a/src/server/scripts/Northrend/Naxxramas/boss_razuvious.cpp
+++ b/src/server/scripts/Northrend/Naxxramas/boss_razuvious.cpp
@@ -17,43 +17,40 @@
#include "ScriptMgr.h"
#include "ScriptedCreature.h"
+#include "SpellInfo.h"
#include "naxxramas.h"
-//Razuvious - NO TEXT sound only
-//8852 aggro01 - Hah hah, I'm just getting warmed up!
-//8853 aggro02 Stand and fight!
-//8854 aggro03 Show me what you've got!
-//8861 slay1 - You should've stayed home!
-//8863 slay2-
-//8858 cmmnd3 - You disappoint me, students!
-//8855 cmmnd1 - Do as I taught you!
-//8856 cmmnd2 - Show them no mercy!
-//8859 cmmnd4 - The time for practice is over! Show me what you've learned!
-//8861 Sweep the leg! Do you have a problem with that?
-//8860 death - An honorable... death...
-//8947 - Aggro Mixed? - ?
-
-#define SOUND_AGGRO RAND(8852, 8853, 8854)
-#define SOUND_SLAY RAND(8861, 8863)
-#define SOUND_COMMND RAND(8855, 8856, 8858, 8859, 8861)
-#define SOUND_DEATH 8860
-#define SOUND_AGGROMIX 8847
+enum Yells
+{
+ SAY_AGGRO = 0,
+ SAY_SLAY = 1,
+ SAY_TAUNTED = 2,
+ SAY_DEATH = 3
+};
enum Spells
{
- SPELL_UNBALANCING_STRIKE = 26613,
- SPELL_DISRUPTING_SHOUT = 29107,
- SPELL_JAGGED_KNIFE = 55550,
- SPELL_HOPELESS = 29125
+ SPELL_UNBALANCING_STRIKE = 26613,
+ SPELL_DISRUPTING_SHOUT = 29107,
+ SPELL_JAGGED_KNIFE = 55550,
+ SPELL_HOPELESS = 29125,
+ SPELL_UNDERSTUDY_TAUNT = 29060,
+ SPELL_UNDERSTUDY_BLOOD_STRIKE = 61696,
+ SPELL_FORCE_OBEDIENCE = 55479
};
enum Events
{
- EVENT_NONE,
+ EVENT_ATTACK = 1,
EVENT_STRIKE,
EVENT_SHOUT,
- EVENT_KNIFE,
- EVENT_COMMAND,
+ EVENT_KNIFE
+};
+
+enum SummonGroups
+{
+ SUMMON_GROUP_10MAN = 1,
+ SUMMON_GROUP_25MAN = 2
};
class boss_razuvious : public CreatureScript
@@ -70,36 +67,60 @@ public:
{
boss_razuviousAI(Creature* creature) : BossAI(creature, BOSS_RAZUVIOUS) { }
- void KilledUnit(Unit* /*victim*/) override
+ void SummonAdds()
{
- if (!(rand32() % 3))
- DoPlaySoundToSet(me, SOUND_SLAY);
+ me->SummonCreatureGroup(SUMMON_GROUP_10MAN);
+ if (Is25ManRaid())
+ me->SummonCreatureGroup(SUMMON_GROUP_25MAN);
}
- void DamageTaken(Unit* pDone_by, uint32& uiDamage) override
+ void InitializeAI() override
{
- // Damage done by the controlled Death Knight understudies should also count toward damage done by players
- if (pDone_by->GetTypeId() == TYPEID_UNIT && (pDone_by->GetEntry() == 16803 || pDone_by->GetEntry() == 29941))
+ if (!me->isDead())
{
- me->LowerPlayerDamageReq(uiDamage);
+ Reset();
+ SummonAdds();
}
}
+ void JustReachedHome() override
+ {
+ _JustReachedHome();
+ SummonAdds();
+ me->GetMotionMaster()->Initialize();
+ }
+
+ void KilledUnit(Unit* victim) override
+ {
+ if (victim->GetTypeId() == TYPEID_PLAYER || (victim->GetTypeId() == TYPEID_UNIT && victim->GetEntry() == NPC_DK_UNDERSTUDY))
+ Talk(SAY_SLAY);
+ }
+
+ void SpellHit(Unit* caster, SpellInfo const* spell) override
+ {
+ if (spell->Id == SPELL_UNDERSTUDY_TAUNT)
+ Talk(SAY_TAUNTED, caster);
+ }
+
void JustDied(Unit* /*killer*/) override
{
- _JustDied();
- DoPlaySoundToSet(me, SOUND_DEATH);
- me->CastSpell(me, SPELL_HOPELESS, true); /// @todo this may affect other creatures
+ Talk(SAY_DEATH);
+ DoCastAOE(SPELL_HOPELESS, true);
+
+ events.Reset();
+ instance->SetBossState(BOSS_RAZUVIOUS, DONE);
}
void EnterCombat(Unit* /*who*/) override
{
_EnterCombat();
- DoPlaySoundToSet(me, SOUND_AGGRO);
- events.ScheduleEvent(EVENT_STRIKE, 30000);
- events.ScheduleEvent(EVENT_SHOUT, 25000);
- events.ScheduleEvent(EVENT_COMMAND, 40000);
- events.ScheduleEvent(EVENT_KNIFE, 10000);
+ me->StopMoving();
+ summons.DoZoneInCombat();
+ Talk(SAY_AGGRO);
+ events.ScheduleEvent(EVENT_ATTACK, 7 * IN_MILLISECONDS);
+ events.ScheduleEvent(EVENT_STRIKE, 21 * IN_MILLISECONDS);
+ events.ScheduleEvent(EVENT_SHOUT, 16 * IN_MILLISECONDS);
+ events.ScheduleEvent(EVENT_KNIFE, 10 * IN_MILLISECONDS);
}
void UpdateAI(uint32 diff) override
@@ -113,33 +134,112 @@ public:
{
switch (eventId)
{
+ case EVENT_ATTACK:
+ SetCombatMovement(true);
+ if (Unit* victim = me->GetVictim())
+ me->GetMotionMaster()->MoveChase(victim);
+ break;
case EVENT_STRIKE:
DoCastVictim(SPELL_UNBALANCING_STRIKE);
- events.ScheduleEvent(EVENT_STRIKE, 30000);
+ events.ScheduleEvent(EVENT_STRIKE, 6 * IN_MILLISECONDS);
return;
case EVENT_SHOUT:
DoCastAOE(SPELL_DISRUPTING_SHOUT);
- events.ScheduleEvent(EVENT_SHOUT, 25000);
+ events.ScheduleEvent(EVENT_SHOUT, 16 * IN_MILLISECONDS);
return;
case EVENT_KNIFE:
if (Unit* target = SelectTarget(SELECT_TARGET_RANDOM, 0, 45.0f))
DoCast(target, SPELL_JAGGED_KNIFE);
- events.ScheduleEvent(EVENT_KNIFE, 10000);
- return;
- case EVENT_COMMAND:
- DoPlaySoundToSet(me, SOUND_COMMND);
- events.ScheduleEvent(EVENT_COMMAND, 40000);
+ events.ScheduleEvent(EVENT_KNIFE, urandms(10,15));
return;
}
}
DoMeleeAttackIfReady();
}
+
+ void Reset() override
+ {
+ SetCombatMovement(false);
+ _Reset();
+ }
};
};
+class npc_dk_understudy : public CreatureScript
+{
+ public:
+ npc_dk_understudy() : CreatureScript("npc_dk_understudy") { }
+
+ struct npc_dk_understudyAI : public ScriptedAI
+ {
+ npc_dk_understudyAI(Creature* creature) : ScriptedAI(creature), _instance(creature->GetInstanceScript()), bloodStrikeTimer(0) { }
+
+ void EnterCombat(Unit* /*who*/) override
+ {
+ me->SetUInt32Value(UNIT_NPC_EMOTESTATE, EMOTE_ONESHOT_NONE);
+ if (Creature* razuvious = ObjectAccessor::GetCreature(*me, _instance->GetGuidData(DATA_RAZUVIOUS)))
+ razuvious->AI()->DoZoneInCombat(nullptr, 250.0f);
+ }
+
+ void JustReachedHome() override
+ {
+ if (_instance->GetBossState(BOSS_RAZUVIOUS) == DONE)
+ me->DespawnOrUnsummon();
+ else
+ ScriptedAI::JustReachedHome();
+ }
+
+ void UpdateAI(uint32 diff) override
+ {
+ if (!me->isPossessedByPlayer() && !UpdateVictim())
+ return;
+
+ if (!me->isPossessedByPlayer())
+ {
+ if (diff < bloodStrikeTimer)
+ bloodStrikeTimer -= diff;
+ else
+ DoCastVictim(SPELL_UNDERSTUDY_BLOOD_STRIKE);
+ }
+
+ DoMeleeAttackIfReady();
+ }
+
+ void OnCharmed(bool apply) override
+ {
+ ScriptedAI::OnCharmed(apply);
+ if (apply)
+ {
+ if (!me->IsInCombat())
+ EnterCombat(nullptr);
+ me->StopMoving();
+ me->SetReactState(REACT_PASSIVE);
+ _charmer = me->GetCharmerGUID();
+ }
+ else
+ {
+ me->SetReactState(REACT_AGGRESSIVE);
+ if (Unit* charmer = ObjectAccessor::GetUnit(*me, _charmer))
+ me->AddThreat(charmer, 100000.0f);
+ DoZoneInCombat(nullptr, 250.0f);
+ }
+ }
+ private:
+ InstanceScript* const _instance;
+ ObjectGuid _charmer;
+ uint32 bloodStrikeTimer;
+ };
+
+ CreatureAI* GetAI(Creature* creature) const override
+ {
+ return GetInstanceAI<npc_dk_understudyAI>(creature);
+ }
+};
+
void AddSC_boss_razuvious()
{
new boss_razuvious();
+ new npc_dk_understudy();
}
diff --git a/src/server/scripts/Northrend/Naxxramas/instance_naxxramas.cpp b/src/server/scripts/Northrend/Naxxramas/instance_naxxramas.cpp
index 53ce68d3efc..0e572835a51 100644
--- a/src/server/scripts/Northrend/Naxxramas/instance_naxxramas.cpp
+++ b/src/server/scripts/Northrend/Naxxramas/instance_naxxramas.cpp
@@ -60,7 +60,6 @@ DoorData const doorData[] =
MinionData const minionData[] =
{
- { NPC_DK_UNDERSTUDY, BOSS_RAZUVIOUS },
{ NPC_SIR, BOSS_HORSEMEN },
{ NPC_THANE, BOSS_HORSEMEN },
{ NPC_LADY, BOSS_HORSEMEN },
@@ -143,6 +142,9 @@ class instance_naxxramas : public InstanceMapScript
case NPC_FAERLINA:
FaerlinaGUID = creature->GetGUID();
break;
+ case NPC_RAZUVIOUS:
+ RazuviousGUID = creature->GetGUID();
+ break;
case NPC_THANE:
ThaneGUID = creature->GetGUID();
break;
@@ -378,6 +380,8 @@ class instance_naxxramas : public InstanceMapScript
return AnubRekhanGUID;
case DATA_FAERLINA:
return FaerlinaGUID;
+ case DATA_RAZUVIOUS:
+ return RazuviousGUID;
case DATA_THANE:
return ThaneGUID;
case DATA_LADY:
@@ -652,6 +656,8 @@ class instance_naxxramas : public InstanceMapScript
ObjectGuid HeiganGUID;
/* The Military Quarter */
+ // Instructor Razuvious
+ ObjectGuid RazuviousGUID;
// Gothik the Harvester
ObjectGuid GothikGateGUID;
// The Four Horsemen
diff --git a/src/server/scripts/Northrend/Naxxramas/naxxramas.h b/src/server/scripts/Northrend/Naxxramas/naxxramas.h
index d2b99784953..e4d15cf84ba 100644
--- a/src/server/scripts/Northrend/Naxxramas/naxxramas.h
+++ b/src/server/scripts/Northrend/Naxxramas/naxxramas.h
@@ -66,6 +66,7 @@ enum Data64
{
DATA_ANUBREKHAN,
DATA_FAERLINA,
+ DATA_RAZUVIOUS,
DATA_THANE,
DATA_LADY,
DATA_BARON,
@@ -87,6 +88,7 @@ enum CreaturesIds
{
NPC_ANUBREKHAN = 15956,
NPC_FAERLINA = 15953,
+ NPC_RAZUVIOUS = 16061,
NPC_THANE = 16064,
NPC_LADY = 16065,
NPC_BARON = 30549,
diff --git a/src/server/scripts/Pet/pet_mage.cpp b/src/server/scripts/Pet/pet_mage.cpp
index 0d6353cfb86..14d2687c298 100644
--- a/src/server/scripts/Pet/pet_mage.cpp
+++ b/src/server/scripts/Pet/pet_mage.cpp
@@ -24,11 +24,25 @@
#include "ScriptedCreature.h"
#include "CombatAI.h"
#include "Pet.h"
+#include "PetAI.h"
+#include "Cell.h"
+#include "CellImpl.h"
+#include "GridNotifiers.h"
+#include "GridNotifiersImpl.h"
enum MageSpells
{
SPELL_MAGE_CLONE_ME = 45204,
- SPELL_MAGE_MASTERS_THREAT_LIST = 58838
+ SPELL_MAGE_MASTERS_THREAT_LIST = 58838,
+ SPELL_MAGE_FROST_BOLT = 59638,
+ SPELL_MAGE_FIRE_BLAST = 59637
+};
+
+enum MirrorImageTimers
+{
+ TIMER_MIRROR_IMAGE_INIT = 0,
+ TIMER_MIRROR_IMAGE_FROST_BOLT = 4000,
+ TIMER_MIRROR_IMAGE_FIRE_BLAST = 6000
};
class npc_pet_mage_mirror_image : public CreatureScript
@@ -40,20 +54,184 @@ class npc_pet_mage_mirror_image : public CreatureScript
{
npc_pet_mage_mirror_imageAI(Creature* creature) : CasterAI(creature) { }
+ void Init()
+ {
+ Unit* owner = me->GetCharmerOrOwner();
+
+ std::list<Unit*> targets;
+ Trinity::AnyUnfriendlyUnitInObjectRangeCheck u_check(me, me, 30.0f);
+ Trinity::UnitListSearcher<Trinity::AnyUnfriendlyUnitInObjectRangeCheck> searcher(me, targets, u_check);
+ me->VisitNearbyObject(40.0f, searcher);
+
+ Unit* highestThreatUnit = nullptr;
+ float highestThreat = 0.0f;
+ Unit* nearestPlayer = nullptr;
+ for (std::list<Unit*>::const_iterator iter = targets.begin(); iter != targets.end(); ++iter)
+ {
+ // Consider only units without CC
+ if (!(*iter)->HasBreakableByDamageCrowdControlAura((*iter)))
+ {
+ // Take first found unit
+ if (!highestThreatUnit && (*iter)->GetTypeId() != TYPEID_PLAYER)
+ {
+ highestThreatUnit = (*iter);
+ continue;
+ }
+ if (!nearestPlayer && ((*iter)->GetTypeId() == TYPEID_PLAYER))
+ {
+ nearestPlayer = (*iter);
+ continue;
+ }
+ // else compare best fit unit with current unit
+ ThreatContainer::StorageType triggers = (*iter)->getThreatManager().getThreatList();
+ for (ThreatContainer::StorageType::const_iterator trig_citr = triggers.begin(); trig_citr != triggers.end(); ++trig_citr)
+ {
+ // Try to find threat referenced to owner
+ if ((*trig_citr)->getTarget() == owner)
+ {
+ // Check if best fit hostile unit hs lower threat than this current unit
+ if (highestThreat < (*trig_citr)->getThreat())
+ {
+ // If so, update best fit unit
+ highestThreat = (*trig_citr)->getThreat();
+ highestThreatUnit = (*iter);
+ break;
+ }
+ }
+ }
+ // In case no unit with threat was found so far, always check for nearest unit (only for players)
+ if ((*iter)->GetTypeId() == TYPEID_PLAYER)
+ {
+ // If this player is closer than the previous one, update it
+ if (me->GetDistance((*iter)->GetPosition()) < me->GetDistance(nearestPlayer->GetPosition()))
+ nearestPlayer = (*iter);
+ }
+ }
+ }
+ // Prioritize units with threat referenced to owner
+ if (highestThreat > 0.0f && highestThreatUnit)
+ me->Attack(highestThreatUnit, false);
+ // If there is no such target, try to attack nearest hostile unit if such exists
+ else if (nearestPlayer)
+ me->Attack(nearestPlayer, false);
+ }
+
+ bool IsInThreatList(Unit* target)
+ {
+ Unit* owner = me->GetCharmerOrOwner();
+
+ std::list<Unit*> targets;
+ Trinity::AnyUnfriendlyUnitInObjectRangeCheck u_check(me, me, 30.0f);
+ Trinity::UnitListSearcher<Trinity::AnyUnfriendlyUnitInObjectRangeCheck> searcher(me, targets, u_check);
+ me->VisitNearbyObject(40.0f, searcher);
+
+ for (std::list<Unit*>::const_iterator iter = targets.begin(); iter != targets.end(); ++iter)
+ {
+ if ((*iter) == target)
+ {
+ // Consider only units without CC
+ if (!(*iter)->HasBreakableByDamageCrowdControlAura((*iter)))
+ {
+ ThreatContainer::StorageType triggers = (*iter)->getThreatManager().getThreatList();
+ for (ThreatContainer::StorageType::const_iterator trig_citr = triggers.begin(); trig_citr != triggers.end(); ++trig_citr)
+ {
+ // Try to find threat referenced to owner
+ if ((*trig_citr)->getTarget() == owner)
+ return true;
+ }
+ }
+ }
+ }
+ return false;
+ }
+
void InitializeAI() override
{
CasterAI::InitializeAI();
Unit* owner = me->GetOwner();
if (!owner)
return;
- // Inherit Master's Threat List (not yet implemented)
- owner->CastSpell((Unit*)NULL, SPELL_MAGE_MASTERS_THREAT_LIST, true);
+
// here mirror image casts on summoner spell (not present in client dbc) 49866
// here should be auras (not present in client dbc): 35657, 35658, 35659, 35660 selfcast by mirror images (stats related?)
// Clone Me!
owner->CastSpell(me, SPELL_MAGE_CLONE_ME, false);
}
+ void EnterCombat(Unit* who) override
+ {
+ if (me->GetVictim() && !me->GetVictim()->HasBreakableByDamageCrowdControlAura(me))
+ {
+ me->CastSpell(who, SPELL_MAGE_FIRE_BLAST, false);
+ events.ScheduleEvent(SPELL_MAGE_FROST_BOLT, TIMER_MIRROR_IMAGE_INIT);
+ events.ScheduleEvent(SPELL_MAGE_FIRE_BLAST, TIMER_MIRROR_IMAGE_FIRE_BLAST);
+ }
+ else
+ EnterEvadeMode();
+ }
+
+ void Reset() override
+ {
+ events.Reset();
+ }
+
+ void UpdateAI(uint32 diff) override
+ {
+ Unit* owner = me->GetCharmerOrOwner();
+ Unit* target = owner->getAttackerForHelper();
+
+ events.Update(diff);
+
+ // prevent CC interrupts by images
+ if (me->GetVictim() && me->EnsureVictim()->HasBreakableByDamageCrowdControlAura(me))
+ {
+ me->InterruptNonMeleeSpells(false);
+ return;
+ }
+
+ if (me->HasUnitState(UNIT_STATE_CASTING))
+ return;
+
+ if (!owner)
+ return;
+
+ // assign target if image doesnt have any or the target is not actual
+ if (!target || me->GetVictim() != target)
+ {
+ Unit* ownerTarget = nullptr;
+ if (Player* owner = me->GetCharmerOrOwner()->ToPlayer())
+ ownerTarget = owner->GetSelectedUnit();
+
+ // recognize which victim will be choosen
+ if (ownerTarget && ownerTarget->GetTypeId() == TYPEID_PLAYER)
+ {
+ if (!ownerTarget->HasBreakableByDamageCrowdControlAura(ownerTarget))
+ me->Attack(ownerTarget, false);
+ }
+ else if (ownerTarget && (ownerTarget->GetTypeId() != TYPEID_PLAYER) && IsInThreatList(ownerTarget))
+ {
+ if (!ownerTarget->HasBreakableByDamageCrowdControlAura(ownerTarget))
+ me->Attack(ownerTarget, false);
+ }
+ else
+ Init();
+ }
+
+ if (uint32 spellId = events.ExecuteEvent())
+ {
+ if (spellId == SPELL_MAGE_FROST_BOLT)
+ {
+ events.ScheduleEvent(SPELL_MAGE_FROST_BOLT, TIMER_MIRROR_IMAGE_FROST_BOLT);
+ DoCastVictim(spellId);
+ }
+ else if (spellId == SPELL_MAGE_FIRE_BLAST)
+ {
+ DoCastVictim(spellId);
+ events.ScheduleEvent(SPELL_MAGE_FIRE_BLAST, TIMER_MIRROR_IMAGE_FIRE_BLAST);
+ }
+ }
+ }
+
// Do not reload Creature templates on evade mode enter - prevent visual lost
void EnterEvadeMode() override
{
@@ -68,6 +246,7 @@ class npc_pet_mage_mirror_image : public CreatureScript
me->GetMotionMaster()->Clear(false);
me->GetMotionMaster()->MoveFollow(owner, PET_FOLLOW_DIST, me->GetFollowAngle(), MOTION_SLOT_ACTIVE);
}
+ Init();
}
};