diff --git a/data/sql/updates/pending_db_world/rev_1681662634958347500.sql b/data/sql/updates/pending_db_world/rev_1681662634958347500.sql new file mode 100644 index 000000000..830d551fd --- /dev/null +++ b/data/sql/updates/pending_db_world/rev_1681662634958347500.sql @@ -0,0 +1,25 @@ +-- +DELETE FROM `creature_template_movement` WHERE `CreatureId` IN (18708, 20657); +INSERT INTO `creature_template_movement` (`CreatureId`, `Ground`, `Rooted`, `Flight`) VALUES +(18708, 1, 1, 1), +(20657, 1, 1, 1); + +DELETE FROM `spell_script_names` WHERE `spell_id` = 33711; +INSERT INTO `spell_script_names` (`spell_id`, `ScriptName`) VALUES +(33711, 'spell_murmur_touch'); + +DELETE FROM `smart_scripts` WHERE (`entryorguid` = -146210) AND (`source_type` = 0) AND (`id` IN (1)); +INSERT INTO `smart_scripts` (`entryorguid`, `source_type`, `id`, `link`, `event_type`, `event_phase_mask`, `event_chance`, `event_flags`, `event_param1`, `event_param2`, `event_param3`, `event_param4`, `event_param5`, `action_type`, `action_param1`, `action_param2`, `action_param3`, `action_param4`, `action_param5`, `action_param6`, `target_type`, `target_param1`, `target_param2`, `target_param3`, `target_param4`, `target_x`, `target_y`, `target_z`, `target_o`, `comment`) VALUES +(-146210, 0, 1, 0, 58, 0, 100, 0, 8, 1863400, 0, 0, 0, 225, 0, 1, 0, 0, 0, 0, 10, 146104, 18708, 0, 0, 0, 0, 0, 0, 'Cabal Summoner - On Waypoint Finished - Send GUID to Murmur'); + +DELETE FROM `smart_scripts` WHERE (`source_type` = 0 AND `entryorguid` = -146209 AND `id` = 4); +INSERT INTO `smart_scripts` (`entryorguid`, `source_type`, `id`, `link`, `event_type`, `event_phase_mask`, `event_chance`, `event_flags`, `event_param1`, `event_param2`, `event_param3`, `event_param4`, `event_param5`, `action_type`, `action_param1`, `action_param2`, `action_param3`, `action_param4`, `action_param5`, `action_param6`, `target_type`, `target_param1`, `target_param2`, `target_param3`, `target_param4`, `target_x`, `target_y`, `target_z`, `target_o`, `comment`) VALUES +(-146209, 0, 4, 0, 34, 0, 100, 0, 8, 1, 0, 0, 0, 225, 0, 1, 0, 0, 0, 0, 10, 146104, 18708, 0, 0, 0, 0, 0, 0, 'Cabal Summoner - On Reached Point 1 - Send GUID to Murmur'); -- This is a hack as it will trigger spell 33331 instead of 33329 + +DELETE FROM `conditions` WHERE (`SourceTypeOrReferenceId` = 13) AND (`SourceEntry` = 33329); +INSERT INTO `conditions` (`SourceTypeOrReferenceId`, `SourceGroup`, `SourceEntry`, `SourceId`, `ElseGroup`, `ConditionTypeOrReference`, `ConditionTarget`, `ConditionValue1`, `ConditionValue2`, `ConditionValue3`, `NegativeCondition`, `ErrorType`, `ErrorTextId`, `ScriptName`, `Comment`) VALUES +(13, 1, 33329, 0, 0, 31, 0, 3, 18639, 146225, 0, 0, 0, '', 'Murmur\'s Wrath (33329) only targets a set of guids'), +(13, 1, 33329, 0, 1, 31, 0, 3, 18634, 146226, 0, 0, 0, '', 'Murmur\'s Wrath (33329) only targets a set of guids'), +(13, 1, 33329, 0, 2, 31, 0, 3, 18639, 146227, 0, 0, 0, '', 'Murmur\'s Wrath (33329) only targets a set of guids'), +(13, 1, 33329, 0, 3, 31, 0, 3, 18634, 146228, 0, 0, 0, '', 'Murmur\'s Wrath (33329) only targets a set of guids'), +(13, 1, 33329, 0, 4, 31, 0, 3, 18639, 146229, 0, 0, 0, '', 'Murmur\'s Wrath (33329) only targets a set of guids'); diff --git a/src/common/Utilities/TaskScheduler.cpp b/src/common/Utilities/TaskScheduler.cpp index ef6477422..b1c1cbd41 100644 --- a/src/common/Utilities/TaskScheduler.cpp +++ b/src/common/Utilities/TaskScheduler.cpp @@ -107,6 +107,11 @@ void TaskScheduler::Dispatch(success_t const& callback) callback(); } +bool TaskScheduler::IsGroupScheduled(group_t const group) +{ + return _task_holder.IsGroupQueued(group); +} + void TaskScheduler::TaskQueue::Push(TaskContainer&& task) { container.insert(task); @@ -159,6 +164,19 @@ void TaskScheduler::TaskQueue::ModifyIf(std::functionIsInGroup(group)) + { + return true; + } + } + + return false; +} + bool TaskScheduler::TaskQueue::IsEmpty() const { return container.empty(); diff --git a/src/common/Utilities/TaskScheduler.h b/src/common/Utilities/TaskScheduler.h index dcf1642d8..c8b7b584d 100644 --- a/src/common/Utilities/TaskScheduler.h +++ b/src/common/Utilities/TaskScheduler.h @@ -136,6 +136,9 @@ class TaskScheduler void ModifyIf(std::function const& filter); + /// Check if the group exists and is currently scheduled. + bool IsGroupQueued(group_t const group); + bool IsEmpty() const; }; @@ -260,6 +263,9 @@ public: /// Hint: Use std::initializer_list for this: "{1, 2, 3, 4}" TaskScheduler& CancelGroupsOf(std::vector const& groups); + /// Check if the group exists and is currently scheduled. + bool IsGroupScheduled(group_t const group); + /// Delays all tasks with the given duration. template TaskScheduler& DelayAll(std::chrono::duration<_Rep, _Period> const& duration) diff --git a/src/server/scripts/Outland/Auchindoun/ShadowLabyrinth/boss_murmur.cpp b/src/server/scripts/Outland/Auchindoun/ShadowLabyrinth/boss_murmur.cpp index b9a9f3229..665c174eb 100644 --- a/src/server/scripts/Outland/Auchindoun/ShadowLabyrinth/boss_murmur.cpp +++ b/src/server/scripts/Outland/Auchindoun/ShadowLabyrinth/boss_murmur.cpp @@ -24,10 +24,15 @@ enum Murmur { EMOTE_SONIC_BOOM = 0, + SPELL_SUPPRESSION = 33332, + SPELL_SHOCKWAVE = 33686, + SPELL_SHOCKWAVE_SERVERSIDE = 33673, SPELL_RESONANCE = 33657, SPELL_MAGNETIC_PULL = 33689, SPELL_SONIC_SHOCK = 38797, SPELL_THUNDERING_STORM = 39365, + SPELL_MURMUR_WRATH_AOE = 33329, + SPELL_MURMUR_WRATH = 33331, SPELL_SONIC_BOOM_CAST_N = 33923, SPELL_SONIC_BOOM_CAST_H = 38796, @@ -36,194 +41,218 @@ enum Murmur SPELL_MURMURS_TOUCH_N = 33711, SPELL_MURMURS_TOUCH_H = 38794, - EVENT_SPELL_SONIC_BOOM = 1, - EVENT_SPELL_SONIC_BOOM_EFFECT = 2, - EVENT_SPELL_MURMURS_TOUCH = 3, - EVENT_SPELL_RESONANCE = 4, - EVENT_SPELL_MAGNETIC = 5, - EVENT_SPELL_THUNDERING = 6, - EVENT_SPELL_SONIC_SHOCK = 7 + GROUP_RESONANCE = 1, + GROUP_OOC_CAST = 2, + + GUID_MURMUR_NPCS = 1 }; -class boss_murmur : public CreatureScript +enum Creatures { -public: - boss_murmur() : CreatureScript("boss_murmur") { } + NPC_CABAL_SPELLBINDER = 18639 +}; - CreatureAI* GetAI(Creature* creature) const override +struct boss_murmur : public BossAI +{ + boss_murmur(Creature* creature) : BossAI(creature, DATA_MURMUR) { - return GetShadowLabyrinthAI(creature); + SetCombatMovement(false); + + scheduler.SetValidator([this] + { + return !me->HasUnitState(UNIT_STATE_CASTING); + }); } - struct boss_murmurAI : public ScriptedAI + void Reset() override { - boss_murmurAI(Creature* creature) : ScriptedAI(creature) - { - SetCombatMovement(false); - instance = creature->GetInstanceScript(); - } + _Reset(); + me->SetHealth(me->CountPctFromMaxHealth(40)); + me->ResetPlayerDamageReq(); + CastSupressionOOC(); + } - InstanceScript* instance; - EventMap events; - - void Reset() override - { - events.Reset(); - me->SetHealth(me->CountPctFromMaxHealth(40)); - me->ResetPlayerDamageReq(); - - if (instance) - instance->SetData(DATA_MURMUREVENT, NOT_STARTED); - } - - void JustEngagedWith(Unit* /*who*/) override - { - events.ScheduleEvent(EVENT_SPELL_SONIC_BOOM, 30000); - events.ScheduleEvent(EVENT_SPELL_MURMURS_TOUCH, urand(8000, 20000)); - events.ScheduleEvent(EVENT_SPELL_RESONANCE, 5000); - events.ScheduleEvent(EVENT_SPELL_MAGNETIC, urand(15000, 30000)); - if (IsHeroic()) + void CastSupressionOOC() + { + me->m_Events.AddEventAtOffset([this] { + if (me->FindNearestCreature(NPC_CABAL_SPELLBINDER, 35.0f)) { - events.ScheduleEvent(EVENT_SPELL_THUNDERING, 15000); - events.ScheduleEvent(EVENT_SPELL_SONIC_SHOCK, 10000); + me->CastCustomSpell(SPELL_SUPPRESSION, SPELLVALUE_MAX_TARGETS, 5); + DoCastAOE(SPELL_SUPPRESSION); + CastSupressionOOC(); + } + }, 3600ms, 10900ms, GROUP_OOC_CAST); + } + + bool CanAIAttack(Unit const* victim) const override + { + return me->IsWithinMeleeRange(victim); + } + + void EnterEvadeMode(EvadeReason why) override + { + if (me->GetThreatMgr().GetThreatList().empty()) + { + BossAI::EnterEvadeMode(why); + } + } + + bool ShouldCastResonance() + { + if (Unit* victim = me->GetVictim()) + { + if (!me->IsWithinMeleeRange(victim)) + { + return true; } - if (instance) - instance->SetData(DATA_MURMUREVENT, IN_PROGRESS); - } - - void JustDied(Unit*) override - { - if (instance) - instance->SetData(DATA_MURMUREVENT, DONE); - } - - void UpdateAI(uint32 diff) override - { - if (!UpdateVictim() || me->HasUnitState(UNIT_STATE_CASTING)) - return; - - events.Update(diff); - switch (events.ExecuteEvent()) + if (Unit* victimTarget = victim->GetVictim()) { - case EVENT_SPELL_SONIC_BOOM: - Talk(EMOTE_SONIC_BOOM); - me->CastSpell(me, DUNGEON_MODE(SPELL_SONIC_BOOM_CAST_N, SPELL_SONIC_BOOM_CAST_H), false); - events.RepeatEvent(28500); - events.DelayEvents(1500); - events.ScheduleEvent(EVENT_SPELL_SONIC_BOOM_EFFECT, 0); - return; - case EVENT_SPELL_SONIC_BOOM_EFFECT: - me->CastSpell(me, DUNGEON_MODE(SPELL_SONIC_BOOM_EFFECT_N, SPELL_SONIC_BOOM_EFFECT_H), true); - break; - case EVENT_SPELL_MURMURS_TOUCH: - if (Unit* target = SelectTarget(SelectTargetMethod::Random, 0, 80.0f, true)) - me->CastSpell(target, DUNGEON_MODE(SPELL_MURMURS_TOUCH_N, SPELL_MURMURS_TOUCH_H), false); - events.RepeatEvent(urand(25000, 35000)); - break; - case EVENT_SPELL_RESONANCE: - if (!me->IsWithinMeleeRange(me->GetVictim())) - me->CastSpell(me, SPELL_RESONANCE, false); - events.RepeatEvent(5000); - break; - case EVENT_SPELL_MAGNETIC: - if (Unit* target = SelectTarget(SelectTargetMethod::Random, 0, 80.0f, true)) + return victimTarget != me; + } + } + + return true; + } + + void SetGUID(ObjectGuid guid, int32 index) override + { + if (index == GUID_MURMUR_NPCS) + { + if (Creature* creature = ObjectAccessor::GetCreature(*me, guid)) + { + DoCast(creature, SPELL_MURMUR_WRATH, true); + } + } + } + + void JustEngagedWith(Unit* /*who*/) override + { + _JustEngagedWith(); + + scheduler.Schedule(30s, [this](TaskContext context) + { + Talk(EMOTE_SONIC_BOOM); + DoCastAOE(DUNGEON_MODE(SPELL_SONIC_BOOM_CAST_N, SPELL_SONIC_BOOM_CAST_H)); + + scheduler.Schedule(1500ms, [this](TaskContext) + { + DoCastAOE(DUNGEON_MODE(SPELL_SONIC_BOOM_EFFECT_N, SPELL_SONIC_BOOM_EFFECT_H), true); + }); + + context.Repeat(28500ms); + }).Schedule(8s, 20s, [this](TaskContext context) + { + DoCastRandomTarget(DUNGEON_MODE(SPELL_MURMURS_TOUCH_N, SPELL_MURMURS_TOUCH_H)); + context.Repeat(25s, 35s); + }).Schedule(15s, 30s, [this](TaskContext context) + { + if (DoCastRandomTarget(SPELL_MAGNETIC_PULL, 0, 80.0f) == SPELL_CAST_OK) + { + context.Repeat(15s, 30s); + } + else + { + context.Repeat(500ms); + } + }).Schedule(3s, [this](TaskContext context) + { + if (ShouldCastResonance()) + { + if (!scheduler.IsGroupScheduled(GROUP_RESONANCE)) + { + scheduler.Schedule(5s, 5s, GROUP_RESONANCE, [this](TaskContext context) { - me->CastSpell(target, SPELL_MAGNETIC_PULL, false); - events.RepeatEvent(urand(15000, 30000)); - return; - } - events.RepeatEvent(500); - break; - case EVENT_SPELL_THUNDERING: - me->CastSpell(me, SPELL_THUNDERING_STORM, true); - events.RepeatEvent(15000); - break; - case EVENT_SPELL_SONIC_SHOCK: - me->CastSpell(me->GetVictim(), SPELL_SONIC_SHOCK, false); - events.RepeatEvent(urand(10000, 20000)); - break; - } - - if (!me->isAttackReady()) - return; - - if (!me->IsWithinMeleeRange(me->GetVictim())) - { - ThreatContainer::StorageType threatlist = me->GetThreatMgr().GetThreatList(); - for (ThreatContainer::StorageType::const_iterator i = threatlist.begin(); i != threatlist.end(); ++i) - if (Unit* target = ObjectAccessor::GetUnit(*me, (*i)->getUnitGuid())) - if (target->IsAlive() && me->IsWithinMeleeRange(target)) + if (ShouldCastResonance()) { - me->TauntApply(target); - break; + DoCastAOE(SPELL_RESONANCE); + context.Repeat(5s); } + }); + } } - DoMeleeAttackIfReady(); - } - }; -}; + context.Repeat(); + }); -class spell_murmur_sonic_boom_effect : public SpellScriptLoader -{ -public: - spell_murmur_sonic_boom_effect() : SpellScriptLoader("spell_murmur_sonic_boom_effect") { } - - class spell_murmur_sonic_boom_effect_SpellScript : public SpellScript - { - PrepareSpellScript(spell_murmur_sonic_boom_effect_SpellScript) - - public: - spell_murmur_sonic_boom_effect_SpellScript() : SpellScript() { } - - void RecalculateDamage() + if (IsHeroic()) { - SetHitDamage(GetHitUnit()->CountPctFromMaxHealth(90)); + scheduler.Schedule(15s, [this](TaskContext context) + { + DoCastAOE(SPELL_THUNDERING_STORM); + context.Repeat(15s); + }).Schedule(10s, [this](TaskContext context) + { + DoCastVictim(SPELL_SONIC_SHOCK); + context.Repeat(10s, 20s); + }); } - void Register() override - { - OnHit += SpellHitFn(spell_murmur_sonic_boom_effect_SpellScript::RecalculateDamage); - } - }; - - SpellScript* GetSpellScript() const override - { - return new spell_murmur_sonic_boom_effect_SpellScript(); + me->m_Events.CancelEventGroup(GROUP_OOC_CAST); } }; -class spell_murmur_thundering_storm : public SpellScriptLoader +class spell_murmur_thundering_storm : public SpellScript { + PrepareSpellScript(spell_murmur_thundering_storm); + + void SelectTarget(std::list& targets) + { + targets.remove_if(Acore::AllWorldObjectsInExactRange(GetCaster(), 100.0f, true)); + targets.remove_if(Acore::AllWorldObjectsInExactRange(GetCaster(), 25.0f, false)); + } + + void Register() override + { + OnObjectAreaTargetSelect += SpellObjectAreaTargetSelectFn(spell_murmur_thundering_storm::SelectTarget, EFFECT_0, TARGET_UNIT_SRC_AREA_ENEMY); + } +}; + +// 33711/38794 - Murmur's Touch +class spell_murmur_touch : public AuraScript +{ + PrepareAuraScript(spell_murmur_touch); + + void HandleAfterRemove(AuraEffect const* /*aurEff*/, AuraEffectHandleModes /*mode*/) + { + if (GetTargetApplication()->GetRemoveMode() == AURA_REMOVE_BY_EXPIRE) + { + if (GetTarget()) + { + GetTarget()->CastSpell(GetTarget(), SPELL_SHOCKWAVE, true); + GetTarget()->CastSpell(GetTarget(), SPELL_SHOCKWAVE_SERVERSIDE, true); + } + } + } + + void Register() override + { + AfterEffectRemove += AuraEffectRemoveFn(spell_murmur_touch::HandleAfterRemove, EFFECT_0, SPELL_AURA_PERIODIC_TRIGGER_SPELL, AURA_EFFECT_HANDLE_REAL); + } +}; + +class spell_murmur_sonic_boom_effect : public SpellScript +{ + PrepareSpellScript(spell_murmur_sonic_boom_effect) + public: - spell_murmur_thundering_storm() : SpellScriptLoader("spell_murmur_thundering_storm") { } + spell_murmur_sonic_boom_effect() : SpellScript() { } - class spell_murmur_thundering_storm_SpellScript : public SpellScript + void RecalculateDamage() { - PrepareSpellScript(spell_murmur_thundering_storm_SpellScript); + SetHitDamage(GetHitUnit()->CountPctFromCurHealth(80)); + } - void SelectTarget(std::list& targets) - { - targets.remove_if(Acore::AllWorldObjectsInExactRange(GetCaster(), 100.0f, true)); - targets.remove_if(Acore::AllWorldObjectsInExactRange(GetCaster(), 25.0f, false)); - } - - void Register() override - { - OnObjectAreaTargetSelect += SpellObjectAreaTargetSelectFn(spell_murmur_thundering_storm_SpellScript::SelectTarget, EFFECT_0, TARGET_UNIT_SRC_AREA_ENEMY); - } - }; - - SpellScript* GetSpellScript() const override + void Register() override { - return new spell_murmur_thundering_storm_SpellScript(); + OnHit += SpellHitFn(spell_murmur_sonic_boom_effect::RecalculateDamage); } }; void AddSC_boss_murmur() { - new boss_murmur(); - new spell_murmur_sonic_boom_effect(); - new spell_murmur_thundering_storm(); + RegisterShadowLabyrinthCreatureAI(boss_murmur); + RegisterSpellScript(spell_murmur_thundering_storm); + RegisterSpellScript(spell_murmur_touch); + RegisterSpellScript(spell_murmur_sonic_boom_effect); } diff --git a/src/server/scripts/Outland/Auchindoun/ShadowLabyrinth/shadow_labyrinth.h b/src/server/scripts/Outland/Auchindoun/ShadowLabyrinth/shadow_labyrinth.h index 49f76fa1e..b0fa42f77 100644 --- a/src/server/scripts/Outland/Auchindoun/ShadowLabyrinth/shadow_labyrinth.h +++ b/src/server/scripts/Outland/Auchindoun/ShadowLabyrinth/shadow_labyrinth.h @@ -31,8 +31,9 @@ enum slData TYPE_HELLMAW = 1, DATA_BLACKHEARTTHEINCITEREVENT = 2, DATA_GRANDMASTERVORPILEVENT = 3, - DATA_MURMUREVENT = 4, - MAX_ENCOUNTER = 5 + DATA_MURMUR = 4, + DATA_MURMUREVENT = 5, + MAX_ENCOUNTER = 6 }; enum slNPCandGO diff --git a/src/server/scripts/Spells/spell_generic.cpp b/src/server/scripts/Spells/spell_generic.cpp index e4acbc9a1..0acf396ff 100644 --- a/src/server/scripts/Spells/spell_generic.cpp +++ b/src/server/scripts/Spells/spell_generic.cpp @@ -3663,7 +3663,9 @@ class spell_gen_ds_flush_knockback : public SpellScript 60864 - Jaws of Death (spell_gen_default_count_pct_from_max_hp) 38441 - Cataclysmic Bolt (spell_gen_50pct_count_pct_from_max_hp) 66316, 67100, 67101, 67102 - Spinning Pain Spike (spell_gen_50pct_count_pct_from_max_hp) - 41360 - L5 Arcane Charge (spell_gen_100pct_count_pct_from_max_hp) */ + 41360 - L5 Arcane Charge (spell_gen_100pct_count_pct_from_max_hp) + 33711/38794 - Murmur's Touch + */ class spell_gen_count_pct_from_max_hp : public SpellScript { PrepareSpellScript(spell_gen_count_pct_from_max_hp)