aboutsummaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
authorShauren <none@none>2010-08-30 11:36:15 +0200
committerShauren <none@none>2010-08-30 11:36:15 +0200
commit6c3b39ac015d294d9b51eeb3aac235fffe50ade8 (patch)
tree24c1c76ec7e1f8e16e623f154d3ec7d4b8bc504f /src
parentdc2c28985f57cd75bb9858dfecba4d3b368acf07 (diff)
Scripts/Icecrown Citadel: Added Festergut script, thx Cromash for providing the base and Cyrax for sniffs
Scripts/Icecrown Citadel: Added Professor Putricide script handling ONLY Festergut related events --HG-- branch : trunk
Diffstat (limited to 'src')
-rw-r--r--src/server/game/Scripting/ScriptLoader.cpp4
-rw-r--r--src/server/scripts/Northrend/IcecrownCitadel/boss_festergut.cpp452
-rw-r--r--src/server/scripts/Northrend/IcecrownCitadel/boss_professor_putricide.cpp212
-rw-r--r--src/server/scripts/Northrend/IcecrownCitadel/icecrown_citadel.h25
-rw-r--r--src/server/scripts/Northrend/IcecrownCitadel/instance_icecrown_citadel.cpp88
5 files changed, 780 insertions, 1 deletions
diff --git a/src/server/game/Scripting/ScriptLoader.cpp b/src/server/game/Scripting/ScriptLoader.cpp
index 0a7eb686d02..71389a124df 100644
--- a/src/server/game/Scripting/ScriptLoader.cpp
+++ b/src/server/game/Scripting/ScriptLoader.cpp
@@ -428,6 +428,8 @@ void AddSC_boss_marwyn();
void AddSC_boss_lord_marrowgar(); // Icecrown Citadel
void AddSC_boss_lady_deathwhisper();
void AddSC_boss_deathbringer_saurfang();
+void AddSC_boss_festergut();
+void AddSC_boss_professor_putricide();
void AddSC_icecrown_citadel_teleport();
void AddSC_instance_icecrown_citadel();
@@ -1105,6 +1107,8 @@ void AddNorthrendScripts()
AddSC_boss_lord_marrowgar(); // Icecrown Citadel
AddSC_boss_lady_deathwhisper();
AddSC_boss_deathbringer_saurfang();
+ AddSC_boss_festergut();
+ AddSC_boss_professor_putricide();
AddSC_icecrown_citadel_teleport();
AddSC_instance_icecrown_citadel();
diff --git a/src/server/scripts/Northrend/IcecrownCitadel/boss_festergut.cpp b/src/server/scripts/Northrend/IcecrownCitadel/boss_festergut.cpp
new file mode 100644
index 00000000000..26a64cedea7
--- /dev/null
+++ b/src/server/scripts/Northrend/IcecrownCitadel/boss_festergut.cpp
@@ -0,0 +1,452 @@
+/*
+ * Copyright (C) 2008-2010 Trinity <http://www.trinitycore.org/>
+ *
+ * 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, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ */
+
+#include "ScriptPCH.h"
+#include "icecrown_citadel.h"
+
+enum eScriptTexts
+{
+ SAY_STINKY_DEAD = -1631078,
+ SAY_AGGRO = -1631079,
+ EMOTE_GAS_SPORE = -1631081,
+ EMOTE_WARN_GAS_SPORE = -1631082,
+ SAY_PUNGENT_BLIGHT = -1631083,
+ EMOTE_WARN_PUNGENT_BLIGHT = -1631084,
+ EMOTE_PUNGENT_BLIGHT = -1631085,
+ SAY_KILL_1 = -1631086,
+ SAY_KILL_2 = -1631087,
+ SAY_BERSERK = -1631088,
+ SAY_DEATH = -1631089
+};
+
+enum eSpells
+{
+ // Festergut
+ SPELL_INHALE_BLIGHT = 69165,
+ SPELL_PUNGENT_BLIGHT = 69195,
+ SPELL_GASTRIC_BLOAT = 72219, // 72214 is the proper way (with proc) but atm procs can't have cooldown for creatures
+ SPELL_GASTRIC_EXPLOSION = 72227,
+ SPELL_GAS_SPORE = 69278,
+ SPELL_VILE_GAS = 69240,
+ SPELL_INOCULATED = 69291,
+
+ // Stinky
+ SPELL_MORTAL_WOUND = 71127,
+ SPELL_DECIMATE = 71123,
+ SPELL_PLAGUE_STENCH = 71805
+};
+
+// Used for HasAura checks
+#define PUNGENT_BLIGHT_HELPER RAID_MODE(69195,71219,73031,73032)
+#define INOCULATED_HELPER RAID_MODE(69291,72101,72102,72103)
+
+static const uint32 gaseousBlight[3] = {69157, 69162, 69164};
+static const uint32 gaseousBlightVisual[3] = {69126, 69152, 69154};
+
+enum eEvents
+{
+ EVENT_BERSERK = 1,
+ EVENT_INHALE_BLIGHT = 2,
+ EVENT_VILE_GAS = 3,
+ EVENT_GAS_SPORE = 4,
+ EVENT_GASTRIC_BLOAT = 5,
+
+ EVENT_DECIMATE = 6,
+ EVENT_MORTAL_WOUND = 7
+};
+
+#define DATA_INOCULATED_STACK 69291
+
+class boss_festergut : public CreatureScript
+{
+ public:
+ boss_festergut() : CreatureScript("boss_festergut") { }
+
+ struct boss_festergutAI : public BossAI
+ {
+ boss_festergutAI(Creature* pCreature) : BossAI(pCreature, DATA_FESTERGUT)
+ {
+ ASSERT(instance);
+ uiMaxInoculatedStack = 0;
+ uiInhaleCounter = 0;
+ gasDummyGUID = 0;
+ }
+
+ void Reset()
+ {
+ events.Reset();
+ events.ScheduleEvent(EVENT_BERSERK, 300000);
+ events.ScheduleEvent(EVENT_INHALE_BLIGHT, urand(25000, 30000));
+ events.ScheduleEvent(EVENT_VILE_GAS, urand(30000, 32500));
+ events.ScheduleEvent(EVENT_GAS_SPORE, urand(20000, 25000));
+ events.ScheduleEvent(EVENT_GASTRIC_BLOAT, urand(12500, 15000));
+ uiMaxInoculatedStack = 0;
+ uiInhaleCounter = 0;
+ me->RemoveAurasDueToSpell(SPELL_BERSERK2);
+ if (Creature* gasDummy = GetClosestCreatureWithEntry(me, NPC_GAS_DUMMY, 100.0f, true))
+ {
+ gasDummyGUID = gasDummy->GetGUID();
+ for (uint8 i = 0; i < 3; ++i)
+ {
+ gasDummy->RemoveAurasDueToSpell(gaseousBlight[i]);
+ gasDummy->RemoveAurasDueToSpell(gaseousBlightVisual[i]);
+ }
+ }
+
+ instance->SetBossState(DATA_FESTERGUT, NOT_STARTED);
+ }
+
+ void EnterCombat(Unit* /*who*/)
+ {
+ DoScriptText(SAY_AGGRO, me);
+ if (Creature* gasDummy = GetClosestCreatureWithEntry(me, NPC_GAS_DUMMY, 100.0f, true))
+ gasDummyGUID = gasDummy->GetGUID();
+ instance->SetBossState(DATA_FESTERGUT, IN_PROGRESS);
+ if (Creature* professor = Unit::GetCreature(*me, instance->GetData64(DATA_PROFESSOR_PUTRICIDE)))
+ professor->AI()->DoAction(ACTION_FESTERGUT_COMBAT);
+
+ DoZoneInCombat(me);
+ }
+
+ void JustDied(Unit* /*killer*/)
+ {
+ DoScriptText(SAY_DEATH, me);
+ instance->SetBossState(DATA_FESTERGUT, DONE);
+ if (Creature* professor = Unit::GetCreature(*me, instance->GetData64(DATA_PROFESSOR_PUTRICIDE)))
+ professor->AI()->DoAction(ACTION_FESTERGUT_DEATH);
+ }
+
+ void JustReachedHome()
+ {
+ instance->SetBossState(DATA_FESTERGUT, FAIL);
+ }
+
+ void EnterEvadeMode()
+ {
+ ScriptedAI::EnterEvadeMode();
+ if (Creature* professor = Unit::GetCreature(*me, instance->GetData64(DATA_PROFESSOR_PUTRICIDE)))
+ professor->AI()->EnterEvadeMode();
+ }
+
+ void KilledUnit(Unit *victim)
+ {
+ if (victim->GetTypeId() == TYPEID_PLAYER)
+ DoScriptText(RAND(SAY_KILL_1, SAY_KILL_2), me);
+ }
+
+ void MoveInLineOfSight(Unit* /*who*/)
+ {
+ // don't enter combat
+ }
+
+ void SpellHitTarget(Unit* target, const SpellEntry* spell)
+ {
+ if (spell->Id == PUNGENT_BLIGHT_HELPER)
+ target->RemoveAurasDueToSpell(INOCULATED_HELPER);
+ }
+
+ void UpdateAI(const uint32 diff)
+ {
+ if (!UpdateVictim() || !CheckInRoom())
+ return;
+
+ events.Update(diff);
+
+ if (me->hasUnitState(UNIT_STAT_CASTING))
+ return;
+
+ while (uint32 eventId = events.ExecuteEvent())
+ {
+ switch (eventId)
+ {
+ case EVENT_INHALE_BLIGHT:
+ {
+ if (Creature* gasDummy = Unit::GetCreature(*me, gasDummyGUID))
+ for (uint8 i = 0; i < 3; ++i)
+ {
+ gasDummy->RemoveAurasDueToSpell(gaseousBlight[i]);
+ gasDummy->RemoveAurasDueToSpell(gaseousBlightVisual[i]);
+ }
+ if (uiInhaleCounter == 3)
+ {
+ DoScriptText(EMOTE_WARN_PUNGENT_BLIGHT, me);
+ DoScriptText(SAY_PUNGENT_BLIGHT, me);
+ DoCast(me, SPELL_PUNGENT_BLIGHT);
+ uiInhaleCounter = 0;
+ if (Creature* professor = Unit::GetCreature(*me, instance->GetData64(DATA_PROFESSOR_PUTRICIDE)))
+ professor->AI()->DoAction(ACTION_FESTERGUT_GAS);
+ }
+ else
+ {
+ DoCast(me, SPELL_INHALE_BLIGHT);
+ // just cast and dont bother with target, conditions will handle it
+ ++uiInhaleCounter;
+ if (uiInhaleCounter < 3)
+ me->CastSpell(me, gaseousBlight[uiInhaleCounter], true, NULL, NULL, me->GetGUID());
+ }
+ events.ScheduleEvent(EVENT_INHALE_BLIGHT, urand(33500, 35000));
+ return;
+ }
+ case EVENT_VILE_GAS:
+ if (Unit* target = SelectTarget(SELECT_TARGET_RANDOM, 0, 0.0f, true))
+ DoCast(target, SPELL_VILE_GAS);
+ events.ScheduleEvent(EVENT_VILE_GAS, urand(28000, 35000));
+ break;
+ case EVENT_GAS_SPORE:
+ DoScriptText(EMOTE_WARN_GAS_SPORE, me);
+ me->CastCustomSpell(SPELL_GAS_SPORE, SPELLVALUE_MAX_TARGETS, RAID_MODE<int32>(2,3,2,3), me);
+ DoScriptText(EMOTE_GAS_SPORE, me);
+ events.ScheduleEvent(EVENT_GAS_SPORE, urand(40000, 45000));
+ case EVENT_GASTRIC_BLOAT:
+ DoCastVictim(SPELL_GASTRIC_BLOAT);
+ events.ScheduleEvent(EVENT_GASTRIC_BLOAT, urand(15000, 17500));
+ break;
+ case EVENT_BERSERK:
+ DoCast(me, SPELL_BERSERK2);
+ DoScriptText(SAY_BERSERK, me);
+ break;
+ default:
+ break;
+ }
+ }
+
+ DoMeleeAttackIfReady();
+ }
+
+ void SetData(uint32 type, uint32 data)
+ {
+ if (type == DATA_INOCULATED_STACK && data > uiMaxInoculatedStack)
+ uiMaxInoculatedStack = data;
+ }
+
+ uint32 GetData(uint32 type)
+ {
+ if (type == DATA_INOCULATED_STACK)
+ return uint32(uiMaxInoculatedStack);
+
+ return 0;
+ }
+
+ private:
+ uint32 uiMaxInoculatedStack;
+ uint8 uiInhaleCounter;
+ uint64 gasDummyGUID;
+ };
+
+ CreatureAI* GetAI(Creature* pCreature) const
+ {
+ return new boss_festergutAI(pCreature);
+ }
+};
+
+class npc_stinky_icc : public CreatureScript
+{
+ public:
+ npc_stinky_icc() : CreatureScript("npc_stinky_icc") { }
+
+ struct npc_stinky_iccAI : public ScriptedAI
+ {
+ npc_stinky_iccAI(Creature* pCreature) : ScriptedAI(pCreature)
+ {
+ pInstance = pCreature->GetInstanceScript();
+ }
+
+ void Reset()
+ {
+ events.Reset();
+ events.ScheduleEvent(EVENT_DECIMATE, urand(20000, 25000));
+ events.ScheduleEvent(EVENT_MORTAL_WOUND, urand(3000, 7000));
+ DoCast(me, SPELL_PLAGUE_STENCH);
+ }
+
+ void UpdateAI(const uint32 diff)
+ {
+ if (!UpdateVictim())
+ return;
+
+ events.Update(diff);
+
+ if (me->hasUnitState(UNIT_STAT_CASTING))
+ return;
+
+ while (uint32 eventId = events.ExecuteEvent())
+ {
+ switch (eventId)
+ {
+ case EVENT_DECIMATE:
+ DoCastVictim(SPELL_DECIMATE);
+ events.ScheduleEvent(EVENT_DECIMATE, urand(20000, 25000));
+ break;
+ case EVENT_MORTAL_WOUND:
+ DoCastVictim(SPELL_MORTAL_WOUND);
+ events.ScheduleEvent(EVENT_MORTAL_WOUND, urand(10000, 12500));
+ break;
+ default:
+ break;
+ }
+ }
+
+ DoMeleeAttackIfReady();
+ }
+
+ void JustDied(Unit* who)
+ {
+ uint64 festergutGUID = pInstance ? pInstance->GetData64(DATA_FESTERGUT) : 0;
+ if (Creature *festergut = me->GetCreature(*me, festergutGUID))
+ DoScriptText(SAY_STINKY_DEAD, festergut);
+ }
+
+ private:
+ EventMap events;
+ InstanceScript* pInstance;
+ };
+
+ CreatureAI* GetAI(Creature* pCreature) const
+ {
+ return new npc_stinky_iccAI(pCreature);
+ }
+};
+
+class spell_festergut_pungent_blight : public SpellScriptLoader
+{
+ public:
+ spell_festergut_pungent_blight() : SpellScriptLoader("spell_festergut_pungent_blight") { }
+
+ class spell_festergut_pungent_blight_SpellScript : public SpellScript
+ {
+ void HandleScript(SpellEffIndex effIndex)
+ {
+ SpellEntry const* spellInfo = sSpellStore.LookupEntry(GetEffectValue());
+ if (!spellInfo)
+ return;
+
+ // Get Inhaled Blight id for our difficulty
+ spellInfo = sSpellMgr.GetSpellForDifficultyFromSpell(spellInfo, GetCaster());
+
+ // ...and remove it
+ GetCaster()->RemoveAurasDueToSpell(spellInfo->Id);
+ DoScriptText(EMOTE_PUNGENT_BLIGHT, GetCaster());
+ }
+
+ void Register()
+ {
+ OnEffect += SpellEffectFn(spell_festergut_pungent_blight_SpellScript::HandleScript, EFFECT_1, SPELL_EFFECT_SCRIPT_EFFECT);
+ }
+ };
+
+ SpellScript* GetSpellScript() const
+ {
+ return new spell_festergut_pungent_blight_SpellScript();
+ }
+};
+
+class spell_festergut_gastric_bloat : public SpellScriptLoader
+{
+ public:
+ spell_festergut_gastric_bloat() : SpellScriptLoader("spell_festergut_gastric_bloat") { }
+
+ class spell_festergut_gastric_bloat_SpellScript : public SpellScript
+ {
+ void HandleScript(SpellEffIndex effIndex)
+ {
+ Aura const* aura = GetHitUnit()->GetAura(GetSpellInfo()->Id);
+ if (!(aura && aura->GetStackAmount() == 10))
+ return;
+
+ //PreventHitAura();
+
+ SpellEntry const* spellInfo = sSpellStore.LookupEntry(SPELL_GASTRIC_EXPLOSION);
+ if (!spellInfo)
+ return;
+
+ // Get Gastric Explosion id for our difficulty
+ spellInfo = sSpellMgr.GetSpellForDifficultyFromSpell(spellInfo, GetCaster());
+ GetHitUnit()->RemoveAurasDueToSpell(GetSpellInfo()->Id);
+ GetHitUnit()->CastSpell(GetHitUnit(), spellInfo, true);
+ }
+
+ void Register()
+ {
+ OnEffect += SpellEffectFn(spell_festergut_gastric_bloat_SpellScript::HandleScript, EFFECT_2, SPELL_EFFECT_SCRIPT_EFFECT);
+ }
+ };
+
+ SpellScript* GetSpellScript() const
+ {
+ return new spell_festergut_gastric_bloat_SpellScript();
+ }
+};
+
+class spell_festergut_blighted_spores : public SpellScriptLoader
+{
+ public:
+ spell_festergut_blighted_spores() : SpellScriptLoader("spell_festergut_blighted_spores") { }
+
+ class spell_festergut_blighted_spores_AuraScript : public AuraScript
+ {
+ void ExtraEffect(AuraEffect const* /*aurEff*/, AuraApplication const* aurApp, AuraEffectHandleModes /*mode*/)
+ {
+ if (!GetCaster()->IsAIEnabled || GetCaster()->GetTypeId() != TYPEID_UNIT)
+ return;
+
+ uint32 inoculateId = CAST_AI(ScriptedAI, GetCaster()->ToCreature()->AI())->INOCULATED_HELPER;
+ uint32 currStack = 0;
+ if (Aura const* inoculate = aurApp->GetTarget()->GetAura(inoculateId))
+ currStack = inoculate->GetStackAmount();
+
+ aurApp->GetTarget()->CastSpell(aurApp->GetTarget(), SPELL_INOCULATED, true);
+ ++currStack;
+ if (GetCaster())
+ GetCaster()->ToCreature()->AI()->SetData(DATA_INOCULATED_STACK, currStack);
+ }
+
+ void Register()
+ {
+ OnEffectApply += AuraEffectApplyFn(spell_festergut_blighted_spores_AuraScript::ExtraEffect, EFFECT_0, SPELL_AURA_PERIODIC_DAMAGE, AURA_EFFECT_HANDLE_REAL);
+ }
+ };
+
+ AuraScript* GetAuraScript() const
+ {
+ return new spell_festergut_blighted_spores_AuraScript();
+ }
+};
+
+class achievement_flu_shot_shortage : public AchievementCriteriaScript
+{
+ public:
+ achievement_flu_shot_shortage() : AchievementCriteriaScript("achievement_flu_shot_shortage") { }
+
+ bool OnCheck(Player* /*source*/, Unit* target)
+ {
+ if (target && target->GetTypeId() == TYPEID_UNIT)
+ return target->ToCreature()->AI()->GetData(DATA_INOCULATED_STACK) < 3;
+
+ return false;
+ }
+};
+
+void AddSC_boss_festergut()
+{
+ new boss_festergut();
+ new npc_stinky_icc();
+ new spell_festergut_pungent_blight();
+ new spell_festergut_gastric_bloat();
+ new spell_festergut_blighted_spores();
+ new achievement_flu_shot_shortage();
+}
diff --git a/src/server/scripts/Northrend/IcecrownCitadel/boss_professor_putricide.cpp b/src/server/scripts/Northrend/IcecrownCitadel/boss_professor_putricide.cpp
new file mode 100644
index 00000000000..c5c88c7935a
--- /dev/null
+++ b/src/server/scripts/Northrend/IcecrownCitadel/boss_professor_putricide.cpp
@@ -0,0 +1,212 @@
+/*
+ * Copyright (C) 2008-2010 Trinity <http://www.trinitycore.org/>
+ *
+ * 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, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ */
+
+#include "ScriptPCH.h"
+#include "icecrown_citadel.h"
+
+enum eScriptTexts
+{
+ // Festergut
+ SAY_FESTERGUT_GASEOUS_BLIGHT = -1631080,
+ SAY_FESTERGUT_DEATH = -1631090,
+};
+
+enum eSpells
+{
+ // Festergut
+ SPELL_RELEASE_GAS_VISUAL = 69125,
+ SPELL_GASEOUS_BLIGHT_LARGE = 69157,
+ SPELL_GASEOUS_BLIGHT_MEDIUM = 69162,
+ SPELL_GASEOUS_BLIGHT_SMALL = 69164,
+ SPELL_MALLABLE_GOO_H = 70852,
+};
+
+enum eEvents
+{
+ // Festergut
+ EVENT_FESTERGUT_DIES = 1,
+ EVENT_FESTERGUT_GOO = 2,
+};
+
+enum ePhases
+{
+ PHASE_FESTERGUT = 1,
+ PHASE_ROTFACE = 2,
+ PHASE_COMBAT = 3,
+
+ PHASE_MASK_NOT_SELF = (1 << PHASE_FESTERGUT) | (1 << PHASE_ROTFACE)
+};
+
+enum ePoints
+{
+ POINT_FESTERGUT = -366260,
+};
+
+static const Position festergutWatchPos = {4324.82f, 3166.03f, 389.3831f, 3.316126f}; //emote 432 (release gas)
+
+class boss_professor_putricide : public CreatureScript
+{
+ public:
+ boss_professor_putricide() : CreatureScript("boss_professor_putricide") { }
+
+ struct boss_professor_putricideAI : public BossAI
+ {
+ boss_professor_putricideAI(Creature* pCreature) : BossAI(pCreature, DATA_PROFESSOR_PUTRICIDE),
+ fBaseSpeed(pCreature->GetSpeedRate(MOVE_RUN))
+ {
+ ASSERT(instance);
+ phase = ePhases(0);
+ }
+
+ void Reset()
+ {
+ events.Reset();
+ summons.DespawnAll();
+ _SetPhase(PHASE_COMBAT);
+ me->SetReactState(REACT_DEFENSIVE);
+ me->RemoveUnitMovementFlag(MOVEMENTFLAG_WALKING);
+ if (me->GetMotionMaster()->GetCurrentMovementGeneratorType() == POINT_MOTION_TYPE)
+ me->GetMotionMaster()->MovementExpired();
+ }
+
+ void DoAction(const int32 action)
+ {
+ switch (action)
+ {
+ case ACTION_FESTERGUT_COMBAT:
+ _SetPhase(PHASE_FESTERGUT);
+ me->SetSpeed(MOVE_RUN, fBaseSpeed*2.0f, true);
+ me->GetMotionMaster()->MovePoint(POINT_FESTERGUT, festergutWatchPos);
+ me->SetReactState(REACT_PASSIVE);
+ if (IsHeroic())
+ {
+ DoZoneInCombat(me);
+ events.ScheduleEvent(EVENT_FESTERGUT_GOO, urand(15000, 20000), 0, PHASE_FESTERGUT);
+ }
+ break;
+ case ACTION_FESTERGUT_GAS:
+ DoScriptText(SAY_FESTERGUT_GASEOUS_BLIGHT, me);
+ if (Creature* festergut = Unit::GetCreature(*me, instance->GetData64(DATA_FESTERGUT)))
+ festergut->CastSpell(festergut, SPELL_RELEASE_GAS_VISUAL, false, NULL, NULL, me->GetGUID()); // cast from festergut for LoS (with prof's GUID for logs)
+ break;
+ case ACTION_FESTERGUT_DEATH:
+ events.ScheduleEvent(EVENT_FESTERGUT_DIES, 4000, 0, PHASE_FESTERGUT);
+ break;
+ default:
+ break;
+ }
+ }
+
+ void JustReachedHome()
+ {
+ if (phase == PHASE_COMBAT)
+ instance->SetBossState(DATA_PROFESSOR_PUTRICIDE, FAIL);
+ }
+
+ void MovementInform(uint32 type, uint32 id)
+ {
+ if (type == POINT_MOTION_TYPE && id == POINT_FESTERGUT)
+ {
+ me->SetSpeed(MOVE_RUN, fBaseSpeed, true);
+ DoAction(ACTION_FESTERGUT_GAS);
+ if (Creature* festergut = Unit::GetCreature(*me, instance->GetData64(DATA_FESTERGUT)))
+ festergut->CastSpell(festergut, SPELL_GASEOUS_BLIGHT_LARGE, false, NULL, NULL, festergut->GetGUID());
+ }
+ }
+
+ void UpdateAI(const uint32 diff)
+ {
+ if ((!UpdateVictim() && !(events.GetPhaseMask() & PHASE_MASK_NOT_SELF)) || !CheckInRoom())
+ return;
+
+ events.Update(diff);
+
+ if (me->hasUnitState(UNIT_STAT_CASTING))
+ return;
+
+ while (uint32 eventId = events.ExecuteEvent())
+ {
+ switch (eventId)
+ {
+ case EVENT_FESTERGUT_DIES:
+ DoScriptText(SAY_FESTERGUT_DEATH, me);
+ EnterEvadeMode();
+ break;
+ case EVENT_FESTERGUT_GOO:
+ if (Unit* target = SelectTarget(SELECT_TARGET_RANDOM, 0, 0.0f, true))
+ DoCast(target, SPELL_MALLABLE_GOO_H, true); // triggered, to skip LoS check
+ events.ScheduleEvent(EVENT_FESTERGUT_GOO, urand(15000, 20000), 0, PHASE_FESTERGUT);
+ break;
+ default:
+ break;
+ }
+ }
+ }
+
+ void _SetPhase(ePhases newPhase)
+ {
+ phase = newPhase;
+ events.SetPhase(newPhase);
+ }
+
+ private:
+ ePhases phase; // external of EventMap because event phase gets reset on evade
+ const float fBaseSpeed;
+ };
+
+ CreatureAI* GetAI(Creature* pCreature) const
+ {
+ return new boss_professor_putricideAI(pCreature);
+ }
+};
+
+// Stinky and Precious spell, it's here because its used for both (Festergut and Rotface "pet")
+class spell_stinky_precious_decimate : public SpellScriptLoader
+{
+ public:
+ spell_stinky_precious_decimate() : SpellScriptLoader("spell_stinky_precious_decimate") { }
+
+ class spell_stinky_precious_decimate_SpellScript : public SpellScript
+ {
+ void HandleScript(SpellEffIndex effIndex)
+ {
+ if (GetHitUnit()->GetHealthPct() > float(GetEffectValue()))
+ {
+ uint32 newHealth = GetHitUnit()->GetMaxHealth() * uint32(GetEffectValue()) / 100;
+ if (GetHitUnit()->GetMaxHealth() >= newHealth)
+ GetHitUnit()->SetHealth(newHealth);
+ }
+ }
+
+ void Register()
+ {
+ OnEffect += SpellEffectFn(spell_stinky_precious_decimate_SpellScript::HandleScript, EFFECT_0, SPELL_EFFECT_SCRIPT_EFFECT);
+ }
+ };
+
+ SpellScript* GetSpellScript() const
+ {
+ return new spell_stinky_precious_decimate_SpellScript();
+ }
+};
+
+void AddSC_boss_professor_putricide()
+{
+ new boss_professor_putricide();
+ new spell_stinky_precious_decimate();
+}
diff --git a/src/server/scripts/Northrend/IcecrownCitadel/icecrown_citadel.h b/src/server/scripts/Northrend/IcecrownCitadel/icecrown_citadel.h
index d95f928d24e..e934fc0721d 100644
--- a/src/server/scripts/Northrend/IcecrownCitadel/icecrown_citadel.h
+++ b/src/server/scripts/Northrend/IcecrownCitadel/icecrown_citadel.h
@@ -21,7 +21,8 @@
enum eSharedSpells
{
- SPELL_BERSERK = 26662
+ SPELL_BERSERK = 26662,
+ SPELL_BERSERK2 = 47008
};
enum eData
@@ -69,6 +70,13 @@ enum eCreatures
NPC_SE_HIGH_OVERLORD_SAURFANG = 37187,
NPC_SE_KOR_KRON_REAVER = 37920,
NPC_SE_SKYBREAKER_MARINE = 37830,
+
+ NPC_FESTERGUT = 36626,
+ NPC_GAS_DUMMY = 36659,
+
+ NPC_ROTFACE = 36627,
+
+ NPC_PROFESSOR_PUTRICIDE = 36678,
};
enum eGameobjects
@@ -84,6 +92,14 @@ enum eGameobjects
GO_DEATHBRINGER_S_CACHE_10H = 202238,
GO_DEATHBRINGER_S_CACHE_25H = 202241,
GO_SCOURGE_TRANSPORTER_SAURFANG = 202244,
+ GO_ORANGE_PLAGUE_MONSTER_ENTRANCE = 201371,
+ GO_GREEN_PLAGUE_MONSTER_ENTRANCE = 201370,
+ GO_SCIENTIST_AIRLOCK_DOOR_COLLISION = 201612,
+ GO_SCIENTIST_AIRLOCK_DOOR_ORANGE = 201613,
+ GO_SCIENTIST_AIRLOCK_DOOR_GREEN = 201614,
+ GO_DOODAD_ICECROWN_ORANGETUBES02 = 201617,
+ GO_DOODAD_ICECROWN_GREENTUBES02 = 201618,
+ GO_SCIENTIST_ENTRANCE = 201372,
};
enum eAchievementCriteria
@@ -94,4 +110,11 @@ enum eAchievementCriteria
CRITERIA_BONED_25H = 13394,
};
+enum ePutricideActions
+{
+ ACTION_FESTERGUT_COMBAT = -366260,
+ ACTION_FESTERGUT_GAS = -366261,
+ ACTION_FESTERGUT_DEATH = -366262,
+};
+
#endif // DEF_ICECROWN_CITADEL_H
diff --git a/src/server/scripts/Northrend/IcecrownCitadel/instance_icecrown_citadel.cpp b/src/server/scripts/Northrend/IcecrownCitadel/instance_icecrown_citadel.cpp
index 917d9469a51..0645c59ff42 100644
--- a/src/server/scripts/Northrend/IcecrownCitadel/instance_icecrown_citadel.cpp
+++ b/src/server/scripts/Northrend/IcecrownCitadel/instance_icecrown_citadel.cpp
@@ -25,6 +25,9 @@ static const DoorData doorData[8] =
{GO_ICEWALL, DATA_LORD_MARROWGAR, DOOR_TYPE_PASSAGE, BOUNDARY_NONE},
{GO_DOODAD_ICECROWN_ICEWALL02, DATA_LORD_MARROWGAR, DOOR_TYPE_PASSAGE, BOUNDARY_NONE},
{GO_ORATORY_OF_THE_DAMNED_ENTRANCE, DATA_LADY_DEATHWHISPER, DOOR_TYPE_ROOM, BOUNDARY_N },
+ {GO_ORANGE_PLAGUE_MONSTER_ENTRANCE, DATA_FESTERGUT, DOOR_TYPE_ROOM, BOUNDARY_E },
+ {GO_GREEN_PLAGUE_MONSTER_ENTRANCE, DATA_ROTFACE, DOOR_TYPE_ROOM, BOUNDARY_E },
+ {GO_SCIENTIST_ENTRANCE, DATA_PROFESSOR_PUTRICIDE, DOOR_TYPE_ROOM, BOUNDARY_E },
{0, 0, DOOR_TYPE_ROOM, BOUNDARY_NONE} // END
};
@@ -45,6 +48,12 @@ class instance_icecrown_citadel : public InstanceMapScript
uiSaurfangEventNPC = 0;
uiDeathbringersCache = 0;
uiSaurfangTeleport = 0;
+ memset(uiPutricidePipes, 0, 2*sizeof(uint32));
+ memset(uiPutricideGates, 0, 2*sizeof(uint32));
+ uiPutricideCollision;
+ uiFestergut = 0;
+ uiRotface = 0;
+ uiProfessorPutricide = 0;
isBonedEligible = false;
}
@@ -75,6 +84,15 @@ class instance_icecrown_citadel : public InstanceMapScript
if (TeamInInstance == ALLIANCE)
creature->UpdateEntry(NPC_SE_SKYBREAKER_MARINE, ALLIANCE);
break;
+ case NPC_FESTERGUT:
+ uiFestergut = creature->GetGUID();
+ break;
+ case NPC_ROTFACE:
+ uiRotface = creature->GetGUID();
+ break;
+ case NPC_PROFESSOR_PUTRICIDE:
+ uiProfessorPutricide = creature->GetGUID();
+ break;
default:
break;
}
@@ -88,6 +106,9 @@ class instance_icecrown_citadel : public InstanceMapScript
case GO_ICEWALL:
case GO_LORD_MARROWGAR_S_ENTRANCE:
case GO_ORATORY_OF_THE_DAMNED_ENTRANCE:
+ case GO_ORANGE_PLAGUE_MONSTER_ENTRANCE:
+ case GO_GREEN_PLAGUE_MONSTER_ENTRANCE:
+ case GO_SCIENTIST_ENTRANCE:
AddDoor(pGo, add);
break;
case GO_LADY_DEATHWHISPER_ELEVATOR:
@@ -110,6 +131,35 @@ class instance_icecrown_citadel : public InstanceMapScript
case GO_SCOURGE_TRANSPORTER_SAURFANG:
uiSaurfangTeleport = pGo->GetGUID();
break;
+ case GO_SCIENTIST_AIRLOCK_DOOR_COLLISION:
+ uiPutricideCollision = pGo->GetGUID();
+ if (GetBossState(DATA_FESTERGUT) == DONE && GetBossState(DATA_ROTFACE) == DONE)
+ HandleGameObject(uiPutricideCollision, true, pGo);
+ break;
+ case GO_SCIENTIST_AIRLOCK_DOOR_ORANGE:
+ uiPutricideGates[0] = pGo->GetGUID();
+ if (GetBossState(DATA_FESTERGUT) == DONE && GetBossState(DATA_ROTFACE) == DONE)
+ pGo->SetGoState(GO_STATE_ACTIVE_ALTERNATIVE);
+ else if (GetBossState(DATA_FESTERGUT) == DONE)
+ HandleGameObject(uiPutricideGates[1], false, pGo);
+ break;
+ case GO_SCIENTIST_AIRLOCK_DOOR_GREEN:
+ uiPutricideGates[1] = pGo->GetGUID();
+ if (GetBossState(DATA_ROTFACE) == DONE && GetBossState(DATA_FESTERGUT) == DONE)
+ pGo->SetGoState(GO_STATE_ACTIVE_ALTERNATIVE);
+ else if (GetBossState(DATA_ROTFACE) == DONE)
+ HandleGameObject(uiPutricideGates[1], false, pGo);
+ break;
+ case GO_DOODAD_ICECROWN_ORANGETUBES02:
+ uiPutricidePipes[0] = pGo->GetGUID();
+ if (GetBossState(DATA_FESTERGUT) == DONE)
+ HandleGameObject(uiPutricidePipes[0], true, pGo);
+ break;
+ case GO_DOODAD_ICECROWN_GREENTUBES02:
+ uiPutricidePipes[1] = pGo->GetGUID();
+ if (GetBossState(DATA_ROTFACE) == DONE)
+ HandleGameObject(uiPutricidePipes[1], true, pGo);
+ break;
default:
break;
}
@@ -127,6 +177,10 @@ class instance_icecrown_citadel : public InstanceMapScript
return uiSaurfangDoor;
case GO_SCOURGE_TRANSPORTER_SAURFANG:
return uiSaurfangTeleport;
+ case DATA_FESTERGUT:
+ return uiFestergut;
+ case DATA_PROFESSOR_PUTRICIDE:
+ return uiProfessorPutricide;
default:
break;
}
@@ -167,7 +221,35 @@ class instance_icecrown_citadel : public InstanceMapScript
}
break;
case DATA_FESTERGUT:
+ if (state == DONE)
+ {
+ if (GetBossState(DATA_ROTFACE) == DONE)
+ HandleGameObject(uiPutricideCollision, true);
+ if (GetBossState(DATA_ROTFACE) == DONE)
+ {
+ if (GameObject* pGo = instance->GetGameObject(uiPutricideGates[0]))
+ pGo->SetGoState(GO_STATE_ACTIVE_ALTERNATIVE);
+ }
+ else
+ HandleGameObject(uiPutricideGates[0], false);
+ HandleGameObject(uiPutricidePipes[0], true);
+ }
+ break;
case DATA_ROTFACE:
+ if (state == DONE)
+ {
+ if (GetBossState(DATA_FESTERGUT) == DONE)
+ HandleGameObject(uiPutricideCollision, true);
+ if (GetBossState(DATA_FESTERGUT) == DONE)
+ {
+ if (GameObject* pGo = instance->GetGameObject(uiPutricideGates[1]))
+ pGo->SetGoState(GO_STATE_ACTIVE_ALTERNATIVE);
+ }
+ else
+ HandleGameObject(uiPutricideGates[1], false);
+ HandleGameObject(uiPutricidePipes[1], true);
+ }
+ break;
case DATA_PROFESSOR_PUTRICIDE:
case DATA_BLOOD_PRINCE_COUNCIL:
case DATA_BLOOD_QUEEN_LANA_THEL:
@@ -256,6 +338,12 @@ class instance_icecrown_citadel : public InstanceMapScript
uint64 uiSaurfangEventNPC; // Muradin Bronzebeard or High Overlord Saurfang
uint64 uiDeathbringersCache;
uint64 uiSaurfangTeleport;
+ uint64 uiPutricidePipes[2];
+ uint64 uiPutricideGates[2];
+ uint64 uiPutricideCollision;
+ uint64 uiFestergut;
+ uint64 uiRotface;
+ uint64 uiProfessorPutricide;
bool isBonedEligible;
};