diff options
-rw-r--r-- | sql/updates/world/master/2021_04_23_00_world.sql | 9 | ||||
-rw-r--r-- | src/server/scripts/Northrend/Naxxramas/boss_grobbulus.cpp | 127 |
2 files changed, 105 insertions, 31 deletions
diff --git a/sql/updates/world/master/2021_04_23_00_world.sql b/sql/updates/world/master/2021_04_23_00_world.sql new file mode 100644 index 00000000000..11d2acc03f2 --- /dev/null +++ b/sql/updates/world/master/2021_04_23_00_world.sql @@ -0,0 +1,9 @@ +-- +DELETE FROM `creature_text` WHERE `CreatureID` = 15931; +INSERT INTO `creature_text` (`CreatureID`,`GroupID`,`ID`,`Text`,`Type`,`Language`,`Probability`,`Emote`,`Duration`,`Sound`,`BroadcastTextId`,`TextRange`,`comment`) VALUES +(15931,0,0,"%s sprays slime across the room!",41,0,100,0,0,0,32318,0,"Grobbulus EMOTE_SLIME"), +(15931,1,0,"%s injects you with a mutagen!",42,0,100,0,0,0,32319,0,"Grobbulus EMOTE_MUTAGEN"); + +UPDATE `creature_template` SET `speed_walk` = 1, `BaseAttackTime` = 1800 WHERE `entry` IN (16290,29388); +UPDATE `creature_template` SET `AIName` = "", `ScriptName` = "npc_fallout_slime" WHERE `entry` = 16290; +DELETE FROM `smart_scripts` WHERE `entryorguid` = 16290 AND `source_type` = 0; diff --git a/src/server/scripts/Northrend/Naxxramas/boss_grobbulus.cpp b/src/server/scripts/Northrend/Naxxramas/boss_grobbulus.cpp index 8742c5d3b83..318a25eb301 100644 --- a/src/server/scripts/Northrend/Naxxramas/boss_grobbulus.cpp +++ b/src/server/scripts/Northrend/Naxxramas/boss_grobbulus.cpp @@ -15,37 +15,52 @@ * with this program. If not, see <http://www.gnu.org/licenses/>. */ -#include "ScriptMgr.h" +/* + * He should call all stitched giants after aggro + */ + #include "naxxramas.h" +#include "Map.h" +#include "ObjectAccessor.h" +#include "PassiveAI.h" #include "ScriptedCreature.h" +#include "ScriptMgr.h" #include "SpellAuraEffects.h" #include "SpellAuras.h" #include "SpellInfo.h" #include "SpellScript.h" -enum Spells +enum GrobbulusTexts { - SPELL_BOMBARD_SLIME = 28280, - SPELL_SLIME_SPRAY = 28157, + EMOTE_SLIME = 0, + EMOTE_MUTAGEN = 1 +}; + +enum GrobbulusSpells +{ + // Grobbulus + SPELL_BOMBARD_SLIME = 28280, // should be used out of combat (waypoint script?) + SPELL_SUMMON_FALLOUT_SLIME = 28218, SPELL_MUTATING_INJECTION = 28169, SPELL_MUTATING_EXPLOSION = 28206, SPELL_POISON_CLOUD = 28240, + SPELL_BERSERK = 26662, + // Grobbulus Cloud SPELL_POISON_CLOUD_PASSIVE = 28158, + SPELL_POISON_CLOUD_PASSIVE_25 = 54362, SPELL_PACIFY_SELF = 19951, - SPELL_BERSERK = 26662 + // Fallout Slime + SPELL_DISEASE_CLOUD = 54367 }; -enum Events -{ - EVENT_BERSERK = 1, - EVENT_CLOUD = 2, - EVENT_INJECT = 3, - EVENT_SPRAY = 4 -}; +#define SPELL_SLIME_SPRAY RAID_MODE<uint32>(28157,54364) -enum CreatureId +enum GrobbulusEvents { - NPC_FALLOUT_SLIME = 16290 + EVENT_BERSERK = 1, + EVENT_CLOUD, + EVENT_INJECT, + EVENT_SPRAY }; struct boss_grobbulus : public BossAI @@ -55,16 +70,16 @@ struct boss_grobbulus : public BossAI void JustEngagedWith(Unit* who) override { BossAI::JustEngagedWith(who); - events.ScheduleEvent(EVENT_CLOUD, 15s); - events.ScheduleEvent(EVENT_INJECT, 20s); - events.ScheduleEvent(EVENT_SPRAY, randtime(Seconds(15), Seconds(30))); // not sure + events.ScheduleEvent(EVENT_CLOUD, 5s, 10s); + events.ScheduleEvent(EVENT_INJECT, 12s, 15s); + events.ScheduleEvent(EVENT_SPRAY, RAND(25700ms, 27700ms, 30000ms)); events.ScheduleEvent(EVENT_BERSERK, 12min); } void SpellHitTarget(WorldObject* target, SpellInfo const* spellInfo) override { if (spellInfo->Id == SPELL_SLIME_SPRAY) - me->SummonCreature(NPC_FALLOUT_SLIME, *target, TEMPSUMMON_TIMED_DESPAWN_OUT_OF_COMBAT); + target->CastSpell(target, SPELL_SUMMON_FALLOUT_SLIME, true); } void UpdateAI(uint32 diff) override @@ -79,19 +94,27 @@ struct boss_grobbulus : public BossAI switch (eventId) { case EVENT_CLOUD: - DoCastAOE(SPELL_POISON_CLOUD); - events.Repeat(Seconds(15)); + DoCastSelf(SPELL_POISON_CLOUD); + events.Repeat(RAND(15600ms, 16800ms)); return; case EVENT_BERSERK: - DoCastAOE(SPELL_BERSERK, true); + DoCastSelf(SPELL_BERSERK, true); return; case EVENT_SPRAY: DoCastAOE(SPELL_SLIME_SPRAY); - events.Repeat(randtime(Seconds(15), Seconds(30))); + Talk(EMOTE_SLIME); + // timers must always looks like ~30 (initial) ~30 (first repeat) 55 (second repeat) ~30 55 + // ~30 55 ~30 55 ~30 55. So after second cast timers are always flipped + events.Repeat(RAND(32500ms, 33700ms)); return; case EVENT_INJECT: if (Unit* target = SelectTarget(SelectTargetMethod::Random, 1, 0.0f, true, true, -SPELL_MUTATING_INJECTION)) + { DoCast(target, SPELL_MUTATING_INJECTION); + Talk(EMOTE_MUTAGEN, target); + } + // The timers indeed depends on health but most likely they are just changed at health ptc + // Default timers are 10800ms, 12000ms, then changed to ~8000ms, 10000ms events.Repeat(Seconds(8) + Milliseconds(uint32(std::round(120 * me->GetHealthPct())))); return; default: @@ -103,22 +126,63 @@ struct boss_grobbulus : public BossAI } }; -struct npc_grobbulus_poison_cloud : public ScriptedAI +struct npc_grobbulus_poison_cloud : public NullCreatureAI +{ + npc_grobbulus_poison_cloud(Creature* creature) : NullCreatureAI(creature) { } + + void JustAppeared() override + { + DoCastSelf(me->GetMap()->Is25ManRaid() ? SPELL_POISON_CLOUD_PASSIVE_25 : SPELL_POISON_CLOUD_PASSIVE); + DoCastSelf(SPELL_PACIFY_SELF); + me->DespawnOrUnsummon(61s); + } +}; + +struct npc_fallout_slime : public ScriptedAI { - npc_grobbulus_poison_cloud(Creature* creature) : ScriptedAI(creature) + npc_fallout_slime(Creature* creature) : ScriptedAI(creature) { } + + void InitializeAI() override { - SetCombatMovement(false); - creature->SetReactState(REACT_PASSIVE); + me->SetCorpseDelay(2, true); + me->SetReactState(REACT_PASSIVE); + DoCastSelf(SPELL_DISEASE_CLOUD); + + _scheduler.Schedule(2s, [this](TaskContext /*task*/) + { + me->SetReactState(REACT_AGGRESSIVE); + + if (Unit* summoner = ObjectAccessor::GetUnit(*me, _summonerGUID)) + // maybe only if threat list was empty? + AddThreat(summoner, 100000.0f); + }); } - void IsSummonedBy(WorldObject* /*summoner*/) override + void IsSummonedBy(WorldObject* summoner) override { - // no visual when casting in ctor or Reset() - DoCast(me, SPELL_POISON_CLOUD_PASSIVE, true); - DoCast(me, SPELL_PACIFY_SELF, true); + _summonerGUID = summoner->GetGUID(); + } + + void EnterEvadeMode(EvadeReason /*why*/) override + { + // They don't despawn when Grobbulus dies. Calling despawn here is not entirely correct because originally + // they just stuck after leaving combat(literally, they don't move), then they despawns after few seconds + me->DespawnOrUnsummon(); + } + + void UpdateAI(uint32 diff) override + { + _scheduler.Update(diff); + + if (!UpdateVictim()) + return; + + DoMeleeAttackIfReady(); } - void UpdateAI(uint32 /*diff*/) override { } +private: + TaskScheduler _scheduler; + ObjectGuid _summonerGUID; }; // 28169 - Mutating Injection @@ -187,6 +251,7 @@ void AddSC_boss_grobbulus() { RegisterNaxxramasCreatureAI(boss_grobbulus); RegisterNaxxramasCreatureAI(npc_grobbulus_poison_cloud); + RegisterNaxxramasCreatureAI(npc_fallout_slime); RegisterSpellScript(spell_grobbulus_mutating_injection); RegisterSpellScript(spell_grobbulus_poison_cloud); } |