diff --git a/sql/updates/world/4.3.4/2020_10_29_01_world.sql b/sql/updates/world/4.3.4/2020_10_29_01_world.sql
new file mode 100644
index 00000000000..be436104555
--- /dev/null
+++ b/sql/updates/world/4.3.4/2020_10_29_01_world.sql
@@ -0,0 +1,13 @@
+UPDATE `creature_template` SET `ScriptName`= 'npc_scarlet_commander_mograine' WHERE `entry`= 3976;
+UPDATE `creature_template_addon` SET `auras`= '' WHERE `entry`= 3976;
+
+UPDATE `creature_template` SET `ScriptName`= 'npc_high_inquisitor_whitemane', `minlevel`= 40, `maxlevel`= 40 WHERE `entry`= 3977;
+
+DELETE FROM `spawn_group_template` WHERE `groupId`= 451;
+INSERT INTO `spawn_group_template` (`groupId`, `groupName`, `groupFlags`) VALUES
+(451, 'The Scarlet Monastery - Mograine and Whitemane', 4);
+
+DELETE FROM `spawn_group` WHERE `groupId`= 451;
+INSERT INTO `spawn_group` (`groupId`, `spawnType`, `spawnId`) VALUES
+(451, 0, 39946),
+(451, 0, 40029);
diff --git a/src/server/scripts/EasternKingdoms/ScarletMonastery/boss_arcanist_doan.cpp b/src/server/scripts/EasternKingdoms/ScarletMonastery/boss_arcanist_doan.cpp
index 66c87d65c02..e20aa3bfcb5 100644
--- a/src/server/scripts/EasternKingdoms/ScarletMonastery/boss_arcanist_doan.cpp
+++ b/src/server/scripts/EasternKingdoms/ScarletMonastery/boss_arcanist_doan.cpp
@@ -123,5 +123,5 @@ private:
void AddSC_boss_arcanist_doan()
{
- RegisterScarletMonastryCreatureAI(boss_arcanist_doan);
+ RegisterScarletMonasteryCreatureAI(boss_arcanist_doan);
}
diff --git a/src/server/scripts/EasternKingdoms/ScarletMonastery/boss_bloodmage_thalnos.cpp b/src/server/scripts/EasternKingdoms/ScarletMonastery/boss_bloodmage_thalnos.cpp
index 5543ed79748..bbe56d58b3a 100644
--- a/src/server/scripts/EasternKingdoms/ScarletMonastery/boss_bloodmage_thalnos.cpp
+++ b/src/server/scripts/EasternKingdoms/ScarletMonastery/boss_bloodmage_thalnos.cpp
@@ -180,5 +180,5 @@ private:
void AddSC_boss_bloodmage_thalnos()
{
- RegisterScarletMonastryCreatureAI(boss_bloodmage_thalnos);
+ RegisterScarletMonasteryCreatureAI(boss_bloodmage_thalnos);
}
diff --git a/src/server/scripts/EasternKingdoms/ScarletMonastery/boss_houndmaster_loksey.cpp b/src/server/scripts/EasternKingdoms/ScarletMonastery/boss_houndmaster_loksey.cpp
index 365801db0a9..7c0e749e993 100644
--- a/src/server/scripts/EasternKingdoms/ScarletMonastery/boss_houndmaster_loksey.cpp
+++ b/src/server/scripts/EasternKingdoms/ScarletMonastery/boss_houndmaster_loksey.cpp
@@ -97,5 +97,5 @@ struct boss_houndmaster_loksey : public BossAI
void AddSC_boss_houndmaster_loksey()
{
- RegisterScarletMonastryCreatureAI(boss_houndmaster_loksey);
+ RegisterScarletMonasteryCreatureAI(boss_houndmaster_loksey);
}
diff --git a/src/server/scripts/EasternKingdoms/ScarletMonastery/boss_interrogator_vishas.cpp b/src/server/scripts/EasternKingdoms/ScarletMonastery/boss_interrogator_vishas.cpp
index 5d5e0bb6c6c..8a98503d136 100644
--- a/src/server/scripts/EasternKingdoms/ScarletMonastery/boss_interrogator_vishas.cpp
+++ b/src/server/scripts/EasternKingdoms/ScarletMonastery/boss_interrogator_vishas.cpp
@@ -108,5 +108,5 @@ private:
void AddSC_boss_interrogator_vishas()
{
- RegisterScarletMonastryCreatureAI(boss_interrogator_vishas);
+ RegisterScarletMonasteryCreatureAI(boss_interrogator_vishas);
}
diff --git a/src/server/scripts/EasternKingdoms/ScarletMonastery/boss_mograine_and_whitemane.cpp b/src/server/scripts/EasternKingdoms/ScarletMonastery/boss_mograine_and_whitemane.cpp
index 325209f60da..2929936dfe1 100644
--- a/src/server/scripts/EasternKingdoms/ScarletMonastery/boss_mograine_and_whitemane.cpp
+++ b/src/server/scripts/EasternKingdoms/ScarletMonastery/boss_mograine_and_whitemane.cpp
@@ -15,366 +15,404 @@
* with this program. If not, see .
*/
-/* ScriptData
-SDName: Boss_Mograine_And_Whitemane
-SD%Complete: 90
-SDComment:
-SDCategory: Scarlet Monastery
-EndScriptData */
-
#include "ScriptMgr.h"
+#include "GameObject.h"
#include "InstanceScript.h"
#include "MotionMaster.h"
#include "ObjectAccessor.h"
#include "scarlet_monastery.h"
#include "ScriptedCreature.h"
+#include "Spell.h"
#include "SpellInfo.h"
enum Says
{
- //Mograine says
+ // Scarlet Commander Mograine
SAY_MO_AGGRO = 0,
SAY_MO_KILL = 1,
SAY_MO_RESURRECTED = 2,
- //Whitemane says
+ // High Inquisitor Whitemane
SAY_WH_INTRO = 0,
SAY_WH_KILL = 1,
- SAY_WH_RESURRECT = 2,
+ SAY_WH_RESURRECT = 2
};
enum Spells
{
- //Mograine Spells
- SPELL_CRUSADERSTRIKE = 14518,
- SPELL_HAMMEROFJUSTICE = 5589,
- SPELL_LAYONHANDS = 9257,
- SPELL_RETRIBUTIONAURA = 8990,
+ // Scarlet Commander Mograine
+ SPELL_CRUSADER_STRIKE = 14518,
+ SPELL_HAMMER_OF_JUSTICE = 77787,
+ SPELL_DIVINE_SHIELD = 63148,
+ SPELL_LAY_ON_HANDS = 9257,
+ SPELL_RETRIBUTION_AURA = 8990,
- //Whitemanes Spells
- SPELL_DEEPSLEEP = 9256,
- SPELL_SCARLETRESURRECTION = 9232,
- SPELL_DOMINATEMIND = 14515,
- SPELL_HOLYSMITE = 9481,
- SPELL_HEAL = 12039,
- SPELL_POWERWORDSHIELD = 22187
+ // High Inquisitor Whitemane
+ SPELL_HOLY_SMITE = 25054,
+ SPELL_DEEP_SLEEP = 9256,
+ SPELL_SCARLET_RESURRECTION = 9232,
+ SPELL_HEAL = 12039,
+ SPELL_POWER_WORD_SHIELD = 22187
};
-class boss_scarlet_commander_mograine : public CreatureScript
+enum Events
{
-public:
- boss_scarlet_commander_mograine() : CreatureScript("boss_scarlet_commander_mograine") { }
+ // Scarlet Commander Mograine
+ EVENT_RESURRECTED = 1,
+ EVENT_HAMMER_OF_JUSTICE,
+ EVENT_CRUSADER_STRIKE,
+ EVENT_DIVINE_SHIELD,
+ EVENT_RETRIBUTION_AURA,
- struct boss_scarlet_commander_mograineAI : public ScriptedAI
+ // High Inquisitor Whitemane
+ EVENT_HOLY_SMITE,
+ EVENT_DEEP_SLEEP,
+ EVENT_SCARLET_RESURRECTION,
+ EVENT_SALUTE_EMOTE,
+ EVENT_REENGAGE_PLAYERS,
+ EVENT_HEAL,
+ EVENT_POWER_WORD_SHIELD
+};
+
+enum Actions
+{
+ ACTION_MOGRAINE_DIED = 1,
+ ACTION_RESURRECTED
+};
+
+enum Points
+{
+ POINT_NONE = 0,
+ POINT_RESURRECT_MOGRAINE
+};
+
+enum Misc
+{
+ SOUND_ID_MOGRAINE_DEATH = 1326
+};
+
+Position const WhitemaneIntroPosition = { 1150.1221f, 1397.4794f, 32.337616f };
+
+struct npc_scarlet_commander_mograine : public ScriptedAI
+{
+ npc_scarlet_commander_mograine(Creature* creature) : ScriptedAI(creature), _resurrected(false), _killed(false) { }
+
+ void InitializeAI() override
{
- boss_scarlet_commander_mograineAI(Creature* creature) : ScriptedAI(creature)
- {
- Initialize();
- instance = creature->GetInstanceScript();
- }
+ _instance = me->GetInstanceScript();
+ }
- void Initialize()
- {
- CrusaderStrike_Timer = 10000;
- HammerOfJustice_Timer = 10000;
- _bHasDied = false;
- _bHeal = false;
- _bFakeDeath = false;
- }
+ void JustAppeared() override
+ {
+ DoCastSelf(SPELL_RETRIBUTION_AURA);
+ }
- InstanceScript* instance;
+ void JustEngagedWith(Unit* /*who*/) override
+ {
+ Talk(SAY_MO_AGGRO);
+ _instance->SetBossState(DATA_MOGRAINE_AND_WHITEMANE, IN_PROGRESS);
+ me->CallForHelp(VISIBLE_RANGE);
+ }
- uint32 CrusaderStrike_Timer;
- uint32 HammerOfJustice_Timer;
+ void EnterEvadeMode(EvadeReason /*why*/) override
+ {
+ _EnterEvadeMode();
+ // The Instance Script will take care of the reset
+ _instance->SetBossState(DATA_MOGRAINE_AND_WHITEMANE, FAIL);
+ }
- bool _bHasDied;
- bool _bHeal;
- bool _bFakeDeath;
-
- void Reset() override
- {
- Initialize();
-
- //Incase wipe during phase that mograine fake death
- me->RemoveFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NON_ATTACKABLE);
- me->RemoveFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NOT_SELECTABLE);
- me->SetStandState(UNIT_STAND_STATE_STAND);
-
- if (me->IsAlive())
- instance->SetBossState(DATA_MOGRAINE_AND_WHITE_EVENT, NOT_STARTED);
- }
-
- void JustReachedHome() override
- {
- if (instance->GetBossState(DATA_MOGRAINE_AND_WHITE_EVENT) != NOT_STARTED)
- instance->SetBossState(DATA_MOGRAINE_AND_WHITE_EVENT, FAIL);
- }
-
- void JustEngagedWith(Unit* /*who*/) override
- {
- Talk(SAY_MO_AGGRO);
- DoCast(me, SPELL_RETRIBUTIONAURA);
-
- me->CallForHelp(VISIBLE_RANGE);
- }
-
- void KilledUnit(Unit* /*victim*/) override
- {
+ void KilledUnit(Unit* who) override
+ {
+ if (who->IsPlayer())
Talk(SAY_MO_KILL);
- }
+ }
- void DamageTaken(Unit* /*doneBy*/, uint32 &damage) override
+ void JustDied(Unit* /*killer*/) override
+ {
+ _events.Reset();
+ if (Creature* whitemane = _instance->GetCreature(DATA_HIGH_INQUISITOR_WHITEMANE))
+ if (whitemane->isDead())
+ _instance->SetBossState(DATA_MOGRAINE_AND_WHITEMANE, DONE);
+ }
+
+ void DamageTaken(Unit* /*attacker*/, uint32& damage) override
+ {
+ // Mograine cannot die when he has not been resurrected yet.
+ if (!_resurrected && damage >= me->GetHealth())
+ damage = me->GetHealth() - 1;
+
+ if (!_killed && !_resurrected && me->HealthBelowPctDamaged(1, damage))
{
- if (damage < me->GetHealth() || _bHasDied || _bFakeDeath)
- return;
+ _killed = true;
+ me->AttackStop();
+ me->SetReactState(REACT_PASSIVE);
+ me->PlayDistanceSound(SOUND_ID_MOGRAINE_DEATH);
+ me->SetFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NOT_SELECTABLE);
+ me->SetImmuneToPC(true, true);
+ me->SetStandState(UNIT_STAND_STATE_DEAD);
+ me->RemoveAllAuras();
- //On first death, fake death and open door, as well as initiate whitemane if exist
- if (Unit* Whitemane = ObjectAccessor::GetUnit(*me, instance->GetGuidData(DATA_WHITEMANE)))
- {
- instance->SetBossState(DATA_MOGRAINE_AND_WHITE_EVENT, IN_PROGRESS);
-
- Whitemane->GetMotionMaster()->MovePoint(1, 1163.113370f, 1398.856812f, 32.527786f);
-
- me->GetMotionMaster()->MovementExpired();
- me->GetMotionMaster()->MoveIdle();
-
- me->SetHealth(0);
-
- if (me->IsNonMeleeSpellCast(false))
- me->InterruptNonMeleeSpells(false);
-
- me->ClearComboPointHolders();
- me->RemoveAllAuras();
- me->ClearAllReactives();
-
- me->SetFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NOT_SELECTABLE);
- me->SetStandState(UNIT_STAND_STATE_DEAD);
-
- _bHasDied = true;
- _bFakeDeath = true;
-
- damage = 0;
- }
+ if (Creature* whitemane = _instance->GetCreature(DATA_HIGH_INQUISITOR_WHITEMANE))
+ if (whitemane->IsAIEnabled)
+ whitemane->AI()->DoAction(ACTION_MOGRAINE_DIED);
}
+ }
- void SpellHit(Unit* /*who*/, SpellInfo const* spell) override
+ void DoAction(int32 action) override
+ {
+ switch (action)
{
- //When hit with resurrection say text
- if (spell->Id == SPELL_SCARLETRESURRECTION)
- {
- Talk(SAY_MO_RESURRECTED);
- _bFakeDeath = false;
-
- instance->SetBossState(DATA_MOGRAINE_AND_WHITE_EVENT, SPECIAL);
- }
+ case ACTION_RESURRECTED:
+ _events.ScheduleEvent(EVENT_RESURRECTED, 3s + 500ms);
+ break;
+ default:
+ break;
}
+ }
- void UpdateAI(uint32 diff) override
+ void UpdateAI(uint32 diff) override
+ {
+ if (!_killed && !UpdateVictim())
+ return;
+
+ _events.Update(diff);
+
+ if (me->HasUnitState(UNIT_STATE_CASTING))
+ return;
+
+ while (uint32 eventId = _events.ExecuteEvent())
{
- if (!UpdateVictim())
- return;
-
- if (_bHasDied && !_bHeal && instance->GetBossState(DATA_MOGRAINE_AND_WHITE_EVENT) == SPECIAL)
+ switch (eventId)
{
- //On resurrection, stop fake death and heal whitemane and resume fight
- if (Unit* Whitemane = ObjectAccessor::GetUnit(*me, instance->GetGuidData(DATA_WHITEMANE)))
- {
+ case EVENT_RESURRECTED:
+ Talk(SAY_MO_RESURRECTED);
me->RemoveFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NOT_SELECTABLE);
+ me->SetImmuneToPC(false, true);
me->SetStandState(UNIT_STAND_STATE_STAND);
- DoCast(Whitemane, SPELL_LAYONHANDS);
+ me->SetReactState(REACT_AGGRESSIVE);
+ DoCastSelf(SPELL_LAY_ON_HANDS);
+ _resurrected = true;
+ _killed = false;
- CrusaderStrike_Timer = 10000;
- HammerOfJustice_Timer = 10000;
-
- if (me->GetVictim())
- me->GetMotionMaster()->MoveChase(me->GetVictim());
-
- _bHeal = true;
- }
+ _events.ScheduleEvent(EVENT_HAMMER_OF_JUSTICE, 6s);
+ _events.ScheduleEvent(EVENT_RETRIBUTION_AURA, 7s);
+ _events.ScheduleEvent(EVENT_CRUSADER_STRIKE, 20s);
+ _events.ScheduleEvent(EVENT_DIVINE_SHIELD, 29s);
+ break;
+ case EVENT_HAMMER_OF_JUSTICE:
+ DoCastVictim(SPELL_HAMMER_OF_JUSTICE);
+ _events.Repeat(8s, 10s);
+ break;
+ case EVENT_CRUSADER_STRIKE:
+ DoCastVictim(SPELL_CRUSADER_STRIKE);
+ _events.Repeat(6s);
+ break;
+ case EVENT_DIVINE_SHIELD:
+ DoCastSelf(SPELL_DIVINE_SHIELD);
+ // @todo: repeat timer
+ break;
+ case EVENT_RETRIBUTION_AURA:
+ DoCastSelf(SPELL_RETRIBUTION_AURA);
+ break;
+ default:
+ break;
}
- //This if-check to make sure mograine does not attack while fake death
- if (_bFakeDeath)
+ if (me->HasUnitState(UNIT_STATE_CASTING))
return;
-
- //CrusaderStrike_Timer
- if (CrusaderStrike_Timer <= diff)
- {
- DoCastVictim(SPELL_CRUSADERSTRIKE);
- CrusaderStrike_Timer = 10000;
- }
- else CrusaderStrike_Timer -= diff;
-
- //HammerOfJustice_Timer
- if (HammerOfJustice_Timer <= diff)
- {
- DoCastVictim(SPELL_HAMMEROFJUSTICE);
- HammerOfJustice_Timer = 60000;
- }
- else HammerOfJustice_Timer -= diff;
-
- DoMeleeAttackIfReady();
}
- };
- CreatureAI* GetAI(Creature* creature) const override
- {
- return GetScarletMonasteryAI(creature);
+ DoMeleeAttackIfReady();
}
+private:
+ InstanceScript* _instance;
+ EventMap _events;
+ bool _resurrected;
+ bool _killed;
};
-class boss_high_inquisitor_whitemane : public CreatureScript
+struct npc_high_inquisitor_whitemane : public ScriptedAI
{
-public:
- boss_high_inquisitor_whitemane() : CreatureScript("boss_high_inquisitor_whitemane") { }
+ npc_high_inquisitor_whitemane(Creature* creature) : ScriptedAI(creature), _below50PctHealth(false), _resurrectedMograine(false){ }
- struct boss_high_inquisitor_whitemaneAI : public ScriptedAI
+ void InitializeAI() override
{
- boss_high_inquisitor_whitemaneAI(Creature* creature) : ScriptedAI(creature)
- {
- Initialize();
- instance = creature->GetInstanceScript();
- }
-
- void Initialize()
- {
- Wait_Timer = 7000;
- Heal_Timer = 10000;
- PowerWordShield_Timer = 15000;
- HolySmite_Timer = 6000;
-
- _bCanResurrectCheck = false;
- _bCanResurrect = false;
- }
-
- InstanceScript* instance;
-
- uint32 Heal_Timer;
- uint32 PowerWordShield_Timer;
- uint32 HolySmite_Timer;
- uint32 Wait_Timer;
-
- bool _bCanResurrectCheck;
- bool _bCanResurrect;
-
- void Reset() override
- {
- Initialize();
-
- if (me->IsAlive())
- instance->SetBossState(DATA_MOGRAINE_AND_WHITE_EVENT, NOT_STARTED);
- }
-
- void AttackStart(Unit* who) override
- {
- if (instance->GetBossState(DATA_MOGRAINE_AND_WHITE_EVENT) == NOT_STARTED)
- return;
-
- ScriptedAI::AttackStart(who);
- }
-
- void JustEngagedWith(Unit* /*who*/) override
- {
- Talk(SAY_WH_INTRO);
- }
-
- void KilledUnit(Unit* /*victim*/) override
- {
- Talk(SAY_WH_KILL);
- }
-
- void DamageTaken(Unit* /*attacker*/, uint32& damage) override
- {
- if (!_bCanResurrectCheck && damage >= me->GetHealth())
- damage = me->GetHealth() - 1;
- }
-
- void UpdateAI(uint32 diff) override
- {
- if (!UpdateVictim())
- return;
-
- if (_bCanResurrect)
- {
- //When casting resuruction make sure to delay so on rez when reinstate battle deepsleep runs out
- if (Wait_Timer <= diff)
- {
- if (Creature* mograine = ObjectAccessor::GetCreature(*me, instance->GetGuidData(DATA_MOGRAINE)))
- {
- DoCast(mograine, SPELL_SCARLETRESURRECTION);
- Talk(SAY_WH_RESURRECT);
- _bCanResurrect = false;
- }
- }
- else Wait_Timer -= diff;
- }
-
- //Cast Deep sleep when health is less than 50%
- if (!_bCanResurrectCheck && !HealthAbovePct(50))
- {
- if (me->IsNonMeleeSpellCast(false))
- me->InterruptNonMeleeSpells(false);
-
- DoCastVictim(SPELL_DEEPSLEEP);
- _bCanResurrectCheck = true;
- _bCanResurrect = true;
- return;
- }
-
- //while in "resurrect-mode", don't do anything
- if (_bCanResurrect)
- return;
-
- //If we are <75% hp cast healing spells at self or Mograine
- if (Heal_Timer <= diff)
- {
- Creature* target = nullptr;
-
- if (!HealthAbovePct(75))
- target = me;
-
- if (Creature* mograine = ObjectAccessor::GetCreature(*me, instance->GetGuidData(DATA_MOGRAINE)))
- {
- // checking _bCanResurrectCheck prevents her healing Mograine while he is "faking death"
- if (_bCanResurrectCheck && mograine->IsAlive() && !mograine->HealthAbovePct(75))
- target = mograine;
- }
-
- if (target)
- DoCast(target, SPELL_HEAL);
-
- Heal_Timer = 13000;
- }
- else Heal_Timer -= diff;
-
- //PowerWordShield_Timer
- if (PowerWordShield_Timer <= diff)
- {
- DoCast(me, SPELL_POWERWORDSHIELD);
- PowerWordShield_Timer = 15000;
- }
- else PowerWordShield_Timer -= diff;
-
- //HolySmite_Timer
- if (HolySmite_Timer <= diff)
- {
- DoCastVictim(SPELL_HOLYSMITE);
- HolySmite_Timer = 6000;
- }
- else HolySmite_Timer -= diff;
-
- DoMeleeAttackIfReady();
- }
- };
-
- CreatureAI* GetAI(Creature* creature) const override
- {
- return GetScarletMonasteryAI(creature);
+ me->SetReactState(REACT_PASSIVE);
+ _instance = me->GetInstanceScript();
}
+
+ void JustEngagedWith(Unit* /*who*/) override
+ {
+ _events.ScheduleEvent(EVENT_HOLY_SMITE, 1ms);
+ _events.ScheduleEvent(EVENT_HEAL, 12s);
+ _events.ScheduleEvent(EVENT_POWER_WORD_SHIELD, 22s); // @todo: validate timer
+ }
+
+ void KilledUnit(Unit* who) override
+ {
+ if (who->IsPlayer())
+ Talk(SAY_WH_KILL);
+ }
+
+ void EnterEvadeMode(EvadeReason /*why*/) override
+ {
+ _EnterEvadeMode();
+ // The Instance Script will take care of the reset
+ _instance->SetBossState(DATA_MOGRAINE_AND_WHITEMANE, FAIL);
+ }
+
+ void JustDied(Unit* /*killer*/) override
+ {
+ if (Creature* mograine = _instance->GetCreature(DATA_SCARLET_COMMANDER_MOGRAINE))
+ if (mograine->isDead())
+ _instance->SetBossState(DATA_MOGRAINE_AND_WHITEMANE, DONE);
+ }
+
+ void DamageTaken(Unit* /*attacker*/, uint32& damage) override
+ {
+ // Do not allow Whitemane to die before she has resurrected Mograine.
+ // This bug can actually happen on retail but for the sake of it, we wont allow it to happen.
+ if (!_resurrectedMograine && damage >= me->GetHealth())
+ damage = me->GetHealth() - 1;
+
+ if (!_below50PctHealth && me->HealthBelowPctDamaged(50, damage))
+ {
+ _below50PctHealth = true;
+ me->AttackStop();
+ me->SetReactState(REACT_PASSIVE);
+ _events.Reset();
+ _events.ScheduleEvent(EVENT_DEEP_SLEEP, 1ms);
+ }
+ }
+
+ void DoAction(int32 action) override
+ {
+ switch (action)
+ {
+ case ACTION_MOGRAINE_DIED:
+ Talk(SAY_WH_INTRO);
+ if (GameObject* door = _instance->GetGameObject(DATA_HIGH_INQUISITORS_DOOR))
+ door->UseDoorOrButton();
+ me->GetMotionMaster()->MovePoint(POINT_NONE, WhitemaneIntroPosition);
+ me->SetReactState(REACT_AGGRESSIVE);
+ break;
+ default:
+ break;
+ }
+ }
+
+ void MovementInform(uint32 type, uint32 pointId)
+ {
+ if (type != POINT_MOTION_TYPE)
+ return;
+
+ switch (pointId)
+ {
+ case POINT_RESURRECT_MOGRAINE:
+ _events.ScheduleEvent(EVENT_SCARLET_RESURRECTION, 3s);
+ break;
+ default:
+ break;
+ }
+ }
+
+ void OnSpellCastFinished(SpellInfo const* spell, SpellFinishReason reason) override
+ {
+ if (spell->Id == SPELL_SCARLET_RESURRECTION && reason == SPELL_FINISHED_SUCCESSFUL_CAST)
+ {
+ Talk(SAY_WH_RESURRECT);
+ _resurrectedMograine = true;
+ _events.ScheduleEvent(EVENT_SALUTE_EMOTE, 1s);
+ _events.ScheduleEvent(EVENT_REENGAGE_PLAYERS, 5s);
+
+ if (Creature* mograine = _instance->GetCreature(DATA_SCARLET_COMMANDER_MOGRAINE))
+ if (mograine->IsAIEnabled)
+ mograine->AI()->DoAction(ACTION_RESURRECTED);
+ }
+ }
+
+ void UpdateAI(uint32 diff) override
+ {
+ if (!UpdateVictim())
+ return;
+
+ _events.Update(diff);
+
+ if (me->HasUnitState(UNIT_STATE_CASTING))
+ return;
+
+ while (uint32 eventId = _events.ExecuteEvent())
+ {
+ switch (eventId)
+ {
+ case EVENT_HOLY_SMITE:
+ DoCastVictim(SPELL_HOLY_SMITE);
+ _events.Repeat(5s, 7s);
+ break;
+ case EVENT_DEEP_SLEEP:
+ DoCastAOE(SPELL_DEEP_SLEEP);
+ if (Creature* mograine = _instance->GetCreature(DATA_SCARLET_COMMANDER_MOGRAINE))
+ {
+ Position pos = mograine->GetPosition();
+ mograine->MovePositionToFirstCollision(pos, 2.f, mograine->GetRelativeAngle(me));
+ me->GetMotionMaster()->MovePoint(POINT_RESURRECT_MOGRAINE, pos);
+ }
+ break;
+ case EVENT_SCARLET_RESURRECTION:
+ DoCastAOE(SPELL_SCARLET_RESURRECTION);
+ break;
+ case EVENT_SALUTE_EMOTE:
+ me->HandleEmoteCommand(EMOTE_ONESHOT_SALUTE);
+ break;
+ case EVENT_REENGAGE_PLAYERS:
+ me->SetReactState(REACT_AGGRESSIVE);
+ _events.ScheduleEvent(EVENT_HOLY_SMITE, 1ms);
+ _events.ScheduleEvent(EVENT_HEAL, 12s);
+ _events.ScheduleEvent(EVENT_POWER_WORD_SHIELD, 22s);
+ break;
+ case EVENT_HEAL:
+ {
+ // @todo: This logic has been ported from CMangos since there is very little sniff information about conditions and repeat timers
+ Unit* target = nullptr;
+ if (me->GetHealthPct() < 75.f)
+ target = me;
+ else if (Creature* mograine = _instance->GetCreature(DATA_SCARLET_COMMANDER_MOGRAINE))
+ if (mograine->GetHealthPct() < 75.f)
+ target = mograine;
+
+ if (target)
+ {
+ DoCast(target, SPELL_HEAL);
+ _events.Repeat(13s);
+ }
+ else
+ _events.Repeat(1s);
+ break;
+ }
+ case EVENT_POWER_WORD_SHIELD:
+ DoCastSelf(SPELL_POWER_WORD_SHIELD);
+ _events.Repeat(22s, 45s);
+ break;
+ default:
+ break;
+ }
+
+ if (me->HasUnitState(UNIT_STATE_CASTING))
+ return;
+ }
+
+ DoMeleeAttackIfReady();
+ }
+private:
+ InstanceScript* _instance;
+ EventMap _events;
+ bool _below50PctHealth;
+ bool _resurrectedMograine;
};
+
void AddSC_boss_mograine_and_whitemane()
{
- new boss_scarlet_commander_mograine();
- new boss_high_inquisitor_whitemane();
+ RegisterScarletMonasteryCreatureAI(npc_scarlet_commander_mograine);
+ RegisterScarletMonasteryCreatureAI(npc_high_inquisitor_whitemane);
}
diff --git a/src/server/scripts/EasternKingdoms/ScarletMonastery/instance_scarlet_monastery.cpp b/src/server/scripts/EasternKingdoms/ScarletMonastery/instance_scarlet_monastery.cpp
index f431b904a07..9a202beec09 100644
--- a/src/server/scripts/EasternKingdoms/ScarletMonastery/instance_scarlet_monastery.cpp
+++ b/src/server/scripts/EasternKingdoms/ScarletMonastery/instance_scarlet_monastery.cpp
@@ -17,6 +17,7 @@
#include "ScriptMgr.h"
#include "Creature.h"
+#include "EventMap.h"
#include "GameObject.h"
#include "InstanceScript.h"
#include "Map.h"
@@ -24,17 +25,29 @@
ObjectData const creatureData[] =
{
- { BOSS_INTERROGATOR_VISHAS, DATA_INTERROGATOR_VISHAS },
- { BOSS_BLOODMAGE_THALNOS, DATA_BLOODMAGE_THALNOS },
- { BOSS_HOUNDMASTER_LOKSEY, DATA_HOUNDMASTER_LOKSEY },
- { BOSS_ARCANIST_DOAN, DATA_ARCANIST_DOAN },
- { 0, 0 } // END
+ { BOSS_INTERROGATOR_VISHAS, DATA_INTERROGATOR_VISHAS },
+ { BOSS_BLOODMAGE_THALNOS, DATA_BLOODMAGE_THALNOS },
+ { BOSS_HOUNDMASTER_LOKSEY, DATA_HOUNDMASTER_LOKSEY },
+ { BOSS_ARCANIST_DOAN, DATA_ARCANIST_DOAN },
+ { BOSS_HIGH_INQUISITOR_WHITEMANE, DATA_HIGH_INQUISITOR_WHITEMANE },
+ { BOSS_SCARLET_COMMANDER_MOGRAINE, DATA_SCARLET_COMMANDER_MOGRAINE },
+ { 0, 0 } // END
};
-DoorData const doorData[] =
+ObjectData const gameObjectData[] =
{
- { GO_HIGH_INQUISITORS_DOOR, DATA_MOGRAINE_AND_WHITE_EVENT, DOOR_TYPE_ROOM },
- { 0, 0, DOOR_TYPE_ROOM } // END
+ { GO_HIGH_INQUISITORS_DOOR, DATA_HIGH_INQUISITORS_DOOR },
+ { 0, 0 } // END
+};
+
+enum SpawnGroups
+{
+ SPAWN_GROUP_ID_WHITEMANE_AND_MOGRAINE = 451
+};
+
+enum Events
+{
+ EVENT_RESPAWN_MOGRAINE_AND_WHITEMANE = 1
};
class instance_scarlet_monastery : public InstanceMapScript
@@ -48,34 +61,29 @@ class instance_scarlet_monastery : public InstanceMapScript
{
SetHeaders(DataHeader);
SetBossNumber(EncounterCount);
- LoadObjectData(creatureData, nullptr);
- LoadDoorData(doorData);
+ LoadObjectData(creatureData, gameObjectData);
+ }
- HorsemanAdds.clear();
+ void Create() override
+ {
+ instance->SpawnGroupSpawn(SPAWN_GROUP_ID_WHITEMANE_AND_MOGRAINE, true);
+ }
+
+ void Load(char const* /*data*/) override
+ {
+ if (GetBossState(DATA_MOGRAINE_AND_WHITEMANE) != DONE)
+ instance->SpawnGroupSpawn(SPAWN_GROUP_ID_WHITEMANE_AND_MOGRAINE, true, true);
}
void OnGameObjectCreate(GameObject* go) override
{
+ InstanceScript::OnGameObjectCreate(go);
+
switch (go->GetEntry())
{
case GO_PUMPKIN_SHRINE:
PumpkinShrineGUID = go->GetGUID();
break;
- case GO_HIGH_INQUISITORS_DOOR:
- AddDoor(go, true);
- break;
- default:
- break;
- }
- }
-
- void OnGameObjectRemove(GameObject* go) override
- {
- switch (go->GetEntry())
- {
- case GO_HIGH_INQUISITORS_DOOR:
- AddDoor(go, false);
- break;
default:
break;
}
@@ -83,6 +91,8 @@ class instance_scarlet_monastery : public InstanceMapScript
void OnCreatureCreate(Creature* creature) override
{
+ InstanceScript::OnCreatureCreate(creature);
+
switch (creature->GetEntry())
{
case NPC_HORSEMAN:
@@ -94,12 +104,6 @@ class instance_scarlet_monastery : public InstanceMapScript
case NPC_PUMPKIN:
HorsemanAdds.insert(creature->GetGUID());
break;
- case NPC_MOGRAINE:
- MograineGUID = creature->GetGUID();
- break;
- case NPC_WHITEMANE:
- WhitemaneGUID = creature->GetGUID();
- break;
case NPC_VORREL:
VorrelGUID = creature->GetGUID();
break;
@@ -140,20 +144,43 @@ class instance_scarlet_monastery : public InstanceMapScript
HandleGameObject(PumpkinShrineGUID, false);
}
break;
+ case DATA_MOGRAINE_AND_WHITEMANE:
+ if (state == FAIL)
+ {
+ instance->SpawnGroupDespawn(SPAWN_GROUP_ID_WHITEMANE_AND_MOGRAINE);
+ _events.ScheduleEvent(EVENT_RESPAWN_MOGRAINE_AND_WHITEMANE, 30s);
+
+ if (GameObject* door = GetGameObject(DATA_HIGH_INQUISITORS_DOOR))
+ door->ResetDoorOrButton();
+ }
+ break;
default:
break;
}
return true;
}
+ void Update(uint32 diff) override
+ {
+ _events.Update(diff);
+
+ while (uint32 eventId = _events.ExecuteEvent())
+ {
+ switch (eventId)
+ {
+ case EVENT_RESPAWN_MOGRAINE_AND_WHITEMANE:
+ instance->SpawnGroupSpawn(SPAWN_GROUP_ID_WHITEMANE_AND_MOGRAINE);
+ break;
+ default:
+ break;
+ }
+ }
+ }
+
ObjectGuid GetGuidData(uint32 type) const override
{
switch (type)
{
- case DATA_MOGRAINE:
- return MograineGUID;
- case DATA_WHITEMANE:
- return WhitemaneGUID;
case DATA_VORREL:
return VorrelGUID;
default:
@@ -162,14 +189,13 @@ class instance_scarlet_monastery : public InstanceMapScript
return ObjectGuid::Empty;
}
- protected:
+ private:
+ EventMap _events;
+
ObjectGuid PumpkinShrineGUID;
ObjectGuid HorsemanGUID;
ObjectGuid HeadGUID;
- ObjectGuid MograineGUID;
- ObjectGuid WhitemaneGUID;
ObjectGuid VorrelGUID;
-
GuidSet HorsemanAdds;
};
diff --git a/src/server/scripts/EasternKingdoms/ScarletMonastery/scarlet_monastery.h b/src/server/scripts/EasternKingdoms/ScarletMonastery/scarlet_monastery.h
index a66789ccd5b..9859cce402f 100644
--- a/src/server/scripts/EasternKingdoms/ScarletMonastery/scarlet_monastery.h
+++ b/src/server/scripts/EasternKingdoms/ScarletMonastery/scarlet_monastery.h
@@ -30,40 +30,43 @@ enum SMDataTypes
// Bosses
DATA_INTERROGATOR_VISHAS = 1,
DATA_BLOODMAGE_THALNOS = 2,
+ DATA_ARCANIST_DOAN = 3,
+ DATA_HOUNDMASTER_LOKSEY = 4,
+ DATA_MOGRAINE_AND_WHITEMANE = 5,
- DATA_MOGRAINE_AND_WHITE_EVENT,
- DATA_MOGRAINE,
- DATA_WHITEMANE,
+
+ // Additional Data Types
+ DATA_SCARLET_COMMANDER_MOGRAINE,
+ DATA_HIGH_INQUISITOR_WHITEMANE,
DATA_HORSEMAN_EVENT,
DATA_PUMPKIN_SHRINE,
DATA_VORREL,
- DATA_ARCANIST_DOAN,
DATA_AZSHIR,
DATA_HEROD,
DATA_HIGH_INQUISITOR_FAIRBANKS,
- DATA_HOUNDMASTER_LOKSEY,
- DATA_SCORN
+ DATA_SCORN,
+ DATA_HIGH_INQUISITORS_DOOR,
};
enum SMCreatureIds
{
// Bosses
- BOSS_INTERROGATOR_VISHAS = 3983,
- BOSS_BLOODMAGE_THALNOS = 4543,
- BOSS_HOUNDMASTER_LOKSEY = 3974,
- BOSS_ARCANIST_DOAN = 6487,
+ BOSS_INTERROGATOR_VISHAS = 3983,
+ BOSS_BLOODMAGE_THALNOS = 4543,
+ BOSS_HOUNDMASTER_LOKSEY = 3974,
+ BOSS_ARCANIST_DOAN = 6487,
+ BOSS_HIGH_INQUISITOR_WHITEMANE = 3977,
+ BOSS_SCARLET_COMMANDER_MOGRAINE = 3976,
// Encounter related creature
/*Houndmaster Loksey*/
- NPC_SCARLET_TRACKING_HOUND = 4304,
+ NPC_SCARLET_TRACKING_HOUND = 4304,
- NPC_MOGRAINE = 3976,
- NPC_WHITEMANE = 3977,
- NPC_VORREL = 3981,
+ NPC_VORREL = 3981,
- NPC_HORSEMAN = 23682,
- NPC_HEAD = 23775,
- NPC_PUMPKIN = 23694
+ NPC_HORSEMAN = 23682,
+ NPC_HEAD = 23775,
+ NPC_PUMPKIN = 23694
};
enum SMGameObjectIds
@@ -78,7 +81,7 @@ inline AI* GetScarletMonasteryAI(T* obj)
return GetInstanceAI(obj, SMScriptName);
}
-#define RegisterScarletMonastryCreatureAI(ai_name) RegisterCreatureAIWithFactory(ai_name, GetScarletMonasteryAI)
+#define RegisterScarletMonasteryCreatureAI(ai_name) RegisterCreatureAIWithFactory(ai_name, GetScarletMonasteryAI)
#endif // SCARLET_M_