aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--sql/updates/world/3.3.5/2025_08_10_00_world.sql9
-rw-r--r--src/server/scripts/Kalimdor/TempleOfAhnQiraj/boss_sartura.cpp412
-rw-r--r--src/server/scripts/Kalimdor/TempleOfAhnQiraj/temple_of_ahnqiraj.h2
3 files changed, 180 insertions, 243 deletions
diff --git a/sql/updates/world/3.3.5/2025_08_10_00_world.sql b/sql/updates/world/3.3.5/2025_08_10_00_world.sql
new file mode 100644
index 00000000000..2c8d752352f
--- /dev/null
+++ b/sql/updates/world/3.3.5/2025_08_10_00_world.sql
@@ -0,0 +1,9 @@
+--
+DELETE FROM `spell_script_names` WHERE `ScriptName` = 'spell_sartura_whirlwind';
+INSERT INTO `spell_script_names` (`spell_id`, `ScriptName`) VALUES
+(26084, 'spell_sartura_whirlwind'),
+(26686, 'spell_sartura_whirlwind');
+
+DELETE FROM `creature_text` WHERE `CreatureID` = 15516 AND `GroupID` = 3;
+INSERT INTO `creature_text` (`CreatureID`, `GroupID`, `ID`, `Text`, `Type`, `Language`, `Probability`, `Emote`, `Duration`, `Sound`, `BroadcastTextId`, `TextRange`, `comment`) VALUES
+(15516,3,0,"%s goes into a frenzy!",16,0,100,0,0,0,2384,0,"sartura EMOTE_FRENZY");
diff --git a/src/server/scripts/Kalimdor/TempleOfAhnQiraj/boss_sartura.cpp b/src/server/scripts/Kalimdor/TempleOfAhnQiraj/boss_sartura.cpp
index d11116f2441..b95c5652fb2 100644
--- a/src/server/scripts/Kalimdor/TempleOfAhnQiraj/boss_sartura.cpp
+++ b/src/server/scripts/Kalimdor/TempleOfAhnQiraj/boss_sartura.cpp
@@ -15,304 +15,229 @@
* with this program. If not, see <http://www.gnu.org/licenses/>.
*/
-/* ScriptData
-SDName: Boss_Sartura
-SD%Complete: 95
-SDComment:
-SDCategory: Temple of Ahn'Qiraj
-EndScriptData */
-
#include "ScriptMgr.h"
#include "InstanceScript.h"
#include "ScriptedCreature.h"
+#include "SpellAuraEffects.h"
+#include "SpellScript.h"
#include "temple_of_ahnqiraj.h"
#include "Player.h"
-enum Sartura
+enum SarturaTexts
{
- SAY_AGGRO = 0,
- SAY_SLAY = 1,
- SAY_DEATH = 2,
+ SAY_AGGRO = 0,
+ SAY_SLAY = 1,
+ SAY_DEATH = 2,
+ EMOTE_FRENZY = 3
+};
- SPELL_WHIRLWIND = 26083,
- SPELL_ENRAGE = 28747, //Not sure if right ID.
- SPELL_ENRAGEHARD = 28798,
+enum SarturaSpells
+{
+ // Sartura
+ SPELL_SUNDERING_CLEAVE = 25174,
+ SPELL_WHIRLWIND = 26083,
+ SPELL_FRENZY = 8269,
+ SPELL_BERSERK = 27680,
+
+ // Guard
+ SPELL_KNOCKBACK = 26027,
+ SPELL_WHIRLWIND_GUARD = 26038
+};
- //Guard Spell
- SPELL_WHIRLWINDADD = 26038,
- SPELL_KNOCKBACK = 26027
+enum SarturaEvents
+{
+ // Sartura
+ EVENT_SUNDERING_CLEAVE = 1,
+ EVENT_WHIRLWIND,
+ EVENT_FRENZY,
+ EVENT_BERSERK,
+
+ // Guard
+ EVENT_KNOCKBACK,
+ EVENT_WHIRLWIND_GUARD
};
-class boss_sartura : public CreatureScript
+// 15516 - Battleguard Sartura
+struct boss_sartura : public BossAI
{
-public:
- boss_sartura() : CreatureScript("boss_sartura") { }
+ boss_sartura(Creature* creature) : BossAI(creature, DATA_SARTURA), _frenzied(false) { }
- CreatureAI* GetAI(Creature* creature) const override
+ void Reset() override
{
- return GetAQ40AI<boss_sarturaAI>(creature);
+ _Reset();
+ _frenzied = false;
}
- struct boss_sarturaAI : public BossAI
+ void JustEngagedWith(Unit* who) override
{
- boss_sarturaAI(Creature* creature) : BossAI(creature, DATA_SARTURA)
- {
- Initialize();
- }
+ Talk(SAY_AGGRO);
+ BossAI::JustEngagedWith(who);
- void Initialize()
+ events.ScheduleEvent(EVENT_SUNDERING_CLEAVE, 2s, 5s);
+ events.ScheduleEvent(EVENT_WHIRLWIND, 10s, 20s);
+ events.ScheduleEvent(EVENT_BERSERK, 10min);
+ }
+
+ void DamageTaken(Unit* /*attacker*/, uint32& damage, DamageEffectType /*damageType*/, SpellInfo const* /*spellInfo = nullptr*/) override
+ {
+ if (!_frenzied && me->HealthBelowPctDamaged(25, damage))
{
- 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;
+ _frenzied = true;
+ events.ScheduleEvent(EVENT_FRENZY, 0s);
}
+ }
- uint32 WhirlWind_Timer;
- uint32 WhirlWindRandom_Timer;
- uint32 WhirlWindEnd_Timer;
- uint32 AggroReset_Timer;
- uint32 AggroResetEnd_Timer;
- uint32 EnrageHard_Timer;
+ void OnSpellCast(SpellInfo const* spell) override
+ {
+ if (spell->Id == SPELL_FRENZY)
+ Talk(EMOTE_FRENZY);
+ }
- bool Enraged;
- bool EnragedHard;
- bool WhirlWind;
- bool AggroReset;
+ void KilledUnit(Unit* /*victim*/) override
+ {
+ Talk(SAY_SLAY);
+ }
- void Reset() override
- {
- Initialize();
- _Reset();
- }
+ void JustDied(Unit* /*killer*/) override
+ {
+ Talk(SAY_DEATH);
+ _JustDied();
+ }
- void JustEngagedWith(Unit* who) override
- {
- Talk(SAY_AGGRO);
- BossAI::JustEngagedWith(who);
- }
+ void UpdateAI(uint32 diff) override
+ {
+ if (!UpdateVictim())
+ return;
- void JustDied(Unit* /*killer*/) override
- {
- Talk(SAY_DEATH);
- _JustDied();
- }
+ events.Update(diff);
- void KilledUnit(Unit* /*victim*/) override
- {
- Talk(SAY_SLAY);
- }
+ if (me->HasUnitState(UNIT_STATE_CASTING))
+ return;
- void UpdateAI(uint32 diff) override
+ while (uint32 eventId = events.ExecuteEvent())
{
- //Return since we have no target
- if (!UpdateVictim())
- return;
-
- if (WhirlWind)
+ switch (eventId)
{
- if (WhirlWindRandom_Timer <= diff)
- {
- //Attack random Gamers
- if (Unit* target = SelectTarget(SelectTargetMethod::Random, 1, 100.0f, true))
- {
- AddThreat(target, 1.0f);
- 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;
+ case EVENT_SUNDERING_CLEAVE:
+ DoCastVictim(SPELL_SUNDERING_CLEAVE);
+ events.Repeat(2s, 5s);
+ break;
+ case EVENT_WHIRLWIND:
+ DoCastSelf(SPELL_WHIRLWIND);
+ events.Repeat(20s, 25s);
+ break;
+ case EVENT_FRENZY:
+ DoCastSelf(SPELL_FRENZY);
+ break;
+ case EVENT_BERSERK:
+ DoCastSelf(SPELL_BERSERK);
+ break;
+ default:
+ break;
}
- 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))
- {
- AddThreat(target, 1.0f);
- 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);
- Enraged = true;
- }
- }
-
- //After 10 minutes hard enrage
- if (!EnragedHard)
- {
- if (EnrageHard_Timer <= diff)
- {
- DoCast(me, SPELL_ENRAGEHARD);
- EnragedHard = true;
- } else EnrageHard_Timer -= diff;
- }
-
- DoMeleeAttackIfReady();
- }
+ if (me->HasUnitState(UNIT_STATE_CASTING))
+ return;
}
- };
+ DoMeleeAttackIfReady();
+ }
+
+private:
+ bool _frenzied;
};
-class npc_sartura_royal_guard : public CreatureScript
+// 15984 - Sartura's Royal Guard
+struct npc_sartura_royal_guard : public ScriptedAI
{
-public:
- npc_sartura_royal_guard() : CreatureScript("npc_sartura_royal_guard") { }
+ npc_sartura_royal_guard(Creature* creature) : ScriptedAI(creature) { }
- CreatureAI* GetAI(Creature* creature) const override
+ void Reset() override
{
- return GetAQ40AI<npc_sartura_royal_guardAI>(creature);
+ _events.Reset();
}
- struct npc_sartura_royal_guardAI : public ScriptedAI
+ void JustEngagedWith(Unit* /*who*/) override
{
- npc_sartura_royal_guardAI(Creature* creature) : ScriptedAI(creature)
- {
- Initialize();
- }
+ _events.ScheduleEvent(EVENT_KNOCKBACK, 5s, 10s);
+ _events.ScheduleEvent(EVENT_WHIRLWIND_GUARD, 10s, 15s);
+ }
- void Initialize()
- {
- 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;
- }
+ void UpdateAI(uint32 diff) override
+ {
+ if (!UpdateVictim())
+ return;
- uint32 WhirlWind_Timer;
- uint32 WhirlWindRandom_Timer;
- uint32 WhirlWindEnd_Timer;
- uint32 AggroReset_Timer;
- uint32 AggroResetEnd_Timer;
- uint32 KnockBack_Timer;
+ _events.Update(diff);
- bool WhirlWind;
- bool AggroReset;
+ if (me->HasUnitState(UNIT_STATE_CASTING))
+ return;
- void Reset() override
+ while (uint32 eventId = _events.ExecuteEvent())
{
- Initialize();
- }
+ switch (eventId)
+ {
+ case EVENT_KNOCKBACK:
+ DoCastSelf(SPELL_KNOCKBACK);
+ _events.Repeat(20s, 30s);
+ break;
+ case EVENT_WHIRLWIND_GUARD:
+ DoCastSelf(SPELL_WHIRLWIND_GUARD);
+ _events.Repeat(10s, 20s);
+ break;
+ default:
+ break;
+ }
- void JustEngagedWith(Unit* /*who*/) override
- {
+ if (me->HasUnitState(UNIT_STATE_CASTING))
+ return;
}
- void UpdateAI(uint32 diff) override
- {
- //Return since we have no target
- if (!UpdateVictim())
- return;
+ DoMeleeAttackIfReady();
+ }
- if (!WhirlWind && WhirlWind_Timer <= diff)
- {
- DoCast(me, SPELL_WHIRLWINDADD);
- WhirlWind = true;
- WhirlWind_Timer = urand(25000, 40000);
- WhirlWindEnd_Timer = 15000;
- } else WhirlWind_Timer -= diff;
+private:
+ EventMap _events;
+};
- if (WhirlWind)
- {
- if (WhirlWindRandom_Timer <= diff)
- {
- //Attack random Gamers
- if (Unit* target = SelectTarget(SelectTargetMethod::Random, 1, 100.0f, true))
- {
- AddThreat(target, 1.0f);
- AttackStart(target);
- }
-
- WhirlWindRandom_Timer = urand(3000, 7000);
- } else WhirlWindRandom_Timer -= diff;
-
- if (WhirlWindEnd_Timer <= diff)
- {
- WhirlWind = false;
- } else WhirlWindEnd_Timer -= diff;
- }
+// 26084 - Whirlwind
+// 26686 - Whirlwind
+class spell_sartura_whirlwind : public SpellScript
+{
+ PrepareSpellScript(spell_sartura_whirlwind);
- if (!WhirlWind)
- {
- if (AggroReset_Timer <= diff)
- {
- //Attack random Gamers
- if (Unit* target = SelectTarget(SelectTargetMethod::Random, 1, 100.0f, true))
- {
- AddThreat(target, 1.0f);
- AttackStart(target);
- }
-
- 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;
- }
+ void HandleScript(SpellEffIndex /*effIndex*/)
+ {
+ Creature* caster = GetCaster()->ToCreature();
+ if (!caster)
+ return;
+
+ SpellInfo const* spellInfo = GetTriggeringSpell();
+ if (!spellInfo)
+ return;
- if (AggroReset)
+ if (AuraEffect const* eff = caster->GetAuraEffect(spellInfo->Id, EFFECT_0))
+ {
+ if (eff->GetTickNumber() != spellInfo->GetMaxTicks())
{
- if (AggroResetEnd_Timer <= diff)
- {
- AggroReset = false;
- AggroResetEnd_Timer = 5000;
- AggroReset_Timer = urand(30000, 40000);
- } else AggroResetEnd_Timer -= diff;
+ if (spellInfo->Id == SPELL_WHIRLWIND_GUARD)
+ if (urand(0, 2))
+ return;
+
+ // This requires additional research
+ caster->GetThreatManager().ResetAllThreat();
+ if (Unit* target = caster->AI()->SelectTarget(SelectTargetMethod::Random, 0, 0.0f, true))
+ caster->GetThreatManager().AddThreat(target, 100000.0f);
}
-
- DoMeleeAttackIfReady();
+ else
+ caster->GetThreatManager().ResetAllThreat();
}
- };
+ }
+ void Register() override
+ {
+ OnEffectHit += SpellEffectFn(spell_sartura_whirlwind::HandleScript, EFFECT_1, SPELL_EFFECT_SCRIPT_EFFECT);
+ }
};
// 4052
@@ -333,7 +258,8 @@ public:
void AddSC_boss_sartura()
{
- new boss_sartura();
- new npc_sartura_royal_guard();
+ RegisterAQ40CreatureAI(boss_sartura);
+ RegisterAQ40CreatureAI(npc_sartura_royal_guard);
+ RegisterSpellScript(spell_sartura_whirlwind);
new at_aq_battleguard_sartura();
}
diff --git a/src/server/scripts/Kalimdor/TempleOfAhnQiraj/temple_of_ahnqiraj.h b/src/server/scripts/Kalimdor/TempleOfAhnQiraj/temple_of_ahnqiraj.h
index 15bbd45cbaa..cc8dd0c9431 100644
--- a/src/server/scripts/Kalimdor/TempleOfAhnQiraj/temple_of_ahnqiraj.h
+++ b/src/server/scripts/Kalimdor/TempleOfAhnQiraj/temple_of_ahnqiraj.h
@@ -89,4 +89,6 @@ inline AI* GetAQ40AI(T* obj)
return GetInstanceAI<AI>(obj, AQ40ScriptName);
}
+#define RegisterAQ40CreatureAI(ai_name) RegisterCreatureAIWithFactory(ai_name, GetAQ40AI)
+
#endif