From 8cb88cce520d4cf7d900cfee506ff7160e447256 Mon Sep 17 00:00:00 2001 From: UltraNix <80540499+UltraNix@users.noreply.github.com> Date: Sat, 7 Jan 2023 20:28:22 +0100 Subject: [PATCH] =?UTF-8?q?fix(Scripts/The=20Underbog):=20Rewritten=20The?= =?UTF-8?q?=20Black=20Stalker's=20Levitate=20mec=E2=80=A6=20(#14541)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit * fix(Scripts/The Underbog): Rewritten The Black Stalker's Levitate mechanic. Fixes #13988 * buildfix. * Update src/server/scripts/Outland/CoilfangReservoir/underbog/boss_the_black_stalker.cpp Co-authored-by: offl Co-authored-by: Kitzunu <24550914+Kitzunu@users.noreply.github.com> --- .../rev_1673089237816039500.sql | 11 ++ src/server/game/Spells/SpellEffects.cpp | 2 +- .../underbog/boss_the_black_stalker.cpp | 167 +++++++++++++----- 3 files changed, 132 insertions(+), 48 deletions(-) create mode 100644 data/sql/updates/pending_db_world/rev_1673089237816039500.sql diff --git a/data/sql/updates/pending_db_world/rev_1673089237816039500.sql b/data/sql/updates/pending_db_world/rev_1673089237816039500.sql new file mode 100644 index 000000000..95d0f7f5c --- /dev/null +++ b/data/sql/updates/pending_db_world/rev_1673089237816039500.sql @@ -0,0 +1,11 @@ +-- +DELETE FROM `spell_script_names` WHERE `spell_id` IN (31704,31701,31702,31703); +INSERT INTO `spell_script_names` (`spell_id`,`ScriptName`) VALUES +(31704,'spell_the_black_stalker_levitate'), +(31701,'spell_the_black_stalker_levitation_pulse'), +(31702,'spell_the_black_stalker_someone_grab_me'), +(31703,'spell_the_black_stalker_magnetic_pull'); + +DELETE FROM `conditions` WHERE `SourceTypeOrReferenceId` = 13 AND `SourceEntry` = 31702; +INSERT INTO `conditions` (`SourceTypeOrReferenceId`,`SourceGroup`,`SourceEntry`,`SourceId`,`ElseGroup`,`ConditionTypeOrReference`,`ConditionTarget`,`ConditionValue1`,`ConditionValue2`,`ConditionValue3`,`NegativeCondition`,`ErrorType`,`ErrorTextId`,`ScriptName`,`Comment`) VALUES +(13,1,31702,0,0,31,0,3,17992,0,0,0,0,"","Group 0: Spell 'Someone Grab Me' (Effect 0) targets creature 'Coilfang Invisible Vacuum Dummy'"); diff --git a/src/server/game/Spells/SpellEffects.cpp b/src/server/game/Spells/SpellEffects.cpp index 68b2c5bd5..3a92f0472 100644 --- a/src/server/game/Spells/SpellEffects.cpp +++ b/src/server/game/Spells/SpellEffects.cpp @@ -5176,7 +5176,7 @@ void Spell::EffectPullTowards(SpellEffIndex effIndex) pos.Relocate(m_caster->GetPositionX(), m_caster->GetPositionY(), m_caster->GetPositionZ() + 1.0f, m_caster->GetOrientation()); } - float speedXY = float(m_spellInfo->Effects[effIndex].MiscValue) * 0.1f; + float speedXY = float(m_spellInfo->Effects[effIndex].MiscValue) ? float(m_spellInfo->Effects[effIndex].MiscValue) * 0.1f : 30.f; float speedZ = unitTarget->GetDistance(pos) / speedXY * 0.5f * Movement::gravity; unitTarget->GetMotionMaster()->MoveJump(pos.GetPositionX(), pos.GetPositionY(), pos.GetPositionZ(), speedXY, speedZ); diff --git a/src/server/scripts/Outland/CoilfangReservoir/underbog/boss_the_black_stalker.cpp b/src/server/scripts/Outland/CoilfangReservoir/underbog/boss_the_black_stalker.cpp index 631060c1c..862f27301 100644 --- a/src/server/scripts/Outland/CoilfangReservoir/underbog/boss_the_black_stalker.cpp +++ b/src/server/scripts/Outland/CoilfangReservoir/underbog/boss_the_black_stalker.cpp @@ -20,16 +20,33 @@ #include "SpellScript.h" #include "the_underbog.h" +/* +How levitation sequence works: boss casts Levitate and it triggers a chain of spells, target(any target, player or pet, any position in +threat list) eventually gets pulled towards by randomly selected trigger. Then target becomes protected from Pull Towards by Suspension +aura which is triggered every 1 sec up to 4 times. Since it has stun mechanic, diminishing returns cuts off its duration every cast in +half (20 > 10 > 5 > 0). Eventually player becomes immune to Suspension and vulnerable to another pull towards. +Whole levitate sequence is designed to pull player towards up to 3 times. Usually it works like this: player gets pulled towards, +gets protected by Suspension from Pull Towards next 2 times. If player is unlucky, boss can cast Levitate on same player again, in that case +player can be pulled towards 2 times in a row without any protection from fall damage by Suspension(case from sniffs). +However currently diminishing returns affects Suspension after first cast, its duration is 10 instead of 20 seconds and player will be +immune to 4th cast. That allows to pull player towards when levitation sequence ends. Levitation sequence has sensetive design and looks +like lack of delays between packets makes it work differently too. +Of course as was said above player can be pulled towards 2 times in a row but that looks like a rare case. +*/ + enum eBlackStalker { SPELL_LEVITATE = 31704, - SPELL_SUSPENSION = 31719, - SPELL_LEVITATION_PULSE = 31701, - SPELL_MAGNETIC_PULL = 31705, SPELL_CHAIN_LIGHTNING = 31717, SPELL_STATIC_CHARGE = 31715, SPELL_SUMMON_SPORE_STRIDER = 38755, + SPELL_LEVITATION_PULSE = 31701, + SPELL_SOMEONE_GRAB_ME = 31702, + SPELL_MAGNETIC_PULL = 31703, + SPELL_SUSPENSION_PRIMER = 31720, + SPELL_SUSPENSION = 31719, + EVENT_LEVITATE = 1, EVENT_SPELL_CHAIN = 2, EVENT_SPELL_STATIC = 3, @@ -47,15 +64,9 @@ struct boss_the_black_stalker : public BossAI { } - void Reset() override - { - lTarget.Clear(); - BossAI::Reset(); - } - void EnterCombat(Unit* who) override { - events.ScheduleEvent(EVENT_LEVITATE, 12000); + events.ScheduleEvent(EVENT_LEVITATE, urand(8000, 12000)); events.ScheduleEvent(EVENT_SPELL_CHAIN, 6000); events.ScheduleEvent(EVENT_SPELL_STATIC, 10000); events.ScheduleEvent(EVENT_CHECK, 5000); @@ -88,6 +99,10 @@ struct boss_the_black_stalker : public BossAI return; events.Update(diff); + + if (me->HasUnitState(UNIT_STATE_CASTING)) + return; + switch (events.ExecuteEvent()) { case EVENT_CHECK: @@ -107,7 +122,6 @@ struct boss_the_black_stalker : public BossAI case EVENT_SPELL_CHAIN: if (Unit* target = SelectTarget(SelectTargetMethod::Random, 0)) me->CastSpell(target, SPELL_CHAIN_LIGHTNING, false); - events.DelayEvents(3000); events.RepeatEvent(9000); break; case EVENT_SPELL_STATIC: @@ -116,46 +130,16 @@ struct boss_the_black_stalker : public BossAI events.RepeatEvent(10000); break; case EVENT_LEVITATE: - events.RepeatEvent(15000); - if (Unit* target = SelectTarget(SelectTargetMethod::Random, 1)) - { - me->CastSpell(target, SPELL_LEVITATE, false); - lTarget = target->GetGUID(); - events.DelayEvents(5000); - events.ScheduleEvent(EVENT_LEVITATE_TARGET_1, 2000); - } + DoCastSelf(SPELL_LEVITATE); + events.RepeatEvent(urand(18000, 24000)); break; - case EVENT_LEVITATE_TARGET_1: - if (Unit* target = ObjectAccessor::GetUnit(*me, lTarget)) - { - if (!target->HasAura(SPELL_LEVITATE)) - lTarget.Clear(); - else - { - target->CastSpell(target, SPELL_MAGNETIC_PULL, true); - events.ScheduleEvent(EVENT_LEVITATE_TARGET_2, 1500); - } - } - break; - case EVENT_LEVITATE_TARGET_2: - if (Unit* target = ObjectAccessor::GetUnit(*me, lTarget)) - { - if (!target->HasAura(SPELL_LEVITATE)) - lTarget.Clear(); - else - { - target->AddAura(SPELL_SUSPENSION, target); - lTarget.Clear(); - } - } - break; - } + } + + if (me->HasUnitState(UNIT_STATE_CASTING)) + return; DoMeleeAttackIfReady(); } - -private: - ObjectGuid lTarget; }; class spell_gen_allergies : public AuraScript @@ -180,8 +164,97 @@ class spell_gen_allergies : public AuraScript } }; +// 31704 - Levitate +class spell_the_black_stalker_levitate : public SpellScript +{ + PrepareSpellScript(spell_the_black_stalker_levitate); + + bool Validate(SpellInfo const* /*spellInfo*/) override + { + return ValidateSpellInfo({ SPELL_LEVITATION_PULSE }); + } + + void HandleScript(SpellEffIndex /*effIndex*/) + { + GetHitUnit()->CastSpell(GetHitUnit(), SPELL_LEVITATION_PULSE, true); + } + + void Register() override + { + OnEffectHitTarget += SpellEffectFn(spell_the_black_stalker_levitate::HandleScript, EFFECT_1, SPELL_EFFECT_SCRIPT_EFFECT); + } +}; + +// 31701 - Levitation Pulse +class spell_the_black_stalker_levitation_pulse : public SpellScript +{ + PrepareSpellScript(spell_the_black_stalker_levitation_pulse); + + bool Validate(SpellInfo const* /*spellInfo*/) override + { + return ValidateSpellInfo({ SPELL_SOMEONE_GRAB_ME }); + } + + void HandleScript(SpellEffIndex /*effIndex*/) + { + GetCaster()->CastSpell(GetCaster(), SPELL_SOMEONE_GRAB_ME, true); + } + + void Register() override + { + OnEffectHit += SpellEffectFn(spell_the_black_stalker_levitation_pulse::HandleScript, EFFECT_0, SPELL_EFFECT_SCRIPT_EFFECT); + } +}; + +// 31702 - Someone Grab Me +class spell_the_black_stalker_someone_grab_me : public SpellScript +{ + PrepareSpellScript(spell_the_black_stalker_someone_grab_me); + + bool Validate(SpellInfo const* /*spellInfo*/) override + { + return ValidateSpellInfo({ SPELL_MAGNETIC_PULL, SPELL_SUSPENSION }); + } + + void HandleScript(SpellEffIndex /*effIndex*/) + { + if (!GetCaster()->HasAura(SPELL_SUSPENSION)) + GetHitUnit()->CastSpell(GetCaster(), SPELL_MAGNETIC_PULL); + } + + void Register() override + { + OnEffectHitTarget += SpellEffectFn(spell_the_black_stalker_someone_grab_me::HandleScript, EFFECT_0, SPELL_EFFECT_SCRIPT_EFFECT); + } +}; + +// 31703 - Magnetic Pull +class spell_the_black_stalker_magnetic_pull : public SpellScript +{ + PrepareSpellScript(spell_the_black_stalker_magnetic_pull); + + bool Validate(SpellInfo const* /*spellInfo*/) override + { + return ValidateSpellInfo({ SPELL_SUSPENSION_PRIMER }); + } + + void HandleScript(SpellEffIndex /*effIndex*/) + { + GetHitUnit()->CastSpell(GetHitUnit(), SPELL_SUSPENSION_PRIMER, true); + } + + void Register() override + { + OnEffectHitTarget += SpellEffectFn(spell_the_black_stalker_magnetic_pull::HandleScript, EFFECT_1, SPELL_EFFECT_SCRIPT_EFFECT); + } +}; + void AddSC_boss_the_black_stalker() { RegisterUnderbogCreatureAI(boss_the_black_stalker); RegisterSpellScript(spell_gen_allergies); + RegisterSpellScript(spell_the_black_stalker_levitate); + RegisterSpellScript(spell_the_black_stalker_levitation_pulse); + RegisterSpellScript(spell_the_black_stalker_someone_grab_me); + RegisterSpellScript(spell_the_black_stalker_magnetic_pull); }