aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--sql/updates/world/master/2021_04_23_00_world.sql9
-rw-r--r--src/server/scripts/Northrend/Naxxramas/boss_grobbulus.cpp127
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);
}