diff --git a/data/sql/updates/pending_db_world/rev_1659294015696463500.sql b/data/sql/updates/pending_db_world/rev_1659294015696463500.sql
new file mode 100644
index 000000000..1f372bfe9
--- /dev/null
+++ b/data/sql/updates/pending_db_world/rev_1659294015696463500.sql
@@ -0,0 +1,7 @@
+--
+UPDATE `creature_formations` SET `dist`=5 WHERE `memberGUID` IN (87649,87650,87651);
+
+DELETE FROM `spell_linked_spell` WHERE `spell_trigger`=26084 AND `spell_effect`=25174 AND `type`=1;
+INSERT INTO `spell_linked_spell` (`spell_trigger`, `spell_effect`, `type`, `comment`) VALUES
+(26084, 25174, 1, 'Battleguard Sartura - OnHit Whirlwind - Apply Sundering Cleave');
+
diff --git a/src/server/scripts/Kalimdor/TempleOfAhnQiraj/boss_sartura.cpp b/src/server/scripts/Kalimdor/TempleOfAhnQiraj/boss_sartura.cpp
index f851d2b5c..789fe5bcf 100644
--- a/src/server/scripts/Kalimdor/TempleOfAhnQiraj/boss_sartura.cpp
+++ b/src/server/scripts/Kalimdor/TempleOfAhnQiraj/boss_sartura.cpp
@@ -15,301 +15,314 @@
* with this program. If not, see .
*/
-/* ScriptData
-SDName: Boss_Sartura
-SD%Complete: 95
-SDComment:
-SDCategory: Temple of Ahn'Qiraj
-EndScriptData */
-
#include "ScriptMgr.h"
+#include "SpellScript.h"
#include "ScriptedCreature.h"
#include "temple_of_ahnqiraj.h"
-enum Sartura
+enum Says
{
- SAY_AGGRO = 0,
- SAY_SLAY = 1,
- SAY_DEATH = 2,
-
- SPELL_WHIRLWIND = 26083,
- SPELL_ENRAGE = 8269,
- SPELL_BERSERK = 27680,
-
- //Guard Spell
- SPELL_WHIRLWINDADD = 26038,
- SPELL_KNOCKBACK = 26027
+ SAY_AGGRO = 0,
+ SAY_SLAY = 1,
+ SAY_DEATH = 2
};
-class boss_sartura : public CreatureScript
+enum Spells
{
-public:
- boss_sartura() : CreatureScript("boss_sartura") { }
+ // Battleguard Sartura
+ SPELL_WHIRLWIND = 26083, // MechanicImmunity->Stunned (15sec)
+ SPELL_ENRAGE = 8269,
+ SPELL_BERSERK = 27680,
+ SPELL_SUNDERING_CLEAVE = 25174,
- CreatureAI* GetAI(Creature* creature) const override
- {
- return GetTempleOfAhnQirajAI(creature);
- }
-
- struct boss_sarturaAI : public ScriptedAI
- {
- boss_sarturaAI(Creature* creature) : ScriptedAI(creature) { }
-
- uint32 WhirlWind_Timer;
- uint32 WhirlWindRandom_Timer;
- uint32 WhirlWindEnd_Timer;
- uint32 AggroReset_Timer;
- uint32 AggroResetEnd_Timer;
- uint32 EnrageHard_Timer;
-
- bool Enraged;
- bool EnragedHard;
- bool WhirlWind;
- bool AggroReset;
-
- void Reset() override
- {
- WhirlWind_Timer = 30000;
- WhirlWindRandom_Timer = urand(3000, 7000);
- WhirlWindEnd_Timer = 15000;
- AggroReset_Timer = urand(45000, 55000);
- AggroResetEnd_Timer = 5000;
- EnrageHard_Timer = 10 * 60000;
-
- WhirlWind = false;
- AggroReset = false;
- Enraged = false;
- EnragedHard = false;
- }
-
- void EnterCombat(Unit* /*who*/) override
- {
- Talk(SAY_AGGRO);
- }
-
- void JustDied(Unit* /*killer*/) override
- {
- Talk(SAY_DEATH);
- }
-
- void KilledUnit(Unit* /*victim*/) override
- {
- Talk(SAY_SLAY);
- }
-
- void UpdateAI(uint32 diff) override
- {
- //Return since we have no target
- if (!UpdateVictim())
- return;
-
- if (WhirlWind)
- {
- if (WhirlWindRandom_Timer <= diff)
- {
- //Attack random Gamers
- if (Unit* target = SelectTarget(SelectTargetMethod::Random, 1, 100.0f, true))
- {
- me->AddThreat(target, 1.0f);
- me->TauntApply(target);
- AttackStart(target);
- }
- WhirlWindRandom_Timer = urand(3000, 7000);
- }
- else WhirlWindRandom_Timer -= diff;
-
- if (WhirlWindEnd_Timer <= diff)
- {
- WhirlWind = false;
- WhirlWind_Timer = urand(25000, 40000);
- }
- else WhirlWindEnd_Timer -= diff;
- }
-
- if (!WhirlWind)
- {
- if (WhirlWind_Timer <= diff)
- {
- DoCast(me, SPELL_WHIRLWIND);
- WhirlWind = true;
- WhirlWindEnd_Timer = 15000;
- }
- else WhirlWind_Timer -= diff;
-
- if (AggroReset_Timer <= diff)
- {
- //Attack random Gamers
- if (Unit* target = SelectTarget(SelectTargetMethod::Random, 1, 100.0f, true))
- {
- me->AddThreat(target, 1.0f);
- me->TauntApply(target);
- AttackStart(target);
- }
- AggroReset = true;
- AggroReset_Timer = urand(2000, 5000);
- }
- else AggroReset_Timer -= diff;
-
- if (AggroReset)
- {
- if (AggroResetEnd_Timer <= diff)
- {
- AggroReset = false;
- AggroResetEnd_Timer = 5000;
- AggroReset_Timer = urand(35000, 45000);
- }
- else AggroResetEnd_Timer -= diff;
- }
-
- //If she is 20% enrage
- if (!Enraged)
- {
- if (!HealthAbovePct(20) && !me->IsNonMeleeSpellCast(false))
- {
- DoCast(me, SPELL_ENRAGE, true);
- Enraged = true;
- }
- }
-
- //After 10 minutes hard enrage
- if (!EnragedHard)
- {
- if (EnrageHard_Timer <= diff)
- {
- DoCast(me, SPELL_BERSERK, true);
- EnragedHard = true;
- }
- else EnrageHard_Timer -= diff;
- }
-
- DoMeleeAttackIfReady();
- }
- }
- };
+ // Sartura's Royal Guard
+ SPELL_GUARD_WHIRLWIND = 26038,
+ SPELL_GUARD_KNOCKBACK = 26027
};
-class npc_sartura_royal_guard : public CreatureScript
+enum events
{
-public:
- npc_sartura_royal_guard() : CreatureScript("npc_sartura_royal_guard") { }
+ // Battleguard Sartura
+ EVENT_SARTURA_WHIRLWIND = 1,
+ EVENT_SARTURA_WHIRLWIND_RANDOM = 2,
+ EVENT_SARTURA_WHIRLWIND_END = 3,
+ EVENT_SPELL_BERSERK = 4,
+ EVENT_SARTURA_AGGRO_RESET = 5,
+ EVENT_SARTURA_AGGRO_RESET_END = 6,
- CreatureAI* GetAI(Creature* creature) const override
+ // Sartura's Royal Guard
+ EVENT_GUARD_WHIRLWIND = 7,
+ EVENT_GUARD_WHIRLWIND_RANDOM = 8,
+ EVENT_GUARD_WHIRLWIND_END = 9,
+ EVENT_GUARD_KNOCKBACK = 10,
+ EVENT_GUARD_AGGRO_RESET = 11,
+ EVENT_GUARD_AGGRO_RESET_END = 12
+};
+
+struct boss_sartura : public BossAI
+{
+ boss_sartura(Creature* creature) : BossAI(creature, DATA_SARTURA) {}
+
+ void Reset() override
{
- return GetTempleOfAhnQirajAI(creature);
+ _Reset();
+ whirlwind = false;
+ enraged = false;
+ berserked = false;
+ aggroReset = false;
+ MinionReset();
+ _savedTargetGUID.Clear();
+ _savedTargetThreat = 0.f;
}
- struct npc_sartura_royal_guardAI : public ScriptedAI
+ void MinionReset()
{
- npc_sartura_royal_guardAI(Creature* creature) : ScriptedAI(creature) { }
-
- uint32 WhirlWind_Timer;
- uint32 WhirlWindRandom_Timer;
- uint32 WhirlWindEnd_Timer;
- uint32 AggroReset_Timer;
- uint32 AggroResetEnd_Timer;
- uint32 KnockBack_Timer;
-
- bool WhirlWind;
- bool AggroReset;
-
- void Reset() override
+ std::list royalGuards;
+ me->GetCreaturesWithEntryInRange(royalGuards, 200.0f, NPC_SARTURA_ROYAL_GUARD);
+ for (Creature* minion : royalGuards)
{
- WhirlWind_Timer = 30000;
- WhirlWindRandom_Timer = urand(3000, 7000);
- WhirlWindEnd_Timer = 15000;
- AggroReset_Timer = urand(45000, 55000);
- AggroResetEnd_Timer = 5000;
- KnockBack_Timer = 10000;
-
- WhirlWind = false;
- AggroReset = false;
+ minion->Respawn();
}
+ }
- void EnterCombat(Unit* /*who*/) override
+ void EnterCombat(Unit* who) override
+ {
+ BossAI::EnterCombat(who);
+ Talk(SAY_AGGRO);
+ events.ScheduleEvent(EVENT_SARTURA_WHIRLWIND, 30000);
+ events.ScheduleEvent(EVENT_SARTURA_AGGRO_RESET, urand(45000, 55000));
+ events.ScheduleEvent(EVENT_SPELL_BERSERK, 10 * 60000);
+ }
+
+ void JustDied(Unit* /*killer*/) override
+ {
+ _JustDied();
+ Talk(SAY_DEATH);
+ }
+
+ void KilledUnit(Unit* /*victim*/) override
+ {
+ Talk(SAY_SLAY);
+ }
+
+ void DamageTaken(Unit*, uint32& /*damage*/, DamageEffectType, SpellSchoolMask) override
+ {
+ if (!enraged && HealthBelowPct(20))
{
+ DoCastSelf(SPELL_ENRAGE);
+ enraged = true;
}
+ }
- void UpdateAI(uint32 diff) override
+ void SpellHit(Unit* /*caster*/, SpellInfo const* spell) override
+ {
+ if (spell->Id != SPELL_SUNDERING_CLEAVE)
+ return;
+
+ me->RemoveAura(SPELL_SUNDERING_CLEAVE);
+ }
+
+ void UpdateAI(uint32 diff) override
+ {
+ if (!UpdateVictim())
+ return;
+
+ events.Update(diff);
+
+ while (uint32 eventId = events.ExecuteEvent())
{
- //Return since we have no target
- if (!UpdateVictim())
- return;
-
- if (!WhirlWind && WhirlWind_Timer <= diff)
+ switch (eventId)
{
- DoCast(me, SPELL_WHIRLWINDADD);
- WhirlWind = true;
- WhirlWind_Timer = urand(25000, 40000);
- WhirlWindEnd_Timer = 15000;
- }
- else WhirlWind_Timer -= diff;
-
- if (WhirlWind)
- {
- if (WhirlWindRandom_Timer <= diff)
- {
- //Attack random Gamers
- if (Unit* target = SelectTarget(SelectTargetMethod::Random, 1, 100.0f, true))
+ case EVENT_SARTURA_WHIRLWIND:
+ DoCastSelf(SPELL_WHIRLWIND, true);
+ whirlwind = true;
+ events.ScheduleEvent(EVENT_SARTURA_WHIRLWIND_RANDOM, urand(3000, 7000));
+ events.ScheduleEvent(EVENT_SARTURA_WHIRLWIND_END, 15000);
+ break;
+ case EVENT_SARTURA_WHIRLWIND_RANDOM:
+ if (whirlwind == true)
{
- me->AddThreat(target, 1.0f);
- me->TauntApply(target);
- AttackStart(target);
+ if (Unit* target = SelectTarget(SelectTargetMethod::Random, 1, 100.0f, true))
+ {
+ me->AddThreat(target, 1.0f);
+ me->TauntApply(target);
+ AttackStart(target);
+ }
+ events.RepeatEvent(urand(3000, 7000));
}
-
- WhirlWindRandom_Timer = urand(3000, 7000);
- }
- else WhirlWindRandom_Timer -= diff;
-
- if (WhirlWindEnd_Timer <= diff)
- {
- WhirlWind = false;
- }
- else WhirlWindEnd_Timer -= diff;
- }
-
- if (!WhirlWind)
- {
- if (AggroReset_Timer <= diff)
- {
- //Attack random Gamers
- if (Unit* target = SelectTarget(SelectTargetMethod::Random, 1, 100.0f, true))
+ break;
+ case EVENT_SARTURA_WHIRLWIND_END:
+ events.CancelEvent(EVENT_SARTURA_WHIRLWIND_RANDOM);
+ whirlwind = false;
+ events.ScheduleEvent(EVENT_SARTURA_WHIRLWIND, urand(25000, 40000));
+ break;
+ case EVENT_SARTURA_AGGRO_RESET:
+ if (aggroReset == false)
{
- me->AddThreat(target, 1.0f);
- me->TauntApply(target);
- AttackStart(target);
+ if (Unit* originalTarget = SelectTarget(SelectTargetMethod::Random, 0))
+ {
+ _savedTargetGUID = originalTarget->GetGUID();
+ _savedTargetThreat = me->GetThreatMgr().getThreat(originalTarget);
+ me->GetThreatMgr().modifyThreatPercent(originalTarget, -100);
+ }
+ aggroReset = true;
+ events.ScheduleEvent(EVENT_SARTURA_AGGRO_RESET_END, 5000);
}
-
- AggroReset = true;
- AggroReset_Timer = urand(2000, 5000);
- }
- else AggroReset_Timer -= diff;
-
- if (KnockBack_Timer <= diff)
- {
- DoCast(me, SPELL_WHIRLWINDADD);
- KnockBack_Timer = urand(10000, 20000);
- }
- else KnockBack_Timer -= diff;
+ else
+ {
+ if (Unit* target = SelectTarget(SelectTargetMethod::Random, 1, 100.0f, true))
+ {
+ me->AddThreat(target, 1.0f);
+ me->TauntApply(target);
+ AttackStart(target);
+ }
+ }
+ events.RepeatEvent(urand(1000, 2000));
+ break;
+ case EVENT_SARTURA_AGGRO_RESET_END:
+ events.CancelEvent(EVENT_SARTURA_AGGRO_RESET);
+ if (Unit* originalTarget = ObjectAccessor::GetUnit(*me, _savedTargetGUID))
+ {
+ me->GetThreatMgr().addThreat(originalTarget, _savedTargetThreat);
+ _savedTargetGUID.Clear();
+ }
+ aggroReset = false;
+ events.RescheduleEvent(EVENT_SARTURA_AGGRO_RESET, urand(30000, 40000));
+ break;
+ case EVENT_SPELL_BERSERK:
+ if (!berserked)
+ {
+ DoCastSelf(SPELL_BERSERK);
+ berserked = true;
+ }
+ break;
+ default:
+ break;
}
-
- if (AggroReset)
- {
- if (AggroResetEnd_Timer <= diff)
- {
- AggroReset = false;
- AggroResetEnd_Timer = 5000;
- AggroReset_Timer = urand(30000, 40000);
- }
- else AggroResetEnd_Timer -= diff;
- }
-
- DoMeleeAttackIfReady();
}
+ DoMeleeAttackIfReady();
};
+ private:
+ bool whirlwind;
+ bool enraged;
+ bool berserked;
+ bool aggroReset;
+ ObjectGuid _savedTargetGUID;
+ float _savedTargetThreat;
+};
+
+struct npc_sartura_royal_guard : public ScriptedAI
+{
+ npc_sartura_royal_guard(Creature* creature) : ScriptedAI(creature) {}
+
+ void Reset() override
+ {
+ events.Reset();
+ whirlwind = false;
+ aggroReset = false;
+ _savedTargetGUID.Clear();
+ _savedTargetThreat = 0.f;
+ }
+
+ void EnterCombat(Unit* /*who*/) override
+ {
+ events.ScheduleEvent(EVENT_GUARD_WHIRLWIND, 30000);
+ events.ScheduleEvent(EVENT_GUARD_AGGRO_RESET, urand(45000, 55000));
+ events.ScheduleEvent(EVENT_GUARD_KNOCKBACK, 10000);
+ }
+
+ void SpellHit(Unit* /*caster*/, SpellInfo const* spell) override
+ {
+ if (spell->Id != SPELL_SUNDERING_CLEAVE)
+ return;
+
+ me->RemoveAura(SPELL_SUNDERING_CLEAVE);
+ }
+
+ void UpdateAI(uint32 diff) override
+ {
+ if (!UpdateVictim())
+ return;
+
+ events.Update(diff);
+
+ while (uint32 eventid = events.ExecuteEvent())
+ {
+ switch (eventid)
+ {
+ case EVENT_GUARD_WHIRLWIND:
+ DoCastSelf(SPELL_GUARD_WHIRLWIND);
+ whirlwind = true;
+ events.ScheduleEvent(EVENT_GUARD_WHIRLWIND_RANDOM, urand(3000, 7000));
+ events.ScheduleEvent(EVENT_GUARD_WHIRLWIND_END, 15000);
+ break;
+ case EVENT_GUARD_WHIRLWIND_RANDOM:
+ if (whirlwind == true)
+ {
+ if (Unit* target = SelectTarget(SelectTargetMethod::Random, 1, 100.0f, true))
+ {
+ me->AddThreat(target, 1.0f);
+ me->TauntApply(target);
+ AttackStart(target);
+ }
+ events.RepeatEvent(urand(3000, 7000));
+ }
+ break;
+ case EVENT_GUARD_WHIRLWIND_END:
+ events.CancelEvent(EVENT_GUARD_WHIRLWIND_RANDOM);
+ whirlwind = false;
+ events.ScheduleEvent(EVENT_GUARD_WHIRLWIND, urand(25000, 40000));
+ break;
+ case EVENT_GUARD_AGGRO_RESET:
+ if (aggroReset == true)
+ {
+ if (Unit* originalTarget = SelectTarget(SelectTargetMethod::Random, 0))
+ {
+ _savedTargetGUID = originalTarget->GetGUID();
+ _savedTargetThreat = me->GetThreatMgr().getThreat(originalTarget);
+ me->GetThreatMgr().modifyThreatPercent(originalTarget, -100);
+ }
+ aggroReset = true;
+ events.ScheduleEvent(EVENT_GUARD_AGGRO_RESET_END, 5000);
+ }
+ else
+ {
+ if (Unit* target = SelectTarget(SelectTargetMethod::Random, 1, 100.0f, true))
+ {
+ me->AddThreat(target, 1.0f);
+ me->TauntApply(target);
+ AttackStart(target);
+ }
+ }
+ events.RepeatEvent(urand(1000, 2000));
+ break;
+ case EVENT_GUARD_AGGRO_RESET_END:
+ events.CancelEvent(EVENT_GUARD_AGGRO_RESET);
+ if (Unit* originalTarget = ObjectAccessor::GetUnit(*me, _savedTargetGUID))
+ {
+ me->GetThreatMgr().addThreat(originalTarget, _savedTargetThreat);
+ _savedTargetGUID.Clear();
+ }
+ aggroReset = false;
+ events.RescheduleEvent(EVENT_GUARD_AGGRO_RESET, urand(30000, 40000));
+ break;
+ case EVENT_GUARD_KNOCKBACK:
+ DoCastVictim(SPELL_GUARD_KNOCKBACK);
+ events.RepeatEvent(urand(10000, 20000));
+ break;
+ }
+ }
+ DoMeleeAttackIfReady();
+ }
+ private:
+ bool whirlwind;
+ bool aggroReset;
+ ObjectGuid _savedTargetGUID;
+ float _savedTargetThreat;
};
void AddSC_boss_sartura()
{
- new boss_sartura();
- new npc_sartura_royal_guard();
+ RegisterTempleOfAhnQirajCreatureAI(boss_sartura);
+ RegisterTempleOfAhnQirajCreatureAI(npc_sartura_royal_guard);
}
diff --git a/src/server/scripts/Kalimdor/TempleOfAhnQiraj/temple_of_ahnqiraj.h b/src/server/scripts/Kalimdor/TempleOfAhnQiraj/temple_of_ahnqiraj.h
index bd8f239eb..63727f51b 100644
--- a/src/server/scripts/Kalimdor/TempleOfAhnQiraj/temple_of_ahnqiraj.h
+++ b/src/server/scripts/Kalimdor/TempleOfAhnQiraj/temple_of_ahnqiraj.h
@@ -56,7 +56,7 @@ enum Creatures
NPC_GIANT_EYE_TENTACLE = 15334,
NPC_FLESH_TENTACLE = 15802,
NPC_GIANT_PORTAL = 15910,
-
+ NPC_SARTURA_ROYAL_GUARD = 15984,
NPC_VISCIDUS = 15299,
NPC_GLOB_OF_VISCIDUS = 15667,