aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--src/server/game/Entities/Unit/Unit.h2
-rw-r--r--src/server/game/Maps/MapRefManager.h6
-rw-r--r--src/server/game/Scripting/ScriptMgr.h11
-rw-r--r--src/server/scripts/EasternKingdoms/ScarletMonastery/boss_arcanist_doan.cpp176
-rw-r--r--src/server/scripts/EasternKingdoms/ScarletMonastery/boss_azshir_the_sleepless.cpp148
-rw-r--r--src/server/scripts/EasternKingdoms/ScarletMonastery/boss_bloodmage_thalnos.cpp157
-rw-r--r--src/server/scripts/EasternKingdoms/ScarletMonastery/boss_headless_horseman.cpp1465
-rw-r--r--src/server/scripts/EasternKingdoms/ScarletMonastery/boss_herod.cpp214
-rw-r--r--src/server/scripts/EasternKingdoms/ScarletMonastery/boss_high_inquisitor_fairbanks.cpp218
-rw-r--r--src/server/scripts/EasternKingdoms/ScarletMonastery/boss_houndmaster_loksey.cpp79
-rw-r--r--src/server/scripts/EasternKingdoms/ScarletMonastery/boss_interrogator_vishas.cpp161
-rw-r--r--src/server/scripts/EasternKingdoms/ScarletMonastery/boss_mograine_and_whitemane.cpp649
-rw-r--r--src/server/scripts/EasternKingdoms/ScarletMonastery/boss_scorn.cpp105
-rw-r--r--src/server/scripts/EasternKingdoms/ScarletMonastery/instance_scarlet_monastery.cpp111
-rw-r--r--src/server/scripts/EasternKingdoms/ScarletMonastery/scarlet_monastery.h52
-rw-r--r--src/server/shared/Dynamic/LinkedReference/RefManager.h38
16 files changed, 1707 insertions, 1885 deletions
diff --git a/src/server/game/Entities/Unit/Unit.h b/src/server/game/Entities/Unit/Unit.h
index 1de18af19b7..4b45ca6af85 100644
--- a/src/server/game/Entities/Unit/Unit.h
+++ b/src/server/game/Entities/Unit/Unit.h
@@ -97,7 +97,7 @@ enum MovementGeneratorType : uint8;
typedef std::list<Unit*> UnitList;
-class DispelableAura
+class TC_GAME_API DispelableAura
{
public:
DispelableAura(Aura* aura, int32 dispelChance, uint8 dispelCharges);
diff --git a/src/server/game/Maps/MapRefManager.h b/src/server/game/Maps/MapRefManager.h
index 324b96fbd60..5b029ab2ea5 100644
--- a/src/server/game/Maps/MapRefManager.h
+++ b/src/server/game/Maps/MapRefManager.h
@@ -29,13 +29,13 @@ class MapRefManager : public RefManager<Map, Player>
typedef LinkedListHead::Iterator<MapReference> iterator;
typedef LinkedListHead::Iterator<MapReference const> const_iterator;
- MapReference* getFirst() { return (MapReference*)RefManager<Map, Player>::getFirst(); }
+ MapReference* getFirst() { return (MapReference*)RefManager<Map, Player>::getFirst(); }
MapReference const* getFirst() const { return (MapReference const*)RefManager<Map, Player>::getFirst(); }
iterator begin() { return iterator(getFirst()); }
- iterator end() { return iterator(nullptr); }
+ iterator end() { return iterator(nullptr); }
const_iterator begin() const { return const_iterator(getFirst()); }
- const_iterator end() const { return const_iterator(nullptr); }
+ const_iterator end() const { return const_iterator(nullptr); }
};
#endif
diff --git a/src/server/game/Scripting/ScriptMgr.h b/src/server/game/Scripting/ScriptMgr.h
index b9677ff70b4..b0dea1e36b6 100644
--- a/src/server/game/Scripting/ScriptMgr.h
+++ b/src/server/game/Scripting/ScriptMgr.h
@@ -1108,7 +1108,7 @@ class GenericCreatureScript : public CreatureScript
};
#define RegisterCreatureAI(ai_name) new GenericCreatureScript<ai_name>(#ai_name)
-template <class AI, AI*(*AIFactory)(Creature*)>
+template <class AI, AI* (*AIFactory)(Creature*)>
class FactoryCreatureScript : public CreatureScript
{
public:
@@ -1126,6 +1126,15 @@ class GenericGameObjectScript : public GameObjectScript
};
#define RegisterGameObjectAI(ai_name) new GenericGameObjectScript<ai_name>(#ai_name)
+template <class AI, AI* (*AIFactory)(GameObject*)>
+class FactoryGameObjectScript : public GameObjectScript
+{
+ public:
+ FactoryGameObjectScript(char const* name) : GameObjectScript(name) { }
+ GameObjectAI* GetAI(GameObject* me) const override { return AIFactory(me); }
+};
+#define RegisterGameObjectAIWithFactory(ai_name, factory_fn) new FactoryGameObjectScript<ai_name, &factory_fn>(#ai_name)
+
#define sScriptMgr ScriptMgr::instance()
#endif
diff --git a/src/server/scripts/EasternKingdoms/ScarletMonastery/boss_arcanist_doan.cpp b/src/server/scripts/EasternKingdoms/ScarletMonastery/boss_arcanist_doan.cpp
index cfc6cd3c0be..80cfec4d37d 100644
--- a/src/server/scripts/EasternKingdoms/ScarletMonastery/boss_arcanist_doan.cpp
+++ b/src/server/scripts/EasternKingdoms/ScarletMonastery/boss_arcanist_doan.cpp
@@ -15,123 +15,107 @@
* with this program. If not, see <http://www.gnu.org/licenses/>.
*/
-#include "ScriptMgr.h"
-#include "ScriptedCreature.h"
#include "scarlet_monastery.h"
+#include "ScriptedCreature.h"
+#include "ScriptMgr.h"
-enum Yells
+enum ArcanistDoanYells
{
- SAY_AGGRO = 0,
- SAY_SPECIALAE = 1
+ SAY_AGGRO = 0,
+ SAY_SPECIALAE = 1
};
-enum Spells
+enum ArcanistDoanSpells
{
- SPELL_SILENCE = 8988,
- SPELL_ARCANE_EXPLOSION = 9433,
- SPELL_DETONATION = 9435,
- SPELL_ARCANE_BUBBLE = 9438,
- SPELL_POLYMORPH = 13323
+ SPELL_SILENCE = 8988,
+ SPELL_ARCANE_EXPLOSION = 9433,
+ SPELL_DETONATION = 9435,
+ SPELL_ARCANE_BUBBLE = 9438,
+ SPELL_POLYMORPH = 13323
};
-enum Events
+enum ArcanistDoanEvents
{
- EVENT_SILENCE = 1,
- EVENT_ARCANE_EXPLOSION = 2,
- EVENT_ARCANE_BUBBLE = 3,
- EVENT_POLYMORPH = 4
+ EVENT_SILENCE = 1,
+ EVENT_ARCANE_EXPLOSION,
+ EVENT_ARCANE_BUBBLE,
+ EVENT_POLYMORPH
};
-class boss_arcanist_doan : public CreatureScript
+struct boss_arcanist_doan : public BossAI
{
- public:
- boss_arcanist_doan() : CreatureScript("boss_arcanist_doan") { }
-
- struct boss_arcanist_doanAI : public BossAI
+ boss_arcanist_doan(Creature* creature) : BossAI(creature, DATA_ARCANIST_DOAN)
+ {
+ _healthAbove50Pct = true;
+ }
+
+ void Reset() override
+ {
+ _Reset();
+ _healthAbove50Pct = true;
+ }
+
+ void JustEngagedWith(Unit* /*who*/) override
+ {
+ _JustEngagedWith();
+ Talk(SAY_AGGRO);
+
+ events.ScheduleEvent(EVENT_SILENCE, 15s);
+ events.ScheduleEvent(EVENT_ARCANE_EXPLOSION, 3s);
+ events.ScheduleEvent(EVENT_POLYMORPH, 30s);
+ }
+
+ void UpdateAI(uint32 diff) override
+ {
+ if (!UpdateVictim())
+ return;
+
+ events.Update(diff);
+
+ if (me->HasUnitState(UNIT_STATE_CASTING))
+ return;
+
+ while (uint32 eventId = events.ExecuteEvent())
{
- boss_arcanist_doanAI(Creature* creature) : BossAI(creature, DATA_ARCANIST_DOAN)
+ switch (eventId)
{
- _healthAbove50Pct = true;
+ case EVENT_SILENCE:
+ DoCastVictim(SPELL_SILENCE);
+ events.Repeat(15s, 20s);
+ break;
+ case EVENT_ARCANE_EXPLOSION:
+ DoCastVictim(SPELL_ARCANE_EXPLOSION);
+ events.Repeat(8s);
+ break;
+ case EVENT_POLYMORPH:
+ if (Unit* target = SelectTarget(SELECT_TARGET_RANDOM, 1, 30.0f, true))
+ DoCast(target, SPELL_POLYMORPH);
+ events.Repeat(20s);
+ break;
+ default:
+ break;
}
- void Reset() override
- {
- _Reset();
- _healthAbove50Pct = true;
- }
-
- void JustEngagedWith(Unit* /*who*/) override
- {
- _JustEngagedWith();
- Talk(SAY_AGGRO);
-
- events.ScheduleEvent(EVENT_SILENCE, 15 * IN_MILLISECONDS);
- events.ScheduleEvent(EVENT_ARCANE_EXPLOSION, 3s);
- events.ScheduleEvent(EVENT_POLYMORPH, 30 * IN_MILLISECONDS);
- }
-
- void JustDied(Unit* /*killer*/) override
- {
- _JustDied();
- }
-
- 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_SILENCE:
- DoCastVictim(SPELL_SILENCE);
- events.ScheduleEvent(EVENT_SILENCE, 15s, 20s);
- break;
- case EVENT_ARCANE_EXPLOSION:
- DoCastVictim(SPELL_ARCANE_EXPLOSION);
- events.ScheduleEvent(EVENT_SILENCE, 8s);
- break;
- case EVENT_POLYMORPH:
- if (Unit* target = SelectTarget(SELECT_TARGET_RANDOM, 1, 30.0f, true))
- DoCast(target, SPELL_POLYMORPH);
- events.ScheduleEvent(EVENT_POLYMORPH, 20s);
- break;
- default:
- break;
- }
-
- if (me->HasUnitState(UNIT_STATE_CASTING))
- return;
- }
-
- if (_healthAbove50Pct && HealthBelowPct(50))
- {
- _healthAbove50Pct = false;
- Talk(SAY_SPECIALAE);
- DoCast(me, SPELL_ARCANE_BUBBLE);
- DoCastAOE(SPELL_DETONATION);
- }
-
- DoMeleeAttackIfReady();
- }
-
- private:
- bool _healthAbove50Pct;
- };
+ if (me->HasUnitState(UNIT_STATE_CASTING))
+ return;
+ }
- CreatureAI* GetAI(Creature* creature) const override
+ if (_healthAbove50Pct && HealthBelowPct(50))
{
- return GetScarletMonasteryAI<boss_arcanist_doanAI>(creature);
+ _healthAbove50Pct = false;
+ Talk(SAY_SPECIALAE);
+ DoCastSelf(SPELL_ARCANE_BUBBLE);
+ DoCastAOE(SPELL_DETONATION);
}
+
+ DoMeleeAttackIfReady();
+ }
+
+private:
+ bool _healthAbove50Pct;
};
void AddSC_boss_arcanist_doan()
{
- new boss_arcanist_doan();
+ RegisterScarletMonasteryCreatureAI(boss_arcanist_doan);
}
diff --git a/src/server/scripts/EasternKingdoms/ScarletMonastery/boss_azshir_the_sleepless.cpp b/src/server/scripts/EasternKingdoms/ScarletMonastery/boss_azshir_the_sleepless.cpp
index 6b2098cc390..3bf122c0575 100644
--- a/src/server/scripts/EasternKingdoms/ScarletMonastery/boss_azshir_the_sleepless.cpp
+++ b/src/server/scripts/EasternKingdoms/ScarletMonastery/boss_azshir_the_sleepless.cpp
@@ -15,112 +15,96 @@
* with this program. If not, see <http://www.gnu.org/licenses/>.
*/
-#include "ScriptMgr.h"
-#include "ScriptedCreature.h"
#include "scarlet_monastery.h"
+#include "ScriptedCreature.h"
+#include "ScriptMgr.h"
-enum Spells
+enum AzshirTheSleeplessSpells
{
- SPELL_CALL_OF_THE_GRAVE = 17831,
- SPELL_TERRIFY = 7399,
- SPELL_SOUL_SIPHON = 7290
+ SPELL_CALL_OF_THE_GRAVE = 17831,
+ SPELL_TERRIFY = 7399,
+ SPELL_SOUL_SIPHON = 7290
};
-enum Events
+enum AzshirTheSleeplessEvents
{
- EVENT_CALL_OF_GRAVE = 1,
+ EVENT_CALL_OF_GRAVE = 1,
EVENT_TERRIFY,
EVENT_SOUL_SIPHON
};
-class boss_azshir_the_sleepless : public CreatureScript
+struct boss_azshir_the_sleepless : public BossAI
{
- public:
- boss_azshir_the_sleepless() : CreatureScript("boss_azshir_the_sleepless") { }
-
- struct boss_azshir_the_sleeplessAI : public BossAI
+ boss_azshir_the_sleepless(Creature* creature) : BossAI(creature, DATA_AZSHIR)
+ {
+ _siphon = false;
+ }
+
+ void Reset() override
+ {
+ _Reset();
+ _siphon = false;
+ }
+
+ void JustEngagedWith(Unit* /*who*/) override
+ {
+ _JustEngagedWith();
+ events.ScheduleEvent(EVENT_CALL_OF_GRAVE, 30s);
+ events.ScheduleEvent(EVENT_TERRIFY, 20s);
+ }
+
+ void DamageTaken(Unit* /*attacker*/, uint32& damage) override
+ {
+ if (!_siphon && me->HealthBelowPctDamaged(50, damage))
{
- boss_azshir_the_sleeplessAI(Creature* creature) : BossAI(creature, DATA_AZSHIR)
- {
- _siphon = false;
- }
+ DoCastVictim(SPELL_SOUL_SIPHON);
+ events.ScheduleEvent(EVENT_SOUL_SIPHON, 20s);
+ _siphon = true;
+ }
+ }
- void Reset() override
- {
- _Reset();
- _siphon = false;
- }
+ void UpdateAI(uint32 diff) override
+ {
+ if (!UpdateVictim())
+ return;
- void JustEngagedWith(Unit* /*who*/) override
- {
- _JustEngagedWith();
- events.ScheduleEvent(EVENT_CALL_OF_GRAVE, 30s);
- events.ScheduleEvent(EVENT_TERRIFY, 20s);
- }
+ events.Update(diff);
- void JustDied(Unit* /*killer*/) override
- {
- _JustDied();
- }
+ if (me->HasUnitState(UNIT_STATE_CASTING))
+ return;
- void DamageTaken(Unit* /*attacker*/, uint32& damage) override
+ while (uint32 eventId = events.ExecuteEvent())
+ {
+ switch (eventId)
{
- if (!_siphon && me->HealthBelowPctDamaged(50, damage))
- {
+ case EVENT_CALL_OF_GRAVE:
+ DoCastVictim(SPELL_CALL_OF_THE_GRAVE);
+ events.Repeat(30s);
+ break;
+ case EVENT_TERRIFY:
+ DoCastVictim(SPELL_TERRIFY);
+ events.Repeat(20s);
+ break;
+ case EVENT_SOUL_SIPHON:
DoCastVictim(SPELL_SOUL_SIPHON);
- events.ScheduleEvent(EVENT_SOUL_SIPHON, 20s);
- _siphon = true;
- }
+ events.Repeat(20s);
+ break;
+ default:
+ break;
}
- 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_CALL_OF_GRAVE:
- DoCastVictim(SPELL_CALL_OF_THE_GRAVE);
- events.ScheduleEvent(EVENT_CALL_OF_GRAVE, 30s);
- break;
- case EVENT_TERRIFY:
- DoCastVictim(SPELL_TERRIFY);
- events.ScheduleEvent(EVENT_TERRIFY, 20s);
- break;
- case EVENT_SOUL_SIPHON:
- DoCastVictim(SPELL_SOUL_SIPHON);
- events.ScheduleEvent(EVENT_SOUL_SIPHON, 20s);
- break;
- default:
- break;
- }
-
- if (me->HasUnitState(UNIT_STATE_CASTING))
- return;
- }
-
- DoMeleeAttackIfReady();
- }
+ if (me->HasUnitState(UNIT_STATE_CASTING))
+ return;
+ }
- private:
- bool _siphon;
- };
+ DoMeleeAttackIfReady();
+ }
- CreatureAI* GetAI(Creature* creature) const override
- {
- return GetScarletMonasteryAI<boss_azshir_the_sleeplessAI>(creature);
- }
+private:
+ bool _siphon;
};
void AddSC_boss_azshir_the_sleepless()
{
- new boss_azshir_the_sleepless();
+ RegisterScarletMonasteryCreatureAI(boss_azshir_the_sleepless);
}
diff --git a/src/server/scripts/EasternKingdoms/ScarletMonastery/boss_bloodmage_thalnos.cpp b/src/server/scripts/EasternKingdoms/ScarletMonastery/boss_bloodmage_thalnos.cpp
index 73506414fb4..667491f84c5 100644
--- a/src/server/scripts/EasternKingdoms/ScarletMonastery/boss_bloodmage_thalnos.cpp
+++ b/src/server/scripts/EasternKingdoms/ScarletMonastery/boss_bloodmage_thalnos.cpp
@@ -15,116 +15,101 @@
* with this program. If not, see <http://www.gnu.org/licenses/>.
*/
-#include "ScriptMgr.h"
-#include "ScriptedCreature.h"
#include "scarlet_monastery.h"
+#include "ScriptedCreature.h"
+#include "ScriptMgr.h"
-enum Yells
+enum BloodmageThalnosYells
{
- SAY_AGGRO = 0,
- SAY_HEALTH = 1,
- SAY_KILL = 2
+ SAY_AGGRO = 0,
+ SAY_HEALTH = 1,
+ SAY_KILL = 2
};
-enum Spells
+enum BloodmageThalnosSpells
{
- SPELL_FLAMESHOCK = 8053,
- SPELL_SHADOWBOLT = 1106,
- SPELL_FLAMESPIKE = 8814,
- SPELL_FIRENOVA = 16079
+ SPELL_FLAMESHOCK = 8053,
+ SPELL_SHADOWBOLT = 1106,
+ SPELL_FLAMESPIKE = 8814,
+ SPELL_FIRENOVA = 16079
};
-enum Events
+enum BloodmageThalnosEvents
{
- EVENT_FLAME_SHOCK = 1,
+ EVENT_FLAME_SHOCK = 1,
EVENT_SHADOW_BOLT,
EVENT_FLAME_SPIKE,
EVENT_FIRE_NOVA
};
-class boss_bloodmage_thalnos : public CreatureScript
+struct boss_bloodmage_thalnos : public BossAI
{
- public:
- boss_bloodmage_thalnos() : CreatureScript("boss_bloodmage_thalnos") { }
-
- struct boss_bloodmage_thalnosAI : public BossAI
- {
- boss_bloodmage_thalnosAI(Creature* creature) : BossAI(creature, DATA_BLOODMAGE_THALNOS)
- {
- _hpYell = false;
- }
+ boss_bloodmage_thalnos(Creature* creature) : BossAI(creature, DATA_BLOODMAGE_THALNOS)
+ {
+ _hpYell = false;
+ }
- void Reset() override
- {
- _hpYell = false;
- _Reset();
- }
+ void Reset() override
+ {
+ _hpYell = false;
+ _Reset();
+ }
- void JustEngagedWith(Unit* /*who*/) override
- {
- Talk(SAY_AGGRO);
- _JustEngagedWith();
- events.ScheduleEvent(EVENT_FLAME_SHOCK, 10s);
- events.ScheduleEvent(EVENT_SHADOW_BOLT, 2s);
- events.ScheduleEvent(EVENT_FLAME_SPIKE, 8s);
- events.ScheduleEvent(EVENT_FIRE_NOVA, 40s);
- }
+ void JustEngagedWith(Unit* /*who*/) override
+ {
+ Talk(SAY_AGGRO);
+ _JustEngagedWith();
+ events.ScheduleEvent(EVENT_FLAME_SHOCK, 10s);
+ events.ScheduleEvent(EVENT_SHADOW_BOLT, 2s);
+ events.ScheduleEvent(EVENT_FLAME_SPIKE, 8s);
+ events.ScheduleEvent(EVENT_FIRE_NOVA, 40s);
+ }
- void JustDied(Unit* /*killer*/) override
- {
- _JustDied();
- }
+ void KilledUnit(Unit* victim) override
+ {
+ if (victim->GetTypeId() == TYPEID_PLAYER)
+ Talk(SAY_KILL);
+ }
- void KilledUnit(Unit* /*victim*/) override
- {
- Talk(SAY_KILL);
- }
-
- void DamageTaken(Unit* /*attacker*/, uint32& damage) override
- {
- if (!_hpYell && me->HealthBelowPctDamaged(35, damage))
- {
- Talk(SAY_HEALTH);
- _hpYell = true;
- }
- }
-
- void ExecuteEvent(uint32 eventId) override
- {
- switch (eventId)
- {
- case EVENT_FLAME_SHOCK:
- DoCastVictim(SPELL_FLAMESHOCK);
- events.ScheduleEvent(EVENT_FLAME_SHOCK, 10s, 15s);
- break;
- case EVENT_SHADOW_BOLT:
- DoCastVictim(SPELL_SHADOWBOLT);
- events.ScheduleEvent(EVENT_SHADOW_BOLT, 2s);
- break;
- case EVENT_FLAME_SPIKE:
- DoCastVictim(SPELL_FLAMESPIKE);
- events.ScheduleEvent(EVENT_FLAME_SPIKE, 30s);
- break;
- case EVENT_FIRE_NOVA:
- DoCastVictim(SPELL_FIRENOVA);
- events.ScheduleEvent(EVENT_FIRE_NOVA, 40s);
- break;
- default:
- break;
- }
- }
-
- private:
- bool _hpYell;
- };
+ void DamageTaken(Unit* /*attacker*/, uint32& damage) override
+ {
+ if (!_hpYell && me->HealthBelowPctDamaged(35, damage))
+ {
+ Talk(SAY_HEALTH);
+ _hpYell = true;
+ }
+ }
- CreatureAI* GetAI(Creature* creature) const override
+ void ExecuteEvent(uint32 eventId) override
+ {
+ switch (eventId)
{
- return GetScarletMonasteryAI<boss_bloodmage_thalnosAI>(creature);
+ case EVENT_FLAME_SHOCK:
+ DoCastVictim(SPELL_FLAMESHOCK);
+ events.Repeat(10s, 15s);
+ break;
+ case EVENT_SHADOW_BOLT:
+ DoCastVictim(SPELL_SHADOWBOLT);
+ events.Repeat(2s);
+ break;
+ case EVENT_FLAME_SPIKE:
+ DoCastVictim(SPELL_FLAMESPIKE);
+ events.Repeat(30s);
+ break;
+ case EVENT_FIRE_NOVA:
+ DoCastVictim(SPELL_FIRENOVA);
+ events.Repeat(40s);
+ break;
+ default:
+ break;
}
+ }
+
+private:
+ bool _hpYell;
};
void AddSC_boss_bloodmage_thalnos()
{
- new boss_bloodmage_thalnos();
+ RegisterScarletMonasteryCreatureAI(boss_bloodmage_thalnos);
}
diff --git a/src/server/scripts/EasternKingdoms/ScarletMonastery/boss_headless_horseman.cpp b/src/server/scripts/EasternKingdoms/ScarletMonastery/boss_headless_horseman.cpp
index 56ed8179a18..0bd6a25fe84 100644
--- a/src/server/scripts/EasternKingdoms/ScarletMonastery/boss_headless_horseman.cpp
+++ b/src/server/scripts/EasternKingdoms/ScarletMonastery/boss_headless_horseman.cpp
@@ -16,14 +16,7 @@
* with this program. If not, see <http://www.gnu.org/licenses/>.
*/
-/* ScriptData
-SDName: Boss_Headless_Horseman
-SD%Complete:
-SDComment:
-SDCategory: Scarlet Monastery
-EndScriptData */
-
-#include "ScriptMgr.h"
+#include "scarlet_monastery.h"
#include "GameObject.h"
#include "GameObjectAI.h"
#include "Group.h"
@@ -33,107 +26,143 @@ EndScriptData */
#include "MotionMaster.h"
#include "ObjectAccessor.h"
#include "Player.h"
-#include "scarlet_monastery.h"
#include "ScriptedCreature.h"
+#include "ScriptMgr.h"
#include "SpellInfo.h"
#include "SpellMgr.h"
#include "TemporarySummon.h"
+#include "Timer.h"
-//this texts are already used by 3975 and 3976
-enum Says
+// this texts are already used by 3975 and 3976
+enum HeadlessHorsemanSays
{
- SAY_LOST_HEAD = 0,
- SAY_PLAYER_DEATH = 1,
-
- SAY_ENTRANCE = 0,
- SAY_REJOINED = 1,
- SAY_CONFLAGRATION = 2,
- SAY_SPROUTING_PUMPKINS = 3,
- SAY_DEATH = 4,
+ SAY_LOST_HEAD = 0,
+ SAY_PLAYER_DEATH = 1,
+
+ SAY_ENTRANCE = 0,
+ SAY_REJOINED = 1,
+ SAY_CONFLAGRATION = 2,
+ SAY_SPROUTING_PUMPKINS = 3,
+ SAY_DEATH = 4,
};
-uint32 RandomLaugh[] = {11965, 11975, 11976};
+std::vector<uint32> HeadlessHorsemanRandomLaughSound = { 11965u, 11975u, 11976u };
-enum Entry
+enum HeadlessHorsemanEntry
{
- HH_MOUNTED = 23682,
- HH_DISMOUNTED = 23800,
- HEAD = 23775,
- PULSING_PUMPKIN = 23694,
- PUMPKIN_FIEND = 23545,
- HELPER = 23686,
- WISP_INVIS = 24034
+ NPC_HEADLESS_HORSEMAN_MOUNTED = 23682,
+ NPC_HEADLESS_HORSEMAN_DISMOUNTED = 23800,
+ NPC_HEADLESS_HORSEMAN_HEAD = 23775,
+ NPC_PULSING_PUMPKIN = 23694,
+ NPC_PUMPKIN_FIEND = 23545,
+ NPC_HELPER = 23686,
+ NPC_WISP_INVIS = 24034
};
-enum Spells
+enum HeadlessHorsemanSpells
{
- SPELL_CLEAVE = 42587,
- SPELL_CONFLAGRATION = 42380, //Phase 2, can't find real spell(Dim Fire?)
- // SPELL_CONFL_SPEED = 22587, //8% increase speed, value 22587 from SPELL_CONFLAGRATION mains that spell?
- SPELL_SUMMON_PUMPKIN = 42394,
-
- SPELL_WHIRLWIND = 43116,
- SPELL_IMMUNE = 42556,
- SPELL_BODY_REGEN = 42403,
- SPELL_CONFUSE = 43105,
-
- SPELL_FLYING_HEAD = 42399, //visual flying head
- SPELL_HEAD = 42413, //visual buff, "head"
- SPELL_HEAD_IS_DEAD = 42428, //at killing head, Phase 3
-
- SPELL_PUMPKIN_AURA = 42280,
- SPELL_PUMPKIN_AURA_GREEN = 42294,
- SPELL_SQUASH_SOUL = 42514,
- SPELL_SPROUTING = 42281,
- SPELL_SPROUT_BODY = 42285,
-
- //Effects
- SPELL_RHYME_BIG = 42909,
- // SPELL_RHYME_SMALL = 42910,
- SPELL_HEAD_SPEAKS = 43129,
- SPELL_HEAD_LANDS = 42400,
- SPELL_BODY_FLAME = 42074,
- SPELL_HEAD_FLAME = 42971,
- // SPELL_ENRAGE_VISUAL = 42438, // he uses this spell?
- SPELL_WISP_BLUE = 42821,
- SPELL_WISP_FLIGHT_PORT = 42818,
- // SPELL_WISP_INVIS = 42823,
- SPELL_SMOKE = 42355,
- SPELL_DEATH = 42566 //not correct spell
+ SPELL_CONFLAGRATION = 42380,
+ SPELL_HORSEMANS_CONFLAGRATION = 42381, // Triggered from SPELL_CONFLAGRATION
+ SPELL_HORSEMANS_SUMMON = 42394,
+ SPELL_HEADLESS_HORSEMAN_CLIMAX___HORSEMANS_WHIRLWIND = 43116,
+ SPELL_HEADLESS_HORSEMAN_CLIMAX___BODY_REGEN_REMOVED_ON_DEATH = 42556,
+ SPELL_HORSEMANS_CLEAVE = 42587, // Triggered from SPELL_HEADLESS_HORSEMAN_CLIMAX___BODY_REGEN_REMOVED_ON_DEATH
+ SPELL_HEADLESS_HORSEMAN_CLIMAX___BODY_REGEN = 42403,
+ SPELL_HEADLESS_HORSEMAN_CLIMAX___BODY_REGEN_CONFUSE_ONLY_REMOVED_ON_DEATH = 43105,
+ SPELL_HEADLESS_HORSEMAN_CLIMAX___SEND_HEAD = 42399, // Visual flying head
+ SPELL_HEADLESS_HORSEMAN_CLIMAX___HEAD_VISUAL = 42413, // Visual buff, "head"
+ SPELL_HEADLESS_HORSEMAN_CLIMAX___HEAD_IS_DEAD = 42428, // At killing head, Phase 3
+ SPELL_HEADLESS_HORSEMAN_CLIMAX___HEAD_IS_DEAD_TRIGGERED = 42566, // Triggered from SPELL_HEADLESS_HORSEMAN_CLIMAX___HEAD_IS_DEAD
+ SPELL_PUMPKIN_LIFE_CYCLE = 42280,
+ SPELL_HEADLESS_HORSEMAN___PUMPKIN_AURA = 42294,
+ SPELL_SQUASH_SOUL = 42514,
+ SPELL_SPROUTING = 42281,
+ SPELL_SPROUT_BODY = 42285,
+ SPELL_HEADLESS_HORSEMAN_CLIMAX___SUMMONING_RHYME_SHAKE_MEDIUM = 42909,
+ SPELL_HEADLESS_HORSEMAN_CLIMAX___SUMMONING_RHYME_SHAKE_SMALL = 42910,
+ SPELL_HEADLESS_HORSEMAN___SPEAKS = 43129,
+ SPELL_HEADLESS_HORSEMAN_CLIMAX___HEAD_LANDS = 42400,
+ SPELL_HEADLESS_HORSEMAN___FIRE = 42074,
+ SPELL_HEADLESS_HORSEMAN___BURNING_COSMETIC = 42971,
+ SPELL_HEADLESS_HORSEMAN_CLIMAX___ENRAGED_VISUAL = 42438, // Is this used?
+ SPELL_HEADLESS_HORSEMAN___WISP_FLIGHT_MISSILE = 42821,
+ SPELL_HEADLESS_HORSEMAN___WISP_FLIGHT_PORT = 42818, // Triggered from SPELL_HEADLESS_HORSEMAN___WISP_FLIGHT_MISSILE
+ SPELL_HEADLESS_HORSEMAN___WISP_INVIS = 42823,
+ SPELL_HEADLESS_HORSEMAN___SMOKE = 42355,
+};
+
+enum HeadlessHorsemanMisc
+{
+ DISPLAYID_INVIS_WISP_MAN = 2027,
+ DISPLAYID_INVIS_WISP_INVISIBLE = 21908,
+
+ DATA_INVIS_WISP_CREATURE_TYPE = 0,
+ DATA_HEAD_TALK,
+ DATA_HEAD_PHASE,
+
+ INVIS_WISP_CREATURE_TYPE_PUMPKIN = 1,
+ INVIS_WISP_CREATURE_TYPE_FLAME,
+ INVIS_WISP_CREATURE_TYPE_SMOKE,
+ INVIS_WISP_CREATURE_TYPE_BLUE,
+
+ ACTION_HEAD_RETURN_TO_BODY = 0,
+ ACTION_HEAD_KILLED,
+ ACTION_HORSEMAN_EVENT_START,
+
+ PHASE_HEAD_1 = 1,
+ PHASE_HEAD_2,
+ PHASE_HEAD_3,
+
+ PHASE_BODY_0 = 0,
+ PHASE_BODY_1,
+ PHASE_BODY_2,
+ PHASE_BODY_3,
+
+ TASK_GROUP_COMBAT = 1,
+ TASK_GROUP_WITHOUT_HEAD,
+
+ POINT_HORSEMAN_0 = 0,
+ POINT_HORSEMAN_1 = 1,
+ POINT_HORSEMAN_6 = 6,
+ POINT_HORSEMAN_19 = 19,
+ POINT_HORSEMAN_20 = 20,
+
+ LFG_DUNGEONID_THE_HEADLESS_HORSEMAN = 285,
};
-Position const FlightPoint[]=
+std::vector<Position> const HeadlessHorsemanFlightPoints =
{
- {1754.00f, 1346.00f, 17.50f},
- {1765.00f, 1347.00f, 19.00f},
- {1784.00f, 1346.80f, 25.40f},
- {1803.30f, 1347.60f, 33.00f},
- {1824.00f, 1350.00f, 42.60f},
- {1838.80f, 1353.20f, 49.80f},
- {1852.00f, 1357.60f, 55.70f},
- {1861.30f, 1364.00f, 59.40f},
- {1866.30f, 1374.80f, 61.70f},
- {1864.00f, 1387.30f, 63.20f},
- {1854.80f, 1399.40f, 64.10f},
- {1844.00f, 1406.90f, 64.10f},
- {1824.30f, 1411.40f, 63.30f},
- {1801.00f, 1412.30f, 60.40f},
- {1782.00f, 1410.10f, 55.50f},
- {1770.50f, 1405.20f, 50.30f},
- {1765.20f, 1400.70f, 46.60f},
- {1761.40f, 1393.40f, 41.70f},
- {1759.10f, 1386.70f, 36.60f},
- {1757.80f, 1378.20f, 29.00f},
- {1758.00f, 1367.00f, 19.51f}
+ { 1754.00f, 1346.00f, 17.50f },
+ { 1765.00f, 1347.00f, 19.00f },
+ { 1784.00f, 1346.80f, 25.40f },
+ { 1803.30f, 1347.60f, 33.00f },
+ { 1824.00f, 1350.00f, 42.60f },
+ { 1838.80f, 1353.20f, 49.80f },
+ { 1852.00f, 1357.60f, 55.70f },
+ { 1861.30f, 1364.00f, 59.40f },
+ { 1866.30f, 1374.80f, 61.70f },
+ { 1864.00f, 1387.30f, 63.20f },
+ { 1854.80f, 1399.40f, 64.10f },
+ { 1844.00f, 1406.90f, 64.10f },
+ { 1824.30f, 1411.40f, 63.30f },
+ { 1801.00f, 1412.30f, 60.40f },
+ { 1782.00f, 1410.10f, 55.50f },
+ { 1770.50f, 1405.20f, 50.30f },
+ { 1765.20f, 1400.70f, 46.60f },
+ { 1761.40f, 1393.40f, 41.70f },
+ { 1759.10f, 1386.70f, 36.60f },
+ { 1757.80f, 1378.20f, 29.00f },
+ { 1758.00f, 1367.00f, 19.51f }
};
-Position const Spawn[]=
+std::vector<Position> const HeadlessHorsemanSpawnPoints =
{
- {1776.27f, 1348.74f, 19.20f}, //spawn point for pumpkin shrine mob
- {1765.28f, 1347.46f, 17.55f} //spawn point for smoke
+ { 1776.27f, 1348.74f, 19.20f }, // spawn point for pumpkin shrine mob
+ { 1765.28f, 1347.46f, 17.55f } // spawn point for smoke
};
-static char const* Text[]=
+//@todo Dear Lord, please someone have mercy and let this die soon
+static char const* HeadlessHorsemanInitialPlayerTexts[] =
{
"Horseman rise...",
"Your time is nigh...",
@@ -141,805 +170,755 @@ static char const* Text[]=
"Now, know demise!"
};
-class npc_wisp_invis : public CreatureScript
+struct npc_wisp_invis : public ScriptedAI
{
-public:
- npc_wisp_invis() : CreatureScript("npc_wisp_invis") { }
-
- CreatureAI* GetAI(Creature* creature) const override
+ npc_wisp_invis(Creature* creature) : ScriptedAI(creature), _timer(0), _creatureType(0), _firstSpell(0), _secondSpell(0)
{
- return GetScarletMonasteryAI<npc_wisp_invisAI>(creature);
+ creature->SetDisplayId(DISPLAYID_INVIS_WISP_INVISIBLE);
}
- struct npc_wisp_invisAI : public ScriptedAI
+ void SetData(uint32 type, uint32 value) override
{
- npc_wisp_invisAI(Creature* creature) : ScriptedAI(creature)
- {
- Creaturetype = delay = _spell = _spell2 = 0;
- }
+ if (type != DATA_INVIS_WISP_CREATURE_TYPE)
+ return;
+
+ switch (_creatureType = value)
+ {
+ case INVIS_WISP_CREATURE_TYPE_PUMPKIN:
+ _firstSpell = SPELL_HEADLESS_HORSEMAN___PUMPKIN_AURA;
+ break;
+ case INVIS_WISP_CREATURE_TYPE_FLAME:
+ _timer.Reset(15 * IN_MILLISECONDS);
+ _firstSpell = SPELL_HEADLESS_HORSEMAN___FIRE;
+ _secondSpell = SPELL_HEADLESS_HORSEMAN_CLIMAX___HEAD_IS_DEAD;
+ break;
+ case INVIS_WISP_CREATURE_TYPE_SMOKE:
+ _timer.Reset(15 * IN_MILLISECONDS);
+ _firstSpell = SPELL_HEADLESS_HORSEMAN___SMOKE;
+ break;
+ case INVIS_WISP_CREATURE_TYPE_BLUE:
+ _timer.Reset(7 * IN_MILLISECONDS);
+ _secondSpell = SPELL_HEADLESS_HORSEMAN___WISP_FLIGHT_MISSILE;
+ break;
+ default:
+ break;
+ }
+ if (_firstSpell)
+ DoCastSelf(_firstSpell);
+ }
- uint32 Creaturetype;
- uint32 delay;
- uint32 _spell;
- uint32 _spell2;
- void Reset() override { }
- void JustEngagedWith(Unit* /*who*/) override { }
- void SetType(uint32 _type)
- {
- switch (Creaturetype = _type)
- {
- case 1:
- _spell = SPELL_PUMPKIN_AURA_GREEN;
- break;
- case 2:
- delay = 15000;
- _spell = SPELL_BODY_FLAME;
- _spell2 = SPELL_DEATH;
- break;
- case 3:
- delay = 15000;
- _spell = SPELL_SMOKE;
- break;
- case 4:
- delay = 7000;
- _spell2 = SPELL_WISP_BLUE;
- break;
- }
- if (_spell)
- DoCast(me, _spell);
- }
+ void SpellHit(Unit* /*caster*/, SpellInfo const* spellInfo) override
+ {
+ if (spellInfo->Id == SPELL_HEADLESS_HORSEMAN___WISP_FLIGHT_PORT && _creatureType == 4)
+ me->SetDisplayId(DISPLAYID_INVIS_WISP_MAN);
+ }
- void SpellHit(Unit* /*caster*/, SpellInfo const* spell) override
- {
- if (spell->Id == SPELL_WISP_FLIGHT_PORT && Creaturetype == 4)
- me->SetDisplayId(2027);
- }
+ void MoveInLineOfSight(Unit* who) override
+ {
+ if (!who || _creatureType != INVIS_WISP_CREATURE_TYPE_PUMPKIN || !who->isTargetableForAttack())
+ return;
- void MoveInLineOfSight(Unit* who) override
- {
- if (!who || Creaturetype != 1 || !who->isTargetableForAttack())
- return;
+ if (me->IsWithinDist(who, 0.1f, false) && !who->HasAura(SPELL_SQUASH_SOUL))
+ DoCast(who, SPELL_SQUASH_SOUL);
+ }
- if (me->IsWithinDist(who, 0.1f, false) && !who->HasAura(SPELL_SQUASH_SOUL))
- DoCast(who, SPELL_SQUASH_SOUL);
- }
+ void UpdateAI(uint32 diff) override
+ {
+ if (_timer.Passed())
+ return;
- void UpdateAI(uint32 diff) override
+ _timer.Update(diff);
+ if (_timer.Passed())
{
- if (delay)
- {
- if (delay <= diff)
- {
- me->RemoveAurasDueToSpell(SPELL_SMOKE);
- if (_spell2)
- DoCast(me, _spell2);
- delay = 0;
- } else delay -= diff;
- }
+ me->RemoveAurasDueToSpell(SPELL_HEADLESS_HORSEMAN___SMOKE);
+ if (_secondSpell)
+ DoCast(me, _secondSpell);
+ _timer.Reset(0);
}
- };
+ }
+
+private:
+ TimeTrackerSmall _timer;
+ uint32 _creatureType;
+ uint32 _firstSpell;
+ uint32 _secondSpell;
};
-class npc_head : public CreatureScript
+struct npc_head : public ScriptedAI
{
-public:
- npc_head() : CreatureScript("npc_head") { }
-
- CreatureAI* GetAI(Creature* creature) const override
+ npc_head(Creature* creature) : ScriptedAI(creature), _laughTimer(urand(15 * IN_MILLISECONDS, 30 * IN_MILLISECONDS))
{
- return GetScarletMonasteryAI<npc_headAI>(creature);
+ creature->SetReactState(REACT_PASSIVE);
+ Initialize();
}
- struct npc_headAI : public ScriptedAI
+ void Initialize()
{
- npc_headAI(Creature* creature) : ScriptedAI(creature)
- {
- Initialize();
- }
-
- void Initialize()
- {
- Phase = 0;
- bodyGUID.Clear();
- die = false;
- withbody = true;
- wait = 1000;
- laugh = urand(15000, 30000);
- }
-
- ObjectGuid bodyGUID;
-
- uint32 Phase;
- uint32 laugh;
- uint32 wait;
-
- bool withbody;
- bool die;
+ _bodyGUID = ObjectGuid::Empty;
+ _phase = 0;
+ _withBody = true;
+ _die = false;
+ }
- void Reset() override
- {
- Initialize();
- }
+ void Reset() override
+ {
+ Initialize();
+ _laughTimer.Reset(urand(15 * IN_MILLISECONDS, 30 * IN_MILLISECONDS));
+ _scheduler.CancelAll();
- void JustEngagedWith(Unit* /*who*/) override { }
+ // Just to be sure it's MOTION_SLOT_DEFAULT is static
+ me->GetMotionMaster()->MoveIdle();
+ }
- void SaySound(uint8 textEntry, Unit* target = 0)
+ void SetData(uint32 type, uint32 value) override
+ {
+ switch (type)
{
- Talk(textEntry, target);
-
- //DoCast(me, SPELL_HEAD_SPEAKS, true);
- if (Creature* speaker = DoSpawnCreature(HELPER, 0, 0, 0, 0, TEMPSUMMON_TIMED_DESPAWN, 1000))
- speaker->CastSpell(speaker, SPELL_HEAD_SPEAKS, false);
- laugh += 3000;
+ case DATA_HEAD_TALK:
+ DoTalk(value);
+ break;
+ case DATA_HEAD_PHASE:
+ _phase = value;
+ break;
+ default:
+ break;
}
+ }
- void DamageTaken(Unit* /*done_by*/, uint32 &damage) override
- {
- if (withbody)
- return;
-
- switch (Phase)
- {
- case 1:
- if (me->HealthBelowPctDamaged(67, damage))
- Disappear();
- break;
- case 2:
- if (me->HealthBelowPctDamaged(34, damage))
- Disappear();
- break;
- case 3:
- if (damage >= me->GetHealth())
- {
- die = true;
- withbody = true;
- wait = 300;
- damage = me->GetHealth() - me->CountPctFromMaxHealth(1);
- me->SetFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NON_ATTACKABLE);
- me->StopMoving();
- //me->GetMotionMaster()->MoveIdle();
- DoCast(me, SPELL_HEAD_IS_DEAD);
- }
- break;
- }
- }
+ void DamageTaken(Unit* /*attacker*/, uint32& damage) override
+ {
+ if (_withBody)
+ return;
- void SpellHit(Unit* caster, SpellInfo const* spell) override
+ if (_die)
{
- if (!withbody)
- return;
-
- if (spell->Id == SPELL_FLYING_HEAD)
- {
- if (Phase < 3)
- ++Phase;
- else
- Phase = 3;
-
- withbody = false;
- if (!bodyGUID)
- bodyGUID = caster->GetGUID();
- me->RemoveAllAuras();
- me->RemoveFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NOT_SELECTABLE);
- DoCast(me, SPELL_HEAD_LANDS, true);
- DoCast(me, SPELL_HEAD, false);
- SaySound(SAY_LOST_HEAD);
- me->GetMotionMaster()->Clear();
- me->GetMotionMaster()->MoveFleeing(caster->GetVictim());
- }
+ damage = 0;
+ return;
}
- void Disappear();
- void UpdateAI(uint32 diff) override
+ switch (_phase)
{
- if (!withbody)
- {
- if (wait <= diff)
+ case PHASE_HEAD_1:
+ if (me->HealthBelowPctDamaged(67, damage))
+ ReturnToBody(true);
+ break;
+ case PHASE_HEAD_2:
+ if (me->HealthBelowPctDamaged(34, damage))
+ ReturnToBody(true);
+ break;
+ case PHASE_HEAD_3:
+ if (!_die && damage >= me->GetHealth())
{
- wait = 1000;
- if (!me->GetVictim())
- return;
+ _die = true;
+ damage = 0;
+ me->SetFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NON_ATTACKABLE);
me->GetMotionMaster()->Clear();
- me->GetMotionMaster()->MoveFleeing(me->GetVictim());
- }
- else wait -= diff;
- if (laugh <= diff)
- {
- laugh = urand(15000, 30000);
- DoPlaySoundToSet(me, RandomLaugh[urand(0, 2)]);
- //DoCast(me, SPELL_HEAD_SPEAKS, true); //this spell remove buff "head"
- Creature* speaker = DoSpawnCreature(HELPER, 0, 0, 0, 0, TEMPSUMMON_TIMED_DESPAWN, 1000);
- if (speaker)
- speaker->CastSpell(speaker, SPELL_HEAD_SPEAKS, false);
- }
- else laugh -= diff;
- }
- else
- {
- if (die)
- {
- if (wait <= diff)
+ DoCastSelf(SPELL_HEADLESS_HORSEMAN_CLIMAX___HEAD_IS_DEAD);
+
+ _scheduler.Schedule(3s, [this](TaskContext /*context*/)
{
- die = false;
- if (Unit* body = ObjectAccessor::GetUnit(*me, bodyGUID))
+ if (Unit* body = ObjectAccessor::GetUnit(*me, _bodyGUID))
body->KillSelf();
me->KillSelf();
- }
- else wait -= diff;
+ });
}
- }
+ break;
+ default:
+ break;
}
- };
-};
-
-class boss_headless_horseman : public CreatureScript
-{
-public:
- boss_headless_horseman() : CreatureScript("boss_headless_horseman") { }
-
- CreatureAI* GetAI(Creature* creature) const override
- {
- return GetScarletMonasteryAI<boss_headless_horsemanAI>(creature);
}
- struct boss_headless_horsemanAI : public ScriptedAI
+ void SpellHit(Unit* caster, SpellInfo const* spell) override
{
- boss_headless_horsemanAI(Creature* creature) : ScriptedAI(creature)
- {
- Initialize();
- instance = creature->GetInstanceScript();
- id = 0;
- whirlwind = 0;
- wp_reached = false;
- }
+ if (!_withBody)
+ return;
- void Initialize()
+ if (spell->Id == SPELL_HEADLESS_HORSEMAN_CLIMAX___SEND_HEAD)
{
- Phase = 1;
- conflagrate = 15000;
- summonadds = 15000;
- laugh = urand(16000, 20000);
- cleave = 2000;
- regen = 1000;
- burn = 6000;
- count = 0;
- say_timer = 3000;
-
- withhead = true;
- returned = true;
- burned = false;
- IsFlying = false;
- }
-
- InstanceScript* instance;
+ _withBody = false;
- ObjectGuid headGUID;
- ObjectGuid PlayerGUID;
+ if (!_bodyGUID)
+ _bodyGUID = caster->GetGUID();
- uint32 Phase;
- uint32 id;
- uint32 count;
- uint32 say_timer;
+ me->RemoveAllAuras();
+ me->RemoveFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NOT_SELECTABLE);
+ me->GetMotionMaster()->Clear();
- uint32 conflagrate;
- uint32 summonadds;
- uint32 cleave;
- uint32 regen;
- uint32 whirlwind;
- uint32 laugh;
- uint32 burn;
+ DoCastSelf(SPELL_HEADLESS_HORSEMAN_CLIMAX___HEAD_LANDS, true);
+ DoCastSelf(SPELL_HEADLESS_HORSEMAN_CLIMAX___HEAD_VISUAL);
- bool withhead;
- bool returned;
- bool IsFlying;
- bool wp_reached;
- bool burned;
+ DoTalk(SAY_LOST_HEAD);
- void Reset() override
- {
- Initialize();
- DoCast(me, SPELL_HEAD);
- if (headGUID)
+ _scheduler.Schedule(2s, [caster, this](TaskContext /*context*/)
{
- if (Creature* Head = ObjectAccessor::GetCreature((*me), headGUID))
- Head->DespawnOrUnsummon();
-
- headGUID.Clear();
- }
-
- me->SetImmuneToPC(false);
- //instance->SetBossState(DATA_HORSEMAN_EVENT, NOT_STARTED);
+ me->GetMotionMaster()->MoveFleeing(caster);
+ });
}
+ }
- void FlyMode()
+ void DoAction(int32 param) override
+ {
+ switch (param)
{
- me->SetVisible(false);
- me->SetFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NON_ATTACKABLE);
- me->SetDisableGravity(true);
- me->SetSpeedRate(MOVE_WALK, 5.0f);
- wp_reached = false;
- count = 0;
- say_timer = 3000;
- id = 0;
- Phase = 0;
+ case ACTION_HEAD_RETURN_TO_BODY:
+ ReturnToBody(false);
+ break;
+ default:
+ break;
}
+ }
- void MovementInform(uint32 type, uint32 i) override
- {
- if (type != POINT_MOTION_TYPE || !IsFlying || i != id)
- return;
+ void UpdateAI(uint32 diff) override
+ {
+ _scheduler.Update(diff);
- wp_reached = true;
+ if (_withBody)
+ return;
- switch (id)
- {
- case 0:
- me->SetVisible(true);
- break;
- case 1:
- {
- if (Creature* smoke = me->SummonCreature(HELPER, Spawn[1], TEMPSUMMON_TIMED_DESPAWN, 20000))
- ENSURE_AI(npc_wisp_invis::npc_wisp_invisAI, smoke->AI())->SetType(3);
- DoCast(me, SPELL_RHYME_BIG);
- break;
- }
- case 6:
- instance->SetData(DATA_PUMPKIN_SHRINE, 0); //hide gameobject
- break;
- case 19:
- me->SetDisableGravity(false);
- break;
- case 20:
- {
- Phase = 1;
- IsFlying = false;
- wp_reached = false;
- me->RemoveFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NON_ATTACKABLE);
- SaySound(SAY_ENTRANCE);
- if (Unit* player = ObjectAccessor::GetUnit(*me, PlayerGUID))
- DoStartMovement(player);
- break;
- }
- }
- ++id;
- }
+ if (!_laughTimer.Passed())
+ _laughTimer.Update(diff);
- void JustEngagedWith(Unit* /*who*/) override
+ if (_laughTimer.Passed())
{
- instance->SetBossState(DATA_HORSEMAN_EVENT, IN_PROGRESS);
- DoZoneInCombat();
- }
+ _laughTimer.Reset(urand(15 * IN_MILLISECONDS, 30 * IN_MILLISECONDS));
- void AttackStart(Unit* who) override
- {
- ScriptedAI::AttackStart(who);
- }
+ DoPlaySoundToSet(me, Trinity::Containers::SelectRandomContainerElement(HeadlessHorsemanRandomLaughSound));
- void MoveInLineOfSight(Unit* who) override
- {
- if (withhead && Phase != 0)
- ScriptedAI::MoveInLineOfSight(who);
+ if (Creature* speaker = DoSpawnCreature(NPC_HELPER, 0.f, 0.f, 0.f, 0.f, TEMPSUMMON_TIMED_DESPAWN, 1 * IN_MILLISECONDS))
+ speaker->CastSpell(speaker, SPELL_HEADLESS_HORSEMAN___SPEAKS, false);
}
+ }
- void KilledUnit(Unit* player) override
- {
- if (player->GetTypeId() == TYPEID_PLAYER)
- {
- if (withhead)
- SaySound(SAY_PLAYER_DEATH);
- //maybe possible when player dies from conflagration
- else if (Creature* Head = ObjectAccessor::GetCreature((*me), headGUID))
- ENSURE_AI(npc_head::npc_headAI, Head->AI())->SaySound(SAY_PLAYER_DEATH);
- }
- }
+private:
+ void ReturnToBody(bool advance)
+ {
+ if (_withBody || _bodyGUID.IsEmpty())
+ return;
- void SaySound(uint8 textEntry, Unit* target = 0)
+ Creature* body = ObjectAccessor::GetCreature(*me, _bodyGUID);
+ if (!body || !body->IsAlive())
{
- Talk(textEntry, target);
- laugh += 4000;
+ me->DespawnOrUnsummon();
+ return;
}
- Player* SelectRandomPlayer(float range = 0.0f, bool checkLoS = true)
- {
- Map::PlayerList const& PlayerList = me->GetMap()->GetPlayers();
- if (PlayerList.isEmpty())
- return nullptr;
+ _withBody = true;
+ me->RemoveAllAuras();
+ me->SetFullHealth();
+ me->SetFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NON_ATTACKABLE | UNIT_FLAG_NOT_SELECTABLE);
+ me->GetMotionMaster()->MoveIdle();
- std::list<Player*> temp;
- for (Map::PlayerList::const_iterator i = PlayerList.begin(); i != PlayerList.end(); ++i)
- if ((me->IsWithinLOSInMap(i->GetSource()) || !checkLoS) && me->GetVictim() != i->GetSource() &&
- me->IsWithinDistInMap(i->GetSource(), range) && i->GetSource()->IsAlive())
- temp.push_back(i->GetSource());
+ if (advance)
+ body->AI()->DoAction(ACTION_HEAD_KILLED);
- if (!temp.empty())
- {
- std::list<Player*>::const_iterator j = temp.begin();
- advance(j, rand32() % temp.size());
- return (*j);
- }
- return nullptr;
- }
+ body->RemoveAurasDueToSpell(SPELL_HEADLESS_HORSEMAN_CLIMAX___BODY_REGEN_REMOVED_ON_DEATH); // hack, SpellHit doesn't calls if body has immune aura
+ DoCast(body, SPELL_HEADLESS_HORSEMAN_CLIMAX___SEND_HEAD);
+ }
- void SpellHitTarget(Unit* unit, SpellInfo const* spell) override
- {
- if (spell->Id == SPELL_CONFLAGRATION && unit->HasAura(SPELL_CONFLAGRATION))
- SaySound(SAY_CONFLAGRATION, unit);
- }
+ void DoTalk(uint32 entry)
+ {
+ Talk(entry);
+ _laughTimer.Reset(3 * IN_MILLISECONDS);
- void JustDied(Unit* /*killer*/) override
+ if (Creature* speaker = DoSpawnCreature(NPC_HELPER, 0.f, 0.f, 0.f, 0.f, TEMPSUMMON_TIMED_DESPAWN, 1 * IN_MILLISECONDS))
+ speaker->CastSpell(speaker, SPELL_HEADLESS_HORSEMAN___SPEAKS, false);
+ }
+
+ TaskScheduler _scheduler;
+ TimeTrackerSmall _laughTimer;
+ ObjectGuid _bodyGUID;
+ uint32 _phase;
+ bool _withBody;
+ bool _die;
+};
+
+struct boss_headless_horseman : public ScriptedAI
+{
+ boss_headless_horseman(Creature* creature) : ScriptedAI(creature), _instance(creature->GetInstanceScript()), _laughTimer(0), _phase(0), _id(0)
+ {
+ Initialize();
+
+ _scheduler.SetValidator([this]
{
- me->StopMoving();
- //me->GetMotionMaster()->MoveIdle();
- SaySound(SAY_DEATH);
- if (Creature* flame = DoSpawnCreature(HELPER, 0, 0, 0, 0, TEMPSUMMON_TIMED_DESPAWN, 60000))
- flame->CastSpell(flame, SPELL_BODY_FLAME, false);
- if (Creature* wisp = DoSpawnCreature(WISP_INVIS, 0, 0, 0, 0, TEMPSUMMON_TIMED_DESPAWN, 60000))
- ENSURE_AI(npc_wisp_invis::npc_wisp_invisAI, wisp->AI())->SetType(4);
- instance->SetBossState(DATA_HORSEMAN_EVENT, DONE);
-
- Map::PlayerList const& players = me->GetMap()->GetPlayers();
- if (!players.isEmpty())
- {
- if (Group* group = players.begin()->GetSource()->GetGroup())
- if (group->isLFGGroup())
- sLFGMgr->FinishDungeon(group->GetGUID(), 285, me->GetMap());
- }
- }
+ return !me->HasUnitState(UNIT_STATE_CASTING);
+ });
+ }
+
+ void Initialize()
+ {
+ _withHead = true;
+ }
+
+ void InitializeAI() override
+ {
+ me->SetImmuneToPC(false);
+ ScriptedAI::InitializeAI();
+ }
- void SpellHit(Unit* caster, SpellInfo const* spell) override
+ void Reset() override
+ {
+ _laughTimer.Reset(0);
+ Initialize();
+
+ DoCastSelf(SPELL_HEADLESS_HORSEMAN_CLIMAX___HEAD_VISUAL);
+ if (_headGUID)
{
- if (withhead)
- return;
+ if (Creature* head = ObjectAccessor::GetCreature(*me, _headGUID))
+ head->DespawnOrUnsummon();
- if (spell->Id == SPELL_FLYING_HEAD)
- {
- if (Phase < 3)
- ++Phase;
- else
- Phase = 3;
- withhead = true;
- me->RemoveAllAuras();
- me->SetName("Headless Horseman");
- me->SetFullHealth();
- SaySound(SAY_REJOINED);
- DoCast(me, SPELL_HEAD);
- caster->GetMotionMaster()->Clear();
- caster->GetMotionMaster()->MoveFollow(me, 6, float(urand(0, 5)));
- }
+ _headGUID.Clear();
}
- void DamageTaken(Unit* /*done_by*/, uint32 &damage) override
- {
- if (damage >= me->GetHealth() && withhead)
- {
- withhead = false;
- returned = false;
- damage = me->GetHealth() - me->CountPctFromMaxHealth(1);
- me->RemoveAllAuras();
- me->SetName("Headless Horseman, Unhorsed");
+ me->SetImmuneToPC(false);
- if (!headGUID)
- headGUID = DoSpawnCreature(HEAD, float(rand32() % 6), float(rand32() % 6), 0, 0, TEMPSUMMON_DEAD_DESPAWN, 0)->GetGUID();
+ // Just to be sure it's MOTION_SLOT_DEFAULT is static
+ me->GetMotionMaster()->MoveIdle();
- Unit* Head = ObjectAccessor::GetUnit(*me, headGUID);
- if (Head && Head->IsAlive())
- {
- Head->RemoveFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NON_ATTACKABLE);
- //Head->CastSpell(Head, SPELL_HEAD_INVIS, false);
- me->InterruptNonMeleeSpells(false);
- DoCast(me, SPELL_IMMUNE, true);
- DoCast(me, SPELL_BODY_REGEN, true);
- DoCast(Head, SPELL_FLYING_HEAD, true);
- DoCast(me, SPELL_CONFUSE, false); //test
- whirlwind = urand(4000, 8000);
- regen = 0;
- }
- }
- }
+ _instance->SetBossState(DATA_HORSEMAN_EVENT, NOT_STARTED);
+ }
+
+ void EnterEvadeMode(EvadeReason why) override
+ {
+ _phase = PHASE_BODY_1;
+ ScriptedAI::EnterEvadeMode(why);
+ }
- void UpdateAI(uint32 diff) override
+ void DoAction(int32 param) override
+ {
+ switch (param)
{
- if (withhead)
- {
- switch (Phase)
+ case ACTION_HORSEMAN_EVENT_START:
+ me->SetVisible(false);
+ me->SetFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NON_ATTACKABLE);
+ me->SetCanFly(true);
+ me->SetWalk(false);
+
+ _id = 0;
+ _phase = PHASE_BODY_0;
+
+ _scheduler.Schedule(3s, [this](TaskContext talkContext)
{
- case 0:
+ if (talkContext.GetRepeatCounter() < 3)
{
- if (!IsFlying)
+ if (me->GetMap()->HavePlayers())
{
- if (say_timer <= diff)
- {
- say_timer = 3000;
- Player* player = SelectRandomPlayer(100.0f, false);
- if (count < 3)
- {
- if (player)
- player->Say(Text[count], LANG_UNIVERSAL);
- }
- else
- {
- DoCast(me, SPELL_RHYME_BIG);
- if (player)
- {
- player->Say(Text[count], LANG_UNIVERSAL);
- player->HandleEmoteCommand(ANIM_EMOTE_SHOUT);
- }
- wp_reached = true;
- IsFlying = true;
- count = 0;
- break;
- }
- ++count;
- }
- else say_timer -= diff;
+ RefManager<Map, Player> const& players = me->GetMap()->GetPlayers();
+ LinkedListHead::Iterator<Reference<Map, Player> const> it = players.RefManager<Map, Player>::begin();
+ std::advance(it, urand(0, uint32(me->GetMap()->GetPlayers().getSize()) - 1));
+ if (Player* player = it->GetSource())
+ player->Say(HeadlessHorsemanInitialPlayerTexts[talkContext.GetRepeatCounter()], LANG_UNIVERSAL);
}
- else
+ talkContext.Repeat(3s);
+ }
+ else
+ {
+ DoCast(SPELL_HEADLESS_HORSEMAN_CLIMAX___SUMMONING_RHYME_SHAKE_MEDIUM);
+ if (me->GetMap()->HavePlayers())
{
- if (wp_reached)
+ RefManager<Map, Player> const& players = me->GetMap()->GetPlayers();
+ LinkedListHead::Iterator<Reference<Map, Player> const> it = players.RefManager<Map, Player>::begin();
+ std::advance(it, urand(0, uint32(me->GetMap()->GetPlayers().getSize()) - 1));
+ if (Player* player = it->GetSource())
{
- wp_reached = false;
- me->GetMotionMaster()->Clear();
- me->GetMotionMaster()->MovePoint(id, FlightPoint[id]);
+ player->Say(HeadlessHorsemanInitialPlayerTexts[talkContext.GetRepeatCounter()], LANG_UNIVERSAL);
+ player->HandleEmoteCommand(ANIM_EMOTE_SHOUT);
}
}
+
+ me->GetMotionMaster()->MovePoint(_id, HeadlessHorsemanFlightPoints[_id]);
}
- break;
- case 1:
- if (burned)
- break;
- if (burn <= diff)
- {
- if (Creature* flame = me->SummonCreature(HELPER, Spawn[0], TEMPSUMMON_TIMED_DESPAWN, 17000))
- ENSURE_AI(npc_wisp_invis::npc_wisp_invisAI, flame->AI())->SetType(2);
- burned = true;
- }
- else burn -= diff;
- break;
- case 2:
- if (conflagrate <= diff)
- {
- if (Unit* player = SelectRandomPlayer(30.0f))
- DoCast(player, SPELL_CONFLAGRATION, false);
- conflagrate = urand(10000, 16000);
- }
- else conflagrate -= diff;
- break;
- case 3:
- if (summonadds <= diff)
- {
- me->InterruptNonMeleeSpells(false);
- DoCast(me, SPELL_SUMMON_PUMPKIN);
- SaySound(SAY_SPROUTING_PUMPKINS);
- summonadds = urand(25000, 35000);
- }
- else summonadds -= diff;
- break;
- }
+ });
+ break;
+ case ACTION_HEAD_KILLED:
+ if (_phase < 3)
+ ++_phase;
+ else
+ _phase = 3;
+ break;
+ default:
+ break;
+ }
+ }
- if (laugh <= diff)
- {
- laugh = urand(11000, 22000);
- DoPlaySoundToSet(me, RandomLaugh[rand32() % 3]);
- }
- else laugh -= diff;
+ void MovementInform(uint32 type, uint32 id) override
+ {
+ if (type != POINT_MOTION_TYPE || _phase != PHASE_BODY_0 || id != _id)
+ return;
+
+ switch (id)
+ {
+ case POINT_HORSEMAN_0:
+ me->SetVisible(true);
+ break;
+ case POINT_HORSEMAN_1:
+ if (Creature* smoke = me->SummonCreature(NPC_HELPER, HeadlessHorsemanSpawnPoints[1], TEMPSUMMON_TIMED_DESPAWN, 20 * IN_MILLISECONDS))
+ smoke->AI()->SetData(DATA_INVIS_WISP_CREATURE_TYPE, INVIS_WISP_CREATURE_TYPE_SMOKE);
+ DoCast(SPELL_HEADLESS_HORSEMAN_CLIMAX___SUMMONING_RHYME_SHAKE_MEDIUM);
+ break;
+ case POINT_HORSEMAN_6:
+ _instance->HandleGameObject(ObjectGuid::Empty, false, _instance->GetGameObject(DATA_PUMPKIN_SHRINE));
+ break;
+ case POINT_HORSEMAN_19:
+ me->SetCanFly(false);
+ break;
+ case POINT_HORSEMAN_20:
+ _phase = PHASE_BODY_1;
+ me->RemoveFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NON_ATTACKABLE);
+ me->SetHomePosition(me->GetPosition());
+ DoTalk(SAY_ENTRANCE);
+ DoZoneInCombat();
+ break;
+ default:
+ break;
+ }
+
+ ++_id;
+ if (_id <= POINT_HORSEMAN_20)
+ me->GetMotionMaster()->MovePoint(_id, HeadlessHorsemanFlightPoints[_id]);
+ }
- if (UpdateVictim())
- {
- DoMeleeAttackIfReady();
- if (cleave <= diff)
- {
- DoCastVictim(SPELL_CLEAVE);
- cleave = urand(2000, 6000); //1 cleave per 2.0f-6.0fsec
- }
- else cleave -= diff;
- }
- }
- else
- {
- if (regen <= diff)
- {
- regen = 1000; //"body calls head"
- if (me->IsFullHealth() && !returned)
- {
- if (Phase > 1)
- --Phase;
- else
- Phase = 1;
- Creature* Head = ObjectAccessor::GetCreature((*me), headGUID);
- if (Head && Head->IsAlive())
- {
- ENSURE_AI(npc_head::npc_headAI, Head->AI())->Phase = Phase;
- ENSURE_AI(npc_head::npc_headAI, Head->AI())->Disappear();
- }
- return;
- }
- }
- else regen -= diff;
+ void JustEngagedWith(Unit* /*who*/) override
+ {
+ _instance->SetBossState(DATA_HORSEMAN_EVENT, IN_PROGRESS);
+ DoZoneInCombat();
- if (whirlwind <= diff)
- {
- whirlwind = urand(4000, 8000);
- if (urand(0, 1))
- {
- me->RemoveAurasDueToSpell(SPELL_CONFUSE);
- DoCast(me, SPELL_WHIRLWIND, true);
- DoCast(me, SPELL_CONFUSE);
- }
- else
- me->RemoveAurasDueToSpell(SPELL_WHIRLWIND);
- }
- else whirlwind -= diff;
- }
- }
- };
-};
+ _scheduler.Schedule(2s, uint32(TASK_GROUP_COMBAT), [this](TaskContext cleaveContext)
+ {
+ DoCastVictim(SPELL_HORSEMANS_CLEAVE);
+ cleaveContext.Repeat(2s, 6s);
+ }).Schedule(6s, uint32(TASK_GROUP_COMBAT), [this](TaskContext /*burnContext*/)
+ {
+ if (Creature* flame = me->SummonCreature(NPC_HELPER, HeadlessHorsemanSpawnPoints[0], TEMPSUMMON_TIMED_DESPAWN, 17 * IN_MILLISECONDS))
+ flame->AI()->SetData(DATA_INVIS_WISP_CREATURE_TYPE, INVIS_WISP_CREATURE_TYPE_FLAME);
+ });
+ }
-class npc_pulsing_pumpkin : public CreatureScript
-{
-public:
- npc_pulsing_pumpkin() : CreatureScript("npc_pulsing_pumpkin") { }
+ void MoveInLineOfSight(Unit* who) override
+ {
+ if (_withHead && _phase != PHASE_BODY_0)
+ ScriptedAI::MoveInLineOfSight(who);
+ }
+
+ void KilledUnit(Unit* player) override
+ {
+ if (player->GetTypeId() != TYPEID_PLAYER)
+ return;
+
+ if (_withHead)
+ DoTalk(SAY_PLAYER_DEATH);
+ else if (Creature* head = ObjectAccessor::GetCreature(*me, _headGUID))
+ head->AI()->SetData(DATA_HEAD_TALK, SAY_PLAYER_DEATH);
+ }
- CreatureAI* GetAI(Creature* creature) const override
+ void SpellHitTarget(Unit* unit, SpellInfo const* spell) override
{
- return GetScarletMonasteryAI<npc_pulsing_pumpkinAI>(creature);
+ if (spell->Id == SPELL_CONFLAGRATION && unit->HasAura(SPELL_CONFLAGRATION))
+ DoTalk(SAY_CONFLAGRATION, unit);
}
- struct npc_pulsing_pumpkinAI : public ScriptedAI
+ void JustDied(Unit* /*killer*/) override
{
- npc_pulsing_pumpkinAI(Creature* creature) : ScriptedAI(creature)
+ DoTalk(SAY_DEATH);
+ if (Creature* flame = DoSpawnCreature(NPC_HELPER, 0.f, 0.f, 0.f, 0.f, TEMPSUMMON_TIMED_DESPAWN, 60 * IN_MILLISECONDS))
+ flame->CastSpell(flame, SPELL_HEADLESS_HORSEMAN___FIRE);
+ if (Creature* wisp = DoSpawnCreature(NPC_WISP_INVIS, 0.f, 0.f, 0.f, 0.f, TEMPSUMMON_TIMED_DESPAWN, 60 * IN_MILLISECONDS))
+ wisp->AI()->SetData(DATA_INVIS_WISP_CREATURE_TYPE, INVIS_WISP_CREATURE_TYPE_BLUE);
+
+ _instance->SetBossState(DATA_HORSEMAN_EVENT, DONE);
+
+ if (me->GetMap()->HavePlayers())
{
- sprouted = false;
+ if (Group* group = me->GetMap()->GetPlayers().begin()->GetSource()->GetGroup())
+ if (group->isLFGGroup())
+ sLFGMgr->FinishDungeon(group->GetGUID(), LFG_DUNGEONID_THE_HEADLESS_HORSEMAN, me->GetMap());
}
+ }
+
+ void SpellHit(Unit* caster, SpellInfo const* spellInfo) override
+ {
+ if (_withHead)
+ return;
+
+ if (spellInfo->Id != SPELL_HEADLESS_HORSEMAN_CLIMAX___SEND_HEAD)
+ return;
+
+ _laughTimer.Reset(urand(2 * IN_MILLISECONDS, 5 * IN_MILLISECONDS));
+ _withHead = true;
+ _scheduler.CancelGroup(TASK_GROUP_WITHOUT_HEAD);
- bool sprouted;
- ObjectGuid debuffGUID;
+ me->InterruptNonMeleeSpells(true);
+ me->RemoveAllAuras();
+ me->SetName("Headless Horseman"); //@todo THIS can't be serious
+ me->SetFullHealth();
- void Reset() override
+ DoTalk(SAY_REJOINED);
+ DoCastSelf(SPELL_HEADLESS_HORSEMAN_CLIMAX___HEAD_VISUAL);
+ caster->GetMotionMaster()->Clear();
+ caster->GetMotionMaster()->MoveFollow(me, 6.f, 0.f);
+
+ switch (_phase)
{
- float x, y, z;
- me->GetPosition(x, y, z); //this visual aura some under ground
- me->UpdatePosition(x, y, z + 0.35f, 0.0f);
- debuffGUID.Clear();
- Despawn();
- Creature* debuff = DoSpawnCreature(HELPER, 0, 0, 0, 0, TEMPSUMMON_TIMED_OR_CORPSE_DESPAWN, 14500);
- if (debuff)
- {
- debuff->SetDisplayId(me->GetDisplayId());
- debuff->CastSpell(debuff, SPELL_PUMPKIN_AURA_GREEN, false);
- ENSURE_AI(npc_wisp_invis::npc_wisp_invisAI, debuff->AI())->SetType(1);
- debuffGUID = debuff->GetGUID();
- }
- sprouted = false;
- DoCast(me, SPELL_PUMPKIN_AURA, true);
- DoCast(me, SPELL_SPROUTING);
- me->SetFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_STUNNED);
+ case PHASE_BODY_1:
+ _scheduler.Schedule(2s, uint32(TASK_GROUP_COMBAT), [this](TaskContext cleaveContext)
+ {
+ DoCastVictim(SPELL_HORSEMANS_CLEAVE);
+ cleaveContext.Repeat(2s, 6s);
+ }).Schedule(6s, uint32(TASK_GROUP_COMBAT), [this](TaskContext /*burnContext*/)
+ {
+ if (Creature* flame = me->SummonCreature(NPC_HELPER, HeadlessHorsemanSpawnPoints[0], TEMPSUMMON_TIMED_DESPAWN, 17 * IN_MILLISECONDS))
+ flame->AI()->SetData(DATA_INVIS_WISP_CREATURE_TYPE, INVIS_WISP_CREATURE_TYPE_FLAME);
+ });
+ break;
+ case PHASE_BODY_2:
+ _scheduler.Schedule(2s, uint32(TASK_GROUP_COMBAT), [this](TaskContext cleaveContext)
+ {
+ DoCastVictim(SPELL_HORSEMANS_CLEAVE);
+ cleaveContext.Repeat(2s, 6s);
+ }).Schedule(15s, uint32(TASK_GROUP_COMBAT), [this](TaskContext clonfragateContext)
+ {
+ if (Unit* player = SelectTarget(SELECT_TARGET_RANDOM, 0, 0.f, true, false, -SPELL_CONFLAGRATION))
+ DoCast(player, SPELL_CONFLAGRATION, false);
+ clonfragateContext.Repeat(10s, 16s);
+ });
+ break;
+ case PHASE_BODY_3:
+ _scheduler.Schedule(2s, uint32(TASK_GROUP_COMBAT), [this](TaskContext cleaveContext)
+ {
+ DoCastVictim(SPELL_HORSEMANS_CLEAVE);
+ cleaveContext.Repeat(2s, 6s);
+ }).Schedule(15s, uint32(TASK_GROUP_COMBAT), [this](TaskContext summonAddsContext)
+ {
+ me->InterruptNonMeleeSpells(false);
+ DoCastSelf(SPELL_HORSEMANS_SUMMON);
+ DoTalk(SAY_SPROUTING_PUMPKINS);
+ summonAddsContext.Repeat(25s, 35s);
+ });
+ break;
+ default:
+ break;
}
- void JustEngagedWith(Unit* /*who*/) override { }
+ }
- void SpellHit(Unit* /*caster*/, SpellInfo const* spell) override
+ void DamageTaken(Unit* /*attacker*/, uint32& damage) override
+ {
+ if (damage < me->GetHealth() || !_withHead)
{
- if (spell->Id == SPELL_SPROUTING)
- {
- sprouted = true;
- me->RemoveAllAuras();
- me->RemoveFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_STUNNED);
- DoCast(me, SPELL_SPROUT_BODY, true);
- me->UpdateEntry(PUMPKIN_FIEND);
- DoStartMovement(me->GetVictim());
- }
+ if (damage >= me->GetHealth() && !_withHead)
+ damage = 0;
+ return;
}
- void Despawn()
- {
- if (!debuffGUID)
- return;
+ damage = 0;
+ _withHead = false;
+ _scheduler.CancelGroup(TASK_GROUP_COMBAT);
+ me->InterruptNonMeleeSpells(true);
+ me->RemoveAllAuras();
+ me->SetName("Headless Horseman, Unhorsed"); //@todo THIS can't be serious
+ DoCastSelf(SPELL_HEADLESS_HORSEMAN_CLIMAX___BODY_REGEN_REMOVED_ON_DEATH, true);
+ DoCastSelf(SPELL_HEADLESS_HORSEMAN_CLIMAX___BODY_REGEN, true);
+ DoCastSelf(SPELL_HEADLESS_HORSEMAN_CLIMAX___BODY_REGEN_CONFUSE_ONLY_REMOVED_ON_DEATH, false); // test
- Unit* debuff = ObjectAccessor::GetUnit(*me, debuffGUID);
- if (debuff)
+ Creature* head = nullptr;
+ if (!_headGUID)
+ {
+ if (Creature* newHead = DoSpawnCreature(NPC_HEADLESS_HORSEMAN_HEAD, frand(0.f, 5.f), frand(0.f, 5.f), 0, 0, TEMPSUMMON_DEAD_DESPAWN, 0))
{
- debuff->SetVisible(false);
- debuffGUID.Clear();
+ _headGUID = newHead->GetGUID();
+ head = newHead;
}
}
- void JustDied(Unit* /*killer*/) override
+ if (!head)
+ head = ObjectAccessor::GetCreature(*me, _headGUID);
+ if (head && head->IsAlive())
{
- if (!sprouted)
- Despawn();
+ head->RemoveFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NON_ATTACKABLE);
+ head->AI()->SetData(DATA_HEAD_PHASE, _phase);
+ DoCast(head, SPELL_HEADLESS_HORSEMAN_CLIMAX___SEND_HEAD, true);
}
- void MoveInLineOfSight(Unit* who) override
+ _scheduler.Schedule(2s, uint32(TASK_GROUP_WITHOUT_HEAD), [this](TaskContext whirlwindContext)
+ {
+ if (roll_chance_i(50))
+ {
+ me->RemoveAurasDueToSpell(SPELL_HEADLESS_HORSEMAN_CLIMAX___BODY_REGEN_CONFUSE_ONLY_REMOVED_ON_DEATH);
+ DoCastSelf(SPELL_HEADLESS_HORSEMAN_CLIMAX___HORSEMANS_WHIRLWIND, true);
+ DoCastSelf(SPELL_HEADLESS_HORSEMAN_CLIMAX___BODY_REGEN_CONFUSE_ONLY_REMOVED_ON_DEATH);
+ }
+ else
+ me->RemoveAurasDueToSpell(SPELL_HEADLESS_HORSEMAN_CLIMAX___HORSEMANS_WHIRLWIND);
+
+ if (!_withHead)
+ whirlwindContext.Repeat(4s, 8s);
+ }).Schedule(1s, uint32(TASK_GROUP_WITHOUT_HEAD), [this](TaskContext regenerateContext)
{
- if (!who || !me->IsValidAttackTarget(who) || me->GetVictim())
- return;
+ if (me->IsFullHealth() && !_withHead)
+ {
+ Creature* head = ObjectAccessor::GetCreature(*me, _headGUID);
+ if (head && head->IsAlive())
+ head->AI()->DoAction(ACTION_HEAD_RETURN_TO_BODY);
+ }
+ else
+ regenerateContext.Repeat(1s);
+ });
+ }
- AddThreat(who, 0.0f);
- if (sprouted)
- DoStartMovement(who);
+ void UpdateAI(uint32 diff) override
+ {
+ if (!_laughTimer.Passed())
+ _laughTimer.Update(diff);
+
+ if (_withHead && _laughTimer.Passed())
+ {
+ _laughTimer.Reset(urand(11 * IN_MILLISECONDS, 22 * IN_MILLISECONDS));
+ DoPlaySoundToSet(me, Trinity::Containers::SelectRandomContainerElement(HeadlessHorsemanRandomLaughSound));
}
- void UpdateAI(uint32 /*diff*/) override
+ if (UpdateVictim())
{
- if (sprouted && UpdateVictim())
- DoMeleeAttackIfReady();
+ _scheduler.Update(diff, [this]
+ {
+ if (_withHead)
+ DoMeleeAttackIfReady();
+ });
}
- };
-};
+ else
+ _scheduler.Update(diff);
+ }
-enum LooselyTurnedSoil
-{
- QUEST_CALL_THE_HEADLESS_HORSEMAN = 11405
+private:
+ void DoTalk(uint8 textEntry, Unit* target = nullptr)
+ {
+ Talk(textEntry, target);
+ _laughTimer.Reset(std::min<uint32>(10 * IN_MILLISECONDS, _laughTimer.GetExpiry() + 4 * IN_MILLISECONDS));
+ }
+
+ InstanceScript* _instance;
+ TaskScheduler _scheduler;
+ TimeTrackerSmall _laughTimer;
+ ObjectGuid _headGUID;
+ uint32 _phase;
+ uint32 _id;
+ bool _withHead;
};
-class go_loosely_turned_soil : public GameObjectScript
+struct npc_pulsing_pumpkin : public ScriptedAI
{
- public:
- go_loosely_turned_soil() : GameObjectScript("go_loosely_turned_soil") { }
-
- struct go_loosely_turned_soilAI : public GameObjectAI
- {
- go_loosely_turned_soilAI(GameObject* go) : GameObjectAI(go), instance(go->GetInstanceScript()) { }
+ npc_pulsing_pumpkin(Creature* creature) : ScriptedAI(creature)
+ {
+ _sprouted = false;
+ }
- InstanceScript* instance;
+ void Reset() override
+ {
+ _debuffGUID.Clear();
- bool GossipHello(Player* player) override
- {
- if (instance->GetBossState(DATA_HORSEMAN_EVENT) == IN_PROGRESS || player->GetQuestStatus(QUEST_CALL_THE_HEADLESS_HORSEMAN) != QUEST_STATUS_COMPLETE)
- return true;
+ Despawn();
- return false;
- }
+ Creature* debuff = DoSpawnCreature(NPC_HELPER, 0.f, 0.f, 0.f, 0.f, TEMPSUMMON_TIMED_OR_CORPSE_DESPAWN, 14 * IN_MILLISECONDS + 500);
+ if (debuff)
+ {
+ debuff->SetDisplayId(me->GetDisplayId());
+ debuff->AI()->SetData(DATA_INVIS_WISP_CREATURE_TYPE, INVIS_WISP_CREATURE_TYPE_PUMPKIN);
+ _debuffGUID = debuff->GetGUID();
+ }
- void QuestReward(Player* player, Quest const* /*quest*/, uint32 /*opt*/) override
- {
- if (instance->GetBossState(DATA_HORSEMAN_EVENT) == IN_PROGRESS)
- return;
+ _sprouted = false;
- player->AreaExploredOrEventHappens(11405);
- if (Creature* horseman = me->SummonCreature(HH_MOUNTED, FlightPoint[20], TEMPSUMMON_MANUAL_DESPAWN, 0))
- {
- ENSURE_AI(boss_headless_horseman::boss_headless_horsemanAI, horseman->AI())->PlayerGUID = player->GetGUID();
- ENSURE_AI(boss_headless_horseman::boss_headless_horsemanAI, horseman->AI())->FlyMode();
- }
- }
- };
+ DoCastSelf(SPELL_PUMPKIN_LIFE_CYCLE, true);
+ DoCastSelf(SPELL_SPROUTING);
+ me->SetFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_STUNNED);
+ }
- GameObjectAI* GetAI(GameObject* go) const override
+ void SpellHit(Unit* /*caster*/, SpellInfo const* spell) override
+ {
+ if (spell->Id == SPELL_SPROUTING)
{
- return GetScarletMonasteryAI<go_loosely_turned_soilAI>(go);
+ _sprouted = true;
+ me->RemoveAllAuras();
+ me->RemoveFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_STUNNED);
+ DoCastSelf(SPELL_SPROUT_BODY, true);
+ DoZoneInCombat();
}
+ }
+
+ void JustDied(Unit* /*killer*/) override
+ {
+ if (!_sprouted)
+ Despawn();
+ }
+
+ void MoveInLineOfSight(Unit* who) override
+ {
+ if (_sprouted)
+ ScriptedAI::MoveInLineOfSight(who);
+ }
+
+ void UpdateAI(uint32 /*diff*/) override
+ {
+ if (_sprouted && UpdateVictim())
+ DoMeleeAttackIfReady();
+ }
+
+private:
+ void Despawn()
+ {
+ if (!_debuffGUID)
+ return;
+
+ Creature* debuff = ObjectAccessor::GetCreature(*me, _debuffGUID);
+ if (debuff)
+ debuff->DespawnOrUnsummon();
+
+ _debuffGUID.Clear();
+ }
+
+ ObjectGuid _debuffGUID;
+ bool _sprouted;
+};
+
+enum LooselyTurnedSoil
+{
+ QUEST_CALL_THE_HEADLESS_HORSEMAN = 11405
};
-void npc_head::npc_headAI::Disappear()
+struct go_loosely_turned_soil : public GameObjectAI
{
- if (withbody)
- return;
+ go_loosely_turned_soil(GameObject* go) : GameObjectAI(go), instance(go->GetInstanceScript()) { }
- if (bodyGUID)
+ bool GossipHello(Player* player) override
{
- Creature* body = ObjectAccessor::GetCreature((*me), bodyGUID);
- if (body && body->IsAlive())
+ if (instance->GetBossState(DATA_HORSEMAN_EVENT) == IN_PROGRESS || player->GetQuestStatus(QUEST_CALL_THE_HEADLESS_HORSEMAN) != QUEST_STATUS_COMPLETE)
+ return true;
+
+ return false;
+ }
+
+ void QuestReward(Player* player, Quest const* /*quest*/, uint32 /*opt*/) override
+ {
+ if (instance->GetBossState(DATA_HORSEMAN_EVENT) == IN_PROGRESS)
+ return;
+
+ player->AreaExploredOrEventHappens(11405);
+
+ if (TempSummon* horseman = me->GetMap()->SummonCreature(NPC_HEADLESS_HORSEMAN_MOUNTED, HeadlessHorsemanFlightPoints[20]))
{
- withbody = true;
- me->RemoveAllAuras();
- body->RemoveAurasDueToSpell(SPELL_IMMUNE);//hack, SpellHit doesn't calls if body has immune aura
- DoCast(body, SPELL_FLYING_HEAD);
- me->SetFullHealth();
- me->SetFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NON_ATTACKABLE);
- me->SetFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NOT_SELECTABLE);
- me->GetMotionMaster()->MoveIdle();
- ENSURE_AI(boss_headless_horseman::boss_headless_horsemanAI, body->AI())->returned = true;
+ horseman->SetTempSummonType(TEMPSUMMON_MANUAL_DESPAWN);
+ horseman->AI()->DoAction(ACTION_HORSEMAN_EVENT_START);
}
}
-}
+
+private:
+ InstanceScript* instance;
+};
void AddSC_boss_headless_horseman()
{
- new boss_headless_horseman();
- new npc_head();
- new npc_pulsing_pumpkin();
- new npc_wisp_invis();
- new go_loosely_turned_soil();
+ RegisterScarletMonasteryCreatureAI(boss_headless_horseman);
+ RegisterScarletMonasteryCreatureAI(npc_head);
+ RegisterScarletMonasteryCreatureAI(npc_pulsing_pumpkin);
+ RegisterScarletMonasteryCreatureAI(npc_wisp_invis);
+ RegisterScarletMonasteryGameObjectAI(go_loosely_turned_soil);
}
diff --git a/src/server/scripts/EasternKingdoms/ScarletMonastery/boss_herod.cpp b/src/server/scripts/EasternKingdoms/ScarletMonastery/boss_herod.cpp
index 49b451eee05..a6e24aa42ef 100644
--- a/src/server/scripts/EasternKingdoms/ScarletMonastery/boss_herod.cpp
+++ b/src/server/scripts/EasternKingdoms/ScarletMonastery/boss_herod.cpp
@@ -16,169 +16,145 @@
* with this program. If not, see <http://www.gnu.org/licenses/>.
*/
-/* ScriptData
-SDName: Boss_Herod
-SD%Complete: 95
-SDComment: Should in addition spawn Myrmidons in the hallway outside
-SDCategory: Scarlet Monastery
-EndScriptData */
-
-#include "ScriptMgr.h"
#include "scarlet_monastery.h"
#include "ScriptedCreature.h"
#include "ScriptedEscortAI.h"
+#include "ScriptMgr.h"
-enum Says
+enum HerodSays
{
- SAY_AGGRO = 0,
- SAY_WHIRLWIND = 1,
- SAY_ENRAGE = 2,
- SAY_KILL = 3,
- EMOTE_ENRAGE = 4
+ SAY_AGGRO = 0,
+ SAY_WHIRLWIND = 1,
+ SAY_ENRAGE = 2,
+ SAY_KILL = 3,
+ EMOTE_ENRAGE = 4
};
-enum Spells
+enum HerodSpells
{
- SPELL_RUSHINGCHARGE = 8260,
- SPELL_CLEAVE = 15496,
- SPELL_WHIRLWIND = 8989,
- SPELL_FRENZY = 8269
+ SPELL_RUSHINGCHARGE = 8260,
+ SPELL_CLEAVE = 15496,
+ SPELL_WHIRLWIND = 8989,
+ SPELL_FRENZY = 8269
};
-enum Npcs
+enum HerodNpcs
{
- NPC_SCARLET_TRAINEE = 6575,
- NPC_SCARLET_MYRMIDON = 4295
+ NPC_SCARLET_TRAINEE = 6575,
+ NPC_SCARLET_MYRMIDON = 4295
};
-enum Events
+enum HerodEvents
{
- EVENT_CLEAVE = 1,
+ EVENT_CLEAVE = 1,
EVENT_WHIRLWIND
};
Position const ScarletTraineePos = { 1939.18f, -431.58f, 17.09f, 6.22f };
-class boss_herod : public CreatureScript
+struct boss_herod : public BossAI
{
- public:
- boss_herod() : CreatureScript("boss_herod") { }
-
- struct boss_herodAI : public BossAI
- {
- boss_herodAI(Creature* creature) : BossAI(creature, DATA_HEROD)
- {
- _enrage = false;
- }
-
- void Reset() override
- {
- _enrage = false;
- _Reset();
- }
-
- void JustEngagedWith(Unit* /*who*/) override
- {
- Talk(SAY_AGGRO);
- DoCast(me, SPELL_RUSHINGCHARGE);
- _JustEngagedWith();
-
- events.ScheduleEvent(EVENT_CLEAVE, 12s);
- events.ScheduleEvent(EVENT_WHIRLWIND, 1min);
- }
-
- void KilledUnit(Unit* /*victim*/) override
- {
- Talk(SAY_KILL);
- }
+ boss_herod(Creature* creature) : BossAI(creature, DATA_HEROD)
+ {
+ _enrage = false;
+ }
- void JustDied(Unit* /*killer*/) override
- {
- _JustDied();
+ void Reset() override
+ {
+ _enrage = false;
+ _Reset();
+ }
- for (uint8 i = 0; i < 20; ++i)
- me->SummonCreature(NPC_SCARLET_TRAINEE, ScarletTraineePos, TEMPSUMMON_TIMED_OR_DEAD_DESPAWN, 600000);
- }
+ void JustEngagedWith(Unit* /*who*/) override
+ {
+ Talk(SAY_AGGRO);
+ DoCast(me, SPELL_RUSHINGCHARGE);
+ _JustEngagedWith();
- void DamageTaken(Unit* /*attacker*/, uint32& damage) override
- {
- if (!_enrage && me->HealthBelowPctDamaged(30, damage))
- {
- Talk(EMOTE_ENRAGE);
- Talk(SAY_ENRAGE);
- DoCast(me, SPELL_FRENZY);
- _enrage = true;
- }
- }
+ events.ScheduleEvent(EVENT_CLEAVE, 12s);
+ events.ScheduleEvent(EVENT_WHIRLWIND, 1min);
+ }
- void ExecuteEvent(uint32 eventId) override
- {
- switch (eventId)
- {
- case EVENT_CLEAVE:
- DoCastVictim(SPELL_CLEAVE);
- events.ScheduleEvent(EVENT_CLEAVE, 12s);
- break;
- case EVENT_WHIRLWIND:
- Talk(SAY_WHIRLWIND);
- DoCastVictim(SPELL_WHIRLWIND);
- events.ScheduleEvent(EVENT_WHIRLWIND, 30s);
- break;
- default:
- break;
- }
- }
+ void KilledUnit(Unit* victim) override
+ {
+ if (victim->GetTypeId() == TYPEID_PLAYER)
+ Talk(SAY_KILL);
+ }
- private:
- bool _enrage;
- };
+ void JustDied(Unit* /*killer*/) override
+ {
+ _JustDied();
- CreatureAI* GetAI(Creature* creature) const override
+ for (uint8 itr = 0; itr < 20; ++itr)
{
- return GetScarletMonasteryAI<boss_herodAI>(creature);
+ Position randomNearPosition = me->GetRandomPoint(ScarletTraineePos, 5.f);
+ randomNearPosition.SetOrientation(ScarletTraineePos.GetOrientation());
+ me->SummonCreature(NPC_SCARLET_TRAINEE, randomNearPosition, TEMPSUMMON_TIMED_OR_DEAD_DESPAWN, 600 * IN_MILLISECONDS);
}
-};
-
-class npc_scarlet_trainee : public CreatureScript
-{
-public:
- npc_scarlet_trainee() : CreatureScript("npc_scarlet_trainee") { }
+ }
- CreatureAI* GetAI(Creature* creature) const override
+ void DamageTaken(Unit* /*attacker*/, uint32& damage) override
{
- return GetScarletMonasteryAI<npc_scarlet_traineeAI>(creature);
+ if (!_enrage && me->HealthBelowPctDamaged(30, damage))
+ {
+ Talk(EMOTE_ENRAGE);
+ Talk(SAY_ENRAGE);
+ DoCastSelf(SPELL_FRENZY);
+ _enrage = true;
+ }
}
- struct npc_scarlet_traineeAI : public EscortAI
+ void ExecuteEvent(uint32 eventId) override
{
- npc_scarlet_traineeAI(Creature* creature) : EscortAI(creature)
+ switch (eventId)
{
- Start_Timer = urand(1000, 6000);
+ case EVENT_CLEAVE:
+ DoCastVictim(SPELL_CLEAVE);
+ events.Repeat(12s);
+ break;
+ case EVENT_WHIRLWIND:
+ Talk(SAY_WHIRLWIND);
+ DoCastVictim(SPELL_WHIRLWIND);
+ events.Repeat(30s);
+ break;
+ default:
+ break;
}
+ }
- uint32 Start_Timer;
+private:
+ bool _enrage;
+};
- void Reset() override { }
- void JustEngagedWith(Unit* /*who*/) override { }
+struct npc_scarlet_trainee : public EscortAI
+{
+ npc_scarlet_trainee(Creature* creature) : EscortAI(creature)
+ {
+ _startTimer = urand(1000, 6000);
+ }
- void UpdateAI(uint32 diff) override
+ void UpdateAI(uint32 diff) override
+ {
+ if (_startTimer)
{
- if (Start_Timer)
+ if (_startTimer <= diff)
{
- if (Start_Timer <= diff)
- {
- Start(true, true);
- Start_Timer = 0;
- } else Start_Timer -= diff;
+ Start(true, true);
+ _startTimer = 0;
}
-
- EscortAI::UpdateAI(diff);
+ else
+ _startTimer -= diff;
}
- };
+
+ EscortAI::UpdateAI(diff);
+ }
+
+private:
+ uint32 _startTimer;
};
void AddSC_boss_herod()
{
- new boss_herod();
- new npc_scarlet_trainee();
+ RegisterScarletMonasteryCreatureAI(boss_herod);
+ RegisterScarletMonasteryCreatureAI(npc_scarlet_trainee);
}
diff --git a/src/server/scripts/EasternKingdoms/ScarletMonastery/boss_high_inquisitor_fairbanks.cpp b/src/server/scripts/EasternKingdoms/ScarletMonastery/boss_high_inquisitor_fairbanks.cpp
index f24365f2c52..5ee58a213c1 100644
--- a/src/server/scripts/EasternKingdoms/ScarletMonastery/boss_high_inquisitor_fairbanks.cpp
+++ b/src/server/scripts/EasternKingdoms/ScarletMonastery/boss_high_inquisitor_fairbanks.cpp
@@ -16,148 +16,148 @@
* with this program. If not, see <http://www.gnu.org/licenses/>.
*/
-/* ScriptData
-SDName: Boss_High_Inquisitor_Fairbanks
-SD%Complete: 100
-SDComment: @todo if this guy not involved in some special event, remove (and let ACID script)
-SDCategory: Scarlet Monastery
-EndScriptData */
-
-#include "ScriptMgr.h"
#include "scarlet_monastery.h"
-#include "InstanceScript.h"
#include "ScriptedCreature.h"
+#include "ScriptMgr.h"
+#include "Timer.h"
-enum Spells
+enum HighInquisitorFairbanksSpells
{
- SPELL_CURSEOFBLOOD = 8282,
- SPELL_DISPELMAGIC = 15090,
- SPELL_FEAR = 12096,
- SPELL_HEAL = 12039,
- SPELL_POWERWORDSHIELD = 11647,
- SPELL_SLEEP = 8399
+ SPELL_CURSEOFBLOOD = 8282,
+ SPELL_DISPEL_MAGIC = 15090,
+ SPELL_FEAR = 12096,
+ SPELL_HEAL = 12039,
+ SPELL_POWERWORDSHIELD = 11647,
+ SPELL_SLEEP = 8399
};
-class boss_high_inquisitor_fairbanks : public CreatureScript
+enum HighInquisitorFairbanksEvents
+{
+ EVENT_CURSE_BLOOD = 1,
+ EVENT_DIPEL_MAGIC,
+ EVENT_FEAR,
+ EVENT_HEAL,
+ EVENT_SLEEP
+};
+
+class HighInquisitorFairbanksDispelMagicTargetSelector
{
public:
- boss_high_inquisitor_fairbanks() : CreatureScript("boss_high_inquisitor_fairbanks") { }
+ HighInquisitorFairbanksDispelMagicTargetSelector(Unit* owner) : _me(owner) { }
- CreatureAI* GetAI(Creature* creature) const override
+ bool operator()(Unit* unit) const
{
- return GetScarletMonasteryAI<boss_high_inquisitor_fairbanksAI>(creature);
- }
+ if (unit->GetTypeId() != TYPEID_PLAYER || _me->GetDistance(unit) > 30.f)
+ return false;
- struct boss_high_inquisitor_fairbanksAI : public ScriptedAI
- {
- boss_high_inquisitor_fairbanksAI(Creature* creature) : ScriptedAI(creature)
- {
- Initialize();
- instance = creature->GetInstanceScript();
- }
+ DispelChargesList dispelList;
+ unit->GetDispellableAuraList(_me, DISPEL_MAGIC, dispelList);
+ if (dispelList.empty())
+ return false;
- void Initialize()
- {
- CurseOfBlood_Timer = 10000;
- DispelMagic_Timer = 30000;
- Fear_Timer = 40000;
- Heal_Timer = 30000;
- Sleep_Timer = 30000;
- Dispel_Timer = 20000;
- PowerWordShield = false;
- }
+ return true;
+ }
- uint32 CurseOfBlood_Timer;
- uint32 DispelMagic_Timer;
- uint32 Fear_Timer;
- uint32 Heal_Timer;
- uint32 Sleep_Timer;
- uint32 Dispel_Timer;
- bool PowerWordShield;
- InstanceScript* instance;
+private:
+ Unit const* _me;
+};
- void Reset() override
- {
- Initialize();
- me->SetStandState(UNIT_STAND_STATE_DEAD);
- instance->SetBossState(DATA_HIGH_INQUISITOR_FAIRBANKS, NOT_STARTED);
- }
+struct boss_high_inquisitor_fairbanks : public BossAI
+{
+ boss_high_inquisitor_fairbanks(Creature* creature) : BossAI(creature, DATA_HIGH_INQUISITOR_FAIRBANKS), _healTimer(0), _powerWordShield(false) { }
- void JustEngagedWith(Unit* /*who*/) override
- {
- me->SetStandState(UNIT_STAND_STATE_STAND);
- instance->SetBossState(DATA_HIGH_INQUISITOR_FAIRBANKS, IN_PROGRESS);
- }
+ void Reset() override
+ {
+ _Reset();
+ _healTimer.Reset(0);
+ _powerWordShield = false;
+ me->SetStandState(UNIT_STAND_STATE_DEAD);
+ }
- void JustDied(Unit* /*killer*/) override
- {
- instance->SetBossState(DATA_HIGH_INQUISITOR_FAIRBANKS, DONE);
- }
+ void JustEngagedWith(Unit* /*who*/) override
+ {
+ _JustEngagedWith();
+ events.ScheduleEvent(EVENT_CURSE_BLOOD, 10s);
+ events.ScheduleEvent(EVENT_DIPEL_MAGIC, 30s);
+ events.ScheduleEvent(EVENT_FEAR, 40s);
+ events.ScheduleEvent(EVENT_SLEEP, 25s);
+ me->SetStandState(UNIT_STAND_STATE_STAND);
+ }
- void UpdateAI(uint32 diff) override
+ void DamageTaken(Unit* /*attacker*/, uint32& damage) override
+ {
+ if (me->HealthBelowPctDamaged(25, damage))
{
- if (!UpdateVictim())
- return;
-
- //If we are <25% hp cast Heal
- if (!HealthAbovePct(25) && !me->IsNonMeleeSpellCast(false) && Heal_Timer <= diff)
+ if (!_powerWordShield)
{
- DoCast(me, SPELL_HEAL);
- Heal_Timer = 30000;
+ DoCastSelf(SPELL_POWERWORDSHIELD);
+ _powerWordShield = true;
}
- else Heal_Timer -= diff;
- //Fear_Timer
- if (Fear_Timer <= diff)
+ if (!me->IsNonMeleeSpellCast(false) && _healTimer.Passed())
{
- if (Unit* target = SelectTarget(SELECT_TARGET_RANDOM, 1))
- DoCast(target, SPELL_FEAR);
-
- Fear_Timer = 40000;
+ _healTimer.Reset(30 * IN_MILLISECONDS);
+ DoCastSelf(SPELL_HEAL);
}
- else Fear_Timer -= diff;
+ }
+ }
- //Sleep_Timer
- if (Sleep_Timer <= diff)
- {
- if (Unit* target = SelectTarget(SELECT_TARGET_MAXTHREAT, 0))
- DoCast(target, SPELL_SLEEP);
+ void UpdateAI(uint32 diff) override
+ {
+ if (!UpdateVictim())
+ return;
- Sleep_Timer = 30000;
- }
- else Sleep_Timer -= diff;
+ events.Update(diff);
- //PowerWordShield_Timer
- if (!PowerWordShield && !HealthAbovePct(25))
- {
- DoCast(me, SPELL_POWERWORDSHIELD);
- PowerWordShield = true;
- }
+ if (me->HasUnitState(UNIT_STATE_CASTING))
+ return;
- //Dispel_Timer
- if (Dispel_Timer <= diff)
- {
- if (Unit* target = SelectTarget(SELECT_TARGET_RANDOM, 0))
- DoCast(target, SPELL_DISPELMAGIC);
+ while (uint32 eventId = events.ExecuteEvent())
+ {
+ ExecuteEvent(eventId);
+ if (me->HasUnitState(UNIT_STATE_CASTING))
+ return;
+ }
- DispelMagic_Timer = 30000;
- }
- else DispelMagic_Timer -= diff;
+ if (!_healTimer.Passed())
+ _healTimer.Update(diff);
- //CurseOfBlood_Timer
- if (CurseOfBlood_Timer <= diff)
- {
- DoCastVictim(SPELL_CURSEOFBLOOD);
- CurseOfBlood_Timer = 25000;
- }
- else CurseOfBlood_Timer -= diff;
+ DoMeleeAttackIfReady();
+ }
- DoMeleeAttackIfReady();
+ void ExecuteEvent(uint32 eventId) override
+ {
+ switch (eventId)
+ {
+ case EVENT_CURSE_BLOOD:
+ DoCastVictim(SPELL_CURSEOFBLOOD);
+ events.Repeat(25s);
+ break;
+ case EVENT_DIPEL_MAGIC:
+ if (Unit* target = SelectTarget(SELECT_TARGET_RANDOM, 0, HighInquisitorFairbanksDispelMagicTargetSelector(me)))
+ DoCast(target, SPELL_DISPEL_MAGIC);
+ events.Repeat(30s);
+ break;
+ case EVENT_FEAR:
+ if (Unit* target = SelectTarget(SELECT_TARGET_RANDOM, 1, 20.f, true))
+ DoCast(target, SPELL_FEAR);
+ events.Repeat(40s);
+ break;
+ case EVENT_SLEEP:
+ if (Unit* target = SelectTarget(SELECT_TARGET_MAXTHREAT, 0, 30.f, true, false))
+ DoCast(target, SPELL_SLEEP);
+ events.Repeat(30s);
+ default:
+ break;
}
- };
+ }
+
+private:
+ TimeTrackerSmall _healTimer;
+ bool _powerWordShield;
};
void AddSC_boss_high_inquisitor_fairbanks()
{
- new boss_high_inquisitor_fairbanks();
+ RegisterScarletMonasteryCreatureAI(boss_high_inquisitor_fairbanks);
}
diff --git a/src/server/scripts/EasternKingdoms/ScarletMonastery/boss_houndmaster_loksey.cpp b/src/server/scripts/EasternKingdoms/ScarletMonastery/boss_houndmaster_loksey.cpp
index 7db8be4bef7..ff95ffccb12 100644
--- a/src/server/scripts/EasternKingdoms/ScarletMonastery/boss_houndmaster_loksey.cpp
+++ b/src/server/scripts/EasternKingdoms/ScarletMonastery/boss_houndmaster_loksey.cpp
@@ -15,73 +15,58 @@
* with this program. If not, see <http://www.gnu.org/licenses/>.
*/
-#include "ScriptMgr.h"
#include "scarlet_monastery.h"
#include "ScriptedCreature.h"
+#include "ScriptMgr.h"
-enum Yells
+enum HoundmasterLokseyYells
{
- SAY_AGGRO = 0,
+ SAY_AGGRO = 0,
};
-enum Spells
+enum HoundmasterLokseySpells
{
- SPELL_SUMMONSCARLETHOUND = 17164,
- SPELL_BLOODLUST = 6742
+ SPELL_SUMMON_SCARLET_HOUND = 17164,
+ SPELL_BLOODLUST = 6742
};
-enum Events
+enum HoundmasterLokseyEvents
{
- EVENT_BLOODLUST = 1
+ EVENT_BLOODLUST = 1
};
-class boss_houndmaster_loksey : public CreatureScript
+struct boss_houndmaster_loksey : public BossAI
{
- public:
- boss_houndmaster_loksey() : CreatureScript("boss_houndmaster_loksey") { }
-
- struct boss_houndmaster_lokseyAI : public BossAI
- {
- boss_houndmaster_lokseyAI(Creature* creature) : BossAI(creature, DATA_HOUNDMASTER_LOKSEY) { }
-
- void Reset() override
- {
- _Reset();
- }
+ boss_houndmaster_loksey(Creature* creature) : BossAI(creature, DATA_HOUNDMASTER_LOKSEY) { }
- void JustEngagedWith(Unit* /*who*/) override
- {
- Talk(SAY_AGGRO);
- _JustEngagedWith();
- events.ScheduleEvent(EVENT_BLOODLUST, 20s);
- }
+ void JustEngagedWith(Unit* /*who*/) override
+ {
+ _JustEngagedWith();
+ Talk(SAY_AGGRO);
+ DoCast(SPELL_SUMMON_SCARLET_HOUND);
+ events.ScheduleEvent(EVENT_BLOODLUST, 20s);
+ }
- void JustDied(Unit* /*killer*/) override
- {
- _JustDied();
- }
-
- void ExecuteEvent(uint32 eventId) override
- {
- switch (eventId)
+ void ExecuteEvent(uint32 eventId) override
+ {
+ switch (eventId)
+ {
+ case EVENT_BLOODLUST:
+ if (me->HealthBelowPct(60))
{
- case EVENT_BLOODLUST:
- DoCast(me, SPELL_BLOODLUST);
- events.ScheduleEvent(EVENT_BLOODLUST, 20s);
- break;
- default:
- break;
+ DoCastSelf(SPELL_BLOODLUST);
+ events.Repeat(60s);
}
- }
- };
-
- CreatureAI* GetAI(Creature* creature) const override
- {
- return GetScarletMonasteryAI<boss_houndmaster_lokseyAI>(creature);
+ else
+ events.Repeat(1s);
+ break;
+ default:
+ break;
}
+ }
};
void AddSC_boss_houndmaster_loksey()
{
- new 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 1637e61b3ae..28a1eb85c84 100644
--- a/src/server/scripts/EasternKingdoms/ScarletMonastery/boss_interrogator_vishas.cpp
+++ b/src/server/scripts/EasternKingdoms/ScarletMonastery/boss_interrogator_vishas.cpp
@@ -15,113 +15,104 @@
* with this program. If not, see <http://www.gnu.org/licenses/>.
*/
-#include "ScriptMgr.h"
#include "scarlet_monastery.h"
#include "InstanceScript.h"
-#include "ObjectAccessor.h"
#include "ScriptedCreature.h"
+#include "ScriptMgr.h"
-enum Says
+enum InterrogatorVishasSays
{
- SAY_AGGRO = 0,
- SAY_HEALTH1 = 1,
- SAY_HEALTH2 = 2,
- SAY_KILL = 3,
- SAY_TRIGGER_VORREL = 0
+ SAY_AGGRO = 0,
+ SAY_HEALTH1 = 1,
+ SAY_HEALTH2 = 2,
+ SAY_KILL = 3,
+ SAY_TRIGGER_VORREL = 0
};
-enum Spells
+enum InterrogatorVishasSpells
{
- SPELL_SHADOW_WORD_PAIN = 2767
+ SPELL_SHADOW_WORD_PAIN = 2767
};
-enum Events
+enum InterrogatorVishasEvents
{
- EVENT_SHADOW_WORD_PAIN = 1
+ EVENT_SHADOW_WORD_PAIN = 1
};
-class boss_interrogator_vishas : public CreatureScript
+struct boss_interrogator_vishas : public BossAI
{
- public:
- boss_interrogator_vishas() : CreatureScript("boss_interrogator_vishas") { }
-
- struct boss_interrogator_vishasAI : public BossAI
+ boss_interrogator_vishas(Creature* creature) : BossAI(creature, DATA_INTERROGATOR_VISHAS)
+ {
+ Initialize();
+ }
+
+ void Initialize()
+ {
+ _yellCount = 0;
+ }
+
+ void Reset() override
+ {
+ Initialize();
+ _Reset();
+ }
+
+ void JustEngagedWith(Unit* /*who*/) override
+ {
+ Talk(SAY_AGGRO);
+ _JustEngagedWith();
+ events.ScheduleEvent(EVENT_SHADOW_WORD_PAIN, 5s);
+ }
+
+ void KilledUnit(Unit* victim) override
+ {
+ if (victim->GetTypeId() == TYPEID_PLAYER)
+ Talk(SAY_KILL);
+ }
+
+ void JustDied(Unit* /*killer*/) override
+ {
+ _JustDied();
+ if (Creature* vorrel = instance->GetCreature(DATA_VORREL))
{
- boss_interrogator_vishasAI(Creature* creature) : BossAI(creature, DATA_INTERROGATOR_VISHAS)
- {
- Initialize();
- }
-
- void Initialize()
- {
- _yellCount = 0;
- }
-
- void Reset() override
- {
- Initialize();
- _Reset();
- }
-
- void JustEngagedWith(Unit* /*who*/) override
- {
- Talk(SAY_AGGRO);
- _JustEngagedWith();
- events.ScheduleEvent(EVENT_SHADOW_WORD_PAIN, 5s);
- }
-
- void KilledUnit(Unit* victim) override
- {
- if (victim->GetTypeId() == TYPEID_PLAYER)
- Talk(SAY_KILL);
- }
-
- void JustDied(Unit* /*killer*/) override
- {
- _JustDied();
- if (Creature* vorrel = ObjectAccessor::GetCreature(*me, instance->GetGuidData(DATA_VORREL)))
- vorrel->AI()->Talk(SAY_TRIGGER_VORREL);
- }
-
- void DamageTaken(Unit* /*attacker*/, uint32 &damage) override
- {
- if (me->HealthBelowPctDamaged(60, damage) && _yellCount < 1)
- {
- Talk(SAY_HEALTH1);
- ++_yellCount;
- }
-
- if (me->HealthBelowPctDamaged(30, damage) && _yellCount < 2)
- {
- Talk(SAY_HEALTH2);
- ++_yellCount;
- }
- }
+ if (vorrel->AI())
+ vorrel->AI()->Talk(SAY_TRIGGER_VORREL);
+ }
+ }
- void ExecuteEvent(uint32 eventId) override
- {
- switch (eventId)
- {
- case EVENT_SHADOW_WORD_PAIN:
- DoCastVictim(SPELL_SHADOW_WORD_PAIN);
- events.ScheduleEvent(EVENT_SHADOW_WORD_PAIN, 5s, 15s);
- break;
- default:
- break;
- }
- }
+ void DamageTaken(Unit* /*attacker*/, uint32 &damage) override
+ {
+ if (me->HealthBelowPctDamaged(60, damage) && _yellCount < 1)
+ {
+ Talk(SAY_HEALTH1);
+ ++_yellCount;
+ }
- private:
- uint8 _yellCount;
- };
+ if (me->HealthBelowPctDamaged(30, damage) && _yellCount < 2)
+ {
+ Talk(SAY_HEALTH2);
+ ++_yellCount;
+ }
+ }
- CreatureAI* GetAI(Creature* creature) const override
+ void ExecuteEvent(uint32 eventId) override
+ {
+ switch (eventId)
{
- return GetScarletMonasteryAI<boss_interrogator_vishasAI>(creature);
+ case EVENT_SHADOW_WORD_PAIN:
+ DoCastVictim(SPELL_SHADOW_WORD_PAIN);
+ events.ScheduleEvent(EVENT_SHADOW_WORD_PAIN, 5s, 15s);
+ break;
+ default:
+ break;
}
+ }
+
+private:
+ uint8 _yellCount;
};
void AddSC_boss_interrogator_vishas()
{
- new 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 6390fff76f7..92fe59c58f7 100644
--- a/src/server/scripts/EasternKingdoms/ScarletMonastery/boss_mograine_and_whitemane.cpp
+++ b/src/server/scripts/EasternKingdoms/ScarletMonastery/boss_mograine_and_whitemane.cpp
@@ -15,429 +15,426 @@
* with this program. If not, see <http://www.gnu.org/licenses/>.
*/
-#include "GameTime.h"
+#include "scarlet_monastery.h"
#include "InstanceScript.h"
#include "MotionMaster.h"
-#include "ObjectAccessor.h"
-#include "scarlet_monastery.h"
-#include "ScriptMgr.h"
#include "ScriptedCreature.h"
+#include "ScriptMgr.h"
+#include "SpellAuras.h"
#include "SpellInfo.h"
+#include "Timer.h"
-enum Says
+enum MograineAndWhitemaneSays
{
- /// Mograine
- SAY_MO_AGGRO = 0,
- SAY_MO_KILL = 1,
- SAY_MO_RESURRECTED = 2,
-
- /// Whitemaine
- SAY_WH_INTRO = 0,
- SAY_WH_KILL = 1,
- SAY_WH_RESURRECT = 2,
+ // Mograine
+ SAY_MO_AGGRO = 0,
+ SAY_MO_KILL = 1,
+ SAY_MO_RESURRECTED = 2,
+
+ // Whitemaine
+ SAY_WH_INTRO = 0,
+ SAY_WH_KILL = 1,
+ SAY_WH_RESURRECT = 2,
};
-enum Spells
+enum MograineAndWhitemaneSpells
{
- /// Mograine Spells
- SPELL_CRUSADER_STRIKE = 14518,
- SPELL_HAMMER_OF_JUSTICE = 5589,
- SPELL_LAYONHANDS = 9257,
- SPELL_RETRIBUTIONAURA = 8990,
-
- /// Whitemane Spells
- SPELL_DEEPSLEEP = 9256,
- SPELL_SCARLETRESURRECTION = 9232,
- SPELL_DOMINATEMIND = 14515,
- SPELL_HOLYSMITE = 9481,
- SPELL_HEAL = 12039,
- SPELL_POWERWORDSHIELD = 22187
+ // Mograine Spells
+ SPELL_CRUSADER_STRIKE = 14518,
+ SPELL_HAMMER_OF_JUSTICE = 5589,
+ SPELL_LAY_ONHANDS = 9257,
+ SPELL_RETRIBUTION_AURA = 8990,
+
+ // Whitemane Spells
+ SPELL_DEEP_SLEEP = 9256,
+ SPELL_SCARLET_RESURRECTION = 9232,
+ SPELL_DOMINATE_MIND = 14515,
+ SPELL_HOLY_SMITE = 9481,
+ SPELL_HEAL = 12039,
+ SPELL_POWER_WORD_SHIELD = 22187
};
-enum Events
+enum MograineAndWhitemaneEvents
{
- /// Mograine
+ // Mograine
EVENT_CRUSADER_STRIKE = 1,
EVENT_HAMMER_OF_JUSTICE,
- /// Whitemane
+ // Whitemane
EVENT_HEAL = 1,
EVENT_POWER_WORD_SHIELD,
EVENT_HOLY_SMITE,
};
-enum Points
+enum MograineAndWhitemanePoints
{
POINT_WHITEMANE_MOVE_TO_MOGRAINE = 1,
};
-const Position WhitemaneIntroMovePos(1163.113370f, 1398.856812f, 32.527786f);
+Position const WhitemaneIntroMovePos = { 1163.113370f, 1398.856812f, 32.527786f, 0.f };
-/// Scarlet Commander Mograine - 3976
-struct boss_scarlet_commander_mograine : public ScriptedAI
+// Scarlet Commander Mograine - 3976
+struct boss_scarlet_commander_mograine : public BossAI
{
- public:
- boss_scarlet_commander_mograine(Creature* creature) : ScriptedAI(creature)
- {
- Initialize();
- }
+public:
+ boss_scarlet_commander_mograine(Creature* creature) : BossAI(creature, DATA_MOGRAINE_AND_WHITE_EVENT), _killYellTimer(0)
+ {
+ Initialize();
+ }
- void Initialize()
- {
- m_LastKillTime = 0;
- m_CanDie = false;
- m_FakeDeath = false;
- }
+ void Initialize()
+ {
+ _fakeDeath = false;
+ _canDie = true;
+ }
- void Reset() override
- {
- Initialize();
+ void Reset() override
+ {
+ Initialize();
- events.Reset();
- scheduler.CancelAll();
+ _Reset();
+ _killYellTimer.Reset(0);
- DoCast(me, SPELL_RETRIBUTIONAURA);
- me->RemoveFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NOT_SELECTABLE);
- me->SetStandState(UNIT_STAND_STATE_STAND);
- me->SetReactState(REACT_AGGRESSIVE);
+ DoCastSelf(SPELL_RETRIBUTION_AURA, true);
+ me->RemoveFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NOT_SELECTABLE | UNIT_FLAG_NON_ATTACKABLE);
+ me->SetStandState(UNIT_STAND_STATE_STAND);
+ me->SetReactState(REACT_AGGRESSIVE);
- // Close the door
- if (auto instance = me->GetInstanceScript())
- instance->HandleGameObject(instance->GetGuidData(GO_HIGH_INQUISITORS_DOOR), false);
- }
+ instance->HandleGameObject(ObjectGuid::Empty, false, instance->GetGameObject(DATA_HIGH_INQUISITORS_DOOR));
+ }
- void JustEngagedWith(Unit* /*who*/) override
- {
- Talk(SAY_MO_AGGRO);
+ void JustEngagedWith(Unit* /*who*/) override
+ {
+ _JustEngagedWith();
- // Call for help (from old script)
- me->CallForHelp(VISIBLE_RANGE);
+ Talk(SAY_MO_AGGRO);
- // Schedule events
- events.ScheduleEvent(EVENT_CRUSADER_STRIKE, Seconds(10), Seconds(15));
- events.ScheduleEvent(EVENT_HAMMER_OF_JUSTICE, Seconds(10), Seconds(15));
- }
+ // Call for help (from old script)
+ me->CallForHelp(VISIBLE_RANGE);
- void KilledUnit(Unit* who) override
- {
- if (who->GetTypeId() != TYPEID_PLAYER)
- return;
+ // Just to be sure it's MOTION_SLOT_DEFAULT is static
+ me->GetMotionMaster()->MoveIdle();
- // Cooldown between talking
- time_t currTime = GameTime::GetGameTime();
+ // Schedule events
+ events.ScheduleEvent(EVENT_CRUSADER_STRIKE, 10s, 15s);
+ events.ScheduleEvent(EVENT_HAMMER_OF_JUSTICE, 10s, 15s);
+ }
- if (m_LastKillTime < currTime)
- {
- Talk(SAY_MO_KILL);
- m_LastKillTime = currTime + 5;
- }
+ void KilledUnit(Unit* who) override
+ {
+ if (who->GetTypeId() != TYPEID_PLAYER)
+ return;
+
+ if (_killYellTimer.Passed())
+ {
+ Talk(SAY_MO_KILL);
+ _killYellTimer.Reset(5 * IN_MILLISECONDS);
}
+ }
- void UpdateAI(uint32 diff) override
+ void ExecuteEvent(uint32 eventId) override
+ {
+ switch (eventId)
{
- if (!UpdateVictim())
- return;
+ case EVENT_CRUSADER_STRIKE:
+ DoCastVictim(SPELL_CRUSADER_STRIKE);
+ events.Repeat(10s);
+ break;
+ case EVENT_HAMMER_OF_JUSTICE:
+ DoCastVictim(SPELL_HAMMER_OF_JUSTICE);
+ events.Repeat(60s);
+ break;
+ default:
+ break;
+ }
+ }
- scheduler.Update(diff);
- events.Update(diff);
+ void DamageTaken(Unit* /*who*/, uint32& damage) override
+ {
+ if (damage >= me->GetHealth() && !_fakeDeath)
+ {
+ _fakeDeath = true;
+ _canDie = false;
- if (me->HasUnitState(UNIT_STATE_CASTING))
- return;
+ // Open the door
+ instance->HandleGameObject(ObjectGuid::Empty, true, instance->GetGameObject(DATA_HIGH_INQUISITORS_DOOR));
- if (uint32 eventId = events.ExecuteEvent())
+ // Tell whitemane to move
+ if (Creature* whitemane = instance->GetCreature(DATA_WHITEMANE))
{
- switch (eventId)
- {
- case EVENT_CRUSADER_STRIKE:
- DoCastVictim(SPELL_CRUSADER_STRIKE);
- events.Repeat(Seconds(10));
- break;
- case EVENT_HAMMER_OF_JUSTICE:
- DoCastVictim(SPELL_HAMMER_OF_JUSTICE);
- events.Repeat(Seconds(60));
- break;
- default:
- break;
- }
+ whitemane->GetMotionMaster()->MovePoint(0, WhitemaneIntroMovePos);
+ DoZoneInCombat(whitemane);
}
- DoMeleeAttackIfReady();
+ me->InterruptNonMeleeSpells(true);
+ me->ClearComboPointHolders();
+ me->RemoveAllAuras();
+ me->ClearAllReactives();
+ me->SetFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NOT_SELECTABLE | UNIT_FLAG_NON_ATTACKABLE);
+ me->SetStandState(UNIT_STAND_STATE_DEAD);
+ me->SetReactState(REACT_PASSIVE); // prevent Mograine from attacking while fake death
+
+ // Stop moving
+ me->GetMotionMaster()->Clear();
}
- void DamageTaken(Unit* /*who*/, uint32& damage) override
+ if (!_canDie && damage >= me->GetHealth())
+ damage = 0;
+ }
+
+ void SpellHit(Unit* /*who*/, SpellInfo const* spell) override
+ {
+ // Casted from Whitemane
+ if (spell->Id == SPELL_SCARLET_RESURRECTION)
{
- if (damage >= me->GetHealth() && !m_FakeDeath)
+ scheduler.Schedule(3s, [this](TaskContext /*context*/)
{
- m_FakeDeath = true;
-
- // Get instance script
- if (auto instance = me->GetInstanceScript())
- {
- // Stop moving
- me->GetMotionMaster()->Clear();
- me->GetMotionMaster()->MoveIdle();
-
- // Open the door
- instance->HandleGameObject(instance->GetGuidData(GO_HIGH_INQUISITORS_DOOR), true);
+ // Say text
+ Talk(SAY_MO_RESURRECTED);
- // Tell whitemane to move
- if (auto whitemane = ObjectAccessor::GetCreature(*me, instance->GetGuidData(DATA_WHITEMANE)))
- {
- DoZoneInCombat(whitemane);
-
- whitemane->GetMotionMaster()->Clear();
- whitemane->GetMotionMaster()->MovePoint(0, WhitemaneIntroMovePos);
- }
+ me->RemoveFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NOT_SELECTABLE);
+ me->SetStandState(UNIT_STAND_STATE_STAND);
+ });
- // Interrupt spells and clear auras
- if (me->IsNonMeleeSpellCast(false))
- me->InterruptNonMeleeSpells(false);
+ scheduler.Schedule(5s, [this](TaskContext /*context*/)
+ {
+ // Schedule events after ressurrect
+ events.ScheduleEvent(EVENT_CRUSADER_STRIKE, 10s, 15s);
+ events.ScheduleEvent(EVENT_HAMMER_OF_JUSTICE, 10s, 15s);
+
+ // We can now die
+ me->RemoveFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NON_ATTACKABLE);
+ me->SetReactState(REACT_AGGRESSIVE);
+ _canDie = true;
+ DoCastSelf(SPELL_RETRIBUTION_AURA, true);
+ });
+ }
+ }
- me->ClearComboPointHolders();
- me->RemoveAllAuras();
- me->ClearAllReactives();
+ void UpdateAI(uint32 diff) override
+ {
+ if (!UpdateVictim())
+ return;
- // Set fake death flags
- me->SetFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NOT_SELECTABLE);
- me->SetStandState(UNIT_STAND_STATE_DEAD);
- me->SetReactState(REACT_PASSIVE); // prevent mograine from attacking while fake death
- }
- }
+ events.Update(diff);
+ scheduler.Update(diff);
- if (!m_CanDie && damage >= me->GetHealth())
- damage = 0;
- }
+ if (me->HasUnitState(UNIT_STATE_CASTING))
+ return;
- void SpellHit(Unit* /*who*/, SpellInfo const* spell) override
+ while (uint32 eventId = events.ExecuteEvent())
{
- // Casted from Whitemane
- if (spell->Id == SPELL_SCARLETRESURRECTION)
- {
- scheduler.Schedule(Seconds(3), [this](TaskContext /*context*/)
- {
- // Say text
- Talk(SAY_MO_RESURRECTED);
-
- me->RemoveFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NOT_SELECTABLE);
- me->SetStandState(UNIT_STAND_STATE_STAND);
- });
-
- scheduler.Schedule(Seconds(5), [this](TaskContext /*context*/)
- {
- // Schedule events after ressurrect
- events.ScheduleEvent(EVENT_CRUSADER_STRIKE, Seconds(10), Seconds(15));
- events.ScheduleEvent(EVENT_HAMMER_OF_JUSTICE, Seconds(10), Seconds(15));
-
- // We can now die
- me->SetReactState(REACT_AGGRESSIVE);
- m_CanDie = true;
- });
- }
+ ExecuteEvent(eventId);
+ if (me->HasUnitState(UNIT_STATE_CASTING))
+ return;
}
- private:
- /// Timers
- EventMap events;
- TaskScheduler scheduler;
+ DoMeleeAttackIfReady();
+ }
- /// Variables
- time_t m_LastKillTime;
- bool m_FakeDeath;
- bool m_CanDie;
+private:
+ TimeTrackerSmall _killYellTimer;
+ bool _fakeDeath;
+ bool _canDie;
};
-/// High Inquisitor Whitemane - 3977
+// High Inquisitor Whitemane - 3977
struct boss_high_inquisitor_whitemane : public ScriptedAI
{
- public:
- boss_high_inquisitor_whitemane(Creature* creature) : ScriptedAI(creature)
+public:
+ boss_high_inquisitor_whitemane(Creature* creature) : ScriptedAI(creature), _instance(creature->GetInstanceScript()), _killYellTimer(0)
+ {
+ Initialize();
+ }
+
+ void Initialize()
+ {
+ _ressurectionInProgress = false;
+ _canDie = true;
+ }
+
+ void Reset() override
+ {
+ Initialize();
+
+ _events.Reset();
+ _scheduler.CancelAll();
+ _killYellTimer.Reset(0);
+
+ DoCastSelf(SPELL_RETRIBUTION_AURA);
+ me->SetReactState(REACT_AGGRESSIVE);
+ }
+
+ void JustEngagedWith(Unit* /*who*/) override
+ {
+ Talk(SAY_WH_INTRO);
+
+ // Just to be sure it's MOTION_SLOT_DEFAULT is static
+ me->GetMotionMaster()->MoveIdle();
+
+ // Start events after 5 seconds
+ _scheduler.Schedule(5s, [this](TaskContext /*context*/)
{
- Initialize();
- }
-
- void Initialize()
+ _events.ScheduleEvent(EVENT_HEAL, 10s);
+ _events.ScheduleEvent(EVENT_POWER_WORD_SHIELD, 15s);
+ _events.ScheduleEvent(EVENT_HOLY_SMITE, 6s);
+ });
+ }
+
+ void KilledUnit(Unit* who) override
+ {
+ if (who->GetTypeId() != TYPEID_PLAYER)
+ return;
+
+ if (_killYellTimer.Passed())
{
- m_LastKillTime = 0;
- m_RessurectionInProgress = false;
- m_CanDie = false;
+ Talk(SAY_WH_KILL);
+ _killYellTimer.Reset(5 * IN_MILLISECONDS);
}
+ }
- void Reset() override
- {
- events.Reset();
- scheduler.CancelAll();
+ void UpdateAI(const uint32 diff) override
+ {
+ if (!UpdateVictim())
+ return;
- DoCast(me, SPELL_RETRIBUTIONAURA);
- me->SetReactState(REACT_AGGRESSIVE);
- }
+ _events.Update(diff);
+ _scheduler.Update(diff);
- void JustEngagedWith(Unit* /*who*/) override
- {
- Talk(SAY_WH_INTRO);
+ if (!_killYellTimer.Passed())
+ _killYellTimer.Update(diff);
- // Start events after 5 seconds
- scheduler.Schedule(Seconds(5), [this](TaskContext /*context*/)
- {
- events.ScheduleEvent(EVENT_HEAL, Seconds(10));
- events.ScheduleEvent(EVENT_POWER_WORD_SHIELD, Seconds(15));
- events.ScheduleEvent(EVENT_HOLY_SMITE, Seconds(6));
- });
- }
+ if (me->HasUnitState(UNIT_STATE_CASTING))
+ return;
- void KilledUnit(Unit* who) override
+ while (uint32 eventId = _events.ExecuteEvent())
{
- if (who->GetTypeId() != TYPEID_PLAYER)
- return;
-
- // Cooldown between talking
- time_t currTime = GameTime::GetGameTime();
-
- if (m_LastKillTime < currTime)
+ switch (eventId)
{
- Talk(SAY_MO_KILL);
- m_LastKillTime = currTime + 5;
- }
- }
-
- void UpdateAI(const uint32 diff) override
- {
- if (!UpdateVictim())
- return;
-
- events.Update(diff);
- scheduler.Update(diff);
-
- if (me->HasUnitState(UNIT_STATE_CASTING))
- return;
-
- if (uint32 eventId = events.ExecuteEvent())
- {
- switch (eventId)
+ case EVENT_HEAL:
{
- case EVENT_HEAL:
+ Creature* target = nullptr;
+ if (HealthBelowPct(75))
+ target = me;
+ else if (Creature* mograine = _instance->GetCreature(DATA_MOGRAINE))
{
- Creature* target = nullptr;
-
- if (HealthBelowPct(75))
- target = me;
- else if (auto instance = me->GetInstanceScript())
- {
- if (auto mograine = ObjectAccessor::GetCreature(*me, instance->GetGuidData(DATA_MOGRAINE)))
- if (mograine->IsAlive() && mograine->HealthBelowPct(75))
- target = mograine;
- }
-
- if (target)
- DoCast(target, SPELL_HEAL);
-
- events.Repeat(Seconds(13));
- break;
+ if (mograine->IsAlive() && mograine->HealthBelowPct(75))
+ target = mograine;
}
- case EVENT_POWER_WORD_SHIELD:
- DoCastSelf(SPELL_POWERWORDSHIELD);
- events.Repeat(Seconds(15));
- break;
- case EVENT_HOLY_SMITE:
- DoCastVictim(SPELL_HOLYSMITE);
- events.Repeat(Seconds(6));
- break;
- default:
- break;
+
+ if (target)
+ DoCast(target, SPELL_HEAL);
+
+ _events.Repeat(13s);
+ break;
}
+ case EVENT_POWER_WORD_SHIELD:
+ DoCastSelf(SPELL_POWER_WORD_SHIELD);
+ _events.Repeat(15s);
+ break;
+ case EVENT_HOLY_SMITE:
+ DoCastVictim(SPELL_HOLY_SMITE);
+ _events.Repeat(6s);
+ break;
+ default:
+ break;
}
- DoMeleeAttackIfReady();
+ if (me->HasUnitState(UNIT_STATE_CASTING))
+ return;
}
- void DamageTaken(Unit* /*who*/, uint32& damage) override
- {
- // When Whitemane falls below 50% cast Deep sleep and schedule to ressurrect
- if (me->HealthBelowPctDamaged(50, damage) && !m_RessurectionInProgress)
- {
- m_RessurectionInProgress = true;
+ if (me->HasReactState(REACT_AGGRESSIVE))
+ DoMeleeAttackIfReady();
+ }
- // Cancel all combat events
- events.CancelEvent(EVENT_HEAL);
- events.CancelEvent(EVENT_POWER_WORD_SHIELD);
- events.CancelEvent(EVENT_HOLY_SMITE);
+ void DamageTaken(Unit* /*who*/, uint32& damage) override
+ {
+ // When Whitemane falls below 50% cast Deep sleep and schedule to ressurrect
+ if (me->HealthBelowPctDamaged(50, damage) && !_ressurectionInProgress)
+ {
+ _ressurectionInProgress = true;
+ _canDie = false;
- if (me->IsNonMeleeSpellCast(false))
- me->InterruptNonMeleeSpells(false);
+ // Cancel all combat events
+ _events.CancelEvent(EVENT_HEAL);
+ _events.CancelEvent(EVENT_POWER_WORD_SHIELD);
+ _events.CancelEvent(EVENT_HOLY_SMITE);
- // Sleep all players
- DoCastAOE(SPELL_DEEPSLEEP);
+ me->InterruptNonMeleeSpells(true);
- // Move to mograine
- if (auto instance = me->GetInstanceScript())
- {
- if (auto mograine = ObjectAccessor::GetCreature(*me, instance->GetGuidData(DATA_MOGRAINE)))
- {
- // Stop moving
- me->SetReactState(REACT_PASSIVE);
- me->GetMotionMaster()->Clear();
+ // Sleep all players
+ DoCastAOE(SPELL_DEEP_SLEEP);
- Position pos = *mograine;
+ if (Creature* mograine = _instance->GetCreature(DATA_MOGRAINE))
+ {
+ me->SetReactState(REACT_PASSIVE);
+ me->GetMotionMaster()->Clear(MOTION_PRIORITY_NORMAL);
- // Get a position within 2 yards of mograine, and facing him
- me->MovePosition(pos, 2.0f, me->GetRelativeAngle(*mograine));
+ Position movePosition = mograine->GetPosition();
- me->GetMotionMaster()->MovePoint(POINT_WHITEMANE_MOVE_TO_MOGRAINE, pos);
- }
- }
+ // Get a position within 2 yards of mograine, and facing him
+ me->MovePosition(movePosition, 2.0f, me->GetRelativeAngle(movePosition));
+ me->GetMotionMaster()->MovePoint(POINT_WHITEMANE_MOVE_TO_MOGRAINE, movePosition);
}
-
- if (!m_CanDie && damage >= me->GetHealth())
- damage = 0;
}
- void MovementInform(uint32 type, uint32 id) override
- {
- if (type != POINT_MOTION_TYPE)
- return;
-
- if (id == POINT_WHITEMANE_MOVE_TO_MOGRAINE)
- {
- if (auto instance = me->GetInstanceScript())
- if (auto mograine = ObjectAccessor::GetCreature(*me, instance->GetGuidData(DATA_MOGRAINE)))
- me->SetFacingToObject(mograine);
-
- // After 3 seconds cast scarlet ressurection
- scheduler.Schedule(Seconds(3), [this](TaskContext /*context*/)
- {
- if (auto instance = me->GetInstanceScript())
- if (auto mograine = ObjectAccessor::GetCreature(*me, instance->GetGuidData(DATA_MOGRAINE)))
- DoCast(mograine, SPELL_SCARLETRESURRECTION);
- });
+ if (!_canDie && damage >= me->GetHealth())
+ damage = 0;
+ }
- // After 5 seconds or when finish cast spell, say Arise my champion.. (Maybe this belongs in an OnSuccessfulCastSpell hook? .. if that exists
- scheduler.Schedule(Seconds(5), [this](TaskContext /*context*/)
- {
- Talk(SAY_WH_RESURRECT);
-
- // Schedule events again
- events.ScheduleEvent(EVENT_HEAL, Seconds(10));
- events.ScheduleEvent(EVENT_POWER_WORD_SHIELD, Seconds(15));
- events.ScheduleEvent(EVENT_HOLY_SMITE, Seconds(6));
-
- m_CanDie = true;
- me->SetReactState(REACT_AGGRESSIVE);
- });
- }
- }
+ void MovementInform(uint32 type, uint32 id) override
+ {
+ if (type != POINT_MOTION_TYPE || id != POINT_WHITEMANE_MOVE_TO_MOGRAINE)
+ return;
- private:
- /// Timers
- EventMap events;
- TaskScheduler scheduler;
+ if (Creature* mograine = _instance->GetCreature(DATA_MOGRAINE))
+ me->SetFacingToObject(mograine);
- /// Variables
- time_t m_LastKillTime;
- bool m_RessurectionInProgress;
- bool m_CanDie;
+ // After 3 seconds cast scarlet ressurection
+ _scheduler.Schedule(3s, [this](TaskContext /*context*/)
+ {
+ if (Creature* mograine = _instance->GetCreature(DATA_MOGRAINE))
+ DoCast(mograine, SPELL_SCARLET_RESURRECTION);
+ else
+ MograineResurrected();
+ });
+ }
+
+ void SpellHitTarget(Unit* target, SpellInfo const* spellInfo) override
+ {
+ if (target->GetEntry() == NPC_MOGRAINE && spellInfo->Id == SPELL_SCARLET_RESURRECTION)
+ MograineResurrected();
+ }
+
+private:
+ void MograineResurrected()
+ {
+ Talk(SAY_WH_RESURRECT);
+
+ // Schedule events again
+ _events.ScheduleEvent(EVENT_HEAL, 10s);
+ _events.ScheduleEvent(EVENT_POWER_WORD_SHIELD, 15s);
+ _events.ScheduleEvent(EVENT_HOLY_SMITE, 6s);
+
+ _canDie = true;
+
+ me->SetReactState(REACT_AGGRESSIVE);
+
+ if (me->GetVictim())
+ me->GetMotionMaster()->MoveChase(me->GetVictim());
+ }
+
+ InstanceScript* _instance;
+ EventMap _events;
+ TaskScheduler _scheduler;
+ TimeTrackerSmall _killYellTimer;
+ bool _ressurectionInProgress;
+ bool _canDie;
};
void AddSC_boss_mograine_and_whitemane()
{
- RegisterScarletMonastaryCreatureAI(boss_scarlet_commander_mograine);
- RegisterScarletMonastaryCreatureAI(boss_high_inquisitor_whitemane);
+ RegisterScarletMonasteryCreatureAI(boss_scarlet_commander_mograine);
+ RegisterScarletMonasteryCreatureAI(boss_high_inquisitor_whitemane);
}
diff --git a/src/server/scripts/EasternKingdoms/ScarletMonastery/boss_scorn.cpp b/src/server/scripts/EasternKingdoms/ScarletMonastery/boss_scorn.cpp
index d33c0e47d16..ee37e277fcd 100644
--- a/src/server/scripts/EasternKingdoms/ScarletMonastery/boss_scorn.cpp
+++ b/src/server/scripts/EasternKingdoms/ScarletMonastery/boss_scorn.cpp
@@ -15,87 +15,66 @@
* with this program. If not, see <http://www.gnu.org/licenses/>.
*/
-#include "ScriptMgr.h"
-#include "ScriptedCreature.h"
#include "scarlet_monastery.h"
+#include "ScriptedCreature.h"
+#include "ScriptMgr.h"
-enum Spells
+enum ScornSpells
{
- SPELL_LICHSLAP = 28873,
- SPELL_FROSTBOLT_VOLLEY = 8398,
- SPELL_MINDFLAY = 17313,
- SPELL_FROSTNOVA = 15531
+ SPELL_LICHSLAP = 28873,
+ SPELL_FROSTBOLT_VOLLEY = 8398,
+ SPELL_MINDFLAY = 17313,
+ SPELL_FROSTNOVA = 15531
};
-enum Events
+enum ScornEvents
{
- EVENT_LICH_SLAP = 1,
+ EVENT_LICH_SLAP = 1,
EVENT_FROSTBOLT_VOLLEY,
EVENT_MIND_FLAY,
EVENT_FROST_NOVA
};
-class boss_scorn : public CreatureScript
+struct boss_scorn : public BossAI
{
- public:
- boss_scorn() : CreatureScript("boss_scorn") { }
-
- struct boss_scornAI : public BossAI
- {
- boss_scornAI(Creature* creature) : BossAI(creature, DATA_SCORN) { }
-
- void Reset() override
- {
- _Reset();
- }
-
- void JustEngagedWith(Unit* /*who*/) override
- {
- _JustEngagedWith();
- events.ScheduleEvent(EVENT_LICH_SLAP, 45s);
- events.ScheduleEvent(EVENT_FROSTBOLT_VOLLEY, 30s);
- events.ScheduleEvent(EVENT_MIND_FLAY, 30s);
- events.ScheduleEvent(EVENT_FROST_NOVA, 30s);
- }
-
- void JustDied(Unit* /*killer*/) override
- {
- _JustDied();
- }
+ boss_scorn(Creature* creature) : BossAI(creature, DATA_SCORN) { }
- void ExecuteEvent(uint32 eventId) override
- {
- switch (eventId)
- {
- case EVENT_LICH_SLAP:
- DoCastVictim(SPELL_LICHSLAP);
- events.ScheduleEvent(EVENT_LICH_SLAP, 45s);
- break;
- case EVENT_FROSTBOLT_VOLLEY:
- DoCastVictim(SPELL_FROSTBOLT_VOLLEY);
- events.ScheduleEvent(EVENT_FROSTBOLT_VOLLEY, 20s);
- break;
- case EVENT_MIND_FLAY:
- DoCastVictim(SPELL_MINDFLAY);
- events.ScheduleEvent(EVENT_MIND_FLAY, 20s);
- break;
- case EVENT_FROST_NOVA:
- DoCastVictim(SPELL_FROSTNOVA);
- events.ScheduleEvent(EVENT_FROST_NOVA, 15s);
- break;
- default:
- break;
- }
- }
- };
+ void JustEngagedWith(Unit* /*who*/) override
+ {
+ _JustEngagedWith();
+ events.ScheduleEvent(EVENT_LICH_SLAP, 45s);
+ events.ScheduleEvent(EVENT_FROSTBOLT_VOLLEY, 30s);
+ events.ScheduleEvent(EVENT_MIND_FLAY, 30s);
+ events.ScheduleEvent(EVENT_FROST_NOVA, 30s);
+ }
- CreatureAI* GetAI(Creature* creature) const override
+ void ExecuteEvent(uint32 eventId) override
+ {
+ switch (eventId)
{
- return GetScarletMonasteryAI<boss_scornAI>(creature);
+ case EVENT_LICH_SLAP:
+ DoCastVictim(SPELL_LICHSLAP);
+ events.Repeat(45s);
+ break;
+ case EVENT_FROSTBOLT_VOLLEY:
+ DoCastVictim(SPELL_FROSTBOLT_VOLLEY);
+ events.Repeat(20s);
+ break;
+ case EVENT_MIND_FLAY:
+ DoCastVictim(SPELL_MINDFLAY);
+ events.Repeat(20s);
+ break;
+ case EVENT_FROST_NOVA:
+ DoCastVictim(SPELL_FROSTNOVA);
+ events.Repeat(15s);
+ break;
+ default:
+ break;
}
+ }
};
void AddSC_boss_scorn()
{
- new boss_scorn();
+ RegisterScarletMonasteryCreatureAI(boss_scorn);
}
diff --git a/src/server/scripts/EasternKingdoms/ScarletMonastery/instance_scarlet_monastery.cpp b/src/server/scripts/EasternKingdoms/ScarletMonastery/instance_scarlet_monastery.cpp
index ed2263bea31..ac79ec42da0 100644
--- a/src/server/scripts/EasternKingdoms/ScarletMonastery/instance_scarlet_monastery.cpp
+++ b/src/server/scripts/EasternKingdoms/ScarletMonastery/instance_scarlet_monastery.cpp
@@ -15,12 +15,29 @@
* with this program. If not, see <http://www.gnu.org/licenses/>.
*/
-#include "ScriptMgr.h"
+#include "scarlet_monastery.h"
#include "Creature.h"
#include "GameObject.h"
#include "InstanceScript.h"
#include "Map.h"
-#include "scarlet_monastery.h"
+#include "ScriptMgr.h"
+
+ObjectData const creatureData[] =
+{
+ { NPC_HEAD, DATA_HEAD },
+ { NPC_HORSEMAN, DATA_HORSEMAN },
+ { NPC_MOGRAINE, DATA_MOGRAINE },
+ { NPC_VORREL, DATA_VORREL },
+ { NPC_WHITEMANE, DATA_WHITEMANE },
+ { 0, 0 } // END
+};
+
+ObjectData const gameObjectData[] =
+{
+ { GO_PUMPKIN_SHRINE, DATA_PUMPKIN_SHRINE },
+ { GO_HIGH_INQUISITORS_DOOR, DATA_HIGH_INQUISITORS_DOOR },
+ { 0, 0 } // END
+};
class instance_scarlet_monastery : public InstanceMapScript
{
@@ -33,62 +50,21 @@ class instance_scarlet_monastery : public InstanceMapScript
{
SetHeaders(DataHeader);
SetBossNumber(EncounterCount);
- }
-
- void OnGameObjectCreate(GameObject* go) override
- {
- InstanceScript::OnGameObjectCreate(go);
-
- switch (go->GetEntry())
- {
- case GO_PUMPKIN_SHRINE:
- PumpkinShrineGUID = go->GetGUID();
- break;
- case GO_HIGH_INQUISITORS_DOOR:
- HighInquistorDoorGUID = go->GetGUID();
- break;
- default:
- break;
- }
+ LoadObjectData(creatureData, gameObjectData);
}
void OnCreatureCreate(Creature* creature) override
{
switch (creature->GetEntry())
{
- case NPC_HORSEMAN:
- HorsemanGUID = creature->GetGUID();
- break;
- case NPC_HEAD:
- HeadGUID = creature->GetGUID();
- break;
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;
default:
break;
}
- }
- void SetData(uint32 type, uint32 /*data*/) override
- {
- switch (type)
- {
- case DATA_PUMPKIN_SHRINE:
- HandleGameObject(PumpkinShrineGUID, false);
- break;
- default:
- break;
- }
+ InstanceScript::OnCreatureCreate(creature);
}
bool SetBossState(uint32 type, EncounterState state) override
@@ -99,16 +75,18 @@ class instance_scarlet_monastery : public InstanceMapScript
switch (type)
{
case DATA_HORSEMAN_EVENT:
- if (state == DONE)
+ if (state == DONE || state == FAIL || state == NOT_STARTED)
{
- for (ObjectGuid guid : HorsemanAdds)
+ for (ObjectGuid const& guid : HorsemanAdds)
{
Creature* add = instance->GetCreature(guid);
- if (add && add->IsAlive())
- add->KillSelf();
+ if (add)
+ add->DespawnOrUnsummon();
}
HorsemanAdds.clear();
- HandleGameObject(PumpkinShrineGUID, false);
+
+ if (state == DONE)
+ HandleGameObject(ObjectGuid::Empty, false, GetGameObject(DATA_PUMPKIN_SHRINE));
}
break;
default:
@@ -117,39 +95,8 @@ class instance_scarlet_monastery : public InstanceMapScript
return true;
}
- ObjectGuid GetGuidData(uint32 type) const override
- {
- switch (type)
- {
- /// Creatures
- case DATA_MOGRAINE:
- return MograineGUID;
- case DATA_WHITEMANE:
- return WhitemaneGUID;
- case DATA_VORREL:
- return VorrelGUID;
- /// GameObjects
- case GO_HIGH_INQUISITORS_DOOR:
- return HighInquistorDoorGUID;
- default:
- break;
- }
- return ObjectGuid::Empty;
- }
-
protected:
- /// Creatures
- ObjectGuid HorsemanGUID;
- ObjectGuid HeadGUID;
- ObjectGuid MograineGUID;
- ObjectGuid WhitemaneGUID;
- ObjectGuid VorrelGUID;
-
- /// GameObjects
- ObjectGuid PumpkinShrineGUID;
- ObjectGuid HighInquistorDoorGUID;
-
- GuidSet HorsemanAdds;
+ GuidUnorderedSet HorsemanAdds;
};
InstanceScript* GetInstanceScript(InstanceMap* map) const override
diff --git a/src/server/scripts/EasternKingdoms/ScarletMonastery/scarlet_monastery.h b/src/server/scripts/EasternKingdoms/ScarletMonastery/scarlet_monastery.h
index bd2c3f39833..6cd2584f6c9 100644
--- a/src/server/scripts/EasternKingdoms/ScarletMonastery/scarlet_monastery.h
+++ b/src/server/scripts/EasternKingdoms/ScarletMonastery/scarlet_monastery.h
@@ -27,39 +27,42 @@ uint32 const EncounterCount = 10;
enum SMDataTypes
{
- DATA_MOGRAINE_AND_WHITE_EVENT = 1,
- DATA_MOGRAINE = 2,
- DATA_WHITEMANE = 3,
+ DATA_INTERROGATOR_VISHAS = 0,
+ DATA_BLOODMAGE_THALNOS,
+ DATA_HOUNDMASTER_LOKSEY,
+ DATA_ARCANIST_DOAN,
+ DATA_HEROD,
+ DATA_HIGH_INQUISITOR_FAIRBANKS,
+ DATA_MOGRAINE_AND_WHITE_EVENT, // Last DungeonEncounter.dbc entry
- DATA_HORSEMAN_EVENT = 4,
- DATA_PUMPKIN_SHRINE = 5,
+ DATA_AZSHIR,
+ DATA_SCORN,
+ DATA_HORSEMAN_EVENT, // Last defined encounter
- DATA_VORREL = 6,
- DATA_ARCANIST_DOAN = 7,
- DATA_AZSHIR = 8,
- DATA_BLOODMAGE_THALNOS = 9,
- DATA_HEROD = 10,
- DATA_HIGH_INQUISITOR_FAIRBANKS = 11,
- DATA_HOUNDMASTER_LOKSEY = 12,
- DATA_INTERROGATOR_VISHAS = 13,
- DATA_SCORN = 14
+ DATA_HEAD,
+ DATA_HORSEMAN,
+ DATA_MOGRAINE,
+ DATA_VORREL,
+ DATA_WHITEMANE,
+
+ DATA_PUMPKIN_SHRINE,
+ DATA_HIGH_INQUISITORS_DOOR,
};
enum SMCreatureIds
{
- NPC_MOGRAINE = 3976,
- NPC_WHITEMANE = 3977,
- NPC_VORREL = 3981,
-
- NPC_HORSEMAN = 23682,
- NPC_HEAD = 23775,
- NPC_PUMPKIN = 23694
+ NPC_MOGRAINE = 3976,
+ NPC_WHITEMANE = 3977,
+ NPC_VORREL = 3981,
+ NPC_HORSEMAN = 23682,
+ NPC_HEAD = 23775,
+ NPC_PUMPKIN = 23694
};
enum SMGameObjectIds
{
- GO_HIGH_INQUISITORS_DOOR = 104600,
- GO_PUMPKIN_SHRINE = 186267
+ GO_HIGH_INQUISITORS_DOOR = 104600,
+ GO_PUMPKIN_SHRINE = 186267
};
template <class AI, class T>
@@ -68,6 +71,7 @@ inline AI* GetScarletMonasteryAI(T* obj)
return GetInstanceAI<AI>(obj, SMScriptName);
}
-#define RegisterScarletMonastaryCreatureAI(ai) RegisterCreatureAIWithFactory(ai, GetScarletMonasteryAI)
+#define RegisterScarletMonasteryCreatureAI(ai) RegisterCreatureAIWithFactory(ai, GetScarletMonasteryAI)
+#define RegisterScarletMonasteryGameObjectAI(ai) RegisterGameObjectAIWithFactory(ai, GetScarletMonasteryAI)
#endif // SCARLET_M_
diff --git a/src/server/shared/Dynamic/LinkedReference/RefManager.h b/src/server/shared/Dynamic/LinkedReference/RefManager.h
index 208bb75e182..acc3d33f397 100644
--- a/src/server/shared/Dynamic/LinkedReference/RefManager.h
+++ b/src/server/shared/Dynamic/LinkedReference/RefManager.h
@@ -18,7 +18,6 @@
#ifndef _REFMANAGER_H
#define _REFMANAGER_H
-//=====================================================
#include "Dynamic/LinkedList.h"
#include "Dynamic/LinkedReference/Reference.h"
@@ -26,28 +25,31 @@
template <class TO, class FROM>
class RefManager : public LinkedListHead
{
- public:
- typedef LinkedListHead::Iterator<Reference<TO, FROM>> iterator;
- RefManager() { }
+public:
+ typedef LinkedListHead::Iterator<Reference<TO, FROM>> iterator;
+ typedef LinkedListHead::Iterator<Reference<TO, FROM> const> const_iterator;
+ RefManager() { }
- Reference<TO, FROM>* getFirst() { return static_cast<Reference<TO, FROM>*>(LinkedListHead::getFirst()); }
+ Reference<TO, FROM>* getFirst() { return static_cast<Reference<TO, FROM>*>(LinkedListHead::getFirst()); }
- Reference<TO, FROM> const* getFirst() const { return static_cast<Reference<TO, FROM> const*>(LinkedListHead::getFirst()); }
+ Reference<TO, FROM> const* getFirst() const { return static_cast<Reference<TO, FROM> const*>(LinkedListHead::getFirst()); }
- iterator begin() { return iterator(getFirst()); }
- iterator end() { return iterator(nullptr); }
+ iterator begin() { return iterator(getFirst()); }
+ iterator end() { return iterator(nullptr); }
- virtual ~RefManager()
- {
- clearReferences();
- }
+ const_iterator begin() const { return const_iterator(getFirst()); }
+ const_iterator end() const { return const_iterator(nullptr); }
- void clearReferences()
- {
- while (Reference<TO, FROM>* ref = getFirst())
- ref->invalidate();
- }
+ virtual ~RefManager()
+ {
+ clearReferences();
+ }
+
+ void clearReferences()
+ {
+ while (Reference<TO, FROM>* ref = getFirst())
+ ref->invalidate();
+ }
};
-//=====================================================
#endif