Scripts/SL: Update Grandmaster Vorpil (#27765)

Closes #23801

(cherry picked from commit a19c9660b4)
This commit is contained in:
offl
2022-02-17 22:40:28 +02:00
committed by Shauren
parent e1bba3d602
commit df841dc9f2
3 changed files with 206 additions and 177 deletions

View File

@@ -0,0 +1,42 @@
-- Portals / Voidwalkers
UPDATE `spell_target_position` SET `PositionZ` = 17.0863, /*`Orientation` = 3.121871,*/ `VerifiedBuild` = 0 WHERE `ID` = 33582;
-- UPDATE `spell_target_position` SET `Orientation` = 1.360249 WHERE `ID` = 33583;
-- UPDATE `spell_target_position` SET `Orientation` = 5.580167 WHERE `ID` = 33584;
-- UPDATE `spell_target_position` SET `Orientation` = 0.047734 WHERE `ID` = 33585;
-- UPDATE `spell_target_position` SET `Orientation` = 6.012834 WHERE `ID` = 33586;
-- Draw Shadows
DELETE FROM `spell_target_position` WHERE `ID` = 33558;
INSERT INTO `spell_target_position` (`ID`,`EffectIndex`,`MapID`,`PositionX`,`PositionY`,`PositionZ`,/*`Orientation`,*/`VerifiedBuild`) VALUES
(33558,0,555,-253.54771,-263.64563,17.169674,/*3.054326,*/0),
(33558,1,555,-253.54771,-263.64563,17.169674,/*3.054326,*/0);
-- Empowering Shadows
UPDATE `conditions` SET `ConditionValue2` = 18732 WHERE `SourceTypeOrReferenceId` = 13 AND `SourceEntry` = 39364;
-- Evade / Death spells
DELETE FROM `conditions` WHERE `SourceTypeOrReferenceId` = 13 AND `SourceEntry` IN (33568,33618);
INSERT INTO `conditions` (`SourceTypeOrReferenceId`,`SourceGroup`,`SourceEntry`,`SourceId`,`ElseGroup`,`ConditionTypeOrReference`,`ConditionTarget`,`ConditionValue1`,`ConditionValue2`,`ConditionValue3`,`NegativeCondition`,`ErrorType`,`ErrorTextId`,`ScriptName`,`Comment`) VALUES
(13,1,33568,0,0,31,0,3,19224,0,0,0,0,"","Group 0: Spell 'Despawn Void Portals' (Effect 0) targets creature 'Void Portal'"),
(13,1,33568,0,1,31,0,3,19427,0,0,0,0,"","Group 1: Spell 'Despawn Void Portals' (Effect 0) targets creature 'Voidwalker Summoner'"),
(13,1,33618,0,0,31,0,3,19226,0,0,0,0,"","Group 0: Spell 'Great Sacrifice' (Effect 0) targets creature 'Void Traveler'");
DELETE FROM `spell_script_names` WHERE `spell_id` = 33568 AND `ScriptName` = 'spell_gen_despawn_target';
INSERT INTO `spell_script_names` (`spell_id`,`ScriptName`) VALUES
(33568,'spell_gen_despawn_target');
--
UPDATE `creature_template` SET `ScriptName` = 'npc_voidwalker_summoner' WHERE `entry` = 19427;
UPDATE `creature_template` SET `ScriptName` = 'npc_void_traveler' WHERE `entry` = 19226;
DELETE FROM `creature_text` WHERE `CreatureID` = 18732;
INSERT INTO `creature_text` (`CreatureID`,`GroupID`,`ID`,`Text`,`Type`,`Language`,`Probability`,`Emote`,`Duration`,`Sound`,`BroadcastTextId`,`TextRange`,`comment`) VALUES
(18732,0,0,"Come to my aid! Heed your master now!",14,0,100,0,0,10523,17867,0,"Grandmaster Vorpil SAY_HELP"),
(18732,1,0,"I'll make an offering of your blood!",14,0,100,0,0,10524,17868,0,"Grandmaster Vorpil SAY_AGGRO1"),
(18732,1,1,"You'll be a fine example for the others!",14,0,100,0,0,10525,17869,0,"Grandmaster Vorpil SAY_AGGRO2"),
(18732,1,2,"Good, a worthy sacrifice!",14,0,100,0,0,10526,17870,0,"Grandmaster Vorpil SAY_AGGRO3"),
(18732,2,0,"I serve with pride.",14,0,100,0,0,10527,17871,0,"Grandmaster Vorpil SAY_SLAY1"),
(18732,2,1,"Your death is for the greater cause...",14,0,100,0,0,10528,17872,0,"Grandmaster Vorpil SAY_SLAY2"),
(18732,3,0,"I give my life... gladly.",14,0,100,0,0,10529,17873,0,"Grandmaster Vorpil SAY_DEATH"),
(18732,4,0,"The darkness in your souls draws you ever closer...",14,0,100,0,0,0,16302,0,"Grandmaster Vorpil SAY_DRAW"),
(18732,5,0,"Fools.",14,0,100,0,0,0,16330,0,"Grandmaster Vorpil SAY_WIPE");

View File

@@ -15,109 +15,88 @@
* with this program. If not, see <http://www.gnu.org/licenses/>.
*/
/*
Name: Boss_Grandmaster_Vorpil
%Complete: 100
Category: Auchindoun, Shadow Labyrinth
*/
#include "ScriptMgr.h"
#include "InstanceScript.h"
#include "Map.h"
#include "MotionMaster.h"
#include "ObjectAccessor.h"
#include "Player.h"
#include "ScriptedCreature.h"
#include "shadow_labyrinth.h"
#include "TemporarySummon.h"
enum GrandmasterVorpil
enum Texts
{
SAY_INTRO = 0,
SAY_AGGRO = 1,
SAY_HELP = 2,
SAY_SLAY = 3,
SAY_DEATH = 4,
SPELL_RAIN_OF_FIRE = 33617,
H_SPELL_RAIN_OF_FIRE = 39363,
SPELL_DRAW_SHADOWS = 33563,
SPELL_SHADOWBOLT_VOLLEY = 33841,
SPELL_BANISH = 38791,
NPC_VOID_TRAVELER = 19226,
SPELL_SUMMON_VOID_TRAVELER_A = 33582,
SPELL_SUMMON_VOID_TRAVELER_B = 33583,
SPELL_SUMMON_VOID_TRAVELER_C = 33584,
SPELL_SUMMON_VOID_TRAVELER_D = 33585,
SPELL_SUMMON_VOID_TRAVELER_E = 33586,
SPELL_SACRIFICE = 33587,
SPELL_SHADOW_NOVA = 33846,
SPELL_EMPOWERING_SHADOWS = 33783,
NPC_VOID_PORTAL = 19224,
SPELL_SUMMON_PORTAL = 33566,
SPELL_VOID_PORTAL_VISUAL = 33569
SAY_HELP = 0,
SAY_AGGRO = 1,
SAY_SLAY = 2,
SAY_DEATH = 3,
SAY_DRAW = 4,
SAY_WIPE = 5
};
Position const VorpilPosition = { -252.8820f, -264.3030f, 17.1f, 0.0f };
float VoidPortalCoords[5][3] =
enum Spells
{
{-283.5894f, -239.5718f, 12.7f},
{-306.5853f, -258.4539f, 12.7f},
{-295.8789f, -269.0899f, 12.7f},
{-209.3401f, -262.7564f, 17.1f},
{-261.4533f, -297.3298f, 17.1f}
SPELL_SHADOWBOLT_VOLLEY = 33841,
SPELL_BANISH = 38791,
SPELL_DRAW_SHADOWS = 33563,
SPELL_RAIN_OF_FIRE = 33617,
SPELL_SUMMON_VOID_PORTAL_A = 33566,
SPELL_SUMMON_VOID_PORTAL_B = 33614,
SPELL_SUMMON_VOID_PORTAL_C = 33615,
SPELL_SUMMON_VOID_PORTAL_D = 33567,
SPELL_SUMMON_VOID_PORTAL_E = 33616,
SPELL_SUMMON_VOID_SUMMONER = 33927,
SPELL_DESPAWN_VOID_PORTALS = 33568,
SPELL_GREAT_SACRIFICE = 33618,
// Voidwalker Summoner
SPELL_SUMMON_VOIDWALKER_A = 33582,
SPELL_SUMMON_VOIDWALKER_B = 33583,
SPELL_SUMMON_VOIDWALKER_C = 33584,
SPELL_SUMMON_VOIDWALKER_D = 33585,
SPELL_SUMMON_VOIDWALKER_E = 33586,
// Void Traveler
SPELL_SACRIFICE = 33587,
SPELL_SHADOW_NOVA = 33846,
SPELL_EMPOWERING_SHADOWS = 33783,
SPELL_INSTAKILL_SELF = 29878
};
enum Events
{
EVENT_SHADOWBOLT_VOLLEY = 1,
EVENT_BANISH = 2,
EVENT_DRAW_SHADOWS = 3,
EVENT_SUMMON_TRAVELER = 4
EVENT_HELP = 1,
EVENT_SHADOWBOLT_VOLLEY,
EVENT_BANISH,
EVENT_DRAW_SHADOWS,
EVENT_RAIN_OF_FIRE
};
std::array<uint32, 5> const VoidwalkerSummonSpells =
{
SPELL_SUMMON_VOIDWALKER_A, SPELL_SUMMON_VOIDWALKER_B, SPELL_SUMMON_VOIDWALKER_C, SPELL_SUMMON_VOIDWALKER_D, SPELL_SUMMON_VOIDWALKER_E
};
struct boss_grandmaster_vorpil : public BossAI
{
boss_grandmaster_vorpil(Creature* creature) : BossAI(creature, DATA_GRANDMASTER_VORPIL)
{
Initialize();
_intro = false;
}
boss_grandmaster_vorpil(Creature* creature) : BossAI(creature, DATA_GRANDMASTER_VORPIL) { }
void Initialize()
void JustEngagedWith(Unit* who) override
{
_helpYell = false;
}
BossAI::JustEngagedWith(who);
events.ScheduleEvent(EVENT_HELP, 6s);
events.ScheduleEvent(EVENT_SHADOWBOLT_VOLLEY, 10s, 15s);
if (IsHeroic())
events.ScheduleEvent(EVENT_BANISH, 10s, 20s);
events.ScheduleEvent(EVENT_DRAW_SHADOWS, 35s, 45s);
void Reset() override
{
_Reset();
Initialize();
}
void SummonPortals()
{
for (uint8 i = 0; i < 5; ++i)
if (Creature* portal = me->SummonCreature(NPC_VOID_PORTAL, VoidPortalCoords[i][0], VoidPortalCoords[i][1], VoidPortalCoords[i][2], 0, TEMPSUMMON_CORPSE_DESPAWN, 50min))
portal->CastSpell(portal, SPELL_VOID_PORTAL_VISUAL, true);
events.ScheduleEvent(EVENT_SUMMON_TRAVELER, 5s);
}
void spawnVoidTraveler()
{
uint8 pos = urand(0, 4);
me->SummonCreature(NPC_VOID_TRAVELER, VoidPortalCoords[pos][0], VoidPortalCoords[pos][1], VoidPortalCoords[pos][2], 0, TEMPSUMMON_CORPSE_TIMED_DESPAWN, 5s);
if (!_helpYell)
{
Talk(SAY_HELP);
_helpYell = true;
}
Talk(SAY_AGGRO);
DoCastSelf(SPELL_SUMMON_VOID_PORTAL_A);
DoCastSelf(SPELL_SUMMON_VOID_PORTAL_B);
DoCastSelf(SPELL_SUMMON_VOID_PORTAL_C);
DoCastSelf(SPELL_SUMMON_VOID_PORTAL_D);
DoCastSelf(SPELL_SUMMON_VOID_PORTAL_E);
DoCastSelf(SPELL_SUMMON_VOID_SUMMONER);
}
void KilledUnit(Unit* who) override
@@ -126,34 +105,23 @@ struct boss_grandmaster_vorpil : public BossAI
Talk(SAY_SLAY);
}
// Despawn is handled by spells, don't store anything
void JustSummoned(Creature* /*summon*/) override { }
void EnterEvadeMode(EvadeReason why) override
{
Talk(SAY_WIPE);
DoCastSelf(SPELL_DESPAWN_VOID_PORTALS, true);
DoCastSelf(SPELL_GREAT_SACRIFICE, true);
ScriptedAI::EnterEvadeMode(why);
}
void JustDied(Unit* /*killer*/) override
{
_JustDied();
Talk(SAY_DEATH);
}
void JustEngagedWith(Unit* who) override
{
BossAI::JustEngagedWith(who);
events.ScheduleEvent(EVENT_SHADOWBOLT_VOLLEY, 7s, 14s);
if (IsHeroic())
events.ScheduleEvent(EVENT_BANISH, 15s);
events.ScheduleEvent(EVENT_DRAW_SHADOWS, 45s);
events.ScheduleEvent(EVENT_SUMMON_TRAVELER, 90s);
Talk(SAY_AGGRO);
SummonPortals();
}
void MoveInLineOfSight(Unit* who) override
{
BossAI::MoveInLineOfSight(who);
if (!_intro && me->IsWithinLOSInMap(who) && me->IsWithinDistInMap(who, 100) && me->IsValidAttackTarget(who))
{
Talk(SAY_INTRO);
_intro = true;
}
DoCastSelf(SPELL_DESPAWN_VOID_PORTALS, true);
DoCastSelf(SPELL_GREAT_SACRIFICE, true);
}
void UpdateAI(uint32 diff) override
@@ -170,36 +138,27 @@ struct boss_grandmaster_vorpil : public BossAI
{
switch (eventId)
{
case EVENT_HELP:
Talk(SAY_HELP);
break;
case EVENT_SHADOWBOLT_VOLLEY:
DoCast(me, SPELL_SHADOWBOLT_VOLLEY);
events.ScheduleEvent(EVENT_SHADOWBOLT_VOLLEY, 15s, 30s);
DoCastSelf(SPELL_SHADOWBOLT_VOLLEY);
events.Repeat(10s, 25s);
break;
case EVENT_BANISH:
if (Unit* target = SelectTarget(SelectTargetMethod::Random, 0, 30.0f, false))
DoCast(target, SPELL_BANISH);
events.ScheduleEvent(EVENT_BANISH, 15s);
DoCast(target, SPELL_BANISH);
events.Repeat(20s, 30s);
break;
case EVENT_DRAW_SHADOWS:
{
instance->instance->DoOnPlayers([this](Player* player)
{
if (player->IsAlive() && !player->HasAura(SPELL_BANISH))
player->TeleportTo(me->GetMapId(), VorpilPosition.GetPositionX(), VorpilPosition.GetPositionY(), VorpilPosition.GetPositionZ(), VorpilPosition.GetOrientation(), TELE_TO_NOT_LEAVE_COMBAT);
});
me->UpdatePosition(VorpilPosition);
DoCast(me, SPELL_DRAW_SHADOWS, true);
DoCast(me, SPELL_RAIN_OF_FIRE);
events.ScheduleEvent(EVENT_SHADOWBOLT_VOLLEY, 6s);
events.ScheduleEvent(EVENT_DRAW_SHADOWS, 30s);
break;
}
case EVENT_SUMMON_TRAVELER:
spawnVoidTraveler();
events.ScheduleEvent(EVENT_SUMMON_TRAVELER, 10s);
// enrage at 20%
if (HealthBelowPct(20))
events.ScheduleEvent(EVENT_SUMMON_TRAVELER, 5s);
if (roll_chance_i(50))
Talk(SAY_DRAW);
DoCastSelf(SPELL_DRAW_SHADOWS);
events.Repeat(35s, 45s);
events.ScheduleEvent(EVENT_RAIN_OF_FIRE, 1s);
break;
case EVENT_RAIN_OF_FIRE:
DoCastSelf(SPELL_RAIN_OF_FIRE);
break;
}
@@ -209,70 +168,79 @@ struct boss_grandmaster_vorpil : public BossAI
DoMeleeAttackIfReady();
}
private:
bool _intro;
bool _helpYell;
};
struct npc_voidtraveler : public ScriptedAI
struct npc_voidwalker_summoner : public ScriptedAI
{
npc_voidtraveler(Creature* creature) : ScriptedAI(creature)
{
Initialize();
_instance = creature->GetInstanceScript();
}
npc_voidwalker_summoner(Creature* creature) : ScriptedAI(creature) { }
void Initialize()
void JustAppeared() override
{
_moveTimer = 0;
_sacrificed = false;
_scheduler.Schedule(10s, [this](TaskContext task)
{
DoCastSelf(Trinity::Containers::SelectRandomContainerElement(VoidwalkerSummonSpells));
task.Repeat(10s, 15s);
});
}
void Reset() override
{
Initialize();
}
void JustEngagedWith(Unit* /*who*/) override { }
void UpdateAI(uint32 diff) override
{
if (_moveTimer <= diff)
{
Creature* Vorpil = ObjectAccessor::GetCreature(*me, _instance->GetGuidData(DATA_GRANDMASTER_VORPIL));
if (!Vorpil)
return;
if (_sacrificed)
{
DoCastAOE(SPELL_EMPOWERING_SHADOWS, true);
DoCast(me, SPELL_SHADOW_NOVA, true);
me->KillSelf();
return;
}
me->GetMotionMaster()->MoveFollow(Vorpil, 0, 0);
if (me->IsWithinDist(Vorpil, 3))
{
DoCast(me, SPELL_SACRIFICE, false);
_sacrificed = true;
_moveTimer = 500;
return;
}
_moveTimer = 1000;
}
else
_moveTimer -= diff;
_scheduler.Update(diff);
}
private:
TaskScheduler _scheduler;
};
struct npc_void_traveler : public ScriptedAI
{
npc_void_traveler(Creature* creature) : ScriptedAI(creature), _instance(creature->GetInstanceScript()) { }
void InitializeAI() override
{
me->SetReactState(REACT_PASSIVE);
}
// This part needs more work
void JustAppeared() override
{
if (Creature* vorpil = ObjectAccessor::GetCreature(*me, _instance->GetGuidData(DATA_GRANDMASTER_VORPIL)))
me->GetMotionMaster()->MoveFollow(vorpil, 0, 0);
_scheduler.Schedule(500ms, [this](TaskContext task)
{
if (Creature* vorpil = ObjectAccessor::GetCreature(*me, _instance->GetGuidData(DATA_GRANDMASTER_VORPIL)))
{
if (me->IsWithinDist(vorpil, 3))
{
DoCastSelf(SPELL_SACRIFICE);
task.Schedule(1s, [this](TaskContext /*task*/)
{
DoCastSelf(SPELL_EMPOWERING_SHADOWS);
DoCastSelf(SPELL_SHADOW_NOVA);
DoCastSelf(SPELL_INSTAKILL_SELF);
});
}
else
task.Repeat();
}
});
}
void UpdateAI(uint32 diff) override
{
_scheduler.Update(diff);
}
private:
TaskScheduler _scheduler;
InstanceScript* _instance;
uint32 _moveTimer;
bool _sacrificed;
};
void AddSC_boss_grandmaster_vorpil()
{
RegisterShadowLabyrinthCreatureAI(boss_grandmaster_vorpil);
RegisterShadowLabyrinthCreatureAI(npc_voidtraveler);
RegisterShadowLabyrinthCreatureAI(npc_voidwalker_summoner);
RegisterShadowLabyrinthCreatureAI(npc_void_traveler);
}

View File

@@ -1276,6 +1276,7 @@ class spell_gen_despawn_aura : public AuraScript
}
};
/// @todo: migrate spells to spell_gen_despawn_target, then remove this
class spell_gen_despawn_self : public SpellScript
{
PrepareSpellScript(spell_gen_despawn_self);
@@ -1297,6 +1298,23 @@ class spell_gen_despawn_self : public SpellScript
}
};
class spell_gen_despawn_target : public SpellScript
{
PrepareSpellScript(spell_gen_despawn_target);
void HandleDespawn(SpellEffIndex /*effIndex*/)
{
if (GetEffectInfo().IsEffect(SPELL_EFFECT_DUMMY) || GetEffectInfo().IsEffect(SPELL_EFFECT_SCRIPT_EFFECT))
if (Creature* target = GetHitCreature())
target->DespawnOrUnsummon();
}
void Register() override
{
OnEffectHitTarget += SpellEffectFn(spell_gen_despawn_target::HandleDespawn, EFFECT_ALL, SPELL_EFFECT_ANY);
}
};
enum DivineStormSpell
{
SPELL_DIVINE_STORM = 53385,
@@ -4863,6 +4881,7 @@ void AddSC_generic_spell_scripts()
RegisterSpellScript(spell_gen_defend);
RegisterSpellScript(spell_gen_despawn_aura);
RegisterSpellScript(spell_gen_despawn_self);
RegisterSpellScript(spell_gen_despawn_target);
RegisterSpellScript(spell_gen_divine_storm_cd_reset);
RegisterSpellScript(spell_gen_ds_flush_knockback);
RegisterSpellScript(spell_gen_dungeon_credit);