Scripts/Botanica: Rework Warp Splinter (#27621)

(cherry picked from commit 78327500d8)
This commit is contained in:
offl
2022-01-22 19:02:07 +02:00
committed by Shauren
parent 18d7814402
commit a6f8dc3052
2 changed files with 138 additions and 195 deletions

View File

@@ -0,0 +1,15 @@
--
DELETE FROM `spell_target_position` WHERE `ID` IN (34727,34730,34731,34732,34733,34734,34735,34736,34737,34739);
INSERT INTO `spell_target_position` (`ID`, `EffectIndex`, `MapID`, `PositionX`, `PositionY`, `PositionZ`, `VerifiedBuild`) VALUES
(34727,0,553,26,419,-25,14007),
(34731,0,553,56,428,-25,14007),
(34733,0,553,94,416,-27,14007),
(34734,0,553,94,376,-27,14007),
(34736,0,553,66,353,-26,14007),
(34739,0,553,33,366,-25,14007);
UPDATE `creature_template` SET `ScriptName` = 'npc_warp_splinter_sapling' WHERE `entry` = 19949;
DELETE FROM `conditions` WHERE `SourceTypeOrReferenceId` = 13 AND `SourceEntry` = 34742;
INSERT INTO `conditions` (`SourceTypeOrReferenceId`,`SourceGroup`,`SourceEntry`,`SourceId`,`ElseGroup`,`ConditionTypeOrReference`,`ConditionTarget`,`ConditionValue1`,`ConditionValue2`,`ConditionValue3`,`NegativeCondition`,`ErrorType`,`ErrorTextId`,`ScriptName`,`Comment`) VALUES
(13,1,34742,0,0,31,0,3,19949,0,0,0,0,"","Group 0: Spell 'Ancestral Life' (Effect 0) targets creature 'Sapling'");

View File

@@ -15,237 +15,165 @@
* with this program. If not, see <http://www.gnu.org/licenses/>.
*/
/* 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:
boss_warp_splinter(Creature* creature) : BossAI(creature, DATA_WARP_SPLINTER) { }
npc_warp_splinter_treant()
: CreatureScript("npc_warp_splinter_treant")
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
}
// Do not despawn them
void JustSummoned(Creature* summon) override
{
if (me->IsEngaged())
DoZoneInCombat(summon);
if (me->GetVictim())
summon->AI()->AttackStart(me->GetVictim());
}
void UpdateAI(uint32 diff) override
{
if (!UpdateVictim())
return;
events.Update(diff);
if (me->HasUnitState(UNIT_STATE_CASTING))
return;
while (uint32 eventId = events.ExecuteEvent())
{
npc_warp_splinter_treantAI(Creature* creature) : ScriptedAI(creature)
switch (eventId)
{
Initialize();
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;
}
void Initialize()
{
check_Timer = 0;
}
ObjectGuid WarpGuid;
uint32 check_Timer;
void Reset() override
{
Initialize();
}
void JustEngagedWith(Unit* /*who*/) override { }
void MoveInLineOfSight(Unit* /*who*/) override { }
void UpdateAI(uint32 diff) override
{
if (!UpdateVictim() || !me->GetVictim())
{
if (!WarpGuid.IsEmpty() && 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(TRIGGERED_FULL_MASK)
.SetOriginalCaster(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();
}
};
CreatureAI* GetAI(Creature* creature) const override
{
return GetBotanicaAI<npc_warp_splinter_treantAI>(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) { }
boss_warp_splinter()
: CreatureScript("boss_warp_splinter")
void InitializeAI() override
{
me->SetCorpseDelay(2, true);
}
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);
}
void UpdateAI(uint32 /*diff*/) override
{
if (!UpdateVictim())
return;
uint32 War_Stomp_Timer;
uint32 Summon_Treants_Timer;
uint32 Arcane_Volley_Timer;
float Treant_Spawn_Pos_X;
float Treant_Spawn_Pos_Y;
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<boss_warp_splinterAI>(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);
}