diff --git a/sql/updates/world/custom/custom_2019_01_18_01_world.sql b/sql/updates/world/custom/custom_2019_01_18_01_world.sql new file mode 100644 index 00000000000..a55becd5dd1 --- /dev/null +++ b/sql/updates/world/custom/custom_2019_01_18_01_world.sql @@ -0,0 +1,37 @@ +-- Template Updates +-- Berserker Boulder Roller +UPDATE `creature_template` SET `DamageModifier`= 120, `BaseVariance`= 0.5, `flags_extra`= 0x40000000, `mechanic_immune_mask`= 634338303, `ScriptName`= 'npc_zulgurub_berserking_boulder_roller' WHERE `entry`= 52348; +-- Boulder +UPDATE `creature_template` SET `speed_run`= 2.1428, `unit_flags`= 33554432, `unit_flags2`= 2099200, `VehicleId`= 1594, `flags_extra`= 2 WHERE `entry` IN (52353, 52351, 52354); +UPDATE `creature_template` SET `unit_flags`= 33554432, `unit_flags2`= 2099200, `flags_extra`= 2, `ScriptName`= '' WHERE `entry`= 52350; + +-- Spells +DELETE FROM `spell_script_names` WHERE `ScriptName` IN +('spell_zulgurub_rolling_boulders', +'spell_zulgurub_boulder_smash'); + +INSERT INTO `spell_script_names` (`spell_id`, `ScriptName`) VALUES +(96826, 'spell_zulgurub_rolling_boulders'), +(96837, 'spell_zulgurub_rolling_boulders'), +(96834, 'spell_zulgurub_boulder_smash'); + +-- Addons +DELETE FROM `creature_template_addon` WHERE `entry` IN (52353, 52351, 52354, 52350); +INSERT INTO `creature_template_addon` (`entry`, `bytes1`, `bytes2`, `auras`) VALUES +(52353, 0, 1, '96831'), +(52351, 0, 1, '96831'), +(52354, 0, 1, '96831'); + +-- Spellclicks +DELETE FROM `npc_spellclick_spells` WHERE `npc_entry` IN (52353, 52351, 52354); +INSERT INTO `npc_spellclick_spells` (`npc_entry`, `spell_id`, `cast_flags`, `user_type`) VALUES +(52353, 46598, 1, 1), +(52351, 46598, 1, 1), +(52354, 46598, 1, 1); + +-- Vehicle accessories +DELETE FROM `vehicle_template_accessory` WHERE `entry` IN (52353, 52351, 52354); +INSERT INTO `vehicle_template_accessory` (`entry`, `accessory_entry`, `seat_id`, `minion`, `description`, `summontype`, `summontimer`) VALUES +(52353, 52350, 0, 1, 'Boulder - Boulder', 8, 0), +(52351, 52350, 0, 1, 'Boulder - Boulder', 8, 0), +(52354, 52350, 0, 1, 'Boulder - Boulder', 8, 0); diff --git a/src/server/game/Spells/SpellMgr.cpp b/src/server/game/Spells/SpellMgr.cpp index 77e927504b7..a174eda0cba 100644 --- a/src/server/game/Spells/SpellMgr.cpp +++ b/src/server/game/Spells/SpellMgr.cpp @@ -4837,6 +4837,12 @@ void SpellMgr::LoadSpellInfoCorrections() spellInfo->MaxAffectedTargets = 1; }); + // Rolling Boulders Search Effect + ApplySpellFix({ 96839 }, [](SpellInfo* spellInfo) + { + spellInfo->MaxAffectedTargets = 1; + }); + // Sunder Rift ApplySpellFix({ 96964 }, [](SpellInfo* spellInfo) { diff --git a/src/server/scripts/EasternKingdoms/ZulGurub/zulgurub.cpp b/src/server/scripts/EasternKingdoms/ZulGurub/zulgurub.cpp new file mode 100644 index 00000000000..fad5a6a5313 --- /dev/null +++ b/src/server/scripts/EasternKingdoms/ZulGurub/zulgurub.cpp @@ -0,0 +1,247 @@ +/* + * Copyright (C) 2008-2019 TrinityCore + * + * This program is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License as published by the + * Free Software Foundation; either version 2 of the License, or (at your + * option) any later version. + * + * This program is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for + * more details. + * + * You should have received a copy of the GNU General Public License along + * with this program. If not, see . + */ + +#include "ScriptMgr.h" +#include "ScriptedCreature.h" +#include "zulgurub.h" +#include "GridNotifiers.h" +#include "MoveSplineInit.h" +#include "Spell.h" +#include "SpellAuraEffects.h" +#include "SpellScript.h" +#include "Vehicle.h" + +enum RollingBoulders +{ + SPELL_ROLLING_BOULDERS_PERIODIC_AURA = 96837, + SPELL_ROLLING_BOULDERS_SEARCH_EFFECT = 96839, + SPELL_ROLLING_BOULDERS_SUMMON_LEFT = 96827, + SPELL_ROLLING_BOULDERS_SUMMON_CENTER = 96828, + SPELL_ROLLING_BOULDERS_SUMMON_RIGHT = 96829, + SPELL_THUNDERCLAP = 15588, + SPELL_KNOCK_AWAY = 97616, + SPELL_EXPLODING_BOULDER = 96836, + SPELL_EXPLODING_BOULDER_VISUAL = 96831, + SPELL_ROLLING_BOULDERS = 96833, + + NPC_BOULDER_LEFT = 52351, + NPC_BOULDER_CENTER = 52354, + NPC_BOULDER_RIGHT = 52353, + + EVENT_THUNDERCLAP = 1, + EVENT_KNOCK_AWAY = 2, + + ACTION_ROLL_BOULDER = 0, + SEAT_0 = 0 +}; + +uint32 boulderCombinationFirst[] = +{ + SPELL_ROLLING_BOULDERS_SUMMON_RIGHT, + SPELL_ROLLING_BOULDERS_SUMMON_CENTER, + SPELL_ROLLING_BOULDERS_SUMMON_LEFT +}; + +uint32 boulderCombinationSecond[] = +{ + SPELL_ROLLING_BOULDERS_SUMMON_RIGHT, + SPELL_ROLLING_BOULDERS_SUMMON_LEFT, + SPELL_ROLLING_BOULDERS_SUMMON_CENTER +}; + +Position const BoulderMovePosLeft = { -12128.5f, -1809.7f, 81.73696f }; // jump to -12134.33 Y: -1809.78 Z: 83.9827 +Position const BoulderMovePosCenter = { -12117.74f, -1818.293f, 80.22023f }; // jump to -12123.57 Y: -1818.352 Z: 80.20083 +Position const BoulderMovePosRight = { -12126.91f, -1827.861f, 81.26235f }; // jump to -12132.74 Y: -1827.843 Z: 83.37392 + +class ExplodingBoulderEvent : public BasicEvent +{ + public: + ExplodingBoulderEvent(Creature* owner) : _owner(owner) { } + + bool Execute(uint64 /*time*/, uint32 /*diff*/) override + { + _owner->RemoveAurasDueToSpell(SPELL_EXPLODING_BOULDER_VISUAL); + _owner->CastSpell(_owner, SPELL_EXPLODING_BOULDER); + _owner->DespawnOrUnsummon(1s); + if (Vehicle* vehicle = _owner->GetVehicleKit()) + if (Unit* passenger = vehicle->GetPassenger(SEAT_0)) + if (Creature* creature = passenger->ToCreature()) + creature->DespawnOrUnsummon(1s); + return true; + } + private: + Creature* _owner; +}; + +class RollingBouldersCastEvent : public BasicEvent +{ + public: + RollingBouldersCastEvent(Creature* owner) : _owner(owner) { } + + bool Execute(uint64 /*time*/, uint32 /*diff*/) override + { + _owner->CastSpell(_owner, SPELL_ROLLING_BOULDERS); + return true; + } + private: + Creature* _owner; +}; + +struct npc_zulgurub_berserking_boulder_roller : public ScriptedAI +{ + npc_zulgurub_berserking_boulder_roller(Creature* creature) : ScriptedAI(creature) + { + Initialize(); + } + + void Initialize() + { + me->SetReactState(REACT_PASSIVE); + _useSecondCombination = false; + } + + void Reset() override + { + Initialize(); + } + + void JustEngagedWith(Unit* /*who*/) override + { + _events.ScheduleEvent(EVENT_THUNDERCLAP, 2s); + _events.ScheduleEvent(EVENT_KNOCK_AWAY, 6s, 7s); + } + + void EnterEvadeMode(EvadeReason /*why*/) override + { + _EnterEvadeMode(); + _events.Reset(); + me->GetMotionMaster()->MoveTargetedHome(); + } + + void SpellHitTarget(Unit* target, SpellInfo const* spell) override + { + if (spell->Id == SPELL_ROLLING_BOULDERS_SEARCH_EFFECT) + { + me->SetReactState(REACT_AGGRESSIVE); + me->RemoveAurasDueToSpell(SPELL_ROLLING_BOULDERS_PERIODIC_AURA); + AttackStart(target); + } + } + + void DoAction(int32 action) override + { + if (action == ACTION_ROLL_BOULDER) + { + uint32 spellId = !_useSecondCombination ? boulderCombinationFirst[_boulderCount] : boulderCombinationSecond[_boulderCount]; + DoCastSelf(spellId, true); + + if (_boulderCount < 2) + _boulderCount++; + else + { + _boulderCount = 0; + _useSecondCombination = !_useSecondCombination ? true : false; + } + } + } + + void JustSummoned(Creature* summon) override + { + Position destination; + switch (summon->GetEntry()) + { + case NPC_BOULDER_LEFT: + destination = BoulderMovePosLeft; + break; + case NPC_BOULDER_CENTER: + destination = BoulderMovePosCenter; + break; + case NPC_BOULDER_RIGHT: + destination = BoulderMovePosRight; + break; + default: + break; + } + + Movement::MoveSplineInit init(summon); + init.MoveTo(destination.GetPositionX(), destination.GetPositionY(), destination.GetPositionZ()); + if (uint32 time = init.Launch()) + summon->m_Events.AddEventAtOffset(new ExplodingBoulderEvent(summon), Milliseconds(time)); + + summon->m_Events.AddEventAtOffset(new RollingBouldersCastEvent(summon), 600ms); + } + + void UpdateAI(uint32 diff) override + { + if (!UpdateVictim()) + return; + + _events.Update(diff); + + if (me->HasUnitState(UNIT_STATE_CASTING)) + return; + + while (uint32 eventId = _events.ExecuteEvent()) + { + switch (eventId) + { + case EVENT_THUNDERCLAP: + DoCastAOE(SPELL_THUNDERCLAP); + _events.Repeat(15s, 16s); + break; + case EVENT_KNOCK_AWAY: + DoCastVictim(SPELL_KNOCK_AWAY); + _events.Repeat(19s, 20s); + break; + default: + break; + } + } + + DoMeleeAttackIfReady(); + } + +private: + EventMap _events; + uint8 _boulderCount; + bool _useSecondCombination; +}; + +class spell_zulgurub_rolling_boulders : public AuraScript +{ + PrepareAuraScript(spell_zulgurub_rolling_boulders); + + void HandleTick(AuraEffect const* /*aurEff*/) + { + // Serverside spell. We just skip that part and do it directly via script + PreventDefaultAction(); + if (Creature* creature = GetTarget()->ToCreature()) + if (creature->IsAIEnabled) + creature->AI()->DoAction(ACTION_ROLL_BOULDER); + } + + void Register() override + { + OnEffectPeriodic += AuraEffectPeriodicFn(spell_zulgurub_rolling_boulders::HandleTick, EFFECT_0, SPELL_AURA_PERIODIC_TRIGGER_SPELL); + } +}; + +void AddSC_zulgurub() +{ + RegisterZulGurubCreatureAI(npc_zulgurub_berserking_boulder_roller); + RegisterAuraScript(spell_zulgurub_rolling_boulders); +} diff --git a/src/server/scripts/EasternKingdoms/eastern_kingdoms_script_loader.cpp b/src/server/scripts/EasternKingdoms/eastern_kingdoms_script_loader.cpp index a17f444a6d7..5e85108f6ea 100644 --- a/src/server/scripts/EasternKingdoms/eastern_kingdoms_script_loader.cpp +++ b/src/server/scripts/EasternKingdoms/eastern_kingdoms_script_loader.cpp @@ -213,6 +213,7 @@ void AddSC_boss_renataki(); void AddSC_boss_high_priest_venoxis(); void AddSC_boss_wushoolay(); void AddSC_boss_zanzil(); +void AddSC_zulgurub(); void AddSC_instance_zulgurub(); //void AddSC_alterac_mountains(); //void AddSC_arathi_highlands(); @@ -437,6 +438,7 @@ void AddEasternKingdomsScripts() AddSC_boss_high_priest_venoxis(); AddSC_boss_wushoolay(); AddSC_boss_zanzil(); + AddSC_zulgurub(); AddSC_instance_zulgurub(); //AddSC_alterac_mountains(); //AddSC_arathi_highlands();