From 78327500d816d923ece63a940fb82bde16d8f8e9 Mon Sep 17 00:00:00 2001
From: offl <11556157+offl@users.noreply.github.com>
Date: Sat, 22 Jan 2022 19:02:07 +0200
Subject: Scripts/Botanica: Rework Warp Splinter (#27621)
---
.../TempestKeep/botanica/boss_warp_splinter.cpp | 310 ++++++++-------------
1 file changed, 120 insertions(+), 190 deletions(-)
(limited to 'src')
diff --git a/src/server/scripts/Outland/TempestKeep/botanica/boss_warp_splinter.cpp b/src/server/scripts/Outland/TempestKeep/botanica/boss_warp_splinter.cpp
index 277d7ef348e..c8c5dd4d2e8 100644
--- a/src/server/scripts/Outland/TempestKeep/botanica/boss_warp_splinter.cpp
+++ b/src/server/scripts/Outland/TempestKeep/botanica/boss_warp_splinter.cpp
@@ -15,235 +15,165 @@
* with this program. If not, see .
*/
-/* ScriptData
-SDName: Boss_Warp_Splinter
-SD%Complete: 80
-SDComment: Includes Sapling (need some better control with these).
-SDCategory: Tempest Keep, The Botanica
-EndScriptData */
-
#include "ScriptMgr.h"
-#include "MotionMaster.h"
-#include "ObjectAccessor.h"
#include "ScriptedCreature.h"
-#include "TemporarySummon.h"
+#include "Spell.h"
+#include "SpellInfo.h"
#include "the_botanica.h"
-enum Says
+enum Texts
{
- SAY_AGGRO = 0,
- SAY_SLAY = 1,
- SAY_SUMMON = 2,
- SAY_DEATH = 3
+ SAY_AGGRO = 0,
+ SAY_SLAY = 1,
+ SAY_SUMMON = 2,
+ SAY_DEATH = 3
};
enum Spells
{
- WAR_STOMP = 34716,
- SUMMON_TREANTS = 34727, // DBC: 34727, 34731, 34733, 34734, 34736, 34739, 34741 (with Ancestral Life spell 34742) // won't work (guardian summon)
- ARCANE_VOLLEY = 36705,
- SPELL_HEAL_FATHER = 6262
+ SPELL_STOMP = 34716,
+ SPELL_ARCANE_VOLLEY = 36705,
+
+ SPELL_SUMMON_SAPLING_1 = 34727,
+ SPELL_SUMMON_SAPLING_2 = 34731,
+ SPELL_SUMMON_SAPLING_3 = 34733,
+ SPELL_SUMMON_SAPLING_4 = 34734,
+ SPELL_SUMMON_SAPLING_5 = 34736,
+ SPELL_SUMMON_SAPLING_6 = 34739,
+ SPELL_SUMMON_SAPLINGS = 34741,
+ SPELL_ANCESTRAL_LIFE = 34742,
+ SPELL_MOONFIRE_VISUAL = 36704
};
-enum Misc
+enum Events
{
- CREATURE_TREANT = 19949,
- TREANT_SPAWN_DIST = 50 //50 yards from Warp Splinter's spawn point
+ EVENT_SUMMON = 1,
+ EVENT_STOMP,
+ EVENT_ARCANE_VOLLEY
};
-float treant_pos[6][3] =
+uint32 const SummonSaplingsSpells[] =
{
- {24.301233f, 427.221100f, -27.060635f},
- {16.795492f, 359.678802f, -27.355425f},
- {53.493484f, 345.381470f, -26.196192f},
- {61.867096f, 439.362732f, -25.921030f},
- {109.861877f, 423.201630f, -27.356019f},
- {106.780159f, 355.582581f, -27.593357f}
+ SPELL_SUMMON_SAPLING_1, SPELL_SUMMON_SAPLING_2, SPELL_SUMMON_SAPLING_3,
+ SPELL_SUMMON_SAPLING_4, SPELL_SUMMON_SAPLING_5, SPELL_SUMMON_SAPLING_6
};
-/*#####
-# npc_treant (Sapling)
-#####*/
-class npc_warp_splinter_treant : public CreatureScript
+struct boss_warp_splinter : public BossAI
{
- public:
-
- npc_warp_splinter_treant()
- : CreatureScript("npc_warp_splinter_treant")
+ boss_warp_splinter(Creature* creature) : BossAI(creature, DATA_WARP_SPLINTER) { }
+
+ void JustEngagedWith(Unit* who) override
+ {
+ BossAI::JustEngagedWith(who);
+ Talk(SAY_AGGRO);
+ events.ScheduleEvent(EVENT_SUMMON, 25s, 30s);
+ events.ScheduleEvent(EVENT_STOMP, 10s, 15s);
+ events.ScheduleEvent(EVENT_ARCANE_VOLLEY, 15s, 20s);
+ }
+
+ void KilledUnit(Unit* /*victim*/) override
+ {
+ Talk(SAY_SLAY);
+ }
+
+ void JustDied(Unit* /*killer*/) override
+ {
+ _JustDied();
+ Talk(SAY_DEATH);
+ }
+
+ void OnSpellCastFinished(SpellInfo const* spell, SpellFinishReason reason) override
+ {
+ if (reason == SPELL_FINISHED_SUCCESSFUL_CAST && spell->Id == SPELL_SUMMON_SAPLINGS)
{
+ for (uint32 summonSpells : SummonSaplingsSpells)
+ DoCastSelf(summonSpells, true);
+ Talk(SAY_SUMMON);
}
- struct npc_warp_splinter_treantAI : public ScriptedAI
- {
- npc_warp_splinter_treantAI(Creature* creature) : ScriptedAI(creature)
- {
- Initialize();
- }
+ }
- void Initialize()
- {
- check_Timer = 0;
- }
+ // Do not despawn them
+ void JustSummoned(Creature* summon) override
+ {
+ if (me->IsEngaged())
+ DoZoneInCombat(summon);
- ObjectGuid WarpGuid;
- uint32 check_Timer;
+ if (me->GetVictim())
+ summon->AI()->AttackStart(me->GetVictim());
+ }
- void Reset() override
- {
- Initialize();
- }
+ void UpdateAI(uint32 diff) override
+ {
+ if (!UpdateVictim())
+ return;
- void JustEngagedWith(Unit* /*who*/) override { }
+ events.Update(diff);
- void MoveInLineOfSight(Unit* /*who*/) override { }
+ if (me->HasUnitState(UNIT_STATE_CASTING))
+ return;
- void UpdateAI(uint32 diff) override
+ while (uint32 eventId = events.ExecuteEvent())
+ {
+ switch (eventId)
{
- if (!UpdateVictim() || !me->GetVictim())
- {
- if (WarpGuid && check_Timer <= diff)
- {
- if (Unit* Warp = ObjectAccessor::GetUnit(*me, WarpGuid))
- {
- if (me->IsWithinMeleeRange(Warp))
- {
- int32 CurrentHP_Treant = (int32)me->GetHealth();
- Warp->CastSpell(Warp, SPELL_HEAL_FATHER, CastSpellExtraArgs(me->GetGUID()).AddSpellBP0(CurrentHP_Treant));
- me->KillSelf();
- return;
- }
- me->GetMotionMaster()->MoveFollow(Warp, 0, 0);
- }
- check_Timer = 1000;
- }
- else
- check_Timer -= diff;
- return;
- }
-
- if (me->EnsureVictim()->GetGUID() != WarpGuid)
- DoMeleeAttackIfReady();
+ case EVENT_SUMMON:
+ // Ignore shared cooldown because otherwise both spells will be not used in too many cases
+ // It looks like both spells indeed should have shared cooldown but it doesn't really blocks spell
+ // cast but delays it. Maybe not in all cases. Really long sniff can tell more
+ DoCastSelf(SPELL_SUMMON_SAPLINGS, TRIGGERED_IGNORE_SPELL_AND_CATEGORY_CD);
+ events.Repeat(40s, 50s);
+ break;
+ case EVENT_STOMP:
+ DoCastSelf(SPELL_STOMP, TRIGGERED_IGNORE_SPELL_AND_CATEGORY_CD);
+ events.Repeat(20s, 30s);
+ break;
+ case EVENT_ARCANE_VOLLEY:
+ DoCastSelf(SPELL_ARCANE_VOLLEY);
+ events.Repeat(20s, 35s);
+ break;
+ default:
+ break;
}
- };
- CreatureAI* GetAI(Creature* creature) const override
- {
- return GetBotanicaAI(creature);
+
+ if (me->HasUnitState(UNIT_STATE_CASTING))
+ return;
}
+
+ DoMeleeAttackIfReady();
+ }
};
-/*#####
-# boss_warp_splinter
-#####*/
-class boss_warp_splinter : public CreatureScript
+struct npc_warp_splinter_sapling : public ScriptedAI
{
- public:
+ npc_warp_splinter_sapling(Creature* creature) : ScriptedAI(creature) { }
+
+ void InitializeAI() override
+ {
+ me->SetCorpseDelay(2, true);
+ }
- boss_warp_splinter()
- : CreatureScript("boss_warp_splinter")
+ void SpellHit(WorldObject* /*caster*/, SpellInfo const* spellInfo) override
+ {
+ // This spell currently can miss, maybe it's fine, maybe not
+ if (spellInfo->Id == SPELL_ANCESTRAL_LIFE)
{
+ me->SetReactState(REACT_PASSIVE);
+ DoCastSelf(SPELL_MOONFIRE_VISUAL);
+ me->DespawnOrUnsummon(2s);
}
- struct boss_warp_splinterAI : public BossAI
- {
- boss_warp_splinterAI(Creature* creature) : BossAI(creature, DATA_WARP_SPLINTER)
- {
- Initialize();
- Treant_Spawn_Pos_X = creature->GetPositionX();
- Treant_Spawn_Pos_Y = creature->GetPositionY();
- }
-
- void Initialize()
- {
- War_Stomp_Timer = urand(25000, 40000);
- Summon_Treants_Timer = 45000;
- Arcane_Volley_Timer = urand(8000, 20000);
- }
-
- uint32 War_Stomp_Timer;
- uint32 Summon_Treants_Timer;
- uint32 Arcane_Volley_Timer;
+ }
- float Treant_Spawn_Pos_X;
- float Treant_Spawn_Pos_Y;
+ void UpdateAI(uint32 /*diff*/) override
+ {
+ if (!UpdateVictim())
+ return;
- void Reset() override
- {
- Initialize();
- }
-
- void JustEngagedWith(Unit* /*who*/) override
- {
- Talk(SAY_AGGRO);
- }
-
- void KilledUnit(Unit* /*victim*/) override
- {
- Talk(SAY_SLAY);
- }
-
- void JustDied(Unit* /*killer*/) override
- {
- Talk(SAY_DEATH);
- }
-
- void SummonTreants()
- {
- for (uint8 i = 0; i < 6; ++i)
- {
- float angle = (float(M_PI) / 3) * i;
-
- float X = Treant_Spawn_Pos_X + TREANT_SPAWN_DIST * std::cos(angle);
- float Y = Treant_Spawn_Pos_Y + TREANT_SPAWN_DIST * std::sin(angle);
- float O = - me->GetAbsoluteAngle(X, Y);
-
- if (Creature* pTreant = me->SummonCreature(CREATURE_TREANT, treant_pos[i][0], treant_pos[i][1], treant_pos[i][2], O, TEMPSUMMON_TIMED_OR_CORPSE_DESPAWN, 25s))
- ENSURE_AI(npc_warp_splinter_treant::npc_warp_splinter_treantAI, pTreant->AI())->WarpGuid = me->GetGUID();
- }
- Talk(SAY_SUMMON);
- }
-
- void UpdateAI(uint32 diff) override
- {
- if (!UpdateVictim())
- return;
-
- //Check for War Stomp
- if (War_Stomp_Timer <= diff)
- {
- DoCastVictim(WAR_STOMP);
- War_Stomp_Timer = urand(25000, 40000);
- }
- else
- War_Stomp_Timer -= diff;
-
- //Check for Arcane Volley
- if (Arcane_Volley_Timer <= diff)
- {
- DoCastVictim(ARCANE_VOLLEY);
- Arcane_Volley_Timer = urand(20000, 35000);
- }
- else
- Arcane_Volley_Timer -= diff;
-
- //Check for Summon Treants
- if (Summon_Treants_Timer <= diff)
- {
- SummonTreants();
- Summon_Treants_Timer = 45000;
- }
- else
- Summon_Treants_Timer -= diff;
-
- DoMeleeAttackIfReady();
- }
- };
-
- CreatureAI* GetAI(Creature* creature) const override
- {
- return GetBotanicaAI(creature);
- }
+ DoMeleeAttackIfReady();
+ }
};
void AddSC_boss_warp_splinter()
{
- new boss_warp_splinter();
- new npc_warp_splinter_treant();
+ RegisterBotanicaCreatureAI(boss_warp_splinter);
+ RegisterBotanicaCreatureAI(npc_warp_splinter_sapling);
}
--
cgit v1.2.3