aboutsummaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
Diffstat (limited to 'src')
-rw-r--r--src/server/scripts/Outland/TempestKeep/botanica/boss_commander_sarannis.cpp283
-rw-r--r--src/server/scripts/Outland/TempestKeep/botanica/boss_high_botanist_freywinn.cpp257
2 files changed, 238 insertions, 302 deletions
diff --git a/src/server/scripts/Outland/TempestKeep/botanica/boss_commander_sarannis.cpp b/src/server/scripts/Outland/TempestKeep/botanica/boss_commander_sarannis.cpp
index fe845de505d..ffccab6b686 100644
--- a/src/server/scripts/Outland/TempestKeep/botanica/boss_commander_sarannis.cpp
+++ b/src/server/scripts/Outland/TempestKeep/botanica/boss_commander_sarannis.cpp
@@ -16,184 +16,189 @@
*/
#include "ScriptMgr.h"
-#include "Map.h"
#include "ScriptedCreature.h"
+#include "Spell.h"
+#include "SpellInfo.h"
#include "SpellScript.h"
#include "the_botanica.h"
-enum Says
+enum Texts
{
- SAY_AGGRO = 0,
- SAY_KILL = 1,
- SAY_ARCANE_RESONANCE = 2,
- SAY_ARCANE_DEVASTATION = 3,
- EMOTE_SUMMON = 4,
- SAY_SUMMON = 5,
- SAY_DEATH = 6
+ SAY_AGGRO = 0,
+ SAY_SLAY = 1,
+ SAY_ARCANE_DEVASTATION = 2,
+ EMOTE_SUMMON = 3,
+ SAY_SUMMON = 4,
+ SAY_DEATH = 5
};
enum Spells
{
- SPELL_ARCANE_RESONANCE = 34794,
- SPELL_ARCANE_DEVASTATION = 34799,
- SPELL_SUMMON_REINFORCEMENTS = 34803
+ SPELL_ARCANE_RESONANCE = 34794,
+ SPELL_ARCANE_DEVASTATION = 34799,
+
+ SPELL_SUMMON_REINFORCEMENTS = 34803,
+ SPELL_SUMMON_MENDER_1 = 34810,
+ SPELL_SUMMON_RESERVIST_1 = 34817,
+ SPELL_SUMMON_RESERVIST_2 = 34818,
+ SPELL_SUMMON_RESERVIST_3 = 34819
};
enum Events
{
- EVENT_ARCANE_RESONANCE = 1,
- EVENT_ARCANE_DEVASTATION = 2
+ EVENT_ARCANE_DEVASTATION = 1,
+ EVENT_SUMMON_REINFORCEMENTS
};
-class boss_commander_sarannis : public CreatureScript
+uint32 const SummonReinforcementsSpells[] =
{
- public: boss_commander_sarannis() : CreatureScript("boss_commander_sarannis") { }
+ SPELL_SUMMON_MENDER_1, SPELL_SUMMON_RESERVIST_1, SPELL_SUMMON_RESERVIST_2, SPELL_SUMMON_RESERVIST_3
+};
- struct boss_commander_sarannisAI : public BossAI
+struct boss_commander_sarannis : public BossAI
+{
+ boss_commander_sarannis(Creature* creature) : BossAI(creature, DATA_COMMANDER_SARANNIS), _summoned(false) { }
+
+ void Reset() override
+ {
+ _Reset();
+ _summoned = false;
+ }
+
+ void JustEngagedWith(Unit* who) override
+ {
+ BossAI::JustEngagedWith(who);
+ Talk(SAY_AGGRO);
+
+ // This is definitely just timed, not scheduled instantly when victim has specific amount of stacks of Arcane Resonance
+ events.ScheduleEvent(EVENT_ARCANE_DEVASTATION, RAND(10s, 15s, 20s, 25s, 30s, 35s));
+ // Timed in heroic (repeatable), on HP PTC in normal (not repeatable)
+ if (IsHeroic())
+ events.ScheduleEvent(EVENT_SUMMON_REINFORCEMENTS, 1min);
+ }
+
+ void KilledUnit(Unit* /*victim*/) override
+ {
+ Talk(SAY_SLAY);
+ }
+
+ void JustDied(Unit* /*killer*/) override
+ {
+ _JustDied();
+ Talk(SAY_DEATH);
+ }
+
+ void DamageTaken(Unit* /*killer*/, uint32& damage, DamageEffectType /*damageType*/, SpellInfo const* /*spellInfo = nullptr*/) override
+ {
+ if (!_summoned && me->HealthBelowPctDamaged(55, damage) && !IsHeroic())
{
- boss_commander_sarannisAI(Creature* creature) : BossAI(creature, DATA_COMMANDER_SARANNIS)
- {
- Initialize();
- }
+ _summoned = true;
+ events.ScheduleEvent(EVENT_SUMMON_REINFORCEMENTS, 0s);
+ }
+ }
- void Initialize()
- {
- _phase = true;
- }
+ void OnSpellCastFinished(SpellInfo const* spell, SpellFinishReason reason) override
+ {
+ if (reason == SPELL_FINISHED_SUCCESSFUL_CAST && spell->Id == SPELL_SUMMON_REINFORCEMENTS)
+ Talk(SAY_SUMMON);
+ }
- void Reset() override
- {
- _Reset();
- Initialize();
- }
+ // Do not despawn them
+ void JustSummoned(Creature* summon) override
+ {
+ if (me->IsEngaged())
+ DoZoneInCombat(summon);
+ }
- void JustEngagedWith(Unit* who) override
- {
- BossAI::JustEngagedWith(who);
- Talk(SAY_AGGRO);
- events.ScheduleEvent(EVENT_ARCANE_RESONANCE, 42700ms);
- events.ScheduleEvent(EVENT_ARCANE_DEVASTATION, 15200ms);
- }
+ void UpdateAI(uint32 diff) override
+ {
+ if (!UpdateVictim())
+ return;
- void KilledUnit(Unit* /*victim*/) override
- {
- Talk(SAY_KILL);
- }
+ events.Update(diff);
- void JustDied(Unit* /*killer*/) override
- {
- _JustDied();
- Talk(SAY_DEATH);
- }
+ if (me->HasUnitState(UNIT_STATE_CASTING))
+ return;
- void DamageTaken(Unit* /*killer*/, uint32& damage, DamageEffectType /*damageType*/, SpellInfo const* /*spellInfo = nullptr*/) override
+ while (uint32 eventId = events.ExecuteEvent())
+ {
+ switch (eventId)
{
- if (me->HealthBelowPctDamaged(50, damage) && _phase)
- {
- _phase = false;
+ case EVENT_ARCANE_DEVASTATION:
+ // Not always?
+ Talk(SAY_ARCANE_DEVASTATION);
+ // She can cast it if victim has only one stack of Arcane Resonance but can she cast it if victim has no stacks?
+ DoCastVictim(SPELL_ARCANE_DEVASTATION);
+ events.Repeat(RAND(10s, 15s, 20s, 25s, 30s, 35s));
+ break;
+ case EVENT_SUMMON_REINFORCEMENTS:
Talk(EMOTE_SUMMON);
- Talk(SAY_SUMMON);
- DoCast(me, SPELL_SUMMON_REINFORCEMENTS);
- }
- }
-
- void JustSummoned(Creature* summon) override
- {
- BossAI::JustSummoned(summon);
+ DoCastSelf(SPELL_SUMMON_REINFORCEMENTS);
+ if (IsHeroic())
+ events.Repeat(1min);
+ 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_ARCANE_RESONANCE:
- Talk(SAY_ARCANE_RESONANCE);
- DoCastVictim(SPELL_ARCANE_RESONANCE, true);
- events.ScheduleEvent(EVENT_ARCANE_RESONANCE, 42700ms);
- break;
- case EVENT_ARCANE_DEVASTATION:
- Talk(SAY_ARCANE_DEVASTATION);
- DoCastVictim(SPELL_ARCANE_DEVASTATION, true);
- events.ScheduleEvent(EVENT_ARCANE_DEVASTATION, 11s, 19200ms);
- break;
- default:
- break;
- }
-
- if (me->HasUnitState(UNIT_STATE_CASTING))
- return;
- }
-
- DoMeleeAttackIfReady();
- }
-
- private:
- bool _phase;
- };
-
- CreatureAI* GetAI(Creature* creature) const override
- {
- return GetBotanicaAI<boss_commander_sarannisAI>(creature);
+ if (me->HasUnitState(UNIT_STATE_CASTING))
+ return;
}
-};
-Position const PosSummonReinforcements[4] =
-{
- { 160.4483f, 287.6435f, -3.887904f, 2.3841f },
- { 153.4406f, 289.9929f, -4.736916f, 2.3841f },
- { 154.4137f, 292.8956f, -4.683603f, 2.3841f },
- { 157.1544f, 294.2599f, -4.726504f, 2.3841f }
+ DoMeleeAttackIfReady();
+ }
+
+private:
+ bool _summoned;
};
-enum Creatures
+// 34799 - Arcane Devastation
+class spell_commander_sarannis_arcane_devastation : public AuraScript
{
- NPC_SUMMONED_BLOODWARDER_MENDER = 20083,
- NPC_SUMMONED_BLOODWARDER_RESERVIST = 20078
+ PrepareAuraScript(spell_commander_sarannis_arcane_devastation);
+
+ bool Validate(SpellInfo const* /*spell*/) override
+ {
+ return ValidateSpellInfo({ SPELL_ARCANE_RESONANCE });
+ }
+
+ void AfterApply(AuraEffect const* /*aurEff*/, AuraEffectHandleModes /*mode*/)
+ {
+ GetTarget()->RemoveAurasDueToSpell(SPELL_ARCANE_RESONANCE);
+ }
+
+ void Register() override
+ {
+ AfterEffectApply += AuraEffectApplyFn(spell_commander_sarannis_arcane_devastation::AfterApply, EFFECT_2, SPELL_AURA_DUMMY, AURA_EFFECT_HANDLE_REAL);
+ }
};
// 34803 - Summon Reinforcements
-class spell_commander_sarannis_summon_reinforcements : public SpellScriptLoader
+class spell_commander_sarannis_summon_reinforcements : public SpellScript
{
- public:
- spell_commander_sarannis_summon_reinforcements() : SpellScriptLoader("spell_commander_sarannis_summon_reinforcements") { }
-
- class spell_commander_sarannis_summon_reinforcements_SpellScript : public SpellScript
- {
- PrepareSpellScript(spell_commander_sarannis_summon_reinforcements_SpellScript);
-
- void HandleCast(SpellEffIndex /*effIndex*/)
- {
- GetCaster()->SummonCreature(NPC_SUMMONED_BLOODWARDER_MENDER, PosSummonReinforcements[0], TEMPSUMMON_CORPSE_DESPAWN);
- GetCaster()->SummonCreature(NPC_SUMMONED_BLOODWARDER_RESERVIST, PosSummonReinforcements[1], TEMPSUMMON_CORPSE_DESPAWN);
- GetCaster()->SummonCreature(NPC_SUMMONED_BLOODWARDER_RESERVIST, PosSummonReinforcements[2], TEMPSUMMON_CORPSE_DESPAWN);
- if (GetCaster()->GetMap()->IsHeroic())
- GetCaster()->SummonCreature(NPC_SUMMONED_BLOODWARDER_RESERVIST, PosSummonReinforcements[3], TEMPSUMMON_CORPSE_DESPAWN);
- }
-
- void Register() override
- {
- OnEffectHitTarget += SpellEffectFn(spell_commander_sarannis_summon_reinforcements_SpellScript::HandleCast, EFFECT_0, SPELL_EFFECT_DUMMY);
- }
- };
-
- SpellScript* GetSpellScript() const override
- {
- return new spell_commander_sarannis_summon_reinforcements_SpellScript();
- }
+ PrepareSpellScript(spell_commander_sarannis_summon_reinforcements);
+
+ bool Validate(SpellInfo const* /*spellInfo*/) override
+ {
+ return ValidateSpellInfo(SummonReinforcementsSpells);
+ }
+
+ void HandleDummy(SpellEffIndex /*effIndex*/)
+ {
+ Unit* caster = GetCaster();
+ for (uint32 spells : SummonReinforcementsSpells)
+ caster->CastSpell(caster, spells, true);
+ }
+
+ void Register() override
+ {
+ OnEffectHit += SpellEffectFn(spell_commander_sarannis_summon_reinforcements::HandleDummy, EFFECT_0, SPELL_EFFECT_DUMMY);
+ }
};
void AddSC_boss_commander_sarannis()
{
- new boss_commander_sarannis();
- new spell_commander_sarannis_summon_reinforcements();
+ RegisterBotanicaCreatureAI(boss_commander_sarannis);
+ RegisterSpellScript(spell_commander_sarannis_arcane_devastation);
+ RegisterSpellScript(spell_commander_sarannis_summon_reinforcements);
}
diff --git a/src/server/scripts/Outland/TempestKeep/botanica/boss_high_botanist_freywinn.cpp b/src/server/scripts/Outland/TempestKeep/botanica/boss_high_botanist_freywinn.cpp
index 88c1cdbc2f5..aedc8509b6e 100644
--- a/src/server/scripts/Outland/TempestKeep/botanica/boss_high_botanist_freywinn.cpp
+++ b/src/server/scripts/Outland/TempestKeep/botanica/boss_high_botanist_freywinn.cpp
@@ -15,27 +15,18 @@
* with this program. If not, see <http://www.gnu.org/licenses/>.
*/
-/* ScriptData
-SDName: Boss_High_Botanist_Freywinn
-SD%Complete: 90
-SDComment: some strange visual related to tree form(if aura lost before normal duration end). possible make summon&transform -process smoother(transform after delay)
-SDCategory: Tempest Keep, The Botanica
-EndScriptData */
-
#include "ScriptMgr.h"
-#include "MotionMaster.h"
-#include "ObjectAccessor.h"
#include "ScriptedCreature.h"
+#include "SpellInfo.h"
#include "the_botanica.h"
-enum Says
+enum Texts
{
SAY_AGGRO = 0,
- SAY_KILL = 1,
+ SAY_SLAY = 1,
SAY_TREE = 2,
- SAY_SUMMON = 3,
- SAY_DEATH = 4,
- SAY_OOC_RANDOM = 5
+ SAY_DEATH = 3,
+ SAY_OOC_RANDOM = 4
};
enum Spells
@@ -46,176 +37,116 @@ enum Spells
SPELL_PLANT_WHITE = 34759,
SPELL_PLANT_GREEN = 34761,
SPELL_PLANT_BLUE = 34762,
- SPELL_PLANT_RED = 34763
+ SPELL_PLANT_RED = 34763,
+ SPELL_CANCEL_TRANQUILITY = 34777
};
-enum Creatures
+enum Events
{
- NPC_FRAYER = 19953
+ EVENT_PLANT_SEEDLING = 1,
+ EVENT_TREE_FORM,
+ EVENT_TRANQUILITY
};
-class boss_high_botanist_freywinn : public CreatureScript
+struct boss_high_botanist_freywinn : public BossAI
{
- public:
-
- boss_high_botanist_freywinn()
- : CreatureScript("boss_high_botanist_freywinn")
- {
- }
-
- struct boss_high_botanist_freywinnAI : public BossAI
+ boss_high_botanist_freywinn(Creature* creature) : BossAI(creature, DATA_HIGH_BOTANIST_FREYWINN), _frayersKilled(0) { }
+
+ void Reset() override
+ {
+ _Reset();
+ _frayersKilled = 0;
+ }
+
+ void JustEngagedWith(Unit* who) override
+ {
+ BossAI::JustEngagedWith(who);
+ Talk(SAY_AGGRO);
+ events.ScheduleEvent(EVENT_PLANT_SEEDLING, 6s);
+ events.ScheduleEvent(EVENT_TREE_FORM, 30s);
+ }
+
+ void KilledUnit(Unit* /*victim*/) override
+ {
+ Talk(SAY_SLAY);
+ }
+
+ void JustDied(Unit* /*killer*/) override
+ {
+ _JustDied();
+ Talk(SAY_DEATH);
+ }
+
+ // Do not despawn them
+ void JustSummoned(Creature* summon) override
+ {
+ if (me->IsEngaged())
+ DoZoneInCombat(summon);
+ }
+
+ void SpellHit(WorldObject* /*caster*/, SpellInfo const* spellInfo) override
+ {
+ // Completely guessed, may be actually not used
+ if (spellInfo->Id == SPELL_CANCEL_TRANQUILITY)
{
- boss_high_botanist_freywinnAI(Creature* creature) : BossAI(creature, DATA_HIGH_BOTANIST_FREYWINN)
- {
- Initialize();
- }
-
- void Initialize()
- {
- SummonSeedling_Timer = 6000;
- TreeForm_Timer = 30000;
- MoveCheck_Timer = 1000;
- DeadAddsCount = 0;
- MoveFree = true;
- }
-
- uint32 SummonSeedling_Timer;
- uint32 TreeForm_Timer;
- uint32 MoveCheck_Timer;
- uint32 DeadAddsCount;
- bool MoveFree;
-
- void Reset() override
- {
- summons.DespawnAll();
-
- Initialize();
- }
-
- void JustEngagedWith(Unit* /*who*/) override
- {
- Talk(SAY_AGGRO);
- }
+ ++_frayersKilled;
- void JustSummoned(Creature* summoned) override
+ if (_frayersKilled >= 3)
{
- if (summoned->GetEntry() == NPC_FRAYER)
- summons.Summon(summoned);
+ _frayersKilled = 0;
+ me->InterruptSpell(CURRENT_CHANNELED_SPELL);
+ me->RemoveAurasDueToSpell(SPELL_TREE_FORM);
}
+ }
+ }
- void SummonedCreatureDespawn(Creature* summon) override
- {
- summons.Despawn(summon);
- }
+ void UpdateAI(uint32 diff) override
+ {
+ if (!UpdateVictim())
+ return;
- void DoSummonSeedling()
- {
- switch (rand32() % 4)
- {
- case 0: DoCast(me, SPELL_PLANT_WHITE); break;
- case 1: DoCast(me, SPELL_PLANT_GREEN); break;
- case 2: DoCast(me, SPELL_PLANT_BLUE); break;
- case 3: DoCast(me, SPELL_PLANT_RED); break;
- }
- }
+ events.Update(diff);
- void KilledUnit(Unit* /*victim*/) override
- {
- Talk(SAY_KILL);
- }
+ if (me->HasUnitState(UNIT_STATE_CASTING))
+ return;
- void JustDied(Unit* /*killer*/) override
- {
- Talk(SAY_DEATH);
- }
-
- void UpdateAI(uint32 diff) override
+ while (uint32 eventId = events.ExecuteEvent())
+ {
+ switch (eventId)
{
- if (!UpdateVictim())
- return;
-
- if (TreeForm_Timer <= diff)
- {
+ case EVENT_PLANT_SEEDLING:
+ DoCastSelf(RAND(SPELL_PLANT_WHITE, SPELL_PLANT_GREEN, SPELL_PLANT_BLUE, SPELL_PLANT_RED));
+ events.Repeat(6s);
+ break;
+ case EVENT_TREE_FORM:
+ // Reset counter in case not all frayers were killed and tree phase was ended, otherwise next time it will be enough to
+ // kill only 1 or 2 to stop phase. It's an edge case, quite possible it was not even supported
+ _frayersKilled = 0;
Talk(SAY_TREE);
-
- if (me->IsNonMeleeSpellCast(false))
- me->InterruptNonMeleeSpells(true);
-
- me->RemoveAllAuras();
-
- DoCast(me, SPELL_SUMMON_FRAYER, true);
- DoCast(me, SPELL_TRANQUILITY, true);
- DoCast(me, SPELL_TREE_FORM, true);
-
- me->GetMotionMaster()->MoveIdle();
- MoveFree = false;
-
- TreeForm_Timer = 75000;
- }
- else
- TreeForm_Timer -= diff;
-
- if (!MoveFree)
- {
- if (MoveCheck_Timer <= diff)
- {
- for (SummonList::iterator itr = summons.begin(); itr != summons.end(); ++itr)
- {
- if (Unit* temp = ObjectAccessor::GetUnit(*me, *itr))
- {
- if (!temp->IsAlive())
- {
- summons.erase(itr);
- ++DeadAddsCount;
- break;
- }
- }
- }
-
- if (DeadAddsCount < 3 && TreeForm_Timer-30000 <= diff)
- DeadAddsCount = 3;
-
- if (DeadAddsCount >= 3)
- {
- summons.DespawnAll();
- DeadAddsCount = 0;
-
- me->InterruptNonMeleeSpells(true);
- me->RemoveAllAuras();
- me->GetMotionMaster()->MoveChase(me->GetVictim());
- MoveFree = true;
- }
- MoveCheck_Timer = 500;
- }
- else
- MoveCheck_Timer -= diff;
-
- return;
- }
-
- /*if (me->HasAura(SPELL_TREE_FORM, 0) || me->HasAura(SPELL_TRANQUILITY, 0))
- return;*/
-
- //one random seedling every 5 secs, but not in tree form
- if (SummonSeedling_Timer <= diff)
- {
- DoSummonSeedling();
- SummonSeedling_Timer = 6000;
- }
- else
- SummonSeedling_Timer -= diff;
-
- DoMeleeAttackIfReady();
+ DoCastSelf(SPELL_SUMMON_FRAYER);
+ DoCastSelf(SPELL_TREE_FORM);
+ events.Repeat(60s);
+ events.ScheduleEvent(EVENT_TRANQUILITY, 1s);
+ break;
+ case EVENT_TRANQUILITY:
+ DoCastSelf(SPELL_TRANQUILITY);
+ break;
+ default:
+ break;
}
- };
- CreatureAI* GetAI(Creature* creature) const override
- {
- return GetBotanicaAI<boss_high_botanist_freywinnAI>(creature);
+ if (me->HasUnitState(UNIT_STATE_CASTING))
+ return;
}
+
+ DoMeleeAttackIfReady();
+ }
+
+private:
+ uint8 _frayersKilled;
};
void AddSC_boss_high_botanist_freywinn()
{
- new boss_high_botanist_freywinn();
+ RegisterBotanicaCreatureAI(boss_high_botanist_freywinn);
}