diff options
author | offl <11556157+offl@users.noreply.github.com> | 2022-01-22 19:01:37 +0200 |
---|---|---|
committer | GitHub <noreply@github.com> | 2022-01-22 19:01:37 +0200 |
commit | 41da43d9f240ecd9976a440824507d73891eeeec (patch) | |
tree | 76dc1746cb238902622df6320c2ef1a56e172f10 /src | |
parent | 6811fe63bfe34ee628fbd7a56b38d92a8f9940e7 (diff) |
Scripts/Botanica: Rework Sarannis & Freywinn (#27611)
Diffstat (limited to 'src')
-rw-r--r-- | src/server/scripts/Outland/TempestKeep/botanica/boss_commander_sarannis.cpp | 283 | ||||
-rw-r--r-- | src/server/scripts/Outland/TempestKeep/botanica/boss_high_botanist_freywinn.cpp | 257 |
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); } |